[Sema] Report public imports of private modules

Intro the concept of library access or distribution level to identify
layers of libraries and report public imports of private libraries from
public ones.

rdar://62934005
This commit is contained in:
Alexis Laferrière
2021-03-12 09:32:03 -08:00
parent 58f03e8490
commit cf58bb7eb4
19 changed files with 207 additions and 0 deletions

View File

@@ -2246,6 +2246,49 @@ SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
return ctx.AllocateCopy(spiGroups.getArrayRef());
}
LibraryLevel ModuleDecl::getLibraryLevel() const {
return evaluateOrDefault(getASTContext().evaluator,
ModuleLibraryLevelRequest{this},
LibraryLevel::Other);
}
LibraryLevel
ModuleLibraryLevelRequest::evaluate(Evaluator &evaluator,
const ModuleDecl *module) const {
auto &ctx = module->getASTContext();
/// Is \p path from System/Library/PrivateFrameworks/?
auto fromPrivateFrameworks = [&](StringRef path) -> bool {
auto sep = llvm::sys::path::get_separator();
auto privateFrameworksPath = llvm::Twine(ctx.SearchPathOpts.SDKPath) +
sep + "System" + sep + "Library" + sep + "PrivateFrameworks" + sep;
return hasPrefix(path, privateFrameworksPath.str());
};
if (module->isNonSwiftModule()) {
if (auto *underlying = module->findUnderlyingClangModule()) {
// Imported clangmodules are SPI if they are defined by a private
// modulemap or from the PrivateFrameworks folder in the SDK.
bool moduleIsSPI = underlying->ModuleMapIsPrivate ||
(underlying->isPartOfFramework() &&
fromPrivateFrameworks(underlying->PresumedModuleMapFile));
return moduleIsSPI ? LibraryLevel::SPI : LibraryLevel::API;
}
return LibraryLevel::Other;
} else if (module->isMainModule()) {
// The current compilation target.
return ctx.LangOpts.LibraryLevel;
} else {
// Other Swift modules are SPI if they are from the PrivateFrameworks
// folder in the SDK.
auto modulePath = module->getModuleFilename();
return fromPrivateFrameworks(modulePath) ?
LibraryLevel::SPI : LibraryLevel::API;
}
}
bool SourceFile::shouldCrossImport() const {
return Kind != SourceFileKind::SIL && Kind != SourceFileKind::Interface &&
getASTContext().LangOpts.EnableCrossImportOverlays;