Bug 10852

Summary: Old for-scoping rules improperly used?
Product: gcc Reporter: derrick
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: bangerth, celtschk, gcc-bugs, gdr, lerdsuwa, msebor, reichelt, webrown.cpp
Priority: P3 Keywords: accepts-invalid, monitored, rejects-valid
Version: 3.3   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2006-09-03 21:39:36
Bug Depends on:    
Bug Blocks: 12944, 33260    

Description derrick 2003-05-19 07:46:00 UTC
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
Comment 1 derrick 2003-05-19 07:46:00 UTC
Fix:
Workaround is to replace "using namespace X" with "using X::i"
Comment 2 Gabriel Dos Reis 2003-05-19 10:15:54 UTC
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
Comment 3 Wolfgang Bangerth 2003-05-19 14:12:47 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Gaby analyzed this. Interesting bug :-)
Comment 4 Andrew Pinski 2004-03-10 16:48:07 UTC
*** Bug 14515 has been marked as a duplicate of this bug. ***
Comment 5 Volker Reichelt 2006-03-07 15:54:15 UTC
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.
Comment 6 Wolfgang Bangerth 2011-10-09 13:59:42 UTC
Still happens for gcc4.5.1.
Comment 7 Martin Sebor 2017-02-28 01:37:15 UTC
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;
         ^