From d3f7b2c67ed130a856a1d7425e76d69d47bb6006 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= Date: Wed, 29 Oct 2008 16:05:27 +0000 Subject: [PATCH] re PR c++/26997 (g++ reports misleading error message when the identifier with error occurs earlier on the same line) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2008-10-29 Manuel López-Ibáñez 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. From-SVN: r141429 --- gcc/cp/ChangeLog | 8 +++ gcc/cp/parser.c | 77 ++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/parse/pr26997.C | 50 ++++++++++++++++++ 4 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/pr26997.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0293d49e833..5115c1b6237 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2008-10-29 Manuel López-Ibáñez + + 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 PR c/7543 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 75960483974..40f2a3a11ec 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5910,6 +5910,60 @@ cp_parser_delete_expression (cp_parser* parser) 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: @@ -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; - /* 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 @@ -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; } + else + cp_parser_abort_tentative_parse (parser); } /* If we get here, then it's not a cast, so it must be a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d6159e9bfad..2a863f3cb47 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-10-29 Manuel López-Ibáñez + + PR c++/26997 + * g++.dg/parse/pr26997.C: New. + 2008-10-29 Jakub Jelinek 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 index 00000000000..acd1e07be34 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr26997.C @@ -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)); +} + -- 2.30.2