re PR c++/54430 ([C++11] For-Loop: Scope of iterating variable begins too early)
authorVille Voutilainen <ville.voutilainen@gmail.com>
Thu, 1 Oct 2015 19:22:08 +0000 (22:22 +0300)
committerVille Voutilainen <ville@gcc.gnu.org>
Thu, 1 Oct 2015 19:22:08 +0000 (22:22 +0300)
PR c++/54430

/cp
2015-10-01  Ville Voutilainen  <ville.voutilainen@gmail.com>

PR c++/54430
* name-lookup.c (push_binding): Make non-static.
* name-lookup.h (push_binding): Declare it.
* parser.c (cp_parser_range_for): Use it, get the range
declaration away from the scope until the range expression
has been parsed, then restore the declaration.

/testsuite
2015-10-01  Ville Voutilainen  <ville.voutilainen@gmail.com>

PR c++/54430
* g++.dg/cpp0x/range-for30.C: New.

From-SVN: r228354

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/range-for30.C [new file with mode: 0644]

index cb3a9b16f43efe69ff43ad4633601708b49b5178..72c3bf93b09df01d61debb82dafe9833b3bf79fb 100644 (file)
@@ -1,3 +1,12 @@
+2015-10-01  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       PR c++/54430
+       * name-lookup.c (push_binding): Make non-static.
+       * name-lookup.h (push_binding): Declare it.
+       * parser.c (cp_parser_range_for): Use it, get the range
+       declaration away from the scope until the range expression
+       has been parsed, then restore the declaration.
+
 2015-09-23  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        Fix small typos in the coding rule enforcement warnings.
index baaf3e7ca98e376a1814df7fb166a5b560572ce2..bd052a487537cf20cf64357171f7c90621c15a4e 100644 (file)
@@ -332,7 +332,7 @@ new_class_binding (tree name, tree value, tree type, cp_binding_level *scope)
 /* Make DECL the innermost binding for ID.  The LEVEL is the binding
    level at which this declaration is being bound.  */
 
-static void
+void
 push_binding (tree id, tree decl, cp_binding_level* level)
 {
   cxx_binding *binding;
index 4b9419282d15037112cbde12268534a636dc30d0..82b5e53c7403ce82b6bccf492b4fc6b8a24e9eff 100644 (file)
@@ -88,6 +88,7 @@ struct GTY(()) cxx_saved_binding {
 
 extern tree identifier_type_value (tree);
 extern void set_identifier_type_value (tree, tree);
+extern void push_binding (tree, tree, cp_binding_level*);
 extern void pop_binding (tree, tree);
 extern void pop_bindings_and_leave_scope (void);
 extern tree constructor_name (tree);
index 114815660a2b3c92f9ec7bf1313d8963922e049d..8aeca4063dbb8ec491d6841ccb850e8426ec013b 100644 (file)
@@ -10725,6 +10725,11 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
 {
   tree stmt, range_expr;
 
+  /* 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);
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
       bool expr_non_constant_p;
@@ -10733,6 +10738,10 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
   else
     range_expr = cp_parser_expression (parser);
 
+  /* Put the range declaration back into scope. */
+  if (range_decl != error_mark_node)
+    push_binding (DECL_NAME (range_decl), range_decl, current_binding_level);
+
   /* If in template, STMT is converted to a normal for-statement
      at instantiation. If not, it is done just ahead. */
   if (processing_template_decl)
index e7e22461de5833e3654837bfa5fb6bb077418bce..92625b32e56c6a6398728869bdc8c1a8dd840f3e 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-01  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       PR c++/54430
+       * g++.dg/cpp0x/range-for30.C: New.
+
 2015-10-01  Marek Polacek  <polacek@redhat.com>
 
        PR c/65345
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for30.C b/gcc/testsuite/g++.dg/cpp0x/range-for30.C
new file mode 100644 (file)
index 0000000..d559d0f
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/54430
+// { dg-require-effective-target c++11 }
+
+struct A
+{
+  A(int) {}
+  int* begin() {return nullptr;}
+  int* end() {return nullptr;}
+};
+
+int main()
+{
+  int i[] = { 1, 2, 3, 4 };
+  for (int i : i);
+  for (auto i : i);
+  for (A v : v); // { dg-error "not declared in this scope" }
+}