]> granicus.if.org Git - clang/commitdiff
Mark successors as reachable/unreachable instead of changing the CFG.
authorManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 18:44:19 +0000 (18:44 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 18:44:19 +0000 (18:44 +0000)
As suggested by Ted, this makes a few warnings less aggressive.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215128 91177308-0d34-0410-b5e6-96231b3b80d8

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

index e6393777e3d510e4ff132b83e47fe751887d2cf6..29f21ec8d47f6ae0d5fc2042612df7471edbec8f 100644 (file)
@@ -479,6 +479,7 @@ private:
       AbstractConditionalOperator *E, bool BindToTemporary,
       TempDtorContext &Context);
   void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
+                                   TryResult ConditionVal,
                                    CFGBlock *FalseSucc = nullptr);
 
   // NYS == Not Yet Supported
@@ -3631,24 +3632,16 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
     BinaryOperator *E, TempDtorContext &Context) {
   if (E->isLogicalOp()) {
     VisitForTemporaryDtors(E->getLHS(), false, Context);
-    TryResult LHSVal = tryEvaluateBool(E->getLHS());
-    bool RHSNotExecuted = (E->getOpcode() == BO_LAnd && LHSVal.isFalse()) ||
-                          (E->getOpcode() == BO_LOr && LHSVal.isTrue());
-    if (RHSNotExecuted) {
-      return Block;
-    }
+    TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
+    if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
+      RHSExecuted.negate();
 
-    // 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()) {
-      VisitForTemporaryDtors(E->getRHS(), false, Context);
-    } else {
-      TempDtorContext RHSContext(/*IsConditional=*/true);
-      VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
-      InsertTempDtorDecisionBlock(RHSContext);
-    }
+    // 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);
+    VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
+    InsertTempDtorDecisionBlock(RHSContext, RHSExecuted);
 
     return Block;
   }
@@ -3705,6 +3698,7 @@ 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.
@@ -3713,8 +3707,9 @@ void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
   assert(Context.TerminatorExpr);
   CFGBlock *Decision = createBlock(false);
   Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true));
-  addSuccessor(Decision, Block);
-  addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ);
+  addSuccessor(Decision, Block, !ConditionVal.isFalse());
+  addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
+               !ConditionVal.isTrue());
   Block = Decision;
 }
 
@@ -3725,16 +3720,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
   CFGBlock *ConditionBlock = Block;
   CFGBlock *ConditionSucc = Succ;
   TryResult ConditionVal = tryEvaluateBool(E->getCond());
-
-  if (ConditionVal.isKnown()) {
-    if (ConditionVal.isTrue()) {
-      VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, Context);
-    } else {
-      assert(ConditionVal.isFalse());
-      VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, Context);
-    }
-    return Block;
-  }
+  TryResult NegatedVal = ConditionVal;
+  if (NegatedVal.isKnown()) NegatedVal.negate();
 
   TempDtorContext TrueContext(/*IsConditional=*/true);
   VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
@@ -3746,12 +3733,12 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
   VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
 
   if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
-    InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
+    InsertTempDtorDecisionBlock(FalseContext, NegatedVal, TrueBlock);
   } else if (TrueContext.TerminatorExpr) {
     Block = TrueBlock;
-    InsertTempDtorDecisionBlock(TrueContext);
+    InsertTempDtorDecisionBlock(TrueContext, ConditionVal);
   } else {
-    InsertTempDtorDecisionBlock(FalseContext);
+    InsertTempDtorDecisionBlock(FalseContext, NegatedVal);
   }
   return Block;
 }
index 3bb395f17d6378a2cf90f14c0f3b59edcb0fc5f0..36097c1e927d14effe63ed46d887ceb0972da74d 100644 (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,7 +209,7 @@ int testStaticallySkppedLogicalAndBranch() {
 
 int testConditionallyExecutedComplexLogicalBranch(bool value) {
   value || (true && NoReturn());
-} // expected-warning {{control may reach end of non-void function}}
+}
 
 #if __cplusplus >= 201103L
 namespace LambdaVsTemporaryDtor {