Test program: ```c++ struct cat { cat(){ __builtin_printf("cat(): %p\n", (void *)this); } ~cat(){ __builtin_printf("~cat(): %p\n", (void *)this); } void meow(){ __builtin_printf("meow(): %p\n", (void *)this); } }; thread_local cat c; int main(){ c.meow(); } ``` Compiling and running this program outputs a garbage pointer inside the dtor: ```plaintext E:\Desktop>i686-w64-mingw32-g++ test.cpp && a.exe cat(): 0084177C meow(): 0084177C ~cat(): 76EC2FED ``` Recompile the original program with `-S -O2` and notice the following assembly code: ```s C1: .ascii "cat(): %p\12\0" .text .def ___tls_init.part.0; .scl 3; .type 32; .endef __tls_init.part.0: pushl %ebx subl $24, %esp movl $___emutls_v.__tls_guard, (%esp) call ___emutls_get_address movb $1, (%eax) movl $___emutls_v.c, (%esp) call ___emutls_get_address movl %eax, %ebx movl %eax, 4(%esp) movl $LC1, (%esp) call _printf movl $0, 8(%esp) movl %ebx, 4(%esp) movl $__ZN3catD1Ev, (%esp) call ___cxa_thread_atexit addl $24, %esp popl %ebx ret ``` GCC emits a call to the destructor of `cat` using `__cxa_thread_atexit()`. This causes the crash, because `__cxa_thread_atexit()` requires the callback to use the `__cdecl` calling convention, where its argument is to be pushed onto stack, while the destructor expects the `__thiscall` calling convention, where its argument, the implicit `this` pointer, is to be passed via the ECX register. Hence inside the callback ECX merely gets whatever garbage value that happens to reside in it. Reference: https://sourceforge.net/p/mingw-w64/bugs/527/
I can confirm that on gcc 7.3.0 / i686-mingw64.
We encountered the same issue today, so this thread_local issue is still present also with gcc 8.1.0 i686-gcc-7.3.0-mingw-5.0.3 i686-gcc-8.1.0-mingw-5.0.3 (Note: With the corresponding 64bit gcc all is fine). Could this bug please be assigned to someone? (It seems this is somehwat stalled since months unfortunately ...) Thank you for taking care of this!
This can easily be fixed by way of a trampoline that adjusts the parameter.
This still is not working causing several boost libraries to fail building when using mingw-w64 compilers (gcc-9.3 and gcc-10.2). Everything works fine with the 64 bit compiler but the i686 compiler reports broken TLS. While we can get around it by disabling the TLS check for libbost_fiber-mt.dll libboost_stacktrace_windbg_cached-mt.dll is another story (halts the build if we skip the TLS check).
https://github.com/gcc-mirror/gcc/commit/7fc0f78c3f43af1967cb7b1ee8f4947f3b890aa2
The mingw-w64 bug which you've linked has been fixed for UCRT: https://github.com/mingw-w64/mingw-w64/blob/0d42217123d3aec0341b79f6d959c76e09648a1e/mingw-w64-crt/crt/tls_atexit.c#L119