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