Skip to content

Commit 6816922

Browse files
committed
[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.
1 parent c24bae7 commit 6816922

File tree

9 files changed

+105
-70
lines changed

9 files changed

+105
-70
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,30 +156,35 @@ struct ScannerImportStatementInfo {
156156
uint32_t columnNumber;
157157
};
158158

159-
ScannerImportStatementInfo(std::string importIdentifier, bool isExported)
160-
: importLocations(), importIdentifier(importIdentifier),
161-
isExported(isExported) {}
159+
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
160+
AccessLevel accessLevel)
161+
: importIdentifier(importIdentifier), importLocations(),
162+
isExported(isExported), accessLevel(accessLevel) {}
162163

163164
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
165+
AccessLevel accessLevel,
164166
ImportDiagnosticLocationInfo location)
165-
: importLocations({location}), importIdentifier(importIdentifier),
166-
isExported(isExported) {}
167+
: importIdentifier(importIdentifier), importLocations({location}),
168+
isExported(isExported), accessLevel(accessLevel) {}
167169

168170
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
171+
AccessLevel accessLevel,
169172
SmallVector<ImportDiagnosticLocationInfo, 4> locations)
170-
: importLocations(locations), importIdentifier(importIdentifier),
171-
isExported(isExported) {}
173+
: importIdentifier(importIdentifier), importLocations(locations),
174+
isExported(isExported), accessLevel(accessLevel) {}
172175

173176
void addImportLocation(ImportDiagnosticLocationInfo location) {
174177
importLocations.push_back(location);
175178
}
176179

177-
/// Buffer, line & column number of the import statement
178-
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
179180
/// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar'
180181
std::string importIdentifier;
182+
/// Buffer, line & column number of the import statement
183+
SmallVector<ImportDiagnosticLocationInfo, 4> importLocations;
181184
/// Is this an @_exported import
182185
bool isExported;
186+
/// Access level of this dependency
187+
AccessLevel accessLevel;
183188
};
184189

185190
/// Base class for the variant storage of ModuleDependencyInfo.
@@ -942,6 +947,7 @@ class ModuleDependencyInfo {
942947
/// Add a dependency on the given module, if it was not already in the set.
943948
void
944949
addOptionalModuleImport(StringRef module, bool isExported,
950+
AccessLevel accessLevel,
945951
llvm::StringSet<> *alreadyAddedModules = nullptr);
946952

947953
/// Add all of the module imports in the given source
@@ -952,12 +958,14 @@ class ModuleDependencyInfo {
952958

953959
/// Add a dependency on the given module, if it was not already in the set.
954960
void addModuleImport(ImportPath::Module module, bool isExported,
961+
AccessLevel accessLevel,
955962
llvm::StringSet<> *alreadyAddedModules = nullptr,
956963
const SourceManager *sourceManager = nullptr,
957964
SourceLoc sourceLocation = SourceLoc());
958965

959966
/// Add a dependency on the given module, if it was not already in the set.
960967
void addModuleImport(StringRef module, bool isExported,
968+
AccessLevel accessLevel,
961969
llvm::StringSet<> *alreadyAddedModules = nullptr,
962970
const SourceManager *sourceManager = nullptr,
963971
SourceLoc sourceLocation = SourceLoc());

include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ using IsExportedImport = BCFixed<1>;
6767
using LineNumberField = BCFixed<32>;
6868
using ColumnNumberField = BCFixed<32>;
6969

70+
/// Access level of an import
71+
using AccessLevelField = BCFixed<8>;
72+
7073
/// Arrays of various identifiers, distinguished for readability
7174
using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>;
7275
using ModuleIDArryField = llvm::BCArray<IdentifierIDField>;
@@ -192,7 +195,8 @@ using ImportStatementLayout =
192195
LineNumberField, // lineNumber
193196
ColumnNumberField, // columnNumber
194197
IsOptionalImport, // isOptional
195-
IsExportedImport // isExported
198+
IsExportedImport, // isExported
199+
AccessLevelField // accessLevel
196200
>;
197201
using ImportStatementArrayLayout =
198202
BCRecordLayout<IMPORT_STATEMENT_ARRAY_NODE, IdentifierIDArryField>;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
170170
bool isTestableImport, bool isCandidateForTextualModule);
171171

172172
struct BinaryModuleImports {
173-
llvm::StringSet<> moduleImports;
174-
llvm::StringSet<> exportedModules;
173+
std::vector<ScannerImportStatementInfo> moduleImports;
175174
std::string headerImport;
176175
};
177176

lib/AST/ModuleDependencies.cpp

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,34 @@ bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const {
116116
}
117117

118118
void ModuleDependencyInfo::addOptionalModuleImport(
119-
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules) {
120-
if (!alreadyAddedModules || alreadyAddedModules->insert(module).second)
121-
storage->optionalModuleImports.push_back({module.str(), isExported});
119+
StringRef module, bool isExported, AccessLevel accessLevel,
120+
llvm::StringSet<> *alreadyAddedModules) {
121+
122+
if (alreadyAddedModules && alreadyAddedModules->contains(module)) {
123+
// Find a prior import of this module and add import location
124+
// and adjust whether or not this module is ever imported as exported
125+
// as well as the access level
126+
for (auto &existingImport : storage->optionalModuleImports) {
127+
if (existingImport.importIdentifier == module) {
128+
existingImport.isExported |= isExported;
129+
existingImport.accessLevel = std::max(existingImport.accessLevel,
130+
accessLevel);
131+
break;
132+
}
133+
}
134+
} else {
135+
if (alreadyAddedModules)
136+
alreadyAddedModules->insert(module);
137+
138+
storage->optionalModuleImports.push_back(
139+
{module.str(), isExported, accessLevel});
140+
}
122141
}
123142

124143
void ModuleDependencyInfo::addModuleImport(
125-
StringRef module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
126-
const SourceManager *sourceManager, SourceLoc sourceLocation) {
144+
StringRef module, bool isExported, AccessLevel accessLevel,
145+
llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
146+
SourceLoc sourceLocation) {
127147
auto scannerImportLocToDiagnosticLocInfo =
128148
[&sourceManager](SourceLoc sourceLocation) {
129149
auto lineAndColumnNumbers =
@@ -138,13 +158,16 @@ void ModuleDependencyInfo::addModuleImport(
138158
if (alreadyAddedModules && alreadyAddedModules->contains(module)) {
139159
// Find a prior import of this module and add import location
140160
// and adjust whether or not this module is ever imported as exported
161+
// as well as the access level
141162
for (auto &existingImport : storage->moduleImports) {
142163
if (existingImport.importIdentifier == module) {
143164
if (validSourceLocation) {
144165
existingImport.addImportLocation(
145-
scannerImportLocToDiagnosticLocInfo(sourceLocation));
166+
scannerImportLocToDiagnosticLocInfo(sourceLocation));
146167
}
147168
existingImport.isExported |= isExported;
169+
existingImport.accessLevel = std::max(existingImport.accessLevel,
170+
accessLevel);
148171
break;
149172
}
150173
}
@@ -154,16 +177,18 @@ void ModuleDependencyInfo::addModuleImport(
154177

155178
if (validSourceLocation)
156179
storage->moduleImports.push_back(ScannerImportStatementInfo(
157-
module.str(), isExported, scannerImportLocToDiagnosticLocInfo(sourceLocation)));
180+
module.str(), isExported, accessLevel,
181+
scannerImportLocToDiagnosticLocInfo(sourceLocation)));
158182
else
159183
storage->moduleImports.push_back(
160-
ScannerImportStatementInfo(module.str(), isExported));
184+
ScannerImportStatementInfo(module.str(), isExported, accessLevel));
161185
}
162186
}
163187

164188
void ModuleDependencyInfo::addModuleImport(
165-
ImportPath::Module module, bool isExported, llvm::StringSet<> *alreadyAddedModules,
166-
const SourceManager *sourceManager, SourceLoc sourceLocation) {
189+
ImportPath::Module module, bool isExported, AccessLevel accessLevel,
190+
llvm::StringSet<> *alreadyAddedModules, const SourceManager *sourceManager,
191+
SourceLoc sourceLocation) {
167192
std::string ImportedModuleName = module.front().Item.str().str();
168193
auto submodulePath = module.getSubmodulePath();
169194
if (submodulePath.size() > 0 && !submodulePath[0].Item.empty()) {
@@ -172,11 +197,12 @@ void ModuleDependencyInfo::addModuleImport(
172197
// module named "Foo_Private". ClangImporter has special support for this.
173198
if (submoduleComponent.Item.str() == "Private")
174199
addOptionalModuleImport(ImportedModuleName + "_Private",
200+
isExported, accessLevel,
175201
alreadyAddedModules);
176202
}
177203

178-
addModuleImport(ImportedModuleName, isExported, alreadyAddedModules,
179-
sourceManager, sourceLocation);
204+
addModuleImport(ImportedModuleName, isExported, accessLevel,
205+
alreadyAddedModules, sourceManager, sourceLocation);
180206
}
181207

182208
void ModuleDependencyInfo::addModuleImports(
@@ -205,6 +231,7 @@ void ModuleDependencyInfo::addModuleImports(
205231
continue;
206232

207233
addModuleImport(realPath, importDecl->isExported(),
234+
importDecl->getAccessLevel(),
208235
&alreadyAddedModules, sourceManager,
209236
importDecl->getLoc());
210237

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
191191
// FIXME: This assumes, conservatively, that all Clang module imports
192192
// are exported. We need to fix this once the clang scanner gains the appropriate
193193
// API to query this.
194-
dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true, &alreadyAddedModules);
194+
dependencies.addModuleImport(moduleName.ModuleName, /* isExported */ true,
195+
AccessLevel::Public, &alreadyAddedModules);
195196
// It is safe to assume that all dependencies of a Clang module are Clang modules.
196197
directDependencyIDs.push_back({moduleName.ModuleName, ModuleDependencyKind::Clang});
197198
}

lib/DependencyScan/ModuleDependencyCacheSerialization.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
415415
unsigned importIdentifierID, bufferIdentifierID;
416416
unsigned lineNumber, columnNumber;
417417
bool isOptional, isExported;
418+
uint8_t rawAccessLevel;
418419
ImportStatementLayout::readRecord(Scratch, importIdentifierID,
419420
bufferIdentifierID, lineNumber,
420-
columnNumber, isOptional, isExported);
421+
columnNumber, isOptional, isExported,
422+
rawAccessLevel);
421423
auto importIdentifier = getIdentifier(importIdentifierID);
422424
if (!importIdentifier)
423425
llvm::report_fatal_error("Bad import statement info: no import name");
@@ -428,10 +430,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
428430
"Bad import statement info: no buffer identifier");
429431
if (bufferIdentifier->empty())
430432
ImportStatements.push_back(ScannerImportStatementInfo(
431-
*importIdentifier, isExported));
433+
*importIdentifier, isExported, AccessLevel(rawAccessLevel)));
432434
else
433435
ImportStatements.push_back(ScannerImportStatementInfo(
434-
*importIdentifier, isExported,
436+
*importIdentifier, isExported, AccessLevel(rawAccessLevel),
435437
ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
436438
*bufferIdentifier, lineNumber, columnNumber)));
437439
break;
@@ -1527,15 +1529,17 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
15271529
ImportStatementLayout::emitRecord(
15281530
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
15291531
getIdentifier(importInfo.importIdentifier),
1530-
0, 0, 0, isOptional, importInfo.isExported);
1532+
0, 0, 0, isOptional, importInfo.isExported,
1533+
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
15311534
count++;
15321535
} else {
15331536
for (auto &importLoc : importInfo.importLocations) {
15341537
ImportStatementLayout::emitRecord(
15351538
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
15361539
getIdentifier(importInfo.importIdentifier),
15371540
getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber,
1538-
importLoc.columnNumber, isOptional, importInfo.isExported);
1541+
importLoc.columnNumber, isOptional, importInfo.isExported,
1542+
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
15391543
count++;
15401544
}
15411545
}

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
544544

545545
case ImplicitStdlibKind::Stdlib:
546546
mainDependencies.addModuleImport("Swift", /* isExported */false,
547+
AccessLevel::Public,
547548
&alreadyAddedModules);
548549
break;
549550
}
@@ -552,6 +553,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
552553
for (const auto &import : importInfo.AdditionalUnloadedImports) {
553554
mainDependencies.addModuleImport(import.module.getModulePath(),
554555
import.options.contains(ImportFlags::Exported),
556+
import.accessLevel,
555557
&alreadyAddedModules,
556558
&ScanASTContext.SourceMgr);
557559
}
@@ -561,6 +563,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
561563
mainDependencies.addModuleImport(
562564
import.module.importedModule->getNameStr(),
563565
import.options.contains(ImportFlags::Exported),
566+
import.accessLevel,
564567
&alreadyAddedModules);
565568
}
566569

@@ -574,6 +577,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
574577
if (importInfo.ShouldImportUnderlyingModule) {
575578
mainDependencies.addModuleImport(mainModule->getName().str(),
576579
/* isExported */ true,
580+
AccessLevel::Public,
577581
&alreadyAddedModules);
578582
}
579583

@@ -584,6 +588,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
584588
ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) {
585589
mainDependencies.addModuleImport(tbdSymbolModule,
586590
/* isExported */ false,
591+
AccessLevel::Public,
587592
&alreadyAddedModules);
588593
}
589594
}
@@ -948,7 +953,8 @@ void ModuleDependencyScanner::resolveAllClangModuleDependencies(
948953
if (importInfo.importIdentifier ==
949954
ScanASTContext.Id_CxxStdlib.str()) {
950955
auto canonicalImportInfo = ScannerImportStatementInfo(
951-
"std", importInfo.isExported, importInfo.importLocations);
956+
"std", importInfo.isExported, importInfo.accessLevel,
957+
importInfo.importLocations);
952958
unresolvedImports.push_back(canonicalImportInfo);
953959
unresolvedImportIdentifiers.insert(
954960
canonicalImportInfo.importIdentifier);
@@ -1475,7 +1481,9 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
14751481
std::for_each(newOverlays.begin(), newOverlays.end(),
14761482
[&](Identifier modName) {
14771483
dummyMainDependencies.addModuleImport(modName.str(),
1478-
/* isExported */ false);
1484+
/* isExported */ false,
1485+
// TODO: What is the right access level for a cross-import overlay?
1486+
AccessLevel::Public);
14791487
});
14801488

14811489
// Record the dummy main module's direct dependencies. The dummy main module

lib/Serialization/ScanningLoaders.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
242242
for (auto import : imInfo.AdditionalUnloadedImports) {
243243
Result->addModuleImport(import.module.getModulePath(),
244244
import.options.contains(ImportFlags::Exported),
245+
import.accessLevel,
245246
&alreadyAddedModules, &Ctx.SourceMgr);
246247
}
247248

@@ -270,6 +271,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
270271
if (!alreadyAddedModules.contains(requiredImport.importIdentifier))
271272
Result->addModuleImport(requiredImport.importIdentifier,
272273
requiredImport.isExported,
274+
requiredImport.accessLevel,
273275
&alreadyAddedModules);
274276
}
275277
}

0 commit comments

Comments
 (0)