From: Manuel Klimek Date: Thu, 7 Aug 2014 17:02:21 +0000 (+0000) Subject: Fix CFG for temporary dtors when the branch taken is known. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4bf775203e8bb64f66f47112317fd86c7c354cb4;p=clang Fix CFG for temporary dtors when the branch taken is known. Use the parent context when visiting temporaries when we do not insert a temporary dtor decision branch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215120 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 96571fdbec..e6393777e3 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -3638,15 +3638,17 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors( return Block; } - TempDtorContext RHSContext(/*IsConditional=*/true); - VisitForTemporaryDtors(E->getRHS(), false, RHSContext); - // If the LHS is known, and the RHS is not executed, we returned above. // Thus, once we arrive here, and the LHS is known, we also know that the // RHS was executed and can execute the RHS unconditionally (that is, we // don't insert a decision block). - if (!LHSVal.isKnown()) + if (LHSVal.isKnown()) { + VisitForTemporaryDtors(E->getRHS(), false, Context); + } else { + TempDtorContext RHSContext(/*IsConditional=*/true); + VisitForTemporaryDtors(E->getRHS(), false, RHSContext); InsertTempDtorDecisionBlock(RHSContext); + } return Block; } @@ -3724,22 +3726,24 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( CFGBlock *ConditionSucc = Succ; TryResult ConditionVal = tryEvaluateBool(E->getCond()); - TempDtorContext TrueContext(/*IsConditional=*/true); - if (!ConditionVal.isFalse()) { - VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext); - if (ConditionVal.isTrue()) - return Block; + if (ConditionVal.isKnown()) { + if (ConditionVal.isTrue()) { + VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, Context); + } else { + assert(ConditionVal.isFalse()); + VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, Context); + } + return Block; } + + TempDtorContext TrueContext(/*IsConditional=*/true); + VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext); CFGBlock *TrueBlock = Block; Block = ConditionBlock; Succ = ConditionSucc; TempDtorContext FalseContext(/*IsConditional=*/true); - if (!ConditionVal.isTrue()) { - VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext); - if (ConditionVal.isFalse()) - return Block; - } + VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext); if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) { InsertTempDtorDecisionBlock(FalseContext, TrueBlock); diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp index 519d27cf0b..3bb395f17d 100644 --- a/test/SemaCXX/return-noreturn.cpp +++ b/test/SemaCXX/return-noreturn.cpp @@ -183,6 +183,14 @@ int testTernaryConditionalNoreturnFalseBranch(bool value) { value ? Return() : (NoReturn() || NoReturn()); } // expected-warning {{control may reach end of non-void function}} +int testConditionallyExecutedComplexTernaryTrueBranch(bool value) { + value || (true ? NoReturn() : true); +} // expected-warning {{control may reach end of non-void function}} + +int testConditionallyExecutedComplexTernaryFalseBranch(bool value) { + value || (false ? true : NoReturn()); +} // expected-warning {{control may reach end of non-void function}} + int testStaticallyExecutedLogicalOrBranch() { false || NoReturn(); } @@ -199,6 +207,9 @@ int testStaticallySkppedLogicalAndBranch() { false && NoReturn(); } // expected-warning {{control reaches end of non-void function}} +int testConditionallyExecutedComplexLogicalBranch(bool value) { + value || (true && NoReturn()); +} // expected-warning {{control may reach end of non-void function}} #if __cplusplus >= 201103L namespace LambdaVsTemporaryDtor {