mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Dependency Scanning] Keep track of whether a given Swift 'import' statement is '@_exported'
This commit is contained in:
@@ -154,12 +154,14 @@ struct ScannerImportStatementInfo {
|
||||
uint32_t columnNumber;
|
||||
};
|
||||
|
||||
ScannerImportStatementInfo(std::string importIdentifier)
|
||||
: importLocations(), importIdentifier(importIdentifier) {}
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported)
|
||||
: importLocations(), importIdentifier(importIdentifier),
|
||||
isExported(isExported) {}
|
||||
|
||||
ScannerImportStatementInfo(std::string importIdentifier,
|
||||
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
|
||||
ImportDiagnosticLocationInfo location)
|
||||
: importLocations({location}), importIdentifier(importIdentifier) {}
|
||||
: importLocations({location}), importIdentifier(importIdentifier),
|
||||
isExported(isExported) {}
|
||||
|
||||
void addImportLocation(ImportDiagnosticLocationInfo location) {
|
||||
importLocations.push_back(location);
|
||||
@@ -169,6 +171,8 @@ struct ScannerImportStatementInfo {
|
||||
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
|
||||
/// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar'
|
||||
std::string importIdentifier;
|
||||
/// Is this an @_exported import
|
||||
bool isExported;
|
||||
};
|
||||
|
||||
/// Base class for the variant storage of ModuleDependencyInfo.
|
||||
@@ -927,7 +931,7 @@ public:
|
||||
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void
|
||||
addOptionalModuleImport(StringRef module,
|
||||
addOptionalModuleImport(StringRef module, bool isExported,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr);
|
||||
|
||||
/// Add all of the module imports in the given source
|
||||
@@ -937,13 +941,13 @@ public:
|
||||
const SourceManager *sourceManager);
|
||||
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void addModuleImport(ImportPath::Module module,
|
||||
void addModuleImport(ImportPath::Module module, bool isExported,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr,
|
||||
const SourceManager *sourceManager = nullptr,
|
||||
SourceLoc sourceLocation = SourceLoc());
|
||||
|
||||
/// Add a dependency on the given module, if it was not already in the set.
|
||||
void addModuleImport(StringRef module,
|
||||
void addModuleImport(StringRef module, bool isExported,
|
||||
llvm::StringSet<> *alreadyAddedModules = nullptr,
|
||||
const SourceManager *sourceManager = nullptr,
|
||||
SourceLoc sourceLocation = SourceLoc());
|
||||
|
||||
@@ -60,6 +60,8 @@ using IsStaticField = BCFixed<1>;
|
||||
using IsForceLoadField = BCFixed<1>;
|
||||
/// A bit taht indicates whether or not an import statement is optional
|
||||
using IsOptionalImport = BCFixed<1>;
|
||||
/// A bit taht indicates whether or not an import statement is @_exported
|
||||
using IsExportedImport = BCFixed<1>;
|
||||
|
||||
/// Source location fields
|
||||
using LineNumberField = BCFixed<32>;
|
||||
@@ -176,7 +178,8 @@ using ImportStatementLayout =
|
||||
IdentifierIDField, // bufferIdentifier
|
||||
LineNumberField, // lineNumber
|
||||
ColumnNumberField, // columnNumber
|
||||
IsOptionalImport // isOptional
|
||||
IsOptionalImport, // isOptional
|
||||
IsExportedImport // isExported
|
||||
>;
|
||||
using ImportStatementArrayLayout =
|
||||
BCRecordLayout<IMPORT_STATEMENT_ARRAY_NODE, IdentifierIDArryField>;
|
||||
|
||||
@@ -171,6 +171,7 @@ protected:
|
||||
|
||||
struct BinaryModuleImports {
|
||||
llvm::StringSet<> moduleImports;
|
||||
llvm::StringSet<> exportedModules;
|
||||
std::string headerImport;
|
||||
};
|
||||
|
||||
@@ -185,7 +186,7 @@ protected:
|
||||
|
||||
/// If the module has a package name matching the one
|
||||
/// specified, return a set of package-only imports for this module.
|
||||
static llvm::ErrorOr<llvm::StringSet<>>
|
||||
static llvm::ErrorOr<std::vector<ScannerImportStatementInfo>>
|
||||
getMatchingPackageOnlyImportsOfModule(Twine modulePath,
|
||||
bool isFramework,
|
||||
bool isRequiredOSSAModules,
|
||||
|
||||
@@ -117,16 +117,16 @@ bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const {
|
||||
}
|
||||
|
||||
void ModuleDependencyInfo::addOptionalModuleImport(
|
||||
StringRef module, llvm::StringSet<> *alreadyAddedModules) {
|
||||
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules) {
|
||||
if (!alreadyAddedModules || alreadyAddedModules->insert(module).second)
|
||||
storage->optionalModuleImports.push_back(module.str());
|
||||
storage->optionalModuleImports.push_back({module.str(), isExported});
|
||||
}
|
||||
|
||||
void ModuleDependencyInfo::addModuleImport(
|
||||
StringRef module, llvm::StringSet<> *alreadyAddedModules,
|
||||
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
|
||||
const SourceManager *sourceManager, SourceLoc sourceLocation) {
|
||||
auto scannerImportLocToDiagnosticLocInfo =
|
||||
[&sourceManager](SourceLoc sourceLocation) {
|
||||
[&sourceManager, isExported](SourceLoc sourceLocation) {
|
||||
auto lineAndColumnNumbers =
|
||||
sourceManager->getLineAndColumnInBuffer(sourceLocation);
|
||||
return ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
|
||||
@@ -137,14 +137,16 @@ void ModuleDependencyInfo::addModuleImport(
|
||||
sourceManager->isOwning(sourceLocation);
|
||||
|
||||
if (alreadyAddedModules && alreadyAddedModules->contains(module)) {
|
||||
if (validSourceLocation) {
|
||||
// Find a prior import of this module and add import location
|
||||
// and adjust whether or not this module is ever imported as exported
|
||||
for (auto &existingImport : storage->moduleImports) {
|
||||
if (existingImport.importIdentifier == module) {
|
||||
if (validSourceLocation) {
|
||||
existingImport.addImportLocation(
|
||||
scannerImportLocToDiagnosticLocInfo(sourceLocation));
|
||||
break;
|
||||
}
|
||||
existingImport.isExported |= isExported;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -153,15 +155,15 @@ void ModuleDependencyInfo::addModuleImport(
|
||||
|
||||
if (validSourceLocation)
|
||||
storage->moduleImports.push_back(ScannerImportStatementInfo(
|
||||
module.str(), scannerImportLocToDiagnosticLocInfo(sourceLocation)));
|
||||
module.str(), isExported, scannerImportLocToDiagnosticLocInfo(sourceLocation)));
|
||||
else
|
||||
storage->moduleImports.push_back(
|
||||
ScannerImportStatementInfo(module.str()));
|
||||
ScannerImportStatementInfo(module.str(), isExported));
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleDependencyInfo::addModuleImport(
|
||||
ImportPath::Module module, llvm::StringSet<> *alreadyAddedModules,
|
||||
ImportPath::Module module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
|
||||
const SourceManager *sourceManager, SourceLoc sourceLocation) {
|
||||
std::string ImportedModuleName = module.front().Item.str().str();
|
||||
auto submodulePath = module.getSubmodulePath();
|
||||
@@ -174,7 +176,7 @@ void ModuleDependencyInfo::addModuleImport(
|
||||
alreadyAddedModules);
|
||||
}
|
||||
|
||||
addModuleImport(ImportedModuleName, alreadyAddedModules,
|
||||
addModuleImport(ImportedModuleName, isExported, alreadyAddedModules,
|
||||
sourceManager, sourceLocation);
|
||||
}
|
||||
|
||||
@@ -203,7 +205,8 @@ void ModuleDependencyInfo::addModuleImports(
|
||||
importDecl->isExported()))
|
||||
continue;
|
||||
|
||||
addModuleImport(realPath, &alreadyAddedModules, sourceManager,
|
||||
addModuleImport(realPath, importDecl->isExported(),
|
||||
&alreadyAddedModules, sourceManager,
|
||||
importDecl->getLoc());
|
||||
|
||||
// Additionally, keep track of which dependencies of a Source
|
||||
|
||||
@@ -240,10 +240,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
|
||||
¯oDependencies](ModuleDependencyInfo &moduleDep) {
|
||||
// Add imports of this module
|
||||
for (const auto &moduleName : currentModuleImports)
|
||||
moduleDep.addModuleImport(moduleName.importIdentifier);
|
||||
moduleDep.addModuleImport(moduleName.importIdentifier,
|
||||
moduleName.isExported);
|
||||
// Add optional imports of this module
|
||||
for (const auto &moduleName : currentOptionalModuleImports)
|
||||
moduleDep.addOptionalModuleImport(moduleName.importIdentifier);
|
||||
moduleDep.addOptionalModuleImport(moduleName.importIdentifier,
|
||||
moduleName.isExported);
|
||||
|
||||
// Add qualified dependencies of this module
|
||||
moduleDep.setImportedClangDependencies(importedClangDependenciesIDs);
|
||||
@@ -408,10 +410,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
|
||||
case IMPORT_STATEMENT_NODE: {
|
||||
unsigned importIdentifierID, bufferIdentifierID;
|
||||
unsigned lineNumber, columnNumber;
|
||||
bool isOptional;
|
||||
bool isOptional, isExported;
|
||||
ImportStatementLayout::readRecord(Scratch, importIdentifierID,
|
||||
bufferIdentifierID, lineNumber,
|
||||
columnNumber, isOptional);
|
||||
columnNumber, isOptional, isExported);
|
||||
auto importIdentifier = getIdentifier(importIdentifierID);
|
||||
if (!importIdentifier)
|
||||
llvm::report_fatal_error("Bad import statement info: no import name");
|
||||
@@ -421,7 +423,7 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
|
||||
llvm::report_fatal_error(
|
||||
"Bad import statement info: no buffer identifier");
|
||||
ImportStatements.push_back(ScannerImportStatementInfo(
|
||||
importIdentifier.value(),
|
||||
importIdentifier.value(), isExported,
|
||||
ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
|
||||
bufferIdentifier.value(), lineNumber, columnNumber)));
|
||||
break;
|
||||
@@ -1443,7 +1445,7 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
|
||||
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
|
||||
getIdentifier(importInfo.importIdentifier),
|
||||
getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber,
|
||||
importLoc.columnNumber, isOptional);
|
||||
importLoc.columnNumber, isOptional, importInfo.isExported);
|
||||
count++;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -412,6 +412,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
|
||||
// Add any implicit module names.
|
||||
for (const auto &import : importInfo.AdditionalUnloadedImports) {
|
||||
mainDependencies.addModuleImport(import.module.getModulePath(),
|
||||
import.options.contains(ImportFlags::Exported),
|
||||
&alreadyAddedModules,
|
||||
&ScanASTContext.SourceMgr);
|
||||
}
|
||||
@@ -420,6 +421,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
|
||||
for (const auto &import : importInfo.AdditionalImports) {
|
||||
mainDependencies.addModuleImport(
|
||||
import.module.importedModule->getNameStr(),
|
||||
import.options.contains(ImportFlags::Exported),
|
||||
&alreadyAddedModules);
|
||||
}
|
||||
|
||||
@@ -432,6 +434,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
|
||||
// add a dependency with the same name to trigger the search.
|
||||
if (importInfo.ShouldImportUnderlyingModule) {
|
||||
mainDependencies.addModuleImport(mainModule->getName().str(),
|
||||
/* isExported */ true,
|
||||
&alreadyAddedModules);
|
||||
}
|
||||
|
||||
@@ -441,6 +444,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
|
||||
for (const auto &tbdSymbolModule :
|
||||
ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) {
|
||||
mainDependencies.addModuleImport(tbdSymbolModule,
|
||||
/* isExported */ false,
|
||||
&alreadyAddedModules);
|
||||
}
|
||||
}
|
||||
@@ -1354,7 +1358,8 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
|
||||
ModuleDependencyInfo::forSwiftSourceModule();
|
||||
std::for_each(newOverlays.begin(), newOverlays.end(),
|
||||
[&](Identifier modName) {
|
||||
dummyMainDependencies.addModuleImport(modName.str());
|
||||
dummyMainDependencies.addModuleImport(modName.str(),
|
||||
/* isExported */ false);
|
||||
});
|
||||
|
||||
// Record the dummy main module's direct dependencies. The dummy main module
|
||||
|
||||
@@ -276,6 +276,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
|
||||
auto &imInfo = mainMod->getImplicitImportInfo();
|
||||
for (auto import : imInfo.AdditionalUnloadedImports) {
|
||||
Result->addModuleImport(import.module.getModulePath(),
|
||||
import.options.contains(ImportFlags::Exported),
|
||||
&alreadyAddedModules, &Ctx.SourceMgr);
|
||||
}
|
||||
|
||||
@@ -301,8 +302,9 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
|
||||
return adjacentBinaryModulePackageOnlyImports.getError();
|
||||
|
||||
for (const auto &requiredImport : *adjacentBinaryModulePackageOnlyImports)
|
||||
if (!alreadyAddedModules.contains(requiredImport.getKey()))
|
||||
Result->addModuleImport(requiredImport.getKey(),
|
||||
if (!alreadyAddedModules.contains(requiredImport.importIdentifier))
|
||||
Result->addModuleImport(requiredImport.importIdentifier,
|
||||
requiredImport.isExported,
|
||||
&alreadyAddedModules);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ std::optional<std::string> SerializedModuleLoaderBase::invalidModuleReason(seria
|
||||
llvm_unreachable("bad status");
|
||||
}
|
||||
|
||||
llvm::ErrorOr<llvm::StringSet<>>
|
||||
llvm::ErrorOr<std::vector<ScannerImportStatementInfo>>
|
||||
SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule(
|
||||
Twine modulePath, bool isFramework, bool isRequiredOSSAModules,
|
||||
StringRef SDKName, StringRef packageName, llvm::vfs::FileSystem *fileSystem,
|
||||
@@ -353,7 +353,7 @@ SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule(
|
||||
if (!moduleBuf)
|
||||
return moduleBuf.getError();
|
||||
|
||||
llvm::StringSet<> importedModuleNames;
|
||||
std::vector<ScannerImportStatementInfo> importedModuleNames;
|
||||
// Load the module file without validation.
|
||||
std::shared_ptr<const ModuleFileSharedCore> loadedModuleFile;
|
||||
serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load(
|
||||
@@ -376,7 +376,7 @@ SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule(
|
||||
if (dotPos != std::string::npos)
|
||||
moduleName = moduleName.slice(0, dotPos);
|
||||
|
||||
importedModuleNames.insert(moduleName);
|
||||
importedModuleNames.push_back({moduleName.str(), dependency.isExported()});
|
||||
}
|
||||
|
||||
return importedModuleNames;
|
||||
@@ -482,6 +482,7 @@ SerializedModuleLoaderBase::getImportsOfModule(
|
||||
ModuleLoadingBehavior transitiveBehavior, StringRef packageName,
|
||||
bool isTestableImport) {
|
||||
llvm::StringSet<> importedModuleNames;
|
||||
llvm::StringSet<> importedExportedModuleNames;
|
||||
std::string importedHeader = "";
|
||||
for (const auto &dependency : loadedModuleFile.getDependencies()) {
|
||||
if (dependency.isHeader()) {
|
||||
@@ -516,9 +517,12 @@ SerializedModuleLoaderBase::getImportsOfModule(
|
||||
moduleName = "std";
|
||||
|
||||
importedModuleNames.insert(moduleName);
|
||||
if (dependency.isExported())
|
||||
importedExportedModuleNames.insert(moduleName);
|
||||
}
|
||||
|
||||
return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames,
|
||||
importedExportedModuleNames,
|
||||
importedHeader};
|
||||
}
|
||||
|
||||
@@ -603,17 +607,23 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework,
|
||||
auto importedModuleSet = binaryModuleImports->moduleImports;
|
||||
std::vector<ScannerImportStatementInfo> moduleImports;
|
||||
moduleImports.reserve(importedModuleSet.size());
|
||||
llvm::transform(
|
||||
importedModuleSet.keys(), std::back_inserter(moduleImports),
|
||||
[](llvm::StringRef N) { return ScannerImportStatementInfo(N.str()); });
|
||||
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(
|
||||
ScannerImportStatementInfo(optionalImportedModule.str()));
|
||||
{optionalImportedModule.str(),
|
||||
importedExportedOptionalModuleSet.contains(optionalImportedModule)});
|
||||
|
||||
std::vector<LinkLibrary> linkLibraries;
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user