blob: 70d38712a032fb802620e8e36d25eb26bf8daf56 [file] [log] [blame]
// PR rtl-optimization/36419
// { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
// { dg-require-effective-target fpic }
// { dg-options "-Os -fasynchronous-unwind-tables -fpic -fno-inline" }
#include <stdarg.h>
extern "C" void abort ();
extern "C"
{
struct R { int r1; unsigned short r2[1]; };
int bar1 (unsigned short *, int, short) throw ();
void bar2 (R *) throw ();
void bar3 (R **, const unsigned short *, int) throw ();
void bar4 (R **, const char *) throw ();
void bar5 (void *, const char *, ...);
}
struct S
{
R *s;
struct T { };
S (R *x, T *) { s = x; }
~S () { bar2 (s); }
S &operator= (const S &x);
S &operator+= (const S &x);
S sfn1 (const S &x) const;
friend S operator+ (const S &x1, const S &x2);
static S sfn2 (int i)
{
unsigned short q[33];
R *p = 0;
bar3 (&p, q, bar1 (q, i, 10));
return S (p, (T *) 0);
}
static S sfn3 (const char *x)
{
R *p = 0;
bar4 (&p, x);
return S (p, (T *) 0);
}
};
struct U { };
template <class C> unsigned char operator >>= (const U &, C &);
struct V;
struct W
{
V *w;
unsigned char is () const;
};
template <class T> struct X : public W
{
inline ~X ();
X ();
X (const W &);
T *operator -> () const;
};
struct E
{
E ();
E (const S &, const X <V> &);
E (E const &);
~E ();
E &operator = (E const &);
};
struct V
{
virtual void release () throw ();
};
template <class T> X <T>::~X ()
{
if (w)
w->release ();
}
struct Y
{
virtual U yfn1 (const S &);
};
struct Z;
X <V> baz1 (const S &)
#if __cplusplus <= 201402L
throw (E) // { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
#endif
;
X <Z> baz2 (const X <Z> &)
#if __cplusplus <= 201402L
throw (E) // { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
#endif
;
template <typename T> X<T>::X ()
{
w = __null;
}
template <typename T> X<T>::X (W const &)
{
w = __null;
}
U Y::yfn1 (const S &)
{
throw 12;
}
Y y;
template <typename T> T *X<T>::operator -> () const
{
return &y;
}
X <V> baz1 (const S &)
#if __cplusplus <= 201402L
throw (E) // { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
#endif
{
return X<V> ();
}
E::E ()
{
}
E::~E ()
{
}
X <Z> baz2 (const X <Z> &)
#if __cplusplus <= 201402L
throw (E) // { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } }
#endif
{
throw E ();
}
int bar1 (unsigned short *, int, short) throw ()
{
asm volatile ("" : : : "memory");
return 0;
}
void bar2 (R *) throw ()
{
asm volatile ("" : : : "memory");
}
void bar3 (R **, const unsigned short *, int) throw ()
{
asm volatile ("" : : : "memory");
}
void bar4 (R **, const char *) throw ()
{
asm volatile ("" : : : "memory");
}
int events[2];
void *sp;
void bar5 (void *p, const char *s, ...)
{
va_list ap;
va_start (ap, s);
if (p)
throw 19;
switch (*s)
{
case 't':
if (events[0] != va_arg (ap, int))
abort ();
events[0]++;
break;
case 'f':
abort ();
case 'c':
if (events[1] != va_arg (ap, int))
abort ();
events[1]++;
if (events[1] == 1)
sp = va_arg (ap, void *);
else if (sp != va_arg (ap, void *))
abort ();
break;
}
}
unsigned char W::is () const
{
return 1;
}
S &S::operator += (const S &)
{
return *this;
}
template <class C> unsigned char operator >>= (const U &, C &)
{
throw 1;
}
template X<Y>::X ();
template X<Z>::X ();
template unsigned char operator >>= (const U &, X<Z> &);
template X<Y>::X (W const &);
template Y *X<Y>::operator-> () const;
X <Z> foo () throw ()
{
X <Z> a;
X <Y> b;
try
{
b = X <Y> (baz1 (S::sfn3 ("defg")));
}
catch (E &)
{
}
if (b.is ())
{
for (int n = 0; n < 10; n++)
{
S c = S::sfn3 ("abcd");
c += S::sfn2 (n);
X <Z> d;
try
{
bar5 ((void *) 0, "trying %d\n", n);
if ((b->yfn1 (c) >>= d))
if (d.is ())
{
bar5 ((void *) 0, "failure1 on %d\n", n);
a = baz2 (d);
if (a.is ())
break;
}
bar5 ((void *) 0, "failure2 on %d\n", n);
}
catch (...)
{
void *p;
asm volatile ("movl %%esp, %0" : "=r" (p));
bar5 ((void *) 0, "caught %d %p\n", n, p);
}
}
}
return a;
}
int
main ()
{
foo ();
if (events[0] != 10 || events[1] != 10)
abort ();
return 0;
}