This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/12205] New: Nondependent name lookup in dependent base classes seems to be broken


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12205

           Summary: Nondependent name lookup in dependent base classes seems
                    to be broken
           Product: gcc
           Version: 3.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: tunali at mojavedesign dot com
                CC: gcc-bugs at gcc dot gnu dot org

The following code :

[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  int bar_val; 
};


template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    cout << "Size of bar_val : " << sizeof(bar_val) << endl;
  }
};

char bar_val; // notice that definition of global bar_val is after Derived

int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ -v this.C
Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/specs
Configured with: ../gcc-3.2/configure 
Thread model: posix
gcc version 3.2
 /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/cc1plus -v -D__GNUC__=3
-D__GNUC_MINOR__=2 -D__GNUC_PATCHLEVEL__=0 -D__GXX_ABI_VERSION=102 -D__ELF__
-Dunix -D__gnu_linux__ -Dlinux -D__ELF__ -D__unix__ -D__gnu_linux__ -D__linux__
-D__unix -D__linux -Asystem=posix -D__NO_INLINE__ -D__STDC_HOSTED__=1
-D_GNU_SOURCE -Acpu=i386 -Amachine=i386 -Di386 -D__i386 -D__i386__
-D__tune_i686__ -D__tune_pentiumpro__ this.C -D__GNUG__=3 -D__DEPRECATED
-D__EXCEPTIONS -quiet -dumpbase this.C -version -o /tmp/ccUF4VWf.s
GNU CPP version 3.2 (cpplib) (i386 Linux/ELF)
GNU C++ version 3.2 (i686-pc-linux-gnu)
	compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.3 2.96-112).
ignoring nonexistent directory "NONE/include"
ignoring nonexistent directory "/usr/local/lib/../i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/lib/../include/c++/3.2
 /usr/local/lib/../include/c++/3.2/i686-pc-linux-gnu
 /usr/local/lib/../include/c++/3.2/backward
 /usr/local/include
 /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/include
 /usr/include
End of search list.
 as -V -Qy -o /tmp/ccwR02tb.o /tmp/ccUF4VWf.s
GNU assembler version 2.11.93.0.2 (i386-redhat-linux) using BFD version
2.11.93.0.2 20020207
 /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/collect2 -m elf_i386
-dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o
/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/crtbegin.o
-L/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2
-L/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/../../.. /tmp/ccwR02tb.o -lstdc++
-lm -lgcc_s -lgcc -lc -lgcc_s -lgcc
/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2/crtend.o /usr/lib/crtn.o
[tunali@oasis dependent_names]$ a.out
Size of bar_val : 4
[tunali@oasis dependent_names]$ 

the size of an integer is printed to the output.

If the definition of the global bar_val is placed before the definition of
Derived class template :

[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  int bar_val; 
};

char bar_val; // notice that definition of global bar_val is before Derived

template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    cout << "Size of bar_val : " << sizeof(bar_val) << endl;
  }
};


int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ this.C
[tunali@oasis dependent_names]$ a.out
Size of bar_val : 1
[tunali@oasis dependent_names]$ 

the size of a char is printed to the output.

The results are inconsistent. And as far as I know C++ standard says that
nondependent names are not looked up in dependent base classes, so the second
output seems to be the correct one.

In case of a typedef the situation is somewhat different :

[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  typedef int bar_type;
};

typedef char bar_type; // notice that definition of global bar_val is before Derived


template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    cout << "Size of bar_type : " << sizeof(bar_type) << endl;
  }
};


int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ this.C
this.C: In member function `void Derived<T>::foo()':
this.C:17: warning: lookup of `bar_type' finds `typedef char bar_type'
this.C:17: warning:   instead of `typename Derived<T>::bar_type' from dependent 
   base class
this.C:17: warning:   (use `typename Derived::bar_type' if that's what you 
   meant)
[tunali@oasis dependent_names]$ a.out
Size of bar_type : 1
[tunali@oasis dependent_names]$ 

The warning is explanatory. However if the place of definition of bar_type is
changed :

[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  typedef int bar_type;
};


template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    cout << "Size of bar_type : " << sizeof(bar_type) << endl;
  }
};

typedef char bar_type; // notice that definition of global bar_type is before
Derived


int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ this.C
this.C: In member function `void Derived<T>::foo()':
this.C:15: warning: `typename Derived<T>::bar_type' is implicitly a typename
this.C:15: warning: implicit typename is deprecated, please see the 
   documentation for details
[tunali@oasis dependent_names]$ a.out
Size of bar_type : 4
[tunali@oasis dependent_names]$ 

The warning is different and the result is inconsistent with the previous one.

Finally, in the case of a member function :

[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  void bar() {
    cout << __PRETTY_FUNCTION__ << endl;
  }
};

void bar() { cout << __PRETTY_FUNCTION__ << endl; }

template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    bar();
  }
};


int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ this.C
[tunali@oasis dependent_names]$ a.out
void Base<T>::bar() [with T = int]
[tunali@oasis dependent_names]$ cat this.C
#include <iostream>
using namespace std;

template<typename T>
class Base {
public:
  void bar() {
    cout << __PRETTY_FUNCTION__ << endl;
  }
};


template<typename T>
class Derived : Base<T> {
public:
  void foo() { 
    bar();
  }
};

void bar() { cout << __PRETTY_FUNCTION__ << endl; }

int main() {
  Derived<int> x;
  x.foo();
}
[tunali@oasis dependent_names]$ /usr/local/bin/g++ this.C
[tunali@oasis dependent_names]$ a.out
void Base<T>::bar() [with T = int]
[tunali@oasis dependent_names]$ 

The result does not depend on the place of the definition of the free form of
bar, but it seems to contradict with the standard (nondependent names are not
looked up int dependent base classes.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]