]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.def (STATIC_ASSERT): New.
authorDouglas Gregor <doug.gregor@gmail.com>
Tue, 21 Nov 2006 20:23:03 +0000 (20:23 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Tue, 21 Nov 2006 20:23:03 +0000 (20:23 +0000)
2006-11-21      Douglas Gregor <doug.gregor@gmail.com>

        * cp-tree.def (STATIC_ASSERT): New.
* cp-objcp-common.c (cp_tree_size): Handle STATIC_ASSERT.
* error.c (dump_decl): Handle STATIC_ASSERT.
* cp-tree.h (STATIC_ASSERT_CONDITION): New.
        (STATIC_ASSERT_MESSAGE): New.
(STATIC_ASSERT_SOURCE_LOCATION): New.
(struct tree_static_assert): New.
(enum cp_tree_node_structure_enum): Add TS_CP_STATIC_ASSERT.
(union lang_tree_node): Add static_assertion.
        (finish_static_assert): Declare.
* cxx-pretty-print.c (pp_cxx_statement): Handle STATIC_ASSERT.
(pp_cxx_declaration): Handle STATIC_ASSERT.
* pt.c (instantiate_class_template): Handle
STATIC_ASSERT members.
        (tsubst_expr): Handle STATIC_ASSERT statements.
* semantics.c (finish_static_assert): New.
        * lex.c (D_CPP0X): New.
        (reswords): Add static_assert keyword.
        (init_reswords): If not flag_cpp0x, mask out C++0x keywords.
        * parser.c (cp_parser_block_declaration): Parse static
assertions.
        (cp_parser_static_assert): New.
        (cp_parser_member_declaration): Parse static assertions.

From-SVN: r119066

gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/error.c
gcc/cp/lex.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c

index 0cd3ccc8fb6156265eb943aa494df0819127dd2c..af4a3fc399f32a4d264c7172abe3cff3471f8ac4 100644 (file)
@@ -1,3 +1,29 @@
+2006-11-21      Douglas Gregor <doug.gregor@gmail.com>
+
+        * cp-tree.def (STATIC_ASSERT): New.  
+       * cp-objcp-common.c (cp_tree_size): Handle STATIC_ASSERT.
+       * error.c (dump_decl): Handle STATIC_ASSERT.
+       * cp-tree.h (STATIC_ASSERT_CONDITION): New.
+        (STATIC_ASSERT_MESSAGE): New.
+       (STATIC_ASSERT_SOURCE_LOCATION): New.
+       (struct tree_static_assert): New.
+       (enum cp_tree_node_structure_enum): Add TS_CP_STATIC_ASSERT.
+       (union lang_tree_node): Add static_assertion.
+        (finish_static_assert): Declare.
+       * cxx-pretty-print.c (pp_cxx_statement): Handle STATIC_ASSERT.
+       (pp_cxx_declaration): Handle STATIC_ASSERT.
+       * pt.c (instantiate_class_template): Handle
+       STATIC_ASSERT members.
+        (tsubst_expr): Handle STATIC_ASSERT statements.  
+       * semantics.c (finish_static_assert): New.
+        * lex.c (D_CPP0X): New.
+        (reswords): Add static_assert keyword.
+        (init_reswords): If not flag_cpp0x, mask out C++0x keywords.
+        * parser.c (cp_parser_block_declaration): Parse static
+       assertions.
+        (cp_parser_static_assert): New.
+        (cp_parser_member_declaration): Parse static assertions.
+
 2006-11-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/29570
index f40be9696956ecf48c5bbab591303cb303454b89..a3e19db244fc4b3d7e39364b3c1c54b55571c430 100644 (file)
@@ -123,6 +123,7 @@ cp_tree_size (enum tree_code code)
     case TEMPLATE_PARM_INDEX:  return sizeof (template_parm_index);
     case DEFAULT_ARG:          return sizeof (struct tree_default_arg);
     case OVERLOAD:             return sizeof (struct tree_overload);
+    case STATIC_ASSERT:         return sizeof (struct tree_static_assert);
     default:
       gcc_unreachable ();
     }
index 55ef21ef79010020a973468187f2b312cff46a6d..090f91f40c5146937fa424206dcf7fa717acaab7 100644 (file)
@@ -342,6 +342,14 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", tcc_expression, 1)
    is applied.  */
 DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1)
 
+/** C++0x extensions. */
+
+/* A static assertion.  This is a C++0x extension.
+   STATIC_ASSERT_CONDITION contains the condition that is being
+   checked.  STATIC_ASSERT_MESSAGE contains the message (a string
+   literal) to be displayed if the condition fails to hold.  */
+DEFTREECODE (STATIC_ASSERT, "static_assert", tcc_exceptional, 0)
+
 /*
 Local variables:
 mode:c
index 43e6e29d0cec945f40a5d570c2cda8436a5363c3..0270eb3a6c2fc52ddcf1fddd4fa091e403807704 100644 (file)
@@ -446,6 +446,29 @@ struct tree_default_arg GTY (())
   VEC(tree,gc) *instantiations;
 };
 
+/* The condition associated with the static assertion.  This must be
+   an integral constant expression.  */
+#define STATIC_ASSERT_CONDITION(NODE) \
+  (((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->condition)
+
+/* The message associated with the static assertion.  This must be a
+   string constant, which will be emitted as an error message when the
+   static assert condition is false.  */
+#define STATIC_ASSERT_MESSAGE(NODE) \
+  (((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->message)
+
+/* Source location information for a static assertion.  */
+#define STATIC_ASSERT_SOURCE_LOCATION(NODE) \
+  (((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->location)
+
+struct tree_static_assert GTY (())
+{
+  struct tree_common common;
+  tree condition;
+  tree message;
+  location_t location;
+};
+
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
   TS_CP_IDENTIFIER,
@@ -457,6 +480,7 @@ enum cp_tree_node_structure_enum {
   TS_CP_BASELINK,
   TS_CP_WRAPPER,
   TS_CP_DEFAULT_ARG,
+  TS_CP_STATIC_ASSERT,
   LAST_TS_CP_ENUM
 };
 
@@ -473,6 +497,8 @@ union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
   struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
   struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg;
   struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
+  struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT"))) 
+    static_assertion;
 };
 
 \f
@@ -4326,6 +4352,8 @@ extern tree cxx_omp_clause_assign_op              (tree, tree, tree);
 extern tree cxx_omp_clause_dtor                        (tree, tree);
 extern bool cxx_omp_privatize_by_reference     (tree);
 extern tree baselink_for_fns                    (tree);
+extern void finish_static_assert                (tree, tree, location_t,
+                                                 bool);
 
 /* in tree.c */
 extern void lang_check_failed                  (const char *, int,
index 5ceca61a4cb30711b87ac2207586bc59e8cf3c94..4f2bf86ed51c82b943eacd67edcef270c5d735d2 100644 (file)
@@ -1711,6 +1711,10 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
       pp_newline_and_indent (pp, -2);
       break;
 
+    case STATIC_ASSERT:
+      pp_cxx_declaration (pp, t);
+      break;
+
     default:
       pp_c_statement (pp_c_base (pp), t);
       break;
@@ -1906,11 +1910,21 @@ pp_cxx_explicit_instantiation (cxx_pretty_printer *pp, tree t)
        asm-definition
        namespace-alias-definition
        using-declaration
-       using-directive  */
+       using-directive
+       static_assert-declaration */
 void
 pp_cxx_declaration (cxx_pretty_printer *pp, tree t)
 {
-  if (!DECL_LANG_SPECIFIC (t))
+  if (TREE_CODE (t) == STATIC_ASSERT)
+    {
+      pp_cxx_identifier (pp, "static_assert");
+      pp_cxx_left_paren (pp);
+      pp_cxx_expression (pp, STATIC_ASSERT_CONDITION (t));
+      pp_cxx_separate_with (pp, ',');
+      pp_cxx_expression (pp, STATIC_ASSERT_MESSAGE (t));
+      pp_cxx_right_paren (pp);
+    }
+  else if (!DECL_LANG_SPECIFIC (t))
     pp_cxx_simple_declaration (pp, t);
   else if (DECL_USE_TEMPLATE (t))
     switch (DECL_USE_TEMPLATE (t))
index f87355893cbc2922e999be1c9be24cb3dc75609d..c4f4d461c2febe29874d71b9b1b01c15fb6349f4 100644 (file)
@@ -886,6 +886,10 @@ dump_decl (tree t, int flags)
       dump_decl (DECL_NAME (t), flags);
       break;
 
+    case STATIC_ASSERT:
+      pp_cxx_declaration (cxx_pp, t);
+      break;
+
     case BASELINK:
       dump_decl (BASELINK_FUNCTIONS (t), flags);
       break;
index d14a1baa926e3511ae9b8e899bad4f837d499476..27a17c3d3feece8ea2891f4acd5c06fe116b395a 100644 (file)
@@ -176,6 +176,7 @@ struct resword
 #define D_EXT          0x01    /* GCC extension */
 #define D_ASM          0x02    /* in C99, but has a switch to turn it off */
 #define D_OBJC         0x04    /* Objective C++ only */
+#define D_CPP0X         0x08    /* C++0x only */
 
 CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
 
@@ -259,6 +260,7 @@ static const struct resword reswords[] =
   { "signed",          RID_SIGNED,     0 },
   { "sizeof",          RID_SIZEOF,     0 },
   { "static",          RID_STATIC,     0 },
+  { "static_assert",    RID_STATIC_ASSERT, D_CPP0X },
   { "static_cast",     RID_STATCAST,   0 },
   { "struct",          RID_STRUCT,     0 },
   { "switch",          RID_SWITCH,     0 },
@@ -314,7 +316,8 @@ init_reswords (void)
   tree id;
   int mask = ((flag_no_asm ? D_ASM : 0)
              | D_OBJC
-             | (flag_no_gnu_keywords ? D_EXT : 0));
+             | (flag_no_gnu_keywords ? D_EXT : 0)
+              | (flag_cpp0x ? 0 : D_CPP0X));
 
   ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
   for (i = 0; i < ARRAY_SIZE (reswords); i++)
index 8e79eabe895639b2fbd8f3e99134f3f3a66942f6..c5dfea6082537a39a3dfce16e3152df232b3f595 100644 (file)
@@ -1589,6 +1589,8 @@ static void cp_parser_asm_definition
   (cp_parser *);
 static void cp_parser_linkage_specification
   (cp_parser *);
+static void cp_parser_static_assert
+  (cp_parser *, bool);
 
 /* Declarators [gram.dcl.decl] */
 
@@ -7211,6 +7213,11 @@ cp_parser_declaration (cp_parser* parser)
      __extension__ block-declaration
      label-declaration
 
+   C++0x Extension:
+
+   block-declaration:
+     static_assert-declaration
+
    If STATEMENT_P is TRUE, then this block-declaration is occurring as
    part of a declaration-statement.  */
 
@@ -7272,6 +7279,9 @@ cp_parser_block_declaration (cp_parser *parser,
        cp_parser_commit_to_tentative_parse (parser);
       cp_parser_label_declaration (parser);
     }
+  /* If the next token is `static_assert' we have a static assertion.  */
+  else if (token1->keyword == RID_STATIC_ASSERT)
+    cp_parser_static_assert (parser, /*member_p=*/false);
   /* Anything else must be a simple-declaration.  */
   else
     cp_parser_simple_declaration (parser, !statement_p);
@@ -7825,6 +7835,68 @@ cp_parser_linkage_specification (cp_parser* parser)
   pop_lang_context ();
 }
 
+/* Parse a static_assert-declaration.
+
+   static_assert-declaration:
+     static_assert ( constant-expression , string-literal ) ; 
+
+   If MEMBER_P, this static_assert is a class member.  */
+
+static void 
+cp_parser_static_assert(cp_parser *parser, bool member_p)
+{
+  tree condition;
+  tree message;
+  cp_token *token;
+  location_t saved_loc;
+
+  /* Peek at the `static_assert' token so we can keep track of exactly
+     where the static assertion started.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  saved_loc = token->location;
+
+  /* Look for the `static_assert' keyword.  */
+  if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
+                                  "`static_assert'"))
+    return;
+
+  /*  We know we are in a static assertion; commit to any tentative
+      parse.  */
+  if (cp_parser_parsing_tentatively (parser))
+    cp_parser_commit_to_tentative_parse (parser);
+
+  /* Parse the `(' starting the static assertion condition.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+
+  /* Parse the constant-expression.  */
+  condition = 
+    cp_parser_constant_expression (parser,
+                                   /*allow_non_constant_p=*/false,
+                                   /*non_constant_p=*/NULL);
+
+  /* Parse the separating `,'.  */
+  cp_parser_require (parser, CPP_COMMA, "`,'");
+
+  /* Parse the string-literal message.  */
+  message = cp_parser_string_literal (parser, 
+                                      /*translate=*/false,
+                                      /*wide_ok=*/true);
+
+  /* A `)' completes the static assertion.  */
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, 
+                                           /*recovering=*/true, 
+                                           /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  /* A semicolon terminates the declaration.  */
+  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+
+  /* Complete the static assertion, which may mean either processing 
+     the static assert now or saving it for template instantiation.  */
+  finish_static_assert (condition, message, saved_loc, member_p);
+}
+
 /* Special member functions [gram.special] */
 
 /* Parse a conversion-function-id.
@@ -13624,7 +13696,12 @@ cp_parser_member_specification_opt (cp_parser* parser)
    member-declarator:
      declarator attributes [opt] pure-specifier [opt]
      declarator attributes [opt] constant-initializer [opt]
-     identifier [opt] attributes [opt] : constant-expression  */
+     identifier [opt] attributes [opt] : constant-expression  
+
+   C++0x Extensions:
+
+   member-declaration:
+     static_assert-declaration  */
 
 static void
 cp_parser_member_declaration (cp_parser* parser)
@@ -13687,6 +13764,13 @@ cp_parser_member_declaration (cp_parser* parser)
       return;
     }
 
+  /* If the next token is `static_assert' we have a static assertion.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
+    {
+      cp_parser_static_assert (parser, /*member_p=*/true);
+      return;
+    }
+
   if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
     return;
 
index 16e3e181d22381e5eaeff27d05afa7c4e30d686b..bcaae6b3ac0a4c1168e20d17eeb002140b6e80b2 100644 (file)
@@ -5886,8 +5886,18 @@ instantiate_class_template (tree type)
          else
            {
              /* Build new TYPE_FIELDS.  */
-
-             if (TREE_CODE (t) != CONST_DECL)
+              if (TREE_CODE (t) == STATIC_ASSERT)
+                {
+                  tree condition = 
+                    tsubst_expr (STATIC_ASSERT_CONDITION (t), args, 
+                                 tf_warning_or_error, NULL_TREE,
+                                 /*integral_constant_expression_p=*/true);
+                  finish_static_assert (condition,
+                                        STATIC_ASSERT_MESSAGE (t), 
+                                        STATIC_ASSERT_SOURCE_LOCATION (t),
+                                        /*member_p=*/true);
+                }
+             else if (TREE_CODE (t) != CONST_DECL)
                {
                  tree r;
 
@@ -8716,6 +8726,20 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
       break;
 
+    case STATIC_ASSERT:
+      {
+        tree condition = 
+          tsubst_expr (STATIC_ASSERT_CONDITION (t), 
+                       args,
+                       complain, in_decl,
+                       /*integral_constant_expression_p=*/true);
+        finish_static_assert (condition,
+                              STATIC_ASSERT_MESSAGE (t),
+                              STATIC_ASSERT_SOURCE_LOCATION (t),
+                              /*member_p=*/false);
+      }
+      break;
+
     case OMP_PARALLEL:
       tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
                                args, complain, in_decl);
index e3dc3ab3ec4525819c86d690f1e44b8a1dc01dc5..9192aff56fc488119003b91be0f6b12694ccd459 100644 (file)
@@ -3914,5 +3914,57 @@ void
 init_cp_semantics (void)
 {
 }
+\f
+/* Build a STATIC_ASSERT for a static assertion with the condition
+   CONDITION and the message text MESSAGE.  LOCATION is the location
+   of the static assertion in the source code.  When MEMBER_P, this
+   static assertion is a member of a class.  */
+void 
+finish_static_assert (tree condition, tree message, location_t location, 
+                      bool member_p)
+{
+  if (type_dependent_expression_p (condition) 
+      || value_dependent_expression_p (condition))
+    {
+      /* We're in a template; build a STATIC_ASSERT and put it in
+         the right place. */
+      tree assertion;
+
+      assertion = make_node (STATIC_ASSERT);
+      STATIC_ASSERT_CONDITION (assertion) = condition;
+      STATIC_ASSERT_MESSAGE (assertion) = message;
+      STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
+
+      if (member_p)
+        maybe_add_class_template_decl_list (current_class_type, 
+                                            assertion,
+                                            /*friend_p=*/0);
+      else
+        add_stmt (assertion);
+
+      return;
+    }
+
+  /* Fold the expression and convert it to a boolean value. */
+  condition = fold_non_dependent_expr (condition);
+  condition = cp_convert (boolean_type_node, condition);
+
+  if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
+    /* Do nothing; the condition is satisfied. */
+    ;
+  else 
+    {
+      location_t saved_loc = input_location;
+
+      input_location = location;
+      if (TREE_CODE (condition) == INTEGER_CST 
+          && integer_zerop (condition))
+        /* Report the error. */
+        error ("static assertion failed: %E", message);
+      else if (condition && condition != error_mark_node)
+        error ("non-constant condition for static assertion");
+      input_location = saved_loc;
+    }
+}
 
 #include "gt-cp-semantics.h"
This page took 0.093004 seconds and 5 git commands to generate.