https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71113
Bug ID: 71113 Summary: Adding "const" to value in constexpr constructor places const object in .bss instead of .rodata Product: gcc Version: 6.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: freddie_chopin at op dot pl Target Milestone: --- Take a look at following test case: -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- class X { public: constexpr X(void* pointer) : pointer_{pointer} { } private: void* pointer_; }; #define PERIPHERAL1 (void*)0x20000000 const X xxx {PERIPHERAL1}; int main() { } -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- Execute test: -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- $ g++ test.cpp && objdump -x --syms --demangle a.out | grep xxx 0000000000400608 l O .rodata 0000000000000008 xxx -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- Everything's fine. Now just add one trivial change, which does _NOT_ change any logic (at least in my opinion (; ). Replace: constexpr X(void* pointer) : with constexpr X(void* const pointer) : And the object is placed in .bss, not in .rodata... -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- $ g++ test.cpp && objdump -x --syms --demangle a.out | grep xxx 0000000000600a58 l O .bss 0000000000000008 xxx -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- There's no problem if an address of "real" object is used, so for example something like this works fine in both cases: -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- int something; const X xxx {&something}; -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- The use case may seem a bit strange, but the macro definition like the one used in the example is used commonly in hardware headers for microcontrollers. They usually look like this: -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- #define PERIPH_BASE ((uint32_t)0x40000000U) #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000U) #define USART1_BASE (APB2PERIPH_BASE + 0x1000U) #define USART1 ((USART_TypeDef *) USART1_BASE) -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- (USART_TypeDef is a typedef of an anonymous struct with layout of peripheral registers) The behaviour was noticed in GCC compiled for "arm-none-eabi-", version 5.3.1, but the same thing happens in a desktop version 6.1.1 on Arch Linux.