aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-07-15 14:38:31 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-07-15 14:38:31 -0400
commit37a92c0ca231f3767dd905f155fb8d9a20369f2b (patch)
tree8579794f6a66c6d0a43e524e60b1dbd9780d1d22
parentaa30dfadf3234caa8a29ef23ddc5932101a0e430 (diff)
downloadgcc-37a92c0ca231f3767dd905f155fb8d9a20369f2b.zip
gcc-37a92c0ca231f3767dd905f155fb8d9a20369f2b.tar.gz
gcc-37a92c0ca231f3767dd905f155fb8d9a20369f2b.tar.bz2
PR c++/71604 - type definition in range-based for
PR c++/54430 * parser.c (cp_parser_range_for): Modify IDENTIFIER_BINDING directly. (cp_parser_simple_declaration): Diagnose type definition in for-range-declaration. From-SVN: r238391
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/parser.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for31.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for8.C4
4 files changed, 36 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d0d855e..14bcf8e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2016-07-15 Jason Merrill <jason@redhat.com>
+ PR c++/71604
+ PR c++/54430
+ * parser.c (cp_parser_range_for): Modify IDENTIFIER_BINDING directly.
+ (cp_parser_simple_declaration): Diagnose type definition in
+ for-range-declaration.
+
PR c++/71711
* operators.def: Add *_FOLD_EXPR.
* cp-tree.h (FOLD_EXPR_P): Parenthesize.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3e865b0..0a0f67b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11187,11 +11187,17 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
bool ivdep)
{
tree stmt, range_expr;
+ cxx_binding *binding = NULL;
+ tree name = NULL_TREE;
/* Get the range declaration momentarily out of the way so that
the range expression doesn't clash with it. */
if (range_decl != error_mark_node)
- pop_binding (DECL_NAME (range_decl), range_decl);
+ {
+ name = DECL_NAME (range_decl);
+ binding = IDENTIFIER_BINDING (name);
+ IDENTIFIER_BINDING (name) = binding->previous;
+ }
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
@@ -11203,7 +11209,10 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
/* Put the range declaration back into scope. */
if (range_decl != error_mark_node)
- push_binding (DECL_NAME (range_decl), range_decl, current_binding_level);
+ {
+ binding->previous = IDENTIFIER_BINDING (name);
+ IDENTIFIER_BINDING (name) = binding;
+ }
/* If in template, STMT is converted to a normal for-statement
at instantiation. If not, it is done just ahead. */
@@ -12437,8 +12446,15 @@ cp_parser_simple_declaration (cp_parser* parser,
if (token->type == CPP_COMMA)
/* will be consumed next time around */;
/* If it's a `;', we are done. */
- else if (token->type == CPP_SEMICOLON || maybe_range_for_decl)
+ else if (token->type == CPP_SEMICOLON)
break;
+ else if (maybe_range_for_decl)
+ {
+ if (declares_class_or_enum && token->type == CPP_COLON)
+ permerror (decl_specifiers.locations[ds_type_spec],
+ "types may not be defined in a for-range-declaration");
+ break;
+ }
/* Anything else is an error. */
else
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for31.C b/gcc/testsuite/g++.dg/cpp0x/range-for31.C
new file mode 100644
index 0000000..833f510
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for31.C
@@ -0,0 +1,9 @@
+// PR c++/71604
+// { dg-do compile { target c++11 } }
+
+void foo ()
+{
+ int a[2] = { 1, 2 };
+ for (struct S { S (int) {} } S : a) // { dg-error "types may not be defined" }
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for8.C b/gcc/testsuite/g++.dg/cpp0x/range-for8.C
index a389f66..38fe456 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for8.C
@@ -7,9 +7,9 @@
void test()
{
- for (struct S { } *x : { (S*)0, (S*)0 } )
+ for (struct S { } *x : { (S*)0, (S*)0 } ) // { dg-error "types may not be defined" }
;
- for (struct S { } x : { S(), S() } )
+ for (struct S { } x : { S(), S() } ) // { dg-error "types may not be defined" }
;
}