1 //===------------------------- incomplete_type.cpp --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout 10 11 // Two abi::__pbase_type_info objects can always be compared for equality 12 // (i.e. of the types represented) or ordering by comparison of their name 13 // NTBS addresses. In addition, unless either or both have either of the 14 // incomplete flags set, equality can be tested by comparing the type_info 15 // addresses. 16 17 // UNSUPPORTED: libcxxabi-no-exceptions 18 19 // RUN: %cxx %flags %compile_flags -c %s -o %t.one.o 20 // RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE 21 // RUN: %cxx %flags %t.one.o %t.two.o %link_flags -o %t.exe 22 // RUN: %exec %t.exe 23 24 #include <stdio.h> 25 #include <cstring> 26 #include <cassert> 27 #include <typeinfo> 28 29 // Check that the addresses of the typeinfo differ but still compare equal 30 // via their NTBS. 31 inline void 32 AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS) 33 { 34 assert(&LHS != &RHS); 35 assert(strcmp(LHS.name(), RHS.name()) == 0); 36 } 37 38 struct NeverDefined; 39 void ThrowNeverDefinedMP(); 40 std::type_info const& ReturnTypeInfoNeverDefinedMP(); 41 42 struct IncompleteAtThrow; 43 void ThrowIncompleteMP(); 44 void ThrowIncompletePP(); 45 void ThrowIncompletePMP(); 46 std::type_info const& ReturnTypeInfoIncompleteMP(); 47 std::type_info const& ReturnTypeInfoIncompletePP(); 48 49 struct CompleteAtThrow; 50 void ThrowCompleteMP(); 51 void ThrowCompletePP(); 52 void ThrowCompletePMP(); 53 std::type_info const& ReturnTypeInfoCompleteMP(); 54 std::type_info const& ReturnTypeInfoCompletePP(); 55 56 void ThrowNullptr(); 57 58 #ifndef TU_ONE 59 60 void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; } 61 std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); } 62 63 void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; } 64 void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; } 65 void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; } 66 std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); } 67 std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); } 68 69 struct CompleteAtThrow {}; 70 void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; } 71 void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; } 72 void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; } 73 std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); } 74 std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); } 75 76 void ThrowNullptr() { throw nullptr; } 77 78 #else 79 80 struct IncompleteAtThrow {}; 81 82 int main() { 83 AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*)); 84 try { 85 ThrowNeverDefinedMP(); 86 assert(false); 87 } catch (int IncompleteAtThrow::*) { 88 assert(false); 89 } catch (int CompleteAtThrow::*) { 90 assert(false); 91 } catch (int NeverDefined::*) {} 92 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*)); 93 try { 94 ThrowIncompleteMP(); 95 assert(false); 96 } catch (CompleteAtThrow**) { 97 assert(false); 98 } catch (int CompleteAtThrow::*) { 99 assert(false); 100 } catch (IncompleteAtThrow**) { 101 assert(false); 102 } catch (int IncompleteAtThrow::*) {} 103 104 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**)); 105 try { 106 ThrowIncompletePP(); 107 assert(false); 108 } catch (int IncompleteAtThrow::*) { 109 assert(false); 110 } catch (IncompleteAtThrow**) {} 111 112 try { 113 ThrowIncompletePMP(); 114 assert(false); 115 } catch (int IncompleteAtThrow::*) { 116 assert(false); 117 } catch (IncompleteAtThrow**) { 118 assert(false); 119 } catch (int IncompleteAtThrow::**) {} 120 121 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*)); 122 try { 123 ThrowCompleteMP(); 124 assert(false); 125 } catch (IncompleteAtThrow**) { 126 assert(false); 127 } catch (int IncompleteAtThrow::*) { 128 assert(false); 129 } catch (CompleteAtThrow**) { 130 assert(false); 131 } catch (int CompleteAtThrow::*) {} 132 133 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**)); 134 try { 135 ThrowCompletePP(); 136 assert(false); 137 } catch (IncompleteAtThrow**) { 138 assert(false); 139 } catch (int IncompleteAtThrow::*) { 140 assert(false); 141 } catch (int CompleteAtThrow::*) { 142 assert(false); 143 } catch (CompleteAtThrow**) {} 144 145 try { 146 ThrowCompletePMP(); 147 assert(false); 148 } catch (IncompleteAtThrow**) { 149 assert(false); 150 } catch (int IncompleteAtThrow::*) { 151 assert(false); 152 } catch (int CompleteAtThrow::*) { 153 assert(false); 154 } catch (CompleteAtThrow**) { 155 assert(false); 156 } catch (int CompleteAtThrow::**) {} 157 158 #if __cplusplus >= 201103L 159 // Catch nullptr as complete type 160 try { 161 ThrowNullptr(); 162 } catch (int IncompleteAtThrow::*) {} 163 164 // Catch nullptr as an incomplete type 165 try { 166 ThrowNullptr(); 167 } catch (int CompleteAtThrow::*) {} 168 // Catch nullptr as a type that is never complete. 169 try { 170 ThrowNullptr(); 171 } catch (int NeverDefined::*) {} 172 #endif 173 } 174 #endif 175