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