@@ -39,6 +39,10 @@ class FindCapturedVars : public ASTWalker {
3939 SmallVector<CapturedValue, 4 > Captures;
4040 llvm::SmallDenseMap<ValueDecl*, unsigned , 4 > captureEntryNumber;
4141
42+ // / We track the pack expansion expressions in ForEachStmts, because
43+ // / their local generics remain in scope until the end of the statement.
44+ llvm::DenseSet<PackExpansionExpr *> ForEachPatternSequences;
45+
4246 // / A stack of pack element environments we're currently walking into.
4347 // / A reference to an element archetype defined by one of these is not
4448 // / a capture.
@@ -652,13 +656,52 @@ class FindCapturedVars : public ASTWalker {
652656 if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
653657 if (auto *env = expansion->getGenericEnvironment ()) {
654658 assert (env == VisitingEnvironments.back ());
655- VisitingEnvironments.pop_back ();
656659 (void ) env;
660+
661+ // If this is the pack expansion of a for .. in loop, the generic
662+ // environment remains in scope until the end of the loop.
663+ if (ForEachPatternSequences.count (expansion) == 0 )
664+ VisitingEnvironments.pop_back ();
657665 }
658666 }
659667
660668 return Action::Continue (E);
661669 }
670+
671+ PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
672+ if (auto *forEachStmt = dyn_cast<ForEachStmt>(S)) {
673+ if (auto *expansion =
674+ dyn_cast<PackExpansionExpr>(forEachStmt->getParsedSequence ())) {
675+ if (auto *env = expansion->getGenericEnvironment ()) {
676+ // Remember this generic environment, so that it remains on the
677+ // visited stack until the end of the for .. in loop.
678+ assert (ForEachPatternSequences.count (expansion) == 0 );
679+ ForEachPatternSequences.insert (expansion);
680+ }
681+ }
682+ }
683+
684+ return Action::Continue (S);
685+ }
686+
687+ PostWalkResult<Stmt *> walkToStmtPost (Stmt *S) override {
688+ if (auto *forEachStmt = dyn_cast<ForEachStmt>(S)) {
689+ if (auto *expansion =
690+ dyn_cast<PackExpansionExpr>(forEachStmt->getParsedSequence ())) {
691+ if (auto *env = expansion->getGenericEnvironment ()) {
692+ assert (ForEachPatternSequences.count (expansion) != 0 );
693+ ForEachPatternSequences.erase (expansion);
694+
695+ // Clean up the generic environment bound by the for loop.
696+ assert (env == VisitingEnvironments.back ());
697+ VisitingEnvironments.pop_back ();
698+ (void ) env;
699+ }
700+ }
701+ }
702+
703+ return Action::Continue (S);
704+ }
662705};
663706
664707} // end anonymous namespace
0 commit comments