Skip to content

Commit a92203c

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 e353a88 commit a92203c

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"
@@ -1162,6 +1163,7 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11621163
lldb::StackFrameWP &stack_frame_wp, SymbolContext &sc,
11631164
ExecutionContextScope &exe_scope, const EvaluateExpressionOptions &options,
11641165
bool repl, bool playground) {
1166+
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
11651167

11661168
auto should_disable_objc_runtime = [&]() {
11671169
lldb::StackFrameSP this_frame_sp(stack_frame_wp.lock());
@@ -1187,7 +1189,20 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
11871189
if (playground) {
11881190
auto *persistent_state =
11891191
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
1190-
persistent_state->AddHandLoadedModule(ConstString("Swift"));
1192+
1193+
Status error;
1194+
SourceModule module_info;
1195+
module_info.path.emplace_back("Swift");
1196+
swift::ModuleDecl *module =
1197+
swift_ast_context->GetModule(module_info, error);
1198+
1199+
if (error.Fail() || !module) {
1200+
LLDB_LOG(log, "couldn't load Swift Standard Library\n");
1201+
return error.ToError();
1202+
}
1203+
1204+
persistent_state->AddHandLoadedModule(ConstString("Swift"),
1205+
swift::ImportedModule(module));
11911206
}
11921207

11931208
std::string main_filename;
@@ -1203,7 +1218,8 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
12031218
// The Swift stdlib needs to be imported before the SwiftLanguageRuntime can
12041219
// be used.
12051220
Status implicit_import_error;
1206-
llvm::SmallVector<swift::ModuleDecl *, 16> additional_imports;
1221+
llvm::SmallVector<swift::AttributedImport<swift::ImportedModule>, 16>
1222+
additional_imports;
12071223
if (!SwiftASTContext::GetImplicitImports(*swift_ast_context, sc, exe_scope,
12081224
stack_frame_wp, additional_imports,
12091225
implicit_import_error)) {
@@ -1213,9 +1229,8 @@ static llvm::Expected<ParsedExpression> ParseAndImport(
12131229

12141230
swift::ImplicitImportInfo importInfo;
12151231
importInfo.StdlibKind = swift::ImplicitStdlibKind::Stdlib;
1216-
for (auto *module : additional_imports)
1217-
importInfo.AdditionalImports.emplace_back(swift::ImportedModule(module),
1218-
swift::ImportOptions());
1232+
for (auto &attributed_import : additional_imports)
1233+
importInfo.AdditionalImports.emplace_back(attributed_import);
12191234

12201235
auto module_id = ast_context->getIdentifier(expr_name_buf);
12211236
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
@@ -8237,7 +8237,9 @@ static swift::ModuleDecl *LoadOneModule(const SourceModule &module,
82378237
bool SwiftASTContext::GetImplicitImports(
82388238
SwiftASTContext &swift_ast_context, SymbolContext &sc,
82398239
ExecutionContextScope &exe_scope, lldb::StackFrameWP &stack_frame_wp,
8240-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules, Status &error) {
8240+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
8241+
&modules,
8242+
Status &error) {
82418243
if (!GetCompileUnitImports(swift_ast_context, sc, stack_frame_wp, modules,
82428244
error)) {
82438245
return false;
@@ -8247,15 +8249,28 @@ bool SwiftASTContext::GetImplicitImports(
82478249
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
82488250

82498251
// Get the hand-loaded modules from the SwiftPersistentExpressionState.
8250-
for (ConstString name : persistent_expression_state->GetHandLoadedModules()) {
8252+
for (auto &module_pair :
8253+
persistent_expression_state->GetHandLoadedModules()) {
8254+
8255+
auto &attributed_import = module_pair.second;
8256+
8257+
// If the ImportedModule in the SwiftPersistentExpressionState has a
8258+
// non-null ModuleDecl, add it to the ImplicitImports list.
8259+
if (attributed_import.module.importedModule) {
8260+
modules.emplace_back(attributed_import);
8261+
continue;
8262+
}
8263+
8264+
// Otherwise, try reloading the ModuleDecl using the module name.
82518265
SourceModule module_info;
8252-
module_info.path.push_back(name);
8253-
auto *module = LoadOneModule(module_info, swift_ast_context, stack_frame_wp,
8254-
error);
8266+
module_info.path.emplace_back(module_pair.first());
8267+
auto *module =
8268+
LoadOneModule(module_info, swift_ast_context, stack_frame_wp, error);
82558269
if (!module)
82568270
return false;
82578271

8258-
modules.push_back(module);
8272+
attributed_import.module = swift::ImportedModule(module);
8273+
modules.emplace_back(attributed_import);
82598274
}
82608275
return true;
82618276
}
@@ -8267,7 +8282,6 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82678282
swift::SourceFile &source_file,
82688283
Status &error) {
82698284
llvm::SmallString<1> m_description;
8270-
llvm::SmallVector<swift::ImportedModule, 2> parsed_imports;
82718285

82728286
swift::ModuleDecl::ImportFilter import_filter {
82738287
swift::ModuleDecl::ImportFilterKind::Exported,
@@ -8277,13 +8291,12 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82778291
swift::ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay
82788292
};
82798293

8280-
source_file.getImportedModules(parsed_imports, import_filter);
8281-
82828294
auto *persistent_expression_state =
82838295
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
82848296

8285-
for (auto module_pair : parsed_imports) {
8286-
swift::ModuleDecl *module = module_pair.importedModule;
8297+
for (const auto &attributed_import : source_file.getImports()) {
8298+
swift::ModuleDecl *module = attributed_import.module.importedModule;
8299+
82878300
if (module) {
82888301
std::string module_name;
82898302
GetNameFromModule(module, module_name);
@@ -8299,7 +8312,8 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82998312
return false;
83008313

83018314
// How do we tell we are in REPL or playground mode?
8302-
persistent_expression_state->AddHandLoadedModule(module_const_str);
8315+
persistent_expression_state->AddHandLoadedModule(module_const_str,
8316+
attributed_import);
83038317
}
83048318
}
83058319
}
@@ -8309,16 +8323,18 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
83098323
bool SwiftASTContext::GetCompileUnitImports(
83108324
SwiftASTContext &swift_ast_context, SymbolContext &sc,
83118325
lldb::StackFrameWP &stack_frame_wp,
8312-
llvm::SmallVectorImpl<swift::ModuleDecl *> &modules, Status &error) {
8326+
llvm::SmallVectorImpl<swift::AttributedImport<swift::ImportedModule>>
8327+
&modules,
8328+
Status &error) {
83138329
// Import the Swift standard library and its dependencies.
83148330
SourceModule swift_module;
8315-
swift_module.path.push_back(ConstString("Swift"));
8331+
swift_module.path.emplace_back("Swift");
83168332
auto *stdlib =
83178333
LoadOneModule(swift_module, swift_ast_context, stack_frame_wp, error);
83188334
if (!stdlib)
83198335
return false;
83208336

8321-
modules.push_back(stdlib);
8337+
modules.emplace_back(swift::ImportedModule(stdlib));
83228338

83238339
CompileUnit *compile_unit = sc.comp_unit;
83248340
if (!compile_unit || compile_unit->GetLanguage() != lldb::eLanguageTypeSwift)
@@ -8339,7 +8355,7 @@ bool SwiftASTContext::GetCompileUnitImports(
83398355
if (!loaded_module)
83408356
return false;
83418357

8342-
modules.push_back(loaded_module);
8358+
modules.emplace_back(swift::ImportedModule(loaded_module));
83438359
}
83448360
return true;
83458361
}

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

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

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

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

771774
protected:
772775
/// 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)