diff mbox

Add -Wshadow-local and -Wshadow-compatible-local.

Message ID 20160911211108.GI2420@stream
State New
Headers show

Commit Message

Mark Wielaard Sept. 11, 2016, 9:11 p.m. UTC
Hi Manuel,

On Sun, Sep 11, 2016 at 08:26:20PM +0100, Manuel López-Ibáñez wrote:
> On 11/09/16 14:02, Mark Wielaard wrote:
> >   -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.
> 
> I honestly don't see the need for the second flag. Why not make Wshadow, or
> at least Wshadow-local, work in this way by default?

Because they are different (subsets) of warnings, projects might prefer
warnings for a wider or smaller set. Also -Wshadow is known to have the
current behaviour, so changing it now will be confusing. Also google
already released a gcc variant with these warnings using these semantics.

> variables that will nevertheless trigger errors/warnings if used wrongly
> seems not very useful anyway.

I am sorry, I cannot follow your reasoning here.
Could you try to explain in different words or with a specific example?

> > +	    /* 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 (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
> > +	      warning_code = OPT_Wshadow_compatible_local;
> > +	    else
> > +	      warning_code = OPT_Wshadow_local;
> > +	    warned = warning (warning_code,
> > +			      "declaration of %q+D shadows a parameter",
> > +			      new_decl);
> 
> Please don't use +D. Use warning_at with DECL_SOURCE_LOCATION(new_decl).
> See: https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Locations

Thanks. I think I fixed it in the attached. But note that this was
existing code and that the wiki page you reference doesn't mention
warning_at even once. If you want this kind of pattern changed in
the code base it would be helpful to add an example of how to change
existing code to use the new/correct way to the wiki so people can do
this as an easy hack.

> > +		  /* 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.  */
> 
> As said above, IMHO, this behavior should be the default of -Wshadow, or at
> least, of -Wshadow-local. The current behavior only leads to people not
> using -Wshadow (and us not including it in -Wall -Wextra). There is a Linus
> rant from some years ago that explains vehemently why Wshadow is useless in
> its current form.

As I explained above I don't think changing the semantics of the warnings
is a good idea. There are projects currently using -Wshadow and expecting
it to warn as it does. I am not familiar with this "rant". If you believe
it is useful input to the discussion could you provide a pointer or ask
Linus to participate in this discussion to explain what his preferences
are?

> > +@item -Wshadow-compatible-local
> > +@opindex Wshadow-compatible-local
> > +@opindex Wno-shadow-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:
> 
> -Wshadow-compatible-local seems safe enough to be enabled by -Wall (or
> -Wextra). Options not enabled by either are rarely used (and, hence, rarely
> tested).

There are multiple testcases provided. I am not against enabling any of
these options in -Wall or -Wextra, but it would be good to see some
experiments using them first on some larger codebases (maybe gcc itself).
If you could try it on some and report what the rate of false positive
is (plus maybe some examples to show whether one might or might not want
to fix them anyway) then we can see if it makes sense. But I believe that
should be done independent from introducing the new warnings themselves.

Thanks,

Mark

Attached v2 of the patch with the suggested change above using warning_at.
No changes in the test results for any of the old or new -Wshadow tests.
From 909c48dc7abe77aefad30a8aac9177e18b5a188b Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Sun, 11 Sep 2016 14:20:33 +0200
Subject: [PATCH] Add -Wshadow-local and -Wshadow-compatible-local.

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:
- The -Wshadow, -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.

v2 - Use warning_at in c-decl.c (warn_if_shadowing).

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

       * common.opt (Wshadow-local): New option.
       (Wshadow-compatible-local): New option.
       * doc/invoke.texi: Document Wshadow-local and Wshadow-compatible-local.

gcc/c/ChangeLog:
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.

gcc/cp/ChangeLog:
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.
---
 gcc/ChangeLog                                      |  7 +++
 gcc/c/ChangeLog                                    |  6 +++
 gcc/c/c-decl.c                                     | 39 +++++++++++---
 gcc/common.opt                                     | 10 +++-
 gcc/cp/ChangeLog                                   |  7 +++
 gcc/cp/name-lookup.c                               | 28 ++++++++--
 gcc/doc/invoke.texi                                | 41 ++++++++++++++
 .../g++.dg/warn/Wshadow-compatible-local-1.C       | 63 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/warn/Wshadow-local-1.C        | 35 ++++++++++++
 gcc/testsuite/g++.dg/warn/Wshadow-local-2.C        | 63 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c  | 36 +++++++++++++
 gcc/testsuite/gcc.dg/Wshadow-local-1.c             | 22 ++++++++
 gcc/testsuite/gcc.dg/Wshadow-local-2.c             | 49 +++++++++++++++++
 gcc/testsuite/gcc.dg/Wshadow-local-3.c             |  9 ++++
 14 files changed, 404 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C
 create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-1.C
 create mode 100644 gcc/testsuite/g++.dg/warn/Wshadow-local-2.C
 create mode 100644 gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wshadow-local-1.c
 create mode 100644 gcc/testsuite/gcc.dg/Wshadow-local-2.c
 create mode 100644 gcc/testsuite/gcc.dg/Wshadow-local-3.c
diff mbox

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2219333..c4486dc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@ 
+2016-09-11  Le-Chun Wu  <lcwu@google.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* common.opt (Wshadow-local): New option.
+	(Wshadow-compatible-local): New option.
+	* doc/invoke.texi: Document Wshadow-local and Wshadow-compatible-local.
+
 2016-09-09  Peter Bergner  <bergner@vnet.ibm.com>
 
 	PR rtl-optimization/77289
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index a647263..23ee5f1 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -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-09-07  David Malcolm  <dmalcolm@redhat.com>
 
 	* c-lang.c (LANG_HOOKS_GET_SUBSTRING_LOCATION): Use
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 8f49c35..6a79781 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -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,21 @@  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 (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 +2798,21 @@  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 (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),
diff --git a/gcc/common.opt b/gcc/common.opt
index fa1c036..17d54e7 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -661,7 +661,15 @@  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.
+
+Wshadow-local
+Common Var(warn_shadow_local) Warning EnabledBy(Wshadow)
+Warn when one local variable shadows another local variable or parameter.
+
+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.
 
 Wstack-protector
 Common Var(warn_stack_protect) Warning
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9480993..f979257 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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-09-09  Jason Merrill  <jason@redhat.com>
 
 	Implement P0035R4, C++17 new of over-aligned types.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 022ab6a..291a7ea 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1195,19 +1195,39 @@  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 (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);
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b2eaea7..e23ca52 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -290,6 +290,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-compatible-local -Wshadow-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
@@ -5001,6 +5002,46 @@  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-local
+@opindex Wshadow-local
+@opindex Wno-shadow-local
+Warn when a local variable shadows another local variable or parameter.
+This warning is enabled by @option{-Wshadow}.
+
+@item -Wshadow-compatible-local
+@opindex Wshadow-compatible-local
+@opindex Wno-shadow-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}
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
index 0000000..b0422fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C
@@ -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
index 0000000..9737e23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C
@@ -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
index 0000000..c0d6741
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C
@@ -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
index 0000000..80f43de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c
@@ -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
index 0000000..df70c11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-1.c
@@ -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
index 0000000..90d4e0f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-2.c
@@ -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
index 0000000..429df37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-3.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Wno-shadow" } */
+
+void func() {
+  int i;
+    {
+      int i; /* should not warn */
+    }
+}