blob: 7f222fa9bdb5b803fa10aefe72bc6db6425e0119 [file] [log] [blame]
/* Various examples of safe array access for which -Warray-bounds
shouldn't issue a warning at any optimization level
(PR tree-optimization/83510). */
/* { dg-options "-Warray-bounds" } */
/* This test is XFAILed because thread1 threads a switch statement
such that the various cases have been split into different
independent blocks. One of these blocks exposes an arr[i_27]
which is later propagated by VRP to be arr[10]. This is an
invalid access, but the array bounds code doesn't know it is an
unreachable path.
However, it is not until dom2 that we "know" that the value of the
switch index is such that the path to arr[10] is unreachable. For
that matter, it is not until dom3 that we remove the unreachable
path.
See:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83510
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83312
It's not until here that ranger "knows" that the path is
unreachable:
thread1
vrp1 <-- array bounds checking
dce2
stdarg
cdce
cselim
copyprop
ifcombine
mergephi3 <-- too late
*/
extern int get_flag (void);
unsigned int arr[10];
struct xyz {
unsigned int a0;
};
extern void wfm(struct xyz *, int, unsigned int);
static unsigned int f(struct xyz * ctx, unsigned int number)
{
switch (number) {
case 0x9:
return ctx->a0;
case 0xA: case 0xB:
case 0xC: case 0xD: case 0xE: case 0xF:
case 0x10: case 0x11: case 0x12: case 0x13:
return arr[number - 0xa];
}
return 0;
}
int g(struct xyz * ctx) {
int i;
for (i = 0; i < 10; i++) {
wfm(ctx, i, f(ctx, i));
}
return 0;
}
int g_signed(struct xyz * ctx) {
int i;
for (i = 0; i < 10; i++) {
wfm(ctx, i, f(ctx, i));
}
return 0;
}
void test_2 (struct xyz * ctx)
{
int i;
for (i = 0; i < 10; i++) {
if (get_flag ())
wfm(ctx, i, f(ctx, i));
}
}
void test_3 (struct xyz * ctx)
{
unsigned int i;
for (i = 0; i < 10; i++) {
switch (i) {
case 0x9:
wfm(ctx, i, ctx->a0);
break;
case 0xA: case 0xB:
case 0xC: case 0xD: case 0xE: case 0xF:
case 0x10: case 0x11: case 0x12: case 0x13:
if (get_flag ())
wfm(ctx, i, arr[i - 0xa]);
break;
}
}
}
void test_3_signed (struct xyz * ctx)
{
int i;
for (i = 0; i < 10; i++) {
switch (i) {
case 0x9:
wfm(ctx, i, ctx->a0);
break;
case 0xA: case 0xB:
case 0xC: case 0xD: case 0xE: case 0xF:
case 0x10: case 0x11: case 0x12: case 0x13:
if (get_flag ())
wfm(ctx, i, arr[i]);
break;
}
}
}
void test_4 (struct xyz * ctx)
{
unsigned int i, j;
for (i = 0; i < 10; i++) {
switch (i) {
case 0x9:
wfm(ctx, i, ctx->a0);
break;
case 0xA: case 0xB:
case 0xC: case 0xD: case 0xE: case 0xF:
case 0x10: case 0x11: case 0x12: case 0x13:
for (j = 0; j < 5; j++)
wfm(ctx, i, arr[i - 0xa]);
break;
}
}
}
void test_4_signed (struct xyz * ctx)
{
int i, j;
for (i = 0; i < 10; i++) {
switch (i) {
case 0x9:
wfm(ctx, i, ctx->a0);
break;
case 0xA: case 0xB:
case 0xC: case 0xD: case 0xE: case 0xF:
case 0x10: case 0x11: case 0x12: case 0x13:
for (j = 0; j < 5; j++)
wfm(ctx, i, arr[i]);
break;
}
}
}
void test_5 (struct xyz * ctx)
{
unsigned int i;
for (i = 10; i < 20; i++) {
wfm(ctx, i, arr[i - 10]);
}
}
void test_5_signed (struct xyz * ctx)
{
int i;
for (i = 10; i < 20; i++) {
wfm(ctx, i, arr[i - 10]);
}
}