Richard Smith | 762bb9d | 2011-10-13 22:29:44 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -verify -std=c++11 %s |
Douglas Gregor | c05babe | 2010-07-01 14:21:35 +0000 | [diff] [blame] | 2 | struct A { }; |
| 3 | struct B { }; |
Douglas Gregor | b87786f | 2010-07-01 17:48:08 +0000 | [diff] [blame] | 4 | struct C { }; |
Douglas Gregor | c05babe | 2010-07-01 14:21:35 +0000 | [diff] [blame] | 5 | |
Douglas Gregor | b87786f | 2010-07-01 17:48:08 +0000 | [diff] [blame] | 6 | // Destructor |
Douglas Gregor | c05babe | 2010-07-01 14:21:35 +0000 | [diff] [blame] | 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 | |
Douglas Gregor | b87786f | 2010-07-01 17:48:08 +0000 | [diff] [blame] | 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 | } |
Richard Smith | 7a614d8 | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 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"); |
Richard Smith | 6a06e5f | 2012-07-18 03:36:00 +0000 | [diff] [blame] | 42 | |
| 43 | namespace PR13381 { |
| 44 | struct NoThrowMove { |
| 45 | NoThrowMove(const NoThrowMove &); |
| 46 | NoThrowMove(NoThrowMove &&) noexcept; |
| 47 | NoThrowMove &operator=(const NoThrowMove &); |
| 48 | NoThrowMove &operator=(NoThrowMove &&) 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 | } |
Richard Smith | 03e6fda | 2012-10-21 23:00:34 +0000 | [diff] [blame^] | 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 | } |