mboehme created this revision. Herald added subscribers: martong, xazax.hun. Herald added a reviewer: NoQ. Herald added a project: All. mboehme requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
The crash was due to unconditionally calling `Block.succ_begin()->getReachableBlock()->hasNoReturnElement()`, but `getReachableBlock()` can return null now that we have turned `PruneTriviallyFalseEdges` on. This patch adds two tests that crash without the fix. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D151071 Files: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -296,6 +296,22 @@ UnorderedElementsAre("foo")))))); } +TEST_F(NoreturnDestructorTest, + ConditionalOperatorConstantCondition_LeftBranchReturns) { + std::string Code = R"( + #include "noreturn_destructor_test_defs.h" + + void target() { + int value = true ? foo() : Fatal().bar(); + (void)0; + // [[p]] + } + )"; + runDataflow(Code, UnorderedElementsAre(IsStringMapEntry( + "p", HoldsFunctionCallLattice(HasCalledFunctions( + UnorderedElementsAre("foo")))))); +} + TEST_F(NoreturnDestructorTest, ConditionalOperatorRightBranchReturns) { std::string Code = R"( #include "noreturn_destructor_test_defs.h" @@ -311,6 +327,22 @@ UnorderedElementsAre("foo")))))); } +TEST_F(NoreturnDestructorTest, + ConditionalOperatorConstantCondition_RightBranchReturns) { + std::string Code = R"( + #include "noreturn_destructor_test_defs.h" + + void target() { + int value = false ? Fatal().bar() : foo(); + (void)0; + // [[p]] + } + )"; + runDataflow(Code, UnorderedElementsAre(IsStringMapEntry( + "p", HoldsFunctionCallLattice(HasCalledFunctions( + UnorderedElementsAre("foo")))))); +} + TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchesDoNotReturn) { std::string Code = R"( #include "noreturn_destructor_test_defs.h" Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -219,7 +219,8 @@ // operator includes a branch that contains a noreturn destructor call. // // See `NoreturnDestructorTest` for concrete examples. - if (Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) { + if (Block.succ_begin()->getReachableBlock() != nullptr && + Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) { auto &StmtToBlock = AC.CFCtx.getStmtToBlock(); auto StmtBlock = StmtToBlock.find(Block.getTerminatorStmt()); assert(StmtBlock != StmtToBlock.end());
Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -296,6 +296,22 @@ UnorderedElementsAre("foo")))))); } +TEST_F(NoreturnDestructorTest, + ConditionalOperatorConstantCondition_LeftBranchReturns) { + std::string Code = R"( + #include "noreturn_destructor_test_defs.h" + + void target() { + int value = true ? foo() : Fatal().bar(); + (void)0; + // [[p]] + } + )"; + runDataflow(Code, UnorderedElementsAre(IsStringMapEntry( + "p", HoldsFunctionCallLattice(HasCalledFunctions( + UnorderedElementsAre("foo")))))); +} + TEST_F(NoreturnDestructorTest, ConditionalOperatorRightBranchReturns) { std::string Code = R"( #include "noreturn_destructor_test_defs.h" @@ -311,6 +327,22 @@ UnorderedElementsAre("foo")))))); } +TEST_F(NoreturnDestructorTest, + ConditionalOperatorConstantCondition_RightBranchReturns) { + std::string Code = R"( + #include "noreturn_destructor_test_defs.h" + + void target() { + int value = false ? Fatal().bar() : foo(); + (void)0; + // [[p]] + } + )"; + runDataflow(Code, UnorderedElementsAre(IsStringMapEntry( + "p", HoldsFunctionCallLattice(HasCalledFunctions( + UnorderedElementsAre("foo")))))); +} + TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchesDoNotReturn) { std::string Code = R"( #include "noreturn_destructor_test_defs.h" Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -219,7 +219,8 @@ // operator includes a branch that contains a noreturn destructor call. // // See `NoreturnDestructorTest` for concrete examples. - if (Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) { + if (Block.succ_begin()->getReachableBlock() != nullptr && + Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) { auto &StmtToBlock = AC.CFCtx.getStmtToBlock(); auto StmtBlock = StmtToBlock.find(Block.getTerminatorStmt()); assert(StmtBlock != StmtToBlock.end());
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits