diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CodeGenCXX/rtti-layout.cpp | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CodeGenCXX/rtti-layout.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/rtti-layout.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/rtti-layout.cpp b/clang/test/CodeGenCXX/rtti-layout.cpp new file mode 100644 index 0000000..7128c4e --- /dev/null +++ b/clang/test/CodeGenCXX/rtti-layout.cpp @@ -0,0 +1,205 @@ +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s +#include <typeinfo> + +// vtables. +extern "C" { + const void *_ZTVN10__cxxabiv123__fundamental_type_infoE; + const void *_ZTVN10__cxxabiv117__class_type_infoE; + const void *_ZTVN10__cxxabiv120__si_class_type_infoE; + const void *_ZTVN10__cxxabiv121__vmi_class_type_infoE; + const void *_ZTVN10__cxxabiv119__pointer_type_infoE; + const void *_ZTVN10__cxxabiv129__pointer_to_member_type_infoE; +}; +#define fundamental_type_info_vtable _ZTVN10__cxxabiv123__fundamental_type_infoE +#define class_type_info_vtable _ZTVN10__cxxabiv117__class_type_infoE +#define si_class_type_info_vtable _ZTVN10__cxxabiv120__si_class_type_infoE +#define vmi_class_type_info_vtable _ZTVN10__cxxabiv121__vmi_class_type_infoE +#define pointer_type_info_vtable _ZTVN10__cxxabiv119__pointer_type_infoE +#define pointer_to_member_type_info_vtable _ZTVN10__cxxabiv129__pointer_to_member_type_infoE + +class __pbase_type_info : public std::type_info { +public: + unsigned int __flags; + const std::type_info *__pointee; + + enum __masks { + __const_mask = 0x1, + __volatile_mask = 0x2, + __restrict_mask = 0x4, + __incomplete_mask = 0x8, + __incomplete_class_mask = 0x10 + }; +}; + +class __class_type_info : public std::type_info { }; + +class __si_class_type_info : public __class_type_info { +public: + const __class_type_info *__base_type; +}; + +struct __base_class_type_info { +public: + const __class_type_info *__base_type; + long __offset_flags; + + enum __offset_flags_masks { + __virtual_mask = 0x1, + __public_mask = 0x2, + __offset_shift = 8 + }; +}; + +class __vmi_class_type_info : public __class_type_info { +public: + unsigned int __flags; + unsigned int __base_count; + __base_class_type_info __base_info[1]; + + enum __flags_masks { + __non_diamond_repeat_mask = 0x1, + __diamond_shaped_mask = 0x2 + }; +}; + +template<typename T> const T& to(const std::type_info &info) { +return static_cast<const T&>(info); +} +struct Incomplete; + +struct A { int a; }; +struct Empty { }; + +struct SI1 : A { }; +struct SI2 : Empty { }; +struct SI3 : Empty { virtual void f() { } }; + +struct VMI1 : private A { }; +struct VMI2 : virtual A { }; +struct VMI3 : A { virtual void f() { } }; +struct VMI4 : A, Empty { }; + +struct VMIBase1 { int a; }; +struct VMIBase2 : VMIBase1 { int a; }; +struct VMI5 : VMIBase1, VMIBase2 { int a; }; + +struct VMIBase3 : virtual VMIBase1 { int a; }; +struct VMI6 : virtual VMIBase1, VMIBase3 { int a; }; + +struct VMI7 : VMIBase1, VMI5, private VMI6 { }; + +#define CHECK(x) if (!(x)) return __LINE__ +#define CHECK_VTABLE(type, vtable) CHECK(&vtable##_type_info_vtable + 2 == (((void **)&(typeid(type)))[0])) +#define CHECK_BASE_INFO_TYPE(type, index, base) CHECK(to<__vmi_class_type_info>(typeid(type)).__base_info[(index)].__base_type == &typeid(base)) +#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))) + +struct B { + static int const volatile (*a)[10]; + static int (*b)[10]; + + static int const volatile (B::*c)[10]; + static int (B::*d)[10]; +}; + +// CHECK: define i32 @_Z1fv() +int f() { + // Vectors should be treated as fundamental types. + typedef short __v4hi __attribute__ ((__vector_size__ (8))); + CHECK_VTABLE(__v4hi, fundamental); + + // A does not have any bases. + CHECK_VTABLE(A, class); + + // SI1 has a single public base. + CHECK_VTABLE(SI1, si_class); + CHECK(to<__si_class_type_info>(typeid(SI1)).__base_type == &typeid(A)); + + // SI2 has a single public empty base. + CHECK_VTABLE(SI2, si_class); + CHECK(to<__si_class_type_info>(typeid(SI2)).__base_type == &typeid(Empty)); + + // SI3 has a single public empty base. SI3 is dynamic whereas Empty is not, but since Empty is + // an empty class, it will still be at offset zero. + CHECK_VTABLE(SI3, si_class); + CHECK(to<__si_class_type_info>(typeid(SI3)).__base_type == &typeid(Empty)); + + // VMI1 has a single base, but it is private. + CHECK_VTABLE(VMI1, vmi_class); + + // VMI2 has a single base, but it is virtual. + CHECK_VTABLE(VMI2, vmi_class); + + // VMI3 has a single base, but VMI3 is dynamic whereas A is not, and A is not empty. + CHECK_VTABLE(VMI3, vmi_class); + + // VMI4 has two bases. + CHECK_VTABLE(VMI4, vmi_class); + + // VMI5 has non-diamond shaped inheritance. + CHECK_VTABLE(VMI5, vmi_class); + CHECK(to<__vmi_class_type_info>(typeid(VMI5)).__flags == __vmi_class_type_info::__non_diamond_repeat_mask); + CHECK(to<__vmi_class_type_info>(typeid(VMI5)).__base_count == 2); + CHECK_BASE_INFO_TYPE(VMI5, 0, VMIBase1); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI5, 0, 0, __base_class_type_info::__public_mask); + CHECK_BASE_INFO_TYPE(VMI5, 1, VMIBase2); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI5, 1, 4, __base_class_type_info::__public_mask); + + // VMI6 has diamond shaped inheritance. + CHECK_VTABLE(VMI6, vmi_class); + CHECK(to<__vmi_class_type_info>(typeid(VMI6)).__flags == __vmi_class_type_info::__diamond_shaped_mask); + CHECK(to<__vmi_class_type_info>(typeid(VMI6)).__base_count == 2); + CHECK_BASE_INFO_TYPE(VMI6, 0, VMIBase1); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI6, 0, -24, __base_class_type_info::__public_mask | __base_class_type_info::__virtual_mask); + CHECK_BASE_INFO_TYPE(VMI6, 1, VMIBase3); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI6, 1, 0, __base_class_type_info::__public_mask); + + // VMI7 has both non-diamond and diamond shaped inheritance. + CHECK_VTABLE(VMI7, vmi_class); + CHECK(to<__vmi_class_type_info>(typeid(VMI7)).__flags == (__vmi_class_type_info::__non_diamond_repeat_mask | __vmi_class_type_info::__diamond_shaped_mask)); + CHECK(to<__vmi_class_type_info>(typeid(VMI7)).__base_count == 3); + CHECK_BASE_INFO_TYPE(VMI7, 0, VMIBase1); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 0, 16, __base_class_type_info::__public_mask); + CHECK_BASE_INFO_TYPE(VMI7, 1, VMI5); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 1, 20, __base_class_type_info::__public_mask); + CHECK_BASE_INFO_TYPE(VMI7, 2, VMI6); + CHECK_BASE_INFO_OFFSET_FLAGS(VMI7, 2, 0, 0); + + // Pointers to incomplete classes. + CHECK_VTABLE(Incomplete *, pointer); + CHECK(to<__pbase_type_info>(typeid(Incomplete *)).__flags == __pbase_type_info::__incomplete_mask); + CHECK(to<__pbase_type_info>(typeid(Incomplete **)).__flags == __pbase_type_info::__incomplete_mask); + CHECK(to<__pbase_type_info>(typeid(Incomplete ***)).__flags == __pbase_type_info::__incomplete_mask); + + // Member pointers. + CHECK_VTABLE(int Incomplete::*, pointer_to_member); + CHECK(to<__pbase_type_info>(typeid(int Incomplete::*)).__flags == __pbase_type_info::__incomplete_class_mask); + CHECK(to<__pbase_type_info>(typeid(Incomplete Incomplete::*)).__flags == (__pbase_type_info::__incomplete_class_mask | __pbase_type_info::__incomplete_mask)); + CHECK(to<__pbase_type_info>(typeid(Incomplete A::*)).__flags == (__pbase_type_info::__incomplete_mask)); + + // Check that when stripping qualifiers off the pointee type, we correctly handle arrays. + CHECK(to<__pbase_type_info>(typeid(B::a)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); + CHECK(to<__pbase_type_info>(typeid(B::a)).__pointee == to<__pbase_type_info>(typeid(B::b)).__pointee); + CHECK(to<__pbase_type_info>(typeid(B::c)).__flags == (__pbase_type_info::__const_mask | __pbase_type_info::__volatile_mask)); + CHECK(to<__pbase_type_info>(typeid(B::c)).__pointee == to<__pbase_type_info>(typeid(B::d)).__pointee); + + // Success! + // CHECK: ret i32 0 + return 0; +} + +#ifdef HARNESS +extern "C" void printf(const char *, ...); + +int main() { + int result = f(); + + if (result == 0) + printf("success!\n"); + else + printf("test on line %d failed!\n", result); + + return result; +} +#endif + + |