Avoid warning for memset writing over multiple members.
Resolves: PR middle-end/95667 - unintended warning for memset writing across multiple members PR middle-end/92814 - missing -Wstringop-overflow writing into a dynamically allocated flexible array member gcc/ChangeLog: PR middle-end/95667 PR middle-end/92814 * builtins.c (compute_objsize): Remove call to compute_builtin_object_size and instead compute conservative sizes directly here. gcc/testsuite/ChangeLog: PR middle-end/95667 PR middle-end/92814 * gcc.dg/Wstringop-overflow-25.c: Remove xfails. * gcc.dg/Wstringop-overflow-39.c: New test.
This commit is contained in:
parent
5421fae8b1
commit
5acc654e38
3 changed files with 140 additions and 34 deletions
|
@ -4009,31 +4009,6 @@ static bool
|
|||
compute_objsize (tree ptr, int ostype, access_ref *pref,
|
||||
bitmap *visited, const vr_values *rvals /* = NULL */)
|
||||
{
|
||||
if (ostype == 0)
|
||||
{
|
||||
/* Use BOS only for raw memory functions like memcpy to get
|
||||
the size of the largest enclosing object. */
|
||||
tree off = NULL_TREE;
|
||||
unsigned HOST_WIDE_INT size;
|
||||
if (compute_builtin_object_size (ptr, ostype, &size, &pref->ref, &off))
|
||||
{
|
||||
if (off)
|
||||
{
|
||||
offset_int offset = wi::to_offset (off);
|
||||
pref->offrng[0] += offset;
|
||||
pref->offrng[1] += offset;
|
||||
|
||||
/* compute_builtin_object_size() returns the remaining
|
||||
size in PTR. Add the offset to it to get the full
|
||||
size. */
|
||||
pref->sizrng[0] = pref->sizrng[1] = size + offset;
|
||||
}
|
||||
else
|
||||
pref->sizrng[0] = pref->sizrng[1] = size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const bool addr = TREE_CODE (ptr) == ADDR_EXPR;
|
||||
if (addr)
|
||||
ptr = TREE_OPERAND (ptr, 0);
|
||||
|
@ -4058,18 +4033,28 @@ compute_objsize (tree ptr, int ostype, access_ref *pref,
|
|||
|
||||
if (code == COMPONENT_REF)
|
||||
{
|
||||
tree field = TREE_OPERAND (ptr, 1);
|
||||
|
||||
if (ostype == 0)
|
||||
{
|
||||
/* For raw memory functions like memcpy bail if the size
|
||||
of the enclosing object cannot be determined. */
|
||||
access_ref tmpref;
|
||||
tree ref = TREE_OPERAND (ptr, 0);
|
||||
if (!compute_objsize (ref, ostype, &tmpref, visited, rvals)
|
||||
|| !tmpref.ref)
|
||||
if (!compute_objsize (ref, ostype, pref, visited, rvals)
|
||||
|| !pref->ref)
|
||||
return false;
|
||||
|
||||
/* Otherwise, use the size of the enclosing object and add
|
||||
the offset of the member to the offset computed so far. */
|
||||
tree offset = byte_position (field);
|
||||
if (TREE_CODE (offset) != INTEGER_CST)
|
||||
return false;
|
||||
offset_int off = wi::to_offset (offset);
|
||||
pref->offrng[0] += off;
|
||||
pref->offrng[1] += off;
|
||||
return true;
|
||||
}
|
||||
|
||||
tree field = TREE_OPERAND (ptr, 1);
|
||||
/* Bail if the reference is to the pointer itself (as opposed
|
||||
to what it points to). */
|
||||
if (!addr && POINTER_TYPE_P (TREE_TYPE (field)))
|
||||
|
@ -4147,8 +4132,11 @@ compute_objsize (tree ptr, int ostype, access_ref *pref,
|
|||
orng[0] *= sz;
|
||||
orng[1] *= sz;
|
||||
|
||||
if (TREE_CODE (eltype) == ARRAY_TYPE)
|
||||
if (ostype && TREE_CODE (eltype) == ARRAY_TYPE)
|
||||
{
|
||||
/* Execpt for the permissive raw memory functions which
|
||||
use the size of the whole object determined above,
|
||||
use the size of the referenced array. */
|
||||
pref->sizrng[0] = pref->offrng[0] + orng[0] + sz;
|
||||
pref->sizrng[1] = pref->offrng[1] + orng[1] + sz;
|
||||
}
|
||||
|
|
|
@ -370,14 +370,14 @@ NOIPA void test_strcpy_malloc_flexarray (void)
|
|||
size_t r_2_3 = UR (2, 3);
|
||||
|
||||
T (char, S (0), r_0_1);
|
||||
T (char, S (1), r_0_1); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" { xfail *-*-* } }
|
||||
T (char, S (1), r_0_1); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
|
||||
|
||||
T (char, S (0), r_1_2);
|
||||
T (char, S (1), r_1_2);
|
||||
T (char, S (2), r_1_2); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" { xfail *-*-* } }
|
||||
T (char, S (2), r_1_2); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
|
||||
|
||||
T (char, S (0), r_2_3);
|
||||
T (char, S (2), r_2_3);
|
||||
T (char, S (3), r_2_3); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" { xfail *-*-* } }
|
||||
T (char, S (9), r_2_3); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" { xfail *-*-* } }
|
||||
T (char, S (3), r_2_3); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
|
||||
T (char, S (9), r_2_3); // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
|
||||
}
|
||||
|
|
118
gcc/testsuite/gcc.dg/Wstringop-overflow-39.c
Normal file
118
gcc/testsuite/gcc.dg/Wstringop-overflow-39.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* PR middle-end/95667 - unintended warning for memset writing across multiple
|
||||
members
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wall" } */
|
||||
|
||||
extern void sink (void*);
|
||||
|
||||
struct S1 { char a[3], b[5]; };
|
||||
|
||||
void warn_strcpy_s1 (void)
|
||||
{
|
||||
struct S1 *p = __builtin_malloc (sizeof *p);
|
||||
char s[] = "1234567";
|
||||
__builtin_strcpy (p->a, s); // { dg-warning "\\\[-Wstringop-overflow" }
|
||||
sink (p);
|
||||
}
|
||||
|
||||
void nowarn_memset_s1 (void)
|
||||
{
|
||||
struct S1 *p = __builtin_malloc (sizeof *p);
|
||||
__builtin_memset (p->a, 0, 8); // { dg-bogus "\\\[-Wstringop-overflow" }
|
||||
sink (p);
|
||||
}
|
||||
|
||||
struct S2 { char a[2], b[2][2], c[3]; };
|
||||
|
||||
void nowarn_memset_s2 (void)
|
||||
{
|
||||
struct S2 *p = __builtin_malloc (sizeof *p);
|
||||
|
||||
__builtin_memset (p->a, 0, sizeof *p);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (p->b, 0, 7);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0], 0, 7);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[1], 0, 5);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0][0], 0, 7);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0][1], 0, 6);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[1][0], 0, 5);
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[1][1], 0, 4);
|
||||
sink (p);
|
||||
}
|
||||
|
||||
void warn_memset_s2 (void)
|
||||
{
|
||||
const unsigned n = sizeof (struct S2);
|
||||
struct S2 *p = __builtin_malloc (n);
|
||||
|
||||
/* These should trigger -Wstringop-overflow rather than -Warray-bounds
|
||||
but the main purpose of the test is to verify the absence of warnings
|
||||
above so the exact warning for these overflwing calls isn't important
|
||||
here. */
|
||||
|
||||
__builtin_memset (p->a, 0, n + 1); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (p->b, 0, 8); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0], 0, 8); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0][0], 0, 8); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[1], 0, 6); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
|
||||
__builtin_memset (&p->b[0][1], 0, 7); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (p);
|
||||
}
|
||||
|
||||
void nowarn_vl_struct (unsigned n)
|
||||
{
|
||||
if (n < 3 || 5 < n)
|
||||
n = 3;
|
||||
|
||||
struct V { char a[3], b[n], c[7]; } v;
|
||||
|
||||
__builtin_memset (v.a, 0, 15);
|
||||
sink (&v);
|
||||
|
||||
__builtin_memset (v.b, 0, 12);
|
||||
sink (&v);
|
||||
|
||||
__builtin_memset (v.c, 0, 7);
|
||||
sink (&v);
|
||||
|
||||
__builtin_memset (v.a, 0, 16); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (&v);
|
||||
|
||||
__builtin_memset (v.b, 0, 13); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
|
||||
sink (&v);
|
||||
|
||||
/* The &V.C argument is represented as a variable offset from
|
||||
the beginning of the allocated object and there's no good
|
||||
way to figure out from its variable offset that it's base
|
||||
is the C member:
|
||||
s.1_12 = __builtin_alloca_with_align (prephitmp_24, 8);
|
||||
_9 = s.1_12 + prephitmp_27;
|
||||
__builtin_memset (_9, 0, 2);
|
||||
*/
|
||||
|
||||
__builtin_memset (v.c, 0, 8); // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" "pr?????" { xfail *-*-* } }
|
||||
sink (&v);
|
||||
}
|
Loading…
Add table
Reference in a new issue