https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80258
--- Comment #4 from Tor Myklebust <tmyklebu at gmail dot com> --- I suppose the program attached doesn't demonstrate that. I ran: info gcc 'C ext' 'thread' I read the following text: When the address-of operator is applied to a thread-local variable, it is evaluated at run time and returns the address of the current thread's instance of that variable. An address so obtained may be used by any thread. When a thread terminates, any pointers to thread-local variables in that thread become invalid. This states that I get the address of the current thread's instance of a thread-local variable when I '&' a variable declared __thread. I edited f() to take the address of foo and pass the address to dump(), and edited dump() to print both the const char ** passed in and the string pointed to by the pointed-to pointer. The result is attached. The program continues to fail with '-O3 -fPIC.' (It also fails with only '-O3.') But now the program relies on the documentation snippet above; it takes the address of the thread-local variable foo once before the call to switch_thread and once after the call to switch_thread and prints the string pointed to by the pointer obtained by taking the address of the thread-local variable foo. Before the call to switch_thread, the current thread's instance of foo points to the string ":(" and dump() faithfully prints a sad face. However, after the call to switch_thread, the current thread's instance of the thread-local variable foo points to the string ":)." With '-O3 -fPIC', the second call to dump() erroneously prints ":(." Since the observed behaviour of the program when compiled with '-O3 -fPIC' deviates from the behaviour specified for the program by the compiler's documentation, I conclude that there is a bug either in the compiler or its documentation---this is a bug. Your comment about swapcontext appears to be a red herring. Whether swapcontext is aware of TLS is irrelevant. I am not aware of any language in the C standard or in gcc's documentation that forbids changing the thread executing a given piece of code with a given stack while it is running. Although gcc has done no analysis to prove that this assumption is sound, the code being generated by gcc effectively assumes that a global pointer is not mutated within a function call.