LiveVariables.cpp revision 87aa1250a90af9d92ad9d6b7b65610a45bf478c1
1#include "clang/Analysis/Analyses/LiveVariables.h"
2#include "clang/AST/Stmt.h"
3#include "clang/Analysis/CFG.h"
4#include "clang/Analysis/AnalysisContext.h"
5#include "clang/AST/StmtVisitor.h"
6
7#include "llvm/ADT/PostOrderIterator.h"
8#include "llvm/ADT/DenseMap.h"
9
10#include <deque>
11#include <algorithm>
12#include <vector>
13
14using namespace clang;
15
16namespace {
17
18// FIXME: This is copy-pasted from ThreadSafety.c.  I wanted a patch that
19// contained working code before refactoring the implementation of both
20// files.
21class CFGBlockSet {
22  llvm::BitVector VisitedBlockIDs;
23
24public:
25  // po_iterator requires this iterator, but the only interface needed is the
26  // value_type typedef.
27  struct iterator {
28    typedef const CFGBlock *value_type;
29  };
30
31  CFGBlockSet() {}
32  CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
33
34  /// \brief Set the bit associated with a particular CFGBlock.
35  /// This is the important method for the SetType template parameter.
36  bool insert(const CFGBlock *Block) {
37    // Note that insert() is called by po_iterator, which doesn't check to make
38    // sure that Block is non-null.  Moreover, the CFGBlock iterator will
39    // occasionally hand out null pointers for pruned edges, so we catch those
40    // here.
41    if (Block == 0)
42      return false;  // if an edge is trivially false.
43    if (VisitedBlockIDs.test(Block->getBlockID()))
44      return false;
45    VisitedBlockIDs.set(Block->getBlockID());
46    return true;
47  }
48
49  /// \brief Check if the bit for a CFGBlock has been already set.
50  /// This method is for tracking visited blocks in the main threadsafety loop.
51  /// Block must not be null.
52  bool alreadySet(const CFGBlock *Block) {
53    return VisitedBlockIDs.test(Block->getBlockID());
54  }
55};
56
57/// \brief We create a helper class which we use to iterate through CFGBlocks in
58/// the topological order.
59class TopologicallySortedCFG {
60  typedef llvm::po_iterator<const CFG*, CFGBlockSet, true>  po_iterator;
61
62  std::vector<const CFGBlock*> Blocks;
63
64  typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
65  BlockOrderTy BlockOrder;
66
67
68public:
69  typedef std::vector<const CFGBlock*>::reverse_iterator iterator;
70
71  TopologicallySortedCFG(const CFG *CFGraph) {
72    Blocks.reserve(CFGraph->getNumBlockIDs());
73    CFGBlockSet BSet(CFGraph);
74
75    for (po_iterator I = po_iterator::begin(CFGraph, BSet),
76         E = po_iterator::end(CFGraph, BSet); I != E; ++I) {
77      BlockOrder[*I] = Blocks.size() + 1;
78      Blocks.push_back(*I);
79    }
80  }
81
82  iterator begin() {
83    return Blocks.rbegin();
84  }
85
86  iterator end() {
87    return Blocks.rend();
88  }
89
90  bool empty() {
91    return begin() == end();
92  }
93
94  struct BlockOrderCompare;
95  friend struct BlockOrderCompare;
96
97  struct BlockOrderCompare {
98    const TopologicallySortedCFG &TSC;
99  public:
100    BlockOrderCompare(const TopologicallySortedCFG &tsc) : TSC(tsc) {}
101
102    bool operator()(const CFGBlock *b1, const CFGBlock *b2) const {
103      TopologicallySortedCFG::BlockOrderTy::const_iterator b1It = TSC.BlockOrder.find(b1);
104      TopologicallySortedCFG::BlockOrderTy::const_iterator b2It = TSC.BlockOrder.find(b2);
105
106      unsigned b1V = (b1It == TSC.BlockOrder.end()) ? 0 : b1It->second;
107      unsigned b2V = (b2It == TSC.BlockOrder.end()) ? 0 : b2It->second;
108      return b1V > b2V;
109    }
110  };
111
112  BlockOrderCompare getComparator() const {
113    return BlockOrderCompare(*this);
114  }
115};
116
117class DataflowWorklist {
118  SmallVector<const CFGBlock *, 20> worklist;
119  llvm::BitVector enqueuedBlocks;
120  TopologicallySortedCFG TSC;
121public:
122  DataflowWorklist(const CFG &cfg)
123    : enqueuedBlocks(cfg.getNumBlockIDs()),
124      TSC(&cfg) {}
125
126  void enqueueBlock(const CFGBlock *block);
127  void enqueueSuccessors(const CFGBlock *block);
128  void enqueuePredecessors(const CFGBlock *block);
129
130  const CFGBlock *dequeue();
131
132  void sortWorklist();
133};
134
135}
136
137void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
138  if (block && !enqueuedBlocks[block->getBlockID()]) {
139    enqueuedBlocks[block->getBlockID()] = true;
140    worklist.push_back(block);
141  }
142}
143
144void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
145  const unsigned OldWorklistSize = worklist.size();
146  for (CFGBlock::const_succ_iterator I = block->succ_begin(),
147       E = block->succ_end(); I != E; ++I) {
148    enqueueBlock(*I);
149  }
150
151  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
152    return;
153
154  sortWorklist();
155}
156
157void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
158  const unsigned OldWorklistSize = worklist.size();
159  for (CFGBlock::const_pred_iterator I = block->pred_begin(),
160       E = block->pred_end(); I != E; ++I) {
161    enqueueBlock(*I);
162  }
163
164  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
165    return;
166
167  sortWorklist();
168}
169
170void DataflowWorklist::sortWorklist() {
171  std::sort(worklist.begin(), worklist.end(), TSC.getComparator());
172}
173
174
175const CFGBlock *DataflowWorklist::dequeue() {
176  if (worklist.empty())
177    return 0;
178  const CFGBlock *b = worklist.back();
179  worklist.pop_back();
180  enqueuedBlocks[b->getBlockID()] = false;
181  return b;
182}
183
184namespace {
185class LiveVariablesImpl {
186public:
187  AnalysisContext &analysisContext;
188  std::vector<LiveVariables::LivenessValues> cfgBlockValues;
189  llvm::ImmutableSet<const Stmt *>::Factory SSetFact;
190  llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
191  llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
192  llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
193  llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
194  llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
195  const bool killAtAssign;
196
197  LiveVariables::LivenessValues
198  merge(LiveVariables::LivenessValues valsA,
199        LiveVariables::LivenessValues valsB);
200
201  LiveVariables::LivenessValues runOnBlock(const CFGBlock *block,
202                                           LiveVariables::LivenessValues val,
203                                           LiveVariables::Observer *obs = 0);
204
205  void dumpBlockLiveness(const SourceManager& M);
206
207  LiveVariablesImpl(AnalysisContext &ac, bool KillAtAssign)
208    : analysisContext(ac), killAtAssign(KillAtAssign) {}
209};
210}
211
212static LiveVariablesImpl &getImpl(void *x) {
213  return *((LiveVariablesImpl *) x);
214}
215
216//===----------------------------------------------------------------------===//
217// Operations and queries on LivenessValues.
218//===----------------------------------------------------------------------===//
219
220bool LiveVariables::LivenessValues::isLive(const Stmt *S) const {
221  return liveStmts.contains(S);
222}
223
224bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
225  return liveDecls.contains(D);
226}
227
228namespace {
229  template <typename SET>
230  SET mergeSets(SET A, SET B) {
231    if (A.isEmpty())
232      return B;
233
234    for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
235      A = A.add(*it);
236    }
237    return A;
238  }
239}
240
241LiveVariables::LivenessValues
242LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
243                         LiveVariables::LivenessValues valsB) {
244
245  llvm::ImmutableSetRef<const Stmt *>
246    SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
247    SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
248
249
250  llvm::ImmutableSetRef<const VarDecl *>
251    DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
252    DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
253
254
255  SSetRefA = mergeSets(SSetRefA, SSetRefB);
256  DSetRefA = mergeSets(DSetRefA, DSetRefB);
257
258  return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
259                                       DSetRefA.asImmutableSet());
260}
261
262bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
263  return liveStmts == V.liveStmts && liveDecls == V.liveDecls;
264}
265
266//===----------------------------------------------------------------------===//
267// Query methods.
268//===----------------------------------------------------------------------===//
269
270static bool isAlwaysAlive(const VarDecl *D) {
271  return D->hasGlobalStorage();
272}
273
274bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
275  return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
276}
277
278bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
279  return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
280}
281
282bool LiveVariables::isLive(const Stmt *Loc, const Stmt *S) {
283  return getImpl(impl).stmtsToLiveness[Loc].isLive(S);
284}
285
286//===----------------------------------------------------------------------===//
287// Dataflow computation.
288//===----------------------------------------------------------------------===//
289
290namespace {
291class TransferFunctions : public StmtVisitor<TransferFunctions> {
292  LiveVariablesImpl &LV;
293  LiveVariables::LivenessValues &val;
294  LiveVariables::Observer *observer;
295  const CFGBlock *currentBlock;
296public:
297  TransferFunctions(LiveVariablesImpl &im,
298                    LiveVariables::LivenessValues &Val,
299                    LiveVariables::Observer *Observer,
300                    const CFGBlock *CurrentBlock)
301  : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
302
303  void VisitBinaryOperator(BinaryOperator *BO);
304  void VisitBlockExpr(BlockExpr *BE);
305  void VisitDeclRefExpr(DeclRefExpr *DR);
306  void VisitDeclStmt(DeclStmt *DS);
307  void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
308  void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
309  void VisitUnaryOperator(UnaryOperator *UO);
310  void Visit(Stmt *S);
311};
312}
313
314static const VariableArrayType *FindVA(QualType Ty) {
315  const Type *ty = Ty.getTypePtr();
316  while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
317    if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
318      if (VAT->getSizeExpr())
319        return VAT;
320
321    ty = VT->getElementType().getTypePtr();
322  }
323
324  return 0;
325}
326
327void TransferFunctions::Visit(Stmt *S) {
328  if (observer)
329    observer->observeStmt(S, currentBlock, val);
330
331  StmtVisitor<TransferFunctions>::Visit(S);
332
333  if (isa<Expr>(S)) {
334    val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
335  }
336
337  // Mark all children expressions live.
338
339  switch (S->getStmtClass()) {
340    default:
341      break;
342    case Stmt::StmtExprClass: {
343      // For statement expressions, look through the compound statement.
344      S = cast<StmtExpr>(S)->getSubStmt();
345      break;
346    }
347    case Stmt::CXXMemberCallExprClass: {
348      // Include the implicit "this" pointer as being live.
349      CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
350      val.liveStmts =
351        LV.SSetFact.add(val.liveStmts,
352                        CE->getImplicitObjectArgument()->IgnoreParens());
353      break;
354    }
355    case Stmt::DeclStmtClass: {
356      const DeclStmt *DS = cast<DeclStmt>(S);
357      if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
358        for (const VariableArrayType* VA = FindVA(VD->getType());
359             VA != 0; VA = FindVA(VA->getElementType())) {
360          val.liveStmts = LV.SSetFact.add(val.liveStmts,
361                                          VA->getSizeExpr()->IgnoreParens());
362        }
363      }
364      break;
365    }
366    // FIXME: These cases eventually shouldn't be needed.
367    case Stmt::ExprWithCleanupsClass: {
368      S = cast<ExprWithCleanups>(S)->getSubExpr();
369      break;
370    }
371    case Stmt::CXXBindTemporaryExprClass: {
372      S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
373      break;
374    }
375    case Stmt::MaterializeTemporaryExprClass: {
376      S = cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr();
377      break;
378    }
379    case Stmt::UnaryExprOrTypeTraitExprClass: {
380      // No need to unconditionally visit subexpressions.
381      return;
382    }
383  }
384
385  for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end();
386       it != ei; ++it) {
387    if (Stmt *child = *it) {
388      if (Expr *Ex = dyn_cast<Expr>(child))
389        child = Ex->IgnoreParens();
390
391      val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
392    }
393  }
394}
395
396void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
397  if (B->isAssignmentOp()) {
398    if (!LV.killAtAssign)
399      return;
400
401    // Assigning to a variable?
402    Expr *LHS = B->getLHS()->IgnoreParens();
403
404    if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS))
405      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
406        // Assignments to references don't kill the ref's address
407        if (VD->getType()->isReferenceType())
408          return;
409
410        if (!isAlwaysAlive(VD)) {
411          // The variable is now dead.
412          val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
413        }
414
415        if (observer)
416          observer->observerKill(DR);
417      }
418  }
419}
420
421void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
422  AnalysisContext::referenced_decls_iterator I, E;
423  llvm::tie(I, E) =
424    LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
425  for ( ; I != E ; ++I) {
426    const VarDecl *VD = *I;
427    if (isAlwaysAlive(VD))
428      continue;
429    val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
430  }
431}
432
433void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
434  if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
435    if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
436      val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
437}
438
439void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
440  for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE = DS->decl_end();
441       DI != DE; ++DI)
442    if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) {
443      if (!isAlwaysAlive(VD))
444        val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
445    }
446}
447
448void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
449  // Kill the iteration variable.
450  DeclRefExpr *DR = 0;
451  const VarDecl *VD = 0;
452
453  Stmt *element = OS->getElement();
454  if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
455    VD = cast<VarDecl>(DS->getSingleDecl());
456  }
457  else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
458    VD = cast<VarDecl>(DR->getDecl());
459  }
460
461  if (VD) {
462    val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
463    if (observer && DR)
464      observer->observerKill(DR);
465  }
466}
467
468void TransferFunctions::
469VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
470{
471  // While sizeof(var) doesn't technically extend the liveness of 'var', it
472  // does extent the liveness of metadata if 'var' is a VariableArrayType.
473  // We handle that special case here.
474  if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
475    return;
476
477  const Expr *subEx = UE->getArgumentExpr();
478  if (subEx->getType()->isVariableArrayType()) {
479    assert(subEx->isLValue());
480    val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->IgnoreParens());
481  }
482}
483
484void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
485  // Treat ++/-- as a kill.
486  // Note we don't actually have to do anything if we don't have an observer,
487  // since a ++/-- acts as both a kill and a "use".
488  if (!observer)
489    return;
490
491  switch (UO->getOpcode()) {
492  default:
493    return;
494  case UO_PostInc:
495  case UO_PostDec:
496  case UO_PreInc:
497  case UO_PreDec:
498    break;
499  }
500
501  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens()))
502    if (isa<VarDecl>(DR->getDecl())) {
503      // Treat ++/-- as a kill.
504      observer->observerKill(DR);
505    }
506}
507
508LiveVariables::LivenessValues
509LiveVariablesImpl::runOnBlock(const CFGBlock *block,
510                              LiveVariables::LivenessValues val,
511                              LiveVariables::Observer *obs) {
512
513  TransferFunctions TF(*this, val, obs, block);
514
515  // Visit the terminator (if any).
516  if (const Stmt *term = block->getTerminator())
517    TF.Visit(const_cast<Stmt*>(term));
518
519  // Apply the transfer function for all Stmts in the block.
520  for (CFGBlock::const_reverse_iterator it = block->rbegin(),
521       ei = block->rend(); it != ei; ++it) {
522    const CFGElement &elem = *it;
523    if (!isa<CFGStmt>(elem))
524      continue;
525
526    const Stmt *S = cast<CFGStmt>(elem).getStmt();
527    TF.Visit(const_cast<Stmt*>(S));
528    stmtsToLiveness[S] = val;
529  }
530  return val;
531}
532
533void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
534  const CFG *cfg = getImpl(impl).analysisContext.getCFG();
535  for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
536    getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
537}
538
539LiveVariables::LiveVariables(void *im) : impl(im) {}
540
541LiveVariables::~LiveVariables() {
542  delete (LiveVariablesImpl*) impl;
543}
544
545LiveVariables *
546LiveVariables::computeLiveness(AnalysisContext &AC,
547                                 bool killAtAssign) {
548
549  // No CFG?  Bail out.
550  CFG *cfg = AC.getCFG();
551  if (!cfg)
552    return 0;
553
554  LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
555
556  // Construct the dataflow worklist.  Enqueue the exit block as the
557  // start of the analysis.
558  DataflowWorklist worklist(*cfg);
559  llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
560
561  // FIXME: we should enqueue using post order.
562  for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
563    const CFGBlock *block = *it;
564    worklist.enqueueBlock(block);
565
566    // FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
567    // We need to do this because we lack context in the reverse analysis
568    // to determine if a DeclRefExpr appears in such a context, and thus
569    // doesn't constitute a "use".
570    if (killAtAssign)
571      for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
572           bi != be; ++bi) {
573        if (const CFGStmt *cs = bi->getAs<CFGStmt>()) {
574          if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(cs->getStmt())) {
575            if (BO->getOpcode() == BO_Assign) {
576              if (const DeclRefExpr *DR =
577                    dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
578                LV->inAssignment[DR] = 1;
579              }
580            }
581          }
582        }
583      }
584  }
585
586  worklist.sortWorklist();
587
588  while (const CFGBlock *block = worklist.dequeue()) {
589    // Determine if the block's end value has changed.  If not, we
590    // have nothing left to do for this block.
591    LivenessValues &prevVal = LV->blocksEndToLiveness[block];
592
593    // Merge the values of all successor blocks.
594    LivenessValues val;
595    for (CFGBlock::const_succ_iterator it = block->succ_begin(),
596                                       ei = block->succ_end(); it != ei; ++it) {
597      if (const CFGBlock *succ = *it) {
598        val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
599      }
600    }
601
602    if (!everAnalyzedBlock[block->getBlockID()])
603      everAnalyzedBlock[block->getBlockID()] = true;
604    else if (prevVal.equals(val))
605      continue;
606
607    prevVal = val;
608
609    // Update the dataflow value for the start of this block.
610    LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
611
612    // Enqueue the value to the predecessors.
613    worklist.enqueuePredecessors(block);
614  }
615
616  return new LiveVariables(LV);
617}
618
619static bool compare_entries(const CFGBlock *A, const CFGBlock *B) {
620  return A->getBlockID() < B->getBlockID();
621}
622
623static bool compare_vd_entries(const Decl *A, const Decl *B) {
624  SourceLocation ALoc = A->getLocStart();
625  SourceLocation BLoc = B->getLocStart();
626  return ALoc.getRawEncoding() < BLoc.getRawEncoding();
627}
628
629void LiveVariables::dumpBlockLiveness(const SourceManager &M) {
630  getImpl(impl).dumpBlockLiveness(M);
631}
632
633void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
634  std::vector<const CFGBlock *> vec;
635  for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
636       it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
637       it != ei; ++it) {
638    vec.push_back(it->first);
639  }
640  std::sort(vec.begin(), vec.end(), compare_entries);
641
642  std::vector<const VarDecl*> declVec;
643
644  for (std::vector<const CFGBlock *>::iterator
645        it = vec.begin(), ei = vec.end(); it != ei; ++it) {
646    llvm::errs() << "\n[ B" << (*it)->getBlockID()
647                 << " (live variables at block exit) ]\n";
648
649    LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
650    declVec.clear();
651
652    for (llvm::ImmutableSet<const VarDecl *>::iterator si =
653          vals.liveDecls.begin(),
654          se = vals.liveDecls.end(); si != se; ++si) {
655      declVec.push_back(*si);
656    }
657
658    std::sort(declVec.begin(), declVec.end(), compare_vd_entries);
659
660    for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
661         de = declVec.end(); di != de; ++di) {
662      llvm::errs() << " " << (*di)->getDeclName().getAsString()
663                   << " <";
664      (*di)->getLocation().dump(M);
665      llvm::errs() << ">\n";
666    }
667  }
668  llvm::errs() << "\n";
669}
670
671