1 // PR rtl-optimization/36419
2 // { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
3 // { dg-require-effective-target fpic }
4 // { dg-options "-Os -fasynchronous-unwind-tables -fpic -fno-inline" }
5 
6 #include <stdarg.h>
7 
8 extern "C" void abort ();
9 
10 extern "C"
11 {
12   struct R { int r1; unsigned short r2[1]; };
13   int bar1 (unsigned short *, int, short) throw ();
14   void bar2 (R *) throw ();
15   void bar3 (R **, const unsigned short *, int) throw ();
16   void bar4 (R **, const char *) throw ();
17   void bar5 (void *, const char *, ...);
18 }
19 
20 struct S
21 {
22   R *s;
23   struct T { };
SS24   S (R *x, T *) { s = x; }
~SS25   ~S () { bar2 (s); }
26   S &operator= (const S &x);
27   S &operator+= (const S &x);
28   S sfn1 (const S &x) const;
29   friend S operator+ (const S &x1, const S &x2);
sfn2S30   static S sfn2 (int i)
31   {
32     unsigned short q[33];
33     R *p = 0;
34     bar3 (&p, q, bar1 (q, i, 10));
35     return S (p, (T *) 0);
36   }
sfn3S37   static S sfn3 (const char *x)
38   {
39     R *p = 0;
40     bar4 (&p, x);
41     return S (p, (T *) 0);
42   }
43 };
44 
45 struct U { };
46 template <class C> unsigned char operator >>= (const U &, C &);
47 
48 struct V;
49 struct W
50 {
51   V *w;
52   unsigned char is () const;
53 };
54 
55 template <class T> struct X : public W
56 {
57   inline ~X ();
58   X ();
59   X (const W &);
60   T *operator -> () const;
61 };
62 
63 struct E
64 {
65   E ();
66   E (const S &, const X <V> &);
67   E (E const &);
68   ~E ();
69   E &operator = (E const &);
70 };
71 
72 struct V
73 {
74   virtual void release () throw ();
75 };
76 
~X()77 template <class T> X <T>::~X ()
78 {
79   if (w)
80     w->release ();
81 }
82 
83 struct Y
84 {
85   virtual U yfn1 (const S &);
86 };
87 
88 struct Z;
89 
90 X <V> baz1 (const S &) throw (E);
91 X <Z> baz2 (const X <Z> &) throw (E);
92 
X()93 template <typename T> X<T>::X ()
94 {
95   w = __null;
96 }
97 
X(W const &)98 template <typename T> X<T>::X (W const &)
99 {
100   w = __null;
101 }
102 
yfn1(const S &)103 U Y::yfn1 (const S &)
104 {
105   throw 12;
106 }
107 
108 Y y;
109 
110 template <typename T> T *X<T>::operator -> () const
111 {
112   return &y;
113 }
114 
baz1(const S &)115 X <V> baz1 (const S &) throw (E)
116 {
117   return X<V> ();
118 }
119 
E()120 E::E ()
121 {
122 }
123 
~E()124 E::~E ()
125 {
126 }
127 
baz2(const X<Z> &)128 X <Z> baz2 (const X <Z> &) throw (E)
129 {
130   throw E ();
131 }
132 
bar1(unsigned short *,int,short)133 int bar1 (unsigned short *, int, short) throw ()
134 {
135   asm volatile ("" : : : "memory");
136   return 0;
137 }
138 
bar2(R *)139 void bar2 (R *) throw ()
140 {
141   asm volatile ("" : : : "memory");
142 }
143 
bar3(R **,const unsigned short *,int)144 void bar3 (R **, const unsigned short *, int) throw ()
145 {
146   asm volatile ("" : : : "memory");
147 }
148 
bar4(R **,const char *)149 void bar4 (R **, const char *) throw ()
150 {
151   asm volatile ("" : : : "memory");
152 }
153 
154 int events[2];
155 void *sp;
156 
bar5(void * p,const char * s,...)157 void bar5 (void *p, const char *s, ...)
158 {
159   va_list ap;
160   va_start (ap, s);
161   if (p)
162     throw 19;
163   switch (*s)
164     {
165     case 't':
166       if (events[0] != va_arg (ap, int))
167 	abort ();
168       events[0]++;
169       break;
170     case 'f':
171       abort ();
172     case 'c':
173       if (events[1] != va_arg (ap, int))
174 	abort ();
175       events[1]++;
176       if (events[1] == 1)
177 	sp = va_arg (ap, void *);
178       else if (sp != va_arg (ap, void *))
179 	abort ();
180       break;
181     }
182 }
183 
is()184 unsigned char W::is () const
185 {
186   return 1;
187 }
188 
189 S &S::operator += (const S &)
190 {
191   return *this;
192 }
193 
194 template <class C> unsigned char operator >>= (const U &, C &)
195 {
196   throw 1;
197 }
198 
199 template X<Y>::X ();
200 template X<Z>::X ();
201 template unsigned char operator >>= (const U &, X<Z> &);
202 template X<Y>::X (W const &);
203 
204 template Y *X<Y>::operator-> () const;
205 
foo()206 X <Z> foo () throw ()
207 {
208   X <Z> a;
209   X <Y> b;
210   try
211   {
212     b = X <Y> (baz1 (S::sfn3 ("defg")));
213   }
214   catch (E &)
215   {
216   }
217   if (b.is ())
218     {
219       for (int n = 0; n < 10; n++)
220 	{
221 	  S c = S::sfn3 ("abcd");
222 	  c += S::sfn2 (n);
223 	  X <Z> d;
224 	  try
225 	  {
226 	    bar5 ((void *) 0, "trying %d\n", n);
227 	    if ((b->yfn1 (c) >>= d))
228 	      if (d.is ())
229 		{
230 		  bar5 ((void *) 0, "failure1 on %d\n", n);
231 		  a = baz2 (d);
232 		  if (a.is ())
233 		    break;
234 		}
235 	      bar5 ((void *) 0, "failure2 on %d\n", n);
236 	  }
237 	  catch (...)
238 	  {
239 	    void *p;
240 	    asm volatile ("movl %%esp, %0" : "=r" (p));
241 	    bar5 ((void *) 0, "caught %d %p\n", n, p);
242 	  }
243 	}
244     }
245   return a;
246 }
247 
248 int
main()249 main ()
250 {
251   foo ();
252   if (events[0] != 10 || events[1] != 10)
253     abort ();
254   return 0;
255 }
256