@@ -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,
@@ -924,7 +921,14 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
924921 }
925922
926923 void addContainedByRelationIfContained (IndexSymbol &Info) {
927- Containers.forEachActiveContainer ([&](const Decl *D) {
924+ // Only consider the innermost container that we are allowed to index.
925+ auto allowDecl = [&](const Decl *D) {
926+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
927+ return shouldIndex (VD, /* IsRef*/ true );
928+ }
929+ return true ;
930+ };
931+ Containers.forEachActiveContainer (allowDecl, [&](const Decl *D) {
928932 addRelation (Info, (unsigned )SymbolRole::RelationContainedBy,
929933 const_cast <Decl *>(D));
930934 });
@@ -1044,7 +1048,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
10441048 return {{line, col, inGeneratedBuffer}};
10451049 }
10461050
1047- bool shouldIndex (ValueDecl *D, bool IsRef) const {
1051+ bool shouldIndex (const ValueDecl *D, bool IsRef) const {
10481052 if (D->isImplicit () && isa<VarDecl>(D) && IsRef) {
10491053 // Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
10501054 // canonical VarDecl for these checks instead.
0 commit comments