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