https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94313
Bug ID: 94313
Summary: stores into string literals sometimes silently
eliminated
Product: gcc
Version: 10.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
Modifying a const-qualified object or a string literal is undefined in both C
and C++ and can result in subtle bugs. Detecting attempts to do so as
requested in pr90404 will help prevent such hard-to-find bugs. However,
reliable detection is made difficult by optimizations that silently eliminate
stores to such objects. The test case below shows that the second of the four
invalid stores below (in g1) is silently eliminated (by DSE) while the others
are retained. (None of them is diagnosed.) The first two will likely crash if
the strings are stored in ROM. The second two could lead in unexpected results
as a result of other optimizations (such as the strlen pass) that assume that
const objects cannot change.
The last revision I have access to that did not eliminate the store is r145753.
The first revision that does is r145825, so the change was introduced sometime
in between these two.
$ cat z.c && gcc -O2 -S -Wall -Wwrite-strings -fdump-tree-optimized=/dev/stdout
z.c
void f (void*);
static char* str (void) { return (char*)"abc"; }
void g0 (int x)
{
char *s = __builtin_strchr (str (), 'a');
*s = 'x'; // not eliminated (okay)
f (s);
}
void g1 (int x)
{
char *s = __builtin_strchr (str (), x);
*s = 'x'; // eliminated
f (s);
}
const char a[] = "bcd";
void g2 (void)
{
char *s = __builtin_strchr (a, 'b');
*s = 'x'; // not eliminated (okay)
f (s);
}
void g3 (int x)
{
const char a[] = "cde";
char *s = __builtin_strchr (a, 'c');
*s = 'x'; // not eliminated (okay)
f (s);
}
;; Function g0 (g0, funcdef_no=1, decl_uid=1935, cgraph_uid=2, symbol_order=1)
g0 (int x)
{
<bb 2> [local count: 1073741824]:
MEM[(char *)"abc"] = 120;
f ("abc"); [tail call]
return;
}
;; Function g1 (g1, funcdef_no=2, decl_uid=1939, cgraph_uid=3, symbol_order=2)
g1 (int x)
{
char * s;
<bb 2> [local count: 1073741824]:
s_3 = __builtin_strchr ("abc", x_2(D));
f (s_3); [tail call]
return;
}
;; Function g2 (g2, funcdef_no=3, decl_uid=1944, cgraph_uid=4, symbol_order=4)
g2 ()
{
<bb 2> [local count: 1073741824]:
MEM[(char *)&a] = 120;
f (&a); [tail call]
return;
}
;; Function g3 (g3, funcdef_no=4, decl_uid=1948, cgraph_uid=5, symbol_order=5)
g3 (int x)
{
char * s;
const char a[4];
<bb 2> [local count: 1073741824]:
a = "cde";
s_3 = __builtin_strchr (&a, 99);
*s_3 = 120;
f (s_3);
a ={v} {CLOBBER};
return;
}