Fix branch reachabiliy annotation for temp dtor branches.

As we only create temp dtor decision branches when a temp dtor needs to
be run (as opposed to for each logical branch in the original
expression), we must include the information about all previous logical
branches when we annotate the temp dtor decision branch.

llvm-svn: 215188
This commit is contained in:
Manuel Klimek 2014-08-08 07:37:13 +00:00
parent f9834d5fa0
commit deb0262a5e
2 changed files with 43 additions and 23 deletions

View File

@ -234,6 +234,12 @@ public:
}
};
TryResult bothKnownTrue(TryResult R1, TryResult R2) {
if (!R1.isKnown() || !R2.isKnown())
return TryResult();
return TryResult(R1.isTrue() && R2.isTrue());
}
class reverse_children {
llvm::SmallVector<Stmt *, 12> childrenBuf;
ArrayRef<Stmt*> children;
@ -439,10 +445,10 @@ private:
/// if the CXXBindTemporaryExpr was marked executed, and otherwise
/// branches to the stored successor.
struct TempDtorContext {
TempDtorContext(bool IsConditional)
: IsConditional(IsConditional),
Succ(nullptr),
TerminatorExpr(nullptr) {}
TempDtorContext() : KnownExecuted(true) {}
TempDtorContext(TryResult KnownExecuted)
: IsConditional(true), KnownExecuted(KnownExecuted) {}
/// Returns whether we need to start a new branch for a temporary destructor
/// call. This is the case when the the temporary destructor is
@ -461,9 +467,10 @@ private:
TerminatorExpr = E;
}
const bool IsConditional;
CFGBlock *Succ;
CXXBindTemporaryExpr *TerminatorExpr;
const bool IsConditional = false;
const TryResult KnownExecuted;
CFGBlock *Succ = nullptr;
CXXBindTemporaryExpr *TerminatorExpr = nullptr;
};
// Visitors to walk an AST and generate destructors of temporaries in
@ -479,7 +486,6 @@ private:
AbstractConditionalOperator *E, bool BindToTemporary,
TempDtorContext &Context);
void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
TryResult ConditionVal,
CFGBlock *FalseSucc = nullptr);
// NYS == Not Yet Supported
@ -1071,7 +1077,7 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
// Generate destructors for temporaries in initialization expression.
TempDtorContext Context(/*IsConditional=*/false);
TempDtorContext Context;
VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
/*BindToTemporary=*/false, Context);
}
@ -2030,7 +2036,7 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
// Generate destructors for temporaries in initialization expression.
TempDtorContext Context(/*IsConditional=*/false);
TempDtorContext Context;
VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
/*BindToTemporary=*/false, Context);
}
@ -3412,7 +3418,7 @@ CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
if (BuildOpts.AddTemporaryDtors) {
// If adding implicit destructors visit the full expression for adding
// destructors of temporaries.
TempDtorContext Context(/*IsConditional=*/false);
TempDtorContext Context;
VisitForTemporaryDtors(E->getSubExpr(), false, Context);
// Full expression has to be added as CFGStmt so it will be sequenced
@ -3639,9 +3645,10 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
// We do not know at CFG-construction time whether the right-hand-side was
// executed, thus we add a branch node that depends on the temporary
// constructor call.
TempDtorContext RHSContext(/*IsConditional=*/true);
TempDtorContext RHSContext(
bothKnownTrue(Context.KnownExecuted, RHSExecuted));
VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
InsertTempDtorDecisionBlock(RHSContext, RHSExecuted);
InsertTempDtorDecisionBlock(RHSContext);
return Block;
}
@ -3698,7 +3705,6 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
}
void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
TryResult ConditionVal,
CFGBlock *FalseSucc) {
if (!Context.TerminatorExpr) {
// If no temporary was found, we do not need to insert a decision point.
@ -3707,9 +3713,9 @@ void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
assert(Context.TerminatorExpr);
CFGBlock *Decision = createBlock(false);
Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true));
addSuccessor(Decision, Block, !ConditionVal.isFalse());
addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
!ConditionVal.isTrue());
!Context.KnownExecuted.isTrue());
Block = Decision;
}
@ -3723,22 +3729,24 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
TryResult NegatedVal = ConditionVal;
if (NegatedVal.isKnown()) NegatedVal.negate();
TempDtorContext TrueContext(/*IsConditional=*/true);
TempDtorContext TrueContext(
bothKnownTrue(Context.KnownExecuted, ConditionVal));
VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
CFGBlock *TrueBlock = Block;
Block = ConditionBlock;
Succ = ConditionSucc;
TempDtorContext FalseContext(/*IsConditional=*/true);
TempDtorContext FalseContext(
bothKnownTrue(Context.KnownExecuted, NegatedVal));
VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
InsertTempDtorDecisionBlock(FalseContext, NegatedVal, TrueBlock);
InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
} else if (TrueContext.TerminatorExpr) {
Block = TrueBlock;
InsertTempDtorDecisionBlock(TrueContext, ConditionVal);
InsertTempDtorDecisionBlock(TrueContext);
} else {
InsertTempDtorDecisionBlock(FalseContext, NegatedVal);
InsertTempDtorDecisionBlock(FalseContext);
}
return Block;
}

View File

@ -185,11 +185,11 @@ int testTernaryConditionalNoreturnFalseBranch(bool value) {
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();
@ -209,6 +209,18 @@ int testStaticallySkppedLogicalAndBranch() {
int testConditionallyExecutedComplexLogicalBranch(bool value) {
value || (true && NoReturn());
} // expected-warning {{control may reach end of non-void function}}
int testConditionallyExecutedComplexLogicalBranch2(bool value) {
(true && value) || (true && NoReturn());
} // expected-warning {{control may reach end of non-void function}}
int testConditionallyExecutedComplexLogicalBranch3(bool value) {
(false && (Return() || true)) || (true && NoReturn());
}
int testConditionallyExecutedComplexLogicalBranch4(bool value) {
false || ((Return() || true) && (true && NoReturn()));
}
#if __cplusplus >= 201103L