@@ -559,105 +559,6 @@ class DoStmt : public LabeledStmt {
559
559
static bool classof (const Stmt *S) { return S->getKind () == StmtKind::Do; }
560
560
};
561
561
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
-
661
562
// / Either an "if let" case or a simple boolean expression can appear as the
662
563
// / condition of an 'if' or 'while' statement.
663
564
using StmtCondition = MutableArrayRef<StmtConditionElement>;
@@ -962,6 +863,8 @@ class CaseLabelItem {
962
863
bool isDefault () const {
963
864
return GuardExprAndKind.getInt () == Kind::Default;
964
865
}
866
+
867
+ bool isSyntacticallyExhaustive () const ;
965
868
};
966
869
967
870
// / FallthroughStmt - The keyword "fallthrough".
@@ -1003,9 +906,12 @@ class FallthroughStmt : public Stmt {
1003
906
}
1004
907
};
1005
908
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.
1009
915
// /
1010
916
// / Some examples:
1011
917
// / \code
@@ -1023,28 +929,32 @@ class CaseStmt final
1023
929
friend TrailingObjects;
1024
930
1025
931
SourceLoc UnknownAttrLoc;
1026
- SourceLoc CaseLoc;
1027
- SourceLoc ColonLoc;
932
+ SourceLoc ItemIntroducerLoc;
933
+ SourceLoc ItemTerminatorLoc;
934
+ CaseParentKind ParentKind;
1028
935
1029
936
llvm::PointerIntPair<Stmt *, 1 , bool > BodyAndHasFallthrough;
1030
937
1031
938
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables;
1032
939
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,
1035
943
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
1036
944
Optional<bool > Implicit,
1037
945
NullablePtr<FallthroughStmt> fallthroughStmt);
1038
946
1039
947
public:
1040
948
static CaseStmt *
1041
- create (ASTContext &C, SourceLoc CaseLoc ,
949
+ create (ASTContext &C, CaseParentKind ParentKind, SourceLoc ItemIntroducerLoc ,
1042
950
ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
1043
- SourceLoc ColonLoc , Stmt *Body,
951
+ SourceLoc ItemTerminatorLoc , Stmt *Body,
1044
952
Optional<MutableArrayRef<VarDecl *>> CaseBodyVariables,
1045
953
Optional<bool > Implicit = None,
1046
954
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr );
1047
955
956
+ CaseParentKind getParentKind () const { return ParentKind; }
957
+
1048
958
ArrayRef<CaseLabelItem> getCaseLabelItems () const {
1049
959
return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt .NumPatterns };
1050
960
}
@@ -1073,17 +983,38 @@ class CaseStmt final
1073
983
// / True if the case block declares any patterns with local variable bindings.
1074
984
bool hasBoundDecls () const { return CaseBodyVariables.hasValue (); }
1075
985
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; }
1078
989
1079
990
SourceLoc getStartLoc () const {
1080
991
if (UnknownAttrLoc.isValid ())
1081
992
return UnknownAttrLoc;
1082
993
return getLoc ();
1083
994
}
1084
995
SourceLoc getEndLoc () const { return getBody ()->getEndLoc (); }
996
+
1085
997
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
+ }
1087
1018
}
1088
1019
1089
1020
bool isDefault () { return getCaseLabelItems ()[0 ].isDefault (); }
@@ -1213,6 +1144,58 @@ class SwitchStmt final : public LabeledStmt,
1213
1144
}
1214
1145
};
1215
1146
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
+
1216
1199
// / BreakStmt - The "break" and "break label" statement.
1217
1200
class BreakStmt : public Stmt {
1218
1201
SourceLoc Loc;
0 commit comments