26
26
#include " llvm/Support/TrailingObjects.h"
27
27
28
28
namespace swift {
29
- class AnyPattern ;
30
- class ASTContext ;
31
- class ASTWalker ;
32
- class Decl ;
33
- class Expr ;
34
- class FuncDecl ;
35
- class Pattern ;
36
- class PatternBindingDecl ;
37
- class VarDecl ;
38
-
29
+
30
+ class AnyPattern ;
31
+ class ASTContext ;
32
+ class ASTWalker ;
33
+ class Decl ;
34
+ class Expr ;
35
+ class FuncDecl ;
36
+ class Pattern ;
37
+ class PatternBindingDecl ;
38
+ class VarDecl ;
39
+ class CaseStmt ;
40
+
39
41
enum class StmtKind {
40
42
#define STMT (ID, PARENT ) ID,
41
43
#define LAST_STMT (ID ) Last_Stmt = ID,
@@ -920,6 +922,45 @@ class CaseLabelItem {
920
922
}
921
923
};
922
924
925
+ // / FallthroughStmt - The keyword "fallthrough".
926
+ class FallthroughStmt : public Stmt {
927
+ SourceLoc Loc;
928
+ CaseStmt *FallthroughSource;
929
+ CaseStmt *FallthroughDest;
930
+
931
+ public:
932
+ FallthroughStmt (SourceLoc Loc, Optional<bool > implicit = None)
933
+ : Stmt(StmtKind::Fallthrough, getDefaultImplicitFlag(implicit, Loc)),
934
+ Loc (Loc), FallthroughSource(nullptr ), FallthroughDest(nullptr ) {}
935
+
936
+ SourceLoc getLoc () const { return Loc; }
937
+
938
+ SourceRange getSourceRange () const { return Loc; }
939
+
940
+ // / Get the CaseStmt block from which the fallthrough transfers control.
941
+ // / Set during Sema. (May stay null if fallthrough is invalid.)
942
+ CaseStmt *getFallthroughSource () const { return FallthroughSource; }
943
+ void setFallthroughSource (CaseStmt *C) {
944
+ assert (!FallthroughSource && " fallthrough source already set?!" );
945
+ FallthroughSource = C;
946
+ }
947
+
948
+ // / Get the CaseStmt block to which the fallthrough transfers control.
949
+ // / Set during Sema.
950
+ CaseStmt *getFallthroughDest () const {
951
+ assert (FallthroughDest && " fallthrough dest is not set until Sema" );
952
+ return FallthroughDest;
953
+ }
954
+ void setFallthroughDest (CaseStmt *C) {
955
+ assert (!FallthroughDest && " fallthrough dest already set?!" );
956
+ FallthroughDest = C;
957
+ }
958
+
959
+ static bool classof (const Stmt *S) {
960
+ return S->getKind () == StmtKind::Fallthrough;
961
+ }
962
+ };
963
+
923
964
// / A 'case' or 'default' block of a switch statement. Only valid as the
924
965
// / substatement of a SwitchStmt. A case block begins either with one or more
925
966
// / CaseLabelItems or a single 'default' label.
@@ -933,8 +974,10 @@ class CaseLabelItem {
933
974
// / default:
934
975
// / \endcode
935
976
// /
936
- class CaseStmt final : public Stmt,
937
- private llvm::TrailingObjects<CaseStmt, CaseLabelItem> {
977
+ class CaseStmt final
978
+ : public Stmt,
979
+ private llvm::TrailingObjects<CaseStmt, FallthroughStmt *,
980
+ CaseLabelItem> {
938
981
friend TrailingObjects;
939
982
940
983
SourceLoc UnknownAttrLoc;
@@ -943,24 +986,47 @@ class CaseStmt final : public Stmt,
943
986
944
987
llvm::PointerIntPair<Stmt *, 1 , bool > BodyAndHasBoundDecls;
945
988
989
+ // / Set to true if we have a fallthrough.
990
+ // /
991
+ // / TODO: Once we have CaseBodyVarDecls, use the bit in BodyAndHasBoundDecls
992
+ // / for this instead. This is separate now for staging reasons.
993
+ bool hasFallthrough;
994
+
946
995
CaseStmt (SourceLoc CaseLoc, ArrayRef<CaseLabelItem> CaseLabelItems,
947
996
bool HasBoundDecls, SourceLoc UnknownAttrLoc, SourceLoc ColonLoc,
948
- Stmt *Body, Optional<bool > Implicit);
997
+ Stmt *Body, Optional<bool > Implicit,
998
+ NullablePtr<FallthroughStmt> fallthroughStmt);
949
999
950
1000
public:
951
- static CaseStmt *create (ASTContext &C, SourceLoc CaseLoc,
952
- ArrayRef<CaseLabelItem> CaseLabelItems,
953
- bool HasBoundDecls, SourceLoc UnknownAttrLoc,
954
- SourceLoc ColonLoc, Stmt *Body,
955
- Optional<bool > Implicit = None);
1001
+ static CaseStmt *
1002
+ create (ASTContext &C, SourceLoc CaseLoc,
1003
+ ArrayRef<CaseLabelItem> CaseLabelItems, bool HasBoundDecls,
1004
+ SourceLoc UnknownAttrLoc, SourceLoc ColonLoc, Stmt *Body,
1005
+ Optional<bool > Implicit = None,
1006
+ NullablePtr<FallthroughStmt> fallthroughStmt = nullptr );
956
1007
957
1008
ArrayRef<CaseLabelItem> getCaseLabelItems () const {
958
1009
return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt .NumPatterns };
959
1010
}
1011
+
960
1012
MutableArrayRef<CaseLabelItem> getMutableCaseLabelItems () {
961
1013
return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt .NumPatterns };
962
1014
}
963
1015
1016
+ unsigned getNumCaseLabelItems () const { return Bits.CaseStmt .NumPatterns ; }
1017
+
1018
+ NullablePtr<CaseStmt> getFallthroughDest () const {
1019
+ return const_cast <CaseStmt &>(*this ).getFallthroughDest ();
1020
+ }
1021
+
1022
+ NullablePtr<CaseStmt> getFallthroughDest () {
1023
+ if (!hasFallthrough)
1024
+ return nullptr ;
1025
+ return (*getTrailingObjects<FallthroughStmt *>())->getFallthroughDest ();
1026
+ }
1027
+
1028
+ bool hasFallthroughDest () const { return hasFallthrough; }
1029
+
964
1030
Stmt *getBody () const { return BodyAndHasBoundDecls.getPointer (); }
965
1031
void setBody (Stmt *body) { BodyAndHasBoundDecls.setPointer (body); }
966
1032
@@ -991,6 +1057,14 @@ class CaseStmt final : public Stmt,
991
1057
}
992
1058
993
1059
static bool classof (const Stmt *S) { return S->getKind () == StmtKind::Case; }
1060
+
1061
+ size_t numTrailingObjects (OverloadToken<CaseLabelItem>) const {
1062
+ return getNumCaseLabelItems ();
1063
+ }
1064
+
1065
+ size_t numTrailingObjects (OverloadToken<FallthroughStmt *>) const {
1066
+ return hasFallthrough ? 1 : 0 ;
1067
+ }
994
1068
};
995
1069
996
1070
// / Switch statement.
@@ -1135,48 +1209,6 @@ class ContinueStmt : public Stmt {
1135
1209
}
1136
1210
};
1137
1211
1138
- // / FallthroughStmt - The keyword "fallthrough".
1139
- class FallthroughStmt : public Stmt {
1140
- SourceLoc Loc;
1141
- CaseStmt *FallthroughSource;
1142
- CaseStmt *FallthroughDest;
1143
-
1144
- public:
1145
- FallthroughStmt (SourceLoc Loc, Optional<bool > implicit = None)
1146
- : Stmt(StmtKind::Fallthrough, getDefaultImplicitFlag(implicit, Loc)),
1147
- Loc (Loc), FallthroughSource(nullptr ), FallthroughDest(nullptr )
1148
- {}
1149
-
1150
- SourceLoc getLoc () const { return Loc; }
1151
-
1152
- SourceRange getSourceRange () const { return Loc; }
1153
-
1154
- // / Get the CaseStmt block from which the fallthrough transfers control.
1155
- // / Set during Sema. (May stay null if fallthrough is invalid.)
1156
- CaseStmt *getFallthroughSource () const {
1157
- return FallthroughSource;
1158
- }
1159
- void setFallthroughSource (CaseStmt *C) {
1160
- assert (!FallthroughSource && " fallthrough source already set?!" );
1161
- FallthroughSource = C;
1162
- }
1163
-
1164
- // / Get the CaseStmt block to which the fallthrough transfers control.
1165
- // / Set during Sema.
1166
- CaseStmt *getFallthroughDest () const {
1167
- assert (FallthroughDest && " fallthrough dest is not set until Sema" );
1168
- return FallthroughDest;
1169
- }
1170
- void setFallthroughDest (CaseStmt *C) {
1171
- assert (!FallthroughDest && " fallthrough dest already set?!" );
1172
- FallthroughDest = C;
1173
- }
1174
-
1175
- static bool classof (const Stmt *S) {
1176
- return S->getKind () == StmtKind::Fallthrough;
1177
- }
1178
- };
1179
-
1180
1212
// / FailStmt - A statement that indicates a failable, which is currently
1181
1213
// / spelled as "return nil" and can only be used within failable initializers.
1182
1214
class FailStmt : public Stmt {
0 commit comments