Skip to content

Commit 9b3fabd

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 1484f1c commit 9b3fabd

File tree

9 files changed

+105
-69
lines changed

9 files changed

+105
-69
lines changed

include/swift/AST/ModuleDependencies.h

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

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

162163
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
164+
AccessLevel accessLevel,
163165
ImportDiagnosticLocationInfo location)
164-
: importLocations({location}), importIdentifier(importIdentifier),
165-
isExported(isExported) {}
166+
: importIdentifier(importIdentifier), importLocations({location}),
167+
isExported(isExported), accessLevel(accessLevel) {}
166168

167169
ScannerImportStatementInfo(std::string importIdentifier, bool isExported,
170+
AccessLevel accessLevel,
168171
SmallVector<ImportDiagnosticLocationInfo, 4> locations)
169-
: importLocations(locations), importIdentifier(importIdentifier),
170-
isExported(isExported) {}
172+
: importIdentifier(importIdentifier), importLocations(locations),
173+
isExported(isExported), accessLevel(accessLevel) {}
171174

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

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

184189
/// Base class for the variant storage of ModuleDependencyInfo.
@@ -933,6 +938,7 @@ class ModuleDependencyInfo {
933938
/// Add a dependency on the given module, if it was not already in the set.
934939
void
935940
addOptionalModuleImport(StringRef module, bool isExported,
941+
AccessLevel accessLevel,
936942
llvm::StringSet<> *alreadyAddedModules = nullptr);
937943

938944
/// Add all of the module imports in the given source
@@ -943,12 +949,14 @@ class ModuleDependencyInfo {
943949

944950
/// Add a dependency on the given module, if it was not already in the set.
945951
void addModuleImport(ImportPath::Module module, bool isExported,
952+
AccessLevel accessLevel,
946953
llvm::StringSet<> *alreadyAddedModules = nullptr,
947954
const SourceManager *sourceManager = nullptr,
948955
SourceLoc sourceLocation = SourceLoc());
949956

950957
/// Add a dependency on the given module, if it was not already in the set.
951958
void addModuleImport(StringRef module, bool isExported,
959+
AccessLevel accessLevel,
952960
llvm::StringSet<> *alreadyAddedModules = nullptr,
953961
const SourceManager *sourceManager = nullptr,
954962
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>;
@@ -178,7 +181,8 @@ using ImportStatementLayout =
178181
LineNumberField, // lineNumber
179182
ColumnNumberField, // columnNumber
180183
IsOptionalImport, // isOptional
181-
IsExportedImport // isExported
184+
IsExportedImport, // isExported
185+
AccessLevelField // accessLevel
182186
>;
183187
using ImportStatementArrayLayout =
184188
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
@@ -393,9 +393,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
393393
unsigned importIdentifierID, bufferIdentifierID;
394394
unsigned lineNumber, columnNumber;
395395
bool isOptional, isExported;
396+
uint8_t rawAccessLevel;
396397
ImportStatementLayout::readRecord(Scratch, importIdentifierID,
397398
bufferIdentifierID, lineNumber,
398-
columnNumber, isOptional, isExported);
399+
columnNumber, isOptional, isExported,
400+
rawAccessLevel);
399401
auto importIdentifier = getIdentifier(importIdentifierID);
400402
if (!importIdentifier)
401403
llvm::report_fatal_error("Bad import statement info: no import name");
@@ -406,10 +408,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph(
406408
"Bad import statement info: no buffer identifier");
407409
if (bufferIdentifier->empty())
408410
ImportStatements.push_back(ScannerImportStatementInfo(
409-
*importIdentifier, isExported));
411+
*importIdentifier, isExported, AccessLevel(rawAccessLevel)));
410412
else
411413
ImportStatements.push_back(ScannerImportStatementInfo(
412-
*importIdentifier, isExported,
414+
*importIdentifier, isExported, AccessLevel(rawAccessLevel),
413415
ScannerImportStatementInfo::ImportDiagnosticLocationInfo(
414416
*bufferIdentifier, lineNumber, columnNumber)));
415417
break;
@@ -1427,15 +1429,17 @@ unsigned ModuleDependenciesCacheSerializer::writeImportStatementInfos(
14271429
ImportStatementLayout::emitRecord(
14281430
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
14291431
getIdentifier(importInfo.importIdentifier),
1430-
0, 0, 0, isOptional, importInfo.isExported);
1432+
0, 0, 0, isOptional, importInfo.isExported,
1433+
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
14311434
count++;
14321435
} else {
14331436
for (auto &importLoc : importInfo.importLocations) {
14341437
ImportStatementLayout::emitRecord(
14351438
Out, ScratchRecord, AbbrCodes[ImportStatementLayout::Code],
14361439
getIdentifier(importInfo.importIdentifier),
14371440
getIdentifier(importLoc.bufferIdentifier), importLoc.lineNumber,
1438-
importLoc.columnNumber, isOptional, importInfo.isExported);
1441+
importLoc.columnNumber, isOptional, importInfo.isExported,
1442+
static_cast<std::underlying_type<AccessLevel>::type>(importInfo.accessLevel));
14391443
count++;
14401444
}
14411445
}

lib/DependencyScan/ModuleDependencyScanner.cpp

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

607607
case ImplicitStdlibKind::Stdlib:
608608
mainDependencies.addModuleImport("Swift", /* isExported */false,
609+
AccessLevel::Public,
609610
&alreadyAddedModules);
610611
break;
611612
}
@@ -614,6 +615,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
614615
for (const auto &import : importInfo.AdditionalUnloadedImports) {
615616
mainDependencies.addModuleImport(import.module.getModulePath(),
616617
import.options.contains(ImportFlags::Exported),
618+
import.accessLevel,
617619
&alreadyAddedModules,
618620
&ScanASTContext.SourceMgr);
619621
}
@@ -623,6 +625,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
623625
mainDependencies.addModuleImport(
624626
import.module.importedModule->getNameStr(),
625627
import.options.contains(ImportFlags::Exported),
628+
import.accessLevel,
626629
&alreadyAddedModules);
627630
}
628631

@@ -636,6 +639,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
636639
if (importInfo.ShouldImportUnderlyingModule) {
637640
mainDependencies.addModuleImport(mainModule->getName().str(),
638641
/* isExported */ true,
642+
AccessLevel::Public,
639643
&alreadyAddedModules);
640644
}
641645

@@ -646,6 +650,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
646650
ScanCompilerInvocation.getTBDGenOptions().embedSymbolsFromModules) {
647651
mainDependencies.addModuleImport(tbdSymbolModule,
648652
/* isExported */ false,
653+
AccessLevel::Public,
649654
&alreadyAddedModules);
650655
}
651656
}
@@ -1010,7 +1015,8 @@ void ModuleDependencyScanner::resolveAllClangModuleDependencies(
10101015
if (importInfo.importIdentifier ==
10111016
ScanASTContext.Id_CxxStdlib.str()) {
10121017
auto canonicalImportInfo = ScannerImportStatementInfo(
1013-
"std", importInfo.isExported, importInfo.importLocations);
1018+
"std", importInfo.isExported, importInfo.accessLevel,
1019+
importInfo.importLocations);
10141020
unresolvedImports.push_back(canonicalImportInfo);
10151021
unresolvedImportIdentifiers.insert(
10161022
canonicalImportInfo.importIdentifier);
@@ -1537,7 +1543,9 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies(
15371543
std::for_each(newOverlays.begin(), newOverlays.end(),
15381544
[&](Identifier modName) {
15391545
dummyMainDependencies.addModuleImport(modName.str(),
1540-
/* isExported */ false);
1546+
/* isExported */ false,
1547+
// TODO: What is the right access level for a cross-import overlay?
1548+
AccessLevel::Public);
15411549
});
15421550

15431551
// 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)