Skip to content

Commit 06675fd

Browse files
authored
Merge pull request #9161 from swiftlang/bugfix/lldb/external-source-to-20240723
[cherry-pick][stable/20240723] [lldb][ClangExpressionParser] Implement ExternalSemaSource::ReadUndefinedButUsed
2 parents f70cfae + 3627190 commit 06675fd

File tree

4 files changed

+75
-15
lines changed

4 files changed

+75
-15
lines changed

lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default;
1818

1919
void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); }
2020

21-
lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default;
21+
lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() {
22+
for (auto *Source : Sources)
23+
Source->Release();
24+
}
2225

2326
void lldb_private::SemaSourceWithPriorities::PrintStats() {
2427
for (size_t i = 0; i < Sources.size(); ++i)

lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "clang/Sema/MultiplexExternalSemaSource.h"
1616
#include "clang/Sema/Sema.h"
1717
#include "clang/Sema/SemaConsumer.h"
18+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
19+
#include "llvm/Support/Casting.h"
1820
#include <optional>
1921

2022
namespace clang {
@@ -25,13 +27,15 @@ class Module;
2527

2628
namespace lldb_private {
2729

28-
/// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
29-
/// ownership of the provided source.
30+
/// Wraps an ExternalASTSource into an ExternalSemaSource.
31+
///
32+
/// Assumes shared ownership of the underlying source.
3033
class ExternalASTSourceWrapper : public ImporterBackedASTSource {
31-
ExternalASTSource *m_Source;
34+
llvm::IntrusiveRefCntPtr<ExternalASTSource> m_Source;
3235

3336
public:
34-
ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
37+
explicit ExternalASTSourceWrapper(ExternalASTSource *Source)
38+
: m_Source(Source) {
3539
assert(m_Source && "Can't wrap nullptr ExternalASTSource");
3640
}
3741

@@ -136,6 +140,24 @@ class ExternalASTSourceWrapper : public ImporterBackedASTSource {
136140
return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
137141
BaseOffsets, VirtualBaseOffsets);
138142
}
143+
144+
/// This gets called when Sema is reconciling undefined but used decls.
145+
/// For LLDB's use-case, we never provide Clang with function definitions,
146+
/// instead we rely on linkage names and symbol resolution to call the
147+
/// correct funcitons during JITting. So this implementation clears
148+
/// any "undefined" FunctionDecls that Clang found while parsing.
149+
///
150+
/// \param[in,out] Undefined A set of used decls for which Clang has not
151+
/// been provided a definition with.
152+
///
153+
void ReadUndefinedButUsed(
154+
llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)
155+
override {
156+
Undefined.remove_if([](auto const &decl_loc_pair) {
157+
const clang::NamedDecl *ND = decl_loc_pair.first;
158+
return llvm::isa_and_present<clang::FunctionDecl>(ND);
159+
});
160+
}
139161
};
140162

141163
/// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the
@@ -257,10 +279,18 @@ class SemaSourceWithPriorities : public ImporterBackedASTSource {
257279
/// Construct a SemaSourceWithPriorities with a 'high quality' source that
258280
/// has the higher priority and a 'low quality' source that will be used
259281
/// as a fallback.
260-
SemaSourceWithPriorities(clang::ExternalSemaSource &high_quality_source,
261-
clang::ExternalSemaSource &low_quality_source) {
262-
Sources.push_back(&high_quality_source);
263-
Sources.push_back(&low_quality_source);
282+
///
283+
/// This class assumes shared ownership of the sources provided to it.
284+
SemaSourceWithPriorities(clang::ExternalSemaSource *high_quality_source,
285+
clang::ExternalSemaSource *low_quality_source) {
286+
assert(high_quality_source);
287+
assert(low_quality_source);
288+
289+
high_quality_source->Retain();
290+
low_quality_source->Retain();
291+
292+
Sources.push_back(high_quality_source);
293+
Sources.push_back(low_quality_source);
264294
}
265295

266296
~SemaSourceWithPriorities() override;

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,19 +1121,22 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
11211121

11221122
clang::ExternalASTSource *ast_source = decl_map->CreateProxy();
11231123

1124+
auto *ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);
1125+
11241126
if (ast_context.getExternalSource()) {
1125-
auto module_wrapper =
1127+
auto *module_wrapper =
11261128
new ExternalASTSourceWrapper(ast_context.getExternalSource());
11271129

1128-
auto ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);
1130+
auto *ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);
1131+
1132+
auto *multiplexer =
1133+
new SemaSourceWithPriorities(module_wrapper, ast_source_wrapper);
11291134

1130-
auto multiplexer =
1131-
new SemaSourceWithPriorities(*module_wrapper, *ast_source_wrapper);
1132-
IntrusiveRefCntPtr<ExternalASTSource> Source(multiplexer);
1133-
ast_context.setExternalSource(Source);
1135+
ast_context.setExternalSource(multiplexer);
11341136
} else {
11351137
ast_context.setExternalSource(ast_source);
11361138
}
1139+
m_compiler->getSema().addExternalSource(ast_source_wrapper);
11371140
decl_map->InstallASTContext(*m_ast_context);
11381141
}
11391142

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Tests that we can evaluate functions that Clang
2+
// classifies as having clang::Linkage::UniqueExternal
3+
// linkage. In this case, a function whose argument
4+
// is not legally usable outside this TU.
5+
6+
// XFAIL: system-windows
7+
8+
// RUN: %build %s -o %t
9+
// RUN: %lldb %t -o run -o "expression func(a)" -o exit | FileCheck %s
10+
11+
// CHECK: expression func(a)
12+
// CHECK: (int) $0 = 15
13+
14+
namespace {
15+
struct InAnon {};
16+
} // namespace
17+
18+
int func(InAnon a) { return 15; }
19+
20+
int main() {
21+
InAnon a;
22+
__builtin_debugtrap();
23+
return func(a);
24+
}

0 commit comments

Comments
 (0)