forked from OSchip/llvm-project
Mark successors as reachable/unreachable instead of changing the CFG.
As suggested by Ted, this makes a few warnings less aggressive. llvm-svn: 215128
This commit is contained in:
parent
1b9f936f91
commit
edf925b935
|
@ -479,6 +479,7 @@ private:
|
||||||
AbstractConditionalOperator *E, bool BindToTemporary,
|
AbstractConditionalOperator *E, bool BindToTemporary,
|
||||||
TempDtorContext &Context);
|
TempDtorContext &Context);
|
||||||
void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
|
void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
|
||||||
|
TryResult ConditionVal,
|
||||||
CFGBlock *FalseSucc = nullptr);
|
CFGBlock *FalseSucc = nullptr);
|
||||||
|
|
||||||
// NYS == Not Yet Supported
|
// NYS == Not Yet Supported
|
||||||
|
@ -3631,24 +3632,16 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
|
||||||
BinaryOperator *E, TempDtorContext &Context) {
|
BinaryOperator *E, TempDtorContext &Context) {
|
||||||
if (E->isLogicalOp()) {
|
if (E->isLogicalOp()) {
|
||||||
VisitForTemporaryDtors(E->getLHS(), false, Context);
|
VisitForTemporaryDtors(E->getLHS(), false, Context);
|
||||||
TryResult LHSVal = tryEvaluateBool(E->getLHS());
|
TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
|
||||||
bool RHSNotExecuted = (E->getOpcode() == BO_LAnd && LHSVal.isFalse()) ||
|
if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
|
||||||
(E->getOpcode() == BO_LOr && LHSVal.isTrue());
|
RHSExecuted.negate();
|
||||||
if (RHSNotExecuted) {
|
|
||||||
return Block;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the LHS is known, and the RHS is not executed, we returned above.
|
// We do not know at CFG-construction time whether the right-hand-side was
|
||||||
// Thus, once we arrive here, and the LHS is known, we also know that the
|
// executed, thus we add a branch node that depends on the temporary
|
||||||
// RHS was executed and can execute the RHS unconditionally (that is, we
|
// constructor call.
|
||||||
// don't insert a decision block).
|
TempDtorContext RHSContext(/*IsConditional=*/true);
|
||||||
if (LHSVal.isKnown()) {
|
VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
|
||||||
VisitForTemporaryDtors(E->getRHS(), false, Context);
|
InsertTempDtorDecisionBlock(RHSContext, RHSExecuted);
|
||||||
} else {
|
|
||||||
TempDtorContext RHSContext(/*IsConditional=*/true);
|
|
||||||
VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
|
|
||||||
InsertTempDtorDecisionBlock(RHSContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Block;
|
return Block;
|
||||||
}
|
}
|
||||||
|
@ -3705,6 +3698,7 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
|
void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
|
||||||
|
TryResult ConditionVal,
|
||||||
CFGBlock *FalseSucc) {
|
CFGBlock *FalseSucc) {
|
||||||
if (!Context.TerminatorExpr) {
|
if (!Context.TerminatorExpr) {
|
||||||
// If no temporary was found, we do not need to insert a decision point.
|
// If no temporary was found, we do not need to insert a decision point.
|
||||||
|
@ -3713,8 +3707,9 @@ void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
|
||||||
assert(Context.TerminatorExpr);
|
assert(Context.TerminatorExpr);
|
||||||
CFGBlock *Decision = createBlock(false);
|
CFGBlock *Decision = createBlock(false);
|
||||||
Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true));
|
Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true));
|
||||||
addSuccessor(Decision, Block);
|
addSuccessor(Decision, Block, !ConditionVal.isFalse());
|
||||||
addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ);
|
addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
|
||||||
|
!ConditionVal.isTrue());
|
||||||
Block = Decision;
|
Block = Decision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3725,16 +3720,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
|
||||||
CFGBlock *ConditionBlock = Block;
|
CFGBlock *ConditionBlock = Block;
|
||||||
CFGBlock *ConditionSucc = Succ;
|
CFGBlock *ConditionSucc = Succ;
|
||||||
TryResult ConditionVal = tryEvaluateBool(E->getCond());
|
TryResult ConditionVal = tryEvaluateBool(E->getCond());
|
||||||
|
TryResult NegatedVal = ConditionVal;
|
||||||
if (ConditionVal.isKnown()) {
|
if (NegatedVal.isKnown()) NegatedVal.negate();
|
||||||
if (ConditionVal.isTrue()) {
|
|
||||||
VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, Context);
|
|
||||||
} else {
|
|
||||||
assert(ConditionVal.isFalse());
|
|
||||||
VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, Context);
|
|
||||||
}
|
|
||||||
return Block;
|
|
||||||
}
|
|
||||||
|
|
||||||
TempDtorContext TrueContext(/*IsConditional=*/true);
|
TempDtorContext TrueContext(/*IsConditional=*/true);
|
||||||
VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
|
VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
|
||||||
|
@ -3746,12 +3733,12 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
|
||||||
VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
|
VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
|
||||||
|
|
||||||
if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
|
if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
|
||||||
InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
|
InsertTempDtorDecisionBlock(FalseContext, NegatedVal, TrueBlock);
|
||||||
} else if (TrueContext.TerminatorExpr) {
|
} else if (TrueContext.TerminatorExpr) {
|
||||||
Block = TrueBlock;
|
Block = TrueBlock;
|
||||||
InsertTempDtorDecisionBlock(TrueContext);
|
InsertTempDtorDecisionBlock(TrueContext, ConditionVal);
|
||||||
} else {
|
} else {
|
||||||
InsertTempDtorDecisionBlock(FalseContext);
|
InsertTempDtorDecisionBlock(FalseContext, NegatedVal);
|
||||||
}
|
}
|
||||||
return Block;
|
return Block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,11 +185,11 @@ int testTernaryConditionalNoreturnFalseBranch(bool value) {
|
||||||
|
|
||||||
int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
|
int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
|
||||||
value || (true ? NoReturn() : true);
|
value || (true ? NoReturn() : true);
|
||||||
} // expected-warning {{control may reach end of non-void function}}
|
}
|
||||||
|
|
||||||
int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
|
int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
|
||||||
value || (false ? true : NoReturn());
|
value || (false ? true : NoReturn());
|
||||||
} // expected-warning {{control may reach end of non-void function}}
|
}
|
||||||
|
|
||||||
int testStaticallyExecutedLogicalOrBranch() {
|
int testStaticallyExecutedLogicalOrBranch() {
|
||||||
false || NoReturn();
|
false || NoReturn();
|
||||||
|
@ -209,7 +209,7 @@ int testStaticallySkppedLogicalAndBranch() {
|
||||||
|
|
||||||
int testConditionallyExecutedComplexLogicalBranch(bool value) {
|
int testConditionallyExecutedComplexLogicalBranch(bool value) {
|
||||||
value || (true && NoReturn());
|
value || (true && NoReturn());
|
||||||
} // expected-warning {{control may reach end of non-void function}}
|
}
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
namespace LambdaVsTemporaryDtor {
|
namespace LambdaVsTemporaryDtor {
|
||||||
|
|
Loading…
Reference in New Issue