https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103121
--- Comment #13 from Martin Sebor <msebor at gcc dot gnu.org> --- Here's a reduced test case that reproduces the problem with an x86_64-linux GCC in ILP32 mode: $ cat pr103121.C && gcc -O2 -S -Wall -m32 pr103121.C typedef typeof (sizeof 0) size_t; struct tree_node { const char *str; unsigned len; }; typedef tree_node *tree; extern tree get_identifier_with_length (const char *, size_t); extern tree get_identifier (const char *); tree decl_assembler_name (tree); tree cdtor_comdat_group (tree complete, tree base) { tree complete_name = decl_assembler_name (complete); tree base_name = decl_assembler_name (base); char *grp_name = (char *) __builtin_alloca (complete_name->len + 1); const char *p = complete_name->str; const char *q = base_name->str; size_t i; bool diff_seen = false; for (i = 0; i < complete_name->len; i++) if (p[i] == q[i]) grp_name[i] = p[i]; else diff_seen = true; grp_name[i] = '\0'; if (!diff_seen) __builtin_abort (); return get_identifier (grp_name); } pr103121.C: In function ‘tree_node* cdtor_comdat_group(tree, tree)’: pr103121.C:32:15: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 32 | grp_name[i] = '\0'; | ~~~~~~~~~~~~^~~~~~ pr103121.C:18:46: note: at offset 1 into destination object of size 1 allocated by ‘__builtin_alloca’ 18 | char *grp_name = (char *) __builtin_alloca (complete_name->len + 1); | ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ An annotated ranger dump is below: ;; Function cdtor_comdat_group =========== BB 2 ============ Imports: _1 Exports: _1 Relational : (_2 != _1) <bb 2> [local count: 118111600]: _20 = decl_assembler_name (complete_18(D)); _23 = decl_assembler_name (base_21(D)); _1 = _20->len; _2 = _1 + 1; grp_name_25 = __builtin_alloca (_2); p_26 = _20->str; q_27 = _23->str; if (_1 != 0) goto <bb 10>; [89.00%] else goto <bb 6>; [11.00%] grp_name_25 : char * [1B, +INF] 2->10 (T) _1 : unsigned int [1, +INF] 2->10 (T) _2 : unsigned int [0, 0][2, +INF] 2->6 (F) _1 : unsigned int [0, 0] 2->6 (F) _2 : unsigned int [1, 1] =========== BB 10 ============ <bb 10> [local count: 105119324]: =========== BB 3 ============ Imports: _4 _6 Exports: _4 _6 Equivalence set : [_6] Equivalence set : [_4] <bb 3> [local count: 955630225]: # i_35 = PHI <i_33(11), 0(10)> # diff_seen_38 = PHI <diff_seen_13(11), 0(10)> _4 = MEM[(const char *)p_26 + i_35 * 1]; _6 = MEM[(const char *)q_27 + i_35 * 1]; if (_4 == _6) goto <bb 4>; [34.00%] else goto <bb 5>; [66.00%] i_35 : size_t [0, 4294967294] =========== BB 4 ============ i_35 size_t [0, 4294967294] Equivalence set : [_4, _6] <bb 4> [local count: 324914280]: MEM[(char *)grp_name_25 + i_35 * 1] = _4; =========== BB 5 ============ Imports: _10 i_35 Exports: _10 i_33 i_35 i_33 : i_35(I) i_35 size_t [0, 4294967294] Relational : (i_33 > i_35) <bb 5> [local count: 955630225]: # diff_seen_13 = PHI <diff_seen_38(4), 1(3)> i_33 = i_35 + 1; _10 = _20->len; if (_10 > i_33) goto <bb 11>; [89.00%] else goto <bb 7>; [11.00%] i_33 : size_t [1, +INF] 5->11 (T) _10 : unsigned int [2, +INF] 5->11 (T) i_33 : size_t [1, 4294967294] 5->11 (T) i_35 : size_t [0, 4294967293] 5->7 (F) i_33 : size_t [1, +INF] 5->7 (F) i_35 : size_t [0, 4294967294] =========== BB 11 ============ diff_seen_13 bool VARYING i_33 size_t [1, 4294967294] Relational : (_10 > i_35) Relational : (_10 > i_33) <bb 11> [local count: 850510901]: goto <bb 3>; [100.00%] =========== BB 6 ============ <bb 6> [local count: 12992276]: *grp_name_25 = 0; goto <bb 8>; [100.00%] =========== BB 7 ============ Imports: diff_seen_13 Exports: diff_seen_13 diff_seen_13 bool VARYING i_33 size_t [1, +INF] Relational : (_10 <= i_33) <bb 7> [local count: 105119324]: _11 = grp_name_25 + i_33; <<< grp_name_25 points to a block of size 1 *_11 = 0; <<< -Wstringop-overflow if (diff_seen_13 != 0) goto <bb 9>; [100.00%] else goto <bb 8>; [0.00%] _11 : char * [1B, +INF] 7->8 (F) diff_seen_13 : bool [0, 0] 7->9 (T) diff_seen_13 : bool [1, 1] =========== BB 8 ============ <bb 8> [count: 0]: __builtin_abort (); =========== BB 9 ============ <bb 9> [local count: 118111600]: _30 = get_identifier (grp_name_25); return _30; Non-varying global ranges: =========================: _11 : char * [1B, +INF] grp_name_25 : char * [1B, +INF] i_33 : size_t [1, +INF] i_35 : size_t [0, 4294967294]