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; }