From 9a9f3c8f1e05cec05b02b8b79e6a5531ba8dc377 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 23 Sep 2014 18:07:59 +0000 Subject: re PR c++/61857 (An init-capturing lambda is parsed incorrectly when used in a braced-init-list) /cp 2014-09-23 Paolo Carlini PR c++/61857 * parser.c (cp_parser_skip_to_closing_square_bracket, cp_parser_array_designator_p): New. (cp_parser_initializer_list): Use the latter. /testsuite 2014-09-23 Paolo Carlini PR c++/61857 * g++.dg/cpp1y/lambda-init10.C: New. From-SVN: r215528 --- gcc/cp/parser.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 4 deletions(-) (limited to 'gcc/cp/parser.c') diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9764794..33ad886 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2487,6 +2487,10 @@ static cp_declarator * cp_parser_make_indirect_declarator (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree); static bool cp_parser_compound_literal_p (cp_parser *); +static bool cp_parser_array_designator_p + (cp_parser *); +static bool cp_parser_skip_to_closing_square_bracket + (cp_parser *); /* Returns nonzero if we are parsing tentatively. */ @@ -19157,6 +19161,69 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) return initializer; } +/* Consume tokens up to, and including, the next non-nested closing `]'. + Returns true iff we found a closing `]'. */ + +static bool +cp_parser_skip_to_closing_square_bracket (cp_parser *parser) +{ + unsigned square_depth = 0; + + while (true) + { + cp_token * token = cp_lexer_peek_token (parser->lexer); + + switch (token->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + /* If we've run out of tokens, then there is no closing `]'. */ + return false; + + case CPP_OPEN_SQUARE: + ++square_depth; + break; + + case CPP_CLOSE_SQUARE: + if (!square_depth--) + { + cp_lexer_consume_token (parser->lexer); + return true; + } + break; + + default: + break; + } + + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + } +} + +/* Return true if we are looking at an array-designator, false otherwise. */ + +static bool +cp_parser_array_designator_p (cp_parser *parser) +{ + /* Consume the `['. */ + cp_lexer_consume_token (parser->lexer); + + cp_lexer_save_tokens (parser->lexer); + + /* Skip tokens until the next token is a closing square bracket. + If we find the closing `]', and the next token is a `=', then + we are looking at an array designator. */ + bool array_designator_p + = (cp_parser_skip_to_closing_square_bracket (parser) + && cp_lexer_next_token_is (parser->lexer, CPP_EQ)); + + /* Roll back the tokens we skipped. */ + cp_lexer_rollback_tokens (parser->lexer); + + return array_designator_p; +} + /* Parse an initializer-list. initializer-list: @@ -19235,10 +19302,20 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) bool non_const = false; cp_parser_parse_tentatively (parser); - cp_lexer_consume_token (parser->lexer); - designator = cp_parser_constant_expression (parser, true, &non_const); - cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - cp_parser_require (parser, CPP_EQ, RT_EQ); + + if (!cp_parser_array_designator_p (parser)) + { + cp_parser_simulate_error (parser); + designator = NULL_TREE; + } + else + { + designator = cp_parser_constant_expression (parser, true, + &non_const); + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + cp_parser_require (parser, CPP_EQ, RT_EQ); + } + if (!cp_parser_parse_definitely (parser)) designator = NULL_TREE; else if (non_const) -- cgit v1.1