Skip to content

Commit d52a044

Browse files
authored
Merge pull request #62338 from hamishknight/break-it-down-for-me
2 parents b3ad462 + 791e2cd commit d52a044

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;
@@ -1343,13 +1344,13 @@ class BreakStmt : public Stmt {
13431344
SourceLoc Loc;
13441345
Identifier TargetName; // Named target statement, if specified in the source.
13451346
SourceLoc TargetLoc;
1346-
LabeledStmt *Target = nullptr; // Target stmt, wired up by Sema.
1347+
DeclContext *DC;
1348+
13471349
public:
13481350
BreakStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
1349-
Optional<bool> implicit = None)
1351+
DeclContext *DC, Optional<bool> implicit = None)
13501352
: Stmt(StmtKind::Break, getDefaultImplicitFlag(implicit, Loc)), Loc(Loc),
1351-
TargetName(TargetName), TargetLoc(TargetLoc) {
1352-
}
1353+
TargetName(TargetName), TargetLoc(TargetLoc), DC(DC) {}
13531354

13541355
SourceLoc getLoc() const { return Loc; }
13551356

@@ -1358,16 +1359,16 @@ class BreakStmt : public Stmt {
13581359
SourceLoc getTargetLoc() const { return TargetLoc; }
13591360
void setTargetLoc(SourceLoc L) { TargetLoc = L; }
13601361

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

13661365
SourceLoc getStartLoc() const { return Loc; }
13671366
SourceLoc getEndLoc() const {
13681367
return (TargetLoc.isValid() ? TargetLoc : Loc);
13691368
}
13701369

1370+
DeclContext *getDeclContext() const { return DC; }
1371+
13711372
static bool classof(const Stmt *S) {
13721373
return S->getKind() == StmtKind::Break;
13731374
}
@@ -1378,24 +1379,21 @@ class ContinueStmt : public Stmt {
13781379
SourceLoc Loc;
13791380
Identifier TargetName; // Named target statement, if specified in the source.
13801381
SourceLoc TargetLoc;
1381-
LabeledStmt *Target = nullptr;
1382+
DeclContext *DC;
13821383

13831384
public:
13841385
ContinueStmt(SourceLoc Loc, Identifier TargetName, SourceLoc TargetLoc,
1385-
Optional<bool> implicit = None)
1386+
DeclContext *DC, Optional<bool> implicit = None)
13861387
: Stmt(StmtKind::Continue, getDefaultImplicitFlag(implicit, Loc)), Loc(Loc),
1387-
TargetName(TargetName), TargetLoc(TargetLoc) {
1388-
}
1388+
TargetName(TargetName), TargetLoc(TargetLoc), DC(DC) {}
13891389

13901390
Identifier getTargetName() const { return TargetName; }
13911391
void setTargetName(Identifier N) { TargetName = N; }
13921392
SourceLoc getTargetLoc() const { return TargetLoc; }
13931393
void setTargetLoc(SourceLoc L) { TargetLoc = L; }
13941394

1395-
// Manipulate the target loop that is bring continued. This is set by sema
1396-
// during type checking.
1397-
void setTarget(LabeledStmt *LS) { Target = LS; }
1398-
LabeledStmt *getTarget() const { return Target; }
1395+
/// Retrieve the target statement being jumped to.
1396+
LabeledStmt *getTarget() const;
13991397

14001398
SourceLoc getLoc() const { return Loc; }
14011399

@@ -1404,6 +1402,8 @@ class ContinueStmt : public Stmt {
14041402
return (TargetLoc.isValid() ? TargetLoc : Loc);
14051403
}
14061404

1405+
DeclContext *getDeclContext() const { return DC; }
1406+
14071407
static bool classof(const Stmt *S) {
14081408
return S->getKind() == StmtKind::Continue;
14091409
}
@@ -1482,7 +1482,9 @@ class PoundAssertStmt : public Stmt {
14821482
}
14831483
};
14841484

1485-
inline void simple_display(llvm::raw_ostream &out, Stmt *S) {
1485+
SourceLoc extractNearestSourceLoc(const Stmt *stmt);
1486+
1487+
inline void simple_display(llvm::raw_ostream &out, const Stmt *S) {
14861488
if (S)
14871489
out << Stmt::getKindName(S->getKind());
14881490
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

@@ -629,6 +630,20 @@ SwitchStmt *SwitchStmt::create(LabeledStmtInfo LabelInfo, SourceLoc SwitchLoc,
629630
return theSwitch;
630631
}
631632

633+
LabeledStmt *BreakStmt::getTarget() const {
634+
auto &eval = getDeclContext()->getASTContext().evaluator;
635+
return evaluateOrDefault(eval, BreakTargetRequest{this}, nullptr);
636+
}
637+
638+
LabeledStmt *ContinueStmt::getTarget() const {
639+
auto &eval = getDeclContext()->getASTContext().evaluator;
640+
return evaluateOrDefault(eval, ContinueTargetRequest{this}, nullptr);
641+
}
642+
643+
SourceLoc swift::extractNearestSourceLoc(const Stmt *S) {
644+
return S->getStartLoc();
645+
}
646+
632647
// See swift/Basic/Statistic.h for declaration: this enables tracing Stmts, is
633648
// defined here to avoid too much layering violation / circular linkage
634649
// 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)