1/* { dg-do run } */
2
3/* Testcase distilled from glibc's nss_parse_service_list in nss/nsswitch.c
4   It can't be distilled further.  Fails with `-O2' for i[3456]86.  */
5
6/* this simulates a bounded-pointer type.  */
7struct ucharp { unsigned char *v, *l, *h; };
8
9/* this simulates bounded-pointer check prior to pointer dereference.  */
10#define AREF(var, idx) ((((((((var).v+(idx)) < (var).l) \
11			   || (((var).v+(idx)+1) > (var).h))) \
12			  && (__builtin_trap (), 0)), \
13			 (var).v)[(idx)])
14
15struct list
16{
17  struct list *next;
18};
19
20struct list *
21alloc_list (void)
22{
23  static struct list l;
24  return &l;
25}
26
27int one = 1;
28
29void
30foo (struct ucharp cp, struct ucharp lp, struct list **nextp)
31{
32  while (1)
33    {
34      struct list *list;
35      while (AREF (lp, 0) && AREF (cp, AREF (lp, 0)))
36        ++lp.v;
37      list = alloc_list ();
38      while (AREF (cp, AREF (lp, 0)))
39        ++lp.v;
40      if (AREF (lp, 0) == one)
41	do
42	  ++lp.v;
43	while (AREF (lp, 0) && AREF (cp, AREF (lp, 0)));
44      /* The above AREF (cp, ...) fails because the pseudo created to
45	 hold cp.v holds garbage, having never been set.
46	 The easiest way to see the problem is to compile wiht `-O2 -da'
47	 then look at *.09.loop.  Search for something like this:
48
49	 Hoisted regno 183 r/o from (mem/s:SI (reg:SI 16 argp) 10)
50	   Replaced reg 91, deleting init_insn (213).
51
52	 Now, look for the use of reg 91, which has no set.  */
53
54      *nextp = list;
55      nextp = &list->next;
56      if (!*lp.v)
57	break;
58    }
59}
60
61extern void exit (int);
62
63int
64main (void)
65{
66  static unsigned char cp0[] = "\0\0\0\0";
67  struct ucharp cp = { cp0, cp0, cp0 + sizeof (cp0) };
68
69  static unsigned char lp0[] = "\1\1\0\0";
70  struct ucharp lp = { lp0, lp0, lp0 + sizeof (lp0) };
71
72  struct list list;
73  struct list *nextp = &list;
74
75  foo (cp, lp, &nextp);
76
77  exit (0);
78}
79