I think this is a bug in g++; but there is always the possibility that it is a bug in my understanding of C++. In the following code gcc assumes that the variable i at the end of function is the same as in the for loop and produces the following error: nstest.cc: In function `void f()': nstest.cc:9: error: name lookup of `i' changed for new ISO `for' scoping nstest.cc:6: error: using obsolete binding at `i' I think it should use the variable i from inside the namespace and quit complaining, but as I said, I may just be misunderstanding C++ arcana. Here's the sample code... namespace X { int i; } void f() { for (int i=0; i<10; ++i) ; using namespace X; i; } Release: gcc-3.3
Fix: Workaround is to replace "using namespace X" with "using X::i"
From: Gabriel Dos Reis <gdr@integrable-solutions.net> To: derrick@cco.caltech.edu Cc: gcc-gnats@gcc.gnu.org Subject: Re: c++/10852: Old for-scoping rules improperly used? Date: 19 May 2003 10:15:54 +0200 derrick@cco.caltech.edu writes: | I think this is a bug in g++; but there is always the possibility that it is a bug in my understanding of C++. In the following code gcc assumes that the variable i at the end of function is the same as in the for loop and produces the following error: | nstest.cc: In function `void f()': | nstest.cc:9: error: name lookup of `i' changed for new ISO `for' scoping | nstest.cc:6: error: using obsolete binding at `i' That is a bug in the compiler. The compiler should first look into X before complaining. -- Gaby
State-Changed-From-To: open->analyzed State-Changed-Why: Gaby analyzed this. Interesting bug :-)
*** Bug 14515 has been marked as a duplicate of this bug. ***
Here's an example where the code is invalid, but is accepted because of the for-scope-warning machinery: ================================== namespace N { int i; } int i; void foo() { for (int i=0; i<10; ++i) ; using namespace N; i; } ================================== The problem is that we track old and new scoping rules simultaneously to be able to issue warnings. This doesn't work properly in corner cases like in this PR.
Still happens for gcc4.5.1.
I think this works correctly now. In C++ 98 mode GCC complains with -fpermissive. In C++ 11 and later it accepts the code as expected. Resolving as fixed. $ (set -x; cat t.C && for y in 98 11 17; do gcc -S -Wall -Wextra -Wpedantic -std=c++$y t.C; done) + cat t.C namespace X { int i; } void f() { for (int i=0; i<10; ++i) ; using namespace X; i; } + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++98 t.C t.C: In function ‘void f()’: t.C:9:3: error: name lookup of ‘i’ changed for ISO ‘for’ scoping [-fpermissive] i; ^ t.C:9:3: note: (if you use ‘-fpermissive’ G++ will accept your code) t.C:9:4: warning: statement has no effect [-Wunused-value] i; ^ + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++11 t.C t.C: In function ‘void f()’: t.C:9:4: warning: statement has no effect [-Wunused-value] i; ^ + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++17 t.C t.C: In function ‘void f()’: t.C:9:4: warning: statement has no effect [-Wunused-value] i; ^ Conversely, the test case from comment #5 is rejected in C++ 11 and later and accepted in C++ 98 mode: $ (set -x; cat t.C && for y in 98 11 17; do gcc -S -Wall -Wextra -Wpedantic -std=c++$y t.C; done) + cat t.C namespace N { int i; } int i; void foo() { for (int i=0; i<10; ++i) ; using namespace N; i; } + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++98 t.C t.C: In function ‘void foo()’: t.C:12:5: warning: name lookup of ‘i’ changed i; ^ t.C:6:5: warning: matches this ‘i’ under ISO standard rules int i; ^ t.C:10:14: warning: matches this ‘i’ under old rules for (int i=0; i<10; ++i) ; ^ t.C:12:6: warning: statement has no effect [-Wunused-value] i; ^ + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++11 t.C t.C: In function ‘void foo()’: t.C:12:5: error: reference to ‘i’ is ambiguous i; ^ t.C:6:5: note: candidates are: int i int i; ^ t.C:3:9: note: int N::i int i; ^ + for y in 98 11 17 + gcc -S -Wall -Wextra -Wpedantic -std=c++17 t.C t.C: In function ‘void foo()’: t.C:12:5: error: reference to ‘i’ is ambiguous i; ^ t.C:6:5: note: candidates are: int i int i; ^ t.C:3:9: note: int N::i int i; ^