https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/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 >From 26cad4ef1a92939400cea4781661204dab443c16 Mon Sep 17 00:00:00 2001 From: Michael Buch <michaelbuc...@gmail.com> Date: Wed, 3 Sep 2025 15:29:40 +0100 Subject: [PATCH] [lldb][DWARFASTParserClang] Don't complete conflicting Objective-C++ types 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 --- .../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 a429ea848b7f7..0f1f41baced86 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2230,6 +2230,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!"; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits