1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: no-exceptions
10
11 // FIXME: This test fails in MSVC mode due to a stack overflow
12 // XFAIL: msvc
13
14 // <exception>
15
16 // class nested_exception;
17
18 // template <class E> void rethrow_if_nested(const E& e);
19
20 #include <exception>
21 #include <cstddef>
22 #include <cstdlib>
23 #include <cassert>
24 #include <utility>
25
26 #include "test_macros.h"
27
28 class A
29 {
30 int data_;
31 public:
A(int data)32 explicit A(int data) : data_(data) {}
33 A(const A&) = default;
34 A& operator=(const A&) = default;
~A()35 virtual ~A() TEST_NOEXCEPT {}
36
operator ==(const A & x,const A & y)37 friend bool operator==(const A& x, const A& y) {return x.data_ == y.data_;}
38 };
39
40 class B
41 : public std::nested_exception,
42 public A
43 {
44 public:
B(int data)45 explicit B(int data) : A(data) {}
B(const B & b)46 B(const B& b) : A(b) {}
47 };
48
49 class C
50 {
51 public:
~C()52 virtual ~C() {}
operator &() const53 C * operator&() const { assert(false); return nullptr; } // should not be called
54 };
55
56 class D : private std::nested_exception {};
57
58
59 class E1 : public std::nested_exception {};
60 class E2 : public std::nested_exception {};
61 class E : public E1, public E2 {};
62
63 #if TEST_STD_VER >= 11
64 template <class, class...>
65 struct can_rethrow_if_nested_impl {
66 static constexpr bool value = false;
67 };
68
69 template <class... Args>
70 struct can_rethrow_if_nested_impl<decltype((void)std::rethrow_if_nested(std::declval<Args>()...)), Args...> {
71 static constexpr bool value = true;
72 };
73
74 template <class... Args>
75 struct can_rethrow_if_nested : can_rethrow_if_nested_impl<void, Args...> {};
76
77 static_assert(!can_rethrow_if_nested<>::value, "");
78 static_assert(can_rethrow_if_nested<A>::value, "");
79 static_assert(can_rethrow_if_nested<const A&>::value, "");
80 static_assert(can_rethrow_if_nested<B>::value, "");
81 static_assert(can_rethrow_if_nested<const B&>::value, "");
82 static_assert(!can_rethrow_if_nested<A, int*>::value, "");
83 static_assert(!can_rethrow_if_nested<B, int*>::value, "");
84 static_assert(!can_rethrow_if_nested<A, std::nullptr_t>::value, "");
85 static_assert(!can_rethrow_if_nested<B, std::nullptr_t>::value, "");
86 #endif
87
main(int,char **)88 int main(int, char**)
89 {
90 {
91 try
92 {
93 A a(3); // not a polymorphic type --> no effect
94 std::rethrow_if_nested(a);
95 assert(true);
96 }
97 catch (...)
98 {
99 assert(false);
100 }
101 }
102 {
103 try
104 {
105 D s; // inaccessible base class --> no effect
106 std::rethrow_if_nested(s);
107 assert(true);
108 }
109 catch (...)
110 {
111 assert(false);
112 }
113 }
114 {
115 try
116 {
117 E s; // ambiguous base class --> no effect
118 std::rethrow_if_nested(s);
119 assert(true);
120 }
121 catch (...)
122 {
123 assert(false);
124 }
125 }
126 {
127 try
128 {
129 throw B(5);
130 }
131 catch (const B& b)
132 {
133 try
134 {
135 throw b;
136 }
137 catch (const A& a)
138 {
139 try
140 {
141 std::rethrow_if_nested(a);
142 assert(false);
143 }
144 catch (const B& b2)
145 {
146 assert(b2 == B(5));
147 }
148 }
149 }
150 }
151 {
152 try
153 {
154 std::rethrow_if_nested(C());
155 assert(true);
156 }
157 catch (...)
158 {
159 assert(false);
160 }
161 }
162
163
164 return 0;
165 }
166