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 &)
91 #if __cplusplus <= 201402L
92 throw (E)			// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
93 #endif
94 ;
95 X <Z> baz2 (const X <Z> &)
96 #if __cplusplus <= 201402L
97 throw (E)			// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
98 #endif
99 ;
100 
X()101 template <typename T> X<T>::X ()
102 {
103   w = __null;
104 }
105 
X(W const &)106 template <typename T> X<T>::X (W const &)
107 {
108   w = __null;
109 }
110 
yfn1(const S &)111 U Y::yfn1 (const S &)
112 {
113   throw 12;
114 }
115 
116 Y y;
117 
118 template <typename T> T *X<T>::operator -> () const
119 {
120   return &y;
121 }
122 
baz1(const S &)123 X <V> baz1 (const S &)
124 #if __cplusplus <= 201402L
125 throw (E)			// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
126 #endif
127 {
128   return X<V> ();
129 }
130 
E()131 E::E ()
132 {
133 }
134 
~E()135 E::~E ()
136 {
137 }
138 
baz2(const X<Z> &)139 X <Z> baz2 (const X <Z> &)
140 #if __cplusplus <= 201402L
141 throw (E)			// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
142 #endif
143 {
144   throw E ();
145 }
146 
bar1(unsigned short *,int,short)147 int bar1 (unsigned short *, int, short) throw ()
148 {
149   asm volatile ("" : : : "memory");
150   return 0;
151 }
152 
bar2(R *)153 void bar2 (R *) throw ()
154 {
155   asm volatile ("" : : : "memory");
156 }
157 
bar3(R **,const unsigned short *,int)158 void bar3 (R **, const unsigned short *, int) throw ()
159 {
160   asm volatile ("" : : : "memory");
161 }
162 
bar4(R **,const char *)163 void bar4 (R **, const char *) throw ()
164 {
165   asm volatile ("" : : : "memory");
166 }
167 
168 int events[2];
169 void *sp;
170 
bar5(void * p,const char * s,...)171 void bar5 (void *p, const char *s, ...)
172 {
173   va_list ap;
174   va_start (ap, s);
175   if (p)
176     throw 19;
177   switch (*s)
178     {
179     case 't':
180       if (events[0] != va_arg (ap, int))
181 	abort ();
182       events[0]++;
183       break;
184     case 'f':
185       abort ();
186     case 'c':
187       if (events[1] != va_arg (ap, int))
188 	abort ();
189       events[1]++;
190       if (events[1] == 1)
191 	sp = va_arg (ap, void *);
192       else if (sp != va_arg (ap, void *))
193 	abort ();
194       break;
195     }
196 }
197 
is()198 unsigned char W::is () const
199 {
200   return 1;
201 }
202 
203 S &S::operator += (const S &)
204 {
205   return *this;
206 }
207 
208 template <class C> unsigned char operator >>= (const U &, C &)
209 {
210   throw 1;
211 }
212 
213 template X<Y>::X ();
214 template X<Z>::X ();
215 template unsigned char operator >>= (const U &, X<Z> &);
216 template X<Y>::X (W const &);
217 
218 template Y *X<Y>::operator-> () const;
219 
foo()220 X <Z> foo () throw ()
221 {
222   X <Z> a;
223   X <Y> b;
224   try
225   {
226     b = X <Y> (baz1 (S::sfn3 ("defg")));
227   }
228   catch (E &)
229   {
230   }
231   if (b.is ())
232     {
233       for (int n = 0; n < 10; n++)
234 	{
235 	  S c = S::sfn3 ("abcd");
236 	  c += S::sfn2 (n);
237 	  X <Z> d;
238 	  try
239 	  {
240 	    bar5 ((void *) 0, "trying %d\n", n);
241 	    if ((b->yfn1 (c) >>= d))
242 	      if (d.is ())
243 		{
244 		  bar5 ((void *) 0, "failure1 on %d\n", n);
245 		  a = baz2 (d);
246 		  if (a.is ())
247 		    break;
248 		}
249 	      bar5 ((void *) 0, "failure2 on %d\n", n);
250 	  }
251 	  catch (...)
252 	  {
253 	    void *p;
254 	    asm volatile ("movl %%esp, %0" : "=r" (p));
255 	    bar5 ((void *) 0, "caught %d %p\n", n, p);
256 	  }
257 	}
258     }
259   return a;
260 }
261 
262 int
main()263 main ()
264 {
265   foo ();
266   if (events[0] != 10 || events[1] != 10)
267     abort ();
268   return 0;
269 }
270