This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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);