This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PR c++/26997 g++ reports misleading error message when the identifier with error occurs earlier on the same line


2008/10/28 Mark Mitchell <mark@codesourcery.com>:
> Manuel López-Ibáñez wrote:
>> 2008/10/28 Mark Mitchell <mark@codesourcery.com>:
>
>> If I understand correctly (C()) followed by comma, semicolon, period,
>> '->' or unambiguous binary operator must be a call to constructor,
>> anything else must be a cast. Am I right?
>
> I think that's correct, with the exception of the statement-expression
> case already handled by the parser.  I hesitate to make absolute
> statements about these things because there are so many corner cases,
> but I can't think of an example where your rule is incorrect.  As a
> first cut, you could try implementing it and running the testsuite.

This is the updated patch. Notice that I added many more cases to the
new testcase. If anyone can think of more testcases, I will
incorporate them.

It is bootstrapped and regression tested with --enable-languages=all,ada,obj-c++

OK for trunk?


2008-10-28  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	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 constructorarse definitely or an
	actual cast.
testsuite/
	* g++.dg/parse/pr26997.C: New.
Index: gcc/testsuite/g++.dg/parse/pr26997.C
===================================================================
--- gcc/testsuite/g++.dg/parse/pr26997.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/pr26997.C	(revision 0)
@@ -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));
+}
+
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 141363)
+++ gcc/cp/parser.c	(working copy)
@@ -5908,10 +5908,64 @@ cp_parser_delete_expression (cp_parser* 
     return error_mark_node;
 
   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:
      unary-expression
      ( type-id ) cast-expression
@@ -5986,21 +6040,22 @@ cp_parser_cast_expression (cp_parser *pa
 	}
 
       /* 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
 	      && !VOID_TYPE_P (type)
 	      && current_lang_name != lang_name_c)
@@ -6017,10 +6072,14 @@ cp_parser_cast_expression (cp_parser *pa
 
 	  /* Perform the cast.  */
 	  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
      unary-expression.  */
   return cp_parser_unary_expression (parser, address_p, cast_p);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]