https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77316
Bug ID: 77316 Summary: Unnecessary template copy constructor weak symbol emitted in wrong section Product: gcc Version: 5.4.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: rbd at debian dot org Target Milestone: --- The example below is extracted via creduce from a large program I have. The program runs incorrectly when build with gcc 5.4.1 because one object file contains a constructor (roughly) std::vector<...allocator>( allocator const& ) but also a symbol for std::vector<...allocator>( std::vector const& )that points to the same function. When the full program is run, a call to the vector copy constructor ends up linked to the wrong function because the dynamic linker happens to choose the symbol that really points to std::vector<...allocator>( allocator const& ). This makes code that should copy a vector end up constructing an empty one instead using a bogus allocator. I believe this small code shows the same failure: $ cat b.cpp template <typename, typename _Alloc> class vector { public: vector(); vector(const _Alloc &) {} void operator=(vector) { vector a(get_allocator()); } _Alloc get_allocator(); }; struct inherent; template <typename, typename = inherent, typename = decltype(nullptr)> struct allocator_affinity {}; typedef vector<void *, allocator_affinity<void *>> addr_list_t; struct A { A(int) {} addr_list_t req_start_h_0; void req_start() { req_start_h_0 = addr_list_t(); } }; int b; void fn1() { A a(b); a.req_start(); } $ g++-5 -v -std=c++11 -o b.o -c b.cpp Using built-in specs. COLLECT_GCC=g++-5 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 5.4.1-1' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.4.1 20160803 (Debian 5.4.1-1) COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-o' 'b.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE b.cpp -quiet -dumpbase b.cpp -mtune=generic -march=x86-64 -auxbase-strip b.o -std=c++11 -version -o /tmp/ccmGdTt0.s GNU C++11 (Debian 5.4.1-1) version 5.4.1 20160803 (x86_64-linux-gnu) compiled by GNU C version 5.4.1 20160803, GMP version 6.1.1, MPFR version 3.1.4-p2, MPC version 1.0.3 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/5" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/5 /usr/include/x86_64-linux-gnu/c++/5 /usr/include/c++/5/backward /usr/lib/gcc/x86_64-linux-gnu/5/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C++11 (Debian 5.4.1-1) version 5.4.1 20160803 (x86_64-linux-gnu) compiled by GNU C version 5.4.1 20160803, GMP version 6.1.1, MPFR version 3.1.4-p2, MPC version 1.0.3 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: f5ac0328c94ad0bc615d4ccef0bcd937 COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-o' 'b.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' as -v --64 -o b.o /tmp/ccmGdTt0.s GNU assembler version 2.26.1 (x86_64-linux-gnu) using BFD version (GNU Binutils for Debian) 2.26.1 COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-std=c++11' '-o' 'b.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' $ objdump -C -t b.o b.o: file format elf64-x86-64 SYMBOL TABLE: 0000000000000000 l df *ABS* 0000000000000000 b.cpp 0000000000000000 l d .text 0000000000000000 .text 0000000000000000 l d .data 0000000000000000 .data 0000000000000000 l d .bss 0000000000000000 .bss 0000000000000000 l d .text._ZN1AC2Ei 0000000000000000 .text._ZN1AC2Ei 0000000000000000 l d .text._ZN1A9req_startEv 0000000000000000 .text._ZN1A9req_startEv 0000000000000000 l d .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEaSES4_ 0000000000000000 .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEaSES4_ 0000000000000000 l d .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 0000000000000000 .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack 0000000000000000 l d .eh_frame 0000000000000000 .eh_frame 0000000000000000 l .group 0000000000000000 A::A(int) 0000000000000000 l .group 0000000000000000 vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(allocator_affinity<void*, inherent, decltype(nullptr)> const&) 0000000000000000 l d .comment 0000000000000000 .comment 0000000000000000 l d .group 0000000000000000 .group 0000000000000000 l d .group 0000000000000000 .group 0000000000000000 l d .group 0000000000000000 .group 0000000000000000 l d .group 0000000000000000 .group 0000000000000000 w F .text._ZN1AC2Ei 000000000000001e A::A(int) 0000000000000000 *UND* 0000000000000000 vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector() 0000000000000000 w F .text._ZN1AC2Ei 000000000000001e A::A(int) 0000000000000000 w F .text._ZN1A9req_startEv 0000000000000035 A::req_start() 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEaSES4_ 000000000000002e vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::operator=(vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >) 0000000000000000 g O .bss 0000000000000004 b 0000000000000000 g F .text 000000000000002b fn1() 0000000000000000 *UND* 0000000000000000 vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::get_allocator() 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 000000000000000f vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(allocator_affinity<void*, inherent, decltype(nullptr)> const&) 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEaSES4_ 000000000000002e _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEaSES5_ 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 000000000000000f vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(allocator_affinity<void*, inherent, decltype(nullptr)> const&) 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 000000000000000f vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> > const&) 0000000000000000 w F .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ 000000000000000f vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> > const&) Notice that the last section, .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3 contains both the constructors vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(allocator_affinity<void*, inherent, decltype(nullptr)> const&) vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> >::vector(vector<void*, allocator_affinity<void*, inherent, decltype(nullptr)> > const&) pointing at the very same address. I don't think there is any reason to create the copy constructor at all - neither gcc 4.9 nor gcc 6.1 emit that symbol. Also if I run "g++-5 -std=c++11 -o b.S -S b.cpp" to create assembly output, I see .section .text._ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_,"axG",@progbits,_ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC5ERKS3_,comdat .align 2 .weak _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ .type _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_, @function _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_: .LFB9: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -8(%rbp) movq %rsi, -16(%rbp) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE9: .size _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_, .-_ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ .weak _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS4_ .set _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS4_,_ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ .weak _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC1ERKS3_ .set _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC1ERKS3_,_ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC2ERKS3_ .weak _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC1ERKS4_ .set _ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC1ERKS4_,_ZN6vectorIPv18allocator_affinityIS0_8inherentDnEEC1ERKS3_ so it seems the compiler is intentionally creating this strange alias...