10968 – [3.3/3.4 regression] If member function implicitly instantiated, explicit instantiation of class fails to instantiate it (original) (raw)
Description jsberg04+bugs.gcc 2003-05-24 14:04:18 UTC
$ gcc -v Reading specs from /opt/gcc-3.3/lib/gcc-lib/i686-pc-linux-gnu/3.3/specs Configured with: ../gcc-3.3/configure --prefix=/opt/gcc-3.3 --enable-threads --with-system-zlib --enable-__cxa_atexit Thread model: posix gcc version 3.3
binutils 2.13.90.0.18 glibc 2.3.2
If a member function of a class is implicitly instantiated in a source file by the member function of another class, and the class is subsequently explicitly instantiated in the same source file, the member function that was implicitly instantiated does not appear in the object file. The problem doesn't occur if the implicit instantiation was caused by a global function.
This behavior did not occur in 3.2.3.
Here are two files, test00.cc, test01.cc. Compile as
$ c++ test00.cc test01.cc -o test01
/tmp/ccfV7tob.o(.text+0x17): In function main': : undefined reference to A::f() const'
collect2: ld returned 1 exit status
The object file for test00.cc contains the instantiation for char*, but not int:
$ c++ -c test00.cc $ nm -C -g test00.o 00000000 W A<char*>::f() const
1 "test00.cc"
1 ""
1 ""
1 "test00.cc"
1 "test00.hh" 1
template class A { public: void f() const; private: };
2 "test00.cc" 2
template void A::f() const { }
class C { public: void f(const A &a) const { a.f(); } };
template class A; template class A<char *>;
1 "test01.cc"
1 ""
1 ""
1 "test01.cc"
1 "test00.hh" 1
template class A { public: void f() const; private: };
2 "test01.cc" 2
int main(int argc, char *argv[]) { A a; a.f(); }
Comment 1 Dara Hazeghi 2003-05-25 00:13:49 UTC
Hello,
I can confirm that this problem is not present on gcc 3.2, but is on gcc 3.3 branch and mainline (20030520). If this behavior is not correct, this is a regression from 3.2.
Dara
Comment 2 Giovanni Bajo 2003-05-29 14:41:50 UTC
A serious regression, if you ask me. I propose the following code snippet as testcase to show the problem:
template struct A { void f(void) {} };
struct Foo { void bar(void) { A a; a.f(); } };
template class A; template class A; template class A; template class A;
$ g++-3.3 -c pr10968.cpp && nm -C -g pr10968.o 00000000 T A::f() 00000000 T A::f() 00000000 T A::f()
$ g++-3.4 -c pr10968.cpp && nm -C -g pr10968.o 00000000 T A::f() 00000000 T A::f() 00000000 T A::f()
$ g++-3.2 -c pr10968.cpp && nm -C -g pr10968.o 00000000 T A::f() 00000000 T A::f() 00000000 T A::f() 00000000 T A::f()
The instantiation of A is missing only because it's referenced within Foo::bar().
Comment 8 Jason Merrill 2003-06-10 19:25:49 UTC
Feexd.
Comment 9 Wolfgang Bangerth 2003-06-11 15:25:12 UTC
*** Bug 11150 has been marked as a duplicate of this bug. ***
Comment 10 Drea Pinski 2003-07-23 22:41:49 UTC
*** Bug 11652 has been marked as a duplicate of this bug. ***