Skip to content

Commit a862225

Browse files
authored
[lldb][DWARFASTParserClang] Don't complete conflicting Objective-C++ types (#156681)
This upstreams swiftlang#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
1 parent 7b96cd7 commit a862225

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,6 +2230,18 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
22302230
for (DelayedAddObjCClassProperty &property : delayed_properties)
22312231
property.Finalize();
22322232
}
2233+
} else if (Language::LanguageIsObjC(
2234+
static_cast<LanguageType>(die.GetAttributeValueAsUnsigned(
2235+
DW_AT_APPLE_runtime_class, eLanguageTypeUnknown)))) {
2236+
/// The forward declaration was C++ but the definition is Objective-C.
2237+
/// We currently don't handle such situations. In such cases, keep the
2238+
/// forward declaration without a definition to avoid violating Clang AST
2239+
/// invariants.
2240+
LLDB_LOG(GetLog(LLDBLog::Expressions),
2241+
"WARNING: Type completion aborted because forward declaration for "
2242+
"'{0}' is C++ while definition is Objective-C.",
2243+
llvm::StringRef(die.GetName()));
2244+
return {};
22332245
}
22342246

22352247
if (!bases.empty()) {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# REQUIRES: system-darwin
2+
3+
# In this test we have two CUs with conflicting forward declaration
4+
# depending on the CU language (one is C++ and the other is Objective-C++).
5+
# We are then stopped in the C++ CU and try to print the type, at which
6+
# point LLDB will try to make it into an Clang AST node. If LLDB were to
7+
# interpret the type as C++ instead of Objective-C, we'd violate Clang
8+
# invariants and crash.
9+
#
10+
# RUN: split-file %s %t
11+
# RUN: %clangxx_host -c -g -x objective-c++ %t/request.m -o %t/request_objc.o
12+
# RUN: %clangxx_host -c -g %t/main.cpp -o %t/main.o
13+
# RUN: %clangxx_host %t/main.o %t/request_objc.o -framework Foundation -o %t/a.out
14+
#
15+
# RUN: %lldb %t/a.out \
16+
# RUN: -o "breakpoint set -p return -X main" \
17+
# RUN: -o run \
18+
# RUN: -o "frame variable r" \
19+
# RUN: -o exit | FileCheck %s
20+
#
21+
# RUN: dsymutil %t/a.out
22+
#
23+
# RUN: %lldb %t/a.out \
24+
# RUN: -o "breakpoint set -p return -X main" \
25+
# RUN: -o run \
26+
# RUN: -o "frame variable r" \
27+
# RUN: -o exit | FileCheck %s --check-prefix=CHECK-DSYM
28+
29+
# CHECK: (lldb) frame variable r
30+
# CHECK-NEXT: (Request) ::r = (m_request = "Hello, World!")
31+
32+
# CHECK-DSYM: (lldb) frame variable r
33+
# CHECK-DSYM-NEXT: (Request) ::r = (m_request = "Hello, World!")
34+
35+
#--- lib.h
36+
#ifndef LIB_H_IN
37+
#define LIB_H_IN
38+
39+
#ifdef __OBJC__
40+
@class NSString;
41+
#else
42+
class NSString;
43+
#endif
44+
45+
struct Request {
46+
NSString * m_request = nullptr;
47+
};
48+
49+
#endif // _H_IN
50+
51+
#--- main.cpp
52+
#include "lib.h"
53+
54+
void process(Request *);
55+
56+
Request r;
57+
58+
int main() {
59+
process(&r);
60+
return 0;
61+
}
62+
63+
#--- request.m
64+
#import <Foundation/Foundation.h>
65+
66+
#include "lib.h"
67+
68+
void process(Request * r) {
69+
r->m_request = @"Hello, World!";
70+
}

0 commit comments

Comments
 (0)