Treating constant strings as dynamically initialized globals

Hi cfe-dev!

Consider the following code:
$ cat
extern const char* const AAA;
extern const char* const BBB;
const char* const AAA = “aaa”;

const char* const BBB = AAA;

“g++ -O0” and “clang++ -O0” behave differently: gcc emits both AAA and BBB as
linker-initialized constants, while Clang initializes BBB during static initialization:
$ g++ -O0 -c -o a.o ; objdump -d a.o

a.o: file format elf64-x86-64

$ ./bin/clang++ -O0 -c -o a.o ; objdump -d a.o
a.o: file format elf64-x86-64

Disassembly of section .text.startup:

0000000000000000 <__cxx_global_var_init>:

0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8b 04 25 00 00 00 mov 0x0,%rax
b: 00
c: 48 89 04 25 00 00 00 mov %rax,0x0
13: 00
14: 5d pop %rbp
15: c3 retq
16: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
1d: 00 00 00
0000000000000020 <_GLOBAL__I_a>:

20: 55 push %rbp
21: 48 89 e5 mov %rsp,%rbp
24: e8 d7 ff ff ff callq 0 <__cxx_global_var_init>
29: 5d pop %rbp
2a: c3 retq

Is Clang correct here? I imagine that user who wrote the code might expect the
“constant strings” to go in .rodata and be safely accessible during static initialization.

clang is correct in the sense that the C++ standard doesn't require the
compiler to use static initialization for BBB. [basic.start.init] is the
relevant section in the standard; "AAA" doesn't count as a constant
expression. You can "fix" this using constexpr.


I see. Another question is whether Clang should always do constant
initialization, although it's not required.

I would be better user experience IMHO.