1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -verify -std=c++11 %s
struct A { };
struct B { };
struct C { };
// Destructor
struct X0 {
virtual ~X0() throw(A); // expected-note{{overridden virtual function is here}}
};
struct X1 {
virtual ~X1() throw(B); // expected-note{{overridden virtual function is here}}
};
struct X2 : public X0, public X1 { }; // expected-error 2{{exception specification of overriding function is more lax than base version}}
// Copy-assignment operator.
struct CA0 {
CA0 &operator=(const CA0&) throw(A);
};
struct CA1 {
CA1 &operator=(const CA1&) throw(B);
};
struct CA2 : CA0, CA1 { };
void test_CA() {
CA2 &(CA2::*captr1)(const CA2&) throw(A, B) = &CA2::operator=;
CA2 &(CA2::*captr2)(const CA2&) throw(A, B, C) = &CA2::operator=;
CA2 &(CA2::*captr3)(const CA2&) throw(A) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}}
CA2 &(CA2::*captr4)(const CA2&) throw(B) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}}
}
// In-class member initializers.
struct IC0 {
int inClassInit = 0;
};
struct IC1 {
int inClassInit = (throw B(), 0);
};
// FIXME: the exception specification on the default constructor is wrong:
// we cannot currently compute the set of thrown types.
static_assert(noexcept(IC0()), "IC0() does not throw");
static_assert(!noexcept(IC1()), "IC1() throws");
namespace PR13381 {
struct NoThrowMove {
NoThrowMove(const NoThrowMove &);
NoThrowMove(NoThrowMove &&) noexcept;
NoThrowMove &operator=(const NoThrowMove &) const;
NoThrowMove &operator=(NoThrowMove &&) const noexcept;
};
struct NoThrowMoveOnly {
NoThrowMoveOnly(NoThrowMoveOnly &&) noexcept;
NoThrowMoveOnly &operator=(NoThrowMoveOnly &&) noexcept;
};
struct X {
const NoThrowMove a;
NoThrowMoveOnly b;
static X val();
static X &ref();
};
// These both perform a move, but that copy might throw, because it calls
// NoThrowMove's copy constructor (because PR13381::a is const).
static_assert(!noexcept(X(X::val())), "");
static_assert(!noexcept(X::ref() = X::val()), "");
}
namespace PR14141 {
// Part of DR1351: the implicit exception-specification is noexcept(false) if
// the set of potential exceptions of the special member function contains
// "any". Hence it is compatible with noexcept(false).
struct ThrowingBase {
ThrowingBase() noexcept(false);
ThrowingBase(const ThrowingBase&) noexcept(false);
ThrowingBase(ThrowingBase&&) noexcept(false);
ThrowingBase &operator=(const ThrowingBase&) noexcept(false);
ThrowingBase &operator=(ThrowingBase&&) noexcept(false);
~ThrowingBase() noexcept(false);
};
struct Derived : ThrowingBase {
Derived() noexcept(false) = default;
Derived(const Derived&) noexcept(false) = default;
Derived(Derived&&) noexcept(false) = default;
Derived &operator=(const Derived&) noexcept(false) = default;
Derived &operator=(Derived&&) noexcept(false) = default;
~Derived() noexcept(false) = default;
} d1;
static_assert(!noexcept(Derived()), "");
static_assert(!noexcept(Derived(static_cast<Derived&&>(d1))), "");
static_assert(!noexcept(Derived(d1)), "");
static_assert(!noexcept(d1 = static_cast<Derived&&>(d1)), "");
static_assert(!noexcept(d1 = d1), "");
struct Derived2 : ThrowingBase {
Derived2() = default;
Derived2(const Derived2&) = default;
Derived2(Derived2&&) = default;
Derived2 &operator=(const Derived2&) = default;
Derived2 &operator=(Derived2&&) = default;
~Derived2() = default;
} d2;
static_assert(!noexcept(Derived2()), "");
static_assert(!noexcept(Derived2(static_cast<Derived2&&>(d2))), "");
static_assert(!noexcept(Derived2(d2)), "");
static_assert(!noexcept(d2 = static_cast<Derived2&&>(d2)), "");
static_assert(!noexcept(d2 = d2), "");
struct Derived3 : ThrowingBase {
Derived3() noexcept(true) = default;
Derived3(const Derived3&) noexcept(true) = default;
Derived3(Derived3&&) noexcept(true) = default;
Derived3 &operator=(const Derived3&) noexcept(true) = default;
Derived3 &operator=(Derived3&&) noexcept(true) = default;
~Derived3() noexcept(true) = default;
} d3;
static_assert(noexcept(Derived3(), Derived3(Derived3()), Derived3(d3), d3 = Derived3(), d3 = d3), "");
}
namespace rdar13017229 {
struct Base {
virtual ~Base() {}
};
struct Derived : Base {
virtual ~Derived();
Typo foo(); // expected-error{{unknown type name 'Typo'}}
};
}
namespace InhCtor {
template<int> struct X {};
struct Base {
Base(X<0>) noexcept(true);
Base(X<1>) noexcept(false);
Base(X<2>) throw(X<2>);
template<typename T> Base(T) throw(T);
};
template<typename T> struct Throw {
Throw() throw(T);
};
struct Derived1 : Base, X<5> {
using Base::Base;
int n;
};
struct Derived2 : Base, Throw<X<3>> {
using Base::Base;
};
struct Derived3 : Base {
using Base::Base;
Throw<X<4>> x;
};
static_assert(noexcept(Derived1(X<0>())), "");
static_assert(!noexcept(Derived1(X<1>())), "");
static_assert(!noexcept(Derived1(X<2>())), "");
static_assert(!noexcept(Derived2(X<0>())), "");
static_assert(!noexcept(Derived3(X<0>())), "");
}
|