Extend the offset and size of merged object references [PR103215].

Resolves:
PR tree-optimization/103215 - bogus -Warray-bounds with two pointers with different offsets each

gcc/ChangeLog:

	PR tree-optimization/103215
	* pointer-query.cc (access_ref::merge_ref): Extend the offset and
	size of the merged object instead of using the larger.

gcc/testsuite/ChangeLog:

	PR tree-optimization/103215
	* gcc.dg/Wstringop-overflow-58.c: Adjust and xfail expected warnings.
	* gcc.dg/Wstringop-overflow-59.c: Same.
	* gcc.dg/warn-strnlen-no-nul.c: Same.
	* gcc.dg/Warray-bounds-91.c: New test.
	* gcc.dg/Warray-bounds-92.c: New test.
	* gcc.dg/Wstringop-overflow-85.c: New test.
	* gcc.dg/Wstringop-overflow-87.c: New test.
This commit is contained in:
Martin Sebor 2021-12-09 12:49:28 -07:00
parent 9eeca99ccc
commit 243a980437
8 changed files with 663 additions and 45 deletions

View file

@ -688,27 +688,32 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
if (known_size && aref.sizrng[0] < minsize)
minsize = aref.sizrng[0];
/* Determine the amount of remaining space in the argument. */
offset_int argrem[2];
argrem[1] = aref.size_remaining (argrem);
/* Extend the size and offset of *THIS to account for AREF. The result
can be cached but results in false negatives. */
/* Determine the amount of remaining space computed so far and
if the remaining space in the argument is more use it instead. */
offset_int merged_rem[2];
merged_rem[1] = size_remaining (merged_rem);
offset_int orng[2];
if (sizrng[1] < aref.sizrng[1])
{
orng[0] = offrng[0];
orng[1] = offrng[1];
*this = aref;
}
else
{
orng[0] = aref.offrng[0];
orng[1] = aref.offrng[1];
}
if (orng[0] < offrng[0])
offrng[0] = orng[0];
if (offrng[1] < orng[1])
offrng[1] = orng[1];
/* Reset the PHI's BASE0 flag if any of the nonnull arguments
refers to an object at an unknown offset. */
if (!aref.base0)
base0 = false;
if (merged_rem[1] < argrem[1]
|| (merged_rem[1] == argrem[1]
&& sizrng[1] < aref.sizrng[1]))
/* Use the argument with the most space remaining as the result,
or the larger one if the space is equal. */
*this = aref;
sizrng[0] = minsize;
parmarray = merged_parmarray;

View file

@ -0,0 +1,145 @@
/* PR middle-end/103215 - bogus -Warray-bounds with two pointers with
different offsets each
Test for accesses into the same array through pointers with different
offsets each.
{ dg-do compile }
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
#define NOIPA __attribute__ ((noipa))
#define A(p, off) ((p)[off] = __COUNTER__)
extern int a4[4];
NOIPA void p0_p1 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *q = i ? p0 : p1;
A (q, -2); // { dg-warning "-Warray-bounds" }
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
/* Since q points to a4 and -1 is a valid subscript, +3 must be invalid.
But the warning for each subscript is independent of prior subscripts
into the same object. That should be improved. */
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" }
}
NOIPA void p1_p0 (int i)
{
int *p1 = a4 + 1;
int *p0 = a4 + 0;
int *q = i ? p0 : p1;
A (q, -2); // { dg-warning "-Warray-bounds" }
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" }
}
NOIPA void p1_p2 (int i)
{
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *q = i ? p1 : p2;
A (q, -3); // { dg-warning "-Warray-bounds" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p2_p1 (int i)
{
int *p2 = a4 + 2;
int *p1 = a4 + 1;
int *q = i ? p1 : p2;
A (q, -3); // { dg-warning "-Warray-bounds" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p1_p3 (int i)
{
int *p1 = a4 + 1;
int *p3 = a4 + 3;
int *q = i ? p1 : p3;
A (q, -4); // { dg-warning "-Warray-bounds" }
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p3_p1 (int i)
{
int *p3 = a4 + 3;
int *p1 = a4 + 1;
int *q = i ? p1 : p3;
A (q, -4); // { dg-warning "-Warray-bounds" }
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p1_p4 (int i)
{
int *p1 = a4 + 1;
int *p4 = a4 + 4;
int *q = i ? p1 : p4;
A (q, -5); // { dg-warning "-Warray-bounds" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p4_p1 (int i)
{
int *p4 = a4 + 4;
int *p1 = a4 + 1;
int *q = i ? p1 : p4;
A (q, -5); // { dg-warning "-Warray-bounds" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" }
}
NOIPA void p0_p1_p2 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *q = i < 0 ? p1 : 0 < i ? p2 : p0;
A (q, -3); // { dg-warning "-Warray-bounds" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" }
}
NOIPA void p0_p1_p2_p3_p4 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *p3 = a4 + 3;
int *p4 = a4 + 4;
int *q = i < -1 ? p1 : i < 0 ? p2 : 1 < i ? p4 : 0 < i ? p3 : p0;
A (q, -5); // { dg-warning "-Warray-bounds" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" }
}

View file

@ -0,0 +1,149 @@
/* PR middle-end/103215 - bogus -Warray-bounds with two pointers with
different offsets each
Test for accesses into distinct arrays through pointers with different
offsets each.
If/when -Warray-bounds is enhanced to issue "maybe" kinds of warnings
some of the accesses here will trigger those and will need updating.
{ dg-do compile }
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
#define NOIPA __attribute__ ((noipa))
#define A(p, off) ((p)[off] = __COUNTER__)
extern int a4[4], a8[8];
NOIPA void a4_p1_a8_p3 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p3 = a8 + 3;
int *q = i ? a4_p1 : a8_p3;
A (q, -4); // { dg-warning "-Warray-bounds" }
/* Because -3 is a valid offset into a8 but not a4, q must point
to the former and so subscripts between -3 and +4 refer to its
elements. */
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); A (q, 2); A (q, 3); A (q, 4);
A (q, 5); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
/* Both of the following are definitely out of bounds but the first isn't
diagnosed because the code conservatively merges the offsets into A4
and A8. */
A (q, 7); // { dg-warning "-Warray-bounds" }
}
NOIPA void a4_p1_a8_p5 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p5 = a8 + 5;
int *q = i ? a4_p1 : a8_p5;
A (q, -6); // { dg-warning "-Warray-bounds" }
/* Similarly to the above, because -5 is a valid offset into a8 but
not a4, q must point to the former and so subscripts between -5
and +2 refer to its elements. */
A (q, -5); A (q, -4); A (q, -3); A (q, -2);
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Warray-bounds" }
}
NOIPA void a4_p1_a8_p7 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p7 = a8 + 7;
int *q = i ? a4_p1 : a8_p7;
A (q, -8); // { dg-warning "-Warray-bounds" }
A (q, -7); A (q, -6); A (q, -5); A (q, -4);
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
/* Since -7 is valid, q must point to a8 and the last valid subscript
must be 0. */
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Warray-bounds" }
}
NOIPA void mp_1_a4_p1_a8_p7 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p7 = a8 + 7;
int *p = i ? a4_p1 : a8_p7;
int *q = j ? p + 1 : p - 1;
A (q, -9); // { dg-warning "-Warray-bounds" }
/* q points either to a8 + [6, 8] or a4 + [0, 2]. */
A (q, -8); A (q, -7); A (q, -6); A (q, -5);
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
/* Since all the above are valid, q must point to a8 + 8. But as
mentioned above, the warning for each subscript is independent
of prior subscripts into the same object so the access below
aren't diagnosed. */
A (q, 0); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Warray-bounds" }
}
NOIPA void mp1_a4_p1_a8_p5 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p5 = a8 + 5;
int *p = i ? a4_p1 : a8_p5;
int *q = j ? p + 1 : p - 1;
// q is assumed to point to a8 + 6
A (q, -7); // { dg-warning "-Warray-bounds" }
A (q, -6); A (q, -5); A (q, -4); A (q, -3);
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
/* Even though the above accesses rule it out, q is now assumed
to point to either a4 + [0, 2] or a8 + [4, 5]. */
A (q, 2);
/* q is now assumed to point tp a4. Given that, only the first store
is valid. */
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 5); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 6); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Warray-bounds" }
}
NOIPA void mp1_a4_p1_a8_p4 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p4 = a8 + 4;
int *p = i ? a4_p1 : a8_p4;
int *q = j ? p + 1 : p - 1;
// q is assumed to point to a8 + 5
A (q, -6); // { dg-warning "-Warray-bounds" }
A (q, -5);
A (q, -4);
A (q, -3);
A (q, -2);
A (q, -1);
A (q, 0);
A (q, 1);
A (q, 2);
/* Even though the above accesses rule it out, q is now assumed
to point tp a4. Given that, only the first store is valid. */
A (q, 3); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 5); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 6); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Warray-bounds" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Warray-bounds" }
}

View file

@ -182,8 +182,8 @@ void memset_decl_2_off (void)
int i2 = SR (2, INT_MAX);
{
char a5[5]; // { dg-warning "at offset [1, 5] into destination object 'a5'
char a7[7]; // { dg-warning "at offset [2, 7] into destination object 'a7'
char a5[5]; // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" }
char a7[7]; // { dg-message "at offset \\\[2, 7] into destination object 'a7'" "note" }
char *p5_p1 = a5 + i1;
char *p7_p2 = a7 + i2;
char *p5_7 = cond1 ? p5_p1 : p7_p2;
@ -193,7 +193,11 @@ void memset_decl_2_off (void)
memset (p5_7, 0, 3);
memset (p5_7, 0, 4);
memset (p5_7, 0, 5);
memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
/* The warning code conservatively "merges" both the sizes and the offsets
into A5 and A7 and so only the second store below is diagnosed but not
the first. See PR 103215. The logic needs to be tightened up. */
memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " "pr??????" { xfail *-*-* } }
memset (p5_7, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6 " }
}
int i3 = SR (3, INT_MAX);
@ -208,7 +212,8 @@ void memset_decl_2_off (void)
// { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
// { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
// { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
// { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
// { dg-message "at offset \\\[1, 9] into destination object 'a9'" "note" { target *-*-* } .-4 }
// { dg-message ": destination object 'a9'" "pr??????" { xfail *-*-* } .-5 }
char *p5_p2 = a5 + i2; // 3 bytes left
char *p9_p3 = a9 + i3; // 6 bytes left
char *p =
@ -220,7 +225,8 @@ void memset_decl_2_off (void)
memset (q, 0, 3);
memset (q, 0, 4);
memset (q, 0, 5);
memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" }
memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" "pr??????" { xfail *-*-* } }
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
--q; // [3 - 6] bytes left
memset (q, 0, 1);
@ -229,7 +235,8 @@ void memset_decl_2_off (void)
memset (q, 0, 4);
memset (q, 0, 5);
memset (q, 0, 6);
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" "pr??????" { xfail *-*-* } }
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
--q; // [4 - 7] bytes left
memset (q, 0, 1);
@ -239,7 +246,8 @@ void memset_decl_2_off (void)
memset (q, 0, 5);
memset (q, 0, 6);
memset (q, 0, 7);
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" "pr??????" { xfail *-*-* } }
memset (q, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 8" }
int m1_x = SR (-1, INT_MAX);
int m2_x = SR (-2, INT_MAX);

View file

@ -200,7 +200,11 @@ void memset_malloc_2_off (void)
memset (p5_7, 0, 3);
memset (p5_7, 0, 4);
memset (p5_7, 0, 5);
memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
/* The warning code conservatively "merges" both the sizes and the offsets
into A5 and A7 and so only the second store below is diagnosed but not
the first. See PR 103215. The logic needs to be tightened up. */
memset (p5_7, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5 " "pr??????" { xfail *-*-* } }
memset (p5_7, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6 " }
}
int i3 = SR (3, INT_MAX);
@ -215,7 +219,8 @@ void memset_malloc_2_off (void)
// { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
// { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
// { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
// { dg-message ": destination object 'a9'" "note" { target *-*-* } .-4 }
// { dg-message "at offset \\\[1, 9] into destination object 'a9'" "note" { target *-*-* } .-4 }
// { dg-message ": destination object 'a9'" "pr??????" { xfail *-*-* } .-5 }
char *p5_p2 = a5 + i2; // 3 bytes left
char *p9_p3 = a9 + i3; // 6 bytes left
char *p =
@ -227,7 +232,8 @@ void memset_malloc_2_off (void)
memset (q, 0, 3);
memset (q, 0, 4);
memset (q, 0, 5);
memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" }
memset (q, 0, 6); // { dg-warning "memset' writing 6 bytes into a region of size 5" "pr??????" { xfail *-*-* } }
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
--q; // [3 - 6] bytes left
memset (q, 0, 1);
@ -236,7 +242,8 @@ void memset_malloc_2_off (void)
memset (q, 0, 4);
memset (q, 0, 5);
memset (q, 0, 6);
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" }
memset (q, 0, 7); // { dg-warning "memset' writing 7 bytes into a region of size 6" "pr??????" { xfail *-*-* } }
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
--q; // [4 - 7] bytes left
memset (q, 0, 1);
@ -246,7 +253,8 @@ void memset_malloc_2_off (void)
memset (q, 0, 5);
memset (q, 0, 6);
memset (q, 0, 7);
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" }
memset (q, 0, 8); // { dg-warning "memset' writing 8 bytes into a region of size 7" "pr??????" { xfail *-*-* } }
memset (q, 0, 9); // { dg-warning "memset' writing 9 bytes into a region of size 8" }
int m1_x = SR (-1, INT_MAX);
int m2_x = SR (-2, INT_MAX);

View file

@ -0,0 +1,153 @@
/* PR middle-end/103215 - bogus -Wstringop-overflow with two pointers with
different offsets each
Test for accesses into distinct arrays through pointers with different
offsets each.
If/when -Wstringop-overflow is enhanced to issue "maybe" kinds of
warnings some of the accesses here will trigger those and will need
updating.
{ dg-do compile }
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
#define NOIPA __attribute__ ((noipa))
void sink (int[1]);
#define A(p, off) sink (p + off)
extern int a4[4], a8[8];
NOIPA void a4_p1_a8_p3 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p3 = a8 + 3;
int *q = i ? a4_p1 : a8_p3;
A (q, -4); // { dg-warning "-Wstringop-overflow" }
/* Because -3 is a valid offset into a8 but not a4, q must point
to the former and so subscripts between -3 and +4 refer to its
elements. */
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); A (q, 2); A (q, 3); A (q, 4);
A (q, 5); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
/* Both of the following are definitely out of bounds but the first isn't
diagnosed because the code conservatively merges the offsets into A4
and A8. */
A (q, 7); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void a4_p1_a8_p5 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p5 = a8 + 5;
int *q = i ? a4_p1 : a8_p5;
A (q, -6); // { dg-warning "-Wstringop-overflow" }
/* Similarly to the above, because -5 is a valid offset into a8 but
not a4, q must point to the former and so subscripts between -5
and +2 refer to its elements. */
A (q, -5); A (q, -4); A (q, -3); A (q, -2);
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void a4_p1_a8_p7 (int i)
{
int *a4_p1 = a4 + 1;
int *a8_p7 = a8 + 7;
int *q = i ? a4_p1 : a8_p7;
A (q, -8); // { dg-warning "-Wstringop-overflow" }
A (q, -7); A (q, -6); A (q, -5); A (q, -4);
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
/* Since -7 is valid, q must point to a8 and the last valid subscript
must be 0. */
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void mp_1_a4_p1_a8_p7 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p7 = a8 + 7;
int *p = i ? a4_p1 : a8_p7;
int *q = j ? p + 1 : p - 1;
A (q, -9); // { dg-warning "-Wstringop-overflow" }
/* q points either to a8 + [6, 8] or a4 + [0, 2]. */
A (q, -8); A (q, -7); A (q, -6); A (q, -5);
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
/* Since all the above are valid, q must point to a8 + 8. But as
mentioned above, the warning for each subscript is independent
of prior subscripts into the same object so the access below
aren't diagnosed. */
A (q, 0); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void mp1_a4_p1_a8_p5 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p5 = a8 + 5;
int *p = i ? a4_p1 : a8_p5;
int *q = j ? p + 1 : p - 1;
// q is assumed to point to a8 + 6
A (q, -7); // { dg-warning "-Wstringop-overflow" }
A (q, -6); A (q, -5); A (q, -4); A (q, -3);
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
/* Even though the above accesses rule it out, q is now assumed
to point to either a4 + [0, 2] or a8 + [4, 5]. */
A (q, 2);
/* q is now assumed to point tp a4. Given that, only the first store
is valid. */
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 5); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 6); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void mp1_a4_p1_a8_p4 (int i, int j)
{
int *a4_p1 = a4 + 1;
int *a8_p4 = a8 + 4;
int *p = i ? a4_p1 : a8_p4;
int *q = j ? p + 1 : p - 1;
// q is assumed to point to a8 + 5
A (q, -6); // { dg-warning "-Wstringop-overflow" }
A (q, -5);
A (q, -4);
A (q, -3);
A (q, -2);
A (q, -1);
A (q, 0);
A (q, 1);
A (q, 2);
/* Even though the above accesses rule it out, q is now assumed
to point tp a4. Given that, only the first store is valid. */
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 5); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 6); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 7); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 8); // { dg-warning "-Wstringop-overflow" }
}

View file

@ -0,0 +1,147 @@
/* PR middle-end/103215 - bogus -Warray-bounds with two pointers with
different offsets each
Test for accesses by a user-defined function into the same array
through pointers with different offsets each. See Warray-bounds-91.c
for the corresponding test exercising -Warray-bounds for direct accesses.
{ dg-do compile }
{ dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
#define NOIPA __attribute__ ((noipa))
void sink (int[1]);
#define A(p, off) sink (p + off)
extern int a4[4];
NOIPA void p0_p1 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *q = i ? p0 : p1;
A (q, -2); // { dg-warning "-Wstringop-overflow" }
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
/* Since q points to a4 and -1 is a valid subscript, +3 must be invalid.
But the warning for each subscript is independent of prior subscripts
into the same object. That should be improved. */
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p1_p0 (int i)
{
int *p1 = a4 + 1;
int *p0 = a4 + 0;
int *q = i ? p0 : p1;
A (q, -2); // { dg-warning "-Wstringop-overflow" }
A (q, -1); A (q, 0); A (q, 1); A (q, 2);
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p1_p2 (int i)
{
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *q = i ? p1 : p2;
A (q, -3); // { dg-warning "-Wstringop-overflow" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p2_p1 (int i)
{
int *p2 = a4 + 2;
int *p1 = a4 + 1;
int *q = i ? p1 : p2;
A (q, -3); // { dg-warning "-Wstringop-overflow" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p1_p3 (int i)
{
int *p1 = a4 + 1;
int *p3 = a4 + 3;
int *q = i ? p1 : p3;
A (q, -4); // { dg-warning "-Wstringop-overflow" }
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p3_p1 (int i)
{
int *p3 = a4 + 3;
int *p1 = a4 + 1;
int *q = i ? p1 : p3;
A (q, -4); // { dg-warning "-Wstringop-overflow" }
A (q, -3); A (q, -2); A (q, -1); A (q, 0);
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p1_p4 (int i)
{
int *p1 = a4 + 1;
int *p4 = a4 + 4;
int *q = i ? p1 : p4;
A (q, -5); // { dg-warning "-Wstringop-overflow" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p4_p1 (int i)
{
int *p4 = a4 + 4;
int *p1 = a4 + 1;
int *q = i ? p1 : p4;
A (q, -5); // { dg-warning "-Wstringop-overflow" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p0_p1_p2 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *q = i < 0 ? p1 : 0 < i ? p2 : p0;
A (q, -3); // { dg-warning "-Wstringop-overflow" }
A (q, -2); A (q, -1); A (q, 0); A (q, 1);
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" }
}
NOIPA void p0_p1_p2_p3_p4 (int i)
{
int *p0 = a4 + 0;
int *p1 = a4 + 1;
int *p2 = a4 + 2;
int *p3 = a4 + 3;
int *p4 = a4 + 4;
int *q = i < -1 ? p1 : i < 0 ? p2 : 1 < i ? p4 : 0 < i ? p3 : p0;
A (q, -5); // { dg-warning "-Wstringop-overflow" }
A (q, -4); A (q, -3); A (q, -2); A (q, -1);
A (q, 0); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 1); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 2); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 3); // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
A (q, 4); // { dg-warning "-Wstringop-overflow" }
}

View file

@ -143,17 +143,18 @@ T (v0 ? b[1] : "", bsz);
T (v0 ? b[2] : "", bsz);
T (v0 ? b[3] : "", bsz);
/* The warnings below are strictly correct but the strnlen calls are safe
because the reads are bounded by the length of the constant arguments.
It might make sense to relax the warning to avoid triggering for them. */
/* Warning for the calls below would be strictly correct even though
the strnlen calls are safe because the reads are bounded by
the length of the constant arguments. Most of the calls are
not diagnosed anymore as a result of the fix for PR 103215. */
T (v0 ? "" : b[0], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "" : b[1], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "" : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "" : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "" : b[1], bsz + 1);
T (v0 ? "" : b[2], bsz + 1);
T (v0 ? "" : b[3], bsz + 1);
T (v0 ? b[0] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[1] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[2] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[3] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[1] : "", bsz + 1);
T (v0 ? b[2] : "", bsz + 1);
T (v0 ? b[3] : "", bsz + 1);
T (v0 ? "" : b[i0], bsz);
T (v0 ? "" : b[i1], bsz);
@ -167,11 +168,11 @@ T (v0 ? b[i3] : "", bsz);
T (v0 ? "" : b[i0], bsz + 1);
T (v0 ? "" : b[i1], bsz + 1);
T (v0 ? "" : b[i2], bsz + 1);
T (v0 ? "" : b[i3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr86937" } */
T (v0 ? "" : b[i3], bsz + 1);
T (v0 ? b[i0] : "", bsz + 1);
T (v0 ? b[i1] : "", bsz + 1);
T (v0 ? b[i2] : "", bsz + 1);
T (v0 ? b[i3] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr86937" } */
T (v0 ? b[i3] : "", bsz + 1);
T (v0 ? "1234" : b[3], bsz);
T (v0 ? "1234" : b[i3], bsz);
@ -183,15 +184,17 @@ T (v0 ? b[0] : b[2], bsz);
T (v0 ? b[2] : b[3], bsz);
T (v0 ? b[3] : b[2], bsz);
T (v0 ? "1234" : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "1234" : b[i3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[3] : "1234", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[i3] : "1234", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? "1234" : b[3], bsz + 1);
T (v0 ? "1234" : b[i3], bsz + 1);
T (v0 ? b[3] : "1234", bsz + 1);
T (v0 ? b[i3] : "1234", bsz + 1);
T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */
/* That the following are not diagnosed is a bug/limitation resulting from
the fix for PR 103215. */
T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr103215" { xfail *-*-* } } */
T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr103215" { xfail *-*-* } } */
T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr103215" { xfail *-*-* } } */
T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr103215" { xfail *-*-* } } */
struct A { char a[5], b[5]; };