Skip to content

Commit 791e2cd

Browse files
committed
Requestify computation of break/continue targets
Introduce BreakTargetRequest and ContinueTargetRequest that perform the ASTScope lookup for the target of a break or continue.
1 parent 2b248f9 commit 791e2cd

File tree

7 files changed

+106
-52
lines changed

7 files changed

+106
-52
lines changed

include/swift/AST/Stmt.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class AnyPattern;
3434
class ASTContext;
3535
class ASTWalker;
3636
class Decl;
37+
class DeclContext;
3738
class Expr;
3839
class FuncDecl;
3940
class Pattern;
@@ -1336,13 +1337,13 @@ class BreakStmt : public Stmt {
13361337
SourceLoc Loc;
13371338
Identifier TargetName; // Named target statement, if specified in the source.
13381339
SourceLoc TargetLoc;
1339-
LabeledStmt *Target = nullptr; // Target stmt, wired up by Sema.
1340+
DeclContext *DC;
1341+
13401342
public:
13411343
BreakStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
1342-
Optional<bool> implicit = None)
1344+
DeclContext *DC, Optional<bool> implicit = None)
13431345
: Stmt(StmtKind::Break, getDefaultImplicitFlag(implicit, Loc)), Loc(Loc),
1344-
TargetName(TargetName), TargetLoc(TargetLoc) {
1345-
}
1346+
TargetName(TargetName), TargetLoc(TargetLoc), DC(DC) {}
13461347

13471348
SourceLoc getLoc() const { return Loc; }
13481349

@@ -1351,16 +1352,16 @@ class BreakStmt : public Stmt {
13511352
SourceLoc getTargetLoc() const { return TargetLoc; }
13521353
void setTargetLoc(SourceLoc L) { TargetLoc = L; }
13531354

1354-
// Manipulate the target loop/switch that is bring broken out of. This is set
1355-
// by sema during type checking.
1356-
void setTarget(LabeledStmt *LS) { Target = LS; }
1357-
LabeledStmt *getTarget() const { return Target; }
1355+
/// Retrieve the target statement being jumped out of.
1356+
LabeledStmt *getTarget() const;
13581357

13591358
SourceLoc getStartLoc() const { return Loc; }
13601359
SourceLoc getEndLoc() const {
13611360
return (TargetLoc.isValid() ? TargetLoc : Loc);
13621361
}
13631362

1363+
DeclContext *getDeclContext() const { return DC; }
1364+
13641365
static bool classof(const Stmt *S) {
13651366
return S->getKind() == StmtKind::Break;
13661367
}
@@ -1371,24 +1372,21 @@ class ContinueStmt : public Stmt {
13711372
SourceLoc Loc;
13721373
Identifier TargetName; // Named target statement, if specified in the source.
13731374
SourceLoc TargetLoc;
1374-
LabeledStmt *Target = nullptr;
1375+
DeclContext *DC;
13751376

13761377
public:
13771378
ContinueStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
1378-
Optional<bool> implicit = None)
1379+
DeclContext *DC, Optional<bool> implicit = None)
13791380
: Stmt(StmtKind::Continue, getDefaultImplicitFlag(implicit, Loc)), Loc(Loc),
1380-
TargetName(TargetName), TargetLoc(TargetLoc) {
1381-
}
1381+
TargetName(TargetName), TargetLoc(TargetLoc), DC(DC) {}
13821382

13831383
Identifier getTargetName() const { return TargetName; }
13841384
void setTargetName(Identifier N) { TargetName = N; }
13851385
SourceLoc getTargetLoc() const { return TargetLoc; }
13861386
void setTargetLoc(SourceLoc L) { TargetLoc = L; }
13871387

1388-
// Manipulate the target loop that is bring continued. This is set by sema
1389-
// during type checking.
1390-
void setTarget(LabeledStmt *LS) { Target = LS; }
1391-
LabeledStmt *getTarget() const { return Target; }
1388+
/// Retrieve the target statement being jumped to.
1389+
LabeledStmt *getTarget() const;
13921390

13931391
SourceLoc getLoc() const { return Loc; }
13941392

@@ -1397,6 +1395,8 @@ class ContinueStmt : public Stmt {
13971395
return (TargetLoc.isValid() ? TargetLoc : Loc);
13981396
}
13991397

1398+
DeclContext *getDeclContext() const { return DC; }
1399+
14001400
static bool classof(const Stmt *S) {
14011401
return S->getKind() == StmtKind::Continue;
14021402
}
@@ -1475,7 +1475,9 @@ class PoundAssertStmt : public Stmt {
14751475
}
14761476
};
14771477

1478-
inline void simple_display(llvm::raw_ostream &out, Stmt *S) {
1478+
SourceLoc extractNearestSourceLoc(const Stmt *stmt);
1479+
1480+
inline void simple_display(llvm::raw_ostream &out, const Stmt *S) {
14791481
if (S)
14801482
out << Stmt::getKindName(S->getKind());
14811483
else

include/swift/AST/TypeCheckRequests.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@ namespace swift {
4040
class AbstractStorageDecl;
4141
class AccessorDecl;
4242
enum class AccessorKind;
43+
class BreakStmt;
4344
class ContextualPattern;
45+
class ContinueStmt;
4446
class DefaultArgumentExpr;
4547
class DefaultArgumentType;
4648
class ClosureExpr;
4749
class GenericParamList;
50+
class LabeledStmt;
4851
struct MacroDefinition;
4952
class PrecedenceGroupDecl;
5053
class PropertyWrapperInitializerInfo;
@@ -3699,6 +3702,40 @@ class SynthesizeLocalVariableForTypeWrapperStorage
36993702
bool isCached() const { return true; }
37003703
};
37013704

3705+
/// Lookup the target of a break statement.
3706+
class BreakTargetRequest
3707+
: public SimpleRequest<BreakTargetRequest,
3708+
LabeledStmt *(const BreakStmt *),
3709+
RequestFlags::Cached> {
3710+
public:
3711+
using SimpleRequest::SimpleRequest;
3712+
3713+
private:
3714+
friend SimpleRequest;
3715+
3716+
LabeledStmt *evaluate(Evaluator &evaluator, const BreakStmt *BS) const;
3717+
3718+
public:
3719+
bool isCached() const { return true; }
3720+
};
3721+
3722+
/// Lookup the target of a continue statement.
3723+
class ContinueTargetRequest
3724+
: public SimpleRequest<ContinueTargetRequest,
3725+
LabeledStmt *(const ContinueStmt *),
3726+
RequestFlags::Cached> {
3727+
public:
3728+
using SimpleRequest::SimpleRequest;
3729+
3730+
private:
3731+
friend SimpleRequest;
3732+
3733+
LabeledStmt *evaluate(Evaluator &evaluator, const ContinueStmt *CS) const;
3734+
3735+
public:
3736+
bool isCached() const { return true; }
3737+
};
3738+
37023739
class GetTypeWrapperInitializer
37033740
: public SimpleRequest<GetTypeWrapperInitializer,
37043741
ConstructorDecl *(NominalTypeDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ SWIFT_REQUEST(TypeChecker, SynthesizeTypeWrappedTypeStorageWrapperInitializer,
434434
SWIFT_REQUEST(TypeChecker, SynthesizeLocalVariableForTypeWrapperStorage,
435435
VarDecl *(ConstructorDecl *),
436436
Cached, NoLocationInfo)
437+
SWIFT_REQUEST(TypeChecker, BreakTargetRequest,
438+
LabeledStmt *(const BreakStmt *),
439+
Cached, NoLocationInfo)
440+
SWIFT_REQUEST(TypeChecker, ContinueTargetRequest,
441+
LabeledStmt *(const ContinueStmt *),
442+
Cached, NoLocationInfo)
437443
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
438444
ConstructorDecl *(NominalTypeDecl *),
439445
Cached, NoLocationInfo)

lib/AST/Stmt.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Decl.h"
2121
#include "swift/AST/Expr.h"
2222
#include "swift/AST/Pattern.h"
23+
#include "swift/AST/TypeCheckRequests.h"
2324
#include "swift/Basic/Statistic.h"
2425
#include "llvm/ADT/PointerUnion.h"
2526

@@ -621,6 +622,20 @@ SwitchStmt *SwitchStmt::create(LabeledStmtInfo LabelInfo, SourceLoc SwitchLoc,
621622
return theSwitch;
622623
}
623624

625+
LabeledStmt *BreakStmt::getTarget() const {
626+
auto &eval = getDeclContext()->getASTContext().evaluator;
627+
return evaluateOrDefault(eval, BreakTargetRequest{this}, nullptr);
628+
}
629+
630+
LabeledStmt *ContinueStmt::getTarget() const {
631+
auto &eval = getDeclContext()->getASTContext().evaluator;
632+
return evaluateOrDefault(eval, ContinueTargetRequest{this}, nullptr);
633+
}
634+
635+
SourceLoc swift::extractNearestSourceLoc(const Stmt *S) {
636+
return S->getStartLoc();
637+
}
638+
624639
// See swift/Basic/Statistic.h for declaration: this enables tracing Stmts, is
625640
// defined here to avoid too much layering violation / circular linkage
626641
// dependency.

lib/Parse/ParseStmt.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,8 +682,8 @@ ParserResult<Stmt> Parser::parseStmtBreak() {
682682
Status |= parseOptionalControlTransferTarget(*this, Target, TargetLoc,
683683
StmtKind::Break);
684684

685-
return makeParserResult(Status,
686-
new (Context) BreakStmt(Loc, Target, TargetLoc));
685+
auto *BS = new (Context) BreakStmt(Loc, Target, TargetLoc, CurDeclContext);
686+
return makeParserResult(Status, BS);
687687
}
688688

689689
/// parseStmtContinue
@@ -699,8 +699,8 @@ ParserResult<Stmt> Parser::parseStmtContinue() {
699699
Status |= parseOptionalControlTransferTarget(*this, Target, TargetLoc,
700700
StmtKind::Continue);
701701

702-
return makeParserResult(Status,
703-
new (Context) ContinueStmt(Loc, Target, TargetLoc));
702+
auto *CS = new (Context) ContinueStmt(Loc, Target, TargetLoc, CurDeclContext);
703+
return makeParserResult(Status, CS);
704704
}
705705

706706

lib/Sema/CSSyntacticElement.cpp

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,27 +1342,14 @@ class SyntacticElementSolutionApplication
13421342
}
13431343

13441344
ASTNode visitBreakStmt(BreakStmt *breakStmt) {
1345-
auto *DC = context.getAsDeclContext();
1346-
if (auto target = findBreakOrContinueStmtTarget(
1347-
DC->getASTContext(), DC->getParentSourceFile(), breakStmt->getLoc(),
1348-
breakStmt->getTargetName(), breakStmt->getTargetLoc(),
1349-
/*isContinue=*/false, context.getAsDeclContext())) {
1350-
breakStmt->setTarget(target);
1351-
}
1352-
1345+
// Force the target to be computed in case it produces diagnostics.
1346+
(void)breakStmt->getTarget();
13531347
return breakStmt;
13541348
}
13551349

13561350
ASTNode visitContinueStmt(ContinueStmt *continueStmt) {
1357-
auto *DC = context.getAsDeclContext();
1358-
if (auto target = findBreakOrContinueStmtTarget(
1359-
DC->getASTContext(), DC->getParentSourceFile(),
1360-
continueStmt->getLoc(), continueStmt->getTargetName(),
1361-
continueStmt->getTargetLoc(), /*isContinue=*/true,
1362-
context.getAsDeclContext())) {
1363-
continueStmt->setTarget(target);
1364-
}
1365-
1351+
// Force the target to be computed in case it produces diagnostics.
1352+
(void)continueStmt->getTarget();
13661353
return continueStmt;
13671354
}
13681355

lib/Sema/TypeCheckStmt.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,23 @@ LabeledStmt *swift::findBreakOrContinueStmtTarget(
437437
return nullptr;
438438
}
439439

440+
LabeledStmt *
441+
BreakTargetRequest::evaluate(Evaluator &evaluator, const BreakStmt *BS) const {
442+
auto *DC = BS->getDeclContext();
443+
return findBreakOrContinueStmtTarget(
444+
DC->getASTContext(), DC->getParentSourceFile(), BS->getLoc(),
445+
BS->getTargetName(), BS->getTargetLoc(), /*isContinue*/ false, DC);
446+
}
447+
448+
LabeledStmt *
449+
ContinueTargetRequest::evaluate(Evaluator &evaluator,
450+
const ContinueStmt *CS) const {
451+
auto *DC = CS->getDeclContext();
452+
return findBreakOrContinueStmtTarget(
453+
DC->getASTContext(), DC->getParentSourceFile(), CS->getLoc(),
454+
CS->getTargetName(), CS->getTargetLoc(), /*isContinue*/ true, DC);
455+
}
456+
440457
static Expr *getDeclRefProvidingExpressionForHasSymbol(Expr *E) {
441458
// Strip coercions, which are necessary in source to disambiguate overloaded
442459
// functions or generic functions, e.g.
@@ -1030,24 +1047,14 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
10301047
}
10311048

10321049
Stmt *visitBreakStmt(BreakStmt *S) {
1033-
if (auto target = findBreakOrContinueStmtTarget(
1034-
getASTContext(), DC->getParentSourceFile(), S->getLoc(),
1035-
S->getTargetName(), S->getTargetLoc(), /*isContinue=*/false,
1036-
DC)) {
1037-
S->setTarget(target);
1038-
}
1039-
1050+
// Force the target to be computed in case it produces diagnostics.
1051+
(void)S->getTarget();
10401052
return S;
10411053
}
10421054

10431055
Stmt *visitContinueStmt(ContinueStmt *S) {
1044-
if (auto target = findBreakOrContinueStmtTarget(
1045-
getASTContext(), DC->getParentSourceFile(), S->getLoc(),
1046-
S->getTargetName(), S->getTargetLoc(), /*isContinue=*/true,
1047-
DC)) {
1048-
S->setTarget(target);
1049-
}
1050-
1056+
// Force the target to be computed in case it produces diagnostics.
1057+
(void)S->getTarget();
10511058
return S;
10521059
}
10531060

0 commit comments

Comments
 (0)