Add -Wshadow=global -Wshadow=local and -Wshadow=compatible-local.
authorLe-Chun Wu <lcwu@google.com>
Mon, 31 Oct 2016 13:21:59 +0000 (13:21 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Mon, 31 Oct 2016 13:21:59 +0000 (13:21 +0000)
This patch from Le-Chun Wu adds two new shadow warning flags for
C and C++:

  -Wshadow=local which warns if a local variable shadows another local
  variable or parameter,

  -Wshadow=compatible-local which warns if a local variable shadows
  another local variable or parameter whose type is compatible with
  that of the shadowing variable.

It is already on the google/main branch (Google ref 39127) and was
previously submitted by Diego Novillo and reviewed on
http://codereview.appspot.com/4452058

I addressed the review comments and made the following changes:
- Add -Wshadow=global (the default alias for -Wshadow).
- Make the documented options -Wshadow=global, -Wshadow=local
  and -Wshadow=compatible-local (with hidden undocumented aliases
  -Wshadow-local and -Wshadow-compatible-local for compatibility).
- The -Wshadow=global, -Wshadow=local and -Wshadow=compatible-local
  relationships are expressed in common.opt instead of in opts.c
  and documented in invoke.texi.
- The "previous declaration" warnings were turned into notes and use
  the (now) existing infrastructure instead of duplicating the warnings.
  The testcases have been adjusted to expect the notes.
- The conditional change in name-lookup.c for non-locals (where we
  don't want to change the warnings, but just check the global ones)
  has been dropped.
- Use warning_at in c-decl.c (warn_if_shadowing).

gcc/ChangeLog:
2016-10-30  Le-Chun Wu  <lcwu@google.com>
            Mark Wielaard  <mjw@redhat.com>

       * doc/invoke.texi: Document Wshadow-local and Wshadow-compatible-local.
       * common.opt (Wshadow=global): New option. Default for -Wshadow.
       (Wshadow=local): New option.
       (Wshadow-local): Hidden alias for -Wshadow=local.
       (Wshadow=compatible-local): New option.
       (Wshadow-compatible-local): Hidden alias for
       -Wshadow=compatible-local.
       * doc/invoke.texi: Document Wshadow=global, Wshadow=local and
       Wshadow=compatible-local.

gcc/c/ChangeLog:
2016-10-30  Le-Chun Wu  <lcwu@google.com>
            Mark Wielaard  <mjw@redhat.com>

       * c-decl.c (warn_if_shadowing): Use the warning code corresponding
       to the given -Wshadow= variant. Use warning_at.

gcc/cp/ChangeLog:
2016-10-30  Le-Chun Wu  <lcwu@google.com>
            Mark Wielaard  <mjw@redhat.com>

       * name-lookup.c (pushdecl_maybe_friend): When emitting a
       shadowing warning, use the code corresponding to the
       given -Wshadow= variant.

gcc/testsuite/ChangeLog
2016-10-30  Le-Chun Wu  <lcwu@google.com>
            Mark Wielaard  <mjw@redhat.com>

       * gcc.dg/Wshadow-compatible-local-1.c: New test.
       * gcc.dg/Wshadow-local-1.c: Likewise.
       * gcc.dg/Wshadow-local-2.c: Likewise.
       * g++.dg/warn/Wshadow-compatible-local-1.C: Likewise.
       * g++.dg/warn/Wshadow-local-1.C: Likewise.
       * g++.dg/warn/Wshadow-local-2.C: Likewise.

Co-Authored-By: Mark Wielaard <mjw@redhat.com>
From-SVN: r241699

15 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/common.opt
gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wshadow-local-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wshadow-local-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wshadow-local-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wshadow-local-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wshadow-local-3.c [new file with mode: 0644]

index ddd004900b8c2830a13fd4f9dcff2116485a1f2d..7905d955cfe352af032fada315650220cab615b4 100644 (file)
@@ -1,3 +1,15 @@
+2016-09-11  Le-Chun Wu  <lcwu@google.com>
+           Mark Wielaard  <mjw@redhat.com>
+
+       * common.opt (Wshadow=global): New option. Default for -Wshadow.
+       (Wshadow=local): New option.
+       (Wshadow-local): Hidden alias for -Wshadow=local.
+       (Wshadow=compatible-local): New option.
+       (Wshadow-compatible-local): Hidden alias for
+       -Wshadow=compatible-local.
+       * doc/invoke.texi: Document Wshadow=global, Wshadow=local and
+       Wshadow=compatible-local.
+
 2016-10-31  Bin Cheng  <bin.cheng@arm.com>
 
        * tree-vect-slp.c (vect_get_and_check_slp_defs): New parameter SWAP.
index 725afcfefa06c7b47653b4e50291a884bc5ab25c..ee50c304b5f6dc361c3d623df79e19a7f01eb161 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-11  Le-Chun Wu  <lcwu@google.com>
+           Mark Wielaard  <mjw@redhat.com>
+
+       * c-decl.c (warn_if_shadowing): Use the warning code corresponding
+       to the given -Wshadow= variant.
+
 2016-10-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * c-typeck.c: Include memmodel.h.
index 136f304ca309ae202c06b41992e6feed0bd51486..3e1b7a4016b1eadbc96cb902ef2e36d7a55d945d 100644 (file)
@@ -2735,7 +2735,9 @@ warn_if_shadowing (tree new_decl)
   struct c_binding *b;
 
   /* Shadow warnings wanted?  */
-  if (!warn_shadow
+  if (!(warn_shadow
+        || warn_shadow_local
+        || warn_shadow_compatible_local)
       /* No shadow warnings for internally generated vars.  */
       || DECL_IS_BUILTIN (new_decl)
       /* No shadow warnings for vars made for inlining.  */
@@ -2759,9 +2761,23 @@ warn_if_shadowing (tree new_decl)
            break;
          }
        else if (TREE_CODE (old_decl) == PARM_DECL)
-         warned = warning (OPT_Wshadow,
-                           "declaration of %q+D shadows a parameter",
-                           new_decl);
+         {
+           enum opt_code warning_code;
+
+           /* If '-Wshadow=compatible-local' is specified without other
+              -Wshadow= flags, we will warn only when the types of the
+              shadowing variable (i.e. new_decl) and the shadowed variable
+              (old_decl) are compatible.  */
+           if (warn_shadow)
+             warning_code = OPT_Wshadow;
+           else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+             warning_code = OPT_Wshadow_compatible_local;
+           else
+             warning_code = OPT_Wshadow_local;
+           warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+                                "declaration of %qD shadows a parameter",
+                                new_decl);
+         }
        else if (DECL_FILE_SCOPE_P (old_decl))
          {
            /* Do not warn if a variable shadows a function, unless
@@ -2784,8 +2800,23 @@ warn_if_shadowing (tree new_decl)
            break;
          }
        else
-         warned = warning (OPT_Wshadow, "declaration of %q+D shadows a "
-                           "previous local", new_decl);
+         {
+           enum opt_code warning_code;
+
+           /* If '-Wshadow=compatible-local' is specified without other
+              -Wshadow= flags, we will warn only when the types of the
+              shadowing variable (i.e. new_decl) and the shadowed variable
+              (old_decl) are compatible.  */
+           if (warn_shadow)
+             warning_code = OPT_Wshadow;
+           else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+             warning_code = OPT_Wshadow_compatible_local;
+           else
+             warning_code = OPT_Wshadow_local;
+           warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+                                "declaration of %qD shadows a previous local",
+                                new_decl);
+         }
 
        if (warned)
          inform (DECL_SOURCE_LOCATION (old_decl),
index 20dbfc1d6a1a496292d40ba904bb1eff441e03c4..2c2f7ad7aa99151f3f872767af75cb902a4a316a 100644 (file)
@@ -668,7 +668,25 @@ Warn about returning a pointer/reference to a local or temporary variable.
 
 Wshadow
 Common Var(warn_shadow) Warning
-Warn when one local variable shadows another.
+Warn when one variable shadows another.  Same as -Wshadow=global.
+
+Wshadow=global
+Common Warning Alias(Wshadow)
+Warn when one variable shadows another (globally).
+
+Wshadow=local
+Common Var(warn_shadow_local) Warning EnabledBy(Wshadow)
+Warn when one local variable shadows another local variable or parameter.
+
+Wshadow-local
+Common Warning Undocumented Alias(Wshadow=local)
+
+Wshadow=compatible-local
+Common Var(warn_shadow_compatible_local) Warning EnabledBy(Wshadow=local)
+Warn when one local variable shadows another local variable or parameter of compatible type.
+
+Wshadow-compatible-local
+Common Warning Undocumented Alias(Wshadow=compatible-local)
 
 Wstack-protector
 Common Var(warn_stack_protect) Warning
index efce361f880a333649ab5910fd02029d65720e60..be439ec3a386aaec3920f404062bf972f7f2c748 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-11  Le-Chun Wu  <lcwu@google.com>
+           Mark Wielaard  <mjw@redhat.com>
+
+       * name-lookup.c (pushdecl_maybe_friend): When emitting a
+       shadowing warning, use the code corresponding to the
+       given -Wshadow= variant.
+
 2016-10-26  Jason Merrill  <jason@redhat.com>
 
        * class.c (add_method): Allow using-declarations to coexist.
index 9e84a1b1f2eeeed222a996f8df0cad4ac518273d..023ed87098f1c4e9b6e55aaac76242146414d038 100644 (file)
@@ -1195,19 +1195,41 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
                  nowarn = true;
                }
 
-             if (warn_shadow && !nowarn)
+             if ((warn_shadow
+                  || warn_shadow_local
+                  || warn_shadow_compatible_local)
+                 && !nowarn)
                {
                  bool warned;
+                 enum opt_code warning_code;
+                 /* If '-Wshadow=compatible-local' is specified without other
+                    -Wshadow= flags, we will warn only when the type of the
+                    shadowing variable (i.e. x) can be converted to that of
+                    the shadowed parameter (oldlocal). The reason why we only
+                    check if x's type can be converted to oldlocal's type
+                    (but not the other way around) is because when users
+                    accidentally shadow a parameter, more than often they
+                    would use the variable thinking (mistakenly) it's still
+                    the parameter. It would be rare that users would use the
+                    variable in the place that expects the parameter but
+                    thinking it's a new decl.  */
+                 if (warn_shadow)
+                   warning_code = OPT_Wshadow;
+                 else if (can_convert (TREE_TYPE (oldlocal), TREE_TYPE (x),
+                                       tf_none))
+                   warning_code = OPT_Wshadow_compatible_local;
+                 else
+                   warning_code = OPT_Wshadow_local;
 
                  if (TREE_CODE (oldlocal) == PARM_DECL)
-                   warned = warning_at (input_location, OPT_Wshadow,
+                   warned = warning_at (input_location, warning_code,
                                "declaration of %q#D shadows a parameter", x);
                  else if (is_capture_proxy (oldlocal))
-                   warned = warning_at (input_location, OPT_Wshadow,
+                   warned = warning_at (input_location, warning_code,
                                "declaration of %qD shadows a lambda capture",
                                x);
                  else
-                   warned = warning_at (input_location, OPT_Wshadow,
+                   warned = warning_at (input_location, warning_code,
                                "declaration of %qD shadows a previous local",
                                x);
 
index 242eed7df34c6ad55ef4408b80f3b2e39505ece9..fd783bf862df9033bb8c4ac9f309fab2ab099e05 100644 (file)
@@ -293,6 +293,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wpointer-arith  -Wno-pointer-to-int-cast @gol
 -Wno-pragmas -Wredundant-decls  -Wno-return-local-addr @gol
 -Wreturn-type  -Wsequence-point  -Wshadow  -Wno-shadow-ivar @gol
+-Wshadow=global, -Wshadow=local, -Wshadow=compatible-local @gol
 -Wshift-overflow -Wshift-overflow=@var{n} @gol
 -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
 -Wsign-compare  -Wsign-conversion -Wfloat-conversion @gol
@@ -5321,6 +5322,7 @@ variable, parameter, type, class member (in C++), or instance variable
 (in Objective-C) or whenever a built-in function is shadowed. Note
 that in C++, the compiler warns if a local variable shadows an
 explicit typedef, but not if it shadows a struct/class/enum.
+Same as @option{-Wshadow=global}.
 
 @item -Wno-shadow-ivar @r{(Objective-C only)}
 @opindex Wno-shadow-ivar
@@ -5328,6 +5330,48 @@ explicit typedef, but not if it shadows a struct/class/enum.
 Do not warn whenever a local variable shadows an instance variable in an
 Objective-C method.
 
+@item -Wshadow=global
+@opindex Wshadow=local
+The default for @option{-Wshadow}. Warns for any (global) shadowing.
+
+@item -Wshadow=local
+@opindex Wshadow=local
+Warn when a local variable shadows another local variable or parameter.
+This warning is enabled by @option{-Wshadow=global}.
+
+@item -Wshadow=compatible-local
+@opindex Wshadow=compatible-local
+Warn when a local variable shadows another local variable or parameter
+whose type is compatible with that of the shadowing variable. In C++,
+type compatibility here means the type of the shadowing variable can be
+converted to that of the shadowed variable. The creation of this flag
+(in addition to @option{-Wshadow=local}) is based on the idea that when
+a local variable shadows another one of incompatible type, it is most
+likely intentional, not a bug or typo, as shown in the following example:
+
+@smallexample
+@group
+for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
+@{
+  for (int i = 0; i < N; ++i)
+  @{
+    ...
+  @}
+  ...
+@}
+@end group
+@end smallexample
+
+Since the two variable @code{i} in the example above have incompatible types,
+enabling only @option{-Wshadow=compatible-local} will not emit a warning.
+Because their types are incompatible, if a programmer accidentally uses one
+in place of the other, type checking will catch that and emit an error or
+warning. So not warning (about shadowing) in this case will not lead to
+undetected bugs. Use of this flag instead of @option{-Wshadow=local} can
+possibly reduce the number of warnings triggered by intentional shadowing.
+
+This warning is enabled by @option{-Wshadow=local}.
+
 @item -Wlarger-than=@var{len}
 @opindex Wlarger-than=@var{len}
 @opindex Wlarger-than-@var{len}
index 051ae8326968b175775c229a162c1fd80b76ef38..5e773fb47a47e9496fa4b74bf58c2d3d0d2b4261 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-30  Le-Chun Wu  <lcwu@google.com>
+           Mark Wielaard  <mjw@redhat.com>
+
+       * gcc.dg/Wshadow-compatible-local-1.c: New test.
+       * gcc.dg/Wshadow-local-1.c: Likewise.
+       * gcc.dg/Wshadow-local-2.c: Likewise.
+       * g++.dg/warn/Wshadow-compatible-local-1.C: Likewise.
+       * g++.dg/warn/Wshadow-local-1.C: Likewise.
+       * g++.dg/warn/Wshadow-local-2.C: Likewise.
+
+
 2016-10-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        PR tree-optimization/71915
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C b/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C
new file mode 100644 (file)
index 0000000..aac6861
--- /dev/null
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=compatible-local } */
+
+class Bar {
+};
+
+class ChildBar : public Bar {
+};
+
+Bar bar;
+
+class Foo {
+ private:
+  int val;
+
+ public:
+  int func1(int x) {
+    int val;
+    val = x;
+    return val;
+  }
+
+  int func2(int i) { // { dg-message "note: shadowed declaration is here" }
+    int a = 3;       // { dg-message "note: shadowed declaration is here" }
+
+    for (int i = 0; i < 5; ++i) {   // { dg-warning "shadows a parameter" }
+      for (int i = 0; i < 3; ++i) { // { dg-warning "shadows a previous local" }
+        int a = i;   // { dg-warning "shadows a previous local" }
+        func1(a);
+      }
+    }
+
+    return a;
+  }
+
+  int func3() {
+    int bar;
+    float func1 = 0.3;
+    int f = 5;       // { dg-message "note: shadowed declaration is here" }
+
+    if (func1 > 1) {
+      float f = 2.0; // { dg-warning "shadows a previous local" }
+      bar = f;
+    }
+    else
+      bar = 1;
+    return bar;
+  }
+
+  void func4() {
+    Bar *bar;        // { dg-bogus "shadowed declaration" }
+    ChildBar *cbp;   // { dg-bogus "shadowed declaration" }
+    Bar *bp;         // { dg-message "note: shadowed declaration is here" }
+    if (val) {
+      int bar;       // { dg-bogus "shadows a previous local" }
+      Bar *cbp;      // { dg-bogus "shadows a previous local" }
+      ChildBar *bp;  // { dg-warning "shadows a previous local" }
+      func1(bar);
+    }
+  }
+};
+
+// { dg-message "note: shadowed declaration" "" { target *-*-* } 26 }
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C
new file mode 100644 (file)
index 0000000..dba6db5
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=local } */
+
+struct status
+{
+  int member;
+  void foo2 ();
+
+  inline static int foo3 (int member)
+  {
+    return member;
+  }
+};
+
+int decl1;                      // { dg-bogus "shadowed declaration" }
+int decl2;                      // { dg-bogus "shadowed declaration" }
+void foo (struct status &status,
+         double decl1)         // { dg-bogus "shadows a global" }
+{
+}
+
+void foo1 (int d)
+{
+  double d;                    // { dg-error "shadows a parameter" }
+}
+
+void status::foo2 ()
+{
+  int member;                  // { dg-bogus "shadows a member" }
+  int decl2;                   // { dg-bogus "shadows a global" }
+  int local;                   // { dg-message "note: shadowed declaration is here" }
+  {
+    int local;                 // { dg-warning "shadows a previous local" }
+  }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C
new file mode 100644 (file)
index 0000000..fe42c89
--- /dev/null
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=local } */
+
+class Bar {
+};
+
+class ChildBar : public Bar {
+};
+
+Bar bar;             // { dg-bogus "shadowed declaration" }
+
+class Foo {
+ private:
+  int val;
+
+ public:
+  int func1(int x) {
+    int val;         // { dg-bogus "shadows a member" }
+    val = x;
+    return val;
+  }
+
+  int func2(int i) { // { dg-message "shadowed declaration is here" }
+    int a = 3;       // { dg-message "shadowed declaration is here" }
+
+    for (int i = 0; i < 5; ++i) {   // { dg-warning "shadows a parameter" }
+      for (int i = 0; i < 3; ++i) { // { dg-warning "shadows a previous local" }
+        int a = i;   // { dg-warning "shadows a previous local" }
+        func1(a);
+      }
+    }
+
+    return a;
+  }
+
+  int func3() {
+    int bar;         // { dg-bogus "shadows a global" }
+    float func1 = 0.3; // { dg-bogus "shadows a member" }
+    int f = 5;       // { dg-message "shadowed declaration is here" }
+
+    if (func1 > 1) {
+      float f = 2.0; // { dg-warning "shadows a previous local" }
+      bar = f;
+    }
+    else
+      bar = 1;
+    return bar;
+  }
+
+  void func4() {
+    Bar *bar;        // { dg-message "shadowed declaration is here" }
+    ChildBar *cbp;   // { dg-message "shadowed declaration is here" }
+    Bar *bp;         // { dg-message "shadowed declaration is here" }
+    if (val) {
+      int bar;       // { dg-warning "shadows a previous local" }
+      Bar *cbp;      // { dg-warning "shadows a previous local" }
+      ChildBar *bp;  // { dg-warning "shadows a previous local" }
+      func1(bar);
+    }
+  }
+};
+
+// { dg-message "shadowed declaration is here" "" { target *-*-* } 26 }
diff --git a/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c b/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c
new file mode 100644 (file)
index 0000000..ed7b2e4
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=compatible-local" } */
+
+struct Bar {
+};
+
+struct Bar bar;       /* { dg-bogus "shadowed declaration" } */
+
+int val;              /* { dg-bogus "shadowed declaration" } */
+
+int func1(int x) {    /* { dg-bogus "shadowed declaration" } */
+  int val;            /* { dg-bogus "shadows a global" } */
+  val = x;
+  return val;
+}
+
+int func2(int i) {
+  int a = 3;          /* { dg-message "shadowed declaration" } */
+  int j;              /* { dg-message "shadowed declaration" } */
+
+  for (j = 0; j < i; ++j) {
+    int a = j;        /* { dg-warning "shadows a previous local" } */
+    int j = a + 1;    /* { dg-warning "shadows a previous local" } */
+    func1(j);
+  }
+
+  return a;
+}
+
+void func4() {
+  struct Bar bar;     /* { dg-bogus "shadowed declaration" } */
+  if (val) {
+    int bar;          /* { dg-bogus "shadows a previous local" } */
+    func1(bar);
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-1.c b/gcc/testsuite/gcc.dg/Wshadow-local-1.c
new file mode 100644 (file)
index 0000000..161f994
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=local" } */
+
+int decl1;                     /* should not warn */
+void foo (double decl1)                /* should not warn */
+{                              
+}
+
+void foo2 (int d)              /* { dg-message "shadowed declaration" } */
+{
+  {
+    double d;                  /* { dg-warning "shadows a parameter" } */
+  }
+}
+
+void foo3 ()
+{
+  int local;                   /* { dg-message "shadowed declaration" } */
+  {
+    int local;                 /* { dg-warning "shadows a previous local" } */
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-2.c b/gcc/testsuite/gcc.dg/Wshadow-local-2.c
new file mode 100644 (file)
index 0000000..8f6b132
--- /dev/null
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=local" } */
+
+struct Bar {
+};
+
+struct Bar bar;       /* { dg-bogus "shadowed declaration" } */
+
+int val;              /* { dg-bogus "shadowed declaration" } */
+
+int func1(int x) {    /* { dg-bogus "shadowed declaration" } */
+  int val;            /* { dg-bogus "shadows a global" } */
+  val = x;
+  return val;
+}
+
+int func2(int i) {
+  int a = 3;          /* { dg-message "shadowed declaration" } */
+  int j;              /* { dg-message "shadowed declaration" } */
+
+  for (j = 0; j < i; ++j) {
+    int a = j;        /* { dg-warning "shadows a previous local" } */
+    int j = a + 1;    /* { dg-warning "shadows a previous local" } */
+    func1(j);
+  }
+
+  return a;
+}
+
+int func3() {
+  int bar;            /* { dg-bogus "shadows a global" } */
+  float func1 = 0.3;  /* { dg-bogus "shadows a global" } */
+
+  if (func1 > 1)
+    bar = 2;
+  else
+    bar = 1;
+  return bar;
+}
+
+void func4() {
+  struct Bar bar;     /* { dg-message "shadowed declaration" } */
+  if (val) {
+    int bar;          /* { dg-warning "shadows a previous local" } */
+    func1(bar);
+  }
+}
+
+/* { dg-bogus "shadows a global" ""  { target *-*-* } 42 } */
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-3.c b/gcc/testsuite/gcc.dg/Wshadow-local-3.c
new file mode 100644 (file)
index 0000000..429df37
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Wno-shadow" } */
+
+void func() {
+  int i;
+    {
+      int i; /* should not warn */
+    }
+}