/* { 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); }