1 // PR middle-end/6247
2 // This testcase was miscompiled on IA-32 because a single stack slot
3 // was used for 2 different variables at the same time.
4 // The function H::h1 was miscompiled.
5 // { dg-do run }
6 // { dg-options "-O2" }
7 
8 extern "C" void abort (void);
9 extern "C" void exit (int);
10 
11 struct A
12 {
AA13   A () { a = 1; }
a1A14   void a1 () { a++; }
a2A15   bool a2 () { return !--a; }
16   unsigned int a;
17 };
18 
19 struct B : public A
20 {
BB21   B () : b (0) { a1 (); }
22   void b1 ();
23   const char *b;
24 };
25 
26 struct C
27 {
28   C ();
29   C (const C &);
~CC30   ~C () { if (c->a2 ()) { if (c == c0) c0 = 0; c->b1 (); } }
31   C &operator= (const C &);
32   static C c1 (const char *x, int y = -1);
33   C (int, bool);
34   void a2 ();
35   B *c;
36   static B *c0;
37 };
38 
39 B *C::c0 = __null;
40 
41 template <class T> struct D
42 {
DD43   D (const T& t) : d (t) {}
DD44   D () {}
45   D<T> *next, *prev;
46   T d;
47 };
48 
49 template<class T> struct E
50 {
51   D<T> *e;
EE52   E () : e (0) {}
EE53   E (D<T> *p) : e (p) {}
EE54   E (const E<T>& x) : e (x.e) {}
55   const T& operator* () const { return e->d; }
56   T& operator* () { return e->d; }
57   bool operator== (const E<T>& x) const { return e == x.e; }
58   bool operator!= (const E<T>& x) const { return e != x.e; }
59   E<T> operator++ (int) { E<T> x = *this; e = e->next; return x; }
60 };
61 
62 template <class T> struct F : public A
63 {
FF64   F () { f = new D<T>; f->next = f->prev = f; f0 = 0; }
~FF65   ~F () {}
66   D<T> *f;
67   unsigned int f0;
68 
FF69   F (const F<T>& x) : A ()
70   {
71     f = new D<T>; f->next = f->prev = f; f0 = 0;
72     E<T> b (x.f->next);
73     E<T> e (x.f);
74     E<T> i (f);
75     while (b != e)
76       f1 (i, *b++);
77   }
78 
f1F79   E<T> f1 (E<T> x, const T& y)
80   {
81     D<T> *p = new D<T> (y);
82     p->next = x.e;
83     p->prev = x.e->prev;
84     x.e->prev->next = p;
85     x.e->prev = p;
86     f0++;
87     return p;
88   }
89 };
90 
91 template <class T> struct G
92 {
g1G93   E<T> g1 () { g3 (); return E<T> (g->f); }
g2G94   E<T> g2 (const T& x) { g3 (); return g->f1 (g1 (), x); }
g3G95   void g3 () { if (g->a > 1) { g->a2 (); g = new F<T> (*g); } }
96   F<T>* g;
97 };
98 
99 struct H
100 {
~HH101   virtual ~H () {};
102   virtual void h1 ();
103   struct I
104   {
IH::I105     I () {}
IH::I106     I (C r, C p) : i1 (r), i2 (p) {}
107     C i1, i2;
108   };
109   G<I> h;
110 };
111 
h1()112 void H::h1 ()
113 {
114   h.g2 (I (C::c1 ("s1"), C::c1 ("t")));
115   h.g2 (I (C::c1 ("s2"), C::c1 ("t")));
116   h.g2 (I (C::c1 ("s3"), C::c1 ("t")));
117 }
118 
b1()119 void B::b1 ()
120 {
121 }
122 
c1(const char * x,int y)123 C C::c1 (const char *x, int y)
124 {
125   C z;
126 
127   if (y != -1)
128     abort ();
129   z.c = new B;
130   z.c->b = x;
131   return z;
132 }
133 
C()134 C::C () : c (__null)
135 {
136 }
137 
C(const C & x)138 C::C (const C &x)
139 {
140   c = x.c;
141   c->a1 ();
142 }
143 
main()144 int main ()
145 {
146   H h;
147   h.h.g = new F<H::I> ();
148   h.h1 ();
149   if (h.h.g->f0 != 3)
150     abort ();
151   D<H::I> *p;
152   int i;
153   for (i = 0, p = h.h.g->f; i < 4; i++, p = p->next)
154     {
155       if (i == 0 && (p->d.i1.c != __null || p->d.i2.c != __null))
156 	abort ();
157       if (i > 0
158 	  && (p->d.i1.c->b[0] != 's'
159 	      || p->d.i1.c->b[1] != '0' + i
160 	      || p->d.i1.c->b[2] != '\0'
161 	      || __builtin_strcmp (p->d.i2.c->b, "t")))
162 	abort ();
163       if (p->prev->next != p)
164 	abort ();
165       if (p->next->prev != p)
166 	abort ();
167       if (i == 3 && p->next != h.h.g->f)
168 	abort ();
169     }
170   exit (0);
171 }
172