@@ -1007,21 +1007,22 @@ class ForEachStmt : public LabeledStmt {
10071007 SourceLoc WhereLoc;
10081008 Expr *WhereExpr = nullptr ;
10091009 BraceStmt *Body;
1010+ DeclContext* DC = nullptr ;
10101011
10111012 // Set by Sema:
10121013 ProtocolConformanceRef sequenceConformance = ProtocolConformanceRef();
10131014 Type sequenceType;
1014- PatternBindingDecl *iteratorVar = nullptr ;
1015- Expr *nextCall = nullptr ;
1016- OpaqueValueExpr *elementExpr = nullptr ;
1015+ BraceStmt *desugaredStmt = nullptr ;
10171016 Expr *convertElementExpr = nullptr ;
1017+ LabeledStmt *continueTarget = nullptr ;
1018+ LabeledStmt *breakTarget = nullptr ;
10181019
10191020public:
10201021 ForEachStmt (LabeledStmtInfo LabelInfo, SourceLoc ForLoc, SourceLoc TryLoc,
10211022 SourceLoc AwaitLoc, SourceLoc UnsafeLoc, Pattern *Pat,
10221023 SourceLoc InLoc, Expr *Sequence,
10231024 SourceLoc WhereLoc, Expr *WhereExpr, BraceStmt *Body,
1024- std::optional<bool > implicit = std::nullopt )
1025+ DeclContext* DC, std::optional<bool > implicit = std::nullopt )
10251026 : LabeledStmt(StmtKind::ForEach, getDefaultImplicitFlag(implicit, ForLoc),
10261027 LabelInfo),
10271028 ForLoc (ForLoc), TryLoc(TryLoc), AwaitLoc(AwaitLoc), UnsafeLoc(UnsafeLoc),
@@ -1030,15 +1031,6 @@ class ForEachStmt : public LabeledStmt {
10301031 setPattern (Pat);
10311032 }
10321033
1033- void setIteratorVar (PatternBindingDecl *var) { iteratorVar = var; }
1034- PatternBindingDecl *getIteratorVar () const { return iteratorVar; }
1035-
1036- void setNextCall (Expr *next) { nextCall = next; }
1037- Expr *getNextCall () const { return nextCall; }
1038-
1039- void setElementExpr (OpaqueValueExpr *expr) { elementExpr = expr; }
1040- OpaqueValueExpr *getElementExpr () const { return elementExpr; }
1041-
10421034 void setConvertElementExpr (Expr *expr) { convertElementExpr = expr; }
10431035 Expr *getConvertElementExpr () const { return convertElementExpr; }
10441036
@@ -1080,20 +1072,29 @@ class ForEachStmt : public LabeledStmt {
10801072 Expr *getParsedSequence () const { return Sequence; }
10811073 void setParsedSequence (Expr *S) { Sequence = S; }
10821074
1083- // / Type-checked version of the sequence or nullptr if this statement
1084- // / yet to be type-checked.
1085- Expr *getTypeCheckedSequence () const ;
1086-
10871075 // / getBody - Retrieve the body of the loop.
10881076 BraceStmt *getBody () const { return Body; }
10891077 void setBody (BraceStmt *B) { Body = B; }
10901078
10911079 SourceLoc getStartLoc () const { return getLabelLocOrKeywordLoc (ForLoc); }
10921080 SourceLoc getEndLoc () const { return Body->getEndLoc (); }
1081+
1082+ DeclContext *getDeclContext () const { return DC; }
1083+ void setDeclContext (DeclContext *newDC) { DC = newDC; }
10931084
10941085 static bool classof (const Stmt *S) {
10951086 return S->getKind () == StmtKind::ForEach;
10961087 }
1088+
1089+ BraceStmt* desugar ();
1090+ BraceStmt* getDesugaredStmt () const { return desugaredStmt; }
1091+ void setDesugaredStmt (BraceStmt* newStmt) { desugaredStmt = newStmt; }
1092+
1093+ void setContinueTarget (LabeledStmt *target) { continueTarget = target; }
1094+ LabeledStmt* getContinueTarget () { return continueTarget; }
1095+
1096+ void setBreakTarget (LabeledStmt *target) { breakTarget = target; }
1097+ LabeledStmt* getBreakTarget () { return breakTarget; }
10971098};
10981099
10991100// / A pattern and an optional guard expression used in a 'case' statement.
@@ -1545,6 +1546,31 @@ class DoCatchStmt final
15451546 }
15461547};
15471548
1549+ // / OpaqueStmt - created to serve as an indirection to a ForEachStmt's body
1550+ // / to avoid visiting it twice in the ASTWalker after having desugared the loop.
1551+ // / This ensures we only visit the body once, and this OpaqueStmt will only be
1552+ // / visited to emit the underlying statement in SILGen.
1553+ class OpaqueStmt final : public Stmt {
1554+ SourceLoc StartLoc;
1555+ SourceLoc EndLoc;
1556+ BraceStmt *Body; // FIXME: should I just use Stmt * so that this is more versatile?
1557+ // If not, should the class be renamed to be more specific?
1558+ public:
1559+ OpaqueStmt (BraceStmt* body, SourceLoc startLoc, SourceLoc endLoc)
1560+ : Stmt(StmtKind::Opaque, true /* always implicit*/ ),
1561+ StartLoc (startLoc), EndLoc(endLoc), Body(body) {}
1562+
1563+ SourceLoc getLoc () const { return StartLoc; }
1564+ SourceLoc getStartLoc () const { return StartLoc; }
1565+ SourceLoc getEndLoc () const { return EndLoc; }
1566+
1567+ BraceStmt* getUnderlyingStmt () { return Body; }
1568+
1569+ static bool classof (const Stmt *S) {
1570+ return S->getKind () == StmtKind::Opaque;
1571+ }
1572+ };
1573+
15481574// / BreakStmt - The "break" and "break label" statement.
15491575class BreakStmt : public Stmt {
15501576 SourceLoc Loc;
0 commit comments