[cfe-commits] r160218 - in /cfe/trunk: lib/Analysis/CFG.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngineC.cpp test/Analysis/auto-obj-dtors-cfg-output.cpp test/Analysis/domtest.c test/Analysis/temp-obj-dtors-cfg-output.cpp test/Sema/uninit-variables.c test/SemaCXX/uninitialized.cpp

Ted Kremenek kremenek at apple.com
Fri Jul 13 22:04:11 PDT 2012


Author: kremenek
Date: Sat Jul 14 00:04:10 2012
New Revision: 160218

URL: http://llvm.org/viewvc/llvm-project?rev=160218&view=rev
Log:
Refine CFG so that '&&' and '||' don't lead to extra confluence points when used in a branch, but
instead push the terminator for the branch down into the basic blocks of the subexpressions of '&&' and '||'
respectively.  This eliminates some artifical control-flow from the CFG and results in a more
compact CFG.

Note that this patch only alters the branches 'while', 'if' and 'for'.  This was complex enough for
one patch.  The remaining branches (e.g., do...while) can be handled in a separate patch, but they
weren't immediately tackled because they were less important.

It is possible that this patch introduces some subtle bugs, particularly w.r.t. to destructor placement.
I've tried to audit these changes, but it is also known that the destructor logic needs some refinement
in the area of '||' and '&&' regardless (i.e., their are known bugs).

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/test/Analysis/auto-obj-dtors-cfg-output.cpp
    cfe/trunk/test/Analysis/domtest.c
    cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp
    cfe/trunk/test/Sema/uninit-variables.c
    cfe/trunk/test/SemaCXX/uninitialized.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Sat Jul 14 00:04:10 2012
@@ -344,6 +344,10 @@
   CFGBlock *VisitLabelStmt(LabelStmt *L);
   CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
   CFGBlock *VisitLogicalOperator(BinaryOperator *B);
+  std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
+                                                         Stmt *Term,
+                                                         CFGBlock *TrueBlock,
+                                                         CFGBlock *FalseBlock);
   CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
   CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
   CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
@@ -1170,46 +1174,98 @@
   if (badCFG)
     return 0;
 
-  // create the block evaluating the LHS
-  CFGBlock *LHSBlock = createBlock(false);
-  LHSBlock->setTerminator(B);
+  return VisitLogicalOperator(B, 0, ConfluenceBlock, ConfluenceBlock).first;
+}
 
-  // create the block evaluating the RHS
-  Succ = ConfluenceBlock;
-  Block = NULL;
-  CFGBlock *RHSBlock = addStmt(B->getRHS());
+std::pair<CFGBlock*, CFGBlock*>
+CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
+                                 Stmt *Term,
+                                 CFGBlock *TrueBlock,
+                                 CFGBlock *FalseBlock) {
+
+  // Introspect the RHS.  If it is a nested logical operation, we recursively
+  // build the CFG using this function.  Otherwise, resort to default
+  // CFG construction behavior.
+  Expr *RHS = B->getRHS()->IgnoreParens();
+  CFGBlock *RHSBlock, *ExitBlock;
+
+  do {
+    if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
+      if (B_RHS->isLogicalOp()) {
+        llvm::tie(RHSBlock, ExitBlock) =
+          VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
+        break;
+      }
+
+    // The RHS is not a nested logical operation.  Don't push the terminator
+    // down further, but instead visit RHS and construct the respective
+    // pieces of the CFG, and link up the RHSBlock with the terminator
+    // we have been provided.
+    ExitBlock = RHSBlock = createBlock(false);
+
+    if (!Term) {
+      assert(TrueBlock == FalseBlock);
+      addSuccessor(RHSBlock, TrueBlock);
+    }
+    else {
+      RHSBlock->setTerminator(Term);
+      TryResult KnownVal = tryEvaluateBool(RHS);
+      addSuccessor(RHSBlock, KnownVal.isFalse() ? NULL : TrueBlock);
+      addSuccessor(RHSBlock, KnownVal.isTrue() ? NULL : FalseBlock);
+    }
 
-  if (RHSBlock) {
-    if (badCFG)
-      return 0;
-  } else {
-    // Create an empty block for cases where the RHS doesn't require
-    // any explicit statements in the CFG.
-    RHSBlock = createBlock();
+    Block = RHSBlock;
+    RHSBlock = addStmt(RHS);
   }
+  while (false);
+
+  if (badCFG)
+    return std::make_pair((CFGBlock*)0, (CFGBlock*)0);
 
   // Generate the blocks for evaluating the LHS.
+  Expr *LHS = B->getLHS()->IgnoreParens();
+
+  if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
+    if (B_LHS->isLogicalOp()) {
+      if (B->getOpcode() == BO_LOr)
+        FalseBlock = RHSBlock;
+      else
+        TrueBlock = RHSBlock;
+
+      // For the LHS, treat 'B' as the terminator that we want to sink
+      // into the nested branch.  The RHS always gets the top-most
+      // terminator.
+      return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
+    }
+
+  // Create the block evaluating the LHS.
+  // This contains the '&&' or '||' as the terminator.
+  CFGBlock *LHSBlock = createBlock(false);
+  LHSBlock->setTerminator(B);
+
   Block = LHSBlock;
-  CFGBlock *EntryLHSBlock = addStmt(B->getLHS());
+  CFGBlock *EntryLHSBlock = addStmt(LHS);
+
+  if (badCFG)
+    return std::make_pair((CFGBlock*)0, (CFGBlock*)0);
 
   // See if this is a known constant.
-  TryResult KnownVal = tryEvaluateBool(B->getLHS());
-  if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr))
-    KnownVal.negate();
+  TryResult KnownVal = tryEvaluateBool(LHS);
 
   // Now link the LHSBlock with RHSBlock.
   if (B->getOpcode() == BO_LOr) {
-    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
-    addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+    addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : TrueBlock);
+    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : RHSBlock);
   } else {
     assert(B->getOpcode() == BO_LAnd);
     addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
-    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+    addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : FalseBlock);
   }
 
-  return EntryLHSBlock;
+  return std::make_pair(EntryLHSBlock, ExitBlock);
 }
 
+
 CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
                                           AddStmtChoice asc) {
    // && or ||
@@ -1646,6 +1702,18 @@
     }
   }
 
+  // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by
+  // having these handle the actual control-flow jump.  Note that
+  // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)"
+  // we resort to the old control-flow behavior.  This special handling
+  // removes infeasible paths from the control-flow graph by having the
+  // control-flow transfer of '&&' or '||' go directly into the then/else
+  // blocks directly.
+  if (!I->getConditionVariable())
+    if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(I->getCond()))
+      if (Cond->isLogicalOp())
+        return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
+
   // Now create a new block containing the if statement.
   Block = createBlock(false);
 
@@ -1796,75 +1864,26 @@
   SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
   BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
 
-  // Because of short-circuit evaluation, the condition of the loop can span
-  // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
-  // evaluate the condition.
-  CFGBlock *ExitConditionBlock = createBlock(false);
-  CFGBlock *EntryConditionBlock = ExitConditionBlock;
-
-  // Set the terminator for the "exit" condition block.
-  ExitConditionBlock->setTerminator(F);
-
-  // Now add the actual condition to the condition block.  Because the condition
-  // itself may contain control-flow, new blocks may be created.
-  if (Stmt *C = F->getCond()) {
-    Block = ExitConditionBlock;
-    EntryConditionBlock = addStmt(C);
-    if (badCFG)
-      return 0;
-    assert(Block == EntryConditionBlock ||
-           (Block == 0 && EntryConditionBlock == Succ));
-
-    // If this block contains a condition variable, add both the condition
-    // variable and initializer to the CFG.
-    if (VarDecl *VD = F->getConditionVariable()) {
-      if (Expr *Init = VD->getInit()) {
-        autoCreateBlock();
-        appendStmt(Block, F->getConditionVariableDeclStmt());
-        EntryConditionBlock = addStmt(Init);
-        assert(Block == EntryConditionBlock);
-      }
-    }
-
-    if (Block) {
-      if (badCFG)
-        return 0;
-    }
-  }
-
-  // The condition block is the implicit successor for the loop body as well as
-  // any code above the loop.
-  Succ = EntryConditionBlock;
-
-  // See if this is a known constant.
-  TryResult KnownVal(true);
-
-  if (F->getCond())
-    KnownVal = tryEvaluateBool(F->getCond());
+  CFGBlock *BodyBlock = 0, *TransitionBlock = 0;
 
   // Now create the loop body.
   {
     assert(F->getBody());
 
-   // Save the current values for Block, Succ, and continue targets.
-   SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
-   SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
+    // Save the current values for Block, Succ, continue and break targets.
+    SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+    SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
 
-    // Create a new block to contain the (bottom) of the loop body.
-    Block = NULL;
-    
-    // Loop body should end with destructor of Condition variable (if any).
-    addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
+    // Create an empty block to represent the transition block for looping back
+    // to the head of the loop.  If we have increment code, it will
+    // go in this block as well.
+    Block = Succ = TransitionBlock = createBlock(false);
+    TransitionBlock->setLoopTarget(F);
 
     if (Stmt *I = F->getInc()) {
       // Generate increment code in its own basic block.  This is the target of
       // continue statements.
       Succ = addStmt(I);
-    } else {
-      // No increment code.  Create a special, empty, block that is used as the
-      // target block for "looping back" to the start of the loop.
-      assert(Succ == EntryConditionBlock);
-      Succ = Block ? Block : createBlock();
     }
 
     // Finish up the increment (or empty) block if it hasn't been already.
@@ -1875,11 +1894,13 @@
       Block = 0;
     }
 
-    ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
+   // The starting block for the loop increment is the block that should
+   // represent the 'loop target' for looping back to the start of the loop.
+   ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
+   ContinueJumpTarget.block->setLoopTarget(F);
 
-    // The starting block for the loop increment is the block that should
-    // represent the 'loop target' for looping back to the start of the loop.
-    ContinueJumpTarget.block->setLoopTarget(F);
+    // Loop body should end with destructor of Condition variable (if any).
+    addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
 
     // If body is not a compound statement create implicit scope
     // and add destructors.
@@ -1888,20 +1909,78 @@
 
     // Now populate the body block, and in the process create new blocks as we
     // walk the body of the loop.
-    CFGBlock *BodyBlock = addStmt(F->getBody());
+    BodyBlock = addStmt(F->getBody());
 
-    if (!BodyBlock)
-      BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);"
+    if (!BodyBlock) {
+      // In the case of "for (...;...;...);" we can have a null BodyBlock.
+      // Use the continue jump target as the proxy for the body.
+      BodyBlock = ContinueJumpTarget.block;
+    }
     else if (badCFG)
       return 0;
+  }
+  
+  // Because of short-circuit evaluation, the condition of the loop can span
+  // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
+  // evaluate the condition.
+  CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0;
 
-    // This new body block is a successor to our "exit" condition block.
+  do {
+    Expr *C = F->getCond();
+
+    // Specially handle logical operators, which have a slightly
+    // more optimal CFG representation.
+    if (BinaryOperator *Cond = dyn_cast_or_null<BinaryOperator>(C))
+      if (Cond->isLogicalOp()) {
+        llvm::tie(EntryConditionBlock, ExitConditionBlock) =
+          VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
+        break;
+      }
+
+    // The default case when not handling logical operators.
+    EntryConditionBlock = ExitConditionBlock = createBlock(false);
+    ExitConditionBlock->setTerminator(F);
+
+    // See if this is a known constant.
+    TryResult KnownVal(true);
+
+    if (C) {
+      // Now add the actual condition to the condition block.
+      // Because the condition itself may contain control-flow, new blocks may
+      // be created.  Thus we update "Succ" after adding the condition.
+      Block = ExitConditionBlock;
+      EntryConditionBlock = addStmt(C);
+
+      // If this block contains a condition variable, add both the condition
+      // variable and initializer to the CFG.
+      if (VarDecl *VD = F->getConditionVariable()) {
+        if (Expr *Init = VD->getInit()) {
+          autoCreateBlock();
+          appendStmt(Block, F->getConditionVariableDeclStmt());
+          EntryConditionBlock = addStmt(Init);
+          assert(Block == EntryConditionBlock);
+        }
+      }
+
+      if (Block && badCFG)
+        return 0;
+
+      KnownVal = tryEvaluateBool(C);
+    }
+
+    // Add the loop body entry as a successor to the condition.
     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
-  }
+    // Link up the condition block with the code that follows the loop.  (the
+    // false branch).
+    addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
 
-  // Link up the condition block with the code that follows the loop.  (the
-  // false branch).
-  addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+  } while (false);
+
+  // Link up the loop-back block to the entry condition block.
+  addSuccessor(TransitionBlock, EntryConditionBlock);
+  
+  // The condition block is the implicit successor for any code above the loop.
+  Succ = EntryConditionBlock;
 
   // If the loop contains initialization, create a new block for those
   // statements.  This block can also contain statements that precede the loop.
@@ -2109,74 +2188,30 @@
       return 0;
     LoopSuccessor = Block;
     Block = 0;
-  } else
+  } else {
     LoopSuccessor = Succ;
-
-  // Because of short-circuit evaluation, the condition of the loop can span
-  // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
-  // evaluate the condition.
-  CFGBlock *ExitConditionBlock = createBlock(false);
-  CFGBlock *EntryConditionBlock = ExitConditionBlock;
-
-  // Set the terminator for the "exit" condition block.
-  ExitConditionBlock->setTerminator(W);
-
-  // Now add the actual condition to the condition block.  Because the condition
-  // itself may contain control-flow, new blocks may be created.  Thus we update
-  // "Succ" after adding the condition.
-  if (Stmt *C = W->getCond()) {
-    Block = ExitConditionBlock;
-    EntryConditionBlock = addStmt(C);
-    // The condition might finish the current 'Block'.
-    Block = EntryConditionBlock;
-
-    // If this block contains a condition variable, add both the condition
-    // variable and initializer to the CFG.
-    if (VarDecl *VD = W->getConditionVariable()) {
-      if (Expr *Init = VD->getInit()) {
-        autoCreateBlock();
-        appendStmt(Block, W->getConditionVariableDeclStmt());        
-        EntryConditionBlock = addStmt(Init);
-        assert(Block == EntryConditionBlock);
-      }
-    }
-
-    if (Block) {
-      if (badCFG)
-        return 0;
-    }
   }
 
-  // The condition block is the implicit successor for the loop body as well as
-  // any code above the loop.
-  Succ = EntryConditionBlock;
-
-  // See if this is a known constant.
-  const TryResult& KnownVal = tryEvaluateBool(W->getCond());
+  CFGBlock *BodyBlock = 0, *TransitionBlock = 0;
 
   // Process the loop body.
   {
     assert(W->getBody());
 
-    // Save the current values for Block, Succ, and continue and break targets
+    // Save the current values for Block, Succ, continue and break targets.
     SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
     SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
-        save_break(BreakJumpTarget);
+                               save_break(BreakJumpTarget);
 
     // Create an empty block to represent the transition block for looping back
     // to the head of the loop.
-    Block = 0;
-    assert(Succ == EntryConditionBlock);
-    Succ = createBlock();
-    Succ->setLoopTarget(W);
+    Succ = TransitionBlock = createBlock(false);
+    TransitionBlock->setLoopTarget(W);
     ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
 
     // All breaks should go to the code following the loop.
     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
 
-    // NULL out Block to force lazy instantiation of blocks for the body.
-    Block = NULL;
-
     // Loop body should end with destructor of Condition variable (if any).
     addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
 
@@ -2186,22 +2221,69 @@
       addLocalScopeAndDtors(W->getBody());
 
     // Create the body.  The returned block is the entry to the loop body.
-    CFGBlock *BodyBlock = addStmt(W->getBody());
+    BodyBlock = addStmt(W->getBody());
 
     if (!BodyBlock)
       BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
-    else if (Block) {
-      if (badCFG)
-        return 0;
+    else if (Block && badCFG)
+      return 0;
+  }
+
+  // Because of short-circuit evaluation, the condition of the loop can span
+  // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
+  // evaluate the condition.
+  CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0;
+
+  do {
+    Expr *C = W->getCond();
+
+    // Specially handle logical operators, which have a slightly
+    // more optimal CFG representation.
+    if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C))
+      if (Cond->isLogicalOp()) {
+        llvm::tie(EntryConditionBlock, ExitConditionBlock) =
+          VisitLogicalOperator(Cond, W, BodyBlock,
+                               LoopSuccessor);
+        break;
+      }
+
+    // The default case when not handling logical operators.
+    EntryConditionBlock = ExitConditionBlock = createBlock(false);
+    ExitConditionBlock->setTerminator(W);
+
+    // Now add the actual condition to the condition block.
+    // Because the condition itself may contain control-flow, new blocks may
+    // be created.  Thus we update "Succ" after adding the condition.
+    Block = ExitConditionBlock;
+    Block = EntryConditionBlock = addStmt(C);
+
+    // If this block contains a condition variable, add both the condition
+    // variable and initializer to the CFG.
+    if (VarDecl *VD = W->getConditionVariable()) {
+      if (Expr *Init = VD->getInit()) {
+        autoCreateBlock();
+        appendStmt(Block, W->getConditionVariableDeclStmt());
+        EntryConditionBlock = addStmt(Init);
+        assert(Block == EntryConditionBlock);
+      }
     }
 
+    if (Block && badCFG)
+      return 0;
+
+    // See if this is a known constant.
+    const TryResult& KnownVal = tryEvaluateBool(C);
+
     // Add the loop body entry as a successor to the condition.
     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
-  }
+    // Link up the condition block with the code that follows the loop.  (the
+    // false branch).
+    addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
 
-  // Link up the condition block with the code that follows the loop.  (the
-  // false branch).
-  addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
+  } while(false);
+
+  // Link up the loop-back block to the entry condition block.
+  addSuccessor(TransitionBlock, EntryConditionBlock);
 
   // There can be no more statements in the condition block since we loop back
   // to this block.  NULL out Block to force lazy creation of another block.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Sat Jul 14 00:04:10 2012
@@ -1208,6 +1208,45 @@
   return state->getSVal(Ex, LCtx);
 }
 
+static const Stmt *ResolveCondition(const Stmt *Condition,
+                                    const CFGBlock *B) {
+  if (const Expr *Ex = dyn_cast<Expr>(Condition))
+    Condition = Ex->IgnoreParens();
+
+  const BinaryOperator *BO = dyn_cast<BinaryOperator>(Condition);
+  if (!BO || !BO->isLogicalOp())
+    return Condition;
+
+  // For logical operations, we still have the case where some branches
+  // use the traditional "merge" approach and others sink the branch
+  // directly into the basic blocks representing the logical operation.
+  // We need to distinguish between those two cases here.
+
+  // The invariants are still shifting, but it is possible that the
+  // last element in a CFGBlock is not a CFGStmt.  Look for the last
+  // CFGStmt as the value of the condition.
+  CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
+  for (; I != E; ++I) {
+    CFGElement Elem = *I;
+    CFGStmt *CS = dyn_cast<CFGStmt>(&Elem);
+    if (!CS)
+      continue;
+    if (CS->getStmt() != Condition)
+      break;
+    return Condition;
+  }
+
+  assert(I != E);
+
+  while (Condition) {
+    BO = dyn_cast<BinaryOperator>(Condition);
+    if (!BO || !BO->isLogicalOp())
+      return Condition;
+    Condition = BO->getRHS()->IgnoreParens();
+  }
+  llvm_unreachable("could not resolve condition");
+}
+
 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                NodeBuilderContext& BldCtx,
                                ExplodedNode *Pred,
@@ -1224,6 +1263,12 @@
     return;
   }
 
+
+  // Resolve the condition in the precense of nested '||' and '&&'.
+  if (const Expr *Ex = dyn_cast<Expr>(Condition))
+    Condition = Ex->IgnoreParens();
+
+  Condition = ResolveCondition(Condition, BldCtx.getBlock());
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 Condition->getLocStart(),
                                 "Error evaluating branch");

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Sat Jul 14 00:04:10 2012
@@ -499,48 +499,43 @@
 
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   ProgramStateRef state = Pred->getState();
-  const LocationContext *LCtx = Pred->getLocationContext();
-  SVal X = state->getSVal(B, LCtx);
-  assert(X.isUndef());
-  
-  const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
-  assert(Ex);
-  
-  if (Ex == B->getRHS()) {
-    X = state->getSVal(Ex, LCtx);
-    
-    // Handle undefined values.
-    if (X.isUndef()) {
-      Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
-      return;
-    }
-    
-    DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);
-    
-    // We took the RHS.  Because the value of the '&&' or '||' expression must
-    // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0
-    // or 1.  Alternatively, we could take a lazy approach, and calculate this
-    // value later when necessary.  We don't have the machinery in place for
-    // this right now, and since most logical expressions are used for branches,
-    // the payoff is not likely to be large.  Instead, we do eager evaluation.
-    if (ProgramStateRef newState = state->assume(XD, true))
-      Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, LCtx,
-                                  svalBuilder.makeIntVal(1U, B->getType())));
-    
-    if (ProgramStateRef newState = state->assume(XD, false))
-      Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, LCtx,
-                                  svalBuilder.makeIntVal(0U, B->getType())));
+
+  ExplodedNode *N = Pred;
+  while (!isa<BlockEntrance>(N->getLocation())) {
+    ProgramPoint P = N->getLocation();
+    assert(isa<PreStmt>(P)|| isa<PreStmtPurgeDeadSymbols>(P));
+    (void) P;
+    assert(N->pred_size() == 1);
+    N = *N->pred_begin();
+  }
+  assert(N->pred_size() == 1);
+  N = *N->pred_begin();
+  BlockEdge BE = cast<BlockEdge>(N->getLocation());
+  SVal X;
+
+  // Determine the value of the expression by introspecting how we
+  // got this location in the CFG.  This requires looking at the previous
+  // block we were in and what kind of control-flow transfer was involved.
+  const CFGBlock *SrcBlock = BE.getSrc();
+  // The only terminator (if there is one) that makes sense is a logical op.
+  CFGTerminator T = SrcBlock->getTerminator();
+  if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
+    assert(Term->isLogicalOp());
+    assert(SrcBlock->succ_size() == 2);
+    // Did we take the true or false branch?
+    unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
+    X = svalBuilder.makeIntVal(constant, B->getType());
   }
   else {
-    // We took the LHS expression.  Depending on whether we are '&&' or
-    // '||' we know what the value of the expression is via properties of
-    // the short-circuiting.
-    X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
-                               B->getType());
-    Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
+    // If there is no terminator, by construction the last statement
+    // in SrcBlock is the value of the enclosing expression.
+    assert(!SrcBlock->empty());
+    CFGStmt Elem = cast<CFGStmt>(*SrcBlock->rbegin());
+    const Stmt *S = Elem.getStmt();
+    X = N->getState()->getSVal(S, Pred->getLocationContext());
   }
+
+  Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
 }
 
 void ExprEngine::VisitInitListExpr(const InitListExpr *IE,

Modified: cfe/trunk/test/Analysis/auto-obj-dtors-cfg-output.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/auto-obj-dtors-cfg-output.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/auto-obj-dtors-cfg-output.cpp (original)
+++ cfe/trunk/test/Analysis/auto-obj-dtors-cfg-output.cpp Sat Jul 14 00:04:10 2012
@@ -416,121 +416,121 @@
 // CHECK:  [B6 (ENTRY)]
 // CHECK:    Succs (1): B5
 // CHECK:  [B1]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
+// CHECK:    1: [B4.4].~A() (Implicit destructor)
 // CHECK:    2: [B5.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B2
+// CHECK:    Preds (1): B4
 // CHECK:    Succs (1): B0
 // CHECK:  [B2]
-// CHECK:    1: a
-// CHECK:    2: [B2.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    3: [B2.2] (CXXConstructExpr, class A)
-// CHECK:    4: A b = a;
-// CHECK:    5: b
-// CHECK:    6: [B2.5] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    7: [B2.6].operator int
-// CHECK:    8: [B2.7]()
-// CHECK:    9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:   10: [B2.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK:    T: while [B2.10]
-// CHECK:    Preds (2): B3 B5
-// CHECK:    Succs (2): B4 B1
+// CHECK:    Preds (1): B3
+// CHECK:    Succs (1): B4
 // CHECK:  [B3]
+// CHECK:    1:  (CXXConstructExpr, class A)
+// CHECK:    2: A c;
+// CHECK:    3: [B3.2].~A() (Implicit destructor)
+// CHECK:    4: [B4.4].~A() (Implicit destructor)
 // CHECK:    Preds (1): B4
 // CHECK:    Succs (1): B2
 // CHECK:  [B4]
-// CHECK:    1:  (CXXConstructExpr, class A)
-// CHECK:    2: A c;
-// CHECK:    3: [B4.2].~A() (Implicit destructor)
-// CHECK:    4: [B2.4].~A() (Implicit destructor)
-// CHECK:    Preds (1): B2
-// CHECK:    Succs (1): B3
+// CHECK:    1: a
+// CHECK:    2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    3: [B4.2] (CXXConstructExpr, class A)
+// CHECK:    4: A b = a;
+// CHECK:    5: b
+// CHECK:    6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    7: [B4.6].operator int
+// CHECK:    8: [B4.7]()
+// CHECK:    9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:   10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK:    T: while [B4.10]
+// CHECK:    Preds (2): B2 B5
+// CHECK:    Succs (2): B3 B1
 // CHECK:  [B5]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A a;
 // CHECK:    Preds (1): B6
-// CHECK:    Succs (1): B2
+// CHECK:    Succs (1): B4
 // CHECK:  [B0 (EXIT)]
 // CHECK:    Preds (1): B1
 // CHECK:  [B12 (ENTRY)]
 // CHECK:    Succs (1): B11
 // CHECK:  [B1]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
+// CHECK:    1: [B10.4].~A() (Implicit destructor)
 // CHECK:    2:  (CXXConstructExpr, class A)
 // CHECK:    3: A e;
 // CHECK:    4: [B1.3].~A() (Implicit destructor)
 // CHECK:    5: [B11.2].~A() (Implicit destructor)
-// CHECK:    Preds (2): B9 B2
+// CHECK:    Preds (2): B8 B10
 // CHECK:    Succs (1): B0
 // CHECK:  [B2]
-// CHECK:    1: a
-// CHECK:    2: [B2.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    3: [B2.2] (CXXConstructExpr, class A)
-// CHECK:    4: A b = a;
-// CHECK:    5: b
-// CHECK:    6: [B2.5] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    7: [B2.6].operator int
-// CHECK:    8: [B2.7]()
-// CHECK:    9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:   10: [B2.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK:    T: while [B2.10]
-// CHECK:    Preds (2): B3 B11
-// CHECK:    Succs (2): B10 B1
+// CHECK:    Preds (2): B3 B6
+// CHECK:    Succs (1): B10
 // CHECK:  [B3]
-// CHECK:    Preds (2): B4 B7
-// CHECK:    Succs (1): B2
-// CHECK:  [B4]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A d;
-// CHECK:    3: [B4.2].~A() (Implicit destructor)
-// CHECK:    4: [B10.2].~A() (Implicit destructor)
-// CHECK:    5: [B2.4].~A() (Implicit destructor)
-// CHECK:    Preds (1): B6
-// CHECK:    Succs (1): B3
-// CHECK:  [B5]
+// CHECK:    3: [B3.2].~A() (Implicit destructor)
+// CHECK:    4: [B9.2].~A() (Implicit destructor)
+// CHECK:    5: [B10.4].~A() (Implicit destructor)
+// CHECK:    Preds (1): B5
+// CHECK:    Succs (1): B2
+// CHECK:  [B4]
 // CHECK:    1: return;
-// CHECK:    2: [B10.2].~A() (Implicit destructor)
-// CHECK:    3: [B2.4].~A() (Implicit destructor)
+// CHECK:    2: [B9.2].~A() (Implicit destructor)
+// CHECK:    3: [B10.4].~A() (Implicit destructor)
 // CHECK:    4: [B11.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B6
+// CHECK:    Preds (1): B5
 // CHECK:    Succs (1): B0
-// CHECK:  [B6]
+// CHECK:  [B5]
 // CHECK:    1: UV
-// CHECK:    2: [B6.1] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B6.2]
-// CHECK:    Preds (1): B8
-// CHECK:    Succs (2): B5 B4
-// CHECK:  [B7]
-// CHECK:    1: [B10.2].~A() (Implicit destructor)
-// CHECK:    2: [B2.4].~A() (Implicit destructor)
+// CHECK:    2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B5.2]
+// CHECK:    Preds (1): B7
+// CHECK:    Succs (2): B4 B3
+// CHECK:  [B6]
+// CHECK:    1: [B9.2].~A() (Implicit destructor)
+// CHECK:    2: [B10.4].~A() (Implicit destructor)
 // CHECK:    T: continue;
-// CHECK:    Preds (1): B8
-// CHECK:    Succs (1): B3
-// CHECK:  [B8]
+// CHECK:    Preds (1): B7
+// CHECK:    Succs (1): B2
+// CHECK:  [B7]
 // CHECK:    1: UV
-// CHECK:    2: [B8.1] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B8.2]
-// CHECK:    Preds (1): B10
-// CHECK:    Succs (2): B7 B6
-// CHECK:  [B9]
-// CHECK:    1: [B10.2].~A() (Implicit destructor)
+// CHECK:    2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B7.2]
+// CHECK:    Preds (1): B9
+// CHECK:    Succs (2): B6 B5
+// CHECK:  [B8]
+// CHECK:    1: [B9.2].~A() (Implicit destructor)
 // CHECK:    T: break;
-// CHECK:    Preds (1): B10
+// CHECK:    Preds (1): B9
 // CHECK:    Succs (1): B1
-// CHECK:  [B10]
+// CHECK:  [B9]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A c;
 // CHECK:    3: UV
-// CHECK:    4: [B10.3] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B10.4]
-// CHECK:    Preds (1): B2
-// CHECK:    Succs (2): B9 B8
+// CHECK:    4: [B9.3] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B9.4]
+// CHECK:    Preds (1): B10
+// CHECK:    Succs (2): B8 B7
+// CHECK:  [B10]
+// CHECK:    1: a
+// CHECK:    2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    3: [B10.2] (CXXConstructExpr, class A)
+// CHECK:    4: A b = a;
+// CHECK:    5: b
+// CHECK:    6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    7: [B10.6].operator int
+// CHECK:    8: [B10.7]()
+// CHECK:    9: [B10.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:   10: [B10.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK:    T: while [B10.10]
+// CHECK:    Preds (2): B2 B11
+// CHECK:    Succs (2): B9 B1
 // CHECK:  [B11]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A a;
 // CHECK:    Preds (1): B12
-// CHECK:    Succs (1): B2
+// CHECK:    Succs (1): B10
 // CHECK:  [B0 (EXIT)]
-// CHECK:    Preds (2): B1 B5
+// CHECK:    Preds (2): B1 B4
 // CHECK:  [B4 (ENTRY)]
 // CHECK:    Succs (1): B2
 // CHECK:  [B1]
@@ -717,124 +717,124 @@
 // CHECK:  [B6 (ENTRY)]
 // CHECK:    Succs (1): B5
 // CHECK:  [B1]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
+// CHECK:    1: [B4.4].~A() (Implicit destructor)
 // CHECK:    2: [B5.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B2
+// CHECK:    Preds (1): B4
 // CHECK:    Succs (1): B0
 // CHECK:  [B2]
-// CHECK:    1: a
-// CHECK:    2: [B2.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    3: [B2.2] (CXXConstructExpr, class A)
-// CHECK:    4: A b = a;
-// CHECK:    5: b
-// CHECK:    6: [B2.5] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    7: [B2.6].operator int
-// CHECK:    8: [B2.7]()
-// CHECK:    9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:   10: [B2.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK:    T: for (...; [B2.10]; )
-// CHECK:    Preds (2): B3 B5
-// CHECK:    Succs (2): B4 B1
+// CHECK:    Preds (1): B3
+// CHECK:    Succs (1): B4
 // CHECK:  [B3]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
+// CHECK:    1:  (CXXConstructExpr, class A)
+// CHECK:    2: A c;
+// CHECK:    3: [B3.2].~A() (Implicit destructor)
+// CHECK:    4: [B4.4].~A() (Implicit destructor)
 // CHECK:    Preds (1): B4
 // CHECK:    Succs (1): B2
 // CHECK:  [B4]
-// CHECK:    1:  (CXXConstructExpr, class A)
-// CHECK:    2: A c;
-// CHECK:    3: [B4.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B2
-// CHECK:    Succs (1): B3
+// CHECK:    1: a
+// CHECK:    2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    3: [B4.2] (CXXConstructExpr, class A)
+// CHECK:    4: A b = a;
+// CHECK:    5: b
+// CHECK:    6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    7: [B4.6].operator int
+// CHECK:    8: [B4.7]()
+// CHECK:    9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:   10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK:    T: for (...; [B4.10]; )
+// CHECK:    Preds (2): B2 B5
+// CHECK:    Succs (2): B3 B1
 // CHECK:  [B5]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A a;
 // CHECK:    Preds (1): B6
-// CHECK:    Succs (1): B2
+// CHECK:    Succs (1): B4
 // CHECK:  [B0 (EXIT)]
 // CHECK:    Preds (1): B1
 // CHECK:  [B12 (ENTRY)]
 // CHECK:    Succs (1): B11
 // CHECK:  [B1]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
+// CHECK:    1: [B10.4].~A() (Implicit destructor)
 // CHECK:    2: [B11.4].~A() (Implicit destructor)
 // CHECK:    3:  (CXXConstructExpr, class A)
 // CHECK:    4: A f;
 // CHECK:    5: [B1.4].~A() (Implicit destructor)
 // CHECK:    6: [B11.2].~A() (Implicit destructor)
-// CHECK:    Preds (2): B9 B2
+// CHECK:    Preds (2): B8 B10
 // CHECK:    Succs (1): B0
 // CHECK:  [B2]
-// CHECK:    1: b
-// CHECK:    2: [B2.1] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    3: [B2.2] (CXXConstructExpr, class A)
-// CHECK:    4: A c = b;
-// CHECK:    5: c
-// CHECK:    6: [B2.5] (ImplicitCastExpr, NoOp, const class A)
-// CHECK:    7: [B2.6].operator int
-// CHECK:    8: [B2.7]()
-// CHECK:    9: [B2.8] (ImplicitCastExpr, UserDefinedConversion, int)
-// CHECK:   10: [B2.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK:    T: for (...; [B2.10]; )
-// CHECK:    Preds (2): B3 B11
-// CHECK:    Succs (2): B10 B1
+// CHECK:    Preds (2): B3 B6
+// CHECK:    Succs (1): B10
 // CHECK:  [B3]
-// CHECK:    1: [B2.4].~A() (Implicit destructor)
-// CHECK:    Preds (2): B4 B7
-// CHECK:    Succs (1): B2
-// CHECK:  [B4]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A e;
-// CHECK:    3: [B4.2].~A() (Implicit destructor)
-// CHECK:    4: [B10.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B6
-// CHECK:    Succs (1): B3
-// CHECK:  [B5]
+// CHECK:    3: [B3.2].~A() (Implicit destructor)
+// CHECK:    4: [B9.2].~A() (Implicit destructor)
+// CHECK:    5: [B10.4].~A() (Implicit destructor)
+// CHECK:    Preds (1): B5
+// CHECK:    Succs (1): B2
+// CHECK:  [B4]
 // CHECK:    1: return;
-// CHECK:    2: [B10.2].~A() (Implicit destructor)
-// CHECK:    3: [B2.4].~A() (Implicit destructor)
+// CHECK:    2: [B9.2].~A() (Implicit destructor)
+// CHECK:    3: [B10.4].~A() (Implicit destructor)
 // CHECK:    4: [B11.4].~A() (Implicit destructor)
 // CHECK:    5: [B11.2].~A() (Implicit destructor)
-// CHECK:    Preds (1): B6
+// CHECK:    Preds (1): B5
 // CHECK:    Succs (1): B0
-// CHECK:  [B6]
+// CHECK:  [B5]
 // CHECK:    1: UV
-// CHECK:    2: [B6.1] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B6.2]
-// CHECK:    Preds (1): B8
-// CHECK:    Succs (2): B5 B4
-// CHECK:  [B7]
-// CHECK:    1: [B10.2].~A() (Implicit destructor)
+// CHECK:    2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B5.2]
+// CHECK:    Preds (1): B7
+// CHECK:    Succs (2): B4 B3
+// CHECK:  [B6]
+// CHECK:    1: [B9.2].~A() (Implicit destructor)
 // CHECK:    T: continue;
-// CHECK:    Preds (1): B8
-// CHECK:    Succs (1): B3
-// CHECK:  [B8]
+// CHECK:    Preds (1): B7
+// CHECK:    Succs (1): B2
+// CHECK:  [B7]
 // CHECK:    1: UV
-// CHECK:    2: [B8.1] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B8.2]
-// CHECK:    Preds (1): B10
-// CHECK:    Succs (2): B7 B6
-// CHECK:  [B9]
-// CHECK:    1: [B10.2].~A() (Implicit destructor)
+// CHECK:    2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B7.2]
+// CHECK:    Preds (1): B9
+// CHECK:    Succs (2): B6 B5
+// CHECK:  [B8]
+// CHECK:    1: [B9.2].~A() (Implicit destructor)
 // CHECK:    T: break;
-// CHECK:    Preds (1): B10
+// CHECK:    Preds (1): B9
 // CHECK:    Succs (1): B1
-// CHECK:  [B10]
+// CHECK:  [B9]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A d;
 // CHECK:    3: UV
-// CHECK:    4: [B10.3] (ImplicitCastExpr, LValueToRValue, _Bool)
-// CHECK:    T: if [B10.4]
-// CHECK:    Preds (1): B2
-// CHECK:    Succs (2): B9 B8
+// CHECK:    4: [B9.3] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK:    T: if [B9.4]
+// CHECK:    Preds (1): B10
+// CHECK:    Succs (2): B8 B7
+// CHECK:  [B10]
+// CHECK:    1: b
+// CHECK:    2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    3: [B10.2] (CXXConstructExpr, class A)
+// CHECK:    4: A c = b;
+// CHECK:    5: c
+// CHECK:    6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:    7: [B10.6].operator int
+// CHECK:    8: [B10.7]()
+// CHECK:    9: [B10.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:   10: [B10.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK:    T: for (...; [B10.10]; )
+// CHECK:    Preds (2): B2 B11
+// CHECK:    Succs (2): B9 B1
 // CHECK:  [B11]
 // CHECK:    1:  (CXXConstructExpr, class A)
 // CHECK:    2: A a;
 // CHECK:    3:  (CXXConstructExpr, class A)
 // CHECK:    4: A b;
 // CHECK:    Preds (1): B12
-// CHECK:    Succs (1): B2
+// CHECK:    Succs (1): B10
 // CHECK:  [B0 (EXIT)]
-// CHECK:    Preds (2): B1 B5
+// CHECK:    Preds (2): B1 B4
 // CHECK:  [B3 (ENTRY)]
 // CHECK:    Succs (1): B0
 // CHECK:  [B1]
@@ -862,3 +862,4 @@
 // CHECK:    Succs (1): B0
 // CHECK:  [B0 (EXIT)]
 // CHECK:    Preds (3): B2 B1 B3
+

Modified: cfe/trunk/test/Analysis/domtest.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/domtest.c?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/domtest.c (original)
+++ cfe/trunk/test/Analysis/domtest.c Sat Jul 14 00:04:10 2012
@@ -1,4 +1,6 @@
-// RUN: %clang -cc1 -analyze -analyzer-checker=debug.DumpDominators %s 2>&1 | FileCheck %s
+// RUN: rm -f %t
+// RUN: %clang -cc1 -analyze -analyzer-checker=debug.DumpDominators %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
 
 // Test the DominatorsTree implementation with various control flows
 int test1()
@@ -24,13 +26,13 @@
 
 // CHECK: Immediate dominance tree (Node#,IDom#):
 // CHECK: (0,1)
-// CHECK: (1,2)
-// CHECK: (2,8)
-// CHECK: (3,4)
-// CHECK: (4,7)
-// CHECK: (5,7)
+// CHECK: (1,7)
+// CHECK: (2,3)
+// CHECK: (3,6)
+// CHECK: (4,6)
+// CHECK: (5,6)
 // CHECK: (6,7)
-// CHECK: (7,2)
+// CHECK: (7,8)
 // CHECK: (8,9)
 // CHECK: (9,9)
 
@@ -55,9 +57,9 @@
 // CHECK: Immediate dominance tree (Node#,IDom#):
 // CHECK: (0,1)
 // CHECK: (1,6)
-// CHECK: (2,6)
+// CHECK: (2,3)
 // CHECK: (3,4)
-// CHECK: (4,2)
+// CHECK: (4,6)
 // CHECK: (5,6)
 // CHECK: (6,7)
 // CHECK: (7,7)
@@ -83,11 +85,11 @@
 // CHECK: Immediate dominance tree (Node#,IDom#):
 // CHECK: (0,1)
 // CHECK: (1,7)
-// CHECK: (2,7)
+// CHECK: (2,5)
 // CHECK: (3,4)
-// CHECK: (4,2)
+// CHECK: (4,5)
 // CHECK: (5,6)
-// CHECK: (6,4)
+// CHECK: (6,7)
 // CHECK: (7,8)
 // CHECK: (8,8)
 
@@ -108,16 +110,16 @@
 
 // CHECK: Immediate dominance tree (Node#,IDom#):
 // CHECK: (0,1)
-// CHECK: (1,2)
-// CHECK: (2,11)
-// CHECK: (3,10)
-// CHECK: (4,10)
-// CHECK: (5,6)
-// CHECK: (6,4)
-// CHECK: (7,10)
+// CHECK: (1,10)
+// CHECK: (2,9)
+// CHECK: (3,4)
+// CHECK: (4,5)
+// CHECK: (5,9)
+// CHECK: (6,7)
+// CHECK: (7,8)
 // CHECK: (8,9)
-// CHECK: (9,7)
-// CHECK: (10,2)
+// CHECK: (9,10)
+// CHECK: (10,11)
 // CHECK: (11,12)
 // CHECK: (12,12)
 
@@ -163,3 +165,4 @@
 // CHECK: (10,11)
 // CHECK: (11,11)
 
+

Modified: cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp (original)
+++ cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp Sat Jul 14 00:04:10 2012
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -cfg-add-implicit-dtors -cfg-add-initializers %s 2>&1 | FileCheck %s
+// RUN: rm -f %t
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG -cfg-add-implicit-dtors -cfg-add-initializers %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
 // XPASS: *
 
 class A {
@@ -106,9 +108,88 @@
   : a(int(A()) + int(B()))
   , b() {}
 
+// CHECK:   [B1 (ENTRY)]
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B1 (ENTRY)]
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: A() (CXXConstructExpr, class A)
+// CHECK:     2: [B1.1] (BindTemporary)
+// CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:     4: [B1.3]
+// CHECK:     5: [B1.4] (CXXConstructExpr, class A)
+// CHECK:     6: ~A() (Temporary object destructor)
+// CHECK:     7: return [B1.5];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: false
+// CHECK:     2: return [B1.1];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: 0
+// CHECK:     2: return [B1.1];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B1 (ENTRY)]
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B1 (ENTRY)]
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: true
+// CHECK:     2: return [B1.1];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: 1
+// CHECK:     2: return [B1.1];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
+// CHECK:   [B2 (ENTRY)]
+// CHECK:     Succs (1): B1
+// CHECK:   [B1]
+// CHECK:     1: A() (CXXConstructExpr, class A)
+// CHECK:     2: [B1.1] (BindTemporary)
+// CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
+// CHECK:     4: [B1.3]
+// CHECK:     5: [B1.4] (CXXConstructExpr, class A)
+// CHECK:     6: ~A() (Temporary object destructor)
+// CHECK:     7: return [B1.5];
+// CHECK:     Preds (1): B2
+// CHECK:     Succs (1): B0
+// CHECK:   [B0 (EXIT)]
+// CHECK:     Preds (1): B1
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
-
 // CHECK:   [B1]
 // CHECK:     1: A() (CXXConstructExpr, class A)
 // CHECK:     2: [B1.1] (BindTemporary)
@@ -150,7 +231,7 @@
 // CHECK:   [B0 (EXIT)]
 // CHECK:     Preds (1): B1
 // CHECK:   [B10 (ENTRY)]
-// CHECK:     Succs (1): B8
+// CHECK:     Succs (1): B9
 // CHECK:   [B1]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: int b;
@@ -161,62 +242,62 @@
 // CHECK:     Preds (1): B3
 // CHECK:     Succs (1): B1
 // CHECK:   [B3]
-// CHECK:     1: [B4.6] && [B5.5]
+// CHECK:     1: [B5.6] && [B4.5]
 // CHECK:     2: foo
 // CHECK:     3: [B3.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
 // CHECK:     4: [B3.3]([B3.1])
-// CHECK:     T: [B4.6] && ...
-// CHECK:     Preds (2): B5 B4
+// CHECK:     T: [B5.6] && ...
+// CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B2 B1
 // CHECK:   [B4]
+// CHECK:     1: B() (CXXConstructExpr, class B)
+// CHECK:     2: [B4.1] (BindTemporary)
+// CHECK:     3: [B4.2].operator _Bool
+// CHECK:     4: [B4.3]()
+// CHECK:     5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     Preds (1): B5
+// CHECK:     Succs (1): B3
+// CHECK:   [B5]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: A() (CXXConstructExpr, class A)
-// CHECK:     3: [B4.2] (BindTemporary)
-// CHECK:     4: [B4.3].operator _Bool
-// CHECK:     5: [B4.4]()
-// CHECK:     6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     T: [B4.6] && ...
+// CHECK:     3: [B5.2] (BindTemporary)
+// CHECK:     4: [B5.3].operator _Bool
+// CHECK:     5: [B5.4]()
+// CHECK:     6: [B5.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     T: [B5.6] && ...
 // CHECK:     Preds (2): B6 B7
-// CHECK:     Succs (2): B5 B3
-// CHECK:   [B5]
-// CHECK:     1: B() (CXXConstructExpr, class B)
-// CHECK:     2: [B5.1] (BindTemporary)
-// CHECK:     3: [B5.2].operator _Bool
-// CHECK:     4: [B5.3]()
-// CHECK:     5: [B5.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     Preds (1): B4
-// CHECK:     Succs (1): B3
+// CHECK:     Succs (2): B4 B3
 // CHECK:   [B6]
 // CHECK:     1: ~B() (Temporary object destructor)
 // CHECK:     Preds (1): B7
-// CHECK:     Succs (1): B4
+// CHECK:     Succs (1): B5
 // CHECK:   [B7]
-// CHECK:     1: [B8.5] && [B9.5]
+// CHECK:     1: [B9.5] && [B8.5]
 // CHECK:     2: bool a = A().operator _Bool() && B().operator _Bool();
-// CHECK:     T: [B8.5] && ...
-// CHECK:     Preds (2): B9 B8
-// CHECK:     Succs (2): B6 B4
+// CHECK:     T: [B9.5] && ...
+// CHECK:     Preds (2): B8 B9
+// CHECK:     Succs (2): B6 B5
 // CHECK:   [B8]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// CHECK:     1: B() (CXXConstructExpr, class B)
 // CHECK:     2: [B8.1] (BindTemporary)
 // CHECK:     3: [B8.2].operator _Bool
 // CHECK:     4: [B8.3]()
 // CHECK:     5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     T: [B8.5] && ...
-// CHECK:     Preds (1): B10
-// CHECK:     Succs (2): B9 B7
+// CHECK:     Preds (1): B9
+// CHECK:     Succs (1): B7
 // CHECK:   [B9]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// CHECK:     1: A() (CXXConstructExpr, class A)
 // CHECK:     2: [B9.1] (BindTemporary)
 // CHECK:     3: [B9.2].operator _Bool
 // CHECK:     4: [B9.3]()
 // CHECK:     5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     Preds (1): B8
-// CHECK:     Succs (1): B7
+// CHECK:     T: [B9.5] && ...
+// CHECK:     Preds (1): B10
+// CHECK:     Succs (2): B8 B7
 // CHECK:   [B0 (EXIT)]
 // CHECK:     Preds (1): B1
 // CHECK:   [B10 (ENTRY)]
-// CHECK:     Succs (1): B8
+// CHECK:     Succs (1): B9
 // CHECK:   [B1]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: int b;
@@ -227,58 +308,58 @@
 // CHECK:     Preds (1): B3
 // CHECK:     Succs (1): B1
 // CHECK:   [B3]
-// CHECK:     1: [B4.6] || [B5.5]
+// CHECK:     1: [B5.6] || [B4.5]
 // CHECK:     2: foo
 // CHECK:     3: [B3.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
 // CHECK:     4: [B3.3]([B3.1])
-// CHECK:     T: [B4.6] || ...
-// CHECK:     Preds (2): B5 B4
+// CHECK:     T: [B5.6] || ...
+// CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B1 B2
 // CHECK:   [B4]
+// CHECK:     1: B() (CXXConstructExpr, class B)
+// CHECK:     2: [B4.1] (BindTemporary)
+// CHECK:     3: [B4.2].operator _Bool
+// CHECK:     4: [B4.3]()
+// CHECK:     5: [B4.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     Preds (1): B5
+// CHECK:     Succs (1): B3
+// CHECK:   [B5]
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: A() (CXXConstructExpr, class A)
-// CHECK:     3: [B4.2] (BindTemporary)
-// CHECK:     4: [B4.3].operator _Bool
-// CHECK:     5: [B4.4]()
-// CHECK:     6: [B4.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     T: [B4.6] || ...
+// CHECK:     3: [B5.2] (BindTemporary)
+// CHECK:     4: [B5.3].operator _Bool
+// CHECK:     5: [B5.4]()
+// CHECK:     6: [B5.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK:     T: [B5.6] || ...
 // CHECK:     Preds (2): B6 B7
-// CHECK:     Succs (2): B3 B5
-// CHECK:   [B5]
-// CHECK:     1: B() (CXXConstructExpr, class B)
-// CHECK:     2: [B5.1] (BindTemporary)
-// CHECK:     3: [B5.2].operator _Bool
-// CHECK:     4: [B5.3]()
-// CHECK:     5: [B5.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     Preds (1): B4
-// CHECK:     Succs (1): B3
+// CHECK:     Succs (2): B3 B4
 // CHECK:   [B6]
 // CHECK:     1: ~B() (Temporary object destructor)
 // CHECK:     Preds (1): B7
-// CHECK:     Succs (1): B4
+// CHECK:     Succs (1): B5
 // CHECK:   [B7]
-// CHECK:     1: [B8.5] || [B9.5]
+// CHECK:     1: [B9.5] || [B8.5]
 // CHECK:     2: bool a = A().operator _Bool() || B().operator _Bool();
-// CHECK:     T: [B8.5] || ...
-// CHECK:     Preds (2): B9 B8
-// CHECK:     Succs (2): B4 B6
+// CHECK:     T: [B9.5] || ...
+// CHECK:     Preds (2): B8 B9
+// CHECK:     Succs (2): B5 B6
 // CHECK:   [B8]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// CHECK:     1: B() (CXXConstructExpr, class B)
 // CHECK:     2: [B8.1] (BindTemporary)
 // CHECK:     3: [B8.2].operator _Bool
 // CHECK:     4: [B8.3]()
 // CHECK:     5: [B8.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     T: [B8.5] || ...
-// CHECK:     Preds (1): B10
-// CHECK:     Succs (2): B7 B9
+// CHECK:     Preds (1): B9
+// CHECK:     Succs (1): B7
 // CHECK:   [B9]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// CHECK:     1: A() (CXXConstructExpr, class A)
 // CHECK:     2: [B9.1] (BindTemporary)
 // CHECK:     3: [B9.2].operator _Bool
 // CHECK:     4: [B9.3]()
 // CHECK:     5: [B9.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
-// CHECK:     Preds (1): B8
-// CHECK:     Succs (1): B7
+// CHECK:     T: [B9.5] || ...
+// CHECK:     Preds (1): B10
+// CHECK:     Succs (2): B7 B8
 // CHECK:   [B0 (EXIT)]
 // CHECK:     Preds (1): B1
 // CHECK:   [B11 (ENTRY)]

Modified: cfe/trunk/test/Sema/uninit-variables.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/uninit-variables.c?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/test/Sema/uninit-variables.c (original)
+++ cfe/trunk/test/Sema/uninit-variables.c Sat Jul 14 00:04:10 2012
@@ -152,15 +152,15 @@
 
 int test20() {
   int z; // expected-note{{initialize the variable 'z' to silence this warning}}
-  if ((test19_aux1() + test19_aux2() && test19_aux1()) || test19_aux3(&z))
-    return z; // expected-warning{{variable 'z' may be uninitialized when used here}}
+  if ((test19_aux1() + test19_aux2() && test19_aux1()) || test19_aux3(&z)) // expected-warning {{variable 'z' is used uninitialized whenever '||' condition is true}} expected-note {{remove the '||' if its condition is always false}}
+    return z; // expected-note {{uninitialized use occurs here}}
   return 0;
 }
 
 int test21(int x, int y) {
   int z; // expected-note{{initialize the variable 'z' to silence this warning}}
-  if ((x && y) || test19_aux3(&z) || test19_aux2())
-    return z; // expected-warning{{variable 'z' may be uninitialized when used here}}
+  if ((x && y) || test19_aux3(&z) || test19_aux2()) // expected-warning {{variable 'z' is used uninitialized whenever '||' condition is true}} expected-note {{remove the '||' if its condition is always false}}
+    return z; // expected-note {{uninitialized use occurs here}}
   return 0;
 }
 

Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=160218&r1=160217&r2=160218&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
+++ cfe/trunk/test/SemaCXX/uninitialized.cpp Sat Jul 14 00:04:10 2012
@@ -25,7 +25,7 @@
 int m = 1 + (k ? m : m);  // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}}
 int n = -n;  // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
 
-void test () {
+void test_stuff () {
   int a = a; // no-warning: used to signal intended lack of initialization.
   int b = b + 1; // expected-warning {{variable 'b' is uninitialized when used within its own initialization}}
   int c = (c + c); // expected-warning {{variable 'c' is uninitialized when used within its own initialization}}





More information about the cfe-commits mailing list