courbet updated this revision to Diff 377457. courbet added a comment. remove accidental paste
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D111210/new/ https://reviews.llvm.org/D111210 Files: clang/lib/Analysis/CFG.cpp clang/unittests/Analysis/CFGTest.cpp Index: clang/unittests/Analysis/CFGTest.cpp =================================================================== --- clang/unittests/Analysis/CFGTest.cpp +++ clang/unittests/Analysis/CFGTest.cpp @@ -268,6 +268,28 @@ } } +// It is valid to create a CFG for a single statement. Creating a CFG for an +// isolated `CaseStmt` should not crash.` +TEST(CFG, SwitchCase) { + const char *Code = "void f(int i) {\n" + " switch (i) {\n" + " case 0:\n" + " return;\n" + " }\n" + "}\n"; + std::vector<std::string> Args = {"-std=c++11", + "-fno-delayed-template-parsing"}; + std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(Code, Args); + ASSERT_NE(AST, nullptr); + + auto Matches = ast_matchers::match(ast_matchers::caseStmt().bind("case"), + AST->getASTContext()); + auto *Case = ast_matchers::selectFirst<CaseStmt>("case", Matches); + std::unique_ptr<CFG> Cfg = + CFG::buildCFG(nullptr, const_cast<CaseStmt *>(Case), + &AST->getASTContext(), CFG::BuildOptions{}); +} + } // namespace } // namespace analysis } // namespace clang Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -4215,10 +4215,12 @@ else TopBlock = currentBlock; - addSuccessor(SwitchTerminatedBlock, - shouldAddCase(switchExclusivelyCovered, switchCond, - CS, *Context) - ? currentBlock : nullptr); + if (SwitchTerminatedBlock) + addSuccessor( + SwitchTerminatedBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, CS, *Context) + ? currentBlock + : nullptr); LastBlock = currentBlock; CS = cast<CaseStmt>(Sub); @@ -4241,10 +4243,10 @@ // Add this block to the list of successors for the block with the switch // statement. - assert(SwitchTerminatedBlock); - addSuccessor(SwitchTerminatedBlock, CaseBlock, - shouldAddCase(switchExclusivelyCovered, switchCond, - CS, *Context)); + if (SwitchTerminatedBlock) + addSuccessor( + SwitchTerminatedBlock, CaseBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, CS, *Context)); // We set Block to NULL to allow lazy creation of a new block (if necessary) Block = nullptr;
Index: clang/unittests/Analysis/CFGTest.cpp =================================================================== --- clang/unittests/Analysis/CFGTest.cpp +++ clang/unittests/Analysis/CFGTest.cpp @@ -268,6 +268,28 @@ } } +// It is valid to create a CFG for a single statement. Creating a CFG for an +// isolated `CaseStmt` should not crash.` +TEST(CFG, SwitchCase) { + const char *Code = "void f(int i) {\n" + " switch (i) {\n" + " case 0:\n" + " return;\n" + " }\n" + "}\n"; + std::vector<std::string> Args = {"-std=c++11", + "-fno-delayed-template-parsing"}; + std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(Code, Args); + ASSERT_NE(AST, nullptr); + + auto Matches = ast_matchers::match(ast_matchers::caseStmt().bind("case"), + AST->getASTContext()); + auto *Case = ast_matchers::selectFirst<CaseStmt>("case", Matches); + std::unique_ptr<CFG> Cfg = + CFG::buildCFG(nullptr, const_cast<CaseStmt *>(Case), + &AST->getASTContext(), CFG::BuildOptions{}); +} + } // namespace } // namespace analysis } // namespace clang Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -4215,10 +4215,12 @@ else TopBlock = currentBlock; - addSuccessor(SwitchTerminatedBlock, - shouldAddCase(switchExclusivelyCovered, switchCond, - CS, *Context) - ? currentBlock : nullptr); + if (SwitchTerminatedBlock) + addSuccessor( + SwitchTerminatedBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, CS, *Context) + ? currentBlock + : nullptr); LastBlock = currentBlock; CS = cast<CaseStmt>(Sub); @@ -4241,10 +4243,10 @@ // Add this block to the list of successors for the block with the switch // statement. - assert(SwitchTerminatedBlock); - addSuccessor(SwitchTerminatedBlock, CaseBlock, - shouldAddCase(switchExclusivelyCovered, switchCond, - CS, *Context)); + if (SwitchTerminatedBlock) + addSuccessor( + SwitchTerminatedBlock, CaseBlock, + shouldAddCase(switchExclusivelyCovered, switchCond, CS, *Context)); // We set Block to NULL to allow lazy creation of a new block (if necessary) Block = nullptr;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits