llvm / llvm-project

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

`std::string` + `-finstrument-functions` + `-std=c++20` = template miscompilation #50742

Open fc2ef0fe-53df-4235-b4bb-a3668189de68 opened 3 years ago

fc2ef0fe-53df-4235-b4bb-a3668189de68 commented 3 years ago
Bugzilla Link 51400
Version trunk
OS Linux
Attachments MRE and test script
CC @mattfbacon,@zygoloid

Extended Description

When compiling with -finstrument-functions and any standard above C++17, that is C++2a aka 20 or 2b aka 23, when attempting to declare a string, the proper templates relating to standard library allocators are not included in the object files, leading to the following linker error:

/usr/bin/ld: /tmp/main-6f2635.o: in function `std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long)':
main.cpp:(.text._ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm[_ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm]+0x5d): undefined reference to `std::allocator<char>::deallocate(char*, unsigned long)'
/usr/bin/ld: main.cpp:(.text._ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm[_ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm]+0x99): undefined reference to `std::allocator<char>::deallocate(char*, unsigned long)'
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)

Additionally, if the string has contents, the error will include the inability to find an allocate method:

/usr/bin/ld: /tmp/main-248bd2.o: in function `std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long)':
main.cpp:(.text._ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm[_ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm]+0x5d): undefined reference to `std::allocator<char>::deallocate(char*, unsigned long)'
/usr/bin/ld: main.cpp:(.text._ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm[_ZNSt16allocator_traitsISaIcEE10deallocateERS0_Pcm]+0x99): undefined reference to `std::allocator<char>::deallocate(char*, unsigned long)'
/usr/bin/ld: /tmp/main-248bd2.o: in function `std::allocator_traits<std::allocator<char> >::allocate(std::allocator<char>&, unsigned long)':
main.cpp:(.text._ZNSt16allocator_traitsISaIcEE8allocateERS0_m[_ZNSt16allocator_traitsISaIcEE8allocateERS0_m]+0x49): undefined reference to `std::allocator<char>::allocate(unsigned long)'
/usr/bin/ld: main.cpp:(.text._ZNSt16allocator_traitsISaIcEE8allocateERS0_m[_ZNSt16allocator_traitsISaIcEE8allocateERS0_m]+0x81): undefined reference to `std::allocator<char>::allocate(unsigned long)'
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)

This manifests for -std=c++20, -std=gnu++20, -std=c++2b, -std=gnu++2b, but not for std=c++17. Additionally, the g++ can compile the code with the same flags, for every C++ standard I tested, from c++17 to c++2b.

See attached tarball for a minimal reproducible example and a script to test whether clang++ and g++ can build it for each standard.

I wasn't sure if this qualifies as release blocker because theoretically you could remove -finstrument-functions, in which case it compiles just fine. However I like seeing all the function names in debugging tools like ASAN.

fc2ef0fe-53df-4235-b4bb-a3668189de68 commented 3 years ago

Godbolt demo link in case you don't want to download the gzip: https://godbolt.org/z/19j1MTa9j