re PR c++/14550 (trouble with pointers in templates)
authorMark Mitchell <mark@codesourcery.com>
Mon, 15 Mar 2004 16:16:18 +0000 (16:16 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 15 Mar 2004 16:16:18 +0000 (16:16 +0000)
PR c++/14550
* parser.c (cp_parser_non_integral_constant_expression): Encode
more of the idiom that surrounded calls to this function within
the function itself
(cp_parser_primary_expression): Adjust accordingly.
(cp_parser_postfix_expression): Likewise.
(cp_parser_unary_expression): Likewise.
(cp_parser_cast_expression): Likewise.
(cp_parser_assignment_expression): Likewise.
(cp_parser_expression): Likewise.
(cp_parser_new_expression): Note that new-expressions are not
allowed in integral constant expressions.
(cp_parser_delete_expression): Likewise.

PR c++/14550
* g++.dg/parse/template14.C: New test.

From-SVN: r79498

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/template14.C [new file with mode: 0644]

index fc34864146c8ea9874521f9950edd7a26a4ee6b8..5dc9e7614846b3d42c830ed7aa16d452910fd370 100644 (file)
@@ -1,3 +1,19 @@
+2004-03-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/14550
+       * parser.c (cp_parser_non_integral_constant_expression): Encode
+       more of the idiom that surrounded calls to this function within
+       the function itself
+       (cp_parser_primary_expression): Adjust accordingly.
+       (cp_parser_postfix_expression): Likewise.
+       (cp_parser_unary_expression): Likewise.
+       (cp_parser_cast_expression): Likewise.
+       (cp_parser_assignment_expression): Likewise.
+       (cp_parser_expression): Likewise.
+       (cp_parser_new_expression): Note that new-expressions are not
+       allowed in integral constant expressions.
+       (cp_parser_delete_expression): Likewise.
+
 2004-03-12  Matt Austern  <austern@apple.com>
 
        * decl2.c (maybe_make_one_only): Look at
index 0691c96ebc0186853e5f1871ecdb69c2295e2b8e..20588b0469d21ad3dddd3cd5e53af65f69aca1e6 100644 (file)
@@ -1719,8 +1719,8 @@ static void cp_parser_check_for_definition_in_return_type
   (tree, int);
 static void cp_parser_check_for_invalid_template_id
   (cp_parser *, tree);
-static tree cp_parser_non_integral_constant_expression
-  (const char *);
+static bool cp_parser_non_integral_constant_expression
+  (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
   (cp_parser *, tree, tree);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
@@ -1922,14 +1922,24 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
     }
 }
 
-/* Issue an error message about the fact that THING appeared in a
-   constant-expression.  Returns ERROR_MARK_NODE.  */
+/* If parsing an integral constant-expression, issue an error message
+   about the fact that THING appeared and return true.  Otherwise,
+   return false, marking the current expression as non-constant.  */
 
-static tree
-cp_parser_non_integral_constant_expression (const char *thing)
+static bool
+cp_parser_non_integral_constant_expression (cp_parser  *parser,
+                                           const char *thing)
 {
-  error ("%s cannot appear in a constant-expression", thing);
-  return error_mark_node;
+  if (parser->integral_constant_expression_p)
+    {
+      if (!parser->allow_non_integral_constant_expression_p)
+       {
+         error ("%s cannot appear in a constant-expression", thing);
+         return true;
+       }
+      parser->non_integral_constant_expression_p = true;
+    }
+  return false;
 }
 
 /* Emit a diagnostic for an invalid type name. Consider also if it is
@@ -2542,12 +2552,9 @@ cp_parser_primary_expression (cp_parser *parser,
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               return cp_parser_non_integral_constant_expression ("`this'");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "`this'"))
+           return error_mark_node;
          return finish_this_expr ();
 
          /* The `operator' keyword can be the beginning of an
@@ -2589,12 +2596,9 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
-           if (parser->integral_constant_expression_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 return cp_parser_non_integral_constant_expression ("`va_arg'");
-               parser->non_integral_constant_expression_p = true;
-             }
+           if (cp_parser_non_integral_constant_expression (parser,
+                                                           "`va_arg'"))
+             return error_mark_node;
            return build_x_va_arg (expression, type);
          }
 
@@ -3518,14 +3522,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
            /* A cast to pointer or reference type is allowed in the
               implementation of "offsetof".  */
-           && !(parser->in_offsetof_p && POINTER_TYPE_P (type)))
-         {
-           if (!parser->allow_non_integral_constant_expression_p)
-             return (cp_parser_non_integral_constant_expression
-                     ("a cast to a type other than an integral or "
-                      "enumeration type"));
-           parser->non_integral_constant_expression_p = true;
-         }
+           && !(parser->in_offsetof_p && POINTER_TYPE_P (type))
+           && (cp_parser_non_integral_constant_expression 
+               (parser,
+                "a cast to a type other than an integral or "
+                "enumeration type")))
+         return error_mark_node;
 
        switch (keyword)
          {
@@ -3771,13 +3773,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            idk = CP_ID_KIND_NONE;
            /* Array references are not permitted in
               constant-expressions.  */
-           if (parser->integral_constant_expression_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 postfix_expression
-                   = cp_parser_non_integral_constant_expression ("an array reference");
-               parser->non_integral_constant_expression_p = true;
-             }
+           if (cp_parser_non_integral_constant_expression 
+               (parser, "an array reference"))
+             postfix_expression = error_mark_node;
          }
          break;
 
@@ -3796,15 +3794,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
            /* Function calls are not permitted in
               constant-expressions.  */
-           if (parser->integral_constant_expression_p)
+           if (cp_parser_non_integral_constant_expression (parser,
+                                                           "a function call"))
              {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 {
-                   postfix_expression
-                     = cp_parser_non_integral_constant_expression ("a function call");
-                   break;
-                 }
-               parser->non_integral_constant_expression_p = true;
+               postfix_expression = error_mark_node;
+               break;
              }
 
            koenig_p = false;
@@ -3999,18 +3993,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
               operator.  */
            parser->context->object_type = NULL_TREE;
            /* These operators may not appear in constant-expressions.  */
-           if (parser->integral_constant_expression_p
-               /* The "->" operator is allowed in the implementation
+           if (/* The "->" operator is allowed in the implementation
                   of "offsetof".  The "." operator may appear in the
                   name of the member.  */
-               && !parser->in_offsetof_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 postfix_expression
-                   = (cp_parser_non_integral_constant_expression
-                      (token_type == CPP_DEREF ? "'->'" : "`.'"));
-               parser->non_integral_constant_expression_p = true;
-             }
+               !parser->in_offsetof_p
+               && (cp_parser_non_integral_constant_expression 
+                   (parser,
+                    token_type == CPP_DEREF ? "'->'" : "`.'")))
+             postfix_expression = error_mark_node;
          }
          break;
 
@@ -4023,13 +4013,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            = finish_increment_expr (postfix_expression,
                                     POSTINCREMENT_EXPR);
          /* Increments may not appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               postfix_expression
-                 = cp_parser_non_integral_constant_expression ("an increment");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "an increment"))
+           postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
          break;
 
@@ -4042,13 +4028,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            = finish_increment_expr (postfix_expression,
                                     POSTDECREMENT_EXPR);
          /* Decrements may not appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               postfix_expression
-                 = cp_parser_non_integral_constant_expression ("a decrement");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "a decrement"))
+           postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
          break;
 
@@ -4447,12 +4429,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          abort ();
        }
 
-      if (non_constant_p && parser->integral_constant_expression_p)
-       {
-         if (!parser->allow_non_integral_constant_expression_p)
-           return cp_parser_non_integral_constant_expression (non_constant_p);
-         parser->non_integral_constant_expression_p = true;
-       }
+      if (non_constant_p 
+         && cp_parser_non_integral_constant_expression (parser,
+                                                        non_constant_p))
+       expression = error_mark_node;
 
       return expression;
     }
@@ -4553,6 +4533,11 @@ cp_parser_new_expression (cp_parser* parser)
   else
     initializer = NULL_TREE;
 
+  /* A new-expression may not appear in an integral constant
+     expression.  */
+  if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+    return error_mark_node;
+
   /* Create a representation of the new-expression.  */
   return build_new (placement, type, initializer, global_scope_p);
 }
@@ -4781,6 +4766,11 @@ cp_parser_delete_expression (cp_parser* parser)
   /* Parse the cast-expression.  */
   expression = cp_parser_simple_cast_expression (parser);
 
+  /* A delete-expression may not appear in an integral constant
+     expression.  */
+  if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+    return error_mark_node;
+
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
@@ -4878,14 +4868,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
             can be used in constant-expressions.  */
          if (parser->integral_constant_expression_p
              && !dependent_type_p (type)
-             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               return (cp_parser_non_integral_constant_expression
-                       ("a casts to a type other than an integral or "
-                        "enumeration type"));
-             parser->non_integral_constant_expression_p = true;
-           }
+             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+             && (cp_parser_non_integral_constant_expression 
+                 (parser,
+                  "a cast to a type other than an integral or "
+                  "enumeration type")))
+           return error_mark_node;
+
          /* Perform the cast.  */
          expr = build_c_cast (type, expr);
          return expr;
@@ -5238,12 +5227,9 @@ cp_parser_assignment_expression (cp_parser* parser)
              rhs = cp_parser_assignment_expression (parser);
              /* An assignment may not appear in a
                 constant-expression.  */
-             if (parser->integral_constant_expression_p)
-               {
-                 if (!parser->allow_non_integral_constant_expression_p)
-                   return cp_parser_non_integral_constant_expression ("an assignment");
-                 parser->non_integral_constant_expression_p = true;
-               }
+             if (cp_parser_non_integral_constant_expression (parser,
+                                                             "an assignment"))
+               return error_mark_node;
              /* Build the assignment expression.  */
              expr = build_x_modify_expr (expr,
                                          assignment_operator,
@@ -5381,13 +5367,9 @@ cp_parser_expression (cp_parser* parser)
       /* Consume the `,'.  */
       cp_lexer_consume_token (parser->lexer);
       /* A comma operator cannot appear in a constant-expression.  */
-      if (parser->integral_constant_expression_p)
-       {
-         if (!parser->allow_non_integral_constant_expression_p)
-           expression
-             = cp_parser_non_integral_constant_expression ("a comma operator");
-         parser->non_integral_constant_expression_p = true;
-       }
+      if (cp_parser_non_integral_constant_expression (parser,
+                                                     "a comma operator"))
+       expression = error_mark_node;
     }
 
   return expression;
index 7a113afdc88ee2081ff90b814800d2fd58270877..7d1450fb100e4ab1e5407798024b35237bd8483b 100644 (file)
@@ -1,3 +1,8 @@
+2004-03-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/14550
+       * g++.dg/parse/template14.C: New test.
+
 2004-03-13  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.c-torture/execute/20040313-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/parse/template14.C b/gcc/testsuite/g++.dg/parse/template14.C
new file mode 100644 (file)
index 0000000..ada8752
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/14550
+
+struct A { 
+  A();
+};
+
+template <int> void foo()
+{
+  A *p = new A;
+}
+
+void bar()
+{
+  foo<0>();
+}
+
+