https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63550
Bug ID: 63550 Summary: Multiple definition errors occur only with -fgnu-tm Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: spear at cse dot lehigh.edu Templates instantiated within transactions from multiple files result in multiple-definition errors at link time. Errors do not occur when compiling without TM, or when all source files are concatenated. Should these symbols be emitted as weak? The smallest testcase entails two files, each of which instantiates std::vector<int> and uses the initializer list constructor. #define is used to show behavior with and without instantiation from within a transaction. f1.cc: #include <vector> #ifdef USE_TM #define TX __transaction_atomic #else #define TX #endif std::vector<int>* v1; void test1() { TX { // make a vector with some elements in it v1 = new std::vector<int>({1, 2, 3, 4, 5}); } } int main(int argc, char** argv) { } f2.cc: #include <vector> #ifdef USE_TM #define TX __transaction_atomic #else #define TX #endif std::vector<int>* v2; void test2() { TX { v2 = new std::vector<int>({11, 13, 15, 17}); } } The following script builds the two files four ways: with and without instantation of std::vector<int>({...}) within a transaction; and with and without multiple .cc files. build.sh: echo "Building from 2 files, no TM" g++ f1.cc f2.cc -std=c++11 -fgnu-tm -o no_tm_2_file.exe echo "Building from 2 files, TM" g++ -DUSE_TM f1.cc f2.cc -std=c++11 -fgnu-tm -o yes_tm_2_file.exe echo "Building from 1 file, no TM" cat f1.cc f2.cc > f.cc; g++ f.cc -std=c++11 -fgnu-tm -o no_tm_1_file.exe; rm f.cc echo "Building from 1 file, TM" cat f1.cc f2.cc > f.cc; g++ -DUSE_TM f.cc -std=c++11 -fgnu-tm -o yes_tm_1_file.exe; rm f.cc Link errors occur only in one case. Other three cases produce executables: Output: sh build.sh Building from 2 files, no TM Building from 2 files, TM /tmp/cchUc9zn.o: In function `transaction clone for std::vector<int, std::allocator<int> >::vector(std::initializer_list<int>, std::allocator<int> const&)': f2.cc:(.text+0x1b4): multiple definition of `transaction clone for std::vector<int, std::allocator<int> >::vector(std::initializer_list<int>, std::allocator<int> const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x1c6): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::allocator<int>::allocator() [clone .localalias.31]': f2.cc:(.text+0x180): multiple definition of `transaction clone for std::allocator<int>::allocator()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x192): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::allocator<int>::~allocator() [clone .localalias.30]': f2.cc:(.text+0x19a): multiple definition of `transaction clone for std::allocator<int>::~allocator()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x1ac): first defined here /tmp/cchUc9zn.o: In function `transaction clone for __gnu_cxx::new_allocator<int>::new_allocator() [clone .localalias.29]': f2.cc:(.text+0x24a): multiple definition of `transaction clone for __gnu_cxx::new_allocator<int>::new_allocator()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x25c): first defined here /tmp/cchUc9zn.o: In function `transaction clone for __gnu_cxx::new_allocator<int>::~new_allocator() [clone .localalias.28]': f2.cc:(.text+0x254): multiple definition of `transaction clone for __gnu_cxx::new_allocator<int>::~new_allocator()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x266): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_base(std::allocator<int> const&) [clone .localalias.27]': f2.cc:(.text+0x25e): multiple definition of `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_base(std::allocator<int> const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x270): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::_Vector_base<int, std::allocator<int> >::~_Vector_base() [clone .localalias.23]': f2.cc:(.text+0x3a4): multiple definition of `transaction clone for std::_Vector_base<int, std::allocator<int> >::~_Vector_base()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x3b6): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_impl::_Vector_impl(std::allocator<int> const&) [clone .localalias.22]': f2.cc:(.text+0x412): multiple definition of `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_impl::_Vector_impl(std::allocator<int> const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x424): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_impl::~_Vector_impl() [clone .localalias.15]': f2.cc:(.text+0x58c): multiple definition of `transaction clone for std::_Vector_base<int, std::allocator<int> >::_Vector_impl::~_Vector_impl()' /tmp/ccvjPFgv.o:f1.cc:(.text+0x59e): first defined here /tmp/cchUc9zn.o: In function `transaction clone for std::allocator<int>::allocator(std::allocator<int> const&) [clone .localalias.14]': f2.cc:(.text+0x5a6): multiple definition of `transaction clone for std::allocator<int>::allocator(std::allocator<int> const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x5b8): first defined here /tmp/cchUc9zn.o: In function `transaction clone for __gnu_cxx::new_allocator<int>::new_allocator(__gnu_cxx::new_allocator<int> const&) [clone .localalias.8]': f2.cc:(.text+0x67e): multiple definition of `transaction clone for __gnu_cxx::new_allocator<int>::new_allocator(__gnu_cxx::new_allocator<int> const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x690): first defined here /tmp/cchUc9zn.o: In function `transaction clone for void std::_Construct<int, int const&>(int*, int const&) [clone .localalias.2]': f2.cc:(.text+0x772): multiple definition of `transaction clone for void std::_Construct<int, int const&>(int*, int const&)' /tmp/ccvjPFgv.o:f1.cc:(.text+0x784): first defined here collect2: error: ld returned 1 exit status Building from 1 file, no TM Building from 1 file, TM