[clang] [clang][DebugInfo] Record objc_runtime_name of ObjC interfaces (PR #233647)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 19 17:54:08 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Adrian Prantl (adrian-prantl)
<details>
<summary>Changes</summary>
An Objective-C class with a custom objc_runtime_name exports its class, metaclass, and ivar offset symbols under the runtime name, but the debug info only records the source name.
This causes problems in LLDB's expression evaluator since it will use the name recorded in the debug info for any ObjC metadata symbols.
This patch uses DW_TAG_LLVM_annotation to record the runtime name in the interface.
rdar://187396633
Assisted-by: Claude
---
Full diff: https://github.com/llvm/llvm-project/pull/233647.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+13-1)
- (added) clang/test/DebugInfo/ObjC/objc-runtime-name.m (+52)
``````````diff
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 93428777b9b24..487b7ad3192d0 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3693,10 +3693,22 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (ID->getImplementation())
Flags |= llvm::DINode::FlagObjcClassComplete;
+ llvm::DINodeArray Annotations;
+ const auto *RuntimeName = ID->getAttr<ObjCRuntimeNameAttr>();
+ if (RuntimeName && RuntimeName->getMetadataName() != ID->getName()) {
+ llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+ llvm::Metadata *Ops[2] = {
+ llvm::MDString::get(Ctx, "objc_runtime_name"),
+ llvm::MDString::get(Ctx, RuntimeName->getMetadataName())};
+ Annotations = DBuilder.getOrCreateArray({llvm::MDNode::get(Ctx, Ops)});
+ }
+
llvm::DIScope *Mod = getParentModuleOrNull(ID);
llvm::DICompositeType *RealDecl = DBuilder.createStructType(
Mod ? Mod : Unit, ID->getName(), DefUnit, Line, Size, Align, Flags,
- nullptr, llvm::DINodeArray(), RuntimeLang);
+ nullptr, llvm::DINodeArray(), RuntimeLang, /*VTableHolder=*/nullptr,
+ /*UniqueIdentifier=*/"", /*Specification=*/nullptr,
+ /*NumExtraInhabitants=*/0, Annotations);
QualType QTy(Ty, 0);
TypeCache[QTy.getAsOpaquePtr()].reset(RealDecl);
diff --git a/clang/test/DebugInfo/ObjC/objc-runtime-name.m b/clang/test/DebugInfo/ObjC/objc-runtime-name.m
new file mode 100644
index 0000000000000..1102969e75799
--- /dev/null
+++ b/clang/test/DebugInfo/ObjC/objc-runtime-name.m
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o %t.ll
+// RUN: FileCheck %s < %t.ll
+// RUN: FileCheck %s --check-prefix=ROOT < %t.ll
+// RUN: FileCheck %s --check-prefix=SAME < %t.ll
+
+// The Objective-C runtime name of a class is recorded in the debug info when
+// it differs from the source name.
+
+__attribute__((objc_root_class))
+ at interface Root
+ at end
+
+ at implementation Root
+ at end
+
+__attribute__((objc_runtime_name("_$s4main7DefinedC")))
+ at interface Defined : Root
+ at end
+
+ at implementation Defined
+ at end
+
+// A class implemented in another TU, such as a Swift class declared in a
+// generated header, is completed at the end of the TU and must carry the
+// runtime name as well.
+__attribute__((objc_runtime_name("_$s4main8DeclaredC")))
+ at interface Declared : Root
+ at end
+
+Declared *d;
+
+__attribute__((objc_runtime_name("Same")))
+ at interface Same : Root
+ at end
+
+ at implementation Same
+ at end
+
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Defined",{{.*}}annotations: ![[DEFINED:[0-9]+]]
+// CHECK-DAG: ![[DEFINED]] = !{![[DEFINED_NAME:[0-9]+]]}
+// CHECK-DAG: ![[DEFINED_NAME]] = !{!"objc_runtime_name", !"_$s4main7DefinedC"}
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Declared",{{.*}}annotations: ![[DECLARED:[0-9]+]]
+// CHECK-DAG: ![[DECLARED]] = !{![[DECLARED_NAME:[0-9]+]]}
+// CHECK-DAG: ![[DECLARED_NAME]] = !{!"objc_runtime_name", !"_$s4main8DeclaredC"}
+
+// ROOT: !DICompositeType(tag: DW_TAG_structure_type, name: "Root",
+// ROOT-NOT: annotations:
+// ROOT-SAME: {{$}}
+
+// SAME: !DICompositeType(tag: DW_TAG_structure_type, name: "Same",
+// SAME-NOT: annotations:
+// SAME-SAME: {{$}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/233647
More information about the cfe-commits
mailing list