[cfe-users] Linking problem with implicit instantiation of constructor/destructor
Hello, I've run into wieird problem when trying to compile and link our programs with clang++ on linux instead of g++. It occurs, when: - template class member definitions are separated from the definition of the class - no explicit instantiation is done - member definitions are available only in some of the units, where the template is being used. (Yeah, our code is a mess) This is simple expamle: // - template.h template< typename T > struct Template { Template(); ~Template(); }; void doSomething(Template& t); // - template.cpp #include "template.h" template< typename T > Template< T >::Template() { } template< typename T> Template< T >::~Template() { } void doSomething(Template& t) { Template new_t; t = new_t; } // - main.cpp #include "template.h" int main(int argc_, char** argv_) { Template t; doSomething(t); return 0; } // - end of code When compiled with clang++: $ clang++ -o test main.cpp template.cpp /usr/bin/ld: /tmp/main-e2fa2c.o: in function `main': main.cpp:(.text+0x2f): undefined reference to `Template::Template()' /usr/bin/ld: main.cpp:(.text+0x4d): undefined reference to `Template::~Template()' /usr/bin/ld: main.cpp:(.text+0x82): undefined reference to `Template::~Template()' reading the object files using nm tool shows, the symbol for destructor instantiated in template.cpp is _ZN8TemplateIiED2Ev, but the main.o requires symbol _ZN8TemplateIiED1Ev. Notice the difference in one digit: D2 vs D1. So symbol ...D1... is required, but only ...D2... is available. The D1 version is generated by clang only for explicit instantiation. g++ generates both D1 and D2 for any type of instantiation. Can this be considered a bug of clang++? Or does this behaior have some purpose? Regards, JZ ___ cfe-users mailing list cfe-users@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
Re: [cfe-users] Linking problem with implicit instantiation of constructor/destructor
> $ clang++ -o test main.cpp template.cpp > >> /usr/bin/ld: /tmp/main-e2fa2c.o: in function `main': > main.cpp:(.text+0x2f): undefined reference to `Template::Template()' > /usr/bin/ld: main.cpp:(.text+0x4d): undefined reference to > `Template::~Template()' > /usr/bin/ld: main.cpp:(.text+0x82): undefined reference to > `Template::~Template()' > What happens if you change the order of the .cpp files, putting template.cpp first; is it stil unresolved? clang++ -o test template.cpp main.cpp ___ cfe-users mailing list cfe-users@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
Re: [cfe-users] Linking problem with implicit instantiation of constructor/destructor
I don't believe this code is valid according to C++. I believe it would require an explicit instantiation of the ctor/dtor somewhere to make that code valid - though I don't have chapter and verse on the spec at hand just now to back that up. On Fri, Apr 17, 2020 at 6:54 AM Jaroslav Zeman via cfe-users < cfe-users@lists.llvm.org> wrote: > Hello, > > I've run into wieird problem when trying to compile and link our programs > with > clang++ on linux instead of g++. It occurs, when: > - template class member definitions are separated from the definition of > the > class > - no explicit instantiation is done > - member definitions are available only in some of the units, where the > template is being used. > (Yeah, our code is a mess) > > This is simple expamle: > // - template.h > template< typename T > > struct Template { > Template(); > ~Template(); > }; > > void doSomething(Template& t); > > // - template.cpp > #include "template.h" > > template< typename T > > Template< T >::Template() { } > > template< typename T> > Template< T >::~Template() { } > > void doSomething(Template& t) { > Template new_t; > t = new_t; > } > > // - main.cpp > #include "template.h" > > int main(int argc_, char** argv_) { > > Template t; > doSomething(t); > > return 0; > } > // - end of code > > When compiled with clang++: > $ clang++ -o test main.cpp template.cpp > /usr/bin/ld: /tmp/main-e2fa2c.o: in function `main': > main.cpp:(.text+0x2f): undefined reference to `Template::Template()' > /usr/bin/ld: main.cpp:(.text+0x4d): undefined reference to > `Template::~Template()' > /usr/bin/ld: main.cpp:(.text+0x82): undefined reference to > `Template::~Template()' > > reading the object files using nm tool shows, the symbol for destructor > instantiated in template.cpp is _ZN8TemplateIiED2Ev, but the main.o > requires > symbol _ZN8TemplateIiED1Ev. Notice the difference in one digit: D2 vs D1. > > So symbol ...D1... is required, but only ...D2... is available. The D1 > version > is generated by clang only for explicit instantiation. g++ generates both > D1 > and D2 for any type of instantiation. > > Can this be considered a bug of clang++? Or does this behaior have some > purpose? > > Regards, > JZ > > > ___ > cfe-users mailing list > cfe-users@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users > ___ cfe-users mailing list cfe-users@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users