https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79061
--- Comment #27 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I think the problem is in the vnode->dynamically_initialized handling, as well as in get_translation_unit_decl being totally unreliable. When LTO merges VAR_DECLs from multiple TUs, it either should clear the dynamically_initialized flag, or should make sure that the decl that is used for the vnode actually is going to have get_translation_unit_decl the TU that it contained the definition. The #c20 testcase has in the end 3 globals: name = "__ioinit", module_name = 0x400f3c "/tmp/ccoQRMfD.ltrans0.o", has_dynamic_init = 1 name = 0x400f5d "xptimer_clean", module_name = 0x400de0 "xptimer.cc", has_dynamic_init = 1 name = 0x400f6b "xptimer_sweep", module_name = 0x400de0 "xptimer.cc", has_dynamic_init = 1 xptimer_clean and xptimer_sweep are both defined in xptiming.cc and declared in xptiming.h, xptimer.cc TU doesn't see any traces of it, yet get_translation_unit_decl returns for it the xptimer.cc TU, because DECL_CONTEXT of those 2 vars is a NAMESPACE_DECL and LTO merges NAMESPACE_DECLs too. Similarly, __ioinit has DECL_CONTEXT of std namespace and that, being prebuilt by the compiler, doesn't have surrounding TU. Even when considering only VAR_DECLs that have DECL_CONTEXT of TRANSLATION_UNIT_DECL directly, I believe this doesn't work right: 1) if the VAR_DECL has more than one definition (comdat, inline var, ...?), then I think we'd need to merge the two definitions with dynamically_initialized 1 as dynamically_initialized 0 2) wonder if we ever merge external decl with decl definition using the external decl's context In short, the easiest fix is just to disable the initialization order checking altogether for LTO (by forcing dynamically_initialized = 0 in LTO). Or at least clear it when merging multiple varpool nodes that have dynamically_initialized = 1, and otherwise (if there is just one TU with vnode->dynamically_initialized == 1), make sure get_translation_unit_decl will return that TU for it and if we can't ensure that, clear dynamically_initialized too. Which can be done e.g. by clearing it whenever DECL_CONTEXT actually isn't a TRANSLATION_UNIT_DECL directly or is some other TU, or by say adding TRANSLATION_UNIT_DECL tree into the vnode (grows memory usage though!) and looking it up from there.