@@ -27,15 +27,21 @@ using namespace namelookup;
27
27
28
28
ImportSet::ImportSet (bool hasHeaderImportModule,
29
29
ArrayRef<ImportedModule> topLevelImports,
30
- ArrayRef<ImportedModule> transitiveImports)
30
+ ArrayRef<ImportedModule> transitiveImports,
31
+ ArrayRef<ImportedModule> transitiveSwiftOnlyImports)
31
32
: HasHeaderImportModule(hasHeaderImportModule),
32
33
NumTopLevelImports(topLevelImports.size()),
33
- NumTransitiveImports(transitiveImports.size()) {
34
+ NumTransitiveImports(transitiveImports.size()),
35
+ NumTransitiveSwiftOnlyImports(transitiveSwiftOnlyImports.size()) {
34
36
auto buffer = getTrailingObjects<ImportedModule>();
35
37
std::uninitialized_copy (topLevelImports.begin (), topLevelImports.end (),
36
38
buffer);
37
39
std::uninitialized_copy (transitiveImports.begin (), transitiveImports.end (),
38
40
buffer + topLevelImports.size ());
41
+ std::uninitialized_copy (transitiveSwiftOnlyImports.begin (),
42
+ transitiveSwiftOnlyImports.end (),
43
+ buffer + topLevelImports.size () +
44
+ transitiveImports.size ());
39
45
40
46
#ifndef NDEBUG
41
47
llvm::SmallDenseSet<ImportedModule, 8 > unique;
@@ -47,6 +53,15 @@ ImportSet::ImportSet(bool hasHeaderImportModule,
47
53
auto result = unique.insert (import ).second ;
48
54
assert (result && " Duplicate imports in import set" );
49
55
}
56
+
57
+ unique.clear ();
58
+ for (auto import : topLevelImports) {
59
+ unique.insert (import );
60
+ }
61
+ for (auto import : transitiveSwiftOnlyImports) {
62
+ auto result = unique.insert (import ).second ;
63
+ assert (result && " Duplicate imports in import set" );
64
+ }
50
65
#endif
51
66
}
52
67
@@ -82,10 +97,14 @@ void ImportSet::dump() const {
82
97
}
83
98
84
99
static void collectExports (ImportedModule next,
85
- SmallVectorImpl<ImportedModule> &stack) {
100
+ SmallVectorImpl<ImportedModule> &stack,
101
+ bool onlySwiftExports) {
86
102
SmallVector<ImportedModule, 4 > exports;
87
103
next.importedModule ->getImportedModulesForLookup (exports);
88
104
for (auto exported : exports) {
105
+ if (onlySwiftExports && exported.importedModule ->isNonSwiftModule ())
106
+ continue ;
107
+
89
108
if (next.accessPath .empty ())
90
109
stack.push_back (exported);
91
110
else if (exported.accessPath .empty ()) {
@@ -135,7 +154,7 @@ ImportCache::getImportSet(ASTContext &ctx,
135
154
136
155
SmallVector<ImportedModule, 4 > stack;
137
156
for (auto next : topLevelImports) {
138
- collectExports (next, stack);
157
+ collectExports (next, stack, /* onlySwiftExports */ false );
139
158
}
140
159
141
160
while (!stack.empty ()) {
@@ -148,7 +167,26 @@ ImportCache::getImportSet(ASTContext &ctx,
148
167
if (next.importedModule == headerImportModule)
149
168
hasHeaderImportModule = true ;
150
169
151
- collectExports (next, stack);
170
+ collectExports (next, stack, /* onlySwiftExports*/ false );
171
+ }
172
+
173
+ // Now collect transitive imports through Swift reexported imports only.
174
+ SmallVector<ImportedModule, 4 > transitiveSwiftOnlyImports;
175
+ visited.clear ();
176
+ stack.clear ();
177
+ for (auto next : topLevelImports) {
178
+ if (!visited.insert (next).second )
179
+ continue ;
180
+ collectExports (next, stack, /* onlySwiftExports*/ true );
181
+ }
182
+
183
+ while (!stack.empty ()) {
184
+ auto next = stack.pop_back_val ();
185
+ if (!visited.insert (next).second )
186
+ continue ;
187
+
188
+ transitiveSwiftOnlyImports.push_back (next);
189
+ collectExports (next, stack, /* onlySwiftExports*/ true );
152
190
}
153
191
154
192
// Find the insert position again, in case the above traversal invalidated
@@ -157,12 +195,15 @@ ImportCache::getImportSet(ASTContext &ctx,
157
195
if (ImportSet *result = ImportSets.FindNodeOrInsertPos (ID, InsertPos))
158
196
return *result;
159
197
160
- size_t bytes = ImportSet::totalSizeToAlloc<ImportedModule>(topLevelImports.size () + transitiveImports.size ());
198
+ size_t bytes = ImportSet::totalSizeToAlloc<ImportedModule>(
199
+ topLevelImports.size () + transitiveImports.size () +
200
+ transitiveSwiftOnlyImports.size ());
161
201
void *mem = ctx.Allocate (bytes, alignof (ImportSet), AllocationArena::Permanent);
162
202
163
203
auto *result = new (mem) ImportSet (hasHeaderImportModule,
164
204
topLevelImports,
165
- transitiveImports);
205
+ transitiveImports,
206
+ transitiveSwiftOnlyImports);
166
207
ImportSets.InsertNode (result, InsertPos);
167
208
168
209
return *result;
@@ -249,6 +290,36 @@ ImportCache::getAllVisibleAccessPaths(const ModuleDecl *mod,
249
290
return result;
250
291
}
251
292
293
+ bool ImportCache::isImportedByViaSwiftOnly (const ModuleDecl *mod,
294
+ const DeclContext *dc) {
295
+ dc = dc->getModuleScopeContext ();
296
+ if (dc->getParentModule ()->isNonSwiftModule ())
297
+ return false ;
298
+
299
+ auto &ctx = mod->getASTContext ();
300
+ auto key = std::make_pair (mod, dc);
301
+ auto found = SwiftOnlyCache.find (key);
302
+ if (found != SwiftOnlyCache.end ()) {
303
+ if (ctx.Stats )
304
+ ++ctx.Stats ->getFrontendCounters ().ModuleVisibilityCacheHit ;
305
+ return found->second ;
306
+ }
307
+
308
+ if (ctx.Stats )
309
+ ++ctx.Stats ->getFrontendCounters ().ModuleVisibilityCacheMiss ;
310
+
311
+ bool result = false ;
312
+ for (auto next : getImportSet (dc).getTransitiveSwiftOnlyImports ()) {
313
+ if (next.importedModule == mod) {
314
+ result = true ;
315
+ break ;
316
+ }
317
+ }
318
+
319
+ SwiftOnlyCache[key] = result;
320
+ return result;
321
+ }
322
+
252
323
ArrayRef<ImportPath::Access>
253
324
ImportCache::getAllAccessPathsNotShadowedBy (const ModuleDecl *mod,
254
325
const ModuleDecl *other,
@@ -307,7 +378,7 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod,
307
378
accessPaths.push_back (next.accessPath );
308
379
}
309
380
310
- collectExports (next, stack);
381
+ collectExports (next, stack, /* onlySwiftExports */ false );
311
382
}
312
383
313
384
auto result = allocateArray (ctx, accessPaths);
0 commit comments