// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -fms-extensions -Wno-delete-incomplete %s
// expected-no-diagnostics
#define P(e) static_assert(noexcept(e), "expected nothrow")
#define N(e) static_assert(!noexcept(e), "expected throw")
#define B(b, e) static_assert(b == noexcept(e), "expectation failed")
void simple() {
P(0);
P(0 + 0);
int i;
P(i);
P(sizeof(0));
P(static_cast<int>(0));
N(throw 0);
N((throw 0, 0));
}
void nospec();
void allspec() throw(...);
void intspec() throw(int);
void emptyspec() throw();
void nothrowattr() __attribute__((nothrow));
void noexcept_true() noexcept;
void noexcept_false() noexcept(false);
void call() {
N(nospec());
N(allspec());
N(intspec());
P(emptyspec());
P(nothrowattr());
P(noexcept_true());
N(noexcept_false());
}
void (*pnospec)();
void (*pallspec)() throw(...);
void (*pintspec)() throw(int);
void (*pemptyspec)() throw();
typedef void (*funcptr)();
funcptr returnsptr() throw();
void callptr() {
N(pnospec());
N((*pnospec)());
N(pallspec());
N((*pallspec)());
N(pintspec());
N((*pintspec)());
P(pemptyspec());
P((*pemptyspec)());
N(returnsptr()());
}
struct S1 {
void nospec();
void allspec() throw(...);
void intspec() throw(int);
void emptyspec() throw();
};
void callmem() {
S1 s;
N(s.nospec());
N(s.allspec());
N(s.intspec());
P(s.emptyspec());
}
void (S1::*mpnospec)();
void (S1::*mpallspec)() throw(...);
void (S1::*mpintspec)() throw(int);
void (S1::*mpemptyspec)() throw();
void callmemptr() {
S1 s;
N((s.*mpnospec)());
N((s.*mpallspec)());
N((s.*mpintspec)());
P((s.*mpemptyspec)());
}
struct S2 {
S2();
S2(int, int) throw();
void operator +();
void operator -() throw();
void operator +(int);
void operator -(int) throw();
operator int();
operator float() throw();
};
void *operator new(__typeof__(sizeof(int)) sz, int) throw();
struct IncompleteStruct;
struct Bad1 {
~Bad1() throw(int);
};
struct Bad2 {
void operator delete(void*) throw(int);
};
typedef int X;
void implicits() {
N(new int);
P(new (0) int);
P(delete (int*)0);
P(delete (IncompleteStruct*)0);
N(delete (Bad1*)0);
N(delete (Bad2*)0);
N(S2());
P(S2(0, 0));
S2 s;
N(+s);
P(-s);
N(s + 0);
P(s - 0);
N(static_cast<int>(s));
P(static_cast<float>(s));
N(Bad1());
P(X().~X());
}
struct V {
virtual ~V() throw();
};
struct D : V {};
void dyncast() {
V *pv = 0;
D *pd = 0;
P(dynamic_cast<V&>(*pd));
P(dynamic_cast<V*>(pd));
N(dynamic_cast<D&>(*pv));
P(dynamic_cast<D*>(pv));
}
namespace std {
struct type_info {};
}
void idtype() {
P(typeid(V));
P(typeid((V*)0));
P(typeid(*(S1*)0));
N(typeid(*(V*)0));
}
void uneval() {
P(sizeof(typeid(*(V*)0)));
P(typeid(typeid(*(V*)0)));
}
struct G1 {};
struct G2 { int i; };
struct G3 { S2 s; };
void gencon() {
P(G1());
P(G2());
N(G3());
}
template <class T> void f(T&&) noexcept;
template <typename T, bool b>
void late() {
B(b, typeid(*(T*)0));
B(b, T(1));
B(b, static_cast<T>(S2(0, 0)));
B(b, S1() + T());
P(f(T()));
P(new (0) T);
P(delete (T*)0);
}
struct S3 {
virtual ~S3() throw();
S3() throw();
explicit S3(int);
S3(const S2&);
};
template <class T> T&& f2() noexcept;
template <typename T>
void late2() {
P(dynamic_cast<S3&>(f2<T&>()));
}
void operator +(const S1&, float) throw();
void operator +(const S1&, const S3&);
void tlate() {
late<float, true>();
late<S3, false>();
late2<S3>();
}