Skip to content

Commit f0cf220

Browse files
committed
DependenciesScanner: add implicitly imported modules to dependencies of Swift module interfaces
Some implicitly imported modules aren't printed in the textual interface file as explicit import, e.g. SwiftOnoneSupport. We should check implicit imports and add them to the dependency graph.
1 parent 2680b0c commit f0cf220

File tree

5 files changed

+80
-42
lines changed

5 files changed

+80
-42
lines changed

include/swift/AST/ModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ struct InterfaceSubContextDelegate {
107107
StringRef interfacePath,
108108
StringRef outputPath,
109109
SourceLoc diagLoc,
110-
llvm::function_ref<bool(ASTContext&,ArrayRef<StringRef>,
110+
llvm::function_ref<bool(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
111111
ArrayRef<StringRef>, StringRef)> action) = 0;
112112
virtual bool runInSubCompilerInstance(StringRef moduleName,
113113
StringRef interfacePath,

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
359359
llvm::BumpPtrAllocator Allocator;
360360
llvm::StringSaver ArgSaver;
361361
std::vector<StringRef> GenericArgs;
362-
CompilerInvocation subInvocation;
362+
CompilerInvocation genericSubInvocation;
363363

364364
template<typename ...ArgTypes>
365365
InFlightDiagnostic diagnose(StringRef interfacePath,
@@ -375,7 +375,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
375375
}
376376
void inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
377377
const LangOptions &LangOpts);
378-
bool extractSwiftInterfaceVersionAndArgs(SmallVectorImpl<const char *> &SubArgs,
378+
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,
379+
SmallVectorImpl<const char *> &SubArgs,
379380
std::string &CompilerVersion,
380381
StringRef interfacePath,
381382
SourceLoc diagnosticLoc);
@@ -395,7 +396,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
395396
StringRef interfacePath,
396397
StringRef outputPath,
397398
SourceLoc diagLoc,
398-
llvm::function_ref<bool(ASTContext&, ArrayRef<StringRef>,
399+
llvm::function_ref<bool(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
399400
ArrayRef<StringRef>, StringRef)> action) override;
400401
bool runInSubCompilerInstance(StringRef moduleName,
401402
StringRef interfacePath,

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ class ModuleInterfaceLoaderImpl {
852852
/*serializeDependencyHashes*/false,
853853
trackSystemDependencies);
854854
// Set up a builder if we need to build the module. It'll also set up
855-
// the subinvocation we'll need to use to compute the cache paths.
855+
// the genericSubInvocation we'll need to use to compute the cache paths.
856856
ModuleInterfaceBuilder builder(
857857
ctx.SourceMgr, ctx.Diags, astDelegate, interfacePath, moduleName, cacheDir,
858858
prebuiltCacheDir,
@@ -1118,68 +1118,69 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
11181118
const SearchPathOptions &SearchPathOpts,
11191119
const LangOptions &LangOpts) {
11201120
GenericArgs.push_back("-frontend");
1121-
// Start with a SubInvocation that copies various state from our
1121+
// Start with a genericSubInvocation that copies various state from our
11221122
// invoking ASTContext.
11231123
GenericArgs.push_back("-compile-module-from-interface");
1124-
subInvocation.setTargetTriple(LangOpts.Target);
1124+
genericSubInvocation.setTargetTriple(LangOpts.Target);
11251125

1126-
auto triple = ArgSaver.save(subInvocation.getTargetTriple());
1126+
auto triple = ArgSaver.save(genericSubInvocation.getTargetTriple());
11271127
if (!triple.empty()) {
11281128
GenericArgs.push_back("-target");
11291129
GenericArgs.push_back(triple);
11301130
}
11311131

11321132
// Inherit the Swift language version
1133-
subInvocation.getLangOptions().EffectiveLanguageVersion =
1133+
genericSubInvocation.getLangOptions().EffectiveLanguageVersion =
11341134
LangOpts.EffectiveLanguageVersion;
11351135
GenericArgs.push_back("-swift-version");
1136-
GenericArgs.push_back(ArgSaver.save(subInvocation.getLangOptions()
1136+
GenericArgs.push_back(ArgSaver.save(genericSubInvocation.getLangOptions()
11371137
.EffectiveLanguageVersion.asAPINotesVersionString()));
11381138

1139-
subInvocation.setImportSearchPaths(SearchPathOpts.ImportSearchPaths);
1139+
genericSubInvocation.setImportSearchPaths(SearchPathOpts.ImportSearchPaths);
11401140
llvm::for_each(SearchPathOpts.ImportSearchPaths,
11411141
[&](const std::string &path) {
11421142
GenericArgs.push_back("-I");
11431143
GenericArgs.push_back(path);
11441144
});
1145-
subInvocation.setFrameworkSearchPaths(SearchPathOpts.FrameworkSearchPaths);
1145+
genericSubInvocation.setFrameworkSearchPaths(SearchPathOpts.FrameworkSearchPaths);
11461146
llvm::for_each(SearchPathOpts.FrameworkSearchPaths,
11471147
[&](const SearchPathOptions::FrameworkSearchPath &path) {
11481148
GenericArgs.push_back(path.IsSystem? "-Fsystem": "-F");
11491149
GenericArgs.push_back(path.Path);
11501150
});
11511151
if (!SearchPathOpts.SDKPath.empty()) {
1152-
subInvocation.setSDKPath(SearchPathOpts.SDKPath);
1152+
genericSubInvocation.setSDKPath(SearchPathOpts.SDKPath);
11531153
GenericArgs.push_back("-sdk");
11541154
GenericArgs.push_back(SearchPathOpts.SDKPath);
11551155
}
11561156

1157-
subInvocation.setInputKind(InputFileKind::SwiftModuleInterface);
1157+
genericSubInvocation.setInputKind(InputFileKind::SwiftModuleInterface);
11581158
if (!SearchPathOpts.RuntimeResourcePath.empty()) {
1159-
subInvocation.setRuntimeResourcePath(SearchPathOpts.RuntimeResourcePath);
1159+
genericSubInvocation.setRuntimeResourcePath(SearchPathOpts.RuntimeResourcePath);
11601160
GenericArgs.push_back("-resource-dir");
11611161
GenericArgs.push_back(SearchPathOpts.RuntimeResourcePath);
11621162
}
11631163

1164-
// Inhibit warnings from the SubInvocation since we are assuming the user
1164+
// Inhibit warnings from the genericSubInvocation since we are assuming the user
11651165
// is not in a position to fix them.
1166-
subInvocation.getDiagnosticOptions().SuppressWarnings = true;
1166+
genericSubInvocation.getDiagnosticOptions().SuppressWarnings = true;
11671167
GenericArgs.push_back("-suppress-warnings");
11681168

11691169
// Inherit this setting down so that it can affect error diagnostics (mostly
11701170
// by making them non-fatal).
1171-
subInvocation.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport;
1171+
genericSubInvocation.getLangOptions().DebuggerSupport = LangOpts.DebuggerSupport;
11721172
if (LangOpts.DebuggerSupport) {
11731173
GenericArgs.push_back("-debugger-support");
11741174
}
11751175

11761176
// Disable this; deinitializers always get printed with `@objc` even in
11771177
// modules that don't import Foundation.
1178-
subInvocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
1178+
genericSubInvocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
11791179
GenericArgs.push_back("-disable-objc-attr-requires-foundation-module");
11801180
}
11811181

11821182
bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
1183+
CompilerInvocation &subInvocation,
11831184
SmallVectorImpl<const char *> &SubArgs,
11841185
std::string &CompilerVersion,
11851186
StringRef interfacePath,
@@ -1251,7 +1252,7 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
12511252
}
12521253

12531254
void InterfaceSubContextDelegateImpl::addExtraClangArg(StringRef arg) {
1254-
subInvocation.getClangImporterOptions().ExtraArgs.push_back(arg);
1255+
genericSubInvocation.getClangImporterOptions().ExtraArgs.push_back(arg);
12551256
GenericArgs.push_back("-Xcc");
12561257
GenericArgs.push_back(ArgSaver.save(arg));
12571258
}
@@ -1268,36 +1269,36 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
12681269
StringRef prebuiltCachePath,
12691270
bool serializeDependencyHashes,
12701271
bool trackSystemDependencies): SM(SM), Diags(Diags), ArgSaver(Allocator) {
1271-
subInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
1272+
genericSubInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
12721273
inheritOptionsForBuildingInterface(searchPathOpts, langOpts);
12731274
// Configure front-end input.
1274-
auto &SubFEOpts = subInvocation.getFrontendOptions();
1275+
auto &SubFEOpts = genericSubInvocation.getFrontendOptions();
12751276
SubFEOpts.RequestedAction = FrontendOptions::ActionType::EmitModuleOnly;
12761277
if (!moduleCachePath.empty()) {
1277-
subInvocation.setClangModuleCachePath(moduleCachePath);
1278+
genericSubInvocation.setClangModuleCachePath(moduleCachePath);
12781279
GenericArgs.push_back("-module-cache-path");
12791280
GenericArgs.push_back(moduleCachePath);
12801281
}
12811282
if (!prebuiltCachePath.empty()) {
1282-
subInvocation.getFrontendOptions().PrebuiltModuleCachePath =
1283+
genericSubInvocation.getFrontendOptions().PrebuiltModuleCachePath =
12831284
prebuiltCachePath.str();
12841285
GenericArgs.push_back("-prebuilt-module-cache-path");
12851286
GenericArgs.push_back(prebuiltCachePath);
12861287
}
12871288
if (trackSystemDependencies) {
1288-
subInvocation.getFrontendOptions().IntermoduleDependencyTracking =
1289+
genericSubInvocation.getFrontendOptions().IntermoduleDependencyTracking =
12891290
IntermoduleDepTrackingMode::IncludeSystem;
12901291
GenericArgs.push_back("-track-system-dependencies");
12911292
} else {
12921293
// Always track at least the non-system dependencies for interface building.
1293-
subInvocation.getFrontendOptions().IntermoduleDependencyTracking =
1294+
genericSubInvocation.getFrontendOptions().IntermoduleDependencyTracking =
12941295
IntermoduleDepTrackingMode::ExcludeSystem;
12951296
}
12961297
if (LoaderOpts.disableImplicitSwiftModule) {
1297-
subInvocation.getFrontendOptions().DisableImplicitModules = true;
1298+
genericSubInvocation.getFrontendOptions().DisableImplicitModules = true;
12981299
GenericArgs.push_back("-disable-implicit-swift-modules");
12991300
}
1300-
subInvocation.getSearchPathOptions().ExplicitSwiftModules =
1301+
genericSubInvocation.getSearchPathOptions().ExplicitSwiftModules =
13011302
searchPathOpts.ExplicitSwiftModules;
13021303
// Dependencies scanner shouldn't know any explict Swift modules to use.
13031304
// Adding these argumnets may not be necessary.
@@ -1309,7 +1310,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
13091310
// Pass down -explicit-swift-module-map-file
13101311
// FIXME: we shouldn't need this. Remove it?
13111312
StringRef explictSwiftModuleMap = searchPathOpts.ExplicitSwiftModuleMap;
1312-
subInvocation.getSearchPathOptions().ExplicitSwiftModuleMap =
1313+
genericSubInvocation.getSearchPathOptions().ExplicitSwiftModuleMap =
13131314
explictSwiftModuleMap;
13141315
if (!explictSwiftModuleMap.empty()) {
13151316
GenericArgs.push_back("-explicit-swift-module-map-file");
@@ -1329,19 +1330,19 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
13291330
// required by sourcekitd.
13301331
auto &Opts = clangImporter->getClangInstance().getPreprocessorOpts();
13311332
if (Opts.DetailedRecord) {
1332-
subInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true;
1333+
genericSubInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true;
13331334
}
13341335
}
13351336

1336-
// Tell the subinvocation to serialize dependency hashes if asked to do so.
1337-
auto &frontendOpts = subInvocation.getFrontendOptions();
1337+
// Tell the genericSubInvocation to serialize dependency hashes if asked to do so.
1338+
auto &frontendOpts = genericSubInvocation.getFrontendOptions();
13381339
frontendOpts.SerializeModuleInterfaceDependencyHashes =
13391340
serializeDependencyHashes;
13401341
if (serializeDependencyHashes) {
13411342
GenericArgs.push_back("-serialize-module-interface-dependency-hashes");
13421343
}
13431344

1344-
// Tell the subinvocation to remark on rebuilds from an interface if asked
1345+
// Tell the genericSubInvocation to remark on rebuilds from an interface if asked
13451346
// to do so.
13461347
frontendOpts.RemarkOnRebuildFromModuleInterface =
13471348
LoaderOpts.remarkOnRebuildFromInterface;
@@ -1355,14 +1356,14 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
13551356
(void)llvm::sys::fs::create_directories(moduleCachePath);
13561357
}
13571358

1358-
/// Calculate an output filename in \p SubInvocation's cache path that
1359+
/// Calculate an output filename in \p genericSubInvocation's cache path that
13591360
/// includes a hash of relevant key data.
13601361
StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
13611362
StringRef moduleName,
13621363
StringRef useInterfacePath,
13631364
llvm::SmallString<256> &OutPath,
13641365
StringRef &CacheHash) {
1365-
OutPath = subInvocation.getClangModuleCachePath();
1366+
OutPath = genericSubInvocation.getClangModuleCachePath();
13661367
llvm::sys::path::append(OutPath, moduleName);
13671368
OutPath.append("-");
13681369
auto hashStart = OutPath.size();
@@ -1387,7 +1388,7 @@ StringRef InterfaceSubContextDelegateImpl::computeCachedOutputPath(
13871388
std::string
13881389
InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
13891390
auto normalizedTargetTriple =
1390-
getTargetSpecificModuleTriple(subInvocation.getLangOptions().Target);
1391+
getTargetSpecificModuleTriple(genericSubInvocation.getLangOptions().Target);
13911392

13921393
llvm::hash_code H = hash_combine(
13931394
// Start with the compiler version (which will be either tag names or
@@ -1411,11 +1412,11 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) {
14111412

14121413
// The SDK path is going to affect how this module is imported, so
14131414
// include it.
1414-
subInvocation.getSDKPath(),
1415+
genericSubInvocation.getSDKPath(),
14151416

14161417
// Whether or not we're tracking system dependencies affects the
14171418
// invalidation behavior of this cache item.
1418-
subInvocation.getFrontendOptions().shouldTrackSystemDependencies());
1419+
genericSubInvocation.getFrontendOptions().shouldTrackSystemDependencies());
14191420

14201421
return llvm::APInt(64, H).toString(36, /*Signed=*/false);
14211422
}
@@ -1424,11 +1425,13 @@ bool InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName,
14241425
StringRef interfacePath,
14251426
StringRef outputPath,
14261427
SourceLoc diagLoc,
1427-
llvm::function_ref<bool(ASTContext&, ArrayRef<StringRef>,
1428+
llvm::function_ref<bool(ASTContext&, ModuleDecl*, ArrayRef<StringRef>,
14281429
ArrayRef<StringRef>, StringRef)> action) {
14291430
return runInSubCompilerInstance(moduleName, interfacePath, outputPath, diagLoc,
14301431
[&](SubCompilerInstanceInfo &info){
1431-
return action(info.Instance->getASTContext(), info.BuildArguments,
1432+
return action(info.Instance->getASTContext(),
1433+
info.Instance->getMainModule(),
1434+
info.BuildArguments,
14321435
info.ExtraPCMArgs,
14331436
info.Hash);
14341437
});
@@ -1439,6 +1442,10 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN
14391442
StringRef outputPath,
14401443
SourceLoc diagLoc,
14411444
llvm::function_ref<bool(SubCompilerInstanceInfo&)> action) {
1445+
// We are about to mess up the compiler invocation by using the compiler
1446+
// arguments in the textual interface file. So copy to use a new compiler
1447+
// invocation.
1448+
CompilerInvocation subInvocation = genericSubInvocation;
14421449
std::vector<StringRef> BuildArgs(GenericArgs.begin(), GenericArgs.end());
14431450
assert(BuildArgs.size() == GenericArgs.size());
14441451
// Configure inputs
@@ -1473,7 +1480,8 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN
14731480
std::string CompilerVersion;
14741481
// Extract compiler arguments from the interface file and use them to configure
14751482
// the compiler invocation.
1476-
if (extractSwiftInterfaceVersionAndArgs(SubArgs,
1483+
if (extractSwiftInterfaceVersionAndArgs(subInvocation,
1484+
SubArgs,
14771485
CompilerVersion,
14781486
interfacePath,
14791487
diagLoc)) {

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "swift/AST/DiagnosticsFrontend.h"
1616
#include "swift/AST/ModuleDependencies.h"
1717
#include "swift/AST/SourceFile.h"
18+
#include "swift/AST/TypeCheckRequests.h"
1819
#include "swift/Basic/FileTypes.h"
1920
#include "swift/Frontend/ModuleInterfaceLoader.h"
2021
#include "swift/Serialization/SerializedModuleLoader.h"
@@ -184,8 +185,10 @@ ErrorOr<ModuleDependencies> ModuleDependencyScanner::scanInterfaceFile(
184185
moduleInterfacePath.str(),
185186
StringRef(),
186187
SourceLoc(),
187-
[&](ASTContext &Ctx, ArrayRef<StringRef> Args,
188+
[&](ASTContext &Ctx, ModuleDecl *mainMod,
189+
ArrayRef<StringRef> Args,
188190
ArrayRef<StringRef> PCMArgs, StringRef Hash) {
191+
assert(mainMod);
189192
std::string InPath = moduleInterfacePath.str();
190193
auto compiledCandidates = getCompiledCandidates(Ctx, moduleName.str(),
191194
InPath);
@@ -211,6 +214,13 @@ ErrorOr<ModuleDependencies> ModuleDependencyScanner::scanInterfaceFile(
211214
// Walk the source file to find the import declarations.
212215
llvm::StringSet<> alreadyAddedModules;
213216
Result->addModuleDependencies(*sourceFile, alreadyAddedModules);
217+
218+
// Collect implicitly imported modules in case they are not explicitly
219+
// printed in the interface file, e.g. SwiftOnoneSupport.
220+
auto &imInfo = mainMod->getImplicitImportInfo();
221+
for (auto name: imInfo.ModuleNames) {
222+
Result->addModuleDependency(name.str(), &alreadyAddedModules);
223+
}
214224
return false;
215225
});
216226

test/ScanDependencies/module_deps.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ import SubE
122122
// CHECK-NEXT: },
123123
// CHECK-NEXT: {
124124
// CHECK-NEXT: "clang": "G"
125+
// CHECK-NEXT: },
126+
// CHECK-NEXT: {
127+
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
125128
// CHECK-NEXT: }
126129
// CHECK-NEXT: ],
127130
// CHECK-NEXT: "details": {
@@ -148,6 +151,22 @@ import SubE
148151
// CHECK-NEXT: {
149152
// CHECK-NEXT: "clang": "SwiftShims"
150153

154+
/// --------Swift module F
155+
// CHECK: "modulePath": "F.swiftmodule",
156+
// CHECK-NEXT: "sourceFiles": [
157+
// CHECK-NEXT: ],
158+
// CHECK-NEXT: "directDependencies": [
159+
// CHECK-NEXT: {
160+
// CHECK-NEXT: "swift": "Swift"
161+
// CHECK-NEXT: },
162+
// CHECK-NEXT: {
163+
// CHECK-NEXT: "clang": "F"
164+
// CHECK-NEXT: },
165+
// CHECK-NEXT: {
166+
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
167+
// CHECK-NEXT: }
168+
// CHECK-NEXT: ],
169+
151170
/// --------Swift module A
152171
// CHECK-LABEL: "modulePath": "A.swiftmodule",
153172

0 commit comments

Comments
 (0)