1 | // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s |
2 | #include <typeinfo> |
3 | |
4 | // vtables. |
5 | extern "C" { |
6 | const void *_ZTVN10__cxxabiv123__fundamental_type_infoE; |
7 | const void *_ZTVN10__cxxabiv117__class_type_infoE; |
8 | const void *_ZTVN10__cxxabiv120__si_class_type_infoE; |
9 | const void *_ZTVN10__cxxabiv121__vmi_class_type_infoE; |
10 | const void *_ZTVN10__cxxabiv119__pointer_type_infoE; |
11 | const void *_ZTVN10__cxxabiv129__pointer_to_member_type_infoE; |
12 | }; |
13 | #define fundamental_type_info_vtable _ZTVN10__cxxabiv123__fundamental_type_infoE |
14 | #define class_type_info_vtable _ZTVN10__cxxabiv117__class_type_infoE |
15 | #define si_class_type_info_vtable _ZTVN10__cxxabiv120__si_class_type_infoE |
16 | #define vmi_class_type_info_vtable _ZTVN10__cxxabiv121__vmi_class_type_infoE |
17 | #define pointer_type_info_vtable _ZTVN10__cxxabiv119__pointer_type_infoE |
18 | #define pointer_to_member_type_info_vtable _ZTVN10__cxxabiv129__pointer_to_member_type_infoE |
19 | |
20 | class __pbase_type_info : public std::type_info { |
21 | public: |
22 | unsigned int __flags; |
23 | const std::type_info *__pointee; |
24 | |
25 | enum __masks { |
26 | __const_mask = 0x1, |
27 | __volatile_mask = 0x2, |
28 | __restrict_mask = 0x4, |
29 | __incomplete_mask = 0x8, |
30 | __incomplete_class_mask = 0x10 |
31 | }; |
32 | }; |
33 | |
34 | class __class_type_info : public std::type_info { }; |
35 | |
36 | class __si_class_type_info : public __class_type_info { |
37 | public: |
38 | const __class_type_info *__base_type; |
39 | }; |
40 | |
41 | struct __base_class_type_info { |
42 | public: |
43 | const __class_type_info *__base_type; |
44 | long __offset_flags; |
45 | |
46 | enum __offset_flags_masks { |
47 | __virtual_mask = 0x1, |
48 | __public_mask = 0x2, |
49 | __offset_shift = 8 |
50 | }; |
51 | }; |
52 | |
53 | class __vmi_class_type_info : public __class_type_info { |
54 | public: |
55 | unsigned int __flags; |
56 | unsigned int __base_count; |
57 | __base_class_type_info __base_info[1]; |
58 | |
59 | enum __flags_masks { |
60 | __non_diamond_repeat_mask = 0x1, |
61 | __diamond_shaped_mask = 0x2 |
62 | }; |
63 | }; |
64 | |
65 | template<typename T> const T& to(const std::type_info &info) { |
66 | return static_cast<const T&>(info); |
67 | } |
68 | struct Incomplete; |
69 | |
70 | struct A { int a; }; |
71 | struct Empty { }; |
72 | |
73 | struct SI1 : A { }; |
74 | struct SI2 : Empty { }; |
75 | struct SI3 : Empty { virtual void f() { } }; |
76 | |
77 | struct VMI1 : private A { }; |
78 | struct VMI2 : virtual A { }; |
79 | struct VMI3 : A { virtual void f() { } }; |
80 | struct VMI4 : A, Empty { }; |
81 | |
82 | struct VMIBase1 { int a; }; |
83 | struct VMIBase2 : VMIBase1 { int a; }; |
84 | struct VMI5 : VMIBase1, VMIBase2 { int a; }; |
85 | |
86 | struct VMIBase3 : virtual VMIBase1 { int a; }; |
87 | struct VMI6 : virtual VMIBase1, VMIBase3 { int a; }; |
88 | |
89 | struct VMI7 : VMIBase1, VMI5, private VMI6 { }; |
90 | |
91 | #define CHECK(x) if (!(x)) return __LINE__ |
92 | #define CHECK_VTABLE(type, vtable) CHECK(&vtable##_type_info_vtable + 2 == (((void **)&(typeid(type)))[0])) |
93 | #define CHECK_BASE_INFO_TYPE(type, index, base) CHECK(to<__vmi_class_type_info>(typeid(type)).__base_info[(index)].__base_type == &typeid(base)) |
94 | #define CHECK_BASE_INFO_OFFSET_FLAGS(type, index, offset, flags) CHECK(to<__vmi_class_type_info>(typeid(type)).__base_info[(index)].__offset_flags == (((offset) << 8) | (flags))) |
95 | |
96 | struct B { |
97 | static int const volatile (*a)[10]; |
98 | static int (*b)[10]; |
99 | |
100 | static int const volatile (B::*c)[10]; |
101 | static int (B::*d)[10]; |
102 | }; |
103 | |
104 | // CHECK-LABEL: define i32 @_Z1fv() |
105 | int f() { |
106 | // Vectors should be treated as fundamental types. |
107 | typedef short __v4hi __attribute__ ((__vector_size__ (8))); |
108 | CHECK_VTABLE(__v4hi, fundamental); |
109 | |
110 | // A does not have any bases. |
111 | CHECK_VTABLE(A, class); |
112 | |
113 | // SI1 has a single public base. |
114 | CHECK_VTABLE(SI1, si_class); |
115 | CHECK(to<__si_class_type_info>(typeid(SI1)).__base_type == &typeid(A)); |
116 | |
117 | // SI2 has a single public empty base. |
118 | CHECK_VTABLE(SI2, si_class); |
119 | CHECK(to<__si_class_type_info>(typeid(SI2)).__base_type == &typeid(Empty)); |
120 | |
121 | // SI3 has a single public empty base. SI3 is dynamic whereas Empty is not, but since Empty is |
122 | // an empty class, it will still be at offset zero. |
123 | CHECK_VTABLE(SI3, si_class); |
124 | CHECK(to<__si_class_type_info>(typeid(SI3)).__base_type == &typeid(Empty)); |
125 | |
126 | // VMI1 has a single base, but it is private. |
127 | CHECK_VTABLE(VMI1, vmi_class); |
128 | |
129 | // VMI2 has a single base, but it is virtual. |
130 | CHECK_VTABLE(VMI2, vmi_class); |
131 | |
132 | // VMI3 has a single base, but VMI3 is dynamic whereas A is not, and A is not empty. |
133 | CHECK_VTABLE(VMI3, vmi_class); |
134 | |
135 | // VMI4 has two bases. |
136 | CHECK_VTABLE(VMI4, vmi_class); |
137 | |
138 | // VMI5 has non-diamond shaped inheritance. |
139 | CHECK_VTABLE(VMI5, vmi_class); |
140 | CHECK(to<__vmi_class_type_info>(typeid(VMI5)).__flags == __vmi_class_type_info::__non_diamond_repeat_mask); |
141 | CHECK(to<__vmi_class_type_info>(typeid(VMI5)).__base_count == 2); |
142 | CHECK_BASE_INFO_TYPE(VMI5, 0, VMIBase1); |
143 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI5, 0, 0, __base_class_type_info::__public_mask); |
144 | CHECK_BASE_INFO_TYPE(VMI5, 1, VMIBase2); |
145 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI5, 1, 4, __base_class_type_info::__public_mask); |
146 | |
147 | // VMI6 has diamond shaped inheritance. |
148 | CHECK_VTABLE(VMI6, vmi_class); |
149 | CHECK(to<__vmi_class_type_info>(typeid(VMI6)).__flags == __vmi_class_type_info::__diamond_shaped_mask); |
150 | CHECK(to<__vmi_class_type_info>(typeid(VMI6)).__base_count == 2); |
151 | CHECK_BASE_INFO_TYPE(VMI6, 0, VMIBase1); |
152 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI6, 0, -24, __base_class_type_info::__public_mask | __base_class_type_info::__virtual_mask); |
153 | CHECK_BASE_INFO_TYPE(VMI6, 1, VMIBase3); |
154 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI6, 1, 0, __base_class_type_info::__public_mask); |
155 | |
156 | // VMI7 has both non-diamond and diamond shaped inheritance. |
157 | CHECK_VTABLE(VMI7, vmi_class); |
158 | CHECK(to<__vmi_class_type_info>(typeid(VMI7)).__flags == (__vmi_class_type_info::__non_diamond_repeat_mask | __vmi_class_type_info::__diamond_shaped_mask)); |
159 | CHECK(to<__vmi_class_type_info>(typeid(VMI7)).__base_count == 3); |
160 | CHECK_BASE_INFO_TYPE(VMI7, 0, VMIBase1); |
161 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 0, 16, __base_class_type_info::__public_mask); |
162 | CHECK_BASE_INFO_TYPE(VMI7, 1, VMI5); |
163 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 1, 20, __base_class_type_info::__public_mask); |
164 | CHECK_BASE_INFO_TYPE(VMI7, 2, VMI6); |
165 | CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 2, 0, 0); |
166 | |
167 | // Pointers to incomplete classes. |
168 | CHECK_VTABLE(Incomplete *, pointer); |
169 | CHECK(to<__pbase_type_info>(typeid(Incomplete *)).__flags == __pbase_type_info::__incomplete_mask); |
170 | CHECK(to<__pbase_type_info>(typeid(Incomplete **)).__flags == __pbase_type_info::__incomplete_mask); |
171 | CHECK(to<__pbase_type_info>(typeid(Incomplete ***)).__flags == __pbase_type_info::__incomplete_mask); |
172 | |
173 | // Member pointers. |
174 | CHECK_VTABLE(int Incomplete::*, pointer_to_member); |
175 | CHECK(to<__pbase_type_info>(typeid(int Incomplete::*)).__flags == __pbase_type_info::__incomplete_class_mask); |
176 | CHECK(to<__pbase_type_info>(typeid(Incomplete Incomplete::*)).__flags == (__pbase_type_info::__incomplete_class_mask | __pbase_type_info::__incomplete_mask)); |
177 | CHECK(to<__pbase_type_info>(typeid(Incomplete A::*)).__flags == (__pbase_type_info::__incomplete_mask)); |
178 | |
179 | // Check that when stripping qualifiers off the pointee type, we correctly handle arrays. |
180 | CHECK(to<__pbase_type_info>(typeid(B::a)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); |
181 | CHECK(to<__pbase_type_info>(typeid(B::a)).__pointee == to<__pbase_type_info>(typeid(B::b)).__pointee); |
182 | CHECK(to<__pbase_type_info>(typeid(B::c)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); |
183 | CHECK(to<__pbase_type_info>(typeid(B::c)).__pointee == to<__pbase_type_info>(typeid(B::d)).__pointee); |
184 | |
185 | // Success! |
186 | // CHECK: ret i32 0 |
187 | return 0; |
188 | } |
189 | |
190 | #ifdef HARNESS |
191 | extern "C" void printf(const char *, ...); |
192 | |
193 | int main() { |
194 | int result = f(); |
195 | |
196 | if (result == 0) |
197 | printf("success!\n"); |
198 | else |
199 | printf("test on line %d failed!\n", result); |
200 | |
201 | return result; |
202 | } |
203 | #endif |
204 | |
205 | |
206 | |