[Lldb-commits] [clang] [lldb] [clang][DebugInfo][gmodules] Set runtimeLang on ObjC forward declarations (PR #120154)

via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 16 14:38:49 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb

@llvm/pr-subscribers-clang

Author: Michael Buch (Michael137)

<details>
<summary>Changes</summary>

In Objective-C, forward declarations are currently represented as:
```
DW_TAG_structure_type
  DW_AT_name                ("Foo")
  DW_AT_declaration         (true)
  DW_AT_APPLE_runtime_class (DW_LANG_ObjC)
```
However, when compiling with `-gmodules`, when a class definition is turned into a forward declaration within a `DW_TAG_module`, the DIE for the forward declaration looks as follows:
```
DW_TAG_structure_type
  DW_AT_name                ("Foo")
  DW_AT_declaration         (true)
```

Note the absence of `DW_AT_APPLE_runtime_class`. With recent changes in LLDB, not being able to differentiate between C++ and Objective-C forward declarations has become problematic (see attached test-case and explanation in https://github.com/llvm/llvm-project/pull/119860).

---
Full diff: https://github.com/llvm/llvm-project/pull/120154.diff


4 Files Affected:

- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+6-5) 
- (modified) clang/test/Modules/ExtDebugInfo.m (+2-1) 
- (modified) clang/test/Modules/ModuleDebugInfo.m (+1) 
- (added) lldb/test/Shell/SymbolFile/DWARF/objc-gmodules-class-extension.test (+34) 


``````````diff
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 60f32f76109e9a..ff27690d47b080 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2995,20 +2995,21 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
   if (!ID)
     return nullptr;
 
+  auto RuntimeLang =
+      static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
+
   // Return a forward declaration if this type was imported from a clang module,
   // and this is not the compile unit with the implementation of the type (which
   // may contain hidden ivars).
   if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition() &&
       !ID->getImplementation())
-    return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
-                                      ID->getName(),
-                                      getDeclContextDescriptor(ID), Unit, 0);
+    return DBuilder.createForwardDecl(
+        llvm::dwarf::DW_TAG_structure_type, ID->getName(),
+        getDeclContextDescriptor(ID), Unit, 0, RuntimeLang);
 
   // Get overall information about the record type for the debug info.
   llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());
   unsigned Line = getLineNumber(ID->getLocation());
-  auto RuntimeLang =
-      static_cast<llvm::dwarf::SourceLanguage>(TheCU->getSourceLanguage());
 
   // If this is just a forward declaration return a special forward-declaration
   // debug type since we won't be able to lay out the entire type.
diff --git a/clang/test/Modules/ExtDebugInfo.m b/clang/test/Modules/ExtDebugInfo.m
index b6a8b2676e5ba4..e2611ae5300634 100644
--- a/clang/test/Modules/ExtDebugInfo.m
+++ b/clang/test/Modules/ExtDebugInfo.m
@@ -75,7 +75,8 @@ int foo(ObjCClass *c) {
 
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
 // CHECK-SAME:             scope: ![[MOD]],
-// CHECK-SAME:             flags: DIFlagFwdDecl)
+// CHECK-SAME:             flags: DIFlagFwdDecl,
+// CHECK-SAME:             runtimeLang: DW_LANG_ObjC)
 
 // CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type,
 // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type,
diff --git a/clang/test/Modules/ModuleDebugInfo.m b/clang/test/Modules/ModuleDebugInfo.m
index 62c6fd68dd8546..c527c43a0f4a2c 100644
--- a/clang/test/Modules/ModuleDebugInfo.m
+++ b/clang/test/Modules/ModuleDebugInfo.m
@@ -39,6 +39,7 @@
 
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDecl",
 // CHECK-SAME:             scope: ![[MODULE]],
+// CHECK-SAME:             runtimeLang: DW_LANG_ObjC
 
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
 // CHECK-SAME:             scope: ![[MODULE]],
diff --git a/lldb/test/Shell/SymbolFile/DWARF/objc-gmodules-class-extension.test b/lldb/test/Shell/SymbolFile/DWARF/objc-gmodules-class-extension.test
new file mode 100644
index 00000000000000..330a6b338c4723
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/objc-gmodules-class-extension.test
@@ -0,0 +1,34 @@
+# REQUIRES: system-darwin
+
+# Test that we can set a breakpoint in a method of a class extension.
+# This requires us to parse the method into an AST type, and the context
+# too (which in DWARF is just a forward declaration).
+#
+# RUN: split-file %s %t
+# RUN: %clangxx_host %t/lib.m  -c -g -gmodules -fmodules -o %t/lib.o
+# RUN: %clangxx_host %t/main.m -g -gmodules -fmodules %t/lib.o -o %t/a.out -framework Foundation
+#
+# RUN: %lldb %t/a.out -o "breakpoint set -f lib.m -l 6" -o exit | FileCheck %s
+
+# CHECK: (lldb) breakpoint set -f lib.m -l 6
+# CHECK: Breakpoint 1: where = a.out`-[NSObject(Foo) func]
+
+#--- main.m
+int main() {
+  return 0;
+}
+
+#--- lib.m
+#import <Foundation/Foundation.h>
+
+ at implementation NSObject (Foo)
+- (NSError *)func {
+    NSLog(@"Hello, World!");
+    return 0;
+}
+ at end
+
+NSObject * func() {
+  return 0;
+}
+

``````````

</details>


https://github.com/llvm/llvm-project/pull/120154


More information about the lldb-commits mailing list