Skip to content

Commit 78880ff

Browse files
authored
Merge pull request #27776 from owenv/catch_revamp_take_4
[SE-0276] Support multiple patterns in catch clauses
2 parents 31e7873 + 43e2d10 commit 78880ff

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+998
-479
lines changed

include/swift/AST/ASTScope.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,29 +1893,6 @@ class ForEachPatternScope final : public ASTScopeImpl {
18931893
DeclConsumer) const override;
18941894
};
18951895

1896-
class CatchStmtScope final : public AbstractStmtScope {
1897-
public:
1898-
CatchStmt *const stmt;
1899-
CatchStmtScope(CatchStmt *e) : stmt(e) {}
1900-
virtual ~CatchStmtScope() {}
1901-
1902-
protected:
1903-
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
1904-
1905-
private:
1906-
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
1907-
1908-
public:
1909-
std::string getClassName() const override;
1910-
SourceRange
1911-
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
1912-
Stmt *getStmt() const override { return stmt; }
1913-
1914-
protected:
1915-
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
1916-
ASTScopeImpl::DeclConsumer) const override;
1917-
};
1918-
19191896
class CaseStmtScope final : public AbstractStmtScope {
19201897
public:
19211898
CaseStmt *const stmt;

include/swift/AST/NameLookup.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,6 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> {
593593
void visitCaseStmt(CaseStmt *S);
594594

595595
void visitDoCatchStmt(DoCatchStmt *S);
596-
void visitCatchClauses(ArrayRef<CatchStmt*> clauses);
597-
void visitCatchStmt(CatchStmt *S);
598596

599597
};
600598

include/swift/AST/Stmt.h

Lines changed: 94 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -559,105 +559,6 @@ class DoStmt : public LabeledStmt {
559559
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Do; }
560560
};
561561

562-
/// An individual 'catch' clause.
563-
///
564-
/// This isn't really an independent statement any more than CaseStmt
565-
/// is; it's just a structural part of a DoCatchStmt.
566-
class CatchStmt : public Stmt {
567-
SourceLoc CatchLoc;
568-
SourceLoc WhereLoc;
569-
Pattern *ErrorPattern;
570-
Expr *GuardExpr;
571-
Stmt *CatchBody;
572-
573-
public:
574-
CatchStmt(SourceLoc catchLoc, Pattern *errorPattern,
575-
SourceLoc whereLoc, Expr *guardExpr, Stmt *body,
576-
Optional<bool> implicit = None)
577-
: Stmt(StmtKind::Catch, getDefaultImplicitFlag(implicit, catchLoc)),
578-
CatchLoc(catchLoc), WhereLoc(whereLoc),
579-
ErrorPattern(nullptr), GuardExpr(guardExpr), CatchBody(body) {
580-
setErrorPattern(errorPattern);
581-
}
582-
583-
SourceLoc getCatchLoc() const { return CatchLoc; }
584-
585-
/// The location of the 'where' keyword if there's a guard expression.
586-
SourceLoc getWhereLoc() const { return WhereLoc; }
587-
588-
SourceLoc getStartLoc() const { return CatchLoc; }
589-
SourceLoc getEndLoc() const { return CatchBody->getEndLoc(); }
590-
591-
Stmt *getBody() const { return CatchBody; }
592-
void setBody(Stmt *body) { CatchBody = body; }
593-
594-
Pattern *getErrorPattern() { return ErrorPattern; }
595-
const Pattern *getErrorPattern() const { return ErrorPattern; }
596-
void setErrorPattern(Pattern *pattern);
597-
598-
/// Is this catch clause "syntactically exhaustive"?
599-
bool isSyntacticallyExhaustive() const;
600-
601-
/// Return the guard expression if present, or null if the catch has
602-
/// no guard.
603-
Expr *getGuardExpr() const { return GuardExpr; }
604-
void setGuardExpr(Expr *guard) { GuardExpr = guard; }
605-
606-
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Catch; }
607-
};
608-
609-
/// DoCatchStmt - do statement with trailing 'catch' clauses.
610-
class DoCatchStmt final : public LabeledStmt,
611-
private llvm::TrailingObjects<DoCatchStmt, CatchStmt *> {
612-
friend TrailingObjects;
613-
614-
SourceLoc DoLoc;
615-
Stmt *Body;
616-
617-
DoCatchStmt(LabeledStmtInfo labelInfo, SourceLoc doLoc,
618-
Stmt *body, ArrayRef<CatchStmt*> catches,
619-
Optional<bool> implicit)
620-
: LabeledStmt(StmtKind::DoCatch, getDefaultImplicitFlag(implicit, doLoc),
621-
labelInfo), DoLoc(doLoc), Body(body) {
622-
Bits.DoCatchStmt.NumCatches = catches.size();
623-
std::uninitialized_copy(catches.begin(), catches.end(),
624-
getTrailingObjects<CatchStmt *>());
625-
}
626-
627-
public:
628-
static DoCatchStmt *create(ASTContext &ctx, LabeledStmtInfo labelInfo,
629-
SourceLoc doLoc, Stmt *body,
630-
ArrayRef<CatchStmt*> catches,
631-
Optional<bool> implicit = None);
632-
633-
SourceLoc getDoLoc() const { return DoLoc; }
634-
635-
SourceLoc getStartLoc() const { return getLabelLocOrKeywordLoc(DoLoc); }
636-
SourceLoc getEndLoc() const { return getCatches().back()->getEndLoc(); }
637-
638-
Stmt *getBody() const { return Body; }
639-
void setBody(Stmt *s) { Body = s; }
640-
641-
ArrayRef<CatchStmt*> getCatches() const {
642-
return {getTrailingObjects<CatchStmt*>(), Bits.DoCatchStmt.NumCatches};
643-
}
644-
MutableArrayRef<CatchStmt*> getMutableCatches() {
645-
return {getTrailingObjects<CatchStmt*>(), Bits.DoCatchStmt.NumCatches};
646-
}
647-
648-
/// Does this statement contain a syntactically exhaustive catch
649-
/// clause?
650-
///
651-
/// Note that an exhaustive do/catch statement can still throw
652-
/// errors out of its catch block(s).
653-
bool isSyntacticallyExhaustive() const;
654-
655-
static bool classof(const Stmt *S) {
656-
return S->getKind() == StmtKind::DoCatch;
657-
}
658-
};
659-
660-
661562
/// Either an "if let" case or a simple boolean expression can appear as the
662563
/// condition of an 'if' or 'while' statement.
663564
using StmtCondition = MutableArrayRef<StmtConditionElement>;
@@ -962,6 +863,8 @@ class CaseLabelItem {
962863
bool isDefault() const {
963864
return GuardExprAndKind.getInt() == Kind::Default;
964865
}
866+
867+
bool isSyntacticallyExhaustive() const;
965868
};
966869

967870
/// FallthroughStmt - The keyword "fallthrough".
@@ -1003,9 +906,12 @@ class FallthroughStmt : public Stmt {
1003906
}
1004907
};
1005908

1006-
/// A 'case' or 'default' block of a switch statement. Only valid as the
1007-
/// substatement of a SwitchStmt. A case block begins either with one or more
1008-
/// CaseLabelItems or a single 'default' label.
909+
enum CaseParentKind { Switch, DoCatch };
910+
911+
/// A 'case' or 'default' block of a switch statement, or a 'catch' clause of a
912+
/// do-catch statement. Only valid as the substatement of a SwitchStmt or
913+
/// DoCatchStmt. A case block begins either with one or more CaseLabelItems or
914+
/// a single 'default' label.
1009915
///
1010916
/// Some examples:
1011917
/// \code
@@ -1023,28 +929,32 @@ class CaseStmt final
1023929
friend TrailingObjects;
1024930

1025931
SourceLoc UnknownAttrLoc;
1026-
SourceLoc CaseLoc;
1027-
SourceLoc ColonLoc;
932+
SourceLoc ItemIntroducerLoc;
933+
SourceLoc ItemTerminatorLoc;
934+
CaseParentKind ParentKind;
1028935

1029936
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndHasFallthrough;
1030937

1031938
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables;
1032939

1033-
CaseStmt(SourceLoc CaseLoc, ArrayRef<CaseLabelItem> CaseLabelItems,
1034-
SourceLoc UnknownAttrLoc, SourceLoc ColonLoc, Stmt *Body,
940+
CaseStmt(CaseParentKind ParentKind, SourceLoc ItemIntroducerLoc,
941+
ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
942+
SourceLoc ItemTerminatorLoc, Stmt *Body,
1035943
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
1036944
Optional<bool> Implicit,
1037945
NullablePtr<FallthroughStmt> fallthroughStmt);
1038946

1039947
public:
1040948
static CaseStmt *
1041-
create(ASTContext &C, SourceLoc CaseLoc,
949+
create(ASTContext &C, CaseParentKind ParentKind, SourceLoc ItemIntroducerLoc,
1042950
ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
1043-
SourceLoc ColonLoc, Stmt *Body,
951+
SourceLoc ItemTerminatorLoc, Stmt *Body,
1044952
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
1045953
Optional<bool> Implicit = None,
1046954
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
1047955

956+
CaseParentKind getParentKind() const { return ParentKind; }
957+
1048958
ArrayRef<CaseLabelItem> getCaseLabelItems() const {
1049959
return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt.NumPatterns};
1050960
}
@@ -1073,17 +983,38 @@ class CaseStmt final
1073983
/// True if the case block declares any patterns with local variable bindings.
1074984
bool hasBoundDecls() const { return CaseBodyVariables.hasValue(); }
1075985

1076-
/// Get the source location of the 'case' or 'default' of the first label.
1077-
SourceLoc getLoc() const { return CaseLoc; }
986+
/// Get the source location of the 'case', 'default', or 'catch' of the first
987+
/// label.
988+
SourceLoc getLoc() const { return ItemIntroducerLoc; }
1078989

1079990
SourceLoc getStartLoc() const {
1080991
if (UnknownAttrLoc.isValid())
1081992
return UnknownAttrLoc;
1082993
return getLoc();
1083994
}
1084995
SourceLoc getEndLoc() const { return getBody()->getEndLoc(); }
996+
1085997
SourceRange getLabelItemsRange() const {
1086-
return ColonLoc.isValid() ? SourceRange(getLoc(), ColonLoc) : getSourceRange();
998+
switch (ParentKind) {
999+
case CaseParentKind::Switch:
1000+
// The range extends from 'case' to the colon at the end.
1001+
return ItemTerminatorLoc.isValid()
1002+
? SourceRange(getLoc(), ItemTerminatorLoc)
1003+
: getSourceRange();
1004+
case CaseParentKind::DoCatch: {
1005+
// The range extends from 'catch' to the end of the last non-implicit
1006+
// item.
1007+
auto items = getCaseLabelItems();
1008+
for (auto item = items.rbegin(), end = items.rend(); item != end;
1009+
++item) {
1010+
auto itemEndLoc = item->getEndLoc();
1011+
if (itemEndLoc.isValid())
1012+
return SourceRange(getLoc(), itemEndLoc);
1013+
}
1014+
// Handle the 'catch {' case.
1015+
return SourceRange(getLoc(), getLoc());
1016+
}
1017+
}
10871018
}
10881019

10891020
bool isDefault() { return getCaseLabelItems()[0].isDefault(); }
@@ -1213,6 +1144,58 @@ class SwitchStmt final : public LabeledStmt,
12131144
}
12141145
};
12151146

1147+
/// DoCatchStmt - do statement with trailing 'catch' clauses.
1148+
class DoCatchStmt final
1149+
: public LabeledStmt,
1150+
private llvm::TrailingObjects<DoCatchStmt, CaseStmt *> {
1151+
friend TrailingObjects;
1152+
1153+
SourceLoc DoLoc;
1154+
Stmt *Body;
1155+
1156+
DoCatchStmt(LabeledStmtInfo labelInfo, SourceLoc doLoc, Stmt *body,
1157+
ArrayRef<CaseStmt *> catches, Optional<bool> implicit)
1158+
: LabeledStmt(StmtKind::DoCatch, getDefaultImplicitFlag(implicit, doLoc),
1159+
labelInfo),
1160+
DoLoc(doLoc), Body(body) {
1161+
Bits.DoCatchStmt.NumCatches = catches.size();
1162+
std::uninitialized_copy(catches.begin(), catches.end(),
1163+
getTrailingObjects<CaseStmt *>());
1164+
}
1165+
1166+
public:
1167+
static DoCatchStmt *create(ASTContext &ctx, LabeledStmtInfo labelInfo,
1168+
SourceLoc doLoc, Stmt *body,
1169+
ArrayRef<CaseStmt *> catches,
1170+
Optional<bool> implicit = None);
1171+
1172+
SourceLoc getDoLoc() const { return DoLoc; }
1173+
1174+
SourceLoc getStartLoc() const { return getLabelLocOrKeywordLoc(DoLoc); }
1175+
SourceLoc getEndLoc() const { return getCatches().back()->getEndLoc(); }
1176+
1177+
Stmt *getBody() const { return Body; }
1178+
void setBody(Stmt *s) { Body = s; }
1179+
1180+
ArrayRef<CaseStmt *> getCatches() const {
1181+
return {getTrailingObjects<CaseStmt *>(), Bits.DoCatchStmt.NumCatches};
1182+
}
1183+
MutableArrayRef<CaseStmt *> getMutableCatches() {
1184+
return {getTrailingObjects<CaseStmt *>(), Bits.DoCatchStmt.NumCatches};
1185+
}
1186+
1187+
/// Does this statement contain a syntactically exhaustive catch
1188+
/// clause?
1189+
///
1190+
/// Note that an exhaustive do/catch statement can still throw
1191+
/// errors out of its catch block(s).
1192+
bool isSyntacticallyExhaustive() const;
1193+
1194+
static bool classof(const Stmt *S) {
1195+
return S->getKind() == StmtKind::DoCatch;
1196+
}
1197+
};
1198+
12161199
/// BreakStmt - The "break" and "break label" statement.
12171200
class BreakStmt : public Stmt {
12181201
SourceLoc Loc;

include/swift/AST/StmtNodes.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ ABSTRACT_STMT(Labeled, Stmt)
6161
LABELED_STMT(Switch, LabeledStmt)
6262
STMT_RANGE(Labeled, If, Switch)
6363
STMT(Case, Stmt)
64-
STMT(Catch, Stmt)
6564
STMT(Break, Stmt)
6665
STMT(Continue, Stmt)
6766
STMT(Fallthrough, Stmt)

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ class Parser {
16171617
ParserResult<Stmt> parseStmtRepeat(LabeledStmtInfo LabelInfo);
16181618
ParserResult<Stmt> parseStmtDo(LabeledStmtInfo LabelInfo,
16191619
bool shouldSkipDoTokenConsume = false);
1620-
ParserResult<CatchStmt> parseStmtCatch();
1620+
ParserResult<CaseStmt> parseStmtCatch();
16211621
ParserResult<Stmt> parseStmtForEach(LabeledStmtInfo LabelInfo);
16221622
ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo);
16231623
ParserStatus parseStmtCases(SmallVectorImpl<ASTNode> &cases, bool IsActive);

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,22 +1710,11 @@ class PrintStmt : public StmtVisitor<PrintStmt> {
17101710
Indent -= 2;
17111711
PrintWithColorRAII(OS, ParenthesisColor) << ')';
17121712
}
1713-
void visitCatches(ArrayRef<CatchStmt*> clauses) {
1713+
void visitCatches(ArrayRef<CaseStmt *> clauses) {
17141714
for (auto clause : clauses) {
1715-
visitCatchStmt(clause);
1715+
visitCaseStmt(clause);
17161716
}
17171717
}
1718-
void visitCatchStmt(CatchStmt *clause) {
1719-
printCommon(clause, "catch") << '\n';
1720-
printRec(clause->getErrorPattern());
1721-
if (auto guard = clause->getGuardExpr()) {
1722-
OS << '\n';
1723-
printRec(guard);
1724-
}
1725-
OS << '\n';
1726-
printRec(clause->getBody());
1727-
PrintWithColorRAII(OS, ParenthesisColor) << ')';
1728-
}
17291718
};
17301719

17311720
} // end anonymous namespace

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3373,22 +3373,10 @@ void PrintAST::visitDoCatchStmt(DoCatchStmt *stmt) {
33733373
Printer << tok::kw_do << " ";
33743374
visit(stmt->getBody());
33753375
for (auto clause : stmt->getCatches()) {
3376-
visitCatchStmt(clause);
3376+
visitCaseStmt(clause);
33773377
}
33783378
}
33793379

3380-
void PrintAST::visitCatchStmt(CatchStmt *stmt) {
3381-
Printer << tok::kw_catch << " ";
3382-
printPattern(stmt->getErrorPattern());
3383-
if (auto guard = stmt->getGuardExpr()) {
3384-
Printer << " " << tok::kw_where << " ";
3385-
// FIXME: print guard expression
3386-
(void) guard;
3387-
}
3388-
Printer << ' ';
3389-
visit(stmt->getBody());
3390-
}
3391-
33923380
void PrintAST::visitForEachStmt(ForEachStmt *stmt) {
33933381
Printer << tok::kw_for << " ";
33943382
printPattern(stmt->getPattern());

lib/AST/ASTScope.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,6 @@ DEFINE_GET_CLASS_NAME(DoCatchStmtScope)
241241
DEFINE_GET_CLASS_NAME(SwitchStmtScope)
242242
DEFINE_GET_CLASS_NAME(ForEachStmtScope)
243243
DEFINE_GET_CLASS_NAME(ForEachPatternScope)
244-
DEFINE_GET_CLASS_NAME(CatchStmtScope)
245244
DEFINE_GET_CLASS_NAME(CaseStmtScope)
246245
DEFINE_GET_CLASS_NAME(BraceStmtScope)
247246

0 commit comments

Comments
 (0)