OSDN Git Service

2008-10-29 Manuel López-Ibáñez <manu@gcc.gnu.org>
authormanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Oct 2008 16:05:27 +0000 (16:05 +0000)
committermanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 Oct 2008 16:05:27 +0000 (16:05 +0000)
PR c++/26997
cp/
* parser.c (cp_parser_token_starts_cast_expression): New.
(cp_parser_cast_expression): Peek the next token to decide whether
this could be a parenthesized constructor or is definitely an
actual cast.
testsuite/
* g++.dg/parse/pr26997.C: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141429 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 0293d49..5115c1b 100644 (file)
@@ -1,3 +1,11 @@
+2008-10-29  Manuel López-Ibáñez  <manu@gcc.gnu.org>
+
+       PR c++/26997
+       * parser.c (cp_parser_token_starts_cast_expression): New.
+       (cp_parser_cast_expression): Peek the next token to decide whether
+       this could be a parenthesized constructor or is definitely an
+       actual cast.
+
 2008-10-24  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c/7543
 2008-10-24  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c/7543
index 7596048..40f2a3a 100644 (file)
@@ -5910,6 +5910,60 @@ cp_parser_delete_expression (cp_parser* parser)
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
+/* Returns true if TOKEN may start a cast-expression and false
+   otherwise.  */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_COMMA:
+    case CPP_SEMICOLON:
+    case CPP_QUERY:
+    case CPP_COLON:
+    case CPP_CLOSE_SQUARE:
+    case CPP_CLOSE_PAREN:
+    case CPP_CLOSE_BRACE:
+    case CPP_DOT:
+    case CPP_DOT_STAR:
+    case CPP_DEREF:
+    case CPP_DEREF_STAR:
+    case CPP_DIV:
+    case CPP_MOD:
+    case CPP_LSHIFT:
+    case CPP_RSHIFT:
+    case CPP_LESS:
+    case CPP_GREATER:
+    case CPP_LESS_EQ:
+    case CPP_GREATER_EQ:
+    case CPP_EQ_EQ:
+    case CPP_NOT_EQ:
+    case CPP_EQ:
+    case CPP_MULT_EQ:
+    case CPP_DIV_EQ:
+    case CPP_MOD_EQ:
+    case CPP_PLUS_EQ:
+    case CPP_MINUS_EQ:
+    case CPP_RSHIFT_EQ:
+    case CPP_LSHIFT_EQ:
+    case CPP_AND_EQ:
+    case CPP_XOR_EQ:
+    case CPP_OR_EQ:
+    case CPP_XOR:
+    case CPP_OR:
+    case CPP_OR_OR:
+      return false;
+
+      /* '[' may start a primary-expression in obj-c++.  */
+    case CPP_OPEN_SQUARE:
+      return c_dialect_objc ();
+
+    default:
+      return true;
+    }
+}
+
 /* Parse a cast-expression.
 
    cast-expression:
 /* Parse a cast-expression.
 
    cast-expression:
@@ -5988,17 +6042,18 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
-      /* If ok so far, parse the dependent expression. We cannot be
-        sure it is a cast. Consider `(T ())'.  It is a parenthesized
-        ctor of T, but looks like a cast to function returning T
-        without a dependent expression.  */
-      if (!cp_parser_error_occurred (parser))
-       expr = cp_parser_cast_expression (parser,
-                                         /*address_p=*/false,
-                                         /*cast_p=*/true);
-
-      if (cp_parser_parse_definitely (parser))
+      /* At this point this can only be either a cast or a
+        parenthesized ctor such as `(T ())' that looks like a cast to
+        function returning T.  */
+      if (!cp_parser_error_occurred (parser)
+         && cp_parser_token_starts_cast_expression (cp_lexer_peek_token
+                                                    (parser->lexer)))
        {
        {
+         cp_parser_parse_definitely (parser);
+         expr = cp_parser_cast_expression (parser,
+                                           /*address_p=*/false,
+                                           /*cast_p=*/true);
+
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
@@ -6019,6 +6074,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          expr = build_c_cast (type, expr);
          return expr;
        }
          expr = build_c_cast (type, expr);
          return expr;
        }
+      else 
+        cp_parser_abort_tentative_parse (parser);
     }
 
   /* If we get here, then it's not a cast, so it must be a
     }
 
   /* If we get here, then it's not a cast, so it must be a
index d6159e9..2a863f3 100644 (file)
@@ -1,3 +1,8 @@
+2008-10-29  Manuel López-Ibáñez  <manu@gcc.gnu.org>
+
+       PR c++/26997
+       * g++.dg/parse/pr26997.C: New.
+
 2008-10-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/37913
 2008-10-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/37913
diff --git a/gcc/testsuite/g++.dg/parse/pr26997.C b/gcc/testsuite/g++.dg/parse/pr26997.C
new file mode 100644 (file)
index 0000000..acd1e07
--- /dev/null
@@ -0,0 +1,50 @@
+// PR c++/26997
+// { dg-do compile }
+void * malloc (unsigned long size);
+typedef struct { int a; } t;
+
+void foo()
+{
+  t *v3;
+  v3 = (t *)
+    malloc(
+          sizeof(t) 
+          * 
+           t->a // { dg-error "before '->' token" }
+          );
+}
+
+class C {
+public:
+  void operator[](int);
+};
+
+C bar (void)
+{
+  (C ())(3); // { dg-error "invalid cast" } 
+  return (C ());
+}
+
+extern void baz (C,C);
+
+void foo1 (void)
+{
+  baz ((C()), (C()));
+}
+
+struct S {
+  void operator()(int);
+};
+
+int *var;
+void foo2 (void)
+{
+  C ()[2];
+  (C ())[2];
+  (S ())(3); // { dg-error "invalid cast" } 
+  (C())*var; // { dg-error "invalid cast" } 
+  (C())+var;  // { dg-error "invalid cast" } 
+  S()(3);
+  (S()(3));
+}
+