https://github.com/llvmbot created 
https://github.com/llvm/llvm-project/pull/156764

Backport a862225813c251c28b085603b7d32d4b111dbc57

Requested by: @Michael137

>From 4afd084013a57eb6ae27f46458d9e4115599a6a9 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Wed, 3 Sep 2025 20:04:53 +0100
Subject: [PATCH] [lldb][DWARFASTParserClang] Don't complete conflicting
 Objective-C++ types (#156681)

This upstreams https://github.com/swiftlang/llvm-project/pull/10313.

If we detect a situation where a forward declaration is C++ and the
definition DIE is Objective-C, then just don't try to complete the type
(it would crash otherwise). In the long term we might want to add
support for completing such types.

We've seen real world crashes when debugging WebKit and wxWidgets
because of this. Both projects forward declare ObjC++ decls in the way
shown in the test.

rdar://145959981
(cherry picked from commit a862225813c251c28b085603b7d32d4b111dbc57)
---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 12 ++++
 .../DWARF/objcxx-forward-decls.test           | 70 +++++++++++++++++++
 2 files changed, 82 insertions(+)
 create mode 100644 lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index c76d67b47b336..8916c58beec0f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2201,6 +2201,18 @@ bool DWARFASTParserClang::CompleteRecordType(const 
DWARFDIE &die,
       for (DelayedAddObjCClassProperty &property : delayed_properties)
         property.Finalize();
     }
+  } else if (Language::LanguageIsObjC(
+                 static_cast<LanguageType>(die.GetAttributeValueAsUnsigned(
+                     DW_AT_APPLE_runtime_class, eLanguageTypeUnknown)))) {
+    /// The forward declaration was C++ but the definition is Objective-C.
+    /// We currently don't handle such situations. In such cases, keep the
+    /// forward declaration without a definition to avoid violating Clang AST
+    /// invariants.
+    LLDB_LOG(GetLog(LLDBLog::Expressions),
+             "WARNING: Type completion aborted because forward declaration for 
"
+             "'{0}' is C++ while definition is Objective-C.",
+             llvm::StringRef(die.GetName()));
+    return {};
   }
 
   if (!bases.empty()) {
diff --git a/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test 
b/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test
new file mode 100644
index 0000000000000..30109c2943c9b
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test
@@ -0,0 +1,70 @@
+# REQUIRES: system-darwin
+
+# In this test we have two CUs with conflicting forward declaration
+# depending on the CU language (one is C++ and the other is Objective-C++).
+# We are then stopped in the C++ CU and try to print the type, at which
+# point LLDB will try to make it into an Clang AST node. If LLDB were to
+# interpret the type as C++ instead of Objective-C, we'd violate Clang
+# invariants and crash.
+#
+# RUN: split-file %s %t
+# RUN: %clangxx_host -c -g -x objective-c++ %t/request.m -o %t/request_objc.o
+# RUN: %clangxx_host -c -g %t/main.cpp -o %t/main.o
+# RUN: %clangxx_host %t/main.o %t/request_objc.o -framework Foundation -o 
%t/a.out
+#
+# RUN: %lldb %t/a.out \
+# RUN:    -o "breakpoint set -p return -X main" \
+# RUN:    -o run \
+# RUN:    -o "frame variable r" \
+# RUN:    -o exit | FileCheck %s
+#
+# RUN: dsymutil %t/a.out
+#
+# RUN: %lldb %t/a.out \
+# RUN:    -o "breakpoint set -p return -X main" \
+# RUN:    -o run \
+# RUN:    -o "frame variable r" \
+# RUN:    -o exit | FileCheck %s --check-prefix=CHECK-DSYM
+
+# CHECK:      (lldb) frame variable r
+# CHECK-NEXT: (Request) ::r = (m_request = "Hello, World!")
+
+# CHECK-DSYM:      (lldb) frame variable r
+# CHECK-DSYM-NEXT: (Request) ::r = (m_request = "Hello, World!")
+
+#--- lib.h
+#ifndef LIB_H_IN
+#define LIB_H_IN
+
+#ifdef __OBJC__
+@class NSString;                                               
+#else
+class NSString;
+#endif
+
+struct Request {
+  NSString * m_request = nullptr;
+};
+
+#endif // _H_IN
+
+#--- main.cpp
+#include "lib.h"
+
+void process(Request *);
+
+Request r;
+
+int main() {
+    process(&r);
+    return 0;
+}
+
+#--- request.m
+#import <Foundation/Foundation.h>
+
+#include "lib.h"
+
+void process(Request * r) {
+  r->m_request = @"Hello, World!";
+}

_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to