@@ -876,20 +876,15 @@ clang::Expr *NormalizeToBool(clang::Expr *expr, clang::ASTContext &ctx) {
876876 /* BasePath=*/ nullptr , clang::VK_PRValue, clang::FPOptionsOverride ());
877877}
878878
879- std::vector<clang::SwitchCase *>
880- GetTopLevelSwitchCases (clang::SwitchStmt *stmt) {
881- std::vector<clang::SwitchCase *> cases;
882- if (auto *body = llvm::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
883- for (auto *s : body->body ()) {
884- if (auto *sc = clang::dyn_cast<clang::SwitchCase>(s)) {
885- cases.push_back (sc);
886- }
887- }
879+ static clang::Stmt *GetLastStmtOfSwitchCase (clang::SwitchCase *c) {
880+ clang::Stmt *cur = c->getSubStmt ();
881+ while (auto *sc = clang::dyn_cast<clang::SwitchCase>(cur)) {
882+ cur = sc->getSubStmt ();
888883 }
889- return cases ;
884+ return cur ;
890885}
891886
892- bool SwitchCaseContainsDefault (clang::SwitchCase *c) {
887+ static bool CaseChainHasDefault (clang::SwitchCase *c) {
893888 for (clang::Stmt *cur = c;;) {
894889 if (clang::isa<clang::DefaultStmt>(cur)) {
895890 return true ;
@@ -900,32 +895,6 @@ bool SwitchCaseContainsDefault(clang::SwitchCase *c) {
900895 }
901896 cur = sc->getSubStmt ();
902897 }
903- return false ;
904- }
905-
906- static clang::Stmt *GetLastStmtOfSwitchCase (clang::SwitchCase *c) {
907- clang::Stmt *cur = c->getSubStmt ();
908- while (auto *sc = clang::dyn_cast<clang::SwitchCase>(cur)) {
909- cur = sc->getSubStmt ();
910- }
911- return cur;
912- }
913-
914- std::vector<clang::Stmt *> GetSwitchCaseBody (clang::CompoundStmt *body,
915- clang::SwitchCase *head) {
916- std::vector<clang::Stmt *> out;
917- out.push_back (GetLastStmtOfSwitchCase (head));
918- auto it = body->body_begin (), end = body->body_end ();
919- while (it != end && *it != head) {
920- ++it;
921- }
922- assert (it != end);
923- ++it;
924- while (it != end && !clang::isa<clang::SwitchCase>(*it)) {
925- out.push_back (*it);
926- ++it;
927- }
928- return out;
929898}
930899
931900static bool SwitchCaseHasFallthrough (clang::Stmt *stmt) {
@@ -947,16 +916,34 @@ static bool SwitchCaseHasFallthrough(clang::Stmt *stmt) {
947916 return true ;
948917}
949918
950- bool SwitchHasFallthrough (clang::SwitchStmt *stmt) {
951- if (auto *body = clang::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
952- for (auto top_level_case : GetTopLevelSwitchCases (stmt)) {
953- auto arm = GetSwitchCaseBody (body, top_level_case);
954- if (arm.empty () || SwitchCaseHasFallthrough (arm.back ())) {
955- return true ;
956- }
919+ std::vector<SwitchArm> AnalyzeSwitchArms (clang::CompoundStmt *body) {
920+ std::vector<SwitchArm> arms;
921+ for (clang::Stmt *s : body->body ()) {
922+ llvm::StringRef label;
923+ clang::Stmt *inner = s;
924+ if (auto *outer = clang::dyn_cast<clang::LabelStmt>(inner)) {
925+ label = outer->getDecl ()->getName ();
926+ do {
927+ inner = clang::cast<clang::LabelStmt>(inner)->getSubStmt ();
928+ } while (clang::isa<clang::LabelStmt>(inner));
929+ }
930+
931+ if (auto *sc = clang::dyn_cast<clang::SwitchCase>(inner)) {
932+ arms.push_back ({sc,
933+ label,
934+ {GetLastStmtOfSwitchCase (sc)},
935+ CaseChainHasDefault (sc),
936+ /* has_fallthrough=*/ false });
937+ } else if (!arms.empty ()) {
938+ arms.back ().body .push_back (s);
957939 }
958940 }
959- return false ;
941+
942+ for (SwitchArm &arm : arms) {
943+ arm.has_fallthrough =
944+ arm.body .empty () || SwitchCaseHasFallthrough (arm.body .back ());
945+ }
946+ return arms;
960947}
961948
962949bool CompoundHasTopLevelLabel (const clang::CompoundStmt *compound) {
0 commit comments