@@ -1003,21 +1003,22 @@ class ForEachStmt : public LabeledStmt {
10031003 SourceLoc WhereLoc;
10041004 Expr *WhereExpr = nullptr ;
10051005 BraceStmt *Body;
1006+ DeclContext* DC = nullptr ;
10061007
10071008 // Set by Sema:
10081009 ProtocolConformanceRef sequenceConformance = ProtocolConformanceRef();
10091010 Type sequenceType;
1010- PatternBindingDecl *iteratorVar = nullptr ;
1011- Expr *nextCall = nullptr ;
1012- OpaqueValueExpr *elementExpr = nullptr ;
1011+ BraceStmt *desugaredStmt = nullptr ;
10131012 Expr *convertElementExpr = nullptr ;
1013+ LabeledStmt *continueTarget = nullptr ;
1014+ LabeledStmt *breakTarget = nullptr ;
10141015
10151016public:
10161017 ForEachStmt (LabeledStmtInfo LabelInfo, SourceLoc ForLoc, SourceLoc TryLoc,
10171018 SourceLoc AwaitLoc, SourceLoc UnsafeLoc, Pattern *Pat,
10181019 SourceLoc InLoc, Expr *Sequence,
10191020 SourceLoc WhereLoc, Expr *WhereExpr, BraceStmt *Body,
1020- std::optional<bool > implicit = std::nullopt )
1021+ DeclContext* DC, std::optional<bool > implicit = std::nullopt )
10211022 : LabeledStmt(StmtKind::ForEach, getDefaultImplicitFlag(implicit, ForLoc),
10221023 LabelInfo),
10231024 ForLoc (ForLoc), TryLoc(TryLoc), AwaitLoc(AwaitLoc), UnsafeLoc(UnsafeLoc),
@@ -1026,15 +1027,6 @@ class ForEachStmt : public LabeledStmt {
10261027 setPattern (Pat);
10271028 }
10281029
1029- void setIteratorVar (PatternBindingDecl *var) { iteratorVar = var; }
1030- PatternBindingDecl *getIteratorVar () const { return iteratorVar; }
1031-
1032- void setNextCall (Expr *next) { nextCall = next; }
1033- Expr *getNextCall () const { return nextCall; }
1034-
1035- void setElementExpr (OpaqueValueExpr *expr) { elementExpr = expr; }
1036- OpaqueValueExpr *getElementExpr () const { return elementExpr; }
1037-
10381030 void setConvertElementExpr (Expr *expr) { convertElementExpr = expr; }
10391031 Expr *getConvertElementExpr () const { return convertElementExpr; }
10401032
@@ -1076,20 +1068,29 @@ class ForEachStmt : public LabeledStmt {
10761068 Expr *getParsedSequence () const { return Sequence; }
10771069 void setParsedSequence (Expr *S) { Sequence = S; }
10781070
1079- // / Type-checked version of the sequence or nullptr if this statement
1080- // / yet to be type-checked.
1081- Expr *getTypeCheckedSequence () const ;
1082-
10831071 // / getBody - Retrieve the body of the loop.
10841072 BraceStmt *getBody () const { return Body; }
10851073 void setBody (BraceStmt *B) { Body = B; }
10861074
10871075 SourceLoc getStartLoc () const { return getLabelLocOrKeywordLoc (ForLoc); }
10881076 SourceLoc getEndLoc () const { return Body->getEndLoc (); }
1077+
1078+ DeclContext *getDeclContext () const { return DC; }
1079+ void setDeclContext (DeclContext *newDC) { DC = newDC; }
10891080
10901081 static bool classof (const Stmt *S) {
10911082 return S->getKind () == StmtKind::ForEach;
10921083 }
1084+
1085+ BraceStmt* desugar ();
1086+ BraceStmt* getDesugaredStmt () const { return desugaredStmt; }
1087+ void setDesugaredStmt (BraceStmt* newStmt) { desugaredStmt = newStmt; }
1088+
1089+ void setContinueTarget (LabeledStmt *target) { continueTarget = target; }
1090+ LabeledStmt* getContinueTarget () { return continueTarget; }
1091+
1092+ void setBreakTarget (LabeledStmt *target) { breakTarget = target; }
1093+ LabeledStmt* getBreakTarget () { return breakTarget; }
10931094};
10941095
10951096// / A pattern and an optional guard expression used in a 'case' statement.
@@ -1541,6 +1542,31 @@ class DoCatchStmt final
15411542 }
15421543};
15431544
1545+ // / OpaqueStmt - created to serve as an indirection to a ForEachStmt's body
1546+ // / to avoid visiting it twice in the ASTWalker after having desugared the loop.
1547+ // / This ensures we only visit the body once, and this OpaqueStmt will only be
1548+ // / visited to emit the underlying statement in SILGen.
1549+ class OpaqueStmt final : public Stmt {
1550+ SourceLoc StartLoc;
1551+ SourceLoc EndLoc;
1552+ BraceStmt *Body; // FIXME: should I just use Stmt * so that this is more versatile?
1553+ // If not, should the class be renamed to be more specific?
1554+ public:
1555+ OpaqueStmt (BraceStmt* body, SourceLoc startLoc, SourceLoc endLoc)
1556+ : Stmt(StmtKind::Opaque, true /* always implicit*/ ),
1557+ StartLoc (startLoc), EndLoc(endLoc), Body(body) {}
1558+
1559+ SourceLoc getLoc () const { return StartLoc; }
1560+ SourceLoc getStartLoc () const { return StartLoc; }
1561+ SourceLoc getEndLoc () const { return EndLoc; }
1562+
1563+ BraceStmt* getUnderlyingStmt () { return Body; }
1564+
1565+ static bool classof (const Stmt *S) {
1566+ return S->getKind () == StmtKind::Opaque;
1567+ }
1568+ };
1569+
15441570// / BreakStmt - The "break" and "break label" statement.
15451571class BreakStmt : public Stmt {
15461572 SourceLoc Loc;
0 commit comments