2626#include " llvm/Support/TrailingObjects.h"
2727
2828namespace 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+
3941enum class StmtKind {
4042#define STMT (ID, PARENT ) ID,
4143#define LAST_STMT (ID ) Last_Stmt = ID,
@@ -920,6 +922,45 @@ class CaseLabelItem {
920922 }
921923};
922924
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+
923964// / A 'case' or 'default' block of a switch statement. Only valid as the
924965// / substatement of a SwitchStmt. A case block begins either with one or more
925966// / CaseLabelItems or a single 'default' label.
@@ -933,8 +974,10 @@ class CaseLabelItem {
933974// / default:
934975// / \endcode
935976// /
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> {
938981 friend TrailingObjects;
939982
940983 SourceLoc UnknownAttrLoc;
@@ -943,24 +986,47 @@ class CaseStmt final : public Stmt,
943986
944987 llvm::PointerIntPair<Stmt *, 1 , bool > BodyAndHasBoundDecls;
945988
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+
946995 CaseStmt (SourceLoc CaseLoc, ArrayRef<CaseLabelItem> CaseLabelItems,
947996 bool HasBoundDecls, SourceLoc UnknownAttrLoc, SourceLoc ColonLoc,
948- Stmt *Body, Optional<bool > Implicit);
997+ Stmt *Body, Optional<bool > Implicit,
998+ NullablePtr<FallthroughStmt> fallthroughStmt);
949999
9501000public:
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 );
9561007
9571008 ArrayRef<CaseLabelItem> getCaseLabelItems () const {
9581009 return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt .NumPatterns };
9591010 }
1011+
9601012 MutableArrayRef<CaseLabelItem> getMutableCaseLabelItems () {
9611013 return {getTrailingObjects<CaseLabelItem>(), Bits.CaseStmt .NumPatterns };
9621014 }
9631015
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+
9641030 Stmt *getBody () const { return BodyAndHasBoundDecls.getPointer (); }
9651031 void setBody (Stmt *body) { BodyAndHasBoundDecls.setPointer (body); }
9661032
@@ -991,6 +1057,14 @@ class CaseStmt final : public Stmt,
9911057 }
9921058
9931059 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+ }
9941068};
9951069
9961070// / Switch statement.
@@ -1135,48 +1209,6 @@ class ContinueStmt : public Stmt {
11351209 }
11361210};
11371211
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-
11801212// / FailStmt - A statement that indicates a failable, which is currently
11811213// / spelled as "return nil" and can only be used within failable initializers.
11821214class FailStmt : public Stmt {
0 commit comments