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