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 // NOTE: Pass -lc++abi explicitly and before -lc++ so that -lc++ doesn't drag 20 // in the system libc++abi installation on OS X. (DYLD_LIBRARY_PATH is ignored 21 // for shell tests because of Apple security features). 22 23 // RUN: %cxx %flags %compile_flags -c %s -o %t.one.o 24 // RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE 25 // RUN: %cxx %flags %t.one.o %t.two.o -lc++abi %link_flags -o %t.exe 26 // RUN: %t.exe 27 28 #include <stdio.h> 29 #include <cstring> 30 #include <cassert> 31 #include <typeinfo> 32 33 // Check that the addresses of the typeinfo differ but still compare equal 34 // via their NTBS. 35 inline void 36 AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS) 37 { 38 assert(&LHS != &RHS); 39 assert(strcmp(LHS.name(), RHS.name()) == 0); 40 } 41 42 struct NeverDefined; 43 void ThrowNeverDefinedMP(); 44 std::type_info const& ReturnTypeInfoNeverDefinedMP(); 45 46 struct IncompleteAtThrow; 47 void ThrowIncompleteMP(); 48 void ThrowIncompletePP(); 49 void ThrowIncompletePMP(); 50 std::type_info const& ReturnTypeInfoIncompleteMP(); 51 std::type_info const& ReturnTypeInfoIncompletePP(); 52 53 struct CompleteAtThrow; 54 void ThrowCompleteMP(); 55 void ThrowCompletePP(); 56 void ThrowCompletePMP(); 57 std::type_info const& ReturnTypeInfoCompleteMP(); 58 std::type_info const& ReturnTypeInfoCompletePP(); 59 60 void ThrowNullptr(); 61 62 #ifndef TU_ONE 63 64 void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; } 65 std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); } 66 67 void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; } 68 void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; } 69 void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; } 70 std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); } 71 std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); } 72 73 struct CompleteAtThrow {}; 74 void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; } 75 void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; } 76 void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; } 77 std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); } 78 std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); } 79 80 void ThrowNullptr() { throw nullptr; } 81 82 #else 83 84 struct IncompleteAtThrow {}; 85 86 int main() { 87 AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*)); 88 try { 89 ThrowNeverDefinedMP(); 90 assert(false); 91 } catch (int IncompleteAtThrow::*) { 92 assert(false); 93 } catch (int CompleteAtThrow::*) { 94 assert(false); 95 } catch (int NeverDefined::*p) { 96 assert(!p); 97 } 98 catch(...) { assert(!"FAIL: Didn't catch NeverDefined::*" ); } 99 100 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*)); 101 try { 102 ThrowIncompleteMP(); 103 assert(false); 104 } catch (CompleteAtThrow**) { 105 assert(false); 106 } catch (int CompleteAtThrow::*) { 107 assert(false); 108 } catch (IncompleteAtThrow**) { 109 assert(false); 110 } catch (int IncompleteAtThrow::*p) { 111 assert(!p); 112 } 113 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow::*" ); } 114 115 AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**)); 116 try { 117 ThrowIncompletePP(); 118 assert(false); 119 } catch (int IncompleteAtThrow::*) { 120 assert(false); 121 } catch (IncompleteAtThrow** p) { 122 assert(!p); 123 } 124 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow**" ); } 125 126 try { 127 ThrowIncompletePMP(); 128 assert(false); 129 } catch (int IncompleteAtThrow::*) { 130 assert(false); 131 } catch (IncompleteAtThrow**) { 132 assert(false); 133 } catch (int IncompleteAtThrow::**p) { 134 assert(!p); 135 } 136 catch(...) { assert(!"FAIL: Didn't catch IncompleteAtThrow::**" ); } 137 138 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*)); 139 try { 140 ThrowCompleteMP(); 141 assert(false); 142 } catch (IncompleteAtThrow**) { 143 assert(false); 144 } catch (int IncompleteAtThrow::*) { 145 assert(false); 146 } catch (CompleteAtThrow**) { 147 assert(false); 148 } catch (int CompleteAtThrow::*p) { 149 assert(!p); 150 } 151 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow::" ); } 152 153 AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**)); 154 try { 155 ThrowCompletePP(); 156 assert(false); 157 } catch (IncompleteAtThrow**) { 158 assert(false); 159 } catch (int IncompleteAtThrow::*) { 160 assert(false); 161 } catch (int CompleteAtThrow::*) { 162 assert(false); 163 } catch (CompleteAtThrow**p) { 164 assert(!p); 165 } 166 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow**" ); } 167 168 try { 169 ThrowCompletePMP(); 170 assert(false); 171 } catch (IncompleteAtThrow**) { 172 assert(false); 173 } catch (int IncompleteAtThrow::*) { 174 assert(false); 175 } catch (int CompleteAtThrow::*) { 176 assert(false); 177 } catch (CompleteAtThrow**) { 178 assert(false); 179 } catch (int CompleteAtThrow::**p) { 180 assert(!p); 181 } 182 catch(...) { assert(!"FAIL: Didn't catch CompleteAtThrow::**" ); } 183 184 #if __cplusplus >= 201103L 185 // Catch nullptr as complete type 186 try { 187 ThrowNullptr(); 188 } catch (int IncompleteAtThrow::*p) { 189 assert(!p); 190 } 191 catch(...) { assert(!"FAIL: Didn't catch nullptr as IncompleteAtThrow::*" ); } 192 193 // Catch nullptr as an incomplete type 194 try { 195 ThrowNullptr(); 196 } catch (int CompleteAtThrow::*p) { 197 assert(!p); 198 } 199 catch(...) { assert(!"FAIL: Didn't catch nullptr as CompleteAtThrow::*" ); } 200 201 // Catch nullptr as a type that is never complete. 202 try { 203 ThrowNullptr(); 204 } catch (int NeverDefined::*p) { 205 assert(!p); 206 } 207 catch(...) { assert(!"FAIL: Didn't catch nullptr as NeverDefined::*" ); } 208 209 #endif 210 } 211 #endif 212