]> granicus.if.org Git - clang/commitdiff
Model temporary destructors from logical operators with known values.
authorManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 16:05:51 +0000 (16:05 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 16:05:51 +0000 (16:05 +0000)
If the truth value of a LHS is known, we can build the knowledge whether
a temporary destructor is executed or not into the CFG. This is needed
by the return type analysis.

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

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

index b9698d550bfba92d9a0c8d5925408054d501d569..96571fdbecd64fc9c6663f75756b05f119c8ab54 100644 (file)
@@ -3631,12 +3631,23 @@ CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
     BinaryOperator *E, TempDtorContext &Context) {
   if (E->isLogicalOp()) {
     VisitForTemporaryDtors(E->getLHS(), false, Context);
-    // 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.
+    TryResult LHSVal = tryEvaluateBool(E->getLHS());
+    bool RHSNotExecuted = (E->getOpcode() == BO_LAnd && LHSVal.isFalse()) ||
+                          (E->getOpcode() == BO_LOr && LHSVal.isTrue());
+    if (RHSNotExecuted) {
+      return Block;
+    }
+
     TempDtorContext RHSContext(/*IsConditional=*/true);
     VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
-    InsertTempDtorDecisionBlock(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())
+      InsertTempDtorDecisionBlock(RHSContext);
+
     return Block;
   }
 
index 8490be9be3829395b4b5ae06e3dae1dbbcb6aea6..519d27cf0b8dc81115406e894462eb6a5eb0602a 100644 (file)
@@ -183,6 +183,22 @@ int testTernaryConditionalNoreturnFalseBranch(bool value) {
   value ? Return() : (NoReturn() || NoReturn());
 } // expected-warning {{control may reach end of non-void function}}
 
+int testStaticallyExecutedLogicalOrBranch() {
+  false || NoReturn();
+}
+
+int testStaticallyExecutedLogicalAndBranch() {
+  true && NoReturn();
+}
+
+int testStaticallySkippedLogicalOrBranch() {
+  true || NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testStaticallySkppedLogicalAndBranch() {
+  false && NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
 
 #if __cplusplus >= 201103L
 namespace LambdaVsTemporaryDtor {