Skip to content

Commit 0b829bf

Browse files
committed
Add error messages for Swift module map parser
Parser errors with large Swift module map files can be hard to diagnose. Refactor the parser to return an llvm::Error so clearer diagnostics can be passed to the user.
1 parent 61cb1a9 commit 0b829bf

File tree

5 files changed

+114
-25
lines changed

5 files changed

+114
-25
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ ERROR(explicit_swift_module_map_missing,none,
360360
(StringRef))
361361

362362
ERROR(explicit_swift_module_map_corrupted,none,
363-
"explicit Swift module map from %0 is malformed",
364-
(StringRef))
363+
"explicit Swift module map from %0 is malformed: %1",
364+
(StringRef, StringRef))
365365

366366
ERROR(const_extract_protocol_list_input_file_missing,none,
367367
"cannot open constant extraction protocol list input file from %0",

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@
111111
#include "swift/Frontend/Frontend.h"
112112
#include "swift/Frontend/ModuleInterfaceSupport.h"
113113
#include "swift/Serialization/SerializedModuleLoader.h"
114+
#include "llvm/Support/Error.h"
115+
#include "llvm/Support/FormatVariadic.h"
114116
#include "llvm/Support/MemoryBuffer.h"
115117
#include "llvm/Support/StringSaver.h"
116118
#include "llvm/Support/YAMLTraits.h"
@@ -317,7 +319,7 @@ class ExplicitModuleMapParser {
317319
public:
318320
ExplicitModuleMapParser(llvm::BumpPtrAllocator &Allocator) : Saver(Allocator) {}
319321

320-
std::error_code parseSwiftExplicitModuleMap(
322+
llvm::Error parseSwiftExplicitModuleMap(
321323
llvm::MemoryBufferRef BufferRef,
322324
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
323325
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap,
@@ -331,16 +333,15 @@ class ExplicitModuleMapParser {
331333
assert(DI != Stream.end() && "Failed to read a document");
332334
if (auto *MN = dyn_cast_or_null<SequenceNode>(DI->getRoot())) {
333335
for (auto &entry : *MN) {
334-
if (parseSingleModuleEntry(entry, swiftModuleMap, clangModuleMap,
335-
moduleAliases)) {
336-
return std::make_error_code(std::errc::invalid_argument);
337-
}
336+
if (auto Err = parseSingleModuleEntry(entry, swiftModuleMap,
337+
clangModuleMap, moduleAliases))
338+
return Err;
338339
}
339340
} else {
340-
return std::make_error_code(std::errc::invalid_argument);
341+
return llvm::createStringError("invalid JSON root object");
341342
}
342343
}
343-
return std::error_code{}; // success
344+
return llvm::Error::success(); // success
344345
}
345346

346347
private:
@@ -360,15 +361,15 @@ class ExplicitModuleMapParser {
360361
llvm_unreachable("Unexpected JSON value for isFramework");
361362
}
362363

363-
bool parseSingleModuleEntry(
364+
llvm::Error parseSingleModuleEntry(
364365
llvm::yaml::Node &node,
365366
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
366367
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap,
367368
llvm::StringMap<std::string> &moduleAliases) {
368369
using namespace llvm::yaml;
369370
auto *mapNode = dyn_cast<MappingNode>(&node);
370371
if (!mapNode)
371-
return true;
372+
return llvm::createStringError("incorrect entry type");
372373
StringRef moduleName;
373374
std::optional<std::string> swiftModulePath, swiftModuleDocPath,
374375
swiftModuleSourceInfoPath, swiftModuleCacheKey, clangModuleCacheKey,
@@ -418,7 +419,7 @@ class ExplicitModuleMapParser {
418419
}
419420
}
420421
if (moduleName.empty())
421-
return true;
422+
return llvm::createStringError("entry is missing module name");
422423

423424
bool didInsert;
424425
if (swiftModulePath.has_value()) {
@@ -445,11 +446,15 @@ class ExplicitModuleMapParser {
445446
clangModuleCacheKey);
446447
didInsert = clangModuleMap.try_emplace(moduleName, std::move(entry)).second;
447448
}
448-
if (didInsert && moduleAlias.has_value()) {
449+
if (!didInsert)
450+
return llvm::createStringError(llvm::formatv(
451+
"duplicate {0} module with name {1}",
452+
swiftModulePath.has_value() ? "Swift" : "Clang", moduleName));
453+
454+
if (moduleAlias.has_value()) {
449455
moduleAliases[*moduleAlias] = moduleName;
450456
}
451-
// Prevent duplicate module names.
452-
return !didInsert;
457+
return llvm::Error::success();
453458
}
454459

455460
llvm::StringSaver Saver;

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,13 +2258,14 @@ struct ExplicitSwiftModuleLoader::Implementation {
22582258
return;
22592259
}
22602260

2261-
auto hasError = parser.parseSwiftExplicitModuleMap(
2261+
auto error = parser.parseSwiftExplicitModuleMap(
22622262
(*fileBufOrErr)->getMemBufferRef(), ExplicitModuleMap,
22632263
ExplicitClangModuleMap, ModuleAliases);
2264-
2265-
if (hasError)
2264+
llvm::handleAllErrors(std::move(error), [this, &fileName](
2265+
const llvm::StringError &E) {
22662266
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
2267-
fileName);
2267+
fileName, E.getMessage());
2268+
});
22682269

22692270
// A single module map can define multiple modules; keep track of the ones
22702271
// we've seen so that we don't generate duplicate flags.
@@ -2536,13 +2537,14 @@ struct ExplicitCASModuleLoader::Implementation {
25362537
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
25372538
llvm::MemoryBuffer::getFile(ID);
25382539

2539-
auto hasError = parser.parseSwiftExplicitModuleMap(
2540+
auto error = parser.parseSwiftExplicitModuleMap(
25402541
buf->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap,
25412542
ModuleAliases);
2542-
2543-
if (hasError)
2543+
llvm::handleAllErrors(std::move(error), [this,
2544+
&ID](const llvm::StringError &E) {
25442545
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
2545-
ID);
2546+
ID, E.getMessage());
2547+
});
25462548

25472549
std::set<std::string> moduleMapsSeen;
25482550
std::vector<std::string> &extraClangArgs = Ctx.ClangImporterOpts.ExtraArgs;

lib/FrontendTool/FrontendTool.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,8 +1604,12 @@ static bool generateReproducer(CompilerInstance &Instance,
16041604
}
16051605
auto map = llvm::json::parse(mapProxy->getData());
16061606
if (!map) {
1607-
diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
1608-
mapOpts);
1607+
llvm::handleAllErrors(
1608+
map.takeError(), [&diags, &mapOpts](const llvm::json::ParseError &E) {
1609+
diags.diagnose(SourceLoc(),
1610+
diag::explicit_swift_module_map_corrupted, mapOpts,
1611+
E.message());
1612+
});
16091613
return true;
16101614
}
16111615
if (auto array = map->getAsArray()) {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: not %target-swift-frontend -typecheck %t/test.swift \
5+
// RUN: -explicit-swift-module-map-file %t/invalid_root_object.json \
6+
// RUN: 2>&1 | %FileCheck %s -check-prefix=CHECK-ROOT
7+
8+
// CHECK-ROOT: malformed: invalid JSON root object
9+
10+
// RUN: not %target-swift-frontend -typecheck %t/test.swift \
11+
// RUN: -explicit-swift-module-map-file %t/invalid_entry_type.json \
12+
// RUN: 2>&1 | %FileCheck %s -check-prefix=CHECK-ENTRY-TYPE
13+
14+
// CHECK-ENTRY-TYPE: malformed: incorrect entry type
15+
16+
// RUN: not %target-swift-frontend -typecheck %t/test.swift \
17+
// RUN: -explicit-swift-module-map-file %t/missing_module_name.json \
18+
// RUN: 2>&1 | %FileCheck %s -check-prefix=CHECK-NAME
19+
20+
// CHECK-NAME: malformed: entry is missing module name
21+
22+
// RUN: not %target-swift-frontend -typecheck %t/test.swift \
23+
// RUN: -explicit-swift-module-map-file %t/duplicate_swift_module.json \
24+
// RUN: 2>&1 | %FileCheck %s -check-prefix=CHECK-DUP-SWIFT
25+
26+
// CHECK-DUP-SWIFT: malformed: duplicate Swift module with name SwiftMod
27+
28+
// RUN: not %target-swift-frontend -typecheck %t/test.swift \
29+
// RUN: -explicit-swift-module-map-file %t/duplicate_clang_module.json \
30+
// RUN: 2>&1 | %FileCheck %s -check-prefix=CHECK-DUP-CLANG
31+
32+
// CHECK-DUP-CLANG: malformed: duplicate Clang module with name ClangMod
33+
34+
//--- invalid_root_object.json
35+
{
36+
"some_key": "some_val"
37+
}
38+
//--- invalid_entry_type.json
39+
[
40+
[
41+
{"some_key": "some_val"}
42+
]
43+
]
44+
//--- missing_module_name.json
45+
[
46+
{
47+
"isFramework": false,
48+
"modulePath": "/some/path"
49+
}
50+
]
51+
//--- duplicate_swift_module.json
52+
[
53+
{
54+
"isFramework": false,
55+
"moduleName": "SwiftMod",
56+
"modulePath": "/some/path"
57+
},
58+
{
59+
"isFramework": false,
60+
"moduleName": "SwiftMod",
61+
"modulePath": "/some/path"
62+
}
63+
]
64+
//--- duplicate_clang_module.json
65+
[
66+
{
67+
"isFramework": false,
68+
"moduleName": "ClangMod",
69+
"clangModulePath": "/some/path"
70+
},
71+
{
72+
"isFramework": false,
73+
"moduleName": "ClangMod",
74+
"clangModulePath": "/some/path"
75+
}
76+
]
77+
//--- test.swift
78+
import Swift

0 commit comments

Comments
 (0)