detect C++ errors to fix 2288 and 18770
authorJanis Johnson <janis187@us.ibm.com>
Thu, 26 May 2011 20:15:22 +0000 (20:15 +0000)
committerNathan Froyd <froydnj@gcc.gnu.org>
Thu, 26 May 2011 20:15:22 +0000 (20:15 +0000)
detect C++ errors to fix 2288 and 18770
gcc/cp/
PR c++/2288
PR c++/18770
* name-lookup.h (enum scope_kind): Add sk_cond.
* name-lookup.c (pushdecl_maybe_friend): Get scope of shadowed local.
Detect and report error for redeclaration from for-init or if
or switch condition.
(begin_scope): Handle sk_cond.
* semantics.c (begin_if_stmt): Use sk_cond.
(begin switch_stmt): Ditto.
gcc/testsuite/
PR c++/2288
PR c++/18770
* g++.old-deja/g++.jason/cond.C: Remove xfails.
* g++.dg/parse/pr18770.C: New test.
* g++.dg/cpp0x/range-for5.C: Add dg-error marker.

Co-Authored-By: Nathan Froyd <froydnj@codesourcery.com>
From-SVN: r174307

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/range-for5.C
gcc/testsuite/g++.dg/parse/pr18770.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.jason/cond.C

index 4835d8498eb34ade68addf6a30f99625e838b1ce..605289fa68fb628b916bcca4804f1f5b855ac28b 100644 (file)
@@ -1,3 +1,16 @@
+2011-05-26  Janis Johnson  <janis187@us.ibm.com>
+           Nathan Froyd  <froydnj@codesourcery.com>
+
+       PR c++/2288
+       PR c++/18770
+       * name-lookup.h (enum scope_kind): Add sk_cond.
+       * name-lookup.c (pushdecl_maybe_friend): Get scope of shadowed local.
+       Detect and report error for redeclaration from for-init or if
+       or switch condition.
+       (begin_scope): Handle sk_cond.
+       * semantics.c (begin_if_stmt): Use sk_cond.
+       (begin switch_stmt): Ditto.
+
 2011-05-26  Jason Merrill  <jason@redhat.com>
 
        PR c++/48211
index 935dd2a78abc45bedb2252e1ea9b4445a0b4211f..3d07ff65ccedf62e2fa4ebf022de069759441623 100644 (file)
@@ -935,8 +935,15 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
       else
        {
          /* Here to install a non-global value.  */
-         tree oldlocal = innermost_non_namespace_value (name);
          tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
+         tree oldlocal = NULL_TREE;
+         cxx_scope *oldscope = NULL;
+         cxx_binding *oldbinding = outer_binding (name, NULL, true);
+         if (oldbinding)
+           {
+             oldlocal = oldbinding->value;
+             oldscope = oldbinding->scope;
+           }
 
          if (need_new_binding)
            {
@@ -1065,6 +1072,20 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
                       }
                   }
                }
+             /* Error if redeclaring a local declared in a
+                for-init-statement or in the condition of an if or
+                switch statement when the new declaration is in the
+                outermost block of the controlled statement.
+                Redeclaring a variable from a for or while condition is
+                detected elsewhere.  */
+             else if (TREE_CODE (oldlocal) == VAR_DECL
+                      && oldscope == current_binding_level->level_chain
+                      && (oldscope->kind == sk_cond
+                          || oldscope->kind == sk_for))
+               {
+                 error ("redeclaration of %q#D", x);
+                 error ("%q+#D previously declared here", oldlocal);
+               }
 
              if (warn_shadow && !nowarn)
                {
@@ -1424,6 +1445,7 @@ begin_scope (scope_kind kind, tree entity)
     case sk_try:
     case sk_catch:
     case sk_for:
+    case sk_cond:
     case sk_class:
     case sk_scoped_enum:
     case sk_function_parms:
index 3309f0a836a745dc3a1c932efa2a5108fc5a0bcd..009b5d982f10bb6aa6643f0f352f8e5927af0122 100644 (file)
@@ -109,6 +109,8 @@ typedef enum scope_kind {
   sk_catch,         /* A catch-block.  */
   sk_for,           /* The scope of the variable declared in a
                        for-init-statement.  */
+  sk_cond,          /* The scope of the variable declared in the condition
+                       of an if or switch statement.  */
   sk_function_parms, /* The scope containing function parameters.  */
   sk_class,         /* The scope containing the members of a class.  */
   sk_scoped_enum,    /* The scope containing the enumertors of a C++0x
index 55ad117880381127ed6e28a3bbdb299ab3391f8e..7833d765e1b930f45c82a3f2906636aab8793106 100644 (file)
@@ -656,7 +656,7 @@ tree
 begin_if_stmt (void)
 {
   tree r, scope;
-  scope = do_pushlevel (sk_block);
+  scope = do_pushlevel (sk_cond);
   r = build_stmt (input_location, IF_STMT, NULL_TREE,
                  NULL_TREE, NULL_TREE, scope);
   begin_cond (&IF_COND (r));
@@ -1013,7 +1013,7 @@ begin_switch_stmt (void)
 {
   tree r, scope;
 
-  scope = do_pushlevel (sk_block);
+  scope = do_pushlevel (sk_cond);
   r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE, scope);
 
   begin_cond (&SWITCH_STMT_COND (r));
index 4805e9d27d0fb0e554a9984fe43c500ac38f44a3..949474f225da4b403101317d47c3ecd4f1645bfc 100644 (file)
@@ -1,3 +1,12 @@
+2011-05-26  Janis Johnson  <janis187@us.ibm.com>
+           Nathan Froyd  <froydnj@codesourcery.com>
+
+       PR c++/2288
+       PR c++/18770
+       * g++.old-deja/g++.jason/cond.C: Remove xfails.
+       * g++.dg/parse/pr18770.C: New test.
+       * g++.dg/cpp0x/range-for5.C: Add dg-error marker.
+
 2011-05-26  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR fortran/48955
index 9c97ad5faf08d32d6436bc178f2c2c446483edc2..fd6f7618f98033f920fb85a77d8d1f87a6c86c65 100644 (file)
@@ -47,8 +47,8 @@ void test1()
 
   //Check the correct scopes
   int i;
-  for (int i : a)
+  for (int i : a)              // { dg-error "previously declared" }
   {
-    int i;
+    int i;                     // { dg-error "redeclaration" }
   }
 }
diff --git a/gcc/testsuite/g++.dg/parse/pr18770.C b/gcc/testsuite/g++.dg/parse/pr18770.C
new file mode 100644 (file)
index 0000000..df57be4
--- /dev/null
@@ -0,0 +1,175 @@
+/* { dg-do compile } */
+
+/* The ISO C++ standard says, in Section 3.3.2 sentence 4, that a name
+   declared in the for-init-statement or in the condition of an if, for
+   while, or switch statement can't be redeclared in the outermost block
+   of the controlled statement.  (Note, this is not an error in C.)  */
+
+extern void foo (int);
+extern int j;
+
+void
+e0 (void)
+{
+  for (int i = 0;      // { dg-error "previously declared here" "prev" }
+       i < 10; ++i)
+    {
+      int i = 2;       // { dg-error "redeclaration" "redecl" }
+      foo (i);
+    }
+}
+
+void
+e1 (void)
+{
+  int i;
+  for (i = 0;
+       int k = j; i++) // { dg-error "previously declared here" "prev" }
+    {
+      int k = 2;       // { dg-error "redeclaration" "redecl" }
+      foo (k);
+    }
+}
+
+void
+e2 (void)
+{
+  if (int i = 1)       // { dg-error "previously declared here" "prev" }
+    {
+      int i = 2;       // { dg-error "redeclaration" "redecl" }
+      foo (i);
+    }
+}
+
+void
+e3 (void)
+{
+  if (int i = 1)       // { dg-error "previously declared here" "prev" }
+    {
+      foo (i);
+    }
+  else
+    {
+      int i = 2;       // { dg-error "redeclaration" "redecl" }
+      foo (i);
+    }
+}
+
+void
+e4 (void)
+{
+  while (int i = 1)    // { dg-error "previously declared here" "prev" }
+    {
+      int i = 2;       // { dg-error "redeclaration" "redecl" }
+      foo (i);
+    }
+}
+
+void
+e5 (void)
+{
+  switch (int i = j)   // { dg-error "previously declared here" "prev" }
+    {
+    int i;             // { dg-error "redeclaration" "redecl" }
+    default:
+      {
+        i = 2;
+        foo (i);
+      }
+    }
+}
+
+void
+f0 (void)
+{
+  for (int i = 0; i < 10; ++i)
+    {
+      foo (i);
+      {
+        int i = 2;     // OK, not outermost block.
+        foo (i);
+      }
+    }
+}
+
+void
+f1 (void)
+{
+  int i;
+  for (i = 0; int k = j; i++)
+    {
+      foo (k);
+      {
+       int k = 2;      // OK, not outermost block.
+       foo (k);
+      }
+    }
+}
+
+void
+f2 (void)
+{
+  if (int i = 1)
+    {
+      foo (i);
+      {
+       int i = 2;      // OK, not outermost block.
+       foo (i);
+      }
+    }
+}
+
+void
+f3 (void)
+{
+  if (int i = 1)
+    {
+      foo (i);
+    }
+  else
+    {
+      foo (i+2);
+      {
+       int i = 2;      // OK, not outermost block.
+       foo (i);
+      }
+    }
+}
+
+void
+f4 (void)
+{
+  while (int i = 1)
+    {
+      foo (i);
+      {
+       int i = 2;      // OK, not outermost block.
+       foo (i);
+      }
+    }
+}
+
+void
+f5 (void)
+{
+  switch (int i = j)
+    {
+    default:
+      {
+        int i = 2;     // OK, not outermost block.
+        foo (i);
+      }
+    }
+}
+
+void
+f6 (void)
+{
+  int i = 1;
+
+  for (int j = 0; j < 10; j++)
+    {
+      int i = 2;       // OK, not variable from for-init.
+      foo (i);
+    }
+}
index d0616e4be554de093d35b3a0b91e251eabe84898..a6e5ba0db2bbd8046114680fdc90cdab9c4692ca 100644 (file)
@@ -6,14 +6,14 @@ int main()
 {
   float i;
   
-  if (int i = 1)               // { dg-error "" "" { xfail *-*-* } } , 
+  if (int i = 1)               // { dg-error "previously" }
     {
-      char i;                  // { dg-error "" "" { xfail *-*-* } } , 
+      char i;                  // { dg-error "redeclaration" } 
       char j;
     }
   else
     {
-      short i;                 // { dg-error "" "" { xfail *-*-* } } , 
+      short i;                 // { dg-error "redeclaration" }
       char j;
     }
 
@@ -27,10 +27,10 @@ int main()
       int i;                   // { dg-error "redeclaration" }
     }
 
-  switch (int i = 0)           // { dg-error "" "" { xfail *-*-* } } 
+  switch (int i = 0)           // { dg-error "previously" }
     {
     default:
-      int i;                   // { dg-error "" "" { xfail *-*-* } } 
+      int i;                   // { dg-error "redeclaration" } 
     }
 
   if (struct A { operator int () { return 1; } } *foo = new A) // { dg-error "defined" }