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 // RUN: %cxx %flags %compile_flags -c %s -o %t.one.o 18 // RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE 19 // RUN: %cxx %flags %t.one.o %t.two.o %link_flags -o %t.exe 20 // RUN: %exec %t.exe 21 22 #include <stdio.h> 23 #include <cstring> 24 #include <cassert> 25 #include <typeinfo> 26 27 // Check that the addresses of the typeinfo differ but still compare equal 28 // via their NTBS. 29 inline void 30 AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS) 31 { 32 assert(&LHS != &RHS); 33 assert(strcmp(LHS.name(), RHS.name()) == 0); 34 } 35 36 struct NeverDefined; 37 void ThrowNeverDefinedMP(); 38 std::type_info const& ReturnTypeInfoNeverDefinedMP(); 39 40 struct IncompleteAtThrow; 41 void ThrowIncompleteMP(); 42 void ThrowIncompletePP(); 43 void ThrowIncompletePMP(); 44 std::type_info const& ReturnTypeInfoIncompleteMP(); 45 std::type_info const& ReturnTypeInfoIncompletePP(); 46 47 struct CompleteAtThrow; 48 void ThrowCompleteMP(); 49 void ThrowCompletePP(); 50 void ThrowCompletePMP(); 51 std::type_info const& ReturnTypeInfoCompleteMP(); 52 std::type_info const& ReturnTypeInfoCompletePP(); 53 54 void ThrowNullptr(); 55 56 #ifndef TU_ONE 57 58 void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; } 59 std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); } 60 61 void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; } 62 void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; } 63 void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; } 64 std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); } 65 std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); } 66 67 struct CompleteAtThrow {}; 68 void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; } 69 void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; } 70 void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; } 71 std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); } 72 std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); } 73 74 void ThrowNullptr() { throw nullptr; } 75 76 #else 77 78 struct IncompleteAtThrow {}; 79 80 int main() { 81 AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*)); 82 try { 83 ThrowNeverDefinedMP(); 84 assert(false); 85 } catch (int IncompleteAtThrow::*) { 86 assert(false); 87 } catch (int CompleteAtThrow::*) { 88 assert(false); 89 } catch (int NeverDefined::*) {} 90 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*)); 91 try { 92 ThrowIncompleteMP(); 93 assert(false); 94 } catch (CompleteAtThrow**) { 95 assert(false); 96 } catch (int CompleteAtThrow::*) { 97 assert(false); 98 } catch (IncompleteAtThrow**) { 99 assert(false); 100 } catch (int IncompleteAtThrow::*) {} 101 102 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**)); 103 try { 104 ThrowIncompletePP(); 105 assert(false); 106 } catch (int IncompleteAtThrow::*) { 107 assert(false); 108 } catch (IncompleteAtThrow**) {} 109 110 try { 111 ThrowIncompletePMP(); 112 assert(false); 113 } catch (int IncompleteAtThrow::*) { 114 assert(false); 115 } catch (IncompleteAtThrow**) { 116 assert(false); 117 } catch (int IncompleteAtThrow::**) {} 118 119 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*)); 120 try { 121 ThrowCompleteMP(); 122 assert(false); 123 } catch (IncompleteAtThrow**) { 124 assert(false); 125 } catch (int IncompleteAtThrow::*) { 126 assert(false); 127 } catch (CompleteAtThrow**) { 128 assert(false); 129 } catch (int CompleteAtThrow::*) {} 130 131 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**)); 132 try { 133 ThrowCompletePP(); 134 assert(false); 135 } catch (IncompleteAtThrow**) { 136 assert(false); 137 } catch (int IncompleteAtThrow::*) { 138 assert(false); 139 } catch (int CompleteAtThrow::*) { 140 assert(false); 141 } catch (CompleteAtThrow**) {} 142 143 try { 144 ThrowCompletePMP(); 145 assert(false); 146 } catch (IncompleteAtThrow**) { 147 assert(false); 148 } catch (int IncompleteAtThrow::*) { 149 assert(false); 150 } catch (int CompleteAtThrow::*) { 151 assert(false); 152 } catch (CompleteAtThrow**) { 153 assert(false); 154 } catch (int CompleteAtThrow::**) {} 155 156 #if __cplusplus >= 201103L 157 // Catch nullptr as complete type 158 try { 159 ThrowNullptr(); 160 } catch (int IncompleteAtThrow::*) {} 161 162 // Catch nullptr as an incomplete type 163 try { 164 ThrowNullptr(); 165 } catch (int CompleteAtThrow::*) {} 166 // Catch nullptr as a type that is never complete. 167 try { 168 ThrowNullptr(); 169 } catch (int NeverDefined::*) {} 170 #endif 171 } 172 #endif 173