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