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 // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#rtti-layout 9 10 // Two abi::__pbase_type_info objects can always be compared for equality 11 // (i.e. of the types represented) or ordering by comparison of their name 12 // NTBS addresses. In addition, unless either or both have either of the 13 // incomplete flags set, equality can be tested by comparing the type_info 14 // addresses. 15 16 // UNSUPPORTED: no-exceptions 17 // UNSUPPORTED: no-rtti 18 19 // The fix for PR25898 landed in the system dylibs in macOS 10.13 20 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} 21 22 // RUN: %{cxx} %{flags} %{compile_flags} -Wno-unreachable-code -c %s -o %t.one.o 23 // RUN: %{cxx} %{flags} %{compile_flags} -Wno-unreachable-code -c %s -o %t.two.o -DTU_ONE 24 // RUN: %{cxx} %{flags} %t.one.o %t.two.o %{link_flags} -o %t.exe 25 // RUN: %{exec} %t.exe 26 27 #include <stdio.h> 28 #include <cstring> 29 #include <cassert> 30 #include <typeinfo> 31 32 // Check that the addresses of the typeinfo differ but still compare equal 33 // via their NTBS. 34 inline void 35 AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS) 36 { 37 assert(&LHS != &RHS); 38 assert(strcmp(LHS.name(), RHS.name()) == 0); 39 } 40 41 struct NeverDefined; 42 void ThrowNeverDefinedMP(); 43 std::type_info const& ReturnTypeInfoNeverDefinedMP(); 44 45 struct IncompleteAtThrow; 46 void ThrowIncompleteMP(); 47 void ThrowIncompletePP(); 48 void ThrowIncompletePMP(); 49 std::type_info const& ReturnTypeInfoIncompleteMP(); 50 std::type_info const& ReturnTypeInfoIncompletePP(); 51 52 struct CompleteAtThrow; 53 void ThrowCompleteMP(); 54 void ThrowCompletePP(); 55 void ThrowCompletePMP(); 56 std::type_info const& ReturnTypeInfoCompleteMP(); 57 std::type_info const& ReturnTypeInfoCompletePP(); 58 59 void ThrowNullptr(); 60 61 #ifndef TU_ONE 62 63 void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; } 64 std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); } 65 66 void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; } 67 void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; } 68 void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; } 69 std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); } 70 std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); } 71 72 struct CompleteAtThrow {}; 73 void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; } 74 void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; } 75 void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; } 76 std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); } 77 std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); } 78 79 void ThrowNullptr() { throw nullptr; } 80 81 #else 82 83 struct IncompleteAtThrow {}; 84 85 int main(int, char**) { 86 AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*)); 87 try { 88 ThrowNeverDefinedMP(); 89 assert(false); 90 } catch (int IncompleteAtThrow::*) { 91 assert(false); 92 } catch (int CompleteAtThrow::*) { 93 assert(false); 94 } catch (int NeverDefined::*p) { 95 assert(!p); 96 } 97 catch(...) { assert(!"FAIL: Didn't catch NeverDefined::*" ); } 98 99 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*)); 100 try { 101 ThrowIncompleteMP(); 102 assert(false); 103 } catch (CompleteAtThrow**) { 104 assert(false); 105 } catch (int CompleteAtThrow::*) { 106 assert(false); 107 } catch (IncompleteAtThrow**) { 108 assert(false); 109 } catch (int IncompleteAtThrow::*p) { 110 assert(!p); 111 } 112 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow::*" ); } 113 114 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**)); 115 try { 116 ThrowIncompletePP(); 117 assert(false); 118 } catch (int IncompleteAtThrow::*) { 119 assert(false); 120 } catch (IncompleteAtThrow** p) { 121 assert(!p); 122 } 123 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow**" ); } 124 125 try { 126 ThrowIncompletePMP(); 127 assert(false); 128 } catch (int IncompleteAtThrow::*) { 129 assert(false); 130 } catch (IncompleteAtThrow**) { 131 assert(false); 132 } catch (int IncompleteAtThrow::**p) { 133 assert(!p); 134 } 135 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow::**" ); } 136 137 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*)); 138 try { 139 ThrowCompleteMP(); 140 assert(false); 141 } catch (IncompleteAtThrow**) { 142 assert(false); 143 } catch (int IncompleteAtThrow::*) { 144 assert(false); 145 } catch (CompleteAtThrow**) { 146 assert(false); 147 } catch (int CompleteAtThrow::*p) { 148 assert(!p); 149 } 150 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow::" ); } 151 152 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**)); 153 try { 154 ThrowCompletePP(); 155 assert(false); 156 } catch (IncompleteAtThrow**) { 157 assert(false); 158 } catch (int IncompleteAtThrow::*) { 159 assert(false); 160 } catch (int CompleteAtThrow::*) { 161 assert(false); 162 } catch (CompleteAtThrow**p) { 163 assert(!p); 164 } 165 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow**" ); } 166 167 try { 168 ThrowCompletePMP(); 169 assert(false); 170 } catch (IncompleteAtThrow**) { 171 assert(false); 172 } catch (int IncompleteAtThrow::*) { 173 assert(false); 174 } catch (int CompleteAtThrow::*) { 175 assert(false); 176 } catch (CompleteAtThrow**) { 177 assert(false); 178 } catch (int CompleteAtThrow::**p) { 179 assert(!p); 180 } 181 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow::**" ); } 182 183 #if __cplusplus >= 201103L 184 // Catch nullptr as complete type 185 try { 186 ThrowNullptr(); 187 } catch (int IncompleteAtThrow::*p) { 188 assert(!p); 189 } 190 catch(...) { assert(!"FAIL: Didn't catch nullptr as IncompleteAtThrow::*" ); } 191 192 // Catch nullptr as an incomplete type 193 try { 194 ThrowNullptr(); 195 } catch (int CompleteAtThrow::*p) { 196 assert(!p); 197 } 198 catch(...) { assert(!"FAIL: Didn't catch nullptr as CompleteAtThrow::*" ); } 199 200 // Catch nullptr as a type that is never complete. 201 try { 202 ThrowNullptr(); 203 } catch (int NeverDefined::*p) { 204 assert(!p); 205 } 206 catch(...) { assert(!"FAIL: Didn't catch nullptr as NeverDefined::*" ); } 207 #endif 208 209 return 0; 210 } 211 #endif 212