]> granicus.if.org Git - clang/commitdiff
[analyzer] Overhaul how the static analyzer expects CFGs by forcing CFGs to be linear...
authorTed Kremenek <kremenek@apple.com>
Thu, 28 Jul 2011 23:07:59 +0000 (23:07 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 28 Jul 2011 23:07:59 +0000 (23:07 +0000)
The motivation of this large change is to drastically simplify the logic in ExprEngine going forward.

Some fallout is that the output of some BugReporterVisitors is not as accurate as before; those will
need to be fixed over time.  There is also some possible performance regression as RemoveDeadBindings
will be called frequently; this can also be improved over time.

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

20 files changed:
include/clang/Analysis/Analyses/LiveVariables.h
include/clang/Analysis/CFG.h
include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
lib/Analysis/AnalysisContext.cpp
lib/Analysis/LiveVariables.cpp
lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
lib/StaticAnalyzer/Core/AnalysisManager.cpp
lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
lib/StaticAnalyzer/Core/Environment.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/GRState.cpp
lib/StaticAnalyzer/Core/SymbolManager.cpp
test/Analysis/auto-obj-dtors-cfg-output.cpp
test/Analysis/initializers-cfg-output.cpp
test/Analysis/out-of-bounds.c
test/Analysis/plist-output-alternate.m
test/Analysis/retain-release.m
test/Analysis/stack-addr-ps.c
test/Analysis/temp-obj-dtors-cfg-output.cpp

index fbbd2613e7c2a4165f8f9304efd4cbedb64269c9..6a1bae03be562c6137a961b27a6f1283c8368c9b 100644 (file)
@@ -1,4 +1,4 @@
-//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
+//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-//
 //
 //                     The LLVM Compiler Infrastructure
 //
 #define LLVM_CLANG_LIVEVARIABLES_H
 
 #include "clang/AST/Decl.h"
-#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
-#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ImmutableSet.h"
 
 namespace clang {
 
+class CFG;
+class CFGBlock;
 class Stmt;
 class DeclRefExpr;
 class SourceManager;
 class AnalysisContext;
-
-struct LiveVariables_ValueTypes {
-
-  struct ObserverTy;
-
-  // We keep dataflow state for declarations and block-level expressions;
-  typedef StmtDeclBitVector_Types::ValTy ValTy;
-
-  // We need to keep track of both declarations and CFGBlock-level expressions,
-  // (so that we don't explore such expressions twice).  We also want
-  // to compute liveness information for block-level expressions, since these
-  // act as "temporary" values.
-
-  struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
-    ObserverTy* Observer;
-    ValTy AlwaysLive;
-    AnalysisContext *AC;
-    bool killAtAssign;
-
-    AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
+  
+class LiveVariables {
+public:
+  class LivenessValues {
+  public:
+
+    llvm::ImmutableSet<const Stmt *> liveStmts;
+    llvm::ImmutableSet<const VarDecl *> liveDecls;
+    
+    bool equals(const LivenessValues &V) const;
+
+    LivenessValues()
+      : liveStmts(0), liveDecls(0) {}
+
+    LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
+                   llvm::ImmutableSet<const VarDecl *> LiveDecls)
+      : liveStmts(LiveStmts), liveDecls(LiveDecls) {}
+
+    ~LivenessValues() {}
+    
+    bool isLive(const Stmt *S) const;
+    bool isLive(const VarDecl *D) const;
+    
+    friend class LiveVariables;    
   };
-
-  //===-----------------------------------------------------===//
-  // ObserverTy - Observer for uninitialized values queries.
-  //===-----------------------------------------------------===//
-
-  struct ObserverTy {
-    virtual ~ObserverTy() {}
-
-    /// ObserveStmt - A callback invoked right before invoking the
+  
+  struct Observer {
+    virtual ~Observer() {}
+    
+    /// A callback invoked right before invoking the
     ///  liveness transfer function on the given statement.
-    virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
-                             const AnalysisDataTy& AD,
-                             const ValTy& V) {}
-
-    virtual void ObserverKill(DeclRefExpr* DR) {}
-  };
-};
-
-class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
-                                            dataflow::backward_analysis_tag> {
-
-
-public:
-  typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
-
-  LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
-
-  /// IsLive - Return true if a variable is live at the end of a
+    virtual void observeStmt(const Stmt* S,
+                             const CFGBlock *currentBlock,
+                             const LivenessValues& V) {}
+    
+    /// Called when the live variables analysis registers
+    /// that a variable is killed.
+    virtual void observerKill(const DeclRefExpr* DR) {}
+  };    
+
+
+  ~LiveVariables();
+  
+  /// Compute the liveness information for a given CFG.
+  static LiveVariables *computeLiveness(AnalysisContext &analysisContext,
+                                          bool killAtAssign = true);
+  
+  /// Return true if a variable is live at the end of a
   /// specified block.
-  bool isLive(const CFGBlock* B, const VarDecl* D) const;
-
-  /// IsLive - Returns true if a variable is live at the beginning of the
+  bool isLive(const CFGBlock* B, const VarDecl* D);
+  
+  /// Returns true if a variable is live at the beginning of the
   ///  the statement.  This query only works if liveness information
   ///  has been recorded at the statement level (see runOnAllBlocks), and
   ///  only returns liveness information for block-level expressions.
-  bool isLive(const Stmt* S, const VarDecl* D) const;
-
-  /// IsLive - Returns true the block-level expression "value" is live
+  bool isLive(const Stmt* S, const VarDecl* D);
+  
+  /// Returns true the block-level expression "value" is live
   ///  before the given block-level expression (see runOnAllBlocks).
-  bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
+  bool isLive(const Stmt* Loc, const Stmt* StmtVal);
+    
+  /// Print to stderr the liveness information associated with
+  /// each basic block.
+  void dumpBlockLiveness(const SourceManager& M);
 
-  /// IsLive - Return true if a variable is live according to the
-  ///  provided livness bitvector.
-  bool isLive(const ValTy& V, const VarDecl* D) const;
+  void runOnAllBlocks(Observer &obs);
 
-  /// dumpLiveness - Print to stderr the liveness information encoded
-  ///  by a specified bitvector.
-  void dumpLiveness(const ValTy& V, const SourceManager& M) const;
-
-  /// dumpBlockLiveness - Print to stderr the liveness information
-  ///  associated with each basic block.
-  void dumpBlockLiveness(const SourceManager& M) const;
-
-  /// getNumDecls - Return the number of variables (declarations) that
-  ///  whose liveness status is being tracked by the dataflow
-  ///  analysis.
-  unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
-
-  /// IntializeValues - This routine can perform extra initialization, but
-  ///  for LiveVariables this does nothing since all that logic is in
-  ///  the constructor.
-  void InitializeValues(const CFG& cfg) {}
-
-  void runOnCFG(CFG& cfg);
-
-  /// runOnAllBlocks - Propagate the dataflow values once for each block,
-  ///  starting from the current dataflow values.  'recordStmtValues' indicates
-  ///  whether the method should store dataflow values per each individual
-  ///  block-level expression.
-  void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
-                      bool recordStmtValues=false);
+private:
+  LiveVariables(void *impl);
+  void *impl;
 };
-
+  
 } // end namespace clang
 
 #endif
index 87f32a5166f03a9efa192217af56a4d09d128550..2f6c4b364080f191328a8075eb331f00186e226b 100644 (file)
@@ -545,8 +545,13 @@ public:
       return alwaysAddMask[stmt->getStmtClass()];
     }
     
-    BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass) {
-      alwaysAddMask[stmtClass] = true;
+    BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
+      alwaysAddMask[stmtClass] = val;
+      return *this;
+    }
+    
+    BuildOptions &setAllAlwaysAdd() {
+      alwaysAddMask.set();
       return *this;
     }
 
index 0cb4ad992bba279004fa2c49754d08d9c674a42b..66ecba7dcf35629d1c9ebcc3ac247ed806b4fc33 100644 (file)
 #include "clang/AST/Expr.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
 
 namespace llvm {
 class BumpPtrAllocator;
@@ -40,10 +42,10 @@ namespace ento {
 
 class SymExpr : public llvm::FoldingSetNode {
 public:
-  enum Kind { BEGIN_SYMBOLS,
-              RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+  enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
               MetadataKind,
-              END_SYMBOLS,
+              BEGIN_SYMBOLS = RegionValueKind,
+              END_SYMBOLS = MetadataKind,
               SymIntKind, SymSymKind };
 private:
   Kind K;
@@ -84,7 +86,7 @@ public:
   // Implement isa<T> support.
   static inline bool classof(const SymExpr* SE) {
     Kind k = SE->getKind();
-    return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
+    return k >= BEGIN_SYMBOLS && k <= END_SYMBOLS;
   }
 };
 
@@ -419,10 +421,13 @@ class SymbolReaper {
   const LocationContext *LCtx;
   const Stmt *Loc;
   SymbolManager& SymMgr;
+  StoreRef reapedStore;
+  llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
 
 public:
-  SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr)
-   : LCtx(ctx), Loc(s), SymMgr(symmgr) {}
+  SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
+               StoreManager &storeMgr)
+   : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {}
 
   ~SymbolReaper() {}
 
@@ -431,7 +436,7 @@ public:
 
   bool isLive(SymbolRef sym);
   bool isLive(const Stmt *ExprVal) const;
-  bool isLive(const VarRegion *VR) const;
+  bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
 
   // markLive - Unconditionally marks a symbol as live. This should never be
   //  used by checkers, only by the state infrastructure such as the store and
@@ -464,6 +469,10 @@ public:
   bool isDead(SymbolRef sym) const {
     return TheDead.count(sym);
   }
+  
+  /// Set to the value of the symbolic store after
+  /// StoreManager::removeDeadBindings has been called.
+  void setReapedStore(StoreRef st) { reapedStore = st; }
 };
 
 class SymbolVisitor {
index 7ee247da00260f2f8f73ac33ac7b73f1edadc27b..5a85899389647ccefa11bffe2711c7ceb2b64c98 100644 (file)
@@ -177,25 +177,14 @@ PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() {
 }
 
 LiveVariables *AnalysisContext::getLiveVariables() {
-  if (!liveness) {
-    if (CFG *c = getCFG()) {
-      liveness.reset(new LiveVariables(*this));
-      liveness->runOnCFG(*c);
-      liveness->runOnAllBlocks(*c, 0, true);
-    }
-  }
-
+  if (!liveness)
+    liveness.reset(LiveVariables::computeLiveness(*this));
   return liveness.get();
 }
 
 LiveVariables *AnalysisContext::getRelaxedLiveVariables() {
   if (!relaxedLiveness)
-    if (CFG *c = getCFG()) {
-      relaxedLiveness.reset(new LiveVariables(*this, false));
-      relaxedLiveness->runOnCFG(*c);
-      relaxedLiveness->runOnAllBlocks(*c, 0, true);
-    }
-
+    relaxedLiveness.reset(LiveVariables::computeLiveness(*this, false));
   return relaxedLiveness.get();
 }
 
index b7ae141781e2bbf9b95321b695cccc9967a52cc5..f81019e2c9f02fb056e52c597204aaf59aee4c49 100644 (file)
-//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs -*- C++ --*-==//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Live Variables analysis for source-level CFGs.
-//
-//===----------------------------------------------------------------------===//
-
 #include "clang/Analysis/Analyses/LiveVariables.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
 #include "clang/Analysis/CFG.h"
-#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
-#include "clang/Analysis/FlowSensitive/DataflowSolver.h"
-#include "clang/Analysis/Support/SaveAndRestore.h"
 #include "clang/Analysis/AnalysisContext.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/raw_ostream.h"
+#include "clang/AST/StmtVisitor.h"
+
+#include <deque>
+#include <algorithm>
+#include <vector>
 
 using namespace clang;
 
-//===----------------------------------------------------------------------===//
-// Useful constants.
-//===----------------------------------------------------------------------===//
+namespace {
+  class LiveVariablesImpl {
+  public:  
+    AnalysisContext &analysisContext;
+    std::vector<LiveVariables::LivenessValues> cfgBlockValues;
+    llvm::ImmutableSet<const Stmt *>::Factory SSetFact;
+    llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
+    llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
+    llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
+    llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
+    llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
+    const bool killAtAssign;
+    
+    LiveVariables::LivenessValues
+    merge(LiveVariables::LivenessValues valsA,
+          LiveVariables::LivenessValues valsB);
+        
+    LiveVariables::LivenessValues runOnBlock(const CFGBlock *block,
+                                             LiveVariables::LivenessValues val,
+                                             LiveVariables::Observer *obs = 0);
+
+    void dumpBlockLiveness(const SourceManager& M);
+
+    LiveVariablesImpl(AnalysisContext &ac, bool KillAtAssign)
+      : analysisContext(ac), killAtAssign(KillAtAssign) {}
+  };
+}
 
-static const bool Alive = true;
-static const bool Dead = false;
+static LiveVariablesImpl &getImpl(void* x) {
+  return *((LiveVariablesImpl *) x);
+}
 
 //===----------------------------------------------------------------------===//
-// Dataflow initialization logic.
+// Operations and queries on LivenessValues.
 //===----------------------------------------------------------------------===//
 
-namespace {
-class RegisterDecls
-  : public CFGRecStmtDeclVisitor<RegisterDecls> {
-
-  LiveVariables::AnalysisDataTy& AD;
-
-  typedef SmallVector<VarDecl*, 20> AlwaysLiveTy;
-  AlwaysLiveTy AlwaysLive;
+bool LiveVariables::LivenessValues::isLive(const Stmt *S) const {
+  return liveStmts.contains(S);
+}
 
+bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
+  return liveDecls.contains(D);
+}
 
-public:
-  RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+namespace {
+  template <typename SET>
+  SET mergeSets(typename SET::Factory &F, SET A, SET B) {
+    for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
+      A = F.add(A, *it);
+    }
+    return A;
+  }
+}
 
-  ~RegisterDecls() {
+LiveVariables::LivenessValues
+LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
+                         LiveVariables::LivenessValues valsB) {  
+  return LiveVariables::LivenessValues(mergeSets(SSetFact, valsA.liveStmts, valsB.liveStmts),
+                        mergeSets(DSetFact, valsA.liveDecls, valsB.liveDecls));
+}
 
-    AD.AlwaysLive.resetValues(AD);
+bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
+  return liveStmts == V.liveStmts && liveDecls == V.liveDecls;
+}
 
-    for (AlwaysLiveTy::iterator I = AlwaysLive.begin(), E = AlwaysLive.end();
-         I != E; ++ I)
-      AD.AlwaysLive(*I, AD) = Alive;
-  }
+//===----------------------------------------------------------------------===//
+// Query methods.
+//===----------------------------------------------------------------------===//
 
-  void VisitImplicitParamDecl(ImplicitParamDecl* IPD) {
-    // Register the VarDecl for tracking.
-    AD.Register(IPD);
-  }
+static bool isAlwaysAlive(const VarDecl *D) {
+  return D->hasGlobalStorage();
+}
 
-  void VisitVarDecl(VarDecl* VD) {
-    // Register the VarDecl for tracking.
-    AD.Register(VD);
+bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
+  return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
+}
 
-    // Does the variable have global storage?  If so, it is always live.
-    if (VD->hasGlobalStorage())
-      AlwaysLive.push_back(VD);
-  }
+bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
+  return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
+}
 
-  CFG& getCFG() { return AD.getCFG(); }
-};
-} // end anonymous namespace
-
-LiveVariables::LiveVariables(AnalysisContext &AC, bool killAtAssign) {
-  // Register all referenced VarDecls.
-  CFG &cfg = *AC.getCFG();
-  getAnalysisData().setCFG(cfg);
-  getAnalysisData().setContext(AC.getASTContext());
-  getAnalysisData().AC = &AC;
-  getAnalysisData().killAtAssign = killAtAssign;
-
-  RegisterDecls R(getAnalysisData());
-  cfg.VisitBlockStmts(R);
-
-  // Register all parameters even if they didn't occur in the function body.
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(AC.getDecl()))
-    for (FunctionDecl::param_const_iterator PI = FD->param_begin(), 
-           PE = FD->param_end(); PI != PE; ++PI)
-      getAnalysisData().Register(*PI);
+bool LiveVariables::isLive(const Stmt *Loc, const Stmt *S) {
+  return getImpl(impl).stmtsToLiveness[Loc].isLive(S);
 }
 
 //===----------------------------------------------------------------------===//
-// Transfer functions.
+// Dataflow computation.
 //===----------------------------------------------------------------------===//
 
 namespace {
-
-class TransferFuncs : public CFGRecStmtVisitor<TransferFuncs>{
-  LiveVariables::AnalysisDataTy& AD;
-  LiveVariables::ValTy LiveState;
-  const CFGBlock *currentBlock;
+class Worklist {
+  llvm::BitVector isBlockEnqueued;
+  std::deque<const CFGBlock *> workListContents;
 public:
-  TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad), currentBlock(0) {}
-
-  LiveVariables::ValTy& getVal() { return LiveState; }
-  CFG& getCFG() { return AD.getCFG(); }
-
-  void VisitDeclRefExpr(DeclRefExpr* DR);
-  void VisitBinaryOperator(BinaryOperator* B);
-  void VisitBlockExpr(BlockExpr *B);
-  void VisitAssign(BinaryOperator* B);
-  void VisitDeclStmt(DeclStmt* DS);
-  void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S);
-  void VisitUnaryOperator(UnaryOperator* U);
-  void Visit(Stmt *S);
-  void VisitTerminator(CFGBlock* B);
+  Worklist(CFG &cfg) : isBlockEnqueued(cfg.getNumBlockIDs()) {}
   
-  /// VisitConditionVariableInit - Handle the initialization of condition
-  ///  variables at branches.  Valid statements include IfStmt, ForStmt,
-  ///  WhileStmt, and SwitchStmt.
-  void VisitConditionVariableInit(Stmt *S);
-
-  void SetTopValue(LiveVariables::ValTy& V) {
-    V = AD.AlwaysLive;
+  bool empty() const { return workListContents.empty(); }
+  
+  const CFGBlock *getNextItem() {
+    const CFGBlock *block = workListContents.front();
+    workListContents.pop_front();
+    isBlockEnqueued[block->getBlockID()] = false;
+    return block;
   }
   
-  void setCurrentBlock(const CFGBlock *block) {
-    currentBlock = block;
+  void enqueueBlock(const CFGBlock *block) {
+    if (!isBlockEnqueued[block->getBlockID()]) {
+      isBlockEnqueued[block->getBlockID()] = true;
+      workListContents.push_back(block);
+    }
   }
 };
+  
+class TransferFunctions : public StmtVisitor<TransferFunctions> {
+  LiveVariablesImpl &LV;
+  LiveVariables::LivenessValues &val;
+  LiveVariables::Observer *observer;
+  const CFGBlock *currentBlock;
+public:
+  TransferFunctions(LiveVariablesImpl &im,
+                    LiveVariables::LivenessValues &Val,
+                    LiveVariables::Observer *Observer,
+                    const CFGBlock *CurrentBlock)
+  : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
+
+  void VisitBinaryOperator(BinaryOperator *BO);
+  void VisitBlockExpr(BlockExpr *BE);
+  void VisitDeclRefExpr(DeclRefExpr *DR);  
+  void VisitDeclStmt(DeclStmt *DS);
+  void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
+  void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
+  void VisitUnaryOperator(UnaryOperator *UO);
+  void Visit(Stmt *S);
+};
+}
 
-void TransferFuncs::Visit(Stmt *S) {
-
-  if (S == getCurrentBlkStmt()) {
-
-    if (AD.Observer)
-      AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
-
-    if (getCFG().isBlkExpr(S))
-      LiveState(S, AD) = Dead;
-
-    StmtVisitor<TransferFuncs,void>::Visit(S);
+void TransferFunctions::Visit(Stmt *S) {
+  if (observer)
+    observer->observeStmt(S, currentBlock, val);
+  
+  StmtVisitor<TransferFunctions>::Visit(S);
+  
+  if (isa<Expr>(S)) {
+    val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
   }
-  else if (!getCFG().isBlkExpr(S)) {
-
-    if (AD.Observer)
-      AD.Observer->ObserveStmt(S, currentBlock, AD, LiveState);
 
-    StmtVisitor<TransferFuncs,void>::Visit(S);
-
-  }
-  else {
-    // For block-level expressions, mark that they are live.
-    LiveState(S, AD) = Alive;
+  // Mark all children expressions live.
+  
+  switch (S->getStmtClass()) {
+    default:
+      break;
+    case Stmt::StmtExprClass: {
+      // For statement expressions, look through the compound statement.
+      S = cast<StmtExpr>(S)->getSubStmt();
+      break;
+    }
+    case Stmt::CXXMemberCallExprClass: {
+      // Include the implicit "this" pointer as being live.
+      CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
+      val.liveStmts =
+        LV.SSetFact.add(val.liveStmts,
+                        CE->getImplicitObjectArgument()->IgnoreParens());
+      break;
+    }
+    // FIXME: These cases eventually shouldn't be needed.
+    case Stmt::ExprWithCleanupsClass: {
+      S = cast<ExprWithCleanups>(S)->getSubExpr();
+      break;
+    }
+    case Stmt::CXXBindTemporaryExprClass: {
+      S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
+      break;
+    }
+    case Stmt::MaterializeTemporaryExprClass: {
+      S = cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr();
+      break;
+    }
   }
-}
   
-void TransferFuncs::VisitConditionVariableInit(Stmt *S) {
-  assert(!getCFG().isBlkExpr(S));
-  CFGRecStmtVisitor<TransferFuncs>::VisitConditionVariableInit(S);
+  for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end();
+       it != ei; ++it) {
+    if (Stmt *child = *it) {
+      if (Expr *Ex = dyn_cast<Expr>(child))
+        child = Ex->IgnoreParens();
+               
+      val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
+    }
+  }
 }
 
-void TransferFuncs::VisitTerminator(CFGBlock* B) {
-
-  const Stmt* E = B->getTerminatorCondition();
-
-  if (!E)
-    return;
-
-  assert (getCFG().isBlkExpr(E));
-  LiveState(E, AD) = Alive;
+void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
+  if (B->isAssignmentOp()) {
+    if (!LV.killAtAssign)
+      return;
+    
+    // Assigning to a variable?
+    Expr *LHS = B->getLHS()->IgnoreParens();
+    
+    if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS))
+      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+        // Assignments to references don't kill the ref's address
+        if (VD->getType()->isReferenceType())
+          return;
+
+        if (!isAlwaysAlive(VD)) {
+          // The variable is now dead.
+          val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
+        }
+
+        if (observer)
+          observer->observerKill(DR);
+      }
+  }
 }
 
-void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
-  if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
-    LiveState(V, AD) = Alive;
-}
-  
-void TransferFuncs::VisitBlockExpr(BlockExpr *BE) {
+void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
   AnalysisContext::referenced_decls_iterator I, E;
-  llvm::tie(I, E) = AD.AC->getReferencedBlockVars(BE->getBlockDecl());
+  llvm::tie(I, E) =
+    LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
   for ( ; I != E ; ++I) {
-    DeclBitVector_Types::Idx i = AD.getIdx(*I);
-    if (i.isValid())
-      LiveState.getBit(i) = Alive;
+    const VarDecl *VD = *I;
+    if (isAlwaysAlive(VD))
+      continue;
+    val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
   }
 }
 
-void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
-  if (B->isAssignmentOp()) VisitAssign(B);
-  else VisitStmt(B);
+void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
+  if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
+    if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
+      val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
 }
 
-void
-TransferFuncs::BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
-
-  // This is a block-level expression.  Its value is 'dead' before this point.
-  LiveState(S, AD) = Dead;
-
-  // This represents a 'use' of the collection.
-  Visit(S->getCollection());
+void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
+  for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE = DS->decl_end();
+       DI != DE; ++DI)
+    if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) {
+      if (!isAlwaysAlive(VD))
+        val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
+    }
+}
 
-  // This represents a 'kill' for the variable.
-  Stmt* Element = S->getElement();
-  DeclRefExprDR = 0;
-  VarDecl* VD = 0;
+void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
+  // Kill the iteration variable.
+  DeclRefExpr *DR = 0;
+  const VarDecl *VD = 0;
 
-  if (DeclStmt* DS = dyn_cast<DeclStmt>(Element))
+  Stmt *element = OS->getElement();
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
     VD = cast<VarDecl>(DS->getSingleDecl());
-  else {
-    Expr* ElemExpr = cast<Expr>(Element)->IgnoreParens();
-    if ((DR = dyn_cast<DeclRefExpr>(ElemExpr)))
-      VD = cast<VarDecl>(DR->getDecl());
-    else {
-      Visit(ElemExpr);
-      return;
-    }
   }
-
+  else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
+    VD = cast<VarDecl>(DR->getDecl());
+  }
+  
   if (VD) {
-    LiveState(VD, AD) = Dead;
-    if (AD.Observer && DR) { AD.Observer->ObserverKill(DR); }
+    val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
+    if (observer && DR)
+      observer->observerKill(DR);
   }
 }
 
+void TransferFunctions::
+VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
+{
+  // While sizeof(var) doesn't technically extend the liveness of 'var', it
+  // does extent the liveness of metadata if 'var' is a VariableArrayType.
+  // We handle that special case here.
+  if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
+    return;
+
+  const DeclRefExpr *DR =
+    dyn_cast<DeclRefExpr>(UE->getArgumentExpr()->IgnoreParens());
+  
+  if (!DR)
+    return;
+  
+  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
 
-void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
-  Expr *E = U->getSubExpr();
+  if (VD && VD->getType()->isVariableArrayType())
+    val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
+}
 
-  switch (U->getOpcode()) {
+void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
+  // Treat ++/-- as a kill.
+  // Note we don't actually have to do anything if we don't have an observer,
+  // since a ++/-- acts as both a kill and a "use".
+  if (!observer)
+    return;
+  
+  switch (UO->getOpcode()) {
+  default:
+    return;
   case UO_PostInc:
-  case UO_PostDec:
+  case UO_PostDec:    
   case UO_PreInc:
   case UO_PreDec:
-    // Walk through the subexpressions, blasting through ParenExprs
-    // until we either find a DeclRefExpr or some non-DeclRefExpr
-    // expression.
-    if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E->IgnoreParens()))
-      if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
-        // Treat the --/++ operator as a kill.
-        if (AD.Observer) { AD.Observer->ObserverKill(DR); }
-        LiveState(VD, AD) = Alive;
-        return VisitDeclRefExpr(DR);
-      }
-
-    // Fall-through.
-
-  default:
-    return Visit(E);
-  }
-}
-
-void TransferFuncs::VisitAssign(BinaryOperator* B) {
-  Expr* LHS = B->getLHS();
-
-  // Assigning to a variable?
-  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParens())) {
-    // Assignments to references don't kill the ref's address
-    if (DR->getDecl()->getType()->isReferenceType()) {
-      VisitDeclRefExpr(DR);
-    } else {
-      if (AD.killAtAssign) {
-        // Update liveness inforamtion.
-        unsigned bit = AD.getIdx(DR->getDecl());
-        LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
-
-        if (AD.Observer) { AD.Observer->ObserverKill(DR); }
-      }
-      // Handle things like +=, etc., which also generate "uses"
-      // of a variable.  Do this just by visiting the subexpression.
-      if (B->getOpcode() != BO_Assign)
-        VisitDeclRefExpr(DR);
-    }
+    break;
   }
-  else // Not assigning to a variable.  Process LHS as usual.
-    Visit(LHS);
-
-  Visit(B->getRHS());
-}
-
-void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
-  // Declarations effectively "kill" a variable since they cannot
-  // possibly be live before they are declared.
-  for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE = DS->decl_end();
-       DI != DE; ++DI)
-    if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) {
-      // Update liveness information by killing the VarDecl.
-      unsigned bit = AD.getIdx(VD);
-      LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
-
-      // The initializer is evaluated after the variable comes into scope, but
-      // before the DeclStmt (which binds the value to the variable).
-      // Since this is a reverse dataflow analysis, we must evaluate the
-      // transfer function for this expression after the DeclStmt.  If the
-      // initializer references the variable (which is bad) then we extend
-      // its liveness.
-      if (Expr* Init = VD->getInit())
-        Visit(Init);
-
-      if (const VariableArrayType* VT =
-            AD.getContext().getAsVariableArrayType(VD->getType())) {
-        StmtIterator I(const_cast<VariableArrayType*>(VT));
-        StmtIterator E;
-        for (; I != E; ++I) Visit(*I);
-      }
+  
+  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens()))
+    if (isa<VarDecl>(DR->getDecl())) {
+      // Treat ++/-- as a kill.
+      observer->observerKill(DR);
     }
 }
 
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Merge operator: if something is live on any successor block, it is live
-//  in the current block (a set union).
-//===----------------------------------------------------------------------===//
+LiveVariables::LivenessValues
+LiveVariablesImpl::runOnBlock(const CFGBlock *block,
+                              LiveVariables::LivenessValues val,
+                              LiveVariables::Observer *obs) {
 
-namespace {
-  typedef StmtDeclBitVector_Types::Union Merge;
-  typedef DataflowSolver<LiveVariables, TransferFuncs, Merge> Solver;
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// External interface to run Liveness analysis.
-//===----------------------------------------------------------------------===//
-
-void LiveVariables::runOnCFG(CFG& cfg) {
-  Solver S(*this);
-  S.runOnCFG(cfg);
+  TransferFunctions TF(*this, val, obs, block);
+  
+  // Visit the terminator (if any).
+  if (const Stmt *term = block->getTerminator())
+    TF.Visit(const_cast<Stmt*>(term));
+  
+  // Apply the transfer function for all Stmts in the block.
+  for (CFGBlock::const_reverse_iterator it = block->rbegin(),
+       ei = block->rend(); it != ei; ++it) {
+    const CFGElement &elem = *it;
+    if (!isa<CFGStmt>(elem))
+      continue;
+    
+    const Stmt *S = cast<CFGStmt>(elem).getStmt();
+    TF.Visit(const_cast<Stmt*>(S));
+    stmtsToLiveness[S] = val;
+  }
+  return val;
 }
 
-void LiveVariables::runOnAllBlocks(const CFG& cfg,
-                                   LiveVariables::ObserverTy* Obs,
-                                   bool recordStmtValues) {
-  Solver S(*this);
-  SaveAndRestore<LiveVariables::ObserverTy*> SRObs(getAnalysisData().Observer,
-                                                   Obs);
-  S.runOnAllBlocks(cfg, recordStmtValues);
+void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
+  const CFG *cfg = getImpl(impl).analysisContext.getCFG();
+  for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
+    getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);    
 }
 
-//===----------------------------------------------------------------------===//
-// liveness queries
-//
+LiveVariables::LiveVariables(void *im) : impl(im) {} 
 
-bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
-  DeclBitVector_Types::Idx i = getAnalysisData().getIdx(D);
-  return i.isValid() ? getBlockData(B).getBit(i) : false;
+LiveVariables::~LiveVariables() {
+  delete (LiveVariablesImpl*) impl;
 }
 
-bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const {
-  DeclBitVector_Types::Idx i = getAnalysisData().getIdx(D);
-  return i.isValid() ? Live.getBit(i) : false;
+LiveVariables *
+LiveVariables::computeLiveness(AnalysisContext &AC,
+                                 bool killAtAssign) {
+
+  // No CFG?  Bail out.
+  CFG *cfg = AC.getCFG();
+  if (!cfg)
+    return 0;
+
+  LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
+
+  // Construct the dataflow worklist.  Enqueue the exit block as the
+  // start of the analysis.
+  Worklist worklist(*cfg);
+  llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
+
+  // FIXME: we should enqueue using post order.
+  for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
+    const CFGBlock *block = *it;
+    worklist.enqueueBlock(block);
+    
+    // FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
+    // We need to do this because we lack context in the reverse analysis
+    // to determine if a DeclRefExpr appears in such a context, and thus
+    // doesn't constitute a "use".
+    if (killAtAssign)
+      for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
+           bi != be; ++bi) {
+        if (const CFGStmt *cs = bi->getAs<CFGStmt>()) {
+          if (BinaryOperator *BO = dyn_cast<BinaryOperator>(cs->getStmt())) {
+            if (BO->getOpcode() == BO_Assign) {
+              if (const DeclRefExpr *DR =
+                    dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
+                LV->inAssignment[DR] = 1;
+              }
+            }
+          }
+        }
+      }
+  }
+  
+  while (!worklist.empty()) {
+    // Dequeue blocks in FIFO order.
+    const CFGBlock *block = worklist.getNextItem();
+    
+    // Determine if the block's end value has changed.  If not, we
+    // have nothing left to do for this block.
+    LivenessValues &prevVal = LV->blocksEndToLiveness[block];
+    
+    // Merge the values of all successor blocks.
+    LivenessValues val;
+    for (CFGBlock::const_succ_iterator it = block->succ_begin(),
+                                       ei = block->succ_end(); it != ei; ++it) {
+      if (const CFGBlock *succ = *it)      
+        val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
+    }
+    
+    if (!everAnalyzedBlock[block->getBlockID()])
+      everAnalyzedBlock[block->getBlockID()] = true;
+    else if (prevVal.equals(val))
+      continue;
+
+    prevVal = val;
+    
+    // Update the dataflow value for the start of this block.
+    LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
+    
+    // Enqueue the value to the predecessors.
+    for (CFGBlock::const_pred_iterator it = block->pred_begin(),
+                                       ei = block->pred_end(); it != ei; ++it)
+    {
+      if (const CFGBlock *pred = *it)
+        worklist.enqueueBlock(pred);
+    }    
+  }
+  
+  return new LiveVariables(LV);
 }
 
-bool LiveVariables::isLive(const Stmt* Loc, const Stmt* StmtVal) const {
-  return getStmtData(Loc)(StmtVal,getAnalysisData());
+bool compare_entries(const CFGBlock *A, const CFGBlock *B) {
+  return A->getBlockID() < B->getBlockID();
+}
+bool compare_vd_entries(const Decl *A, const Decl *B) {
+  SourceLocation ALoc = A->getLocStart();
+  SourceLocation BLoc = B->getLocStart();
+  return ALoc.getRawEncoding() < BLoc.getRawEncoding();
 }
 
-bool LiveVariables::isLive(const Stmt* Loc, const VarDecl* D) const {
-  return getStmtData(Loc)(D,getAnalysisData());
+void LiveVariables::dumpBlockLiveness(const SourceManager &M) {
+  getImpl(impl).dumpBlockLiveness(M);
 }
 
-//===----------------------------------------------------------------------===//
-// printing liveness state for debugging
-//
+void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
+  std::vector<const CFGBlock *> vec;
+  for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
+       it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
+       it != ei; ++it) {
+    vec.push_back(it->first);    
+  }
+  std::sort(vec.begin(), vec.end(), compare_entries);
 
-void LiveVariables::dumpLiveness(const ValTy& V, const SourceManager& SM) const {
-  const AnalysisDataTy& AD = getAnalysisData();
+  std::vector<const VarDecl*> declVec;
 
-  for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
-                                     E = AD.end_decl(); I!=E; ++I)
-    if (V.getDeclBit(I->second)) {
-      llvm::errs() << "  " << I->first->getIdentifier()->getName() << " <";
-      I->first->getLocation().dump(SM);
+  for (std::vector<const CFGBlock *>::iterator
+        it = vec.begin(), ei = vec.end(); it != ei; ++it) {
+    llvm::errs() << "\n[ B" << (*it)->getBlockID()
+                 << " (live variables at block exit) ]\n";
+    
+    LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
+    declVec.clear();
+    
+    for (llvm::ImmutableSet<const VarDecl *>::iterator si =
+          vals.liveDecls.begin(),
+          se = vals.liveDecls.end(); si != se; ++si) {
+      declVec.push_back(*si);      
+    }
+    
+    std::sort(declVec.begin(), declVec.end(), compare_vd_entries);
+    
+    for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
+         de = declVec.end(); di != de; ++di) {
+      llvm::errs() << " " << (*di)->getDeclName().getAsString()
+                   << " <";
+      (*di)->getLocation().dump(M);
       llvm::errs() << ">\n";
     }
-}
-
-void LiveVariables::dumpBlockLiveness(const SourceManager& M) const {
-  for (BlockDataMapTy::const_iterator I = getBlockDataMap().begin(),
-       E = getBlockDataMap().end(); I!=E; ++I) {
-    llvm::errs() << "\n[ B" << I->first->getBlockID()
-                 << " (live variables at block exit) ]\n";
-    dumpLiveness(I->second,M);
   }
-
-  llvm::errs() << "\n";
+  llvm::errs() << "\n";  
 }
+
index 2c5a1a255d2969420f5242ada3da96c09374c4c1..f86bf55c329e43fe34e89a2a9b9f8f32087eec65 100644 (file)
@@ -68,12 +68,12 @@ void ReachableCode::computeReachableBlocks() {
 }
 
 namespace {
-class DeadStoreObs : public LiveVariables::ObserverTy {
+class DeadStoreObs : public LiveVariables::Observer {
   const CFG &cfg;
   ASTContext &Ctx;
   BugReporter& BR;
   ParentMap& Parents;
-  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
   llvm::OwningPtr<ReachableCode> reachableCode;
   const CFGBlock *currentBlock;
 
@@ -82,13 +82,14 @@ class DeadStoreObs : public LiveVariables::ObserverTy {
 public:
   DeadStoreObs(const CFG &cfg, ASTContext &ctx,
                BugReporter& br, ParentMap& parents,
-               llvm::SmallPtrSet<VarDecl*, 20> &escaped)
+               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
     : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
       Escaped(escaped), currentBlock(0) {}
 
   virtual ~DeadStoreObs() {}
 
-  void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
+  void Report(const VarDecl* V, DeadStoreKind dsk,
+              SourceLocation L, SourceRange R) {
     if (Escaped.count(V))
       return;
     
@@ -134,10 +135,9 @@ public:
     BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
   }
 
-  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
+  void CheckVarDecl(const VarDecl* VD, const Expr* Ex, const Expr* Val,
                     DeadStoreKind dsk,
-                    const LiveVariables::AnalysisDataTy& AD,
-                    const LiveVariables::ValTy& Live) {
+                    const LiveVariables::LivenessValues &Live) {
 
     if (!VD->hasLocalStorage())
       return;
@@ -146,30 +146,29 @@ public:
     if (VD->getType()->getAs<ReferenceType>())
       return;
 
-    if (!Live(VD, AD) && 
+    if (!Live.isLive(VD) && 
         !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
       Report(VD, dsk, Ex->getSourceRange().getBegin(),
              Val->getSourceRange());
   }
 
-  void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
-                    const LiveVariables::AnalysisDataTy& AD,
-                    const LiveVariables::ValTy& Live) {
-    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
-      CheckVarDecl(VD, DR, Val, dsk, AD, Live);
+  void CheckDeclRef(const DeclRefExpr* DR, const Expr* Val, DeadStoreKind dsk,
+                    const LiveVariables::LivenessValues& Live) {
+    if (const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
+      CheckVarDecl(VD, DR, Val, dsk, Live);
   }
 
-  bool isIncrement(VarDecl* VD, BinaryOperator* B) {
+  bool isIncrement(VarDecl* VD, const BinaryOperator* B) {
     if (B->isCompoundAssignmentOp())
       return true;
 
-    Expr* RHS = B->getRHS()->IgnoreParenCasts();
-    BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
+    const Expr* RHS = B->getRHS()->IgnoreParenCasts();
+    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
 
     if (!BRHS)
       return false;
 
-    DeclRefExpr *DR;
+    const DeclRefExpr *DR;
 
     if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
       if (DR->getDecl() == VD)
@@ -182,9 +181,8 @@ public:
     return false;
   }
 
-  virtual void ObserveStmt(Stmt* S, const CFGBlock *block,
-                           const LiveVariables::AnalysisDataTy& AD,
-                           const LiveVariables::ValTy& Live) {
+  virtual void observeStmt(const Stmt* S, const CFGBlock *block,
+                           const LiveVariables::LivenessValues &Live) {
 
     currentBlock = block;
     
@@ -194,7 +192,7 @@ public:
 
     // Only cover dead stores from regular assignments.  ++/-- dead stores
     // have never flagged a real bug.
-    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
       if (!B->isAssignmentOp()) return; // Skip non-assignments.
 
       if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
@@ -220,26 +218,26 @@ public:
                               ? Enclosing
                               : (isIncrement(VD,B) ? DeadIncrement : Standard);
 
-          CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
+          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
         }
     }
-    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
+    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
       if (!U->isIncrementOp() || U->isPrefix())
         return;
 
-      Stmt *parent = Parents.getParentIgnoreParenCasts(U);
+      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
       if (!parent || !isa<ReturnStmt>(parent))
         return;
 
-      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
+      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
 
-      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
-        CheckDeclRef(DR, U, DeadIncrement, AD, Live);
+      if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
+        CheckDeclRef(DR, U, DeadIncrement, Live);
     }
-    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+    else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S))
       // Iterate through the decls.  Warn if any initializers are complex
       // expressions that are not live (never used).
-      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
+      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
            DI != DE; ++DI) {
 
         VarDecl* V = dyn_cast<VarDecl>(*DI);
@@ -265,7 +263,7 @@ public:
             // A dead initialization is a variable that is dead after it
             // is initialized.  We don't flag warnings for those variables
             // marked 'unused'.
-            if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
+            if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) {
               // Special case: check for initializations with constants.
               //
               //  e.g. : int x = 0;
@@ -318,7 +316,7 @@ public:
 
   CFG& getCFG() { return *cfg; }
 
-  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
+  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
 
   void VisitUnaryOperator(UnaryOperator* U) {
     // Check for '&'.  Any VarDecl whose value has its address-taken we
@@ -351,7 +349,7 @@ public:
       FindEscaped FS(&cfg);
       FS.getCFG().VisitBlockStmts(FS);
       DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
-      L->runOnAllBlocks(cfg, &A);
+      L->runOnAllBlocks(A);
     }
   }
 };
index b540bce9817044840da518a6978087b968993c31..69081a93a63e1cb633a7ae54e2d9b7f1539e2473 100644 (file)
@@ -111,13 +111,19 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
     // FIXME: This should be extended to include other unreachable markers,
     // such as llvm_unreachable.
     if (!CB->empty()) {
-      CFGElement First = CB->front();
-      if (const CFGStmt *S = First.getAs<CFGStmt>()) {
-        if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
-          if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
-            continue;
-        }
+      bool foundUnreachable = false;
+      for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end();
+           ci != ce; ++ci) {
+        if (const CFGStmt *S = (*ci).getAs<CFGStmt>())
+          if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
+            if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable) {
+              foundUnreachable = true;
+              break;
+            }
+          }
       }
+      if (foundUnreachable)
+        continue;
     }
 
     // We found a block that wasn't covered - find the statement to report
index 274d7a6d5d9617cc75958b9f3152a7cd666632e3..543388e4fbc846516a949bee91a95ba938efa116 100644 (file)
@@ -35,6 +35,7 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, Diagnostic &diags,
     EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall),
     EagerlyTrimEGraph(eagerlyTrimEGraph)
 {
+  AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
 }
 
 AnalysisContext *
index 8e31adead18838c44548556bb1f03a45b748486c..75e232f5bdcd1c79f748822420007a5cd77eb857 100644 (file)
@@ -39,8 +39,6 @@ const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
     return ME->getBase()->IgnoreParenCasts();
   }
   else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
-    // Retrieve the base for arrays since BasicStoreManager doesn't know how
-    // to reason about them.
     return AE->getBase();
   }
 
@@ -314,6 +312,21 @@ void bugreporter::registerTrackNullOrUndefValue(BugReporterContext& BRC,
     return;
 
   GRStateManager &StateMgr = BRC.getStateManager();
+  
+  // Walk through nodes until we get one that matches the statement
+  // exactly.
+  while (N) {
+    const ProgramPoint &pp = N->getLocation();
+    if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) {
+      if (ps->getStmt() == S)
+        break;
+    }
+    N = *N->pred_begin();
+  }
+
+  if (!N)
+    return;
+  
   const GRState *state = N->getState();
 
   // Walk through lvalue-to-rvalue conversions.  
index 4a2d33d8d325b503ebfc66494402e24674d4e0b1..92c4a4c581cbfc8900e2eedf6fb1a98368ee670c 100644 (file)
@@ -158,8 +158,6 @@ EnvironmentManager::removeDeadBindings(Environment Env,
                                        const GRState *ST,
                               SmallVectorImpl<const MemRegion*> &DRoots) {
 
-  CFG &C = *SymReaper.getLocationContext()->getCFG();
-
   // We construct a new Environment object entirely, as this is cheaper than
   // individually removing all the subexpression bindings (which will greatly
   // outnumber block-level expression bindings).
@@ -172,7 +170,6 @@ EnvironmentManager::removeDeadBindings(Environment Env,
        I != E; ++I) {
 
     const Stmt *BlkExpr = I.getKey();
-    
     // For recorded locations (used when evaluating loads and stores), we
     // consider them live only when their associated normal expression is
     // also live.
@@ -182,28 +179,8 @@ EnvironmentManager::removeDeadBindings(Environment Env,
       deferredLocations.push_back(std::make_pair(BlkExpr, I.getData()));
       continue;
     }
-    
     const SVal &X = I.getData();
 
-    // Block-level expressions in callers are assumed always live.
-    if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) {
-      NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X);
-
-      if (isa<loc::MemRegionVal>(X)) {
-        const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
-        DRoots.push_back(R);
-      }
-
-      // Mark all symbols in the block expr's value live.
-      MarkLiveCallback cb(SymReaper);
-      ST->scanReachableSymbols(X, cb);
-      continue;
-    }
-
-    // Not a block-level expression?
-    if (!C.isBlkExpr(BlkExpr))
-      continue;
-
     if (SymReaper.isLive(BlkExpr)) {
       // Copy the binding to the new map.
       NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X);
index 003c0f305d279feb6c1219085641e9e4550ea3a0..2c7ad63bd1affa5cf552f0f9c19767ea23747dfa 100644 (file)
@@ -244,7 +244,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
 
   // Create the cleaned state.
   const LocationContext *LC = EntryNode->getLocationContext();
-  SymbolReaper SymReaper(LC, currentStmt, SymMgr);
+  SymbolReaper SymReaper(LC, currentStmt, SymMgr, getStoreManager());
 
   if (AMgr.shouldPurgeDead()) {
     const GRState *St = EntryNode->getState();
index cbc490949076e294bdc00d789cfa36243f8f36fd..370f98ac56b2b2333f7d3e96a6ef71514135bace 100644 (file)
@@ -78,8 +78,11 @@ GRStateManager::removeDeadBindings(const GRState* state,
                                            state, RegionRoots);
 
   // Clean up the store.
-  NewState.setStore(StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
-                                                 SymReaper, RegionRoots));
+  StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
+                                                   SymReaper, RegionRoots);
+  NewState.setStore(newStore);
+  SymReaper.setReapedStore(newStore);
+  
   state = getPersistentState(NewState);
   return ConstraintMgr->removeDeadBindings(state, SymReaper);
 }
@@ -519,9 +522,9 @@ const GRState *GRStateManager::removeGDM(const GRState *state, void *Key) {
 
 namespace {
 class ScanReachableSymbols : public SubRegionMap::Visitor  {
-  typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
+  typedef llvm::DenseMap<const void*, unsigned> VisitedItems;
 
-  VisitedRegionsTy visited;
+  VisitedItems visited;
   const GRState *state;
   SymbolVisitor &visitor;
   llvm::OwningPtr<SubRegionMap> SRM;
@@ -533,6 +536,7 @@ public:
   bool scan(nonloc::CompoundVal val);
   bool scan(SVal val);
   bool scan(const MemRegion *R);
+  bool scan(const SymExpr *sym);
 
   // From SubRegionMap::Visitor.
   bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) {
@@ -549,6 +553,33 @@ bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
   return true;
 }
 
+bool ScanReachableSymbols::scan(const SymExpr *sym) {
+  unsigned &isVisited = visited[sym];
+  if (isVisited)
+    return true;
+  isVisited = 1;
+  
+  if (const SymbolData *sData = dyn_cast<SymbolData>(sym))
+    if (!visitor.VisitSymbol(sData))
+      return false;
+  
+  switch (sym->getKind()) {
+    case SymExpr::RegionValueKind:
+    case SymExpr::ConjuredKind:
+    case SymExpr::DerivedKind:
+    case SymExpr::ExtentKind:
+    case SymExpr::MetadataKind:
+      break;
+    case SymExpr::SymIntKind:
+      return scan(cast<SymIntExpr>(sym)->getLHS());
+    case SymExpr::SymSymKind: {
+      const SymSymExpr *x = cast<SymSymExpr>(sym);
+      return scan(x->getLHS()) && scan(x->getRHS());
+    }
+  }
+  return true;
+}
+
 bool ScanReachableSymbols::scan(SVal val) {
   if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
     return scan(X->getRegion());
@@ -557,7 +588,10 @@ bool ScanReachableSymbols::scan(SVal val) {
     return scan(X->getLoc());
 
   if (SymbolRef Sym = val.getAsSymbol())
-    return visitor.VisitSymbol(Sym);
+    return scan(Sym);
+
+  if (const SymExpr *Sym = val.getAsSymbolicExpression())
+    return scan(Sym);
 
   if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
     return scan(*X);
@@ -566,10 +600,13 @@ bool ScanReachableSymbols::scan(SVal val) {
 }
 
 bool ScanReachableSymbols::scan(const MemRegion *R) {
-  if (isa<MemSpaceRegion>(R) || visited.count(R))
+  if (isa<MemSpaceRegion>(R))
     return true;
-
-  visited.insert(R);
+  
+  unsigned &isVisited = visited[R];
+  if (isVisited)
+    return true;
+  isVisited = 1;
 
   // If this is a symbolic region, visit the symbol for the region.
   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
index b55c96934e42183d9aac391ab80a60b0cc26074d..7ae338e8d89527804b4f4ad4338c3d56bf9b85a2 100644 (file)
@@ -15,6 +15,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
@@ -272,7 +273,7 @@ static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
     return Reaper.isLive(SR->getSymbol());
 
   if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
-    return Reaper.isLive(VR);
+    return Reaper.isLive(VR, true);
 
   // FIXME: This is a gross over-approximation. What we really need is a way to
   // tell if anything still refers to this region. Unlike SymbolicRegions,
@@ -331,13 +332,35 @@ bool SymbolReaper::isLive(const Stmt* ExprVal) const {
       isLive(Loc, ExprVal);
 }
 
-bool SymbolReaper::isLive(const VarRegion *VR) const {
+bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
   const StackFrameContext *VarContext = VR->getStackFrame();
   const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
 
-  if (VarContext == CurrentContext)
-    return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
-        isLive(Loc, VR->getDecl());
+  if (VarContext == CurrentContext) {
+    if (LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+          isLive(Loc, VR->getDecl()))
+      return true;
+
+    if (!includeStoreBindings)
+      return false;
+    
+    unsigned &cachedQuery =
+      const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
+
+    if (cachedQuery) {
+      return cachedQuery == 1;
+    }
+
+    // Query the store to see if the region occurs in any live bindings.
+    if (Store store = reapedStore.getStore()) {
+      bool hasRegion = 
+        reapedStore.getStoreManager().includedInBindings(store, VR);
+      cachedQuery = hasRegion ? 1 : 2;
+      return hasRegion;
+    }
+    
+    return false;
+  }
 
   return VarContext->isParentOf(CurrentContext);
 }
index c877061eb6aeeafdb08003b8389cd719da6003d6..17aa486de0ceb2148bd73d1000b37c3b0c8580a6 100644 (file)
@@ -155,655 +155,718 @@ void test_catch_copy() {
   }
 }
 
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: const A &b = a;
-// CHECK:      4: A()
-// CHECK:      5: const A &c = A();
-// CHECK:      6: [B1.5].~A() (Implicit destructor)
-// CHECK:      7: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1:
-// CHECK:      2: A a[2];
-// CHECK:      3:
-// CHECK:      4: A b[0];
-// CHECK:      5: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3:
-// CHECK:      4: A c;
-// CHECK:      5:
-// CHECK:      6: A d;
-// CHECK:      7: [B1.6].~A() (Implicit destructor)
-// CHECK:      8: [B1.4].~A() (Implicit destructor)
-// CHECK:      9:
-// CHECK:     10: A b;
-// CHECK:     11: [B1.10].~A() (Implicit destructor)
-// CHECK:     12: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B4 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B3
-// CHECK: [ B1 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B1.2].~A() (Implicit destructor)
-// CHECK:      4: [B3.4].~A() (Implicit destructor)
-// CHECK:      5: [B3.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: return;
-// CHECK:      2: [B3.4].~A() (Implicit destructor)
-// CHECK:      3: [B3.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B3 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3:
-// CHECK:      4: A b;
-// CHECK:      5: UV
-// CHECK:      T: if [B3.5]
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (2): B2 B1
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (2): B1 B2
-// CHECK:    Successors (0):
-// CHECK: [ B8 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B7
-// CHECK: [ B1 ]
-// CHECK:    l1:
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B1.2].~A() (Implicit destructor)
-// CHECK:      4: [B6.2].~A() (Implicit destructor)
-// CHECK:      5: [B7.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A b;
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:      4: [B6.4].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: [B6.4].~A() (Implicit destructor)
-// CHECK:      T: goto l1;
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B4.1]
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (2): B3 B2
-// CHECK: [ B5 ]
-// CHECK:      1: [B6.4].~A() (Implicit destructor)
-// CHECK:      2: [B6.2].~A() (Implicit destructor)
-// CHECK:      T: goto l0;
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B6
-// CHECK: [ B6 ]
-// CHECK:    l0:
-// CHECK:      1:
-// CHECK:      2: A b;
-// CHECK:      3:
-// CHECK:      4: A a;
-// CHECK:      5: UV
-// CHECK:      T: if [B6.5]
-// CHECK:    Predecessors (2): B7 B5
-// CHECK:    Successors (2): B5 B4
-// CHECK: [ B7 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B6
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B5 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B4
-// CHECK: [ B1 ]
-// CHECK:      1: [B4.4].~A() (Implicit destructor)
-// CHECK:      2: [B4.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B3.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: a
-// CHECK:      4: A b = a;
-// CHECK:      5: b.operator int()
-// CHECK:      6: [B4.5]
-// CHECK:      T: if [B4.6]
-// CHECK:    Predecessors (1): B5
-// CHECK:    Successors (2): B3 B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B9 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B8
-// CHECK: [ B1 ]
-// CHECK:      1: [B8.4].~A() (Implicit destructor)
-// CHECK:      2:
-// CHECK:      3: A e;
-// CHECK:      4: [B1.3].~A() (Implicit destructor)
-// CHECK:      5: [B8.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B5
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A d;
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:      4: [B4.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: return;
-// CHECK:      2: [B4.2].~A() (Implicit destructor)
-// CHECK:      3: [B8.4].~A() (Implicit destructor)
-// CHECK:      4: [B8.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B0
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: UV
-// CHECK:      T: if [B4.3]
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B3 B2
-// CHECK: [ B5 ]
-// CHECK:      1:
-// CHECK:      2: A d;
-// CHECK:      3: [B5.2].~A() (Implicit destructor)
-// CHECK:      4: [B7.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B1
-// CHECK: [ B6 ]
-// CHECK:      1: return;
-// CHECK:      2: [B7.2].~A() (Implicit destructor)
-// CHECK:      3: [B8.4].~A() (Implicit destructor)
-// CHECK:      4: [B8.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B0
-// CHECK: [ B7 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: UV
-// CHECK:      T: if [B7.3]
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B6 B5
-// CHECK: [ B8 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: a
-// CHECK:      4: A b = a;
-// CHECK:      5: b.operator int()
-// CHECK:      6: [B8.5]
-// CHECK:      T: if [B8.6]
-// CHECK:    Predecessors (1): B9
-// CHECK:    Successors (2): B7 B4
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (3): B1 B3 B6
-// CHECK:    Successors (0):
-// CHECK: [ B6 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B5
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:      2: [B5.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: a
-// CHECK:      2: A b = a;
-// CHECK:      3: b.operator int()
-// CHECK:      4: [B2.3]
-// CHECK:      T: while [B2.4]
-// CHECK:    Predecessors (2): B3 B5
-// CHECK:    Successors (2): B4 B1
-// CHECK: [ B3 ]
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B2
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:      4: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B3
-// CHECK: [ B5 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B12 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B11
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:      2:
-// CHECK:      3: A e;
-// CHECK:      4: [B1.3].~A() (Implicit destructor)
-// CHECK:      5: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B9 B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: a
-// CHECK:      2: A b = a;
-// CHECK:      3: b.operator int()
-// CHECK:      4: [B2.3]
-// CHECK:      T: while [B2.4]
-// CHECK:    Predecessors (2): B3 B11
-// CHECK:    Successors (2): B10 B1
-// CHECK: [ B3 ]
-// CHECK:    Predecessors (2): B4 B7
-// CHECK:    Successors (1): B2
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A d;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:      4: [B10.2].~A() (Implicit destructor)
-// CHECK:      5: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B3
-// CHECK: [ B5 ]
-// CHECK:      1: return;
-// CHECK:      2: [B10.2].~A() (Implicit destructor)
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:      4: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B0
-// CHECK: [ B6 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B6.1]
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B5 B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B10.2].~A() (Implicit destructor)
-// CHECK:      2: [B2.2].~A() (Implicit destructor)
-// CHECK:      T: continue;
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B3
-// CHECK: [ B8 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B8.1]
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (2): B7 B6
-// CHECK: [ B9 ]
-// CHECK:      1: [B10.2].~A() (Implicit destructor)
-// CHECK:      T: break;
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B1
-// CHECK: [ B10 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: UV
-// CHECK:      T: if [B10.3]
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (2): B9 B8
-// CHECK: [ B11 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:    Predecessors (1): B12
-// CHECK:    Successors (1): B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (2): B1 B5
-// CHECK:    Successors (0):
-// CHECK: [ B4 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B2
-// CHECK: [ B1 ]
-// CHECK:      1: UV
-// CHECK:      T: do ... while [B1.1]
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (2): B3 B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B3 B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (1): B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B12 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B11
-// CHECK: [ B1 ]
-// CHECK:      1:
-// CHECK:      2: A d;
-// CHECK:      3: [B1.2].~A() (Implicit destructor)
-// CHECK:      4: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B8 B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: UV
-// CHECK:      T: do ... while [B2.1]
-// CHECK:    Predecessors (2): B3 B6
-// CHECK:    Successors (2): B10 B1
-// CHECK: [ B3 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B3.2].~A() (Implicit destructor)
-// CHECK:      4: [B9.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B5
-// CHECK:    Successors (1): B2
-// CHECK: [ B4 ]
-// CHECK:      1: return;
-// CHECK:      2: [B9.2].~A() (Implicit destructor)
-// CHECK:      3: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B5
-// CHECK:    Successors (1): B0
-// CHECK: [ B5 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B5.1]
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (2): B4 B3
-// CHECK: [ B6 ]
-// CHECK:      1: [B9.2].~A() (Implicit destructor)
-// CHECK:      T: continue;
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B2
-// CHECK: [ B7 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B7.1]
-// CHECK:    Predecessors (1): B9
-// CHECK:    Successors (2): B6 B5
-// CHECK: [ B8 ]
-// CHECK:      1: [B9.2].~A() (Implicit destructor)
-// CHECK:      T: break;
-// CHECK:    Predecessors (1): B9
-// CHECK:    Successors (1): B1
-// CHECK: [ B9 ]
-// CHECK:      1:
-// CHECK:      2: A b;
-// CHECK:      3: UV
-// CHECK:      T: if [B9.3]
-// CHECK:    Predecessors (2): B10 B11
-// CHECK:    Successors (2): B8 B7
-// CHECK: [ B10 ]
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B9
-// CHECK: [ B11 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:    Predecessors (1): B12
-// CHECK:    Successors (1): B9
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (2): B1 B4
-// CHECK:    Successors (0):
-// CHECK: [ B4 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B2
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.4].~A() (Implicit destructor)
-// CHECK:      2: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B3 B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: a
-// CHECK:      4: A b = a;
-// CHECK:      5: b.operator int()
-// CHECK:      T: switch [B2.5]
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B3.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B9 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B2
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.4].~A() (Implicit destructor)
-// CHECK:      2:
-// CHECK:      3: A g;
-// CHECK:      4: [B1.3].~A() (Implicit destructor)
-// CHECK:      5: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (3): B3 B7 B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3: a
-// CHECK:      4: A b = a;
-// CHECK:      5: b.operator int()
-// CHECK:      T: switch [B2.5]
-// CHECK:    Predecessors (1): B9
-// CHECK:    Successors (3): B3 B8
-// CHECK:     B1
-// CHECK: [ B3 ]
-// CHECK:    case 1:
-// CHECK:      T: break;
-// CHECK:    Predecessors (2): B2 B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A f;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:      4: [B8.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B3
-// CHECK: [ B5 ]
-// CHECK:      1: return;
-// CHECK:      2: [B8.2].~A() (Implicit destructor)
-// CHECK:      3: [B2.4].~A() (Implicit destructor)
-// CHECK:      4: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B0
-// CHECK: [ B6 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B6.1]
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B5 B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B8.2].~A() (Implicit destructor)
-// CHECK:      T: break;
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B1
-// CHECK: [ B8 ]
-// CHECK:    case 0:
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: UV
-// CHECK:      T: if [B8.3]
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (2): B7 B6
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (2): B1 B5
-// CHECK:    Successors (0):
-// CHECK: [ B6 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B5
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:      2: [B5.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: a
-// CHECK:      2: A b = a;
-// CHECK:      3: b.operator int()
-// CHECK:      4: [B2.3]
-// CHECK:      T: for (...; [B2.4]; )
-// CHECK:    Predecessors (2): B3 B5
-// CHECK:    Successors (2): B4 B1
-// CHECK: [ B3 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B2
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A c;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B3
-// CHECK: [ B5 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B12 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B11
-// CHECK: [ B1 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:      2: [B11.4].~A() (Implicit destructor)
-// CHECK:      3:
-// CHECK:      4: A f;
-// CHECK:      5: [B1.4].~A() (Implicit destructor)
-// CHECK:      6: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B9 B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: b
-// CHECK:      2: A c = b;
-// CHECK:      3: c.operator int()
-// CHECK:      4: [B2.3]
-// CHECK:      T: for (...; [B2.4]; )
-// CHECK:    Predecessors (2): B3 B11
-// CHECK:    Successors (2): B10 B1
-// CHECK: [ B3 ]
-// CHECK:      1: [B2.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B4 B7
-// CHECK:    Successors (1): B2
-// CHECK: [ B4 ]
-// CHECK:      1:
-// CHECK:      2: A e;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:      4: [B10.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B3
-// CHECK: [ B5 ]
-// CHECK:      1: return;
-// CHECK:      2: [B10.2].~A() (Implicit destructor)
-// CHECK:      3: [B2.2].~A() (Implicit destructor)
-// CHECK:      4: [B11.4].~A() (Implicit destructor)
-// CHECK:      5: [B11.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B6
-// CHECK:    Successors (1): B0
-// CHECK: [ B6 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B6.1]
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B5 B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B10.2].~A() (Implicit destructor)
-// CHECK:      T: continue;
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B3
-// CHECK: [ B8 ]
-// CHECK:      1: UV
-// CHECK:      T: if [B8.1]
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (2): B7 B6
-// CHECK: [ B9 ]
-// CHECK:      1: [B10.2].~A() (Implicit destructor)
-// CHECK:      T: break;
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B1
-// CHECK: [ B10 ]
-// CHECK:      1:
-// CHECK:      2: A d;
-// CHECK:      3: UV
-// CHECK:      T: if [B10.3]
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (2): B9 B8
-// CHECK: [ B11 ]
-// CHECK:      1:
-// CHECK:      2: A a;
-// CHECK:      3:
-// CHECK:      4: A b;
-// CHECK:    Predecessors (1): B12
-// CHECK:    Successors (1): B2
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (2): B1 B5
-// CHECK:    Successors (0):
-// CHECK: [ B3 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B0
-// CHECK: [ B1 ]
-// CHECK:      T: try ...
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (2): B2 B0
-// CHECK: [ B2 ]
-// CHECK:    catch (const A &e):
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (3): B2 B1 B3
-// CHECK:    Successors (0):
-// CHECK: [ B3 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B0
-// CHECK: [ B1 ]
-// CHECK:      T: try ...
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (2): B2 B0
-// CHECK: [ B2 ]
-// CHECK:    catch (A e):
-// CHECK:      1: .~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (3): B2 B1 B3
-// CHECK:    Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: a
+// CHECK:       4: [B1.3]
+// CHECK:       5: const A &b = a;
+// CHECK:       6: A()
+// CHECK:       7: [B1.6] (BindTemporary)
+// CHECK:       8: [B1.7]
+// CHECK:       9: [B1.8]
+// CHECK:      10: const A &c = A();
+// CHECK:      11: [B1.10].~A() (Implicit destructor)
+// CHECK:      12: [B1.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A a[2];
+// CHECK:       3: 
+// CHECK:       4: A b[0];
+// CHECK:       5: [B1.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: 
+// CHECK:       4: A c;
+// CHECK:       5: 
+// CHECK:       6: A d;
+// CHECK:       7: [B1.6].~A() (Implicit destructor)
+// CHECK:       8: [B1.4].~A() (Implicit destructor)
+// CHECK:       9: 
+// CHECK:      10: A b;
+// CHECK:      11: [B1.10].~A() (Implicit destructor)
+// CHECK:      12: [B1.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B4 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B3
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B1.2].~A() (Implicit destructor)
+// CHECK:       4: [B3.4].~A() (Implicit destructor)
+// CHECK:       5: [B3.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: return;
+// CHECK:       2: [B3.4].~A() (Implicit destructor)
+// CHECK:       3: [B3.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B3 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: 
+// CHECK:       4: A b;
+// CHECK:       5: UV
+// CHECK:       6: [B3.5]
+// CHECK:       T: if [B3.6]
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (2): B2 B1
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B2
+// CHECK:     Successors (0):
+// CHECK:  [ B8 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B7
+// CHECK:  [ B1 ]
+// CHECK:     l1:
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B1.2].~A() (Implicit destructor)
+// CHECK:       4: [B6.2].~A() (Implicit destructor)
+// CHECK:       5: [B7.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A b;
+// CHECK:       3: [B2.2].~A() (Implicit destructor)
+// CHECK:       4: [B6.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B6.4].~A() (Implicit destructor)
+// CHECK:       T: goto l1;
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: UV
+// CHECK:       2: [B4.1]
+// CHECK:       T: if [B4.2]
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B5 ]
+// CHECK:       1: [B6.4].~A() (Implicit destructor)
+// CHECK:       2: [B6.2].~A() (Implicit destructor)
+// CHECK:       T: goto l0;
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B6
+// CHECK:  [ B6 ]
+// CHECK:     l0:
+// CHECK:       1: 
+// CHECK:       2: A b;
+// CHECK:       3: 
+// CHECK:       4: A a;
+// CHECK:       5: UV
+// CHECK:       6: [B6.5]
+// CHECK:       T: if [B6.6]
+// CHECK:     Predecessors (2): B7 B5
+// CHECK:     Successors (2): B5 B4
+// CHECK:  [ B7 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B6
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B5 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B4
+// CHECK:  [ B1 ]
+// CHECK:       1: [B4.6].~A() (Implicit destructor)
+// CHECK:       2: [B4.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B2.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B3.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: a
+// CHECK:       4: [B4.3]
+// CHECK:       5: [B4.4]
+// CHECK:       6: A b = a;
+// CHECK:       7: b
+// CHECK:       8: [B4.7]
+// CHECK:       9: [B4.8].operator int
+// CHECK:      10: [B4.9]()
+// CHECK:      11: [B4.10]
+// CHECK:       T: if [B4.11]
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B9 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B8
+// CHECK:  [ B1 ]
+// CHECK:       1: [B8.6].~A() (Implicit destructor)
+// CHECK:       2: 
+// CHECK:       3: A e;
+// CHECK:       4: [B1.3].~A() (Implicit destructor)
+// CHECK:       5: [B8.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B5
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A d;
+// CHECK:       3: [B2.2].~A() (Implicit destructor)
+// CHECK:       4: [B4.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: return;
+// CHECK:       2: [B4.2].~A() (Implicit destructor)
+// CHECK:       3: [B8.6].~A() (Implicit destructor)
+// CHECK:       4: [B8.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B0
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: UV
+// CHECK:       4: [B4.3]
+// CHECK:       T: if [B4.4]
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B5 ]
+// CHECK:       1: 
+// CHECK:       2: A d;
+// CHECK:       3: [B5.2].~A() (Implicit destructor)
+// CHECK:       4: [B7.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B1
+// CHECK:  [ B6 ]
+// CHECK:       1: return;
+// CHECK:       2: [B7.2].~A() (Implicit destructor)
+// CHECK:       3: [B8.6].~A() (Implicit destructor)
+// CHECK:       4: [B8.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B0
+// CHECK:  [ B7 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: UV
+// CHECK:       4: [B7.3]
+// CHECK:       T: if [B7.4]
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B6 B5
+// CHECK:  [ B8 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: a
+// CHECK:       4: [B8.3]
+// CHECK:       5: [B8.4]
+// CHECK:       6: A b = a;
+// CHECK:       7: b
+// CHECK:       8: [B8.7]
+// CHECK:       9: [B8.8].operator int
+// CHECK:      10: [B8.9]()
+// CHECK:      11: [B8.10]
+// CHECK:       T: if [B8.11]
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (2): B7 B4
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (3): B1 B3 B6
+// CHECK:     Successors (0):
+// CHECK:  [ B6 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B5
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:       2: [B5.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: a
+// CHECK:       2: [B2.1]
+// CHECK:       3: [B2.2]
+// CHECK:       4: A b = a;
+// CHECK:       5: b
+// CHECK:       6: [B2.5]
+// CHECK:       7: [B2.6].operator int
+// CHECK:       8: [B2.7]()
+// CHECK:       9: [B2.8]
+// CHECK:       T: while [B2.9]
+// CHECK:     Predecessors (2): B3 B5
+// CHECK:     Successors (2): B4 B1
+// CHECK:  [ B3 ]
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B2
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B4.2].~A() (Implicit destructor)
+// CHECK:       4: [B2.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B12 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B11
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:       2: 
+// CHECK:       3: A e;
+// CHECK:       4: [B1.3].~A() (Implicit destructor)
+// CHECK:       5: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B9 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: a
+// CHECK:       2: [B2.1]
+// CHECK:       3: [B2.2]
+// CHECK:       4: A b = a;
+// CHECK:       5: b
+// CHECK:       6: [B2.5]
+// CHECK:       7: [B2.6].operator int
+// CHECK:       8: [B2.7]()
+// CHECK:       9: [B2.8]
+// CHECK:       T: while [B2.9]
+// CHECK:     Predecessors (2): B3 B11
+// CHECK:     Successors (2): B10 B1
+// CHECK:  [ B3 ]
+// CHECK:     Predecessors (2): B4 B7
+// CHECK:     Successors (1): B2
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// 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:     Predecessors (1): B6
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: return;
+// CHECK:       2: [B10.2].~A() (Implicit destructor)
+// CHECK:       3: [B2.4].~A() (Implicit destructor)
+// CHECK:       4: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B0
+// CHECK:  [ B6 ]
+// CHECK:       1: UV
+// CHECK:       2: [B6.1]
+// CHECK:       T: if [B6.2]
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B5 B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B10.2].~A() (Implicit destructor)
+// CHECK:       2: [B2.4].~A() (Implicit destructor)
+// CHECK:       T: continue;
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B3
+// CHECK:  [ B8 ]
+// CHECK:       1: UV
+// CHECK:       2: [B8.1]
+// CHECK:       T: if [B8.2]
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B7 B6
+// CHECK:  [ B9 ]
+// CHECK:       1: [B10.2].~A() (Implicit destructor)
+// CHECK:       T: break;
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B1
+// CHECK:  [ B10 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: UV
+// CHECK:       4: [B10.3]
+// CHECK:       T: if [B10.4]
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (2): B9 B8
+// CHECK:  [ B11 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:     Predecessors (1): B12
+// CHECK:     Successors (1): B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B5
+// CHECK:     Successors (0):
+// CHECK:  [ B4 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B2
+// CHECK:  [ B1 ]
+// CHECK:       1: UV
+// CHECK:       2: [B1.1]
+// CHECK:       T: do ... while [B1.2]
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (2): B3 B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: [B2.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B3 B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (1): B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B12 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B11
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A d;
+// CHECK:       3: [B1.2].~A() (Implicit destructor)
+// CHECK:       4: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B8 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: UV
+// CHECK:       2: [B2.1]
+// CHECK:       T: do ... while [B2.2]
+// CHECK:     Predecessors (2): B3 B6
+// CHECK:     Successors (2): B10 B1
+// CHECK:  [ B3 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B3.2].~A() (Implicit destructor)
+// CHECK:       4: [B9.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (1): B2
+// CHECK:  [ B4 ]
+// CHECK:       1: return;
+// CHECK:       2: [B9.2].~A() (Implicit destructor)
+// CHECK:       3: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (1): B0
+// CHECK:  [ B5 ]
+// CHECK:       1: UV
+// CHECK:       2: [B5.1]
+// CHECK:       T: if [B5.2]
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (2): B4 B3
+// CHECK:  [ B6 ]
+// CHECK:       1: [B9.2].~A() (Implicit destructor)
+// CHECK:       T: continue;
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B2
+// CHECK:  [ B7 ]
+// CHECK:       1: UV
+// CHECK:       2: [B7.1]
+// CHECK:       T: if [B7.2]
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (2): B6 B5
+// CHECK:  [ B8 ]
+// CHECK:       1: [B9.2].~A() (Implicit destructor)
+// CHECK:       T: break;
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (1): B1
+// CHECK:  [ B9 ]
+// CHECK:       1: 
+// CHECK:       2: A b;
+// CHECK:       3: UV
+// CHECK:       4: [B9.3]
+// CHECK:       T: if [B9.4]
+// CHECK:     Predecessors (2): B10 B11
+// CHECK:     Successors (2): B8 B7
+// CHECK:  [ B10 ]
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B9
+// CHECK:  [ B11 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:     Predecessors (1): B12
+// CHECK:     Successors (1): B9
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B4
+// CHECK:     Successors (0):
+// CHECK:  [ B4 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B2
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.6].~A() (Implicit destructor)
+// CHECK:       2: [B2.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B3 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: a
+// CHECK:       4: [B2.3]
+// CHECK:       5: [B2.4]
+// CHECK:       6: A b = a;
+// CHECK:       7: b
+// CHECK:       8: [B2.7]
+// CHECK:       9: [B2.8].operator int
+// CHECK:      10: [B2.9]()
+// CHECK:       T: switch [B2.10]
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B3.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B9 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B2
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.6].~A() (Implicit destructor)
+// CHECK:       2: 
+// CHECK:       3: A g;
+// CHECK:       4: [B1.3].~A() (Implicit destructor)
+// CHECK:       5: [B2.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (3): B3 B7 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: a
+// CHECK:       4: [B2.3]
+// CHECK:       5: [B2.4]
+// CHECK:       6: A b = a;
+// CHECK:       7: b
+// CHECK:       8: [B2.7]
+// CHECK:       9: [B2.8].operator int
+// CHECK:      10: [B2.9]()
+// CHECK:       T: switch [B2.10]
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (3): B3 B8
+// CHECK:      B1
+// CHECK:  [ B3 ]
+// CHECK:     case 1:
+// CHECK:       T: break;
+// CHECK:     Predecessors (2): B2 B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A f;
+// CHECK:       3: [B4.2].~A() (Implicit destructor)
+// CHECK:       4: [B8.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: return;
+// CHECK:       2: [B8.2].~A() (Implicit destructor)
+// CHECK:       3: [B2.6].~A() (Implicit destructor)
+// CHECK:       4: [B2.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B0
+// CHECK:  [ B6 ]
+// CHECK:       1: UV
+// CHECK:       2: [B6.1]
+// CHECK:       T: if [B6.2]
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B5 B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B8.2].~A() (Implicit destructor)
+// CHECK:       T: break;
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B1
+// CHECK:  [ B8 ]
+// CHECK:     case 0:
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: UV
+// CHECK:       4: [B8.3]
+// CHECK:       T: if [B8.4]
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (2): B7 B6
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B5
+// CHECK:     Successors (0):
+// CHECK:  [ B6 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B5
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:       2: [B5.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: a
+// CHECK:       2: [B2.1]
+// CHECK:       3: [B2.2]
+// CHECK:       4: A b = a;
+// CHECK:       5: b
+// CHECK:       6: [B2.5]
+// CHECK:       7: [B2.6].operator int
+// CHECK:       8: [B2.7]()
+// CHECK:       9: [B2.8]
+// CHECK:       T: for (...; [B2.9]; )
+// CHECK:     Predecessors (2): B3 B5
+// CHECK:     Successors (2): B4 B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B2
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A c;
+// CHECK:       3: [B4.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B12 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B11
+// CHECK:  [ B1 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:       2: [B11.4].~A() (Implicit destructor)
+// CHECK:       3: 
+// CHECK:       4: A f;
+// CHECK:       5: [B1.4].~A() (Implicit destructor)
+// CHECK:       6: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B9 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: b
+// CHECK:       2: [B2.1]
+// CHECK:       3: [B2.2]
+// CHECK:       4: A c = b;
+// CHECK:       5: c
+// CHECK:       6: [B2.5]
+// CHECK:       7: [B2.6].operator int
+// CHECK:       8: [B2.7]()
+// CHECK:       9: [B2.8]
+// CHECK:       T: for (...; [B2.9]; )
+// CHECK:     Predecessors (2): B3 B11
+// CHECK:     Successors (2): B10 B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B2.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B4 B7
+// CHECK:     Successors (1): B2
+// CHECK:  [ B4 ]
+// CHECK:       1: 
+// CHECK:       2: A e;
+// CHECK:       3: [B4.2].~A() (Implicit destructor)
+// CHECK:       4: [B10.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: return;
+// CHECK:       2: [B10.2].~A() (Implicit destructor)
+// CHECK:       3: [B2.4].~A() (Implicit destructor)
+// CHECK:       4: [B11.4].~A() (Implicit destructor)
+// CHECK:       5: [B11.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B0
+// CHECK:  [ B6 ]
+// CHECK:       1: UV
+// CHECK:       2: [B6.1]
+// CHECK:       T: if [B6.2]
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B5 B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B10.2].~A() (Implicit destructor)
+// CHECK:       T: continue;
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B3
+// CHECK:  [ B8 ]
+// CHECK:       1: UV
+// CHECK:       2: [B8.1]
+// CHECK:       T: if [B8.2]
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B7 B6
+// CHECK:  [ B9 ]
+// CHECK:       1: [B10.2].~A() (Implicit destructor)
+// CHECK:       T: break;
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B1
+// CHECK:  [ B10 ]
+// CHECK:       1: 
+// CHECK:       2: A d;
+// CHECK:       3: UV
+// CHECK:       4: [B10.3]
+// CHECK:       T: if [B10.4]
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (2): B9 B8
+// CHECK:  [ B11 ]
+// CHECK:       1: 
+// CHECK:       2: A a;
+// CHECK:       3: 
+// CHECK:       4: A b;
+// CHECK:     Predecessors (1): B12
+// CHECK:     Successors (1): B2
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B5
+// CHECK:     Successors (0):
+// CHECK:  [ B3 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B0
+// CHECK:  [ B1 ]
+// CHECK:       T: try ...
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (2): B2 B0
+// CHECK:  [ B2 ]
+// CHECK:     catch (const A &e):
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (3): B2 B1 B3
+// CHECK:     Successors (0):
+// CHECK:  [ B3 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B0
+// CHECK:  [ B1 ]
+// CHECK:       T: try ...
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (2): B2 B0
+// CHECK:  [ B2 ]
+// CHECK:     catch (A e):
+// CHECK:       1: .~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (3): B2 B1 B3
+// CHECK:     Successors (0):
 
index 5c5d51494749dce62605ebbe1a61f15207bbb745..b73809f2b83ac2c62e4f46a322ecfe33c07e663e 100644 (file)
@@ -44,51 +44,60 @@ TestControlFlow::TestControlFlow(bool b)
   int v;
 }
 
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: 
-// CHECK:      2: A([B1.1]) (Base initializer)
-// CHECK:      3: 
-// CHECK:      4: C([B1.3]) (Base initializer)
-// CHECK:      5: 
-// CHECK:      6: B([B1.5]) (Base initializer)
-// CHECK:      7: 
-// CHECK:      8: A([B1.7]) (Base initializer)
-// CHECK:      9: i(/*implicit*/int()) (Member initializer)
-// CHECK:     10: r(this->i) (Member initializer)
-// CHECK:     11: 
-// CHECK:     12: A a;
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B5 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B4
-// CHECK: [ B1 ]
-// CHECK:      1: [B4.2] ? [B2.1] : [B3.1]
-// CHECK:      2: y([B1.1]) (Member initializer)
-// CHECK:      3: z(this->y) (Member initializer)
-// CHECK:      4: int v;
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: 0
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: 1
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: x(0) (Member initializer)
-// CHECK:      2: b
-// CHECK:      T: [B4.2] ? ... : ...
-// CHECK:    Predecessors (1): B5
-// CHECK:    Successors (2): B2 B3
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: 
+// CHECK:       2: A([B1.1]) (Base initializer)
+// CHECK:       3: 
+// CHECK:       4: C([B1.3]) (Base initializer)
+// CHECK:       5: 
+// CHECK:       6: B([B1.5]) (Base initializer)
+// CHECK:       7: 
+// CHECK:       8: A([B1.7]) (Base initializer)
+// CHECK:       9: /*implicit*/int()
+// CHECK:      10: i([B1.9]) (Member initializer)
+// CHECK:      11: this
+// CHECK:      12: [B1.11]->i
+// CHECK:      13: r([B1.12]) (Member initializer)
+// CHECK:      14: 
+// CHECK:      15: A a;
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B5 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B4
+// CHECK:  [ B1 ]
+// CHECK:       1: [B4.4] ? [B2.1] : [B3.1]
+// CHECK:       2: y([B1.1]) (Member initializer)
+// CHECK:       3: this
+// CHECK:       4: [B1.3]->y
+// CHECK:       5: [B1.4]
+// CHECK:       6: z([B1.5]) (Member initializer)
+// CHECK:       7: int v;
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 0
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: 1
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: 0
+// CHECK:       2: x([B4.1]) (Member initializer)
+// CHECK:       3: b
+// CHECK:       4: [B4.3]
+// CHECK:       T: [B4.4] ? ... : ...
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (2): B2 B3
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+
index 8c65b478f1c2532ccfd7e020eac9764ac3bf263b..227365709116e21697b7b0186a8e9c4ffd2b4d93 100644 (file)
@@ -94,7 +94,6 @@ void test2_ptr(int x) {
   p[-1] = 1; // expected-warning{{Out of bound memory access}}
 }
 
-// ** FIXME ** Doesn't work yet because we don't support pointer arithmetic.
 // Tests doing an out-of-bounds access before the start of an array using:
 // - indirect pointer to buffer, manipulated using simple pointer arithmetic
 // - constant integer index
@@ -103,7 +102,7 @@ void test2_ptr_arith(int x) {
   int buf[100];
   int *p = buf;
   --p;
-  p[0] = 1; // no-warning
+  p[0] = 1; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
 }
 
 // Tests doing an out-of-bounds access before the start of a multi-dimensional
index 0f4d3aee07444eaa19d427d3c3be2e30d005b351..d07a929b7f3267899055674505b43de109501af8 100644 (file)
@@ -69,34 +69,6 @@ void rdar8331641(int x) {
 // CHECK:    <key>path</key>
 // CHECK:    <array>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>4</integer>
-// CHECK:       <key>col</key><integer>3</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>4</integer>
-// CHECK:          <key>col</key><integer>3</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>4</integer>
-// CHECK:          <key>col</key><integer>8</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Variable &apos;p&apos; initialized to a null pointer value</string>
-// CHECK:      <key>message</key>
-// CHECK: <string>Variable &apos;p&apos; initialized to a null pointer value</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -110,7 +82,7 @@ void rdar8331641(int x) {
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>4</integer>
-// CHECK:            <key>col</key><integer>8</integer>
+// CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -193,68 +165,6 @@ void rdar8331641(int x) {
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>10</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>10</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:          </array>
-// CHECK:        </dict>
-// CHECK:       </array>
-// CHECK:     </dict>
-// CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>10</integer>
-// CHECK:       <key>col</key><integer>3</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>10</integer>
-// CHECK:          <key>col</key><integer>3</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>10</integer>
-// CHECK:          <key>col</key><integer>7</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK:      <key>message</key>
-// CHECK: <string>Null pointer value stored to &apos;p&apos;</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
-// CHECK:      <key>kind</key><string>control</string>
-// CHECK:      <key>edges</key>
-// CHECK:       <array>
-// CHECK:        <dict>
-// CHECK:         <key>start</key>
-// CHECK:          <array>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>10</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>10</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:          </array>
-// CHECK:         <key>end</key>
-// CHECK:          <array>
-// CHECK:           <dict>
 // CHECK:            <key>line</key><integer>11</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
@@ -331,68 +241,6 @@ void rdar8331641(int x) {
 // CHECK:         <key>end</key>
 // CHECK:          <array>
 // CHECK:           <dict>
-// CHECK:            <key>line</key><integer>17</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>17</integer>
-// CHECK:            <key>col</key><integer>8</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:          </array>
-// CHECK:        </dict>
-// CHECK:       </array>
-// CHECK:     </dict>
-// CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>17</integer>
-// CHECK:       <key>col</key><integer>3</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>17</integer>
-// CHECK:          <key>col</key><integer>3</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>17</integer>
-// CHECK:          <key>col</key><integer>8</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Variable &apos;q&apos; initialized to a null pointer value</string>
-// CHECK:      <key>message</key>
-// CHECK: <string>Variable &apos;q&apos; initialized to a null pointer value</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
-// CHECK:      <key>kind</key><string>control</string>
-// CHECK:      <key>edges</key>
-// CHECK:       <array>
-// CHECK:        <dict>
-// CHECK:         <key>start</key>
-// CHECK:          <array>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>17</integer>
-// CHECK:            <key>col</key><integer>3</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:           <dict>
-// CHECK:            <key>line</key><integer>17</integer>
-// CHECK:            <key>col</key><integer>8</integer>
-// CHECK:            <key>file</key><integer>0</integer>
-// CHECK:           </dict>
-// CHECK:          </array>
-// CHECK:         <key>end</key>
-// CHECK:          <array>
-// CHECK:           <dict>
 // CHECK:            <key>line</key><integer>18</integer>
 // CHECK:            <key>col</key><integer>3</integer>
 // CHECK:            <key>file</key><integer>0</integer>
@@ -551,7 +399,7 @@ void rdar8331641(int x) {
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>29</integer>
-// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -559,34 +407,6 @@ void rdar8331641(int x) {
 // CHECK:       </array>
 // CHECK:     </dict>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>29</integer>
-// CHECK:       <key>col</key><integer>5</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>29</integer>
-// CHECK:          <key>col</key><integer>5</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>29</integer>
-// CHECK:          <key>col</key><integer>10</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Variable &apos;p&apos; initialized to a null pointer value</string>
-// CHECK:      <key>message</key>
-// CHECK: <string>Variable &apos;p&apos; initialized to a null pointer value</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -600,7 +420,7 @@ void rdar8331641(int x) {
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>29</integer>
-// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>col</key><integer>5</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -924,12 +744,12 @@ void rdar8331641(int x) {
 // CHECK:          <array>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>56</integer>
-// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>col</key><integer>10</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>56</integer>
-// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>col</key><integer>10</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
@@ -945,12 +765,12 @@ void rdar8331641(int x) {
 // CHECK:          <array>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>56</integer>
-// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>col</key><integer>10</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:           <dict>
 // CHECK:            <key>line</key><integer>56</integer>
-// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>col</key><integer>10</integer>
 // CHECK:            <key>file</key><integer>0</integer>
 // CHECK:           </dict>
 // CHECK:          </array>
index 457c9023c400a25cee95549ce42ffc0287486ea2..cf4e1d0d72bce8bf661652c6dbdbee752f4db787 100644 (file)
@@ -1446,7 +1446,7 @@ static void rdar_8724287(CFErrorRef error)
     while (error_to_dump != ((void*)0)) {
         CFDictionaryRef info;
 
-        info = CFErrorCopyUserInfo(error_to_dump); // expected-warning{{Potential leak of an object allocated on line 1449 and stored into 'info'}}
+        info = CFErrorCopyUserInfo(error_to_dump); // expected-warning{{Potential leak of an object allocated on line 1447 and stored into 'info'}}
 
         if (info != ((void*)0)) {
         }
index bf2a4fa4e13cdd845595f46ee0aa3a0105277637..8a1ae6761ca7ac0e40c244c46ed27245c3ec9b85 100644 (file)
@@ -59,7 +59,7 @@ int struct_test(struct baz byVal, int flag) {
 typedef int (^ComparatorBlock)(int a, int b);
 ComparatorBlock test_return_block(void) {
   ComparatorBlock b = ^int(int a, int b){ return a > b; };
-  return b; // expected-warning{{Address of stack-allocated block declared on line 61 returned to caller}}
+  return b; // expected-warning{{Address of stack-allocated block declared on line 60 returned to caller}}
 }
 
 ComparatorBlock test_return_block_neg_aux(void);
index 5ed782c690a1d82b91711df8b79d2f46966062bf..17864e4c548598d1af5670aebaef1b962ce579d2 100644 (file)
@@ -106,486 +106,661 @@ TestCtorInits::TestCtorInits()
   : a(int(A()) + int(B()))
   , b() {}
 
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A()
-// CHECK:      2: [B1.1].operator int()
-// CHECK:      3: B()
-// CHECK:      4: [B1.3].operator int()
-// CHECK:      5: int a = int(A().operator int()) + int(B().operator int());
-// CHECK:      6: ~B() (Temporary object destructor)
-// CHECK:      7: ~A() (Temporary object destructor)
-// CHECK:      8: A()
-// CHECK:      9: [B1.8].operator int()
-// CHECK:     10: B()
-// CHECK:     11: [B1.10].operator int()
-// CHECK:     12: foo(int([B1.9]) + int([B1.11]))
-// CHECK:     13: ~B() (Temporary object destructor)
-// CHECK:     14: ~A() (Temporary object destructor)
-// CHECK:     15: int b;
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B10 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B8
-// CHECK: [ B1 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: int b;
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B3
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: [B4.3] && [B5.2]
-// CHECK:      2: foo([B3.1])
-// CHECK:      T: [B4.3] && ...
-// CHECK:    Predecessors (2): B5 B4
-// CHECK:    Successors (2): B2 B1
-// CHECK: [ B4 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: A()
-// CHECK:      3: [B4.2].operator _Bool()
-// CHECK:      T: [B4.3] && ...
-// CHECK:    Predecessors (2): B6 B7
-// CHECK:    Successors (2): B5 B3
-// CHECK: [ B5 ]
-// CHECK:      1: B()
-// CHECK:      2: [B5.1].operator _Bool()
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B3
-// CHECK: [ B6 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B8.2] && [B9.2]
-// CHECK:      2: bool a = A().operator _Bool() && B().operator _Bool();
-// CHECK:      T: [B8.2] && ...
-// CHECK:    Predecessors (2): B9 B8
-// CHECK:    Successors (2): B6 B4
-// CHECK: [ B8 ]
-// CHECK:      1: A()
-// CHECK:      2: [B8.1].operator _Bool()
-// CHECK:      T: [B8.2] && ...
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (2): B9 B7
-// CHECK: [ B9 ]
-// CHECK:      1: B()
-// CHECK:      2: [B9.1].operator _Bool()
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B7
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B10 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B8
-// CHECK: [ B1 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: int b;
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B3
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: [B4.3] || [B5.2]
-// CHECK:      2: foo([B3.1])
-// CHECK:      T: [B4.3] || ...
-// CHECK:    Predecessors (2): B5 B4
-// CHECK:    Successors (2): B1 B2
-// CHECK: [ B4 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: A()
-// CHECK:      3: [B4.2].operator _Bool()
-// CHECK:      T: [B4.3] || ...
-// CHECK:    Predecessors (2): B6 B7
-// CHECK:    Successors (2): B3 B5
-// CHECK: [ B5 ]
-// CHECK:      1: B()
-// CHECK:      2: [B5.1].operator _Bool()
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B3
-// CHECK: [ B6 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B8.2] || [B9.2]
-// CHECK:      2: bool a = A().operator _Bool() || B().operator _Bool();
-// CHECK:      T: [B8.2] || ...
-// CHECK:    Predecessors (2): B9 B8
-// CHECK:    Successors (2): B4 B6
-// CHECK: [ B8 ]
-// CHECK:      1: A()
-// CHECK:      2: [B8.1].operator _Bool()
-// CHECK:      T: [B8.2] || ...
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (2): B7 B9
-// CHECK: [ B9 ]
-// CHECK:      1: B()
-// CHECK:      2: [B9.1].operator _Bool()
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (1): B7
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B11 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B10
-// CHECK: [ B1 ]
-// CHECK:      1: int b;
-// CHECK:      2: [B7.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: foo(0)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: foo(0)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:      2: B()
-// CHECK:      3: [B4.2].operator _Bool()
-// CHECK:      4: ~B() (Temporary object destructor)
-// CHECK:      T: if [B4.3]
-// CHECK:    Predecessors (2): B5 B6
-// CHECK:    Successors (2): B3 B2
-// CHECK: [ B5 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B6 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:      3: ~A() (Temporary object destructor)
-// CHECK:      4: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: [B10.2] ? [B8.2] : [B9.3]
-// CHECK:      2: A a = B().operator _Bool() ? A() : A(B().operator A());
-// CHECK:      T: [B10.2] ? ... : ...
-// CHECK:    Predecessors (2): B8 B9
-// CHECK:    Successors (2): B5 B6
-// CHECK: [ B8 ]
-// CHECK:      1: A()
-// CHECK:      2: [B8.1] (BindTemporary)
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B7
-// CHECK: [ B9 ]
-// CHECK:      1: B()
-// CHECK:      2: [B9.1].operator A()
-// CHECK:      3: A([B9.2]) (BindTemporary)
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B7
-// CHECK: [ B10 ]
-// CHECK:      1: B()
-// CHECK:      2: [B10.1].operator _Bool()
-// CHECK:      T: [B10.2] ? ... : ...
-// CHECK:    Predecessors (1): B11
-// CHECK:    Successors (2): B8 B9
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B14 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B13
-// CHECK: [ B1 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:      2: int b;
-// CHECK:      3: [B10.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:      3: ~A() (Temporary object destructor)
-// CHECK:      4: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: [B7.3] ? [B5.2] : [B6.3]
-// CHECK:      2: foo([B4.1])
-// CHECK:      T: [B7.3] ? ... : ...
-// CHECK:    Predecessors (2): B5 B6
-// CHECK:    Successors (2): B2 B3
-// CHECK: [ B5 ]
-// CHECK:      1: A()
-// CHECK:      2: [B5.1] (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B6 ]
-// CHECK:      1: B()
-// CHECK:      2: [B6.1].operator A()
-// CHECK:      3: A([B6.2]) (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: ~B() (Temporary object destructor)
-// CHECK:      2: B()
-// CHECK:      3: [B7.2].operator _Bool()
-// CHECK:      T: [B7.3] ? ... : ...
-// CHECK:    Predecessors (2): B8 B9
-// CHECK:    Successors (2): B5 B6
-// CHECK: [ B8 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B7
-// CHECK: [ B9 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:      3: ~B() (Temporary object destructor)
-// CHECK:    Predecessors (1): B10
-// CHECK:    Successors (1): B7
-// CHECK: [ B10 ]
-// CHECK:      1: [B13.2] ? [B11.2] : [B12.3]
-// CHECK:      2: const A &a = B().operator _Bool() ? A() : A(B().operator A());
-// CHECK:      T: [B13.2] ? ... : ...
-// CHECK:    Predecessors (2): B11 B12
-// CHECK:    Successors (2): B8 B9
-// CHECK: [ B11 ]
-// CHECK:      1: A()
-// CHECK:      2: [B11.1] (BindTemporary)
-// CHECK:    Predecessors (1): B13
-// CHECK:    Successors (1): B10
-// CHECK: [ B12 ]
-// CHECK:      1: B()
-// CHECK:      2: [B12.1].operator A()
-// CHECK:      3: A([B12.2]) (BindTemporary)
-// CHECK:    Predecessors (1): B13
-// CHECK:    Successors (1): B10
-// CHECK: [ B13 ]
-// CHECK:      1: B()
-// CHECK:      2: [B13.1].operator _Bool()
-// CHECK:      T: [B13.2] ? ... : ...
-// CHECK:    Predecessors (1): B14
-// CHECK:    Successors (2): B11 B12
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B8 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B7
-// CHECK: [ B1 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: int b;
-// CHECK:      3: [B4.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: [B7.2] ?: [B6.2]
-// CHECK:      2: A a = A() ?: A();
-// CHECK:      T: [B7.3] ? ... : ...
-// CHECK:    Predecessors (2): B5 B6
-// CHECK:    Successors (2): B2 B3
-// CHECK: [ B5 ]
-// CHECK:      1:
-// CHECK:      2: [B5.1] (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B6 ]
-// CHECK:      1: A()
-// CHECK:      2: [B6.1] (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: A()
-// CHECK:      2: [B7.1] (BindTemporary)
-// CHECK:      3: .operator _Bool()
-// CHECK:      T: [B7.3] ? ... : ...
-// CHECK:    Predecessors (1): B8
-// CHECK:    Successors (2): B5 B6
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B13 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B12
-// CHECK: [ B1 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: int b;
-// CHECK:      3: [B9.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (2): B2 B3
-// CHECK:    Successors (1): B0
-// CHECK: [ B2 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B3 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B4
-// CHECK:    Successors (1): B1
-// CHECK: [ B4 ]
-// CHECK:      1: [B7.3] ?: [B6.2]
-// CHECK:      2: foo([B4.1])
-// CHECK:      T: [B7.4] ? ... : ...
-// CHECK:    Predecessors (2): B5 B6
-// CHECK:    Successors (2): B2 B3
-// CHECK: [ B5 ]
-// CHECK:      1:
-// CHECK:      2: [B5.1] (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B6 ]
-// CHECK:      1: A()
-// CHECK:      2: [B6.1] (BindTemporary)
-// CHECK:    Predecessors (1): B7
-// CHECK:    Successors (1): B4
-// CHECK: [ B7 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:      2: A()
-// CHECK:      3: [B7.2] (BindTemporary)
-// CHECK:      4: .operator _Bool()
-// CHECK:      T: [B7.4] ? ... : ...
-// CHECK:    Predecessors (2): B9 B8
-// CHECK:    Successors (2): B5 B6
-// CHECK: [ B8 ]
-// CHECK:      1: ~A() (Temporary object destructor)
-// CHECK:    Predecessors (1): B9
-// CHECK:    Successors (1): B7
-// CHECK: [ B9 ]
-// CHECK:      1: [B12.2] ?: [B11.2]
-// CHECK:      2: const A &a = A() ?: A();
-// CHECK:      T: [B12.3] ? ... : ...
-// CHECK:    Predecessors (2): B10 B11
-// CHECK:    Successors (2): B7 B8
-// CHECK: [ B10 ]
-// CHECK:      1:
-// CHECK:      2: [B10.1] (BindTemporary)
-// CHECK:    Predecessors (1): B12
-// CHECK:    Successors (1): B9
-// CHECK: [ B11 ]
-// CHECK:      1: A()
-// CHECK:      2: [B11.1] (BindTemporary)
-// CHECK:    Predecessors (1): B12
-// CHECK:    Successors (1): B9
-// CHECK: [ B12 ]
-// CHECK:      1: A()
-// CHECK:      2: [B12.1] (BindTemporary)
-// CHECK:      3: .operator _Bool()
-// CHECK:      T: [B12.3] ? ... : ...
-// CHECK:    Predecessors (1): B13
-// CHECK:    Successors (2): B10 B11
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A()
-// CHECK:      2: A a = A();
-// CHECK:      3: ~A() (Temporary object destructor)
-// CHECK:      4: int b;
-// CHECK:      5: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A()
-// CHECK:      2: const A &a = A();
-// CHECK:      3: A()
-// CHECK:      4: foo([B1.3])
-// CHECK:      5: ~A() (Temporary object destructor)
-// CHECK:      6: int b;
-// CHECK:      7: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A::make()
-// CHECK:      2: A a = A::make();
-// CHECK:      3: ~A() (Temporary object destructor)
-// CHECK:      4: int b;
-// CHECK:      5: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A::make()
-// CHECK:      2: const A &a = A::make();
-// CHECK:      3: A::make()
-// CHECK:      4: foo([B1.3])
-// CHECK:      5: ~A() (Temporary object destructor)
-// CHECK:      6: int b;
-// CHECK:      7: [B1.2].~A() (Implicit destructor)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: int a;
-// CHECK:      2: A()
-// CHECK:      3: [B1.2].operator int()
-// CHECK:      4: a = [B1.3]
-// CHECK:      5: ~A() (Temporary object destructor)
-// CHECK:      6: int b;
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
-// CHECK: [ B2 (ENTRY) ]
-// CHECK:    Predecessors (0):
-// CHECK:    Successors (1): B1
-// CHECK: [ B1 ]
-// CHECK:      1: A()
-// CHECK:      2: [B1.1].operator int()
-// CHECK:      3: B()
-// CHECK:      4: [B1.3].operator int()
-// CHECK:      5: a(int([B1.2]) + int([B1.4])) (Member initializer)
-// CHECK:      6: ~B() (Temporary object destructor)
-// CHECK:      7: ~A() (Temporary object destructor)
-// CHECK:      8: b(/*implicit*/int()) (Member initializer)
-// CHECK:    Predecessors (1): B2
-// CHECK:    Successors (1): B0
-// CHECK: [ B0 (EXIT) ]
-// CHECK:    Predecessors (1): B1
-// CHECK:    Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1] (BindTemporary)
+// CHECK:       3: [B1.2].operator int
+// CHECK:       4: [B1.3]()
+// CHECK:       5: [B1.4]
+// CHECK:       6: int([B1.5])
+// CHECK:       7: B()
+// CHECK:       8: [B1.7] (BindTemporary)
+// CHECK:       9: [B1.8].operator int
+// CHECK:      10: [B1.9]()
+// CHECK:      11: [B1.10]
+// CHECK:      12: int([B1.11])
+// CHECK:      13: [B1.6] + [B1.12]
+// CHECK:      14: int a = int(A().operator int()) + int(B().operator int());
+// CHECK:      15: ~B() (Temporary object destructor)
+// CHECK:      16: ~A() (Temporary object destructor)
+// CHECK:      17: A()
+// CHECK:      18: [B1.17] (BindTemporary)
+// CHECK:      19: [B1.18].operator int
+// CHECK:      20: [B1.19]()
+// CHECK:      21: [B1.20]
+// CHECK:      22: int([B1.21])
+// CHECK:      23: B()
+// CHECK:      24: [B1.23] (BindTemporary)
+// CHECK:      25: [B1.24].operator int
+// CHECK:      26: [B1.25]()
+// CHECK:      27: [B1.26]
+// CHECK:      28: int([B1.27])
+// CHECK:      29: [B1.22] + [B1.28]
+// CHECK:      30: foo
+// CHECK:      31: [B1.30]
+// CHECK:      32: [B1.31]([B1.29])
+// CHECK:      33: ~B() (Temporary object destructor)
+// CHECK:      34: ~A() (Temporary object destructor)
+// CHECK:      35: int b;
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B10 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B8
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B4.5] && [B5.4]
+// CHECK:       2: foo
+// CHECK:       3: [B3.2]
+// CHECK:       4: [B3.3]([B3.1])
+// CHECK:       T: [B4.5] && ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B2 B1
+// CHECK:  [ B4 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B4.2] (BindTemporary)
+// CHECK:       4: [B4.3].operator _Bool
+// CHECK:       5: [B4.4]()
+// CHECK:       T: [B4.5] && ...
+// CHECK:     Predecessors (2): B6 B7
+// CHECK:     Successors (2): B5 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: B()
+// CHECK:       2: [B5.1] (BindTemporary)
+// CHECK:       3: [B5.2].operator _Bool
+// CHECK:       4: [B5.3]()
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B3
+// CHECK:  [ B6 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B8.4] && [B9.4]
+// CHECK:       2: bool a = A().operator _Bool() && B().operator _Bool();
+// CHECK:       T: [B8.4] && ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B6 B4
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1] (BindTemporary)
+// CHECK:       3: [B8.2].operator _Bool
+// CHECK:       4: [B8.3]()
+// CHECK:       T: [B8.4] && ...
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B9 B7
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1] (BindTemporary)
+// CHECK:       3: [B9.2].operator _Bool
+// CHECK:       4: [B9.3]()
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B7
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B10 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B8
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B4.5] || [B5.4]
+// CHECK:       2: foo
+// CHECK:       3: [B3.2]
+// CHECK:       4: [B3.3]([B3.1])
+// CHECK:       T: [B4.5] || ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B1 B2
+// CHECK:  [ B4 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B4.2] (BindTemporary)
+// CHECK:       4: [B4.3].operator _Bool
+// CHECK:       5: [B4.4]()
+// CHECK:       T: [B4.5] || ...
+// CHECK:     Predecessors (2): B6 B7
+// CHECK:     Successors (2): B3 B5
+// CHECK:  [ B5 ]
+// CHECK:       1: B()
+// CHECK:       2: [B5.1] (BindTemporary)
+// CHECK:       3: [B5.2].operator _Bool
+// CHECK:       4: [B5.3]()
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B3
+// CHECK:  [ B6 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B8.4] || [B9.4]
+// CHECK:       2: bool a = A().operator _Bool() || B().operator _Bool();
+// CHECK:       T: [B8.4] || ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B4 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1] (BindTemporary)
+// CHECK:       3: [B8.2].operator _Bool
+// CHECK:       4: [B8.3]()
+// CHECK:       T: [B8.4] || ...
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B7 B9
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1] (BindTemporary)
+// CHECK:       3: [B9.2].operator _Bool
+// CHECK:       4: [B9.3]()
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B7
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B11 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B10
+// CHECK:  [ B1 ]
+// CHECK:       1: int b;
+// CHECK:       2: [B7.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: 0
+// CHECK:       2: foo
+// CHECK:       3: [B2.2]
+// CHECK:       4: [B2.3]([B2.1])
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: 0
+// CHECK:       2: foo
+// CHECK:       3: [B3.2]
+// CHECK:       4: [B3.3]([B3.1])
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: B()
+// CHECK:       3: [B4.2] (BindTemporary)
+// CHECK:       4: [B4.3].operator _Bool
+// CHECK:       5: [B4.4]()
+// CHECK:       6: ~B() (Temporary object destructor)
+// CHECK:       T: if [B4.5]
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B5 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~A() (Temporary object destructor)
+// CHECK:       4: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B10.4] ? [B8.5] : [B9.13]
+// CHECK:       2: [B7.1]
+// CHECK:       3: [B7.2]
+// CHECK:       4: A a = B().operator _Bool() ? A() : A(B().operator A());
+// CHECK:       T: [B10.4] ? ... : ...
+// CHECK:     Predecessors (2): B8 B9
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1] (BindTemporary)
+// CHECK:       3: [B8.2]
+// CHECK:       4: [B8.3]
+// CHECK:       5: [B8.4] (BindTemporary)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1] (BindTemporary)
+// CHECK:       3: [B9.2].operator A
+// CHECK:       4: [B9.3]()
+// CHECK:       5: [B9.4] (BindTemporary)
+// CHECK:       6: [B9.5]
+// CHECK:       7: [B9.6]
+// CHECK:       8: [B9.7]
+// CHECK:       9: [B9.8] (BindTemporary)
+// CHECK:      10: A([B9.9])
+// CHECK:      11: [B9.10]
+// CHECK:      12: [B9.11]
+// CHECK:      13: [B9.12] (BindTemporary)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B10 ]
+// CHECK:       1: B()
+// CHECK:       2: [B10.1] (BindTemporary)
+// CHECK:       3: [B10.2].operator _Bool
+// CHECK:       4: [B10.3]()
+// CHECK:       T: [B10.4] ? ... : ...
+// CHECK:     Predecessors (1): B11
+// CHECK:     Successors (2): B8 B9
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B14 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B13
+// CHECK:  [ B1 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B10.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~A() (Temporary object destructor)
+// CHECK:       4: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: [B7.5] ? [B5.5] : [B6.13]
+// CHECK:       2: [B4.1]
+// CHECK:       3: [B4.2]
+// CHECK:       4: foo
+// CHECK:       5: [B4.4]
+// CHECK:       6: [B4.5]([B4.3])
+// CHECK:       T: [B7.5] ? ... : ...
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B2 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: A()
+// CHECK:       2: [B5.1] (BindTemporary)
+// CHECK:       3: [B5.2]
+// CHECK:       4: [B5.3]
+// CHECK:       5: [B5.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: B()
+// CHECK:       2: [B6.1] (BindTemporary)
+// CHECK:       3: [B6.2].operator A
+// CHECK:       4: [B6.3]()
+// CHECK:       5: [B6.4] (BindTemporary)
+// CHECK:       6: [B6.5]
+// CHECK:       7: [B6.6]
+// CHECK:       8: [B6.7]
+// CHECK:       9: [B6.8] (BindTemporary)
+// CHECK:      10: A([B6.9])
+// CHECK:      11: [B6.10]
+// CHECK:      12: [B6.11]
+// CHECK:      13: [B6.12] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: B()
+// CHECK:       3: [B7.2] (BindTemporary)
+// CHECK:       4: [B7.3].operator _Bool
+// CHECK:       5: [B7.4]()
+// CHECK:       T: [B7.5] ? ... : ...
+// CHECK:     Predecessors (2): B8 B9
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B10 ]
+// CHECK:       1: [B13.4] ? [B11.5] : [B12.13]
+// CHECK:       2: [B10.1]
+// CHECK:       3: [B10.2]
+// CHECK:       4: const A &a = B().operator _Bool() ? A() : A(B().operator A());
+// CHECK:       T: [B13.4] ? ... : ...
+// CHECK:     Predecessors (2): B11 B12
+// CHECK:     Successors (2): B8 B9
+// CHECK:  [ B11 ]
+// CHECK:       1: A()
+// CHECK:       2: [B11.1] (BindTemporary)
+// CHECK:       3: [B11.2]
+// CHECK:       4: [B11.3]
+// CHECK:       5: [B11.4] (BindTemporary)
+// CHECK:     Predecessors (1): B13
+// CHECK:     Successors (1): B10
+// CHECK:  [ B12 ]
+// CHECK:       1: B()
+// CHECK:       2: [B12.1] (BindTemporary)
+// CHECK:       3: [B12.2].operator A
+// CHECK:       4: [B12.3]()
+// CHECK:       5: [B12.4] (BindTemporary)
+// CHECK:       6: [B12.5]
+// CHECK:       7: [B12.6]
+// CHECK:       8: [B12.7]
+// CHECK:       9: [B12.8] (BindTemporary)
+// CHECK:      10: A([B12.9])
+// CHECK:      11: [B12.10]
+// CHECK:      12: [B12.11]
+// CHECK:      13: [B12.12] (BindTemporary)
+// CHECK:     Predecessors (1): B13
+// CHECK:     Successors (1): B10
+// CHECK:  [ B13 ]
+// CHECK:       1: B()
+// CHECK:       2: [B13.1] (BindTemporary)
+// CHECK:       3: [B13.2].operator _Bool
+// CHECK:       4: [B13.3]()
+// CHECK:       T: [B13.4] ? ... : ...
+// CHECK:     Predecessors (1): B14
+// CHECK:     Successors (2): B11 B12
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B8 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B7
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B4.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: [B7.2] ?: [B6.5]
+// CHECK:       2: [B4.1]
+// CHECK:       3: [B4.2]
+// CHECK:       4: A a = A() ?: A();
+// CHECK:       T: [B7.5] ? ... : ...
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B2 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: [B7.3]
+// CHECK:       2: [B7.3]
+// CHECK:       3: [B5.2]
+// CHECK:       4: [B5.3]
+// CHECK:       5: [B5.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: A()
+// CHECK:       2: [B6.1] (BindTemporary)
+// CHECK:       3: [B6.2]
+// CHECK:       4: [B6.3]
+// CHECK:       5: [B6.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: A()
+// CHECK:       2: [B7.1] (BindTemporary)
+// CHECK:       3: 
+// CHECK:       4: [B7.3].operator _Bool
+// CHECK:       5: [B7.4]()
+// CHECK:       T: [B7.5] ? ... : ...
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B13 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B12
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B9.4].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: [B7.3] ?: [B6.5]
+// CHECK:       2: [B4.1]
+// CHECK:       3: [B4.2]
+// CHECK:       4: foo
+// CHECK:       5: [B4.4]
+// CHECK:       6: [B4.5]([B4.3])
+// CHECK:       T: [B7.6] ? ... : ...
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B2 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: [B7.4]
+// CHECK:       2: [B7.4]
+// CHECK:       3: [B5.2]
+// CHECK:       4: [B5.3]
+// CHECK:       5: [B5.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: A()
+// CHECK:       2: [B6.1] (BindTemporary)
+// CHECK:       3: [B6.2]
+// CHECK:       4: [B6.3]
+// CHECK:       5: [B6.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B7.2] (BindTemporary)
+// CHECK:       4: 
+// CHECK:       5: [B7.4].operator _Bool
+// CHECK:       6: [B7.5]()
+// CHECK:       T: [B7.6] ? ... : ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: [B12.2] ?: [B11.5]
+// CHECK:       2: [B9.1]
+// CHECK:       3: [B9.2]
+// CHECK:       4: const A &a = A() ?: A();
+// CHECK:       T: [B12.5] ? ... : ...
+// CHECK:     Predecessors (2): B10 B11
+// CHECK:     Successors (2): B7 B8
+// CHECK:  [ B10 ]
+// CHECK:       1: [B12.3]
+// CHECK:       2: [B12.3]
+// CHECK:       3: [B10.2]
+// CHECK:       4: [B10.3]
+// CHECK:       5: [B10.4] (BindTemporary)
+// CHECK:     Predecessors (1): B12
+// CHECK:     Successors (1): B9
+// CHECK:  [ B11 ]
+// CHECK:       1: A()
+// CHECK:       2: [B11.1] (BindTemporary)
+// CHECK:       3: [B11.2]
+// CHECK:       4: [B11.3]
+// CHECK:       5: [B11.4] (BindTemporary)
+// CHECK:     Predecessors (1): B12
+// CHECK:     Successors (1): B9
+// CHECK:  [ B12 ]
+// CHECK:       1: A()
+// CHECK:       2: [B12.1] (BindTemporary)
+// CHECK:       3: 
+// CHECK:       4: [B12.3].operator _Bool
+// CHECK:       5: [B12.4]()
+// CHECK:       T: [B12.5] ? ... : ...
+// CHECK:     Predecessors (1): B13
+// CHECK:     Successors (2): B10 B11
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1] (BindTemporary)
+// CHECK:       3: [B1.2]
+// CHECK:       4: [B1.3]
+// CHECK:       5: A a = A();
+// CHECK:       6: ~A() (Temporary object destructor)
+// CHECK:       7: int b;
+// CHECK:       8: [B1.5].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1] (BindTemporary)
+// CHECK:       3: [B1.2]
+// CHECK:       4: [B1.3]
+// CHECK:       5: const A &a = A();
+// CHECK:       6: A()
+// CHECK:       7: [B1.6] (BindTemporary)
+// CHECK:       8: [B1.7]
+// CHECK:       9: [B1.8]
+// CHECK:      10: foo
+// CHECK:      11: [B1.10]
+// CHECK:      12: [B1.11]([B1.9])
+// CHECK:      13: ~A() (Temporary object destructor)
+// CHECK:      14: int b;
+// CHECK:      15: [B1.5].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A::make
+// CHECK:       2: [B1.1]
+// CHECK:       3: [B1.2]()
+// CHECK:       4: [B1.3] (BindTemporary)
+// CHECK:       5: [B1.4]
+// CHECK:       6: [B1.5]
+// CHECK:       7: A a = A::make();
+// CHECK:       8: ~A() (Temporary object destructor)
+// CHECK:       9: int b;
+// CHECK:      10: [B1.7].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A::make
+// CHECK:       2: [B1.1]
+// CHECK:       3: [B1.2]()
+// CHECK:       4: [B1.3] (BindTemporary)
+// CHECK:       5: [B1.4]
+// CHECK:       6: [B1.5]
+// CHECK:       7: const A &a = A::make();
+// CHECK:       8: A::make
+// CHECK:       9: [B1.8]
+// CHECK:      10: [B1.9]()
+// CHECK:      11: [B1.10] (BindTemporary)
+// CHECK:      12: [B1.11]
+// CHECK:      13: [B1.12]
+// CHECK:      14: foo
+// CHECK:      15: [B1.14]
+// CHECK:      16: [B1.15]([B1.13])
+// CHECK:      17: ~A() (Temporary object destructor)
+// CHECK:      18: int b;
+// CHECK:      19: [B1.7].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: int a;
+// CHECK:       2: A()
+// CHECK:       3: [B1.2] (BindTemporary)
+// CHECK:       4: [B1.3].operator int
+// CHECK:       5: [B1.4]()
+// CHECK:       6: a
+// CHECK:       7: [B1.6] = [B1.5]
+// CHECK:       8: ~A() (Temporary object destructor)
+// CHECK:       9: int b;
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1] (BindTemporary)
+// CHECK:       3: [B1.2].operator int
+// CHECK:       4: [B1.3]()
+// CHECK:       5: [B1.4]
+// CHECK:       6: int([B1.5])
+// CHECK:       7: B()
+// CHECK:       8: [B1.7] (BindTemporary)
+// CHECK:       9: [B1.8].operator int
+// CHECK:      10: [B1.9]()
+// CHECK:      11: [B1.10]
+// CHECK:      12: int([B1.11])
+// CHECK:      13: [B1.6] + [B1.12]
+// CHECK:      14: a([B1.13]) (Member initializer)
+// CHECK:      15: ~B() (Temporary object destructor)
+// CHECK:      16: ~A() (Temporary object destructor)
+// CHECK:      17: /*implicit*/int()
+// CHECK:      18: b([B1.17]) (Member initializer)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+