diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 2c08f79d520..628dca2a800 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -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 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()); diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index 4a38096a7e1..d1e4ce900b4 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -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; diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 072b2e009fd..f7a96e27d69 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -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> + static llvm::ErrorOr> getMatchingPackageOnlyImportsOfModule(Twine modulePath, bool isFramework, bool isRequiredOSSAModules, diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 27f8e5db315..49b55ccf24a 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -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 - for (auto &existingImport : storage->moduleImports) { - if (existingImport.importIdentifier == module) { + // 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; + scannerImportLocToDiagnosticLocInfo(sourceLocation)); } + 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 diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index b76ea8768ff..7dd4d09569e 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -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++; } }; diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 2e75a668fa2..0241a5a0e68 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -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 diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 8a34845ac3b..01c23df5980 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -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); } } diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index f01af126c6d..acda28350da 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -344,7 +344,7 @@ std::optional SerializedModuleLoaderBase::invalidModuleReason(seria llvm_unreachable("bad status"); } -llvm::ErrorOr> +llvm::ErrorOr> 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 importedModuleNames; // Load the module file without validation. std::shared_ptr 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 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 optionalModuleImports; for (const auto optionalImportedModule : importedOptionalModuleSet.keys()) if (!importedModuleSet.contains(optionalImportedModule)) optionalModuleImports.push_back( - ScannerImportStatementInfo(optionalImportedModule.str())); + {optionalImportedModule.str(), + importedExportedOptionalModuleSet.contains(optionalImportedModule)}); std::vector linkLibraries; {