llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.67k stars 11.85k forks source link

clang c++ virtual methods for templated class not instantiated with instantiation of constructor #5929

Closed efriedma-quic closed 14 years ago

efriedma-quic commented 14 years ago
Bugzilla Link 5557
Resolution FIXED
Resolved on Feb 22, 2010 12:53
Version unspecified
OS Linux
Blocks llvm/llvm-project#5883
CC @DougGregor

Extended Description

Testcase: template struct A { A(); virtual int a(T x); }; template A::A() {} template int A::a(T x) { return *x; } A x; int main() { return 0; }

Output (clang x.cpp -fno-rtti): /tmp/cc-nJeNb1.o:(.gnu.linkonce.r._ZTV1AIiE+0x8): undefined reference to `A::a()' collect2: ld returned 1 exit status clang: error: linker command failed with exit code 1 (use -v to see invocation)

Compare to output from g++: /tmp/x.cpp: In member function ‘int A::a(T) [with T = int]’: /tmp/x.cpp:10: instantiated from here /tmp/x.cpp:8: error: invalid type argument of ‘unary *’

llvmbot commented 14 years ago

Never mind, it's fixed in SVN. Thanks, Anders!

llvmbot commented 14 years ago

I don't know... I still get link errors related to the std::basic_istream class. I don't know if this is a separate issue or what, but std::basic_istream still isn't getting instantiated properly.

llvmbot commented 14 years ago

Committed revision 90753.

DougGregor commented 14 years ago

I think we'll need to figure out what GCC does and mimic that.

I believe what gcc does is that at the end of file, for any templated class, it checks whether the vtable is needed; if it is, it defines the vtable and instantiates the functions referred to by the vtable. As proof, note that for the following testcase, the instantiation error comes after the error about b(), even though there isn't anything interesting in the file after it: template struct A { virtual int a(T x); }; template int A::a(T x) { return x; } A a() { return new A; } void b() { return 1; } //template<> int A::a(int x) { return 2; }

It's extremely nasty, but if libstdc++ depends on it, I don't really see an alternative.

FWIW, GCC (and Clang, and EDG) instantiate functions at the end of the translation unit regardless of where the actual point of instantiation was. It's possible that the synthesis of the definition of the default constructor is also being delayed until the end of the file and that, in turn, forces the instantiation of the non-pure virtuals in the class (because a vtable is needed).

efriedma-quic commented 14 years ago

I think we'll need to figure out what GCC does and mimic that.

I believe what gcc does is that at the end of file, for any templated class, it checks whether the vtable is needed; if it is, it defines the vtable and instantiates the functions referred to by the vtable. As proof, note that for the following testcase, the instantiation error comes after the error about b(), even though there isn't anything interesting in the file after it: template struct A { virtual int a(T x); }; template int A::a(T x) { return x; } A a() { return new A; } void b() { return 1; } //template<> int A::a(int x) { return 2; }

It's extremely nasty, but if libstdc++ depends on it, I don't really see an alternative.

DougGregor commented 14 years ago

I tried implementing that approach, where we instantiate virtual member functions along with the class itself, but I was running into specialization-after-instantiation errors in libstdc++. See the attached patch and test case.

I think we'll need to figure out what GCC does and mimic that.

DougGregor commented 14 years ago

Test case that illustrates the specialization-after-instantiation problem

DougGregor commented 14 years ago

Failed attempt at instantiating virtual member functions with the class

llvmbot commented 14 years ago

The standard gives us a lot of leeway there. If we want, we can instantiate virtual members the moment the containing class is instantiated.

DougGregor commented 14 years ago

We need to instantiate the virtual functions of an implicitly-instantiated class template specialization (or member class thereof) when we're going to emit a vtable. Right now, that decision is made by CodeGen, but we'll need to boost it up into Sema so that we can make sure that all of the virtual functions will get instantiated when CodeGen is going to need them.