https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119359
Bug ID: 119359 Summary: incomplete folding of initializers leads to dynamic initialization Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: nathan at gcc dot gnu.org Target Milestone: --- Created attachment 60811 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60811&action=edit reproducer #ifdef BUG #define ADDR (16 + 16 * 0) #else #define ADDR 16 #endif int *const FOO = (int *)ADDR; int *const BAR = FOO; int foo () {return *FOO;} int bar () {return *addr;} g++ -O2 results in static initialization (and folding away the const vars) g++ -O2 -DBUG results in dynamic initialization of 'run' but not 'addr': _Z4frobv: movq _ZL3run(%rip), %rax movl (%rax), %eax ret _GLOBAL__sub_I__Z4frobv: .cfi_startproc movq $16, _ZL3run(%rip) ret What happens is we end up inside initializer_constant_valid_p (varasm.cc) examining ADDR's initializer when considering RUN's initializer. We see an unfolded tree '(+ 16 (* 16 0))' and that multiplication causes us to think it's not a valid constant. I think initializer_constant_valid_p is assuming trees are fully folded? I suspect we need to store the folded initializer into DECL_INITIAL or something.