Hi,
in this C++14 rejects valid issue, we reject the testcase with "‘x’ was
not declared in this scope", because in cp_parser_initializer_list we
tentatively try to parse what follows the '[' as a
cp_parser_constant_expression. As far as I can see, we can easily solve
the issue with the approach already used in many other places, thus
don't even try a constant if the ']' isn't followed by '='. Tested
x86_64-linux.
Thanks!
Paolo.
PS: I tried to once reuse as is the new
cp_parser_skip_to_closing_square_bracket in cp_parser_lambda_introducer
but we get more redundant diagnostic eg, at the end of
g++.old-deja/g++.other/crash28.C. In fact, the context is slightly
different, because in cp_parser_skip_to_closing_square_bracket we are in
error recovery. I suppose we can further investigate this later...
/cp
2014-09-23 Paolo Carlini <paolo.carl...@oracle.com>
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 <paolo.carl...@oracle.com>
PR c++/61857
* g++.dg/cpp1y/lambda-init10.C: New.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 215496)
+++ cp/parser.c (working copy)
@@ -2487,6 +2487,10 @@ static cp_declarator * cp_parser_make_indirect_dec
(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* no
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, boo
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)
Index: testsuite/g++.dg/cpp1y/lambda-init10.C
===================================================================
--- testsuite/g++.dg/cpp1y/lambda-init10.C (revision 0)
+++ testsuite/g++.dg/cpp1y/lambda-init10.C (working copy)
@@ -0,0 +1,8 @@
+// PR c++/61857
+// { dg-do compile { target c++14 } }
+
+struct A {
+ A(int val) {}
+};
+
+A a{ [x=123]{ return x; }() };