[Dependency Scanning] Keep track of each imported module's access control

Adds an access control field for each imported module identified. When multiple imports of the same module are found, this keeps track of the most "open" access specifier.
This commit is contained in:
Artem Chikin
2025-06-10 16:05:54 -07:00
parent c24bae70e8
commit 6816922dd4
9 changed files with 105 additions and 70 deletions

View File

@@ -156,30 +156,35 @@ struct ScannerImportStatementInfo {
uint32_t columnNumber; uint32_t columnNumber;
}; };
ScannerImportStatementInfo(std::string importIdentifier, bool isExported) ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
: importLocations(), importIdentifier(importIdentifier), AccessLevel accessLevel)
isExported(isExported) {} : importIdentifier(importIdentifier), importLocations(),
isExported(isExported), accessLevel(accessLevel) {}
ScannerImportStatementInfo(std::string importIdentifier, bool isExported, ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
AccessLevel accessLevel,
ImportDiagnosticLocationInfo location) ImportDiagnosticLocationInfo location)
: importLocations({location}), importIdentifier(importIdentifier), : importIdentifier(importIdentifier), importLocations({location}),
isExported(isExported) {} isExported(isExported), accessLevel(accessLevel) {}
ScannerImportStatementInfo(std::string importIdentifier, bool isExported, ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
AccessLevel accessLevel,
SmallVector<ImportDiagnosticLocationInfo, 4> locations) SmallVector<ImportDiagnosticLocationInfo, 4> locations)
: importLocations(locations), importIdentifier(importIdentifier), : importIdentifier(importIdentifier), importLocations(locations),
isExported(isExported) {} isExported(isExported), accessLevel(accessLevel) {}
void addImportLocation(ImportDiagnosticLocationInfo location) { void addImportLocation(ImportDiagnosticLocationInfo location) {
importLocations.push_back(location); importLocations.push_back(location);
} }
/// Buffer, line & column number of the import statement
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
/// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar' /// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar'
std::string importIdentifier; std::string importIdentifier;
/// Buffer, line & column number of the import statement
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
/// Is this an @_exported import /// Is this an @_exported import
bool isExported; bool isExported;
/// Access level of this dependency
AccessLevel accessLevel;
}; };
/// Base class for the variant storage of ModuleDependencyInfo. /// Base class for the variant storage of ModuleDependencyInfo.
@@ -942,6 +947,7 @@ public:
/// Add a dependency on the given module, if it was not already in the set. /// Add a dependency on the given module, if it was not already in the set.
void void
addOptionalModuleImport(StringRef module, bool isExported, addOptionalModuleImport(StringRef module, bool isExported,
AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules = nullptr); llvm::StringSet<> *alreadyAddedModules = nullptr);
/// Add all of the module imports in the given source /// Add all of the module imports in the given source
@@ -952,12 +958,14 @@ public:
/// Add a dependency on the given module, if it was not already in the set. /// Add a dependency on the given module, if it was not already in the set.
void addModuleImport(ImportPath::Module module, bool isExported, void addModuleImport(ImportPath::Module module, bool isExported,
AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules = nullptr, llvm::StringSet<> *alreadyAddedModules = nullptr,
const SourceManager *sourceManager = nullptr, const SourceManager *sourceManager = nullptr,
SourceLoc sourceLocation = SourceLoc()); SourceLoc sourceLocation = SourceLoc());
/// Add a dependency on the given module, if it was not already in the set. /// Add a dependency on the given module, if it was not already in the set.
void addModuleImport(StringRef module, bool isExported, void addModuleImport(StringRef module, bool isExported,
AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules = nullptr, llvm::StringSet<> *alreadyAddedModules = nullptr,
const SourceManager *sourceManager = nullptr, const SourceManager *sourceManager = nullptr,
SourceLoc sourceLocation = SourceLoc()); SourceLoc sourceLocation = SourceLoc());

View File

@@ -67,6 +67,9 @@ using IsExportedImport = BCFixed<1>;
using LineNumberField = BCFixed<32>; using LineNumberField = BCFixed<32>;
using ColumnNumberField = BCFixed<32>; using ColumnNumberField = BCFixed<32>;
/// Access level of an import
using AccessLevelField = BCFixed<8>;
/// Arrays of various identifiers, distinguished for readability /// Arrays of various identifiers, distinguished for readability
using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>; using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>;
using ModuleIDArryField = llvm::BCArray<IdentifierIDField>; using ModuleIDArryField = llvm::BCArray<IdentifierIDField>;
@@ -192,7 +195,8 @@ using ImportStatementLayout =
LineNumberField, // lineNumber LineNumberField, // lineNumber
ColumnNumberField, // columnNumber ColumnNumberField, // columnNumber
IsOptionalImport, // isOptional IsOptionalImport, // isOptional
IsExportedImport // isExported IsExportedImport, // isExported
AccessLevelField // accessLevel
>; >;
using ImportStatementArrayLayout = using ImportStatementArrayLayout =
BCRecordLayout<IMPORT_STATEMENT_ARRAY_NODE, IdentifierIDArryField>; BCRecordLayout<IMPORT_STATEMENT_ARRAY_NODE, IdentifierIDArryField>;

View File

@@ -170,8 +170,7 @@ protected:
bool isTestableImport, bool isCandidateForTextualModule); bool isTestableImport, bool isCandidateForTextualModule);
struct BinaryModuleImports { struct BinaryModuleImports {
llvm::StringSet<> moduleImports; std::vector<ScannerImportStatementInfo> moduleImports;
llvm::StringSet<> exportedModules;
std::string headerImport; std::string headerImport;
}; };

View File

@@ -116,14 +116,34 @@ bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const {
} }
void ModuleDependencyInfo::addOptionalModuleImport( void ModuleDependencyInfo::addOptionalModuleImport(
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules) { StringRef module, bool isExported, AccessLevel accessLevel,
if (!alreadyAddedModules || alreadyAddedModules->insert(module).second) llvm::StringSet<> *alreadyAddedModules) {
storage->optionalModuleImports.push_back({module.str(), isExported});
if (alreadyAddedModules && alreadyAddedModules->contains(module)) {
// Find a prior import of this module and add import location
// and adjust whether or not this module is ever imported as exported
// as well as the access level
for (auto &existingImport : storage->optionalModuleImports) {
if (existingImport.importIdentifier == module) {
existingImport.isExported |= isExported;
existingImport.accessLevel = std::max(existingImport.accessLevel,
accessLevel);
break;
}
}
} else {
if (alreadyAddedModules)
alreadyAddedModules->insert(module);
storage->optionalModuleImports.push_back(
{module.str(), isExported, accessLevel});
}
} }
void ModuleDependencyInfo::addModuleImport( void ModuleDependencyInfo::addModuleImport(
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules, StringRef module, bool isExported, AccessLevel accessLevel,
const SourceManager *sourceManager, SourceLoc sourceLocation) { llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
SourceLoc sourceLocation) {
auto scannerImportLocToDiagnosticLocInfo = auto scannerImportLocToDiagnosticLocInfo =
[&sourceManager](SourceLoc sourceLocation) { [&sourceManager](SourceLoc sourceLocation) {
auto lineAndColumnNumbers = auto lineAndColumnNumbers =
@@ -138,6 +158,7 @@ void ModuleDependencyInfo::addModuleImport(
if (alreadyAddedModules && alreadyAddedModules->contains(module)) { if (alreadyAddedModules && alreadyAddedModules->contains(module)) {
// Find a prior import of this module and add import location // Find a prior import of this module and add import location
// and adjust whether or not this module is ever imported as exported // and adjust whether or not this module is ever imported as exported
// as well as the access level
for (auto &existingImport : storage->moduleImports) { for (auto &existingImport : storage->moduleImports) {
if (existingImport.importIdentifier == module) { if (existingImport.importIdentifier == module) {
if (validSourceLocation) { if (validSourceLocation) {
@@ -145,6 +166,8 @@ void ModuleDependencyInfo::addModuleImport(
scannerImportLocToDiagnosticLocInfo(sourceLocation)); scannerImportLocToDiagnosticLocInfo(sourceLocation));
} }
existingImport.isExported |= isExported; existingImport.isExported |= isExported;
existingImport.accessLevel = std::max(existingImport.accessLevel,
accessLevel);
break; break;
} }
} }
@@ -154,16 +177,18 @@ void ModuleDependencyInfo::addModuleImport(
if (validSourceLocation) if (validSourceLocation)
storage->moduleImports.push_back(ScannerImportStatementInfo( storage->moduleImports.push_back(ScannerImportStatementInfo(
module.str(), isExported, scannerImportLocToDiagnosticLocInfo(sourceLocation))); module.str(), isExported, accessLevel,
scannerImportLocToDiagnosticLocInfo(sourceLocation)));
else else
storage->moduleImports.push_back( storage->moduleImports.push_back(
ScannerImportStatementInfo(module.str(), isExported)); ScannerImportStatementInfo(module.str(), isExported, accessLevel));
} }
} }
void ModuleDependencyInfo::addModuleImport( void ModuleDependencyInfo::addModuleImport(
ImportPath::Module module, bool isExported, llvm::StringSet<> *alreadyAddedModules, ImportPath::Module module, bool isExported, AccessLevel accessLevel,
const SourceManager *sourceManager, SourceLoc sourceLocation) { llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
SourceLoc sourceLocation) {
std::string ImportedModuleName = module.front().Item.str().str(); std::string ImportedModuleName = module.front().Item.str().str();
auto submodulePath = module.getSubmodulePath(); auto submodulePath = module.getSubmodulePath();
if (submodulePath.size() > 0 && !submodulePath[0].Item.empty()) { if (submodulePath.size() > 0 && !submodulePath[0].Item.empty()) {
@@ -172,11 +197,12 @@ void ModuleDependencyInfo::addModuleImport(
// module named "Foo_Private". ClangImporter has special support for this. // module named "Foo_Private". ClangImporter has special support for this.
if (submoduleComponent.Item.str() == "Private") if (submoduleComponent.Item.str() == "Private")
addOptionalModuleImport(ImportedModuleName + "_Private", addOptionalModuleImport(ImportedModuleName + "_Private",
isExported, accessLevel,
alreadyAddedModules); alreadyAddedModules);
} }
addModuleImport(ImportedModuleName, isExported, alreadyAddedModules, addModuleImport(ImportedModuleName, isExported, accessLevel,
sourceManager, sourceLocation); alreadyAddedModules, sourceManager, sourceLocation);
} }
void ModuleDependencyInfo::addModuleImports( void ModuleDependencyInfo::addModuleImports(
@@ -205,6 +231,7 @@ void ModuleDependencyInfo::addModuleImports(
continue; continue;
addModuleImport(realPath, importDecl->isExported(), addModuleImport(realPath, importDecl->isExported(),
importDecl->getAccessLevel(),
&alreadyAddedModules, sourceManager, &alreadyAddedModules, sourceManager,
importDecl->getLoc()); importDecl->getLoc());

View File

@@ -191,7 +191,8 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
// FIXME: This assumes, conservatively, that all Clang module imports // FIXME: This assumes, conservatively, that all Clang module imports
// are exported. We need to fix this once the clang scanner gains the appropriate // are exported. We need to fix this once the clang scanner gains the appropriate
// API to query this. // API to query this.
dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true, &alreadyAddedModules); dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true,
AccessLevel::Public, &alreadyAddedModules);
// It is safe to assume that all dependencies of a Clang module are Clang modules. // It is safe to assume that all dependencies of a Clang module are Clang modules.
directDependencyIDs.push_back({moduleName.ModuleName, ModuleDependencyKind::Clang}); directDependencyIDs.push_back({moduleName.ModuleName, ModuleDependencyKind::Clang});
} }

View File

@@ -415,9 +415,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
unsigned importIdentifierID, bufferIdentifierID; unsigned importIdentifierID, bufferIdentifierID;
unsigned lineNumber, columnNumber; unsigned lineNumber, columnNumber;
bool isOptional, isExported; bool isOptional, isExported;
uint8_t rawAccessLevel;
ImportStatementLayout::readRecord(Scratch, importIdentifierID, ImportStatementLayout::readRecord(Scratch, importIdentifierID,
bufferIdentifierID, lineNumber, bufferIdentifierID, lineNumber,
columnNumber, isOptional, isExported); columnNumber, isOptional, isExported,
rawAccessLevel);
auto importIdentifier = getIdentifier(importIdentifierID); auto importIdentifier = getIdentifier(importIdentifierID);
if (!importIdentifier) if (!importIdentifier)
llvm::report_fatal_error("Bad import statement info: no import name"); llvm::report_fatal_error("Bad import statement info: no import name");
@@ -428,10 +430,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
"Bad import statement info: no buffer identifier"); "Bad import statement info: no buffer identifier");
if (bufferIdentifier->empty()) if (bufferIdentifier->empty())
ImportStatements.push_back(ScannerImportStatementInfo( ImportStatements.push_back(ScannerImportStatementInfo(
*importIdentifier, isExported)); *importIdentifier, isExported, AccessLevel(rawAccessLevel)));
else else
ImportStatements.push_back(ScannerImportStatementInfo( ImportStatements.push_back(ScannerImportStatementInfo(
*importIdentifier, isExported, *importIdentifier, isExported, AccessLevel(rawAccessLevel),
ScannerImportStatementInfo::ImportDiagnosticLocationInfo( ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
*bufferIdentifier, lineNumber, columnNumber))); *bufferIdentifier, lineNumber, columnNumber)));
break; break;
@@ -1527,7 +1529,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
ImportStatementLayout::emitRecord( ImportStatementLayout::emitRecord(
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code], Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
getIdentifier(importInfo.importIdentifier), getIdentifier(importInfo.importIdentifier),
0, 0, 0, isOptional, importInfo.isExported); 0, 0, 0, isOptional, importInfo.isExported,
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
count++; count++;
} else { } else {
for (auto &importLoc : importInfo.importLocations) { for (auto &importLoc : importInfo.importLocations) {
@@ -1535,7 +1538,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code], Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
getIdentifier(importInfo.importIdentifier), getIdentifier(importInfo.importIdentifier),
getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber, getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber,
importLoc.columnNumber, isOptional, importInfo.isExported); importLoc.columnNumber, isOptional, importInfo.isExported,
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
count++; count++;
} }
} }

View File

@@ -544,6 +544,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
case ImplicitStdlibKind::Stdlib: case ImplicitStdlibKind::Stdlib:
mainDependencies.addModuleImport("Swift", /* isExported */false, mainDependencies.addModuleImport("Swift", /* isExported */false,
AccessLevel::Public,
&alreadyAddedModules); &alreadyAddedModules);
break; break;
} }
@@ -552,6 +553,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
for (const auto &import : importInfo.AdditionalUnloadedImports) { for (const auto &import : importInfo.AdditionalUnloadedImports) {
mainDependencies.addModuleImport(import.module.getModulePath(), mainDependencies.addModuleImport(import.module.getModulePath(),
import.options.contains(ImportFlags::Exported), import.options.contains(ImportFlags::Exported),
import.accessLevel,
&alreadyAddedModules, &alreadyAddedModules,
&ScanASTContext.SourceMgr); &ScanASTContext.SourceMgr);
} }
@@ -561,6 +563,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
mainDependencies.addModuleImport( mainDependencies.addModuleImport(
import.module.importedModule->getNameStr(), import.module.importedModule->getNameStr(),
import.options.contains(ImportFlags::Exported), import.options.contains(ImportFlags::Exported),
import.accessLevel,
&alreadyAddedModules); &alreadyAddedModules);
} }
@@ -574,6 +577,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
if (importInfo.ShouldImportUnderlyingModule) { if (importInfo.ShouldImportUnderlyingModule) {
mainDependencies.addModuleImport(mainModule->getName().str(), mainDependencies.addModuleImport(mainModule->getName().str(),
/* isExported */ true, /* isExported */ true,
AccessLevel::Public,
&alreadyAddedModules); &alreadyAddedModules);
} }
@@ -584,6 +588,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) { ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) {
mainDependencies.addModuleImport(tbdSymbolModule, mainDependencies.addModuleImport(tbdSymbolModule,
/* isExported */ false, /* isExported */ false,
AccessLevel::Public,
&alreadyAddedModules); &alreadyAddedModules);
} }
} }
@@ -948,7 +953,8 @@ void ModuleDependencyScanner::resolveAllClangModuleDependencies(
if (importInfo.importIdentifier == if (importInfo.importIdentifier ==
ScanASTContext.Id_CxxStdlib.str()) { ScanASTContext.Id_CxxStdlib.str()) {
auto canonicalImportInfo = ScannerImportStatementInfo( auto canonicalImportInfo = ScannerImportStatementInfo(
"std", importInfo.isExported, importInfo.importLocations); "std", importInfo.isExported, importInfo.accessLevel,
importInfo.importLocations);
unresolvedImports.push_back(canonicalImportInfo); unresolvedImports.push_back(canonicalImportInfo);
unresolvedImportIdentifiers.insert( unresolvedImportIdentifiers.insert(
canonicalImportInfo.importIdentifier); canonicalImportInfo.importIdentifier);
@@ -1475,7 +1481,9 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
std::for_each(newOverlays.begin(), newOverlays.end(), std::for_each(newOverlays.begin(), newOverlays.end(),
[&](Identifier modName) { [&](Identifier modName) {
dummyMainDependencies.addModuleImport(modName.str(), dummyMainDependencies.addModuleImport(modName.str(),
/* isExported */ false); /* isExported */ false,
// TODO: What is the right access level for a cross-import overlay?
AccessLevel::Public);
}); });
// Record the dummy main module's direct dependencies. The dummy main module // Record the dummy main module's direct dependencies. The dummy main module

View File

@@ -242,6 +242,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
for (auto import : imInfo.AdditionalUnloadedImports) { for (auto import : imInfo.AdditionalUnloadedImports) {
Result->addModuleImport(import.module.getModulePath(), Result->addModuleImport(import.module.getModulePath(),
import.options.contains(ImportFlags::Exported), import.options.contains(ImportFlags::Exported),
import.accessLevel,
&alreadyAddedModules, &Ctx.SourceMgr); &alreadyAddedModules, &Ctx.SourceMgr);
} }
@@ -270,6 +271,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
if (!alreadyAddedModules.contains(requiredImport.importIdentifier)) if (!alreadyAddedModules.contains(requiredImport.importIdentifier))
Result->addModuleImport(requiredImport.importIdentifier, Result->addModuleImport(requiredImport.importIdentifier,
requiredImport.isExported, requiredImport.isExported,
requiredImport.accessLevel,
&alreadyAddedModules); &alreadyAddedModules);
} }
} }

View File

@@ -373,7 +373,8 @@ SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule(
if (dotPos != std::string::npos) if (dotPos != std::string::npos)
moduleName = moduleName.slice(0, dotPos); moduleName = moduleName.slice(0, dotPos);
importedModuleNames.push_back({moduleName.str(), dependency.isExported()}); importedModuleNames.push_back({moduleName.str(), dependency.isExported(),
dependency.isInternalOrBelow() ? AccessLevel::Internal : AccessLevel::Public});
} }
return importedModuleNames; return importedModuleNames;
@@ -478,8 +479,7 @@ SerializedModuleLoaderBase::getImportsOfModule(
const ModuleFileSharedCore &loadedModuleFile, const ModuleFileSharedCore &loadedModuleFile,
ModuleLoadingBehavior transitiveBehavior, StringRef packageName, ModuleLoadingBehavior transitiveBehavior, StringRef packageName,
bool isTestableImport) { bool isTestableImport) {
llvm::StringSet<> importedModuleNames; std::vector<ScannerImportStatementInfo> moduleImports;
llvm::StringSet<> importedExportedModuleNames;
std::string importedHeader = ""; std::string importedHeader = "";
for (const auto &dependency : loadedModuleFile.getDependencies()) { for (const auto &dependency : loadedModuleFile.getDependencies()) {
if (dependency.isHeader()) { if (dependency.isHeader()) {
@@ -513,13 +513,13 @@ SerializedModuleLoaderBase::getImportsOfModule(
if (moduleName == Ctx.Id_CxxStdlib.str()) if (moduleName == Ctx.Id_CxxStdlib.str())
moduleName = "std"; moduleName = "std";
importedModuleNames.insert(moduleName); moduleImports.push_back(ScannerImportStatementInfo(
if (dependency.isExported()) moduleName.str(), dependency.isExported(),
importedExportedModuleNames.insert(moduleName); dependency.isInternalOrBelow() ? AccessLevel::Internal
: AccessLevel::Public));
} }
return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames, return SerializedModuleLoaderBase::BinaryModuleImports{moduleImports,
importedExportedModuleNames,
importedHeader}; importedHeader};
} }
@@ -601,51 +601,33 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework,
getImportsOfModule(*loadedModuleFile, ModuleLoadingBehavior::Optional, getImportsOfModule(*loadedModuleFile, ModuleLoadingBehavior::Optional,
Ctx.LangOpts.PackageName, isTestableImport); Ctx.LangOpts.PackageName, isTestableImport);
auto importedModuleSet = binaryModuleImports->moduleImports;
std::vector<ScannerImportStatementInfo> moduleImports;
moduleImports.reserve(importedModuleSet.size());
llvm::transform(importedModuleSet.keys(), std::back_inserter(moduleImports),
[&binaryModuleImports](llvm::StringRef N) {
return ScannerImportStatementInfo(
N.str(),
binaryModuleImports->exportedModules.contains(N));
});
auto importedHeader = binaryModuleImports->headerImport;
auto &importedOptionalModuleSet = binaryModuleOptionalImports->moduleImports;
auto &importedExportedOptionalModuleSet =
binaryModuleOptionalImports->exportedModules;
std::vector<ScannerImportStatementInfo> optionalModuleImports;
for (const auto optionalImportedModule : importedOptionalModuleSet.keys())
if (!importedModuleSet.contains(optionalImportedModule))
optionalModuleImports.push_back(
{optionalImportedModule.str(),
importedExportedOptionalModuleSet.contains(optionalImportedModule)});
std::vector<LinkLibrary> linkLibraries; std::vector<LinkLibrary> linkLibraries;
{ {
linkLibraries.reserve(loadedModuleFile->getLinkLibraries().size()); linkLibraries.reserve(loadedModuleFile->getLinkLibraries().size());
llvm::copy(loadedModuleFile->getLinkLibraries(), llvm::copy(loadedModuleFile->getLinkLibraries(),
std::back_inserter(linkLibraries)); std::back_inserter(linkLibraries));
if (loadedModuleFile->isFramework()) if (loadedModuleFile->isFramework())
linkLibraries.emplace_back( linkLibraries.emplace_back(loadedModuleFile->getName(),
loadedModuleFile->getName(), LibraryKind::Framework, LibraryKind::Framework,
loadedModuleFile->isStaticLibrary()); loadedModuleFile->isStaticLibrary());
} }
// Attempt to resolve the module's defining .swiftinterface path // Attempt to resolve the module's defining .swiftinterface path
std::string definingModulePath = std::string definingModulePath =
loadedModuleFile->resolveModuleDefiningFilePath(Ctx.SearchPathOpts.getSDKPath()); loadedModuleFile->resolveModuleDefiningFilePath(
Ctx.SearchPathOpts.getSDKPath());
std::string userModuleVer = loadedModuleFile->getUserModuleVersion().getAsString(); std::string userModuleVer =
loadedModuleFile->getUserModuleVersion().getAsString();
std::vector<serialization::SearchPath> serializedSearchPaths; std::vector<serialization::SearchPath> serializedSearchPaths;
llvm::copy(loadedModuleFile->getSearchPaths(), std::back_inserter(serializedSearchPaths)); llvm::copy(loadedModuleFile->getSearchPaths(), std::back_inserter(serializedSearchPaths));
// Map the set of dependencies over to the "module dependencies". // Map the set of dependencies over to the "module dependencies".
auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule( auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule(
modulePath.str(), moduleDocPath, sourceInfoPath, moduleImports, modulePath.str(), moduleDocPath, sourceInfoPath,
optionalModuleImports, linkLibraries, serializedSearchPaths, binaryModuleImports->moduleImports,
importedHeader, definingModulePath, isFramework, binaryModuleOptionalImports->moduleImports, linkLibraries, serializedSearchPaths,
binaryModuleImports->headerImport, definingModulePath, isFramework,
loadedModuleFile->isStaticLibrary(), loadedModuleFile->isStaticLibrary(),
/*module-cache-key*/ "", userModuleVer); /*module-cache-key*/ "", userModuleVer);