Skip to content

Commit 255d737

Browse files
authored
Merge pull request swiftlang#68549 from artemcm/NoErrorOnMissingOptionalTranstiveDep
[ClangImporter] On failing a module lookup, reset Clang's DiagnosticEngine, in addition to filtering out the "module not found" diagnostic
2 parents 70e7df9 + 4e5b054 commit 255d737

File tree

4 files changed

+78
-6
lines changed

4 files changed

+78
-6
lines changed

lib/ClangImporter/ClangDiagnosticConsumer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ void ClangDiagnosticConsumer::HandleDiagnostic(
118118
// we're looking for.
119119
if (clangDiag.getID() == clang::diag::err_module_not_found &&
120120
CurrentImport && clangDiag.getArgStdStr(0) == CurrentImport->getName()) {
121+
CurrentImportNotFound = true;
121122
return;
122123
}
123124

lib/ClangImporter/ClangDiagnosticConsumer.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ namespace swift {
2323
class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
2424
struct LoadModuleRAII {
2525
ClangDiagnosticConsumer *Consumer;
26+
clang::DiagnosticsEngine *Engine;
27+
bool DiagEngineClearPriorToLookup;
28+
2629
public:
2730
LoadModuleRAII(ClangDiagnosticConsumer &consumer,
31+
clang::DiagnosticsEngine &engine,
2832
const clang::IdentifierInfo *import)
29-
: Consumer(&consumer) {
33+
: Consumer(&consumer), Engine(&engine) {
3034
assert(import);
3135
assert(!Consumer->CurrentImport);
36+
assert(!Consumer->CurrentImportNotFound);
3237
Consumer->CurrentImport = import;
38+
DiagEngineClearPriorToLookup = !engine.hasErrorOccurred();
3339
}
3440

3541
LoadModuleRAII(LoadModuleRAII &) = delete;
@@ -45,8 +51,21 @@ class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
4551
}
4652

4753
~LoadModuleRAII() {
48-
if (Consumer)
54+
if (Consumer) {
55+
// We must reset Clang's diagnostic engine here since we know that only
56+
// the module lookup errors have been emitted. While the ClangDiagnosticConsumer
57+
// takes care of filtering out the diagnostics from the output and from
58+
// being handled by Swift's DiagnosticEngine, we must ensure to also
59+
// reset Clang's DiagnosticEngine because its state is queried in later
60+
// stages of compilation and errors emitted on "module_not_found" should not
61+
// be counted.
62+
// FIXME: We must instead allow for module loading in Clang to fail without
63+
// needing to emit a diagnostic.
64+
if (Engine && Consumer->CurrentImportNotFound && DiagEngineClearPriorToLookup)
65+
Engine->Reset();
4966
Consumer->CurrentImport = nullptr;
67+
Consumer->CurrentImportNotFound = false;
68+
}
5069
}
5170
};
5271

@@ -56,6 +75,7 @@ class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
5675
ClangImporter::Implementation &ImporterImpl;
5776

5877
const clang::IdentifierInfo *CurrentImport = nullptr;
78+
bool CurrentImportNotFound = false;
5979
SourceLoc DiagLoc;
6080
const bool DumpToStderr;
6181

@@ -65,9 +85,10 @@ class ClangDiagnosticConsumer : public clang::TextDiagnosticPrinter {
6585
bool dumpToStderr);
6686

6787
LoadModuleRAII handleImport(const clang::IdentifierInfo *name,
88+
clang::DiagnosticsEngine &engine,
6889
SourceLoc diagLoc) {
6990
DiagLoc = diagLoc;
70-
return LoadModuleRAII(*this, name);
91+
return LoadModuleRAII(*this, engine, name);
7192
}
7293

7394
void HandleDiagnostic(clang::DiagnosticsEngine::Level diagLevel,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,14 +2058,16 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang(
20582058
exportSourceLoc(component.Loc));
20592059
}
20602060

2061-
auto &rawDiagClient = Instance->getDiagnosticClient();
2061+
auto &diagEngine = Instance->getDiagnostics();
2062+
auto &rawDiagClient = *diagEngine.getClient();
20622063
auto &diagClient = static_cast<ClangDiagnosticConsumer &>(rawDiagClient);
20632064

20642065
auto loadModule = [&](clang::ModuleIdPath path,
20652066
clang::Module::NameVisibilityKind visibility)
20662067
-> clang::ModuleLoadResult {
20672068
auto importRAII =
2068-
diagClient.handleImport(clangPath.front().first, importLoc);
2069+
diagClient.handleImport(clangPath.front().first, diagEngine,
2070+
importLoc);
20692071

20702072
std::string preservedIndexStorePathOption;
20712073
auto &clangFEOpts = Instance->getFrontendOpts();
@@ -2079,7 +2081,6 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang(
20792081
}
20802082

20812083
clang::SourceLocation clangImportLoc = getNextIncludeLoc();
2082-
20832084
clang::ModuleLoadResult result =
20842085
Instance->loadModule(clangImportLoc, path, visibility,
20852086
/*IsInclusionDirective=*/false);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/clang-module-cache)
3+
// RUN: %empty-directory(%t/Foo.swiftmodule)
4+
// RUN: %empty-directory(%t/inputs)
5+
// RUN: echo "@_implementationOnly import A; public func foo() {}" > %t/Foo.swift
6+
// REQUIRES: executable_test
7+
// REQUIRES: objc_interop
8+
9+
// Create the explicit module inputs map
10+
// RUN: echo "[{" > %/t/inputs/map.json
11+
// RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json
12+
// RUN: echo "\"modulePath\": \"%/t/Foo.swiftmodule/%target-swiftmodule-name\"," >> %/t/inputs/map.json
13+
// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json
14+
// RUN: echo "}," >> %/t/inputs/map.json
15+
// RUN: echo "{" >> %/t/inputs/map.json
16+
// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json
17+
// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json
18+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
19+
// RUN: echo "}," >> %/t/inputs/map.json
20+
// RUN: echo "{" >> %/t/inputs/map.json
21+
// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json
22+
// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json
23+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
24+
// RUN: echo "}," >> %/t/inputs/map.json
25+
// RUN: echo "{" >> %/t/inputs/map.json
26+
// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json
27+
// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json
28+
// RUN: echo "\"clangModuleMapPath\": \"%swift-lib-dir/swift/shims/module.modulemap\"," >> %/t/inputs/map.json
29+
// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json
30+
// RUN: echo "}]" >> %/t/inputs/map.json
31+
32+
// Emit the shims module PCM for explicit loading
33+
// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm
34+
35+
@testable import Foo
36+
37+
// Step 1: build Foo Swift module
38+
// RUN: %target-swift-frontend -emit-module %t/Foo.swift -emit-module-path %t/Foo.swiftmodule/%target-swiftmodule-name -module-name Foo -emit-module-interface-path %t/Foo.swiftmodule/%target-swiftinterface-name -enable-library-evolution -I %S/Inputs/CHeaders -I %S/Inputs/Swift -enable-testing -swift-version 5 -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import
39+
40+
// Step 2: scan dependencies and ensure the transitive dependency on "A" is misssing
41+
// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -sdk %t -prebuilt-module-cache-path %t/clang-module-cache
42+
// RUN: %validate-json %t/deps.json | %FileCheck -check-prefix CHECK_SCAN %s
43+
// CHECK_SCAN-NOT: "swift": "A"
44+
45+
// Step 3: Run an explicit module compile of this file ensuring object files are produced
46+
// RUN: %target-swift-frontend -emit-object -o %t/optional_transitive_dep_load_fail.o -disable-implicit-swift-modules -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -module-cache-path %t.module-cache -explicit-swift-module-map-file %t/inputs/map.json %s
47+
48+
// Step 4: Ensure the resulting object file exists
49+
// RUN: ls %t/optional_transitive_dep_load_fail.o > /dev/null

0 commit comments

Comments
 (0)