• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // 1b00fc5d8133 made it in the dylib in macOS 10.11
12 // XFAIL: stdlib=apple-libc++ && target={{.+}}-apple-macosx10.{{9|10}}
13 
14 #include <cassert>
15 #include <cstdio>
16 #include <cstdlib>
17 
18 // Roll our own assertion macro to get better error messages out of the tests.
19 // In particular on systems that don't use __PRETTY_FUNCTION__ in assertions.
20 #define my_assert(pred, msg) do_assert(pred, msg, __LINE__, __PRETTY_FUNCTION__)
21 
do_assert(bool assert_passed,const char * msg,int line,const char * func)22 void do_assert(bool assert_passed, const char* msg, int line, const char* func) {
23   if (assert_passed)
24     return;
25   std::printf("%s:%d %s: Assertion Failed '%s'\n\n", __FILE__, line, func, msg);
26   std::abort();
27 }
28 
29 struct A {};
30 struct Base {};
31 struct Derived : public Base {};
32 
33 template <class To>
test_conversion(To)34 bool test_conversion(To) { return true; }
35 
36 template <class To>
test_conversion(...)37 bool test_conversion(...) { return false; }
38 
39 template <class Pointer>
40 struct CreatePointer {
operator ()CreatePointer41   Pointer operator()() const {
42       return (Pointer)0;
43   }
44 };
45 
46 template <class Tp>
47 struct CreatePointer<Tp*> {
operator ()CreatePointer48   Tp* operator()() const {
49       return (Tp*)42;
50   }
51 };
52 
53 template <class Throw, class Catch>
catch_pointer_test()54 void catch_pointer_test() {
55   Throw throw_ptr = CreatePointer<Throw>()();
56   // Use the compiler to determine if the exception of type Throw can be
57   // implicitly converted to type Catch.
58   const bool can_convert = test_conversion<Catch>(throw_ptr);
59   try {
60     throw throw_ptr;
61     assert(false);
62   } catch (Catch catch_ptr) {
63     Catch catch2 = CreatePointer<Catch>()();
64     my_assert(can_convert, "non-convertible type incorrectly caught");
65     my_assert(catch_ptr == catch2,
66               "Thrown pointer does not match caught ptr");
67   } catch (...) {
68     my_assert(!can_convert, "convertible type incorrectly not caught");
69   }
70 }
71 
72 // Generate CV qualified pointer typedefs.
73 template <class Tp, bool First = false>
74 struct TestTypes {
75   typedef Tp* Type;
76   typedef Tp const* CType;
77   typedef Tp volatile* VType;
78   typedef Tp const volatile* CVType;
79 };
80 
81 // Special case for cv-qualifying a pointer-to-member without adding an extra
82 // pointer to it.
83 template <class Member, class Class>
84 struct TestTypes<Member Class::*, true> {
85   typedef Member (Class::*Type);
86   typedef const Member (Class::*CType);
87   typedef volatile Member (Class::*VType);
88   typedef const volatile Member (Class::*CVType);
89 };
90 
91 template <class Throw, class Catch, int level, bool first = false>
92 struct generate_tests_imp {
93   typedef TestTypes<Throw, first> ThrowTypes;
94   typedef TestTypes<Catch, first> CatchTypes;
operator ()generate_tests_imp95   void operator()() {
96       typedef typename ThrowTypes::Type Type;
97       typedef typename ThrowTypes::CType CType;
98       typedef typename ThrowTypes::VType VType;
99       typedef typename ThrowTypes::CVType CVType;
100 
101       run_catch_tests<Type>();
102       run_catch_tests<CType>();
103       run_catch_tests<VType>();
104       run_catch_tests<CVType>();
105   }
106 
107   template <class ThrowTp>
run_catch_testsgenerate_tests_imp108   void run_catch_tests() {
109       typedef typename CatchTypes::Type Type;
110       typedef typename CatchTypes::CType CType;
111       typedef typename CatchTypes::VType VType;
112       typedef typename CatchTypes::CVType CVType;
113 
114       catch_pointer_test<ThrowTp, Type>();
115       catch_pointer_test<ThrowTp, CType>();
116       catch_pointer_test<ThrowTp, VType>();
117       catch_pointer_test<ThrowTp, CVType>();
118 
119       generate_tests_imp<ThrowTp, Type, level-1>()();
120       generate_tests_imp<ThrowTp, CType, level-1>()();
121       generate_tests_imp<ThrowTp, VType, level-1>()();
122       generate_tests_imp<ThrowTp, CVType, level-1>()();
123   }
124 };
125 
126 template <class Throw, class Catch, bool first>
127 struct generate_tests_imp<Throw, Catch, 0, first> {
operator ()generate_tests_imp128   void operator()() {
129       catch_pointer_test<Throw, Catch>();
130   }
131 };
132 
133 template <class Throw, class Catch, int level>
134 struct generate_tests : generate_tests_imp<Throw, Catch, level, true> {};
135 
main(int,char **)136 int main(int, char**)
137 {
138   generate_tests<int, int, 3>()();
139   generate_tests<Base, Derived, 2>()();
140   generate_tests<Derived, Base, 2>()();
141   generate_tests<int, void, 2>()();
142   generate_tests<void, int, 2>()();
143 
144   generate_tests<int A::*, int A::*, 3>()();
145   generate_tests<int A::*, void, 2>()();
146   generate_tests<void, int A::*, 2>()();
147 
148   return 0;
149 }
150