[clang] [CIR] Implement vTableClassName for Type::ObjCObject (PR #195232)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 1 10:11:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Dylan Leifer-Ives (dleiferives)
<details>
<summary>Changes</summary>
Implements `Type::ObjCObject` case in `vTableClassNameForType` and `buildTypeInfo` in `CIRGenItaniumCXXABI.cpp`. Mirroring implementation in `ItaniumCXXABI.cpp`.
In `vTableClassNameForType` handles the builtin types directly and returns `__class_type_info`. The ObjCInterface sub-case falls through to `errorNYI` as it belongs to the separate `Type::ObjCInterface` subissue.
Also fixes `builtTypeInfo` for `Type::ObjCObjectPointer`, which was `errorNYI` in #<!-- -->184011 probably over looked as it was handled in `vTableClassNameForType`. This fix to `builtTypeInfo` is load-bearing: `typeid(id)` calls `buildTypeInfo(ObjCObjectPointerType)` first, which must delegate to `buildPointerTypeInfo` before recursing into the `ObjCObject` case. Without it the `rtti-objc.mm` test fails.
`rtti-objc.mm` verifies RTTI emission for `typeid(id)` and `typeid(Class)`. Type operands are used to emit `Type::ObjCObject` for testability as the regular path of `convertType(ObjCObjectPointerType)` is NYI in CIRGenTypes. The test covers both the `ObjCObjectPointer` and `ObjCObject` paths through both CIR and LLVM lowering.
Furthers #<!-- -->163601
---
Full diff: https://github.com/llvm/llvm-project/pull/195232.diff
2 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp (+20-6)
- (added) clang/test/CIR/CodeGen/rtti-objc.mm (+47)
``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 946739d4e1702..517fb30642e31 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -1074,8 +1074,15 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
}
case Type::ObjCObject:
- cgm.errorNYI("VTableClassNameForType: ObjCObject");
- break;
+ // Ignore protocol qualifiers.
+ ty = cast<ObjCObjectType>(ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(ty))
+ return classTypeInfo;
+
+ assert(isa<ObjCInterfaceType>(ty));
+ [[fallthrough]];
case Type::ObjCInterface:
cgm.errorNYI("VTableClassNameForType: ObjCInterface");
@@ -1564,17 +1571,24 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
break;
}
- case Type::ObjCObject:
+ case Type::ObjCObject: {
+ // Drop protocol qualifiers.
+ const Type *T = cast<ObjCObjectType>(ty)->getBaseType().getTypePtr();
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T))
+ break;
+ } [[fallthrough]];
+
case Type::ObjCInterface:
- cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");
+ cgm.errorNYI("buildTypeInfo: ObjCInterface");
break;
case Type::ObjCObjectPointer:
- cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");
+ buildPointerTypeInfo(loc, cast<ObjCObjectPointerType>(ty)->getPointeeType());
break;
case Type::Pointer:
- // We need to get the type info for the pointee type.
buildPointerTypeInfo(loc, cast<PointerType>(ty)->getPointeeType());
break;
diff --git a/clang/test/CIR/CodeGen/rtti-objc.mm b/clang/test/CIR/CodeGen/rtti-objc.mm
new file mode 100644
index 0000000000000..8fceefb0767b8
--- /dev/null
+++ b/clang/test/CIR/CodeGen/rtti-objc.mm
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -x objective-c++
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll -x objective-c++
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll -x objective-c++
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// RTTI emission of ObjCObject for Objective C builtin types via typeid. Type operands were
+// used to avoid using convertType(ObjCObjectPointerType) as it is NYI in
+// CIRGenTypes.
+
+namespace std { class type_info; }
+
+void f() {
+ const std::type_info &t1 = typeid(id);
+ const std::type_info &t2 = typeid(Class);
+}
+
+// CIR-DAG: cir.global {{.*}} @_ZTS11objc_object = #cir.const_array<"11objc_object" : !cir.array<!s8i x 13>, trailing_zeros> : !cir.array<!s8i x 14>
+// CIR-DAG: cir.global {{.*}} @_ZTI11objc_object = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS11objc_object> : !cir.ptr<!u8i>}>
+// CIR-DAG: cir.global {{.*}} @_ZTSP11objc_object = #cir.const_array<"P11objc_object" : !cir.array<!s8i x 14>, trailing_zeros> : !cir.array<!s8i x 15>
+// CIR-DAG: cir.global {{.*}} @_ZTIP11objc_object = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv119__pointer_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSP11objc_object> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTI11objc_object> : !cir.ptr<!u8i>}>
+
+// CIR-DAG: cir.global {{.*}} @_ZTS10objc_class = #cir.const_array<"10objc_class" : !cir.array<!s8i x 12>, trailing_zeros> : !cir.array<!s8i x 13>
+// CIR-DAG: cir.global {{.*}} @_ZTI10objc_class = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv117__class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS10objc_class> : !cir.ptr<!u8i>}>
+// CIR-DAG: cir.global {{.*}} @_ZTSP10objc_class = #cir.const_array<"P10objc_class" : !cir.array<!s8i x 13>, trailing_zeros> : !cir.array<!s8i x 14>
+// CIR-DAG: cir.global {{.*}} @_ZTIP10objc_class = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv119__pointer_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTSP10objc_class> : !cir.ptr<!u8i>, #cir.int<0> : !u32i, #cir.global_view<@_ZTI10objc_class> : !cir.ptr<!u8i>}>
+
+// LLVM-DAG: @_ZTS11objc_object = linkonce_odr global [14 x i8] c"11objc_object\00", comdat
+// LLVM-DAG: @_ZTI11objc_object = linkonce_odr constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS11objc_object }, comdat
+// LLVM-DAG: @_ZTSP11objc_object = linkonce_odr global [15 x i8] c"P11objc_object\00", comdat
+// LLVM-DAG: @_ZTIP11objc_object = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 16), ptr @_ZTSP11objc_object, i32 0, ptr @_ZTI11objc_object }, comdat
+
+// LLVM-DAG: @_ZTS10objc_class = linkonce_odr global [13 x i8] c"10objc_class\00", comdat
+// LLVM-DAG: @_ZTI10objc_class = linkonce_odr constant { ptr, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 16), ptr @_ZTS10objc_class }, comdat
+// LLVM-DAG: @_ZTSP10objc_class = linkonce_odr global [14 x i8] c"P10objc_class\00", comdat
+// LLVM-DAG: @_ZTIP10objc_class = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr (i8, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 16), ptr @_ZTSP10objc_class, i32 0, ptr @_ZTI10objc_class }, comdat
+
+// OGCG-DAG: @_ZTS11objc_object = linkonce_odr constant [14 x i8] c"11objc_object\00", comdat
+// OGCG-DAG: @_ZTI11objc_object = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS11objc_object }, comdat
+// OGCG-DAG: @_ZTSP11objc_object = linkonce_odr constant [15 x i8] c"P11objc_object\00", comdat
+// OGCG-DAG: @_ZTIP11objc_object = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2), ptr @_ZTSP11objc_object, i32 0, ptr @_ZTI11objc_object }, comdat
+
+// OGCG-DAG: @_ZTS10objc_class = linkonce_odr constant [13 x i8] c"10objc_class\00", comdat
+// OGCG-DAG: @_ZTI10objc_class = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS10objc_class }, comdat
+// OGCG-DAG: @_ZTSP10objc_class = linkonce_odr constant [14 x i8] c"P10objc_class\00", comdat
+// OGCG-DAG: @_ZTIP10objc_class = linkonce_odr constant { ptr, ptr, i32, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2), ptr @_ZTSP10objc_class, i32 0, ptr @_ZTI10objc_class }, comdat
``````````
</details>
https://github.com/llvm/llvm-project/pull/195232
More information about the cfe-commits
mailing list