Implement RTTI generation for Objective C types. Fixes PR7864.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110900 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 7dce9a0..6917141 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -45,7 +45,11 @@
/// 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 @@
}
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 @@
// abi::__enum_type_info.
VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
break;
-
+
case Type::Record: {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(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<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ VTableName = ClassTypeInfo;
+ break;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ // Fall through.
+
case Type::ObjCInterface:
- case Type::ObjCObjectPointer:
- assert(false && "FIXME: Needs to be written!");
- VTableName = "_ZTVN10__cxxabiv117__class_type_infoE";
+ if (cast<ObjCInterfaceType>(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 @@
break;
}
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
+ break;
+
+ case Type::ObjCObjectPointer:
+ BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ break;
case Type::Pointer:
- BuildPointerTypeInfo(cast<PointerType>(Ty));
+ BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
break;
-
+
case Type::MemberPointer:
BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
break;
@@ -612,6 +647,30 @@
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<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
+
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T)) return;
+
+ ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(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 @@
/// 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/test/CodeGenObjCXX/rtti.mm b/test/CodeGenObjCXX/rtti.mm
new file mode 100644
index 0000000..d24eaa6
--- /dev/null
+++ b/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<P> 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<P> c2 = 0;
+ const std::type_info &t9 = typeid(c2);
+ const std::type_info &t10 = typeid(*c2);
+}