https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107500
--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Reduced:
extern "C" int puts(const char*);
struct A
{
constexpr A() { }
~A() { puts("bye"); }
};
namespace
{
struct constant_init
{
union {
A obj;
};
constexpr constant_init() : obj() { }
~constant_init() { /* do nothing, union member is not destroyed */ }
};
// Single-threaded fallback buffer.
constinit constant_init global;
}
extern "C" A* get() { return &global.obj; }
With -std=c++20 -Os GCC emits a call to atexit:
(anonymous namespace)::constant_init::~constant_init() [base object
destructor]:
ret
get:
mov eax, OFFSET FLAT:_ZN12_GLOBAL__N_16globalE
ret
_GLOBAL__sub_I_get:
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZN12_GLOBAL__N_16globalE
mov edi, OFFSET FLAT:_ZN12_GLOBAL__N_113constant_initD1Ev
jmp __cxa_atexit
With the same options, Clang doesn't:
get: # @get
lea rax, [rip + (anonymous namespace)::global]
ret