From 398dc37d1f52788b2cd9835bd2e51458d579045d Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 12 Aug 2010 02:17:33 +0000 Subject: [PATCH] Implement RTTI generation for Objective C types. Fixes PR7864. llvm-svn: 110900 --- clang/lib/CodeGen/CGRTTI.cpp | 89 ++++++++++++++++++++++++++------ clang/test/CodeGenObjCXX/rtti.mm | 52 +++++++++++++++++++ 2 files changed, 125 insertions(+), 16 deletions(-) create mode 100644 clang/test/CodeGenObjCXX/rtti.mm diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index 7dce9a0f5fa8..69171419b66f 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -45,7 +45,11 @@ class RTTIBuilder { /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used /// for pointer types. - void BuildPointerTypeInfo(const PointerType *Ty); + void BuildPointerTypeInfo(QualType PointeeTy); + + /// BuildObjCObjectTypeInfo - Build the appropriate kind of + /// type_info for an object type. + void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty); /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info /// struct, used for member pointer types. @@ -390,6 +394,16 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { } void RTTIBuilder::BuildVTablePointer(const Type *Ty) { + // abi::__class_type_info. + static const char * const ClassTypeInfo = + "_ZTVN10__cxxabiv117__class_type_infoE"; + // abi::__si_class_type_info. + static const char * const SIClassTypeInfo = + "_ZTVN10__cxxabiv120__si_class_type_infoE"; + // abi::__vmi_class_type_info. + static const char * const VMIClassTypeInfo = + "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + const char *VTableName = 0; switch (Ty->getTypeClass()) { @@ -433,32 +447,44 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { // abi::__enum_type_info. VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; break; - + case Type::Record: { const CXXRecordDecl *RD = cast(cast(Ty)->getDecl()); if (!RD->hasDefinition() || !RD->getNumBases()) { - // abi::__class_type_info. - VTableName = "_ZTVN10__cxxabiv117__class_type_infoE"; + VTableName = ClassTypeInfo; } else if (CanUseSingleInheritance(RD)) { - // abi::__si_class_type_info. - VTableName = "_ZTVN10__cxxabiv120__si_class_type_infoE"; + VTableName = SIClassTypeInfo; } else { - // abi::__vmi_class_type_info. - VTableName = "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + VTableName = VMIClassTypeInfo; } break; } case Type::ObjCObject: + // Ignore protocol qualifiers. + Ty = cast(Ty)->getBaseType().getTypePtr(); + + // Handle id and Class. + if (isa(Ty)) { + VTableName = ClassTypeInfo; + break; + } + + assert(isa(Ty)); + // Fall through. + case Type::ObjCInterface: - case Type::ObjCObjectPointer: - assert(false && "FIXME: Needs to be written!"); - VTableName = "_ZTVN10__cxxabiv117__class_type_infoE"; + if (cast(Ty)->getDecl()->getSuperClass()) { + VTableName = SIClassTypeInfo; + } else { + VTableName = ClassTypeInfo; + } break; + case Type::ObjCObjectPointer: case Type::Pointer: // abi::__pointer_type_info. VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; @@ -559,11 +585,20 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { break; } + + case Type::ObjCObject: + case Type::ObjCInterface: + BuildObjCObjectTypeInfo(cast(Ty)); + break; + + case Type::ObjCObjectPointer: + BuildPointerTypeInfo(cast(Ty)->getPointeeType()); + break; case Type::Pointer: - BuildPointerTypeInfo(cast(Ty)); + BuildPointerTypeInfo(cast(Ty)->getPointeeType()); break; - + case Type::MemberPointer: BuildPointerToMemberTypeInfo(cast(Ty)); break; @@ -612,6 +647,30 @@ static unsigned ComputeQualifierFlags(Qualifiers Quals) { return Flags; } +/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info +/// for the given Objective-C object type. +void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { + // Drop qualifiers. + const Type *T = OT->getBaseType().getTypePtr(); + assert(isa(T) || isa(T)); + + // The builtin types are abi::__class_type_infos and don't require + // extra fields. + if (isa(T)) return; + + ObjCInterfaceDecl *Class = cast(T)->getDecl(); + ObjCInterfaceDecl *Super = Class->getSuperClass(); + + // Root classes are also __class_type_info. + if (!Super) return; + + QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super); + + // Everything else is single inheritance. + llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy); + Fields.push_back(BaseTypeInfo); +} + /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single /// inheritance, according to the Itanium C++ ABI, 2.95p6b. void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { @@ -767,9 +826,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, /// used for pointer types. -void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) { - QualType PointeeTy = Ty->getPointeeType(); - +void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { Qualifiers Quals; QualType UnqualifiedPointeeTy = CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); diff --git a/clang/test/CodeGenObjCXX/rtti.mm b/clang/test/CodeGenObjCXX/rtti.mm new file mode 100644 index 000000000000..d24eaa62e25c --- /dev/null +++ b/clang/test/CodeGenObjCXX/rtti.mm @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// PR7864. This all follows GCC's lead. + +namespace std { class type_info; } + +// CHECK: @_ZTI1A = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A +@interface A +@end + +// CHECK: @_ZTI1B = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A +@interface B : A +@end + +// CHECK: @_ZTIP1B = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP1B{{.*}}), i32 0, {{.*}}@_ZTI1B +// CHECK: @_ZTI11objc_object = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object +// CHECK: @_ZTIP11objc_object = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP11objc_object{{.*}}@_ZTI11objc_object +// CHECK: @_ZTI10objc_class = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class +// CHECK: @_ZTIP10objc_class = weak_odr hidden constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP10objc_class{{.*}}@_ZTI10objc_class + +@protocol P; + +int main() { + // CHECK: store {{.*}} @_ZTIP1B + // CHECK: store {{.*}} @_ZTI1B + const std::type_info &t1 = typeid(B*); + const std::type_info &t2 = typeid(B); + + // CHECK: store {{.*}} @_ZTIP11objc_object + // CHECK: store {{.*}} @_ZTI11objc_object + id i = 0; + const std::type_info &t3 = typeid(i); + const std::type_info &t4 = typeid(*i); + + // CHECK: store {{.*}} @_ZTIP10objc_class + // CHECK: store {{.*}} @_ZTI10objc_class + Class c = 0; + const std::type_info &t5 = typeid(c); + const std::type_info &t6 = typeid(*c); + + // CHECK: store {{.*}} @_ZTIP11objc_object + // CHECK: store {{.*}} @_ZTI11objc_object + id

i2 = 0; + const std::type_info &t7 = typeid(i2); + const std::type_info &t8 = typeid(*i2); + + // CHECK: store {{.*}} @_ZTIP10objc_class + // CHECK: store {{.*}} @_ZTI10objc_class + Class

c2 = 0; + const std::type_info &t9 = typeid(c2); + const std::type_info &t10 = typeid(*c2); +}