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]