diff options
Diffstat (limited to 'gcc/testsuite/gcc.dg/20000906-1.c')
-rw-r--r-- | gcc/testsuite/gcc.dg/20000906-1.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/20000906-1.c b/gcc/testsuite/gcc.dg/20000906-1.c new file mode 100644 index 000000000..90d09d4db --- /dev/null +++ b/gcc/testsuite/gcc.dg/20000906-1.c @@ -0,0 +1,78 @@ +/* { dg-do run } */ + +/* Testcase distilled from glibc's nss_parse_service_list in nss/nsswitch.c + It can't be distilled further. Fails with `-O2' for i[3456]86. */ + +/* this simulates a bounded-pointer type. */ +struct ucharp { unsigned char *v, *l, *h; }; + +/* this simulates bounded-pointer check prior to pointer dereference. */ +#define AREF(var, idx) ((((((((var).v+(idx)) < (var).l) \ + || (((var).v+(idx)+1) > (var).h))) \ + && (__builtin_trap (), 0)), \ + (var).v)[(idx)]) + +struct list +{ + struct list *next; +}; + +struct list * +alloc_list (void) +{ + static struct list l; + return &l; +} + +int one = 1; + +void +foo (struct ucharp cp, struct ucharp lp, struct list **nextp) +{ + while (1) + { + struct list *list; + while (AREF (lp, 0) && AREF (cp, AREF (lp, 0))) + ++lp.v; + list = alloc_list (); + while (AREF (cp, AREF (lp, 0))) + ++lp.v; + if (AREF (lp, 0) == one) + do + ++lp.v; + while (AREF (lp, 0) && AREF (cp, AREF (lp, 0))); + /* The above AREF (cp, ...) fails because the pseudo created to + hold cp.v holds garbage, having never been set. + The easiest way to see the problem is to compile wiht `-O2 -da' + then look at *.09.loop. Search for something like this: + + Hoisted regno 183 r/o from (mem/s:SI (reg:SI 16 argp) 10) + Replaced reg 91, deleting init_insn (213). + + Now, look for the use of reg 91, which has no set. */ + + *nextp = list; + nextp = &list->next; + if (!*lp.v) + break; + } +} + +extern void exit (int); + +int +main (void) +{ + static unsigned char cp0[] = "\0\0\0\0"; + struct ucharp cp = { cp0, cp0, cp0 + sizeof (cp0) }; + + static unsigned char lp0[] = "\1\1\0\0"; + struct ucharp lp = { lp0, lp0, lp0 + sizeof (lp0) }; + + struct list list; + struct list *nextp = &list; + + foo (cp, lp, &nextp); + + exit (0); +} |