@@ -660,4 +660,78 @@ clang::Expr *CreateConversionToBool(clang::Expr *expr, clang::ASTContext &ctx) {
660660 /* BasePath=*/ nullptr , clang::VK_PRValue, clang::FPOptionsOverride ());
661661}
662662
663+ std::vector<clang::SwitchCase *>
664+ GetTopLevelSwitchCases (clang::SwitchStmt *stmt) {
665+ std::vector<clang::SwitchCase *> cases;
666+ if (auto *body = llvm::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
667+ for (auto *s : body->body ()) {
668+ if (auto *sc = clang::dyn_cast<clang::SwitchCase>(s)) {
669+ cases.push_back (sc);
670+ }
671+ }
672+ }
673+ return cases;
674+ }
675+
676+ bool ChainContainsDefault (clang::SwitchCase *c) {
677+ for (clang::Stmt *cur = c;;) {
678+ if (clang::isa<clang::DefaultStmt>(cur)) {
679+ return true ;
680+ }
681+ auto *sc = clang::dyn_cast<clang::SwitchCase>(cur);
682+ if (!sc) {
683+ return false ;
684+ }
685+ cur = sc->getSubStmt ();
686+ }
687+ return false ;
688+ }
689+
690+ clang::Stmt *ChainLeafBody (clang::SwitchCase *c) {
691+ clang::Stmt *cur = c->getSubStmt ();
692+ while (auto *sc = clang::dyn_cast<clang::SwitchCase>(cur)) {
693+ cur = sc->getSubStmt ();
694+ }
695+ return cur;
696+ }
697+
698+ std::vector<clang::Stmt *> GetSwitchArmBody (clang::CompoundStmt *body,
699+ clang::SwitchCase *head) {
700+ std::vector<clang::Stmt *> out;
701+ out.push_back (ChainLeafBody (head));
702+ auto it = body->body_begin (), end = body->body_end ();
703+ while (it != end && *it != head) {
704+ ++it;
705+ }
706+ assert (it != end);
707+ ++it;
708+ while (it != end && !clang::isa<clang::SwitchCase>(*it)) {
709+ out.push_back (*it);
710+ ++it;
711+ }
712+ return out;
713+ }
714+
715+ bool SwitchArmHasFallthrough (clang::Stmt *stmt) {
716+ if (stmt) {
717+ if (clang::isa<clang::BreakStmt>(stmt) ||
718+ clang::isa<clang::ReturnStmt>(stmt)) {
719+ return false ;
720+ }
721+ }
722+ return true ;
723+ }
724+
725+ bool SwitchHasFallthrough (clang::SwitchStmt *stmt) {
726+ if (auto *body = clang::dyn_cast<clang::CompoundStmt>(stmt->getBody ())) {
727+ for (auto top_level_case : GetTopLevelSwitchCases (stmt)) {
728+ auto arm = GetSwitchArmBody (body, top_level_case);
729+ if (arm.empty () || SwitchArmHasFallthrough (arm.back ())) {
730+ return true ;
731+ }
732+ }
733+ }
734+ return false ;
735+ }
736+
663737} // namespace cpp2rust
0 commit comments