@@ -216,26 +216,39 @@ class ContainerTracker {
216216
217217 bool empty () const { return Stack.empty (); }
218218
219- void forEachActiveContainer (llvm::function_ref<void (const Decl *)> f) const {
220- if (Stack.empty ())
221- return ;
222-
223- const StackEntry &Entry = Stack.back ();
224-
225- if (!Entry.ActiveKey )
226- return ;
227-
228- auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
219+ void forEachActiveContainer (llvm::function_ref<bool (const Decl *)> allowDecl,
220+ llvm::function_ref<void(const Decl *)> f) const {
221+ for (const auto &Entry : llvm::reverse (Stack)) {
222+ // No active container, we're done.
223+ if (!Entry.ActiveKey )
224+ return ;
229225
230- if (MapEntry == Entry.Containers .end ())
231- return ;
226+ auto MapEntry = Entry.Containers .find (Entry.ActiveKey );
227+ if (MapEntry == Entry.Containers .end ())
228+ return ;
232229
233- Container C = MapEntry->second ;
230+ bool hadViableContainer = false ;
231+ auto tryContainer = [&](const Decl *D) {
232+ if (!allowDecl (D))
233+ return ;
234234
235- if (auto *D = C.dyn_cast <const Decl *>()) {
236- f (D);
237- } else if (auto *P = C.dyn_cast <const Pattern *>()) {
238- P->forEachVariable ([&](VarDecl *VD) { f (VD); });
235+ f (D);
236+ hadViableContainer = true ;
237+ };
238+ if (auto C = MapEntry->second ) {
239+ if (auto *D = C.dyn_cast <const Decl *>()) {
240+ tryContainer (D);
241+ } else {
242+ auto *P = C.get <const Pattern *>();
243+ P->forEachVariable ([&](VarDecl *VD) {
244+ tryContainer (VD);
245+ });
246+ }
247+ }
248+ // If we had a viable containers, we're done. Otherwise continue walking
249+ // up the stack.
250+ if (hadViableContainer)
251+ return ;
239252 }
240253 }
241254
@@ -343,26 +356,10 @@ class ContainerTracker {
343356 }
344357
345358 // AnyPatterns behave differently to other patterns as they've no associated
346- // VarDecl. The given ActivationKey is therefore associated with the current
347- // active container, if any .
359+ // VarDecl. We store null here, and will walk up to the parent container in
360+ // forEachActiveContainer .
348361 void associateAnyPattern (ActivationKey K, StackEntry &Entry) const {
349- Entry.Containers [K] = activeContainer ();
350- }
351-
352- Container activeContainer () const {
353- if (Stack.empty ())
354- return nullptr ;
355-
356- const StackEntry &Entry = Stack.back ();
357-
358- if (Entry.ActiveKey ) {
359- auto ActiveContainer = Entry.Containers .find (Entry.ActiveKey );
360-
361- if (ActiveContainer != Entry.Containers .end ())
362- return ActiveContainer->second ;
363- }
364-
365- return nullptr ;
362+ Entry.Containers [K] = nullptr ;
366363 }
367364
368365 void associateAllPatternElements (const Pattern *P, ActivationKey K,
@@ -547,6 +544,10 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
547544
548545 bool addRelation (IndexSymbol &Info, SymbolRoleSet RelationRoles, Decl *D) {
549546 assert (D);
547+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
548+ if (!shouldIndex (VD, /* IsRef*/ true ))
549+ return true ;
550+ }
550551 auto Match = std::find_if (Info.Relations .begin (), Info.Relations .end (),
551552 [D](IndexRelation R) { return R.decl == D; });
552553 if (Match != Info.Relations .end ()) {
@@ -924,7 +925,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
924925 }
925926
926927 void addContainedByRelationIfContained (IndexSymbol &Info) {
927- Containers.forEachActiveContainer ([&](const Decl *D) {
928+ // Only consider the innermost container that we are allowed to index.
929+ auto allowDecl = [&](const Decl *D) {
930+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
931+ return shouldIndex (VD, /* IsRef*/ true );
932+ }
933+ return true ;
934+ };
935+ Containers.forEachActiveContainer (allowDecl, [&](const Decl *D) {
928936 addRelation (Info, (unsigned )SymbolRole::RelationContainedBy,
929937 const_cast <Decl *>(D));
930938 });
@@ -1044,7 +1052,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
10441052 return {{line, col, inGeneratedBuffer}};
10451053 }
10461054
1047- bool shouldIndex (ValueDecl *D, bool IsRef) const {
1055+ bool shouldIndex (const ValueDecl *D, bool IsRef) const {
10481056 if (D->isImplicit () && isa<VarDecl>(D) && IsRef) {
10491057 // Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
10501058 // canonical VarDecl for these checks instead.
0 commit comments