r215188 - Fix branch reachabiliy annotation for temp dtor branches.
Manuel Klimek
klimek at google.com
Fri Aug 8 00:37:13 PDT 2014
Author: klimek
Date: Fri Aug 8 02:37:13 2014
New Revision: 215188
URL: http://llvm.org/viewvc/llvm-project?rev=215188&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Analysis/CFG.cpp
cfe/trunk/test/SemaCXX/return-noreturn.cpp
Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=215188&r1=215187&r2=215188&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Fri Aug 8 02:37:13 2014
@@ -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(CXX
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(D
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::VisitExprWithClean
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::VisitBinaryOperato
// 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::VisitCXXBindTempor
}
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::InsertTempDtorDecisionB
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::VisitConditionalOp
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;
}
Modified: cfe/trunk/test/SemaCXX/return-noreturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/return-noreturn.cpp?rev=215188&r1=215187&r2=215188&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/return-noreturn.cpp (original)
+++ cfe/trunk/test/SemaCXX/return-noreturn.cpp Fri Aug 8 02:37:13 2014
@@ -185,11 +185,11 @@ int testTernaryConditionalNoreturnFalseB
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
More information about the cfe-commits
mailing list