https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107500
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2022-11-02 Ever confirmed|0 |1 --- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to R. Diez from comment #0) > The check above fails with GCC 12.2. Apparently, a destructor called > constant_init::~constant_init() gets added to the atexit table on start-up. This was done to make the global object in that file immortal. The constant_init wrapper gets destroyed, but its subobject doesn't, so code that refers to it later is ... slightly less undefined. > Because of the way that Newlib works, that wastes 400 bytes of SRAM, which > corresponds to sizeof( _global_atexit0 ). The structure has room for 32 > atexit calls (because of some ANSI conformance), but we are only using 1 > entry. > > The interesting thing is that the destructor is supposed to be empty, see: > > https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/ > eh_globals.cc > > ~constant_init() { /* do nothing, union member is not destroyed */ } > > GCC generates the following code for that empty destructor: > > 0008da68 <(anonymous namespace)::constant_init::~constant_init()>: > 8da68: b580 push {r7, lr} > 8da6a: af00 add r7, sp, #0 > 8da6c: bd80 pop {r7, pc} > > That does not make any sense. Is there a way to prevent GCC from registering > such an empty atexit function? Failing that, is there a way to prevent GCC > from registering a particular atexit function, even if it is not empty? If we had clang's no_destroy attribute then we could use that on those constant_init wrappers: https://clang.llvm.org/docs/AttributeReference.html#no-destroy > I find surprising that GCC emits such code. My project is building its own > GCC/Newlib toolchain with optimisation level "-Os", so I would expect at > least the "add r7, sp, #0" to be optimised away. Agreed, I don't think we should be emitting cleanup if it's a no-op. But I don't know if the compiler is able to tell it's a no-op at the point where it emits that code. The attribute would tell the compiler it's OK to do that.