Author: Adrian Prantl
Date: 2026-10-21T15:03:58-07:00
New Revision: ed07c22327fdc4ccddac4e44c32bc69c796be782

URL: 
https://github.com/llvm/llvm-project/commit/ed07c22327fdc4ccddac4e44c32bc69c796be782
DIFF: 
https://github.com/llvm/llvm-project/commit/ed07c22327fdc4ccddac4e44c32bc69c796be782.diff

LOG: [clang][DebugInfo] Record objc_runtime_name of ObjC interfaces  (#233647)

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

Added: 
    clang/test/DebugInfo/ObjC/objc-runtime-name.m

Modified: 
    clang/lib/CodeGen/CGDebugInfo.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp 
b/clang/lib/CodeGen/CGDebugInfo.cpp
index da62fbbec20590..96cda4555e49db 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3710,10 +3710,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 00000000000000..1102969e757992
--- /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 
diff ers from the source name.
+
+__attribute__((objc_root_class))
+@interface Root
+@end
+
+@implementation Root
+@end
+
+__attribute__((objc_runtime_name("_$s4main7DefinedC")))
+@interface Defined : Root
+@end
+
+@implementation Defined
+@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")))
+@interface Declared : Root
+@end
+
+Declared *d;
+
+__attribute__((objc_runtime_name("Same")))
+@interface Same : Root
+@end
+
+@implementation Same
+@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: {{$}}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to