Skip to content

Commit 94898aa

Browse files
committed
[Dependency Scanning][C++Interop] Do not query 'CxxStdlib' Swift overlay for textual modules which were not built with c++interop
When we discover a textual module dependency which is a module which was not originally built from source using C++ interop (specifying '-formal-cxx-interoperability-mode=off'), avoid looking up the C++ standard library Swift overlay for it. This is required for the case of the 'Darwin' module, for example, which includes headers which map to C++ stdlib headers when the compiler is operating in C++ interop mode, but the C++ standard library Swift overlay module itself depends on 'Darwin', which results in a cycle. To resolve such situations, we can rely on the fact that Swift textual interfaces of modules which were not built with C++ interop must be able to build without importing the C++ standard library Swift overlay, so we avoid specifying it as a dependency for such modules. The primary source module, as well as Swift textual module dependencies which *were* built with C++ interop will continue getting a direct depedency of the 'CxxStdlib' Swift module. Resolves rdar://150222155
1 parent 84058a7 commit 94898aa

File tree

4 files changed

+118
-32
lines changed

4 files changed

+118
-32
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ class ModuleDependencyInfo {
689689
storage->importedSwiftModules.assign(dependencyIDs.begin(),
690690
dependencyIDs.end());
691691
}
692-
const ArrayRef<ModuleDependencyID> getImportedSwiftDependencies() const {
692+
ArrayRef<ModuleDependencyID> getImportedSwiftDependencies() const {
693693
return storage->importedSwiftModules;
694694
}
695695

@@ -698,7 +698,7 @@ class ModuleDependencyInfo {
698698
storage->importedClangModules.assign(dependencyIDs.begin(),
699699
dependencyIDs.end());
700700
}
701-
const ArrayRef<ModuleDependencyID> getImportedClangDependencies() const {
701+
ArrayRef<ModuleDependencyID> getImportedClangDependencies() const {
702702
return storage->importedClangModules;
703703
}
704704

@@ -732,7 +732,7 @@ class ModuleDependencyInfo {
732732
}
733733
}
734734
}
735-
const ArrayRef<ModuleDependencyID> getHeaderClangDependencies() const {
735+
ArrayRef<ModuleDependencyID> getHeaderClangDependencies() const {
736736
switch (getKind()) {
737737
case swift::ModuleDependencyKind::SwiftInterface: {
738738
auto swiftInterfaceStorage =
@@ -760,7 +760,7 @@ class ModuleDependencyInfo {
760760
storage->swiftOverlayDependencies.assign(dependencyIDs.begin(),
761761
dependencyIDs.end());
762762
}
763-
const ArrayRef<ModuleDependencyID> getSwiftOverlayDependencies() const {
763+
ArrayRef<ModuleDependencyID> getSwiftOverlayDependencies() const {
764764
return storage->swiftOverlayDependencies;
765765
}
766766

@@ -770,11 +770,11 @@ class ModuleDependencyInfo {
770770
storage->crossImportOverlayModules.assign(dependencyIDs.begin(),
771771
dependencyIDs.end());
772772
}
773-
const ArrayRef<ModuleDependencyID> getCrossImportOverlayDependencies() const {
773+
ArrayRef<ModuleDependencyID> getCrossImportOverlayDependencies() const {
774774
return storage->crossImportOverlayModules;
775775
}
776776

777-
const ArrayRef<LinkLibrary> getLinkLibraries() const {
777+
ArrayRef<LinkLibrary> getLinkLibraries() const {
778778
return storage->linkLibraries;
779779
}
780780

@@ -783,7 +783,7 @@ class ModuleDependencyInfo {
783783
storage->linkLibraries.assign(linkLibraries.begin(), linkLibraries.end());
784784
}
785785

786-
const ArrayRef<std::string> getAuxiliaryFiles() const {
786+
ArrayRef<std::string> getAuxiliaryFiles() const {
787787
return storage->auxiliaryFiles;
788788
}
789789

@@ -795,7 +795,7 @@ class ModuleDependencyInfo {
795795
return false;
796796
}
797797

798-
const ArrayRef<std::string> getHeaderInputSourceFiles() const {
798+
ArrayRef<std::string> getHeaderInputSourceFiles() const {
799799
if (auto *detail = getAsSwiftInterfaceModule())
800800
return detail->textualModuleDetails.bridgingSourceFiles;
801801
if (auto *detail = getAsSwiftSourceModule())
@@ -805,7 +805,7 @@ class ModuleDependencyInfo {
805805
return {};
806806
}
807807

808-
std::vector<std::string> getCommandline() const {
808+
ArrayRef<std::string> getCommandline() const {
809809
if (auto *detail = getAsClangModule())
810810
return detail->buildCommandLine;
811811
if (auto *detail = getAsSwiftInterfaceModule())
@@ -828,7 +828,7 @@ class ModuleDependencyInfo {
828828
llvm_unreachable("Unexpected type");
829829
}
830830

831-
std::vector<std::string> getBridgingHeaderCommandline() const {
831+
ArrayRef<std::string> getBridgingHeaderCommandline() const {
832832
if (auto *detail = getAsSwiftSourceModule())
833833
return detail->bridgingHeaderBuildCommandLine;
834834
return {};

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
468468
// build command to main module to ensure frontend gets the same result.
469469
// This needs to happen after visiting all the top-level decls from all
470470
// SourceFiles.
471-
auto buildArgs = mainDependencies.getCommandline();
471+
std::vector<std::string> buildArgs = mainDependencies.getCommandline();
472472
mainModule->getASTContext().forEachCanImportVersionCheck(
473473
[&](StringRef moduleName, const llvm::VersionTuple &Version,
474474
const llvm::VersionTuple &UnderlyingVersion) {
@@ -1328,25 +1328,33 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
13281328
recordResult(clangDep);
13291329

13301330
// C++ Interop requires additional handling
1331-
if (ScanCompilerInvocation.getLangOptions().EnableCXXInterop) {
1332-
for (const auto &clangDepName : allClangDependencies) {
1333-
// If this Clang module is a part of the C++ stdlib, and we haven't loaded
1334-
// the overlay for it so far, it is a split libc++ module (e.g.
1335-
// std_vector). Load the CxxStdlib overlay explicitly.
1336-
const auto &clangDepInfo =
1337-
cache.findDependency(clangDepName, ModuleDependencyKind::Clang)
1338-
.value()
1339-
->getAsClangModule();
1340-
if (importer::isCxxStdModule(clangDepName, clangDepInfo->IsSystem) &&
1341-
!swiftOverlayDependencies.contains(
1342-
{clangDepName, ModuleDependencyKind::SwiftInterface}) &&
1343-
!swiftOverlayDependencies.contains(
1344-
{clangDepName, ModuleDependencyKind::SwiftBinary})) {
1345-
ScanningThreadPool.async(
1346-
scanForSwiftDependency,
1347-
getModuleImportIdentifier(ScanASTContext.Id_CxxStdlib.str()));
1348-
ScanningThreadPool.wait();
1349-
recordResult(ScanASTContext.Id_CxxStdlib.str().str());
1331+
if (ScanCompilerInvocation.getLangOptions().EnableCXXInterop &&
1332+
moduleID.Kind == ModuleDependencyKind::SwiftInterface) {
1333+
const auto &moduleInfo = cache.findKnownDependency(moduleID);
1334+
const auto commandLine = moduleInfo.getCommandline();
1335+
1336+
// If the textual interface was built without C++ interop, do not query
1337+
// the C++ Standard Library Swift overlay for its compilation.
1338+
if (llvm::find(commandLine, "-formal-cxx-interoperability-mode=off") ==
1339+
commandLine.end()) {
1340+
for (const auto &clangDepName : allClangDependencies) {
1341+
// If this Clang module is a part of the C++ stdlib, and we haven't
1342+
// loaded the overlay for it so far, it is a split libc++ module (e.g.
1343+
// std_vector). Load the CxxStdlib overlay explicitly.
1344+
const auto &clangDepInfo =
1345+
cache.findDependency(clangDepName, ModuleDependencyKind::Clang)
1346+
.value()
1347+
->getAsClangModule();
1348+
if (importer::isCxxStdModule(clangDepName, clangDepInfo->IsSystem) &&
1349+
!swiftOverlayDependencies.contains(
1350+
{clangDepName, ModuleDependencyKind::SwiftInterface}) &&
1351+
!swiftOverlayDependencies.contains(
1352+
{clangDepName, ModuleDependencyKind::SwiftBinary})) {
1353+
scanForSwiftDependency(
1354+
getModuleImportIdentifier(ScanASTContext.Id_CxxStdlib.str()));
1355+
recordResult(ScanASTContext.Id_CxxStdlib.str().str());
1356+
break;
1357+
}
13501358
}
13511359
}
13521360
}
@@ -1401,7 +1409,7 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
14011409
// Update the command-line on the main module to
14021410
// disable implicit cross-import overlay search.
14031411
auto mainDep = cache.findKnownDependency(actualMainID);
1404-
auto cmdCopy = mainDep.getCommandline();
1412+
std::vector<std::string> cmdCopy = mainDep.getCommandline();
14051413
cmdCopy.push_back("-disable-cross-import-overlay-search");
14061414
for (auto &entry : overlayFiles) {
14071415
mainDep.addAuxiliaryFile(entry.second);

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ generateFullDependencyGraph(const CompilerInstance &instance,
933933
moduleInfo->details = getModuleDetails();
934934

935935
// Create a link libraries set for this module
936-
auto &linkLibraries = moduleDependencyInfo.getLinkLibraries();
936+
auto linkLibraries = moduleDependencyInfo.getLinkLibraries();
937937
swiftscan_link_library_set_t *linkLibrarySet =
938938
new swiftscan_link_library_set_t;
939939
linkLibrarySet->count = linkLibraries.size();
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: %empty-directory(%t/deps)
3+
// RUN: split-file %s %t
4+
5+
// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json %t/clientWithInteropDep.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -verify
6+
// RUN: cat %t/deps.json | %FileCheck %s -check-prefix=ENABLE-CHECK
7+
8+
// RUN: %target-swift-frontend -scan-dependencies -o %t/deps_no_interop_dep.json %t/clientNoInteropDep.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -verify
9+
// RUN: cat %t/deps_no_interop_dep.json | %FileCheck %s -check-prefix=DISABLE-CHECK
10+
11+
//--- deps/bar.h
12+
void bar(void);
13+
14+
//--- deps/module.modulemap
15+
module std_Bar [system] {
16+
header "bar.h"
17+
export *
18+
}
19+
20+
//--- deps/Foo.swiftinterface
21+
// swift-interface-format-version: 1.0
22+
// swift-module-flags: -module-name Foo -enable-library-evolution
23+
import std_Bar
24+
public struct Foo1 {}
25+
26+
//--- deps/FooNoInterop.swiftinterface
27+
// swift-interface-format-version: 1.0
28+
// swift-module-flags: -module-name FooNoInterop -enable-library-evolution
29+
// swift-module-flags-ignorable: -formal-cxx-interoperability-mode=off
30+
import std_Bar
31+
public struct Foo2 {}
32+
33+
//--- clientWithInteropDep.swift
34+
import Foo
35+
36+
//--- clientNoInteropDep.swift
37+
import FooNoInterop
38+
39+
// Ensure that when the 'Foo' dependency was built with C++ interop enabled,
40+
// it gets the C++ standard library overlay for its 'std_*' dependency
41+
//
42+
// 'Foo' as it appears in direct deps
43+
// ENABLE-CHECK: "swift": "Foo"
44+
// 'Foo' as it appears in source-import deps
45+
// ENABLE-CHECK: "swift": "Foo"
46+
// Actual dependency info node
47+
// ENABLE-CHECK: "swift": "Foo"
48+
// ENABLE-CHECK: "directDependencies": [
49+
// ENABLE-CHECK: {
50+
// ENABLE-CHECK: "swift": "SwiftOnoneSupport"
51+
// ENABLE-CHECK: },
52+
// ENABLE-CHECK: {
53+
// ENABLE-CHECK: "swift": "CxxStdlib"
54+
// ENABLE-CHECK: },
55+
// ENABLE-CHECK: {
56+
// ENABLE-CHECK: "clang": "std_Bar"
57+
// ENABLE-CHECK: }
58+
// ENABLE-CHECK: ],
59+
60+
// Ensure that when the 'Foo' dependency was *not* built with C++ interop enabled,
61+
// it does not get the C++ standard library overlay for its 'std_*' dependency
62+
//
63+
// 'Foo' as it appears in direct deps
64+
// DISABLE-CHECK: "swift": "FooNoInterop"
65+
// 'Foo' as it appears in source-import deps
66+
// DISABLE-CHECK: "swift": "FooNoInterop"
67+
// Actual dependency info node
68+
// DISABLE-CHECK: "swift": "FooNoInterop"
69+
// DISABLE-CHECK: "directDependencies": [
70+
// DISABLE-CHECK: {
71+
// DISABLE-CHECK: "swift": "SwiftOnoneSupport"
72+
// DISABLE-CHECK: },
73+
// DISABLE-CHECK: {
74+
// DISABLE-CHECK: "clang": "std_Bar"
75+
// DISABLE-CHECK: }
76+
// DISABLE-CHECK: ],
77+
78+

0 commit comments

Comments
 (0)