https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108299
--- Comment #3 from Andrea Griffini <agriff at tin dot it> --- Thread storage duration is different from static storage duration. The text I found on the topic is different from the one you are linking, but even in this version (that is indeed more permissive) it's explicitly stated that a thread_local variable must be initialized before any other thread_local variable is accessed in the same compilation unit. > it is implementation-defined whether the dynamic initialization of a > non-block non-inline variable with thread storage duration is sequenced > before the first statement of the initial function of a thread or is deferred. > -------------------------------------------------------------------- > If it is deferred, the initialization associated with the entity for thread > t is sequenced before the first non-initialization odr-use by t of any > non-inline variable with thread storage duration defined in the same > translation unit as the variable to be initialized. > -------------------------------------------------------------------- > It is implementation-defined in which threads and at which points in > the program such deferred dynamic initialization occurs. g++ doesn't seem to follow the rule #include <stdio.h> thread_local int flag = ([](){ printf("HERE!\n"); // This initialization never happens return 1; })(); thread_local int flag2; int main() { printf("Hello, world.\n"); flag2 = 0; // accesses another thread_local variable in same compilation unit return 0; }