PR c++/71604 - type definition in range-based for
authorJason Merrill <jason@redhat.com>
Fri, 15 Jul 2016 18:38:31 +0000 (14:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 15 Jul 2016 18:38:31 +0000 (14:38 -0400)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/range-for31.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/range-for8.C

index d0d855ec088ed9b268498747ca9b8ac7b4c77313..14bcf8e9e54aede0d712b3a2132c9f5763ca695e 100644 (file)
@@ -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.
index 3e865b0fb64557972e447e5f34968c28337566c8..0a0f67b85e32402d249f111b176278bf601d4ee7 100644 (file)
@@ -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 (file)
index 0000000..833f510
--- /dev/null
@@ -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" }
+    ;
+}
index a389f66f60908a60a80184e2921eae1cfc4e54d5..38fe4561eb43d55d531cea6b7dfe9eeab2a88d6b 100644 (file)
@@ -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" }
         ;
 }