@@ -808,20 +808,15 @@ clang::Expr *NormalizeToBool(clang::Expr *expr, clang::ASTContext &ctx) {
808808 /* BasePath=*/ nullptr , clang::VK_PRValue, clang::FPOptionsOverride ());
809809}
810810
811- std::vector<clang::SwitchCase *>
812- GetTopLevelSwitchCases (clang::SwitchStmt *stmt) {
813- std::vector<clang::SwitchCase *> cases;
814- if (auto *body = llvm::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
815- for (auto *s : body->body ()) {
816- if (auto *sc = clang::dyn_cast<clang::SwitchCase>(s)) {
817- cases.push_back (sc);
818- }
819- }
811+ static clang::Stmt *GetLastStmtOfSwitchCase (clang::SwitchCase *c) {
812+ clang::Stmt *cur = c->getSubStmt ();
813+ while (auto *sc = clang::dyn_cast<clang::SwitchCase>(cur)) {
814+ cur = sc->getSubStmt ();
820815 }
821- return cases ;
816+ return cur ;
822817}
823818
824- bool SwitchCaseContainsDefault (clang::SwitchCase *c) {
819+ static bool CaseChainHasDefault (clang::SwitchCase *c) {
825820 for (clang::Stmt *cur = c;;) {
826821 if (clang::isa<clang::DefaultStmt>(cur)) {
827822 return true ;
@@ -832,32 +827,6 @@ bool SwitchCaseContainsDefault(clang::SwitchCase *c) {
832827 }
833828 cur = sc->getSubStmt ();
834829 }
835- return false ;
836- }
837-
838- static clang::Stmt *GetLastStmtOfSwitchCase (clang::SwitchCase *c) {
839- clang::Stmt *cur = c->getSubStmt ();
840- while (auto *sc = clang::dyn_cast<clang::SwitchCase>(cur)) {
841- cur = sc->getSubStmt ();
842- }
843- return cur;
844- }
845-
846- std::vector<clang::Stmt *> GetSwitchCaseBody (clang::CompoundStmt *body,
847- clang::SwitchCase *head) {
848- std::vector<clang::Stmt *> out;
849- out.push_back (GetLastStmtOfSwitchCase (head));
850- auto it = body->body_begin (), end = body->body_end ();
851- while (it != end && *it != head) {
852- ++it;
853- }
854- assert (it != end);
855- ++it;
856- while (it != end && !clang::isa<clang::SwitchCase>(*it)) {
857- out.push_back (*it);
858- ++it;
859- }
860- return out;
861830}
862831
863832static bool SwitchCaseHasFallthrough (clang::Stmt *stmt) {
@@ -879,16 +848,34 @@ static bool SwitchCaseHasFallthrough(clang::Stmt *stmt) {
879848 return true ;
880849}
881850
882- bool SwitchHasFallthrough (clang::SwitchStmt *stmt) {
883- if (auto *body = clang::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
884- for (auto top_level_case : GetTopLevelSwitchCases (stmt)) {
885- auto arm = GetSwitchCaseBody (body, top_level_case);
886- if (arm.empty () || SwitchCaseHasFallthrough (arm.back ())) {
887- return true ;
888- }
851+ std::vector<SwitchArm> AnalyzeSwitchArms (clang::CompoundStmt *body) {
852+ std::vector<SwitchArm> arms;
853+ for (clang::Stmt *s : body->body ()) {
854+ llvm::StringRef label;
855+ clang::Stmt *inner = s;
856+ if (auto *outer = clang::dyn_cast<clang::LabelStmt>(inner)) {
857+ label = outer->getDecl ()->getName ();
858+ do {
859+ inner = clang::cast<clang::LabelStmt>(inner)->getSubStmt ();
860+ } while (clang::isa<clang::LabelStmt>(inner));
861+ }
862+
863+ if (auto *sc = clang::dyn_cast<clang::SwitchCase>(inner)) {
864+ arms.push_back ({sc,
865+ label,
866+ {GetLastStmtOfSwitchCase (sc)},
867+ CaseChainHasDefault (sc),
868+ /* has_fallthrough=*/ false });
869+ } else if (!arms.empty ()) {
870+ arms.back ().body .push_back (s);
889871 }
890872 }
891- return false ;
873+
874+ for (SwitchArm &arm : arms) {
875+ arm.has_fallthrough =
876+ arm.body .empty () || SwitchCaseHasFallthrough (arm.body .back ());
877+ }
878+ return arms;
892879}
893880
894881bool CompoundHasTopLevelLabel (const clang::CompoundStmt *compound) {
0 commit comments