Skip to content

Commit 1ee7672

Browse files
committed
[Multi-expression closures] Add support for break & continue statements.
1 parent 0198a70 commit 1ee7672

File tree

4 files changed

+49
-5
lines changed

4 files changed

+49
-5
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ class ClosureConstraintGenerator
172172
visit(whileStmt->getBody());
173173
}
174174

175+
void visitBreakStmt(BreakStmt *breakStmt) { }
176+
void visitContinueStmt(ContinueStmt *continueStmt) { }
177+
175178
#define UNSUPPORTED_STMT(STMT) void visit##STMT##Stmt(STMT##Stmt *) { \
176179
llvm_unreachable("Unsupported statement kind " #STMT); \
177180
}
@@ -180,8 +183,6 @@ class ClosureConstraintGenerator
180183
UNSUPPORTED_STMT(DoCatch)
181184
UNSUPPORTED_STMT(Switch)
182185
UNSUPPORTED_STMT(Case)
183-
UNSUPPORTED_STMT(Break)
184-
UNSUPPORTED_STMT(Continue)
185186
UNSUPPORTED_STMT(Fallthrough)
186187
UNSUPPORTED_STMT(Fail)
187188
UNSUPPORTED_STMT(Throw)
@@ -213,6 +214,10 @@ class ClosureConstraintApplication
213214
RewriteTargetFn rewriteTarget;
214215
bool isSingleExpression;
215216

217+
ASTContext &getASTContext() const {
218+
return solution.getConstraintSystem().getASTContext();
219+
}
220+
216221
public:
217222
/// Whether an error was encountered while generating constraints.
218223
bool hadError = false;
@@ -412,6 +417,29 @@ class ClosureConstraintApplication
412417
return whileStmt;
413418
}
414419

420+
ASTNode visitBreakStmt(BreakStmt *breakStmt) {
421+
if (auto target = findBreakOrContinueStmtTarget(
422+
getASTContext(), closure->getParentSourceFile(), breakStmt->getLoc(),
423+
breakStmt->getTargetName(), breakStmt->getTargetLoc(),
424+
/*isContinue=*/false, closure, { })) {
425+
breakStmt->setTarget(target);
426+
}
427+
428+
return breakStmt;
429+
}
430+
431+
ASTNode visitContinueStmt(ContinueStmt *continueStmt) {
432+
if (auto target = findBreakOrContinueStmtTarget(
433+
getASTContext(), closure->getParentSourceFile(),
434+
continueStmt->getLoc(), continueStmt->getTargetName(),
435+
continueStmt->getTargetLoc(), /*isContinue=*/true,
436+
closure, { })) {
437+
continueStmt->setTarget(target);
438+
}
439+
440+
return continueStmt;
441+
}
442+
415443
#define UNSUPPORTED_STMT(STMT) ASTNode visit##STMT##Stmt(STMT##Stmt *) { \
416444
llvm_unreachable("Unsupported statement kind " #STMT); \
417445
}
@@ -420,8 +448,6 @@ class ClosureConstraintApplication
420448
UNSUPPORTED_STMT(DoCatch)
421449
UNSUPPORTED_STMT(Switch)
422450
UNSUPPORTED_STMT(Case)
423-
UNSUPPORTED_STMT(Break)
424-
UNSUPPORTED_STMT(Continue)
425451
UNSUPPORTED_STMT(Fallthrough)
426452
UNSUPPORTED_STMT(Fail)
427453
UNSUPPORTED_STMT(Throw)

lib/Sema/TypeCheckStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ static LabeledStmt *findUnlabeledBreakOrContinueStmtTarget(
401401
///
402402
/// \returns the target, if one was found, or \c nullptr if no such target
403403
/// exists.
404-
static LabeledStmt *findBreakOrContinueStmtTarget(
404+
LabeledStmt *swift::findBreakOrContinueStmtTarget(
405405
ASTContext &ctx, SourceFile *sourceFile,
406406
SourceLoc loc, Identifier targetName, SourceLoc targetLoc,
407407
bool isContinue, DeclContext *dc,

lib/Sema/TypeChecker.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,16 @@ bool areGenericRequirementsSatisfied(const DeclContext *DC,
13651365
SubstitutionMap Substitutions,
13661366
bool isExtension);
13671367

1368+
/// Find the target of a break or continue statement.
1369+
///
1370+
/// \returns the target, if one was found, or \c nullptr if no such target
1371+
/// exists.
1372+
LabeledStmt *findBreakOrContinueStmtTarget(
1373+
ASTContext &ctx, SourceFile *sourceFile,
1374+
SourceLoc loc, Identifier targetName, SourceLoc targetLoc,
1375+
bool isContinue, DeclContext *dc,
1376+
ArrayRef<LabeledStmt *> oldActiveLabeledStmts);
1377+
13681378
/// Check for restrictions on the use of the @unknown attribute on a
13691379
/// case statement.
13701380
void checkUnknownAttrRestrictions(

test/expr/closure/multi_statement.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,19 @@ func mapWithMoreStatements(ints: [Int]) {
2929
actualValue += 1
3030
}
3131

32+
my_repeat:
3233
repeat {
3334
print("still here")
35+
36+
if i % 7 == 0 {
37+
break my_repeat
38+
}
3439
} while random(i)
3540

3641
for j in 0..<i where j % 2 == 0 {
42+
if j % 7 == 0 {
43+
continue
44+
}
3745
print("even")
3846
}
3947

0 commit comments

Comments
 (0)