]> granicus.if.org Git - clang/commitdiff
Only have one path in the CFG for ternaries if the condition is known.
authorManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 14:25:43 +0000 (14:25 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 7 Aug 2014 14:25:43 +0000 (14:25 +0000)
The return type analysis requires that the CFG is simplified when the
truth values of branches are statically known at analysis time.

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

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

index 20438b478779fc364598786d70341a444c8964e5..b9698d550bfba92d9a0c8d5925408054d501d569 100644 (file)
@@ -3711,15 +3711,24 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
   VisitForTemporaryDtors(E->getCond(), false, Context);
   CFGBlock *ConditionBlock = Block;
   CFGBlock *ConditionSucc = Succ;
+  TryResult ConditionVal = tryEvaluateBool(E->getCond());
 
   TempDtorContext TrueContext(/*IsConditional=*/true);
-  VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
+  if (!ConditionVal.isFalse()) {
+    VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
+    if (ConditionVal.isTrue())
+      return Block;
+  }
   CFGBlock *TrueBlock = Block;
 
   Block = ConditionBlock;
   Succ = ConditionSucc;
   TempDtorContext FalseContext(/*IsConditional=*/true);
-  VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
+  if (!ConditionVal.isTrue()) {
+    VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
+    if (ConditionVal.isFalse())
+      return Block;
+  }
 
   if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
     InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
index bafeafcf1cf0c3ac7b3f8d3f66387035b9bdcae0..8490be9be3829395b4b5ae06e3dae1dbbcb6aea6 100644 (file)
@@ -159,6 +159,22 @@ int testTernaryUnconditionalNoreturn() {
   true ? NoReturn() : NoReturn();
 }
 
+int testTernaryStaticallyConditionalNoretrunOnTrue() {
+  true ? NoReturn() : Return();
+}
+
+int testTernaryStaticallyConditionalRetrunOnTrue() {
+  true ? Return() : NoReturn();
+} // expected-warning {{control reaches end of non-void function}}
+
+int testTernaryStaticallyConditionalNoretrunOnFalse() {
+  false ? Return() : NoReturn();
+}
+
+int testTernaryStaticallyConditionalRetrunOnFalse() {
+  false ? NoReturn() : Return();
+} // expected-warning {{control reaches end of non-void function}}
+
 int testTernaryConditionalNoreturnTrueBranch(bool value) {
   value ? (NoReturn() || NoReturn()) : Return();
 } // expected-warning {{control may reach end of non-void function}}