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