https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102876
--- Comment #12 from Mathias Stearn <redbeard0531 at gmail dot com> --- (In reply to Jakub Jelinek from comment #10) > So we'd just punt at optimizing that, we don't know if b is read or written > by foo (and, note, it doesn't have to be just the case of explicitly being > passed address of some var, it can get the address through other means). > On the other side, we can't optimize b to b: .long 2, because bar can use > the variable and/or modify it, so by using 2 as static initializer bar would > be miscompiled. I'm pretty sure that that is explicitly allowed by https://eel.is/c++draft/basic.start.static#3, so it should *not* be considered a miscompilation. The example only shows reading from another static-duration variable's initializer, but I believe writing would also be covered. I took a look at how other compilers handle this, and it is somewhat interesting: https://godbolt.org/z/9YvcbEeax int foo(int&); inline int bar() { return 7; } extern int b; int z = bar(); int a = foo(b); // comment this out and watch clang change... int b = bar(); int c = bar(); GCC: always does dynamic init for everything. MSVC: always does static init for z, b, and c. always dynamic init for a. Clang: it seems like if it does any dynamic init in the TU, it doesn't promote any dynamic init to static. So with that code all four variables are dynamicially initialized, but if you comment out a, the remaining 3 become static. If you add an unrelated variable that requires dynamic init, those 3 become dynamically initialized again. I don't understand why clang does what it does. I don't think it is required to do that by the standard, and it clearly seems suboptimal. So I would rather GCC behave like MSVC in this case than like clang. Also note what happens if we provide a definition for foo like `inline int foo(int& x) { return x += 6; }`: https://godbolt.org/z/sWd6chsnP. Now both MSVC and Clang will static initialize z, b, and c to 7 and *static* initialize a to 6. GCC gets the same result dynamically, but for some reason tries to load b prior to adding 6, even though it has to be 0 (barring a UB write to b from another TU).