aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2014-09-23 18:07:59 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2014-09-23 18:07:59 +0000
commit9a9f3c8f1e05cec05b02b8b79e6a5531ba8dc377 (patch)
treecc7176301d6b9e77036a648226d04212b4efe368 /gcc
parent866e32ad336f1698809cc03c48f884379d6b39e0 (diff)
downloadgcc-9a9f3c8f1e05cec05b02b8b79e6a5531ba8dc377.zip
gcc-9a9f3c8f1e05cec05b02b8b79e6a5531ba8dc377.tar.gz
gcc-9a9f3c8f1e05cec05b02b8b79e6a5531ba8dc377.tar.bz2
re PR c++/61857 (An init-capturing lambda is parsed incorrectly when used in a braced-init-list)
/cp 2014-09-23 Paolo Carlini <paolo.carlini@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.carlini@oracle.com> PR c++/61857 * g++.dg/cpp1y/lambda-init10.C: New. From-SVN: r215528
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c85
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-init10.C8
4 files changed, 101 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d6db39f..8058348 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2014-09-23 Paolo Carlini <paolo.carlini@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.
+
2014-09-22 Jason Merrill <jason@redhat.com>
* semantics.c (finish_non_static_data_member): In diagnostic, give
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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c7be6d9..206860a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-09-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/61857
+ * g++.dg/cpp1y/lambda-init10.C: New.
+
2014-09-23 Jakub Jelinek <jakub@redhat.com>
PR fortran/63331
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init10.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init10.C
new file mode 100644
index 0000000..230b3d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init10.C
@@ -0,0 +1,8 @@
+// PR c++/61857
+// { dg-do compile { target c++14 } }
+
+struct A {
+ A(int val) {}
+};
+
+A a{ [x=123]{ return x; }() };