@@ -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.
663564using 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
1039947public:
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.
12171200class BreakStmt : public Stmt {
12181201 SourceLoc Loc;
0 commit comments