Created attachment 29268 [details] Test case Compiling the test case with "-Wshadow" gives: shadow.cpp: In instantiation of 'void bar<T>::baz() [with T = int]': shadow.cpp:4:17: required from 'void bar<T>::qux() [with T = int]' shadow.cpp:13:21: required from here shadow.cpp:6:21: warning: declaration of 'foo' shadows a global declaration [-Wshadow] shadow.cpp:9:5: warning: shadowed declaration is here [-Wshadow] Observed with 4.4.6, 4.6.1 and 4.7.2. Note: "private" is not necessary to trigger the warning, it's just there to show it occurs even with "private". The warning seems strange because the supposedly shadowed variable is declared after the shadowing one. (I assume that's because of the processing done during instantiation.) It's annoying because it means that an identifier used in a template defined in some header, even in a local scope in a private method is "poisoned" when used anywhere else with -Wshadow.
I think this is an artifact of warning during instantiation rather than at definition time.
I guess many warnings can only be given correctly during instantiation because they depend on the actual arguments. But shadowing is not one of them as the set of identifiers declared doesn't depend on the arguments. (Even in the case of partial specializations, one would expect the warning where the specialization is defined, not when it's instantiated.) So perhaps a simple fix is to turn off -Wshadow temporarily during instantiation. After all, the instantiated code has no access to currently declared global identifiers. This code fails as it should (AFAIK), unless foo is declared before the template: template <typename T> struct bar { int qux () { return foo; } }; int foo; int main () { bar <int> ().qux (); }
I wonder if in such cases would it simply make sense to suppress the warning basing on the locations, eg the below certainly works for the testcase and passes testing: Index: name-lookup.c =================================================================== --- name-lookup.c (revision 221789) +++ name-lookup.c (working copy) @@ -1271,7 +1271,9 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) } } else if (oldglobal != NULL_TREE - && (VAR_P (oldglobal) + && ((VAR_P (oldglobal) + && (input_location + > DECL_SOURCE_LOCATION (oldglobal))) /* If the old decl is a type decl, only warn if the old decl is an explicit typedef or if both the old and new decls are type decls. */
(In reply to Paolo Carlini from comment #3) > I wonder if in such cases would it simply make sense to suppress the warning > basing on the locations I think we want to suppress the warning on instantiation even if the order is reversed: given int foo; template <typename T> struct bar { void qux () { baz (); } private: void baz () { int foo; } }; int main () { bar <int> ().qux (); } We first warn about the declaration in the template, and then again about the instantiation.
Doh, thanks Jason I thought I had already checked the behavior in that case.
Author: paolo Date: Wed Apr 1 21:27:55 2015 New Revision: 221814 URL: https://gcc.gnu.org/viewcvs?rev=221814&root=gcc&view=rev Log: /cp 2015-04-01 Paolo Carlini <paolo.carlini@oracle.com> PR c++/56100 * pt.c (instantiating_current_function_p): New. * name-lookup.c (pushdecl_maybe_friend_1): Use it. * cp-tree.h (instantiating_current_function_p): Declare. /testsuite 2015-04-01 Paolo Carlini <paolo.carlini@oracle.com> PR c++/56100 * g++.dg/warn/Wshadow-8.C: New. * g++.dg/warn/Wshadow-9.C: Likewise. * g++.dg/warn/Wshadow-10.C: Likewise. * g++.dg/warn/Wshadow-11.C: Likewise. Added: trunk/gcc/testsuite/g++.dg/warn/Wshadow-10.C trunk/gcc/testsuite/g++.dg/warn/Wshadow-11.C trunk/gcc/testsuite/g++.dg/warn/Wshadow-8.C trunk/gcc/testsuite/g++.dg/warn/Wshadow-9.C Modified: trunk/gcc/cp/cp-tree.h trunk/gcc/cp/name-lookup.c trunk/gcc/cp/pt.c trunk/gcc/testsuite/ChangeLog
Fixed for 5.0.