Skip to content

LTO breaks importing TLS from shared libraries on MinGW, making libstdc++ unusable #161039

@HolyBlackCat

Description

@HolyBlackCat

Consider those files:

// 1.cpp
extern thread_local int x;
int main() {return x;}
// 2.cpp
thread_local int x;

If you do following on MinGW (e.g. in MSYS2):

clang++ -fuse-ld=lld 2.cpp -shared -o lib2.dll
clang++ -fuse-ld=lld 1.cpp -l2 -L. -flto

Then you get one of the following two errors. If -femulated-tls is used (as is necessary for libstdc++, default in MSYS2 MINGW64 and MSYS2 CLANG64):

ld.lld: error: undefined symbol: x
>>> referenced by 1.cpp
>>>               /tmp/1-061a94.o
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Or if -fno-emulated-tls is used: (default in MSYS2 CLANG64)

ld.lld: error: undefined symbol: x
>>> referenced by 1.cpp
>>>               /tmp/1-061a94.o
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

This bug makes libstdc++ unusable with LTO on MinGW, because it uses thread_local variables for std::once_flag (if you use this feature, that is):

// 3.cpp
#include <mutex>
int main() {std::once_flag f; std::call_once(f, []{});}

Compiling with clang++ -fuse-ld=lld 3.cpp -flto I get:

ld.lld: error: undefined symbol: std::__once_callable
>>> referenced by 3.cpp
>>>               /tmp/3-c926bc.o

ld.lld: error: undefined symbol: std::__once_call
>>> referenced by 3.cpp
>>>               /tmp/3-c926bc.o
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Tested on Clang 21.1.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    LTOLink time optimization (regular/full LTO or ThinLTO)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions