diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -216,7 +216,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()); diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/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"