https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107500
Bug ID: 107500 Summary: Useless atexit entry for ~constant_init in eh_globals.cc Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: rdiezmail-gcc at yahoo dot de Target Milestone: --- I have this embedded firmware project of mine, which uses Newlib: https://github.com/rdiez/DebugDue It is the template for other similar bare-metal projects I have. Even though some targets have very little SRAM (like 16 KiB), I am still using C++ and exceptions. The project above documents how I configure GCC to that effect. Up until GCC 11.2, I have been doing this check: if ( _GLOBAL_ATEXIT != nullptr ) { Panic( "Unexpected entries in atexit table." ); } On devices with very little RAM and without an operating system, initialisation and destruction can be tricky. With the check above, I am making sure that nothing unexpected comes up in that respect. I am initialising all static objects manually anyway, to prevent any ordering surprises (the initialisation order of C++ static objects can be problematic too). 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. 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? 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.