Merge pull request #82779 from artemcm/62_DepScanImportAccessControl

[6.2 🍒][Dependency Scanning] Keep track of each imported module's access control
This commit is contained in:
Artem Chikin
2025-07-07 10:53:00 -07:00
committed by GitHub
20 changed files with 400 additions and 90 deletions

View File

@@ -25,7 +25,7 @@
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
#define SWIFTSCAN_VERSION_MAJOR 2
#define SWIFTSCAN_VERSION_MINOR 1
#define SWIFTSCAN_VERSION_MINOR 2
SWIFTSCAN_BEGIN_DECLS
@@ -49,6 +49,9 @@ typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t;
/// Opaque container to a link library info.
typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t;
/// Opaque container to an import info.
typedef struct swiftscan_import_info_s *swiftscan_import_info_t;
/// Opaque container to a macro dependency.
typedef struct swiftscan_macro_dependency_s *swiftscan_macro_dependency_t;
@@ -76,6 +79,18 @@ typedef struct {
size_t count;
} swiftscan_link_library_set_t;
/// Set of details about source imports
typedef struct {
swiftscan_import_info_t *imports;
size_t count;
} swiftscan_import_info_set_t;
/// Set of source location infos
typedef struct {
swiftscan_source_location_t *source_locations;
size_t count;
} swiftscan_source_location_set_t;
/// Set of macro dependency
typedef struct {
swiftscan_macro_dependency_t *macro_dependencies;
@@ -89,6 +104,15 @@ typedef enum {
SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3
} swiftscan_diagnostic_severity_t;
// Must maintain consistency with swift::AccessLevel
typedef enum {
SWIFTSCAN_ACCESS_LEVEL_PRIVATE = 0,
SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE = 1,
SWIFTSCAN_ACCESS_LEVEL_INTERNAL = 2,
SWIFTSCAN_ACCESS_LEVEL_PACKAGE = 3,
SWIFTSCAN_ACCESS_LEVEL_PUBLIC = 4
} swiftscan_access_level_t;
typedef struct {
swiftscan_diagnostic_info_t *diagnostics;
size_t count;
@@ -148,10 +172,23 @@ swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info);
SWIFTSCAN_PUBLIC swiftscan_link_library_set_t *
swiftscan_module_info_get_link_libraries(swiftscan_dependency_info_t info);
SWIFTSCAN_PUBLIC swiftscan_import_info_set_t *
swiftscan_module_info_get_imports(swiftscan_dependency_info_t info);
SWIFTSCAN_PUBLIC swiftscan_module_details_t
swiftscan_module_info_get_details(swiftscan_dependency_info_t info);
//=== Link Library Info Functions ------------------------------------===//
//=== Import Details Functions -------------------------------------------===//
SWIFTSCAN_PUBLIC swiftscan_source_location_set_t *
swiftscan_import_info_get_source_locations(swiftscan_import_info_t info);
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
swiftscan_import_info_get_identifier(swiftscan_import_info_t info);
SWIFTSCAN_PUBLIC swiftscan_access_level_t
swiftscan_import_info_get_access_level(swiftscan_import_info_t info);
//=== Link Library Info Functions ----------------------------------------===//
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
swiftscan_link_library_info_get_link_name(
swiftscan_link_library_info_t info);

View File

@@ -156,30 +156,35 @@ struct ScannerImportStatementInfo {
uint32_t columnNumber;
};
ScannerImportStatementInfo(std::string importIdentifier, bool isExported)
: importLocations(), importIdentifier(importIdentifier),
isExported(isExported) {}
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
AccessLevel accessLevel)
: importIdentifier(importIdentifier), importLocations(),
isExported(isExported), accessLevel(accessLevel) {}
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
AccessLevel accessLevel,
ImportDiagnosticLocationInfo location)
: importLocations({location}), importIdentifier(importIdentifier),
isExported(isExported) {}
: importIdentifier(importIdentifier), importLocations({location}),
isExported(isExported), accessLevel(accessLevel) {}
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
AccessLevel accessLevel,
SmallVector<ImportDiagnosticLocationInfo, 4> locations)
: importLocations(locations), importIdentifier(importIdentifier),
isExported(isExported) {}
: importIdentifier(importIdentifier), importLocations(locations),
isExported(isExported), accessLevel(accessLevel) {}
void addImportLocation(ImportDiagnosticLocationInfo 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'
std::string importIdentifier;
/// Buffer, line & column number of the import statement
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
/// Is this an @_exported import
bool isExported;
/// Access level of this dependency
AccessLevel accessLevel;
};
/// 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.
void
addOptionalModuleImport(StringRef module, bool isExported,
AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules = nullptr);
/// 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.
void addModuleImport(ImportPath::Module module, bool isExported,
AccessLevel accessLevel,
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, bool isExported,
AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules = nullptr,
const SourceManager *sourceManager = nullptr,
SourceLoc sourceLocation = SourceLoc());

View File

@@ -63,6 +63,9 @@ struct swiftscan_dependency_info_s {
/// The list of link libraries for this module.
swiftscan_link_library_set_t *link_libraries;
/// The list of source import infos.
swiftscan_import_info_set_t *imports;
/// Specific details of a particular kind of module.
swiftscan_module_details_t details;
};
@@ -74,10 +77,16 @@ struct swiftscan_link_library_info_s {
bool forceLoad;
};
struct swiftscan_import_info_s {
swiftscan_string_ref_t import_identifier;
swiftscan_source_location_set_t *source_locations;
swiftscan_access_level_t access_level;
};
struct swiftscan_macro_dependency_s {
swiftscan_string_ref_t moduleName;
swiftscan_string_ref_t libraryPath;
swiftscan_string_ref_t executablePath;
swiftscan_string_ref_t module_name;
swiftscan_string_ref_t library_path;
swiftscan_string_ref_t executable_path;
};
/// Swift modules to be built from a module interface, may have a bridging

View File

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

View File

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

View File

@@ -116,14 +116,34 @@ bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const {
}
void ModuleDependencyInfo::addOptionalModuleImport(
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules) {
if (!alreadyAddedModules || alreadyAddedModules->insert(module).second)
storage->optionalModuleImports.push_back({module.str(), isExported});
StringRef module, bool isExported, AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules) {
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(
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
const SourceManager *sourceManager, SourceLoc sourceLocation) {
StringRef module, bool isExported, AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
SourceLoc sourceLocation) {
auto scannerImportLocToDiagnosticLocInfo =
[&sourceManager](SourceLoc sourceLocation) {
auto lineAndColumnNumbers =
@@ -138,13 +158,16 @@ void ModuleDependencyInfo::addModuleImport(
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->moduleImports) {
if (existingImport.importIdentifier == module) {
if (validSourceLocation) {
existingImport.addImportLocation(
scannerImportLocToDiagnosticLocInfo(sourceLocation));
scannerImportLocToDiagnosticLocInfo(sourceLocation));
}
existingImport.isExported |= isExported;
existingImport.accessLevel = std::max(existingImport.accessLevel,
accessLevel);
break;
}
}
@@ -154,16 +177,18 @@ void ModuleDependencyInfo::addModuleImport(
if (validSourceLocation)
storage->moduleImports.push_back(ScannerImportStatementInfo(
module.str(), isExported, scannerImportLocToDiagnosticLocInfo(sourceLocation)));
module.str(), isExported, accessLevel,
scannerImportLocToDiagnosticLocInfo(sourceLocation)));
else
storage->moduleImports.push_back(
ScannerImportStatementInfo(module.str(), isExported));
ScannerImportStatementInfo(module.str(), isExported, accessLevel));
}
}
void ModuleDependencyInfo::addModuleImport(
ImportPath::Module module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
const SourceManager *sourceManager, SourceLoc sourceLocation) {
ImportPath::Module module, bool isExported, AccessLevel accessLevel,
llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
SourceLoc sourceLocation) {
std::string ImportedModuleName = module.front().Item.str().str();
auto submodulePath = module.getSubmodulePath();
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.
if (submoduleComponent.Item.str() == "Private")
addOptionalModuleImport(ImportedModuleName + "_Private",
isExported, accessLevel,
alreadyAddedModules);
}
addModuleImport(ImportedModuleName, isExported, alreadyAddedModules,
sourceManager, sourceLocation);
addModuleImport(ImportedModuleName, isExported, accessLevel,
alreadyAddedModules, sourceManager, sourceLocation);
}
void ModuleDependencyInfo::addModuleImports(
@@ -205,6 +231,7 @@ void ModuleDependencyInfo::addModuleImports(
continue;
addModuleImport(realPath, importDecl->isExported(),
importDecl->getAccessLevel(),
&alreadyAddedModules, sourceManager,
importDecl->getLoc());

View File

@@ -192,7 +192,8 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
// FIXME: This assumes, conservatively, that all Clang module imports
// are exported. We need to fix this once the clang scanner gains the appropriate
// 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.
directDependencyIDs.push_back({moduleName.ModuleName, ModuleDependencyKind::Clang});
}

View File

@@ -77,6 +77,11 @@ void writeJSONValue(llvm::raw_ostream &out, bool value, unsigned indentLevel) {
out.write_escaped(value ? "true" : "false");
}
/// Write a boolean value as JSON.
void writeJSONValue(llvm::raw_ostream &out, uint32_t value, unsigned indentLevel) {
out.write_escaped(std::to_string(value));
}
/// Write a JSON array.
template <typename T>
void writeJSONValue(llvm::raw_ostream &out, ArrayRef<T> values,
@@ -226,6 +231,90 @@ void writeLinkLibraries(llvm::raw_ostream &out,
out << "\n";
}
void writeImportInfos(llvm::raw_ostream &out,
const swiftscan_import_info_set_t *imports,
unsigned indentLevel, bool trailingComma) {
out.indent(indentLevel * 2);
out << "\"imports\": ";
out << "[\n";
for (size_t i = 0; i < imports->count; ++i) {
const auto &iInfo = *imports->imports[i];
out.indent((indentLevel + 1) * 2);
out << "{\n";
auto entryIndentLevel = ((indentLevel + 2) * 2);
out.indent(entryIndentLevel);
out << "\"identifier\": ";
writeJSONValue(out, iInfo.import_identifier, indentLevel);
out << ",\n";
out.indent(entryIndentLevel);
out << "\"accessLevel\": ";
switch (iInfo.access_level) {
case SWIFTSCAN_ACCESS_LEVEL_PRIVATE:
writeJSONValue(out, StringRef("private"), entryIndentLevel);
break;
case SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE:
writeJSONValue(out, StringRef("fileprivate"), entryIndentLevel);
break;
case SWIFTSCAN_ACCESS_LEVEL_INTERNAL:
writeJSONValue(out, StringRef("internal"), entryIndentLevel);
break;
case SWIFTSCAN_ACCESS_LEVEL_PACKAGE:
writeJSONValue(out, StringRef("package"), entryIndentLevel);
break;
case SWIFTSCAN_ACCESS_LEVEL_PUBLIC:
writeJSONValue(out, StringRef("public"), entryIndentLevel);
break;
}
if (iInfo.source_locations->count) {
out << ",\n";
out.indent(entryIndentLevel);
out << "\"importLocations\": ";
out << "[\n";
auto slIndentLevel = ((entryIndentLevel + 4));
for (size_t i = 0; i < iInfo.source_locations->count; ++i) {
out.indent(entryIndentLevel + 2);
out << "{\n";
const auto &sl = *iInfo.source_locations->source_locations[i];
out.indent(slIndentLevel);
out << "\"bufferIdentifier\": ";
writeJSONValue(out, sl.buffer_identifier, indentLevel);
out << ",\n";
out.indent(slIndentLevel);
out << "\"linuNumber\": ";
writeJSONValue(out, sl.line_number, indentLevel);
out << ",\n";
out.indent(slIndentLevel);
out << "\"columnNumber\": ";
writeJSONValue(out, sl.column_number, indentLevel);
out << "\n";
out.indent(entryIndentLevel + 2);
out << "}";
if (i != iInfo.source_locations->count - 1)
out << ",";
out << "\n";
}
out.indent(entryIndentLevel);
out << "]\n";
} else {
out << "\n";
}
out.indent((indentLevel + 1) * 2);
out << "}";
if (i != imports->count - 1)
out << ",";
out << "\n";
}
out.indent(indentLevel * 2);
out << "]";
if (trailingComma)
out << ",";
out << "\n";
}
static void
writeMacroDependencies(llvm::raw_ostream &out,
const swiftscan_macro_dependency_set_t *macro_deps,
@@ -243,15 +332,15 @@ writeMacroDependencies(llvm::raw_ostream &out,
auto entryIndentLevel = ((indentLevel + 2) * 2);
out.indent(entryIndentLevel);
out << "\"moduleName\": ";
writeJSONValue(out, macroInfo.moduleName, indentLevel);
writeJSONValue(out, macroInfo.module_name, indentLevel);
out << ",\n";
out.indent(entryIndentLevel);
out << "\"libraryPath\": ";
writeJSONValue(out, macroInfo.libraryPath, entryIndentLevel);
writeJSONValue(out, macroInfo.library_path, entryIndentLevel);
out << ",\n";
out.indent(entryIndentLevel);
out << "\"executablePath\": ";
writeJSONValue(out, macroInfo.executablePath, entryIndentLevel);
writeJSONValue(out, macroInfo.executable_path, entryIndentLevel);
out << "\n";
out.indent((indentLevel + 1) * 2);
out << "}";
@@ -368,6 +457,8 @@ void writeJSON(llvm::raw_ostream &out,
/*trailingComma=*/true);
writeLinkLibraries(out, moduleInfo.link_libraries,
3, /*trailingComma=*/true);
writeImportInfos(out, moduleInfo.imports,
3, /*trailingComma=*/true);
}
// Swift and Clang-specific details.
out.indent(3 * 2);

View File

@@ -238,6 +238,13 @@ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput(
hollowLinkLibrarySet->link_libraries = nullptr;
hollowMainModuleInfo->link_libraries = hollowLinkLibrarySet;
// Empty Import set
swiftscan_import_info_set_t *hollowImportInfoSet =
new swiftscan_import_info_set_t;
hollowImportInfoSet->count = 0;
hollowImportInfoSet->imports = nullptr;
hollowMainModuleInfo->imports = hollowImportInfoSet;
// Populate the diagnostic info
hollowResult->diagnostics =
mapCollectedDiagnosticsForOutput(&ScanDiagnosticConsumer);

View File

@@ -415,9 +415,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
unsigned importIdentifierID, bufferIdentifierID;
unsigned lineNumber, columnNumber;
bool isOptional, isExported;
uint8_t rawAccessLevel;
ImportStatementLayout::readRecord(Scratch, importIdentifierID,
bufferIdentifierID, lineNumber,
columnNumber, isOptional, isExported);
columnNumber, isOptional, isExported,
rawAccessLevel);
auto importIdentifier = getIdentifier(importIdentifierID);
if (!importIdentifier)
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");
if (bufferIdentifier->empty())
ImportStatements.push_back(ScannerImportStatementInfo(
*importIdentifier, isExported));
*importIdentifier, isExported, AccessLevel(rawAccessLevel)));
else
ImportStatements.push_back(ScannerImportStatementInfo(
*importIdentifier, isExported,
*importIdentifier, isExported, AccessLevel(rawAccessLevel),
ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
*bufferIdentifier, lineNumber, columnNumber)));
break;
@@ -1527,7 +1529,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
ImportStatementLayout::emitRecord(
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
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++;
} else {
for (auto &importLoc : importInfo.importLocations) {
@@ -1535,7 +1538,8 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
getIdentifier(importInfo.importIdentifier),
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++;
}
}

View File

@@ -544,6 +544,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
case ImplicitStdlibKind::Stdlib:
mainDependencies.addModuleImport("Swift", /* isExported */false,
AccessLevel::Public,
&alreadyAddedModules);
break;
}
@@ -552,6 +553,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
for (const auto &import : importInfo.AdditionalUnloadedImports) {
mainDependencies.addModuleImport(import.module.getModulePath(),
import.options.contains(ImportFlags::Exported),
import.accessLevel,
&alreadyAddedModules,
&ScanASTContext.SourceMgr);
}
@@ -561,6 +563,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
mainDependencies.addModuleImport(
import.module.importedModule->getNameStr(),
import.options.contains(ImportFlags::Exported),
import.accessLevel,
&alreadyAddedModules);
}
@@ -574,6 +577,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
if (importInfo.ShouldImportUnderlyingModule) {
mainDependencies.addModuleImport(mainModule->getName().str(),
/* isExported */ true,
AccessLevel::Public,
&alreadyAddedModules);
}
@@ -584,6 +588,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) {
mainDependencies.addModuleImport(tbdSymbolModule,
/* isExported */ false,
AccessLevel::Public,
&alreadyAddedModules);
}
}
@@ -948,7 +953,8 @@ void ModuleDependencyScanner::resolveAllClangModuleDependencies(
if (importInfo.importIdentifier ==
ScanASTContext.Id_CxxStdlib.str()) {
auto canonicalImportInfo = ScannerImportStatementInfo(
"std", importInfo.isExported, importInfo.importLocations);
"std", importInfo.isExported, importInfo.accessLevel,
importInfo.importLocations);
unresolvedImports.push_back(canonicalImportInfo);
unresolvedImportIdentifiers.insert(
canonicalImportInfo.importIdentifier);
@@ -1477,7 +1483,9 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
std::for_each(newOverlays.begin(), newOverlays.end(),
[&](Identifier modName) {
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

View File

@@ -747,10 +747,10 @@ static swiftscan_macro_dependency_set_t *createMacroDependencySet(
unsigned SI = 0;
for (auto &entry : macroDeps) {
set->macro_dependencies[SI] = new swiftscan_macro_dependency_s;
set->macro_dependencies[SI]->moduleName = create_clone(entry.first.c_str());
set->macro_dependencies[SI]->libraryPath =
set->macro_dependencies[SI]->module_name = create_clone(entry.first.c_str());
set->macro_dependencies[SI]->library_path =
create_clone(entry.second.LibraryPath.c_str());
set->macro_dependencies[SI]->executablePath =
set->macro_dependencies[SI]->executable_path =
create_clone(entry.second.ExecutablePath.c_str());
++ SI;
}
@@ -976,6 +976,37 @@ generateFullDependencyGraph(const CompilerInstance &instance,
linkLibrarySet->link_libraries[i] = llInfo;
}
moduleInfo->link_libraries = linkLibrarySet;
// Create source import infos set for this module
auto imports = moduleDependencyInfo.getModuleImports();
swiftscan_import_info_set_t *importInfoSet =
new swiftscan_import_info_set_t;
importInfoSet->count = imports.size();
importInfoSet->imports = new swiftscan_import_info_t[importInfoSet->count];
for (size_t i = 0; i < imports.size(); ++i) {
const auto &ii = imports[i];
swiftscan_import_info_s *iInfo = new swiftscan_import_info_s;
iInfo->import_identifier = create_clone(ii.importIdentifier.c_str());
iInfo->access_level = static_cast<swiftscan_access_level_t>(ii.accessLevel);
const auto &sourceLocations = ii.importLocations;
swiftscan_source_location_set_t *sourceLocSet =
new swiftscan_source_location_set_t;
sourceLocSet->count = sourceLocations.size();
sourceLocSet->source_locations =
new swiftscan_source_location_t[sourceLocSet->count];
for (size_t j = 0; j < sourceLocations.size(); ++j) {
const auto &sl = sourceLocations[j];
swiftscan_source_location_s *slInfo = new swiftscan_source_location_s;
slInfo->buffer_identifier = create_clone(sl.bufferIdentifier.c_str());
slInfo->line_number = sl.lineNumber;
slInfo->column_number = sl.columnNumber;
sourceLocSet->source_locations[j] = slInfo;
}
iInfo->source_locations = sourceLocSet;
importInfoSet->imports[i] = iInfo;
}
moduleInfo->imports = importInfoSet;
}
swiftscan_dependency_graph_t result = new swiftscan_dependency_graph_s;

View File

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

View File

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

View File

@@ -35,9 +35,9 @@ void swiftscan_macro_dependency_dispose(
return;
for (unsigned i = 0; i < macro->count; ++i) {
swiftscan_string_dispose(macro->macro_dependencies[i]->moduleName);
swiftscan_string_dispose(macro->macro_dependencies[i]->libraryPath);
swiftscan_string_dispose(macro->macro_dependencies[i]->executablePath);
swiftscan_string_dispose(macro->macro_dependencies[i]->module_name);
swiftscan_string_dispose(macro->macro_dependencies[i]->library_path);
swiftscan_string_dispose(macro->macro_dependencies[i]->executable_path);
delete macro->macro_dependencies[i];
}
delete[] macro->macro_dependencies;
@@ -240,12 +240,17 @@ swiftscan_link_library_set_t *swiftscan_module_info_get_link_libraries(
return info->link_libraries;
}
swiftscan_import_info_set_t *swiftscan_module_info_get_imports(
swiftscan_dependency_info_t info) {
return info->imports;
}
swiftscan_module_details_t
swiftscan_module_info_get_details(swiftscan_dependency_info_t info) {
return info->details;
}
//=== Link Library Info query APIs -----------------------------------===//
//=== Link Library Info query APIs ---------------------------------------===//
swiftscan_string_ref_t
swiftscan_link_library_info_get_link_name(swiftscan_link_library_info_t info) {
@@ -267,7 +272,23 @@ swiftscan_link_library_info_get_should_force_load(swiftscan_link_library_info_t
return info->forceLoad;
}
//=== Swift Textual Module Details query APIs -----------------------------===//
//=== Import Details Query APIs ------------------------------------------===//
swiftscan_source_location_set_t *
swiftscan_import_info_get_source_locations(swiftscan_import_info_t info) {
return info->source_locations;
}
swiftscan_string_ref_t
swiftscan_import_info_get_identifier(swiftscan_import_info_t info) {
return info->import_identifier;
}
swiftscan_access_level_t
swiftscan_import_info_get_access_level(swiftscan_import_info_t info) {
return info->access_level;
}
//=== Swift Textual Module Details query APIs ----------------------------===//
swiftscan_dependency_info_kind_t
swiftscan_module_detail_get_kind(swiftscan_module_details_t details) {

View File

@@ -5,11 +5,15 @@ swiftscan_link_library_info_get_link_name
swiftscan_link_library_info_get_is_static
swiftscan_link_library_info_get_is_framework
swiftscan_link_library_info_get_should_force_load
swiftscan_import_info_get_source_locations
swiftscan_import_info_get_identifier
swiftscan_import_info_get_access_level
swiftscan_module_info_get_module_name
swiftscan_module_info_get_module_path
swiftscan_module_info_get_source_files
swiftscan_module_info_get_direct_dependencies
swiftscan_module_info_get_link_libraries
swiftscan_module_info_get_imports
swiftscan_module_info_get_details
swiftscan_module_detail_get_kind
swiftscan_swift_textual_detail_get_module_interface_path

View File

@@ -75,7 +75,8 @@ import F
/// Check that the dependency swift module hashes are identical when the vfs overlays are ignored.
// MOD-HASH: "mainModuleName": "deps",
// MOD-HASH: "linkLibraries": [],
// MOD-HASH-NEXT: "details": {
// MOD-HASH: "imports": [
// MOD-HASH: "details": {
// MOD-HASH-NEXT: "swift": {
// MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface",
// MOD-HASH: "commandLine": [
@@ -86,6 +87,7 @@ import F
// MOD-HASH: ],
// MOD-HASH: "mainModuleName": "deps1",
// MOD-HASH: "linkLibraries": [],
// MOD-HASH: "imports": [
// MOD-HASH: "details": {
// MOD-HASH-NEXT: "swift": {
// MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface",
@@ -97,6 +99,7 @@ import F
// MOD-HASH: ],
// MOD-HASH: "mainModuleName": "deps2",
// MOD-HASH: "linkLibraries": [],
// MOD-HASH: "imports": [
// MOD-HASH: "details": {
// MOD-HASH-NEXT: "swift": {
// MOD-HASH-NEXT: "moduleInterfacePath": "{{.*}}{{/|\\}}F.swiftinterface",

View File

@@ -0,0 +1,72 @@
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/module-cache)
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import
// RUN: %validate-json %t/deps.json | %FileCheck %s
// CHECK: "mainModuleName": "deps"
// CHECK: "swift": "deps"
// CHECK: "modulePath": "deps.swiftmodule"
// CHECK: "imports": [
// CHECK-NEXT: {
// CHECK-NEXT: "identifier": "Swift"
// CHECK-NEXT: "accessLevel": "public"
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "identifier": "SwiftOnoneSupport"
// CHECK-NEXT: "accessLevel": "public"
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "identifier": "C"
// CHECK-NEXT: "accessLevel": "internal"
// CHECK-NEXT: "importLocations": [
// CHECK-NEXT: {
// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift"
// CHECK-NEXT: "linuNumber": 65
// CHECK-NEXT: "columnNumber": 17
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift"
// CHECK-NEXT: "linuNumber": 72
// CHECK-NEXT: "columnNumber": 16
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "identifier": "E"
// CHECK-NEXT: "accessLevel": "public"
// CHECK-NEXT: "importLocations": [
// CHECK-NEXT: {
// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift"
// CHECK-NEXT: "linuNumber": 67
// CHECK-NEXT: "columnNumber": 15
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift"
// CHECK-NEXT: "linuNumber": 68
// CHECK-NEXT: "columnNumber": 8
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: {
// CHECK-NEXT: "identifier": "G"
// CHECK-NEXT: "accessLevel": "fileprivate"
// CHECK-NEXT: "importLocations": [
// CHECK-NEXT: {
// CHECK-NEXT: "bufferIdentifier": "{{.*}}import_infos.swift"
// CHECK-NEXT: "linuNumber": 70
// CHECK-NEXT: "columnNumber": 20
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
internal import C
public import E
import E
fileprivate import G
private import C

View File

@@ -128,7 +128,7 @@ import SubE
// CHECK: ],
// CHECK-NEXT: "linkLibraries": [
// CHECK-NEXT: ],
// CHECK-NEXT: "details": {
// CHECK: "details": {
// CHECK: "commandLine": [
// CHECK: "-compile-module-from-interface"

View File

@@ -29,7 +29,7 @@ import A
// CHECK-INITIAL-SCAN: ],
// CHECK-INITIAL-SCAN-NEXT: "linkLibraries": [
// CHECK-INITIAL-SCAN-NEXT: ],
// CHECK-INITIAL-SCAN-NEXT: "details": {
// CHECK-INITIAL-SCAN: "details": {
// CHECK-INITIAL-SCAN-NEXT: "swift": {
// CHECK-INITIAL-SCAN-NEXT: "moduleInterfacePath": "{{.*}}/Swift/A.swiftinterface",
@@ -43,6 +43,6 @@ import A
// CHECK-DIFFERENT: ],
// CHECK-DIFFERENT-NEXT: "linkLibraries": [
// CHECK-DIFFERENT-NEXT: ],
// CHECK-DIFFERENT-NEXT: "details": {
// CHECK-DIFFERENT: "details": {
// CHECK-DIFFERENT-NEXT: "swift": {
// CHECK-DIFFERENT-NEXT: "moduleInterfacePath": "{{.*}}/SwiftDifferent/A.swiftinterface",