Skip to content

Commit 5232c25

Browse files
Merge pull request #9560 from adrian-prantl/module-import-hint
[lldb] Add a hint for potential missing module imports in the express…
2 parents 2b23b84 + e13165e commit 5232c25

File tree

12 files changed

+101
-20
lines changed

12 files changed

+101
-20
lines changed

lldb/packages/Python/lldbsuite/test/make/Swift.rules

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,11 @@ ifneq "$(FRAMEWORK)" ""
253253
mkdir -p $(FRAMEWORK).framework/Versions/A/Headers
254254
mkdir -p $(FRAMEWORK).framework/Versions/A/Modules
255255
mkdir -p $(FRAMEWORK).framework/Versions/A/Resources
256+
ifeq "$(DYLIB_HIDE_SWIFTMODULE)" ""
256257
ifneq "$(MODULENAME)" ""
257258
mkdir -p $(FRAMEWORK).framework/Versions/A/Modules/$(MODULENAME).swiftmodule
258259
cp -r $(MODULENAME).swiftmodule $(FRAMEWORK).framework/Versions/A/Modules/$(MODULENAME).swiftmodule/$(ARCH).swiftmodule
260+
endif
259261
endif
260262
(cd $(FRAMEWORK).framework/Versions; ln -sf A Current)
261263
(cd $(FRAMEWORK).framework/; ln -sf Versions/A/Headers Headers)

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,26 @@ RedirectCallFromSinkToTrampolineFunction(llvm::Module &module,
16541654
return true;
16551655
}
16561656

1657+
/// Add additional context that is otherwise hard to convey.
1658+
static void AnnotateDiagnostics(DiagnosticManager &diagnostic_manager) {
1659+
bool append_missing_library_note = false;
1660+
for (auto &diag : diagnostic_manager.Diagnostics()) {
1661+
if (!diag || diag->GetSeverity() != eSeverityError)
1662+
continue;
1663+
const auto &detail = diag->GetDetail();
1664+
if (StringRef(detail.message).contains("has no member")) {
1665+
append_missing_library_note = true;
1666+
break;
1667+
}
1668+
}
1669+
if (append_missing_library_note)
1670+
diagnostic_manager.AddDiagnostic(
1671+
"If the member name is spelled correctly, this error could mean that "
1672+
"it depends on a (private) type from a module that has not been "
1673+
"imported into the current context.",
1674+
eSeverityInfo, eDiagnosticOriginLLDB);
1675+
}
1676+
16571677
SwiftExpressionParser::ParseResult
16581678
SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
16591679
uint32_t first_line, uint32_t last_line) {
@@ -1675,6 +1695,7 @@ SwiftExpressionParser::Parse(DiagnosticManager &diagnostic_manager,
16751695
"error expected");
16761696
expr_diagnostics->PrintDiagnostics(diagnostic_manager, buffer_id,
16771697
first_line, last_line);
1698+
AnnotateDiagnostics(diagnostic_manager);
16781699
};
16791700

16801701
// In the case of playgrounds, we turn all rewriting functionality off.

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,14 @@ class SwiftLanguageRuntimeStub {
298298
llvm::Expected<uint32_t> GetNumChildren(CompilerType type,
299299
ExecutionContextScope *exe_scopej) {
300300
STUB_LOG();
301-
return 0;
301+
return llvm::createStringError("runtime not loaded");
302302
}
303303

304-
std::optional<std::string> GetEnumCaseName(CompilerType type,
304+
llvm::Expected<std::string> GetEnumCaseName(CompilerType type,
305305
const DataExtractor &data,
306306
ExecutionContext *exe_ctx) {
307307
STUB_LOG();
308-
return {};
308+
return llvm::createStringError("runtime not loaded");
309309
}
310310

311311
std::pair<SwiftLanguageRuntime::LookupResult, std::optional<size_t>>
@@ -2417,7 +2417,7 @@ SwiftLanguageRuntime::GetNumChildren(CompilerType type,
24172417
FORWARD(GetNumChildren, type, exe_scope);
24182418
}
24192419

2420-
std::optional<std::string> SwiftLanguageRuntime::GetEnumCaseName(
2420+
llvm::Expected<std::string> SwiftLanguageRuntime::GetEnumCaseName(
24212421
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
24222422
FORWARD(GetEnumCaseName, type, data, exe_ctx);
24232423
}

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ class SwiftLanguageRuntime : public LanguageRuntime {
344344

345345
/// Determine the enum case name for the \p data value of the enum \p type.
346346
/// This is performed using Swift reflection.
347-
std::optional<std::string> GetEnumCaseName(CompilerType type,
347+
llvm::Expected<std::string> GetEnumCaseName(CompilerType type,
348348
const DataExtractor &data,
349349
ExecutionContext *exe_ctx);
350350

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -952,15 +952,20 @@ findFieldWithName(const std::vector<swift::reflection::FieldInfo> &fields,
952952
return {SwiftLanguageRuntime::eFound, child_indexes.size()};
953953
}
954954

955-
std::optional<std::string> SwiftLanguageRuntimeImpl::GetEnumCaseName(
955+
llvm::Expected<std::string> SwiftLanguageRuntimeImpl::GetEnumCaseName(
956956
CompilerType type, const DataExtractor &data, ExecutionContext *exe_ctx) {
957957
using namespace swift::reflection;
958958
using namespace swift::remote;
959959
auto *ti = GetSwiftRuntimeTypeInfo(type, exe_ctx->GetFramePtr());
960960
if (!ti)
961-
return {};
961+
return llvm::createStringError("could not get runtime type info for " +
962+
type.GetMangledTypeName().GetStringRef());
963+
964+
// FIXME: Not reported as an error. There seems to be an odd
965+
// compiler optimization happening with single-case payload carrying
966+
// enums, which report their type as the inner type.
962967
if (ti->getKind() != TypeInfoKind::Enum)
963-
return {};
968+
return "";
964969

965970
auto *eti = llvm::cast<EnumTypeInfo>(ti);
966971
PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize());
@@ -972,7 +977,7 @@ std::optional<std::string> SwiftLanguageRuntimeImpl::GetEnumCaseName(
972977

973978
// TODO: uncomment this after fixing projection for every type: rdar://138424904
974979
// LogUnimplementedTypeKind(__FUNCTION__, type);
975-
return {};
980+
return llvm::createStringError("unimplemented enum kind");
976981
}
977982

978983
std::pair<SwiftLanguageRuntime::LookupResult, std::optional<size_t>>

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class SwiftLanguageRuntimeImpl {
134134
std::optional<unsigned> GetNumFields(CompilerType type,
135135
ExecutionContext *exe_ctx);
136136

137-
std::optional<std::string> GetEnumCaseName(CompilerType type,
137+
llvm::Expected<std::string> GetEnumCaseName(CompilerType type,
138138
const DataExtractor &data,
139139
ExecutionContext *exe_ctx);
140140

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/ADT/ScopeExit.h"
4646

4747
#include <algorithm>
48+
#include <cerrno>
4849
#include <sstream>
4950
#include <type_traits>
5051

@@ -4412,30 +4413,36 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
44124413
}
44134414
case Node::Kind::Enum:
44144415
case Node::Kind::BoundGenericEnum: {
4416+
std::string error;
44154417
if (exe_scope)
44164418
if (auto runtime =
44174419
SwiftLanguageRuntime::Get(exe_scope->CalculateProcess())) {
44184420
ExecutionContext exe_ctx;
44194421
exe_scope->CalculateExecutionContext(exe_ctx);
4420-
if (auto case_name = runtime->GetEnumCaseName(
4421-
{weak_from_this(), type}, data, &exe_ctx)) {
4422+
auto case_name = runtime->GetEnumCaseName({weak_from_this(), type},
4423+
data, &exe_ctx);
4424+
if (case_name && !case_name->empty()) {
44224425
s.PutCString(*case_name);
44234426
return true;
44244427
}
4428+
if (!case_name)
4429+
error = toString(case_name.takeError());
44254430
}
44264431

44274432
// No result available from the runtime, fallback to the AST. This occurs
4428-
// for some Clang imported enums
4433+
// for some Clang imported enums.
44294434
if (auto *swift_ast_context =
44304435
GetSwiftASTContextFromExecutionScope(exe_scope)) {
44314436
ExecutionContext exe_ctx;
44324437
exe_scope->CalculateExecutionContext(exe_ctx);
4433-
return swift_ast_context->DumpTypeValue(
4434-
ReconstructType(type, &exe_ctx), s, format, data, data_offset,
4435-
data_byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope,
4436-
is_base_class);
4438+
if (swift_ast_context->DumpTypeValue(
4439+
ReconstructType(type, &exe_ctx), s, format, data, data_offset,
4440+
data_byte_size, bitfield_bit_size, bitfield_bit_offset,
4441+
exe_scope, is_base_class))
4442+
return true;
44374443
}
4438-
return {};
4444+
s << error;
4445+
return false;
44394446
}
44404447
case Node::Kind::TypeAlias:
44414448
case Node::Kind::BoundGenericTypeAlias: {
@@ -4449,7 +4456,7 @@ bool TypeSystemSwiftTypeRef::DumpTypeValue(
44494456
ReconstructType(type, exe_scope), s, format, data, data_offset,
44504457
data_byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope,
44514458
is_base_class);
4452-
return {};
4459+
return false;
44534460
}
44544461
default:
44554462
assert(false && "Unhandled node kind");
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
private enum E {
2+
case WithString(String)
3+
case OtherCase
4+
}
5+
6+
public struct S {
7+
private var e : E { get { return .WithString("hidden") } }
8+
}
9+
10+
public func getS() -> S { return S() }
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS := -I.
3+
LD_EXTRAS = -lLibrary -L$(BUILDDIR)
4+
all: libLibrary.dylib a.out
5+
6+
lib%.dylib: %.swift
7+
$(MAKE) MAKE_DSYM=NO DYLIB_ONLY=YES \
8+
DYLIB_HIDE_SWIFTMODULE=YES \
9+
DYLIB_NAME=$(shell basename $< .swift) \
10+
DYLIB_SWIFT_SOURCES=$(shell basename $<) \
11+
VPATH=$(SRCDIR) -I $(SRCDIR) -f $(MAKEFILE_RULES) all
12+
rm -f Library.private.swiftinterface
13+
14+
include Makefile.rules
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
6+
class TestSwiftExpressionErrorMissingType(TestBase):
7+
NO_DEBUG_INFO_TESTCASE = True
8+
9+
@swiftTest
10+
def test(self):
11+
"""Test an extra hint inserted by LLDB for missing module imports"""
12+
self.build()
13+
os.remove(self.getBuildArtifact("Library.swiftmodule"))
14+
lldbutil.run_to_source_breakpoint(self, 'break here',
15+
lldb.SBFileSpec('main.swift'),
16+
extra_images=['Library'])
17+
18+
self.expect('expression s.e', error=True,
19+
substrs=['spelled', 'correctly', 'module', 'import'])
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Library
2+
let s = getS()
3+
print("break here")

lldb/test/API/lang/swift/expression/error_reporting/TestSwiftExpressionErrorReporting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from lldbsuite.test.decorators import *
44
import lldbsuite.test.lldbutil as lldbutil
55

6-
class TestSwiftExpressionErrorReportingy(TestBase):
6+
class TestSwiftExpressionErrorReporting(TestBase):
77
NO_DEBUG_INFO_TESTCASE = True
88

99
@swiftTest

0 commit comments

Comments
 (0)