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
28class A
29{
30 int data_;
31public:
32 explicit A(int data) : data_(data) {}
33 A(const A&) = default;
34 A& operator=(const A&) = default;
35 virtual ~A() TEST_NOEXCEPT {}
36
37 friend bool operator==(const A& x, const A& y) {return x.data_ == y.data_;}
38};
39
40class B
41 : public std::nested_exception,
42 public A
43{
44public:
45 explicit B(int data) : A(data) {}
46 B(const B& b) : A(b) {}
47};
48
49class C
50{
51public:
52 virtual ~C() {}
53 C * operator&() const { assert(false); return nullptr; } // should not be called
54};
55
56class D : private std::nested_exception {};
57
58
59class E1 : public std::nested_exception {};
60class E2 : public std::nested_exception {};
61class E : public E1, public E2 {};
62
63#if TEST_STD_VER >= 11
64template <class, class...>
65struct can_rethrow_if_nested_impl {
66 static constexpr bool value = false;
67};
68
69template <class... Args>
70struct can_rethrow_if_nested_impl<decltype((void)std::rethrow_if_nested(std::declval<Args>()...)), Args...> {
71 static constexpr bool value = true;
72};
73
74template <class... Args>
75struct can_rethrow_if_nested : can_rethrow_if_nested_impl<void, Args...> {};
76
77static_assert(!can_rethrow_if_nested<>::value, "");
78static_assert(can_rethrow_if_nested<A>::value, "");
79static_assert(can_rethrow_if_nested<const A&>::value, "");
80static_assert(can_rethrow_if_nested<B>::value, "");
81static_assert(can_rethrow_if_nested<const B&>::value, "");
82static_assert(!can_rethrow_if_nested<A, int*>::value, "");
83static_assert(!can_rethrow_if_nested<B, int*>::value, "");
84static_assert(!can_rethrow_if_nested<A, std::nullptr_t>::value, "");
85static_assert(!can_rethrow_if_nested<B, std::nullptr_t>::value, "");
86#endif
87
88int main(int, char**)
89{
90 {
91 try
92 {
93 A a(3); // not a polymorphic type --> no effect
94 std::rethrow_if_nested(ex: 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(ex: 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(ex: 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(ex: 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(ex: C());
155 assert(true);
156 }
157 catch (...)
158 {
159 assert(false);
160 }
161 }
162
163
164 return 0;
165}
166

source code of libcxx/test/std/language.support/support.exception/except.nested/rethrow_if_nested.pass.cpp