Skip to content

Commit d26ebfd

Browse files
committed
[lldb/Swift] Fix import attributes handing in expression evaluations
Previously, when importing a Swift module it the REPL or a Playground, LLDB would only cache the module name and reload the module at every expression evaluation. Doing so means that, when LLDB transfers imports information from the original source file to the new one, it is doing it with low fidelity, because LLDB would not keep track of the import attributes used in the previous expression evaluations. Thanks to swiftlang/swift#33935, we can now cache the whole `swift::AttributedImport<swift::ImportedModule>>` instead of only storing the module name. This struct contains both the `ImportedModule` with the `ModuleDecl` but also the `ImportOptions` set containing all the possible import attributes (Exported / Testable / PrivateImport ...) of that import statement. Now, before compiling and evaluating a Swift expression, LLDB fetches all the attributed imports cached previously and add them to the `ImplicitImportInfo` object that is used to create the `ModuleDecl` of the evaluated expression. It allows for the `ImportOptions` to be propagated in the compiled expression. This should fix some irregularities between the debugger and the compiler regarding import statements. rdar://65319954 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 9f1d8f2 commit d26ebfd

File tree

8 files changed

+144
-36
lines changed

8 files changed

+144
-36
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,18 @@
5555
#include "clang/Rewrite/Core/RewriteBuffer.h"
5656

5757
#include "swift/AST/ASTContext.h"
58-
#include "swift/AST/DiagnosticEngine.h"
5958
#include "swift/AST/DiagnosticConsumer.h"
59+
#include "swift/AST/DiagnosticEngine.h"
6060
#include "swift/AST/IRGenOptions.h"
6161
#include "swift/AST/IRGenRequests.h"
62+
#include "swift/AST/Import.h"
6263
#include "swift/AST/Module.h"
6364
#include "swift/AST/ModuleLoader.h"
64-
#include "swift/Demangling/Demangle.h"
65+
#include "swift/Basic/OptimizationMode.h"
6566
#include "swift/Basic/PrimarySpecificPaths.h"
6667
#include "swift/Basic/SourceManager.h"
67-
#include "swift/Basic/OptimizationMode.h"
6868
#include "swift/ClangImporter/ClangImporter.h"
69+
#include "swift/Demangling/Demangle.h"
6970
#include "swift/Frontend/Frontend.h"
7071
#include "swift/Parse/LocalContext.h"
7172
#include "swift/Parse/PersistentParserState.h"
@@ -1137,6 +1138,7 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11371138
lldb::StackFrameWP &stack_frame_wp, SymbolContext &sc,
11381139
ExecutionContextScope &exe_scope, const EvaluateExpressionOptions &options,
11391140
bool repl, bool playground) {
1141+
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
11401142

11411143
auto should_disable_objc_runtime = [&]() {
11421144
lldb::StackFrameSP this_frame_sp(stack_frame_wp.lock());
@@ -1162,7 +1164,20 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11621164
if (playground) {
11631165
auto *persistent_state =
11641166
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
1165-
persistent_state->AddHandLoadedModule(ConstString("Swift"));
1167+
1168+
Status error;
1169+
SourceModule module_info;
1170+
module_info.path.emplace_back("Swift");
1171+
swift::ModuleDecl *module =
1172+
swift_ast_context->GetModule(module_info, error);
1173+
1174+
if (error.Fail() || !module) {
1175+
LLDB_LOG(log, "couldn't load Swift Standard Library\n");
1176+
return error.ToError();
1177+
}
1178+
1179+
persistent_state->AddHandLoadedModule(ConstString("Swift"),
1180+
swift::ImportedModule(module));
11661181
}
11671182

11681183
std::string main_filename;
@@ -1178,7 +1193,8 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11781193
// The Swift stdlib needs to be imported before the SwiftLanguageRuntime can
11791194
// be used.
11801195
Status implicit_import_error;
1181-
llvm::SmallVector<swift::ModuleDecl *, 16> additional_imports;
1196+
llvm::SmallVector<swift::AttributedImport<swift::ImportedModule>, 16>
1197+
additional_imports;
11821198
if (!SwiftASTContext::GetImplicitImports(*swift_ast_context, sc, exe_scope,
11831199
stack_frame_wp, additional_imports,
11841200
implicit_import_error)) {
@@ -1188,9 +1204,8 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11881204

11891205
swift::ImplicitImportInfo importInfo;
11901206
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;
1191-
for (auto *module : additional_imports)
1192-
importInfo.AdditionalImports.emplace_back(swift::ImportedModule(module),
1193-
swift::ImportOptions());
1207+
for (auto &attributed_import : additional_imports)
1208+
importInfo.AdditionalImports.emplace_back(attributed_import);
11941209

11951210
auto module_id = ast_context->getIdentifier(expr_name_buf);
11961211
auto &module = *swift::ModuleDecl::create(module_id, *ast_context,

lldb/source/Plugins/ExpressionParser/Swift/SwiftPersistentExpressionState.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515

1616
#include "SwiftExpressionVariable.h"
1717

18+
#include "swift/AST/Import.h"
19+
#include "swift/AST/Module.h"
20+
1821
#include "lldb/Core/SwiftForward.h"
1922
#include "lldb/Expression/ExpressionVariable.h"
2023

21-
#include "llvm/ADT/DenseMap.h"
24+
#include "llvm/ADT/StringMap.h"
2225
#include "llvm/ADT/StringRef.h"
2326

2427
#include <set>
@@ -38,7 +41,9 @@ namespace lldb_private {
3841
/// 0-based counter for naming result variables.
3942
//----------------------------------------------------------------------
4043
class SwiftPersistentExpressionState : public PersistentExpressionState {
41-
typedef std::set<lldb_private::ConstString> HandLoadedModuleSet;
44+
45+
typedef llvm::StringMap<swift::AttributedImport<swift::ImportedModule>>
46+
HandLoadedModuleSet;
4247

4348
public:
4449
class SwiftDeclMap {
@@ -114,8 +119,11 @@ class SwiftPersistentExpressionState : public PersistentExpressionState {
114119

115120
// This just adds this module to the list of hand-loaded modules, it doesn't
116121
// actually load it.
117-
void AddHandLoadedModule(ConstString module_name) {
118-
m_hand_loaded_modules.insert(module_name);
122+
void AddHandLoadedModule(
123+
ConstString module_name,
124+
swift::AttributedImport<swift::ImportedModule> attributed_import) {
125+
m_hand_loaded_modules.insert_or_assign(module_name.GetStringRef(),
126+
attributed_import);
119127
}
120128

121129
/// This returns the list of hand-loaded modules.

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,38 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
285285
"couldn't start parsing (no target)");
286286
return false;
287287
}
288+
289+
StackFrame *frame = exe_ctx.GetFramePtr();
290+
if (!frame) {
291+
LLDB_LOG(log, "no stack frame");
292+
return false;
293+
}
294+
295+
// Make sure the target's SwiftASTContext has been setup before doing any
296+
// Swift name lookups.
297+
llvm::Optional<SwiftASTContextReader> maybe_swift_ast_ctx =
298+
target->GetScratchSwiftASTContext(err, *frame);
299+
if (!maybe_swift_ast_ctx) {
300+
LLDB_LOG(log, "no Swift AST Context");
301+
return false;
302+
}
303+
304+
SwiftASTContext *swift_ast_ctx = maybe_swift_ast_ctx->get();
305+
288306
if (auto *persistent_state = GetPersistentState(target, exe_ctx)) {
289-
persistent_state->AddHandLoadedModule(ConstString("Swift"));
307+
308+
Status error;
309+
SourceModule module_info;
310+
module_info.path.emplace_back("Swift");
311+
swift::ModuleDecl *module = swift_ast_ctx->GetModule(module_info, error);
312+
313+
if (error.Fail() || !module) {
314+
LLDB_LOG(log, "couldn't load Swift Standard Library\n");
315+
return false;
316+
}
317+
318+
persistent_state->AddHandLoadedModule(ConstString("Swift"),
319+
swift::ImportedModule(module));
290320
m_result_delegate.RegisterPersistentState(persistent_state);
291321
m_error_delegate.RegisterPersistentState(persistent_state);
292322
} else {

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8284,7 +8284,9 @@ static swift::ModuleDecl *LoadOneModule(const SourceModule &module,
82848284
bool SwiftASTContext::GetImplicitImports(
82858285
SwiftASTContext &swift_ast_context, SymbolContext &sc,
82868286
ExecutionContextScope &exe_scope, lldb::StackFrameWP &stack_frame_wp,
8287-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules, Status &error) {
8287+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
8288+
&modules,
8289+
Status &error) {
82888290
if (!GetCompileUnitImports(swift_ast_context, sc, stack_frame_wp, modules,
82898291
error)) {
82908292
return false;
@@ -8294,15 +8296,28 @@ bool SwiftASTContext::GetImplicitImports(
82948296
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
82958297

82968298
// Get the hand-loaded modules from the SwiftPersistentExpressionState.
8297-
for (ConstString name : persistent_expression_state->GetHandLoadedModules()) {
8299+
for (auto &module_pair :
8300+
persistent_expression_state->GetHandLoadedModules()) {
8301+
8302+
auto &attributed_import = module_pair.second;
8303+
8304+
// If the ImportedModule in the SwiftPersistentExpressionState has a
8305+
// non-null ModuleDecl, add it to the ImplicitImports list.
8306+
if (attributed_import.module.importedModule) {
8307+
modules.emplace_back(attributed_import);
8308+
continue;
8309+
}
8310+
8311+
// Otherwise, try reloading the ModuleDecl using the module name.
82988312
SourceModule module_info;
8299-
module_info.path.push_back(name);
8300-
auto *module = LoadOneModule(module_info, swift_ast_context, stack_frame_wp,
8301-
error);
8313+
module_info.path.emplace_back(module_pair.first());
8314+
auto *module =
8315+
LoadOneModule(module_info, swift_ast_context, stack_frame_wp, error);
83028316
if (!module)
83038317
return false;
83048318

8305-
modules.push_back(module);
8319+
attributed_import.module = swift::ImportedModule(module);
8320+
modules.emplace_back(attributed_import);
83068321
}
83078322
return true;
83088323
}
@@ -8314,7 +8329,6 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
83148329
swift::SourceFile &source_file,
83158330
Status &error) {
83168331
llvm::SmallString<1> m_description;
8317-
llvm::SmallVector<swift::ImportedModule, 2> parsed_imports;
83188332

83198333
swift::ModuleDecl::ImportFilter import_filter {
83208334
swift::ModuleDecl::ImportFilterKind::Exported,
@@ -8324,13 +8338,12 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
83248338
swift::ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay
83258339
};
83268340

8327-
source_file.getImportedModules(parsed_imports, import_filter);
8328-
83298341
auto *persistent_expression_state =
83308342
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
83318343

8332-
for (auto module_pair : parsed_imports) {
8333-
swift::ModuleDecl *module = module_pair.importedModule;
8344+
for (const auto &attributed_import : source_file.getImports()) {
8345+
swift::ModuleDecl *module = attributed_import.module.importedModule;
8346+
83348347
if (module) {
83358348
std::string module_name;
83368349
GetNameFromModule(module, module_name);
@@ -8346,7 +8359,8 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
83468359
return false;
83478360

83488361
// How do we tell we are in REPL or playground mode?
8349-
persistent_expression_state->AddHandLoadedModule(module_const_str);
8362+
persistent_expression_state->AddHandLoadedModule(module_const_str,
8363+
attributed_import);
83508364
}
83518365
}
83528366
}
@@ -8356,16 +8370,18 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
83568370
bool SwiftASTContext::GetCompileUnitImports(
83578371
SwiftASTContext &swift_ast_context, SymbolContext &sc,
83588372
lldb::StackFrameWP &stack_frame_wp,
8359-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules, Status &error) {
8373+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
8374+
&modules,
8375+
Status &error) {
83608376
// Import the Swift standard library and its dependencies.
83618377
SourceModule swift_module;
8362-
swift_module.path.push_back(ConstString("Swift"));
8378+
swift_module.path.emplace_back("Swift");
83638379
auto *stdlib =
83648380
LoadOneModule(swift_module, swift_ast_context, stack_frame_wp, error);
83658381
if (!stdlib)
83668382
return false;
83678383

8368-
modules.push_back(stdlib);
8384+
modules.emplace_back(swift::ImportedModule(stdlib));
83698385

83708386
CompileUnit *compile_unit = sc.comp_unit;
83718387
if (!compile_unit || compile_unit->GetLanguage() != lldb::eLanguageTypeSwift)
@@ -8386,7 +8402,7 @@ bool SwiftASTContext::GetCompileUnitImports(
83868402
if (!loaded_module)
83878403
return false;
83888404

8389-
modules.push_back(loaded_module);
8405+
modules.emplace_back(swift::ImportedModule(loaded_module));
83908406
}
83918407
return true;
83928408
}

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,9 @@ class SwiftASTContext : public TypeSystemSwift {
750750
static bool GetImplicitImports(
751751
SwiftASTContext &swift_ast_context, SymbolContext &sc,
752752
ExecutionContextScope &exe_scope, lldb::StackFrameWP &stack_frame_wp,
753-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules, Status &error);
753+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
754+
&modules,
755+
Status &error);
754756

755757
/// Cache the user's imports from a SourceFile in a given execution scope such
756758
/// that they are carried over into future expression evaluations.
@@ -761,11 +763,12 @@ class SwiftASTContext : public TypeSystemSwift {
761763
swift::SourceFile &source_file, Status &error);
762764

763765
/// Retrieve the modules imported by the compilation unit.
764-
static bool
765-
GetCompileUnitImports(SwiftASTContext &swift_ast_context, SymbolContext &sc,
766-
lldb::StackFrameWP &stack_frame_wp,
767-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules,
768-
Status &error);
766+
static bool GetCompileUnitImports(
767+
SwiftASTContext &swift_ast_context, SymbolContext &sc,
768+
lldb::StackFrameWP &stack_frame_wp,
769+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
770+
&modules,
771+
Status &error);
769772

770773
protected:
771774
/// This map uses the string value of ConstStrings as the key, and the

lldb/source/Target/Target.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2504,7 +2504,8 @@ llvm::Optional<SwiftASTContextReader> Target::GetScratchSwiftASTContext(
25042504
!swift_ast_ctx->HasFatalErrors()) {
25052505
StackFrameWP frame_wp(frame_sp);
25062506
SymbolContext sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
2507-
llvm::SmallVector<swift::ModuleDecl *, 16> modules;
2507+
llvm::SmallVector<swift::AttributedImport<swift::ImportedModule>, 16>
2508+
modules;
25082509
swift_ast_ctx->GetCompileUnitImports(*swift_ast_ctx, sc, frame_wp, modules,
25092510
error);
25102511
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public struct Bar {
2+
public init(baz: Int) { self.baz = baz }
3+
4+
var baz : Int
5+
}
6+
7+
struct Foo {
8+
init(bar: Int) { self.bar = bar }
9+
10+
var bar : Int
11+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Make sure import attributes are taken into consideration at every evaluation
2+
// rdar://65319954
3+
// REQUIRES: swift
4+
5+
// RUN: rm -rf %t
6+
// RUN: mkdir %t
7+
// RUN: %target-swiftc -emit-library %S/Inputs/Test.swift -module-name Test -emit-module-path %t/Test.swiftmodule -o %t/libTest%target-shared-library-suffix -Onone -g -enable-testing
8+
9+
// RUN: %lldb --repl="-I%t -L%t -lTest" < %s 2>&1 | FileCheck %s
10+
11+
import Test
12+
13+
let y = Bar(baz: 123)
14+
// CHECK: y: Test.Bar = {
15+
// CHECK: baz = 123
16+
17+
let x = Foo(bar:42)
18+
// CHECK: error: repl.swift:{{.*}}: error: cannot find 'Foo' in scope
19+
20+
@testable import Test
21+
22+
let x = Foo(bar:42)
23+
// CHECK: x: Test.Foo = {
24+
// CHECK: bar = 42

0 commit comments

Comments
 (0)