From 54063e0f79ebafc8eb90ba9170596b76211799d8 Mon Sep 17 00:00:00 2001 From: paolo Date: Sat, 2 Nov 2013 09:34:13 +0000 Subject: [PATCH] /cp 2013-11-02 Paolo Carlini PR c++/29234 PR c++/56037 * parser.c (cp_parser_cast_expression): If we aren't looking at a cast-expression don't call cp_parser_type_id. (cp_parser_postfix_expression): Likewise for compound-literal. (cp_parser_tokens_start_cast_expression): Adjust. /testsuite 2013-11-02 Paolo Carlini PR c++/29234 PR c++/56037 * g++.dg/parse/pr29234.C: New. * g++.dg/parse/pr56037.C: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204312 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/parser.c | 88 +++++++++++++++++++++++------------- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/g++.dg/parse/pr29234.C | 16 +++++++ gcc/testsuite/g++.dg/parse/pr56037.C | 12 +++++ 5 files changed, 101 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/pr29234.C create mode 100644 gcc/testsuite/g++.dg/parse/pr56037.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 707b9495560..694aaae6de3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2013-11-02 Paolo Carlini + + PR c++/29234 + PR c++/56037 + * parser.c (cp_parser_cast_expression): If we aren't looking at + a cast-expression don't call cp_parser_type_id. + (cp_parser_postfix_expression): Likewise for compound-literal. + (cp_parser_tokens_start_cast_expression): Adjust. + 2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net> PR c++/58708 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d55f5f9c786..4e06e8af0b6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5817,31 +5817,45 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { tree initializer = NULL_TREE; - bool saved_in_type_id_in_expr_p; + bool compound_literal_p; cp_parser_parse_tentatively (parser); /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); - /* Parse the type. */ - saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; - parser->in_type_id_in_expr_p = true; - type = cp_parser_type_id (parser); - parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; - /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + + /* Avoid calling cp_parser_type_id pointlessly, see comment + in cp_parser_cast_expression about c++/29234. */ + cp_lexer_save_tokens (parser->lexer); + + compound_literal_p + = (cp_parser_skip_to_closing_parenthesis (parser, false, false, + /*consume_paren=*/true) + && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); + + /* Roll back the tokens we skipped. */ + cp_lexer_rollback_tokens (parser->lexer); + + if (!compound_literal_p) + cp_parser_simulate_error (parser); + else + { + /* Parse the type. */ + bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; + parser->in_type_id_in_expr_p = true; + type = cp_parser_type_id (parser); + parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; + /* Look for the `)'. */ + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + } + /* If things aren't going well, there's no need to keep going. */ if (!cp_parser_error_occurred (parser)) { - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - { - bool non_constant_p; - /* Parse the brace-enclosed initializer list. */ - initializer = cp_parser_braced_list (parser, - &non_constant_p); - } - else - cp_parser_simulate_error (parser); + bool non_constant_p; + /* Parse the brace-enclosed initializer list. */ + initializer = cp_parser_braced_list (parser, + &non_constant_p); } /* If that worked, we're definitely looking at a compound-literal expression. */ @@ -7509,6 +7523,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) case CPP_CLOSE_SQUARE: case CPP_CLOSE_PAREN: case CPP_CLOSE_BRACE: + case CPP_OPEN_BRACE: case CPP_DOT: case CPP_DOT_STAR: case CPP_DEREF: @@ -7576,7 +7591,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, { tree type = NULL_TREE; tree expr = NULL_TREE; - bool compound_literal_p; + bool cast_expression_p; const char *saved_message; /* There's no way to know yet whether or not this is a cast. @@ -7599,26 +7614,38 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, will commit to the parse at that point, because we cannot undo the action that is done when creating a new class. So, then we cannot back up and do a postfix-expression. + Another tricky case is the following (c++/29234): + + struct S { void operator () (); }; + + void foo () + { + ( S()() ); + } + + As a type-id we parse the parenthesized S()() as a function + returning a function, groktypename complains and we cannot + back up in this case either. Therefore, we scan ahead to the closing `)', and check to see - if the token after the `)' is a `{'. If so, we are not - looking at a cast-expression. + if the tokens after the `)' can start a cast-expression. Otherwise + we are dealing with an unary-expression, a postfix-expression + or something else. Save tokens so that we can put them back. */ cp_lexer_save_tokens (parser->lexer); - /* Skip tokens until the next token is a closing parenthesis. - If we find the closing `)', and the next token is a `{', then - we are looking at a compound-literal. */ - compound_literal_p + + /* We may be looking at a cast-expression. */ + cast_expression_p = (cp_parser_skip_to_closing_parenthesis (parser, false, false, /*consume_paren=*/true) - && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); + && cp_parser_tokens_start_cast_expression (parser)); + /* Roll back the tokens we skipped. */ cp_lexer_rollback_tokens (parser->lexer); - /* If we were looking at a compound-literal, simulate an error - so that the call to cp_parser_parse_definitely below will - fail. */ - if (compound_literal_p) + /* If we aren't looking at a cast-expression, simulate an error so + that the call to cp_parser_parse_definitely below will fail. */ + if (!cast_expression_p) cp_parser_simulate_error (parser); else { @@ -7637,8 +7664,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* 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_tokens_start_cast_expression (parser)) + if (!cp_parser_error_occurred (parser)) { cp_parser_parse_definitely (parser); expr = cp_parser_cast_expression (parser, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 964cd4114f7..1abd7c10075 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-11-02 Paolo Carlini + + PR c++/29234 + PR c++/56037 + * g++.dg/parse/pr29234.C: New. + * g++.dg/parse/pr56037.C: Likewise. + 2013-11-01 Balaji V. Iyer * gcc.dg/cilk-plus/cilk-plus.exp: Loaded libcilkrts library path and diff --git a/gcc/testsuite/g++.dg/parse/pr29234.C b/gcc/testsuite/g++.dg/parse/pr29234.C new file mode 100644 index 00000000000..d2dc735f226 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr29234.C @@ -0,0 +1,16 @@ +// PR c++/29234 + +struct S { void operator()(); }; + +void foo () +{ + ( S()() ); +} + +struct C { void operator[](C); }; + +void bar () +{ + C x; + ( C()[x] ); +} diff --git a/gcc/testsuite/g++.dg/parse/pr56037.C b/gcc/testsuite/g++.dg/parse/pr56037.C new file mode 100644 index 00000000000..10f145ae5ee --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr56037.C @@ -0,0 +1,12 @@ +// PR c++/56037 + +struct T +{ + T(int, int); +}; + +int main() +{ + static const int zero = 0; + (T(int(zero), int(zero))); +} -- 2.11.4.GIT