https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87314
--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #9)
> The question is how far we want to go and what we just ignore.
> With -fmerge-all-constants, we can have:
> const char var[] = "foobar";
> int foo (void) { return &var[0] != "foobar"; }
> which will likely be now miscompiled.
GCC 8 produces the following and so doesn't actually merge the constants
.LC0:
.string "foobar"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
movl $var, %eax
cmpq $.LC0, %rax
setne %al
movzbl %al, %eax
ret
.cfi_endproc
.LFE0:
.size main, .-main
.globl var
.section .rodata.str1.1
.type var, @object
.size var, 7
var:
.string "foobar"
And with -O0 it's even more obvious:
var:
.string "foobar"
.LC0:
.string "foobar"
and yes, we now optimize this.
> But we could even have two sources,
> const char var2[] = "foobar";
> compiled with -fmerge-all-constants and
> extern char var2[];
> int bar (void) { return &var2[0] != "foobar"; }
> compiled with -fmerge-constants (the default).
>
> So, can we e.g. optimize less if we see flag_merge_all_constants and a
> TREE_READONLY decl(s) (both the above first case and your const int case)?
> If the decl(s) have DECL_INITIAL and bind to current TU, we could of course
> check further the initializers, and ignore the nasty second case above, by
> saying that
> if you define vars as const and declare as non-const, it is your problem and
> similarly, if you -fmerge-all-constants the defining TUs but not uses of
> those decls, it is again your fault? I'd lean towards that.
I didn't manage to merge the variable and the string literal, so I believe
this is a theoretical issue?