]> granicus.if.org Git - clang/commitdiff
Fix CFG for temporary dtors when the branch taken is known.
authorManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 17:02:21 +0000 (17:02 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 17:02:21 +0000 (17:02 +0000)
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

lib/Analysis/CFG.cpp
test/SemaCXX/return-noreturn.cpp

index 96571fdbecd64fc9c6663f75756b05f119c8ab54..e6393777e3d510e4ff132b83e47fe751887d2cf6 100644 (file)
@@ -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);
index 519d27cf0b8dc81115406e894462eb6a5eb0602a..3bb395f17d6378a2cf90f14c0f3b59edcb0fc5f0 100644 (file)
@@ -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 {