]> granicus.if.org Git - clang/blob - include/clang/Analysis/CFG.h
Add skeleton for handling other kinds of CFGElements.
[clang] / include / clang / Analysis / CFG.h
1 //===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the CFG and CFGBuilder classes for representing and
11 //  building Control-Flow Graphs (CFGs) from ASTs.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_CFG_H
16 #define LLVM_CLANG_CFG_H
17
18 #include "llvm/ADT/PointerIntPair.h"
19 #include "llvm/ADT/GraphTraits.h"
20 #include "llvm/Support/Allocator.h"
21 #include "llvm/Support/Casting.h"
22 #include "clang/Analysis/Support/BumpVector.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include <cassert>
25
26 namespace llvm {
27   class raw_ostream;
28 }
29
30 namespace clang {
31   class Decl;
32   class Stmt;
33   class Expr;
34   class FieldDecl;
35   class VarDecl;
36   class CXXBaseOrMemberInitializer;
37   class CXXBaseSpecifier;
38   class CXXBindTemporaryExpr;
39   class CFG;
40   class PrinterHelper;
41   class LangOptions;
42   class ASTContext;
43
44 /// CFGElement - Represents a top-level expression in a basic block.
45 class CFGElement {
46 public:
47   enum Kind {
48     // main kind
49     Statement,
50     StatementAsLValue,
51     Initializer,
52     ImplicitDtor,
53     // dtor kind
54     AutomaticObjectDtor,
55     BaseDtor,
56     MemberDtor,
57     TemporaryDtor,
58     DTOR_BEGIN = AutomaticObjectDtor
59   };
60
61 protected:
62   // The int bits are used to mark the main kind.
63   llvm::PointerIntPair<void *, 2> Data1;
64   // The int bits are used to mark the dtor kind.
65   llvm::PointerIntPair<void *, 2> Data2;
66
67   CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
68   CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2)
69       : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {}
70
71 public:
72   CFGElement() {}
73
74   Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
75
76   Kind getDtorKind() const {
77     assert(getKind() == ImplicitDtor);
78     return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN);
79   }
80
81   bool isValid() const { return Data1.getPointer(); }
82
83   operator bool() const { return isValid(); }
84
85   template<class ElemTy> ElemTy getAs() const {
86     if (llvm::isa<ElemTy>(this))
87       return *static_cast<const ElemTy*>(this);
88     return ElemTy();
89   }
90
91   static bool classof(const CFGElement *E) { return true; }
92 };
93
94 class CFGStmt : public CFGElement {
95 public:
96   CFGStmt() {}
97   CFGStmt(Stmt *S, bool asLValue) : CFGElement(S, asLValue) {}
98
99   Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
100
101   operator Stmt*() const { return getStmt(); }
102
103   bool asLValue() const { 
104     return static_cast<Kind>(Data1.getInt()) == StatementAsLValue;
105   }
106
107   static bool classof(const CFGElement *E) {
108     return E->getKind() == Statement || E->getKind() == StatementAsLValue;
109   }
110 };
111
112 /// CFGInitializer - Represents C++ base or member initializer from
113 /// constructor's initialization list.
114 class CFGInitializer : public CFGElement {
115 public:
116   CFGInitializer() {}
117   CFGInitializer(CXXBaseOrMemberInitializer* I)
118       : CFGElement(I, Initializer) {}
119
120   CXXBaseOrMemberInitializer* getInitializer() const {
121     return static_cast<CXXBaseOrMemberInitializer*>(Data1.getPointer());
122   }
123   operator CXXBaseOrMemberInitializer*() const { return getInitializer(); }
124
125   static bool classof(const CFGElement *E) {
126     return E->getKind() == Initializer;
127   }
128 };
129
130 /// CFGImplicitDtor - Represents C++ object destructor implicitly generated
131 /// by compiler on various occasions.
132 class CFGImplicitDtor : public CFGElement {
133 protected:
134   CFGImplicitDtor(unsigned K, void* P, void* S)
135       : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {}
136
137 public:
138   CFGImplicitDtor() {}
139
140   static bool classof(const CFGElement *E) {
141     return E->getKind() == ImplicitDtor;
142   }
143 };
144
145 /// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
146 /// for automatic object or temporary bound to const reference at the point
147 /// of leaving its local scope.
148 class CFGAutomaticObjDtor: public CFGImplicitDtor {
149 public:
150   CFGAutomaticObjDtor() {}
151   CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
152       : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
153
154   VarDecl* getVarDecl() const {
155     return static_cast<VarDecl*>(Data1.getPointer());
156   }
157
158   // Get statement end of which triggered the destructor call.
159   Stmt* getTriggerStmt() const {
160     return static_cast<Stmt*>(Data2.getPointer());
161   }
162
163   static bool classof(const CFGElement *E) {
164     return E->getKind() == ImplicitDtor && 
165            E->getDtorKind() == AutomaticObjectDtor;
166   }
167 };
168
169 /// CFGBaseDtor - Represents C++ object destructor implicitly generated for
170 /// base object in destructor.
171 class CFGBaseDtor : public CFGImplicitDtor {
172 public:
173   CFGBaseDtor() {}
174   CFGBaseDtor(const CXXBaseSpecifier *BS)
175       : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
176
177   const CXXBaseSpecifier *getBaseSpecifier() const {
178     return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
179   }
180
181   static bool classof(const CFGElement *E) {
182     return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor;
183   }
184 };
185
186 /// CFGMemberDtor - Represents C++ object destructor implicitly generated for
187 /// member object in destructor.
188 class CFGMemberDtor : public CFGImplicitDtor {
189 public:
190   CFGMemberDtor() {}
191   CFGMemberDtor(FieldDecl *FD)
192       : CFGImplicitDtor(MemberDtor, FD, NULL) {}
193
194   FieldDecl *getFieldDecl() const {
195     return static_cast<FieldDecl*>(Data1.getPointer());
196   }
197
198   static bool classof(const CFGElement *E) {
199     return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor;
200   }
201 };
202
203 /// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
204 /// at the end of full expression for temporary object.
205 class CFGTemporaryDtor : public CFGImplicitDtor {
206 public:
207   CFGTemporaryDtor() {}
208   CFGTemporaryDtor(CXXBindTemporaryExpr *E)
209       : CFGImplicitDtor(TemporaryDtor, E, NULL) {}
210
211   CXXBindTemporaryExpr *getBindTemporaryExpr() const {
212     return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer());
213   }
214
215   static bool classof(const CFGElement *E) {
216     return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor;
217   }
218 };
219
220 /// CFGTerminator - Represents CFGBlock terminator statement.
221 ///
222 /// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
223 /// in control flow of destructors of temporaries. In this case terminator
224 /// statement is the same statement that branches control flow in evaluation
225 /// of matching full expression.
226 class CFGTerminator {
227   llvm::PointerIntPair<Stmt *, 1> Data;
228 public:
229   CFGTerminator() {}
230   CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
231       : Data(S, TemporaryDtorsBranch) {}
232
233   Stmt *getStmt() { return Data.getPointer(); }
234   const Stmt *getStmt() const { return Data.getPointer(); }
235
236   bool isTemporaryDtorsBranch() const { return Data.getInt(); }
237
238   operator Stmt *() { return getStmt(); }
239   operator const Stmt *() const { return getStmt(); }
240
241   Stmt *operator->() { return getStmt(); }
242   const Stmt *operator->() const { return getStmt(); }
243
244   Stmt &operator*() { return *getStmt(); }
245   const Stmt &operator*() const { return *getStmt(); }
246
247   operator bool() const { return getStmt(); }
248 };
249
250 /// CFGBlock - Represents a single basic block in a source-level CFG.
251 ///  It consists of:
252 ///
253 ///  (1) A set of statements/expressions (which may contain subexpressions).
254 ///  (2) A "terminator" statement (not in the set of statements).
255 ///  (3) A list of successors and predecessors.
256 ///
257 /// Terminator: The terminator represents the type of control-flow that occurs
258 /// at the end of the basic block.  The terminator is a Stmt* referring to an
259 /// AST node that has control-flow: if-statements, breaks, loops, etc.
260 /// If the control-flow is conditional, the condition expression will appear
261 /// within the set of statements in the block (usually the last statement).
262 ///
263 /// Predecessors: the order in the set of predecessors is arbitrary.
264 ///
265 /// Successors: the order in the set of successors is NOT arbitrary.  We
266 ///  currently have the following orderings based on the terminator:
267 ///
268 ///     Terminator       Successor Ordering
269 ///  -----------------------------------------------------
270 ///       if            Then Block;  Else Block
271 ///     ? operator      LHS expression;  RHS expression
272 ///     &&, ||          expression that uses result of && or ||, RHS
273 ///
274 class CFGBlock {
275   class ElementList {
276     typedef BumpVector<CFGElement> ImplTy;
277     ImplTy Impl;
278   public:
279     ElementList(BumpVectorContext &C) : Impl(C, 4) {}
280     
281     typedef std::reverse_iterator<ImplTy::iterator>       iterator;
282     typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
283     typedef ImplTy::iterator                              reverse_iterator;
284     typedef ImplTy::const_iterator                        const_reverse_iterator;
285   
286     void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
287     reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
288         BumpVectorContext& C) {
289       return Impl.insert(I, Cnt, E, C);
290     }
291
292     CFGElement front() const { return Impl.back(); }
293     CFGElement back() const { return Impl.front(); }
294     
295     iterator begin() { return Impl.rbegin(); }
296     iterator end() { return Impl.rend(); }
297     const_iterator begin() const { return Impl.rbegin(); }
298     const_iterator end() const { return Impl.rend(); }
299     reverse_iterator rbegin() { return Impl.begin(); }
300     reverse_iterator rend() { return Impl.end(); }
301     const_reverse_iterator rbegin() const { return Impl.begin(); }
302     const_reverse_iterator rend() const { return Impl.end(); }
303
304    CFGElement operator[](size_t i) const  {
305      assert(i < Impl.size());
306      return Impl[Impl.size() - 1 - i];
307    }
308     
309     size_t size() const { return Impl.size(); }
310     bool empty() const { return Impl.empty(); }
311   };
312
313   /// Stmts - The set of statements in the basic block.
314   ElementList Elements;
315
316   /// Label - An (optional) label that prefixes the executable
317   ///  statements in the block.  When this variable is non-NULL, it is
318   ///  either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
319   Stmt *Label;
320
321   /// Terminator - The terminator for a basic block that
322   ///  indicates the type of control-flow that occurs between a block
323   ///  and its successors.
324   CFGTerminator Terminator;
325
326   /// LoopTarget - Some blocks are used to represent the "loop edge" to
327   ///  the start of a loop from within the loop body.  This Stmt* will be
328   ///  refer to the loop statement for such blocks (and be null otherwise).
329   const Stmt *LoopTarget;
330
331   /// BlockID - A numerical ID assigned to a CFGBlock during construction
332   ///   of the CFG.
333   unsigned BlockID;
334
335   /// Predecessors/Successors - Keep track of the predecessor / successor
336   /// CFG blocks.
337   typedef BumpVector<CFGBlock*> AdjacentBlocks;
338   AdjacentBlocks Preds;
339   AdjacentBlocks Succs;
340
341 public:
342   explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
343     : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
344       BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
345   ~CFGBlock() {}
346
347   // Statement iterators
348   typedef ElementList::iterator                      iterator;
349   typedef ElementList::const_iterator                const_iterator;
350   typedef ElementList::reverse_iterator              reverse_iterator;
351   typedef ElementList::const_reverse_iterator        const_reverse_iterator;
352
353   CFGElement                 front()       const { return Elements.front();   }
354   CFGElement                 back()        const { return Elements.back();    }
355
356   iterator                   begin()             { return Elements.begin();   }
357   iterator                   end()               { return Elements.end();     }
358   const_iterator             begin()       const { return Elements.begin();   }
359   const_iterator             end()         const { return Elements.end();     }
360
361   reverse_iterator           rbegin()            { return Elements.rbegin();  }
362   reverse_iterator           rend()              { return Elements.rend();    }
363   const_reverse_iterator     rbegin()      const { return Elements.rbegin();  }
364   const_reverse_iterator     rend()        const { return Elements.rend();    }
365
366   unsigned                   size()        const { return Elements.size();    }
367   bool                       empty()       const { return Elements.empty();   }
368
369   CFGElement operator[](size_t i) const  { return Elements[i]; }
370
371   // CFG iterators
372   typedef AdjacentBlocks::iterator                              pred_iterator;
373   typedef AdjacentBlocks::const_iterator                  const_pred_iterator;
374   typedef AdjacentBlocks::reverse_iterator              pred_reverse_iterator;
375   typedef AdjacentBlocks::const_reverse_iterator  const_pred_reverse_iterator;
376
377   typedef AdjacentBlocks::iterator                              succ_iterator;
378   typedef AdjacentBlocks::const_iterator                  const_succ_iterator;
379   typedef AdjacentBlocks::reverse_iterator              succ_reverse_iterator;
380   typedef AdjacentBlocks::const_reverse_iterator  const_succ_reverse_iterator;
381
382   pred_iterator                pred_begin()        { return Preds.begin();   }
383   pred_iterator                pred_end()          { return Preds.end();     }
384   const_pred_iterator          pred_begin()  const { return Preds.begin();   }
385   const_pred_iterator          pred_end()    const { return Preds.end();     }
386
387   pred_reverse_iterator        pred_rbegin()       { return Preds.rbegin();  }
388   pred_reverse_iterator        pred_rend()         { return Preds.rend();    }
389   const_pred_reverse_iterator  pred_rbegin() const { return Preds.rbegin();  }
390   const_pred_reverse_iterator  pred_rend()   const { return Preds.rend();    }
391
392   succ_iterator                succ_begin()        { return Succs.begin();   }
393   succ_iterator                succ_end()          { return Succs.end();     }
394   const_succ_iterator          succ_begin()  const { return Succs.begin();   }
395   const_succ_iterator          succ_end()    const { return Succs.end();     }
396
397   succ_reverse_iterator        succ_rbegin()       { return Succs.rbegin();  }
398   succ_reverse_iterator        succ_rend()         { return Succs.rend();    }
399   const_succ_reverse_iterator  succ_rbegin() const { return Succs.rbegin();  }
400   const_succ_reverse_iterator  succ_rend()   const { return Succs.rend();    }
401
402   unsigned                     succ_size()   const { return Succs.size();    }
403   bool                         succ_empty()  const { return Succs.empty();   }
404
405   unsigned                     pred_size()   const { return Preds.size();    }
406   bool                         pred_empty()  const { return Preds.empty();   }
407
408
409   class FilterOptions {
410   public:
411     FilterOptions() {
412       IgnoreDefaultsWithCoveredEnums = 0;
413     }
414
415     unsigned IgnoreDefaultsWithCoveredEnums : 1;
416   };
417
418   static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
419        const CFGBlock *Dst);
420
421   template <typename IMPL, bool IsPred>
422   class FilteredCFGBlockIterator {
423   private:
424     IMPL I, E;
425     const FilterOptions F;
426     const CFGBlock *From;
427    public:
428     explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
429               const CFGBlock *from,
430               const FilterOptions &f)
431       : I(i), E(e), F(f), From(from) {}
432
433     bool hasMore() const { return I != E; }
434
435     FilteredCFGBlockIterator &operator++() {
436       do { ++I; } while (hasMore() && Filter(*I));
437       return *this;
438     }
439
440     const CFGBlock *operator*() const { return *I; }
441   private:
442     bool Filter(const CFGBlock *To) {
443       return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
444     }
445   };
446
447   typedef FilteredCFGBlockIterator<const_pred_iterator, true>
448           filtered_pred_iterator;
449
450   typedef FilteredCFGBlockIterator<const_succ_iterator, false>
451           filtered_succ_iterator;
452
453   filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
454     return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
455   }
456
457   filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const {
458     return filtered_succ_iterator(succ_begin(), succ_end(), this, f);
459   }
460
461   // Manipulation of block contents
462
463   void setTerminator(Stmt* Statement) { Terminator = Statement; }
464   void setLabel(Stmt* Statement) { Label = Statement; }
465   void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
466
467   CFGTerminator getTerminator() { return Terminator; }
468   const CFGTerminator getTerminator() const { return Terminator; }
469
470   Stmt* getTerminatorCondition();
471
472   const Stmt* getTerminatorCondition() const {
473     return const_cast<CFGBlock*>(this)->getTerminatorCondition();
474   }
475
476   const Stmt *getLoopTarget() const { return LoopTarget; }
477
478   bool hasBinaryBranchTerminator() const;
479
480   Stmt* getLabel() { return Label; }
481   const Stmt* getLabel() const { return Label; }
482
483   unsigned getBlockID() const { return BlockID; }
484
485   void dump(const CFG *cfg, const LangOptions &LO) const;
486   void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
487   void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const;
488   
489   void addSuccessor(CFGBlock* Block, BumpVectorContext &C) {
490     if (Block)
491       Block->Preds.push_back(this, C);
492     Succs.push_back(Block, C);
493   }
494   
495   void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
496     Elements.push_back(CFGStmt(Statement, asLValue), C);
497   }
498
499   void appendInitializer(CXXBaseOrMemberInitializer *I, BumpVectorContext& C) {
500     Elements.push_back(CFGInitializer(I), C);
501   }
502
503   void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
504     Elements.push_back(CFGBaseDtor(BS), C);
505   }
506
507   void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
508     Elements.push_back(CFGMemberDtor(FD), C);
509   }
510   
511   void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) {
512     Elements.push_back(CFGTemporaryDtor(E), C);
513   }
514
515   // Destructors must be inserted in reversed order. So insertion is in two
516   // steps. First we prepare space for some number of elements, then we insert
517   // the elements beginning at the last position in prepared space.
518   iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
519       BumpVectorContext& C) {
520     return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C));
521   }
522   iterator insertAutomaticObjDtor(iterator I, VarDecl* VD, Stmt* S) {
523     *I = CFGAutomaticObjDtor(VD, S);
524     return ++I;
525   }
526 };
527
528 /// CFG - Represents a source-level, intra-procedural CFG that represents the
529 ///  control-flow of a Stmt.  The Stmt can represent an entire function body,
530 ///  or a single expression.  A CFG will always contain one empty block that
531 ///  represents the Exit point of the CFG.  A CFG will also contain a designated
532 ///  Entry block.  The CFG solely represents control-flow; it consists of
533 ///  CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
534 ///  was constructed from.
535 class CFG {
536 public:
537   //===--------------------------------------------------------------------===//
538   // CFG Construction & Manipulation.
539   //===--------------------------------------------------------------------===//
540
541   class BuildOptions {
542   public:
543     bool PruneTriviallyFalseEdges:1;
544     bool AddEHEdges:1;
545     bool AddInitializers:1;
546     bool AddImplicitDtors:1;
547
548     BuildOptions()
549         : PruneTriviallyFalseEdges(true)
550         , AddEHEdges(false)
551         , AddInitializers(false)
552         , AddImplicitDtors(false) {}
553   };
554
555   /// buildCFG - Builds a CFG from an AST.  The responsibility to free the
556   ///   constructed CFG belongs to the caller.
557   static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
558       BuildOptions BO = BuildOptions());
559
560   /// createBlock - Create a new block in the CFG.  The CFG owns the block;
561   ///  the caller should not directly free it.
562   CFGBlock* createBlock();
563
564   /// setEntry - Set the entry block of the CFG.  This is typically used
565   ///  only during CFG construction.  Most CFG clients expect that the
566   ///  entry block has no predecessors and contains no statements.
567   void setEntry(CFGBlock *B) { Entry = B; }
568
569   /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
570   ///  This is typically used only during CFG construction.
571   void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
572
573   //===--------------------------------------------------------------------===//
574   // Block Iterators
575   //===--------------------------------------------------------------------===//
576
577   typedef BumpVector<CFGBlock*>                    CFGBlockListTy;    
578   typedef CFGBlockListTy::iterator                 iterator;
579   typedef CFGBlockListTy::const_iterator           const_iterator;
580   typedef std::reverse_iterator<iterator>          reverse_iterator;
581   typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;
582
583   CFGBlock&                 front()                { return *Blocks.front(); }
584   CFGBlock&                 back()                 { return *Blocks.back(); }
585
586   iterator                  begin()                { return Blocks.begin(); }
587   iterator                  end()                  { return Blocks.end(); }
588   const_iterator            begin()       const    { return Blocks.begin(); }
589   const_iterator            end()         const    { return Blocks.end(); }
590
591   reverse_iterator          rbegin()               { return Blocks.rbegin(); }
592   reverse_iterator          rend()                 { return Blocks.rend(); }
593   const_reverse_iterator    rbegin()      const    { return Blocks.rbegin(); }
594   const_reverse_iterator    rend()        const    { return Blocks.rend(); }
595
596   CFGBlock&                 getEntry()             { return *Entry; }
597   const CFGBlock&           getEntry()    const    { return *Entry; }
598   CFGBlock&                 getExit()              { return *Exit; }
599   const CFGBlock&           getExit()     const    { return *Exit; }
600
601   CFGBlock*        getIndirectGotoBlock() { return IndirectGotoBlock; }
602   const CFGBlock*  getIndirectGotoBlock() const { return IndirectGotoBlock; }
603
604   //===--------------------------------------------------------------------===//
605   // Member templates useful for various batch operations over CFGs.
606   //===--------------------------------------------------------------------===//
607
608   template <typename CALLBACK>
609   void VisitBlockStmts(CALLBACK& O) const {
610     for (const_iterator I=begin(), E=end(); I != E; ++I)
611       for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
612            BI != BE; ++BI) {
613         if (CFGStmt S = BI->getAs<CFGStmt>())
614           O(S);
615       }
616   }
617
618   //===--------------------------------------------------------------------===//
619   // CFG Introspection.
620   //===--------------------------------------------------------------------===//
621
622   struct   BlkExprNumTy {
623     const signed Idx;
624     explicit BlkExprNumTy(signed idx) : Idx(idx) {}
625     explicit BlkExprNumTy() : Idx(-1) {}
626     operator bool() const { return Idx >= 0; }
627     operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
628   };
629
630   bool          isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
631   BlkExprNumTy  getBlkExprNum(const Stmt* S);
632   unsigned      getNumBlkExprs();
633
634   /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
635   /// start at 0).
636   unsigned getNumBlockIDs() const { return NumBlockIDs; }
637
638   //===--------------------------------------------------------------------===//
639   // CFG Debugging: Pretty-Printing and Visualization.
640   //===--------------------------------------------------------------------===//
641
642   void viewCFG(const LangOptions &LO) const;
643   void print(llvm::raw_ostream& OS, const LangOptions &LO) const;
644   void dump(const LangOptions &LO) const;
645
646   //===--------------------------------------------------------------------===//
647   // Internal: constructors and data.
648   //===--------------------------------------------------------------------===//
649
650   CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
651           BlkExprMap(NULL), Blocks(BlkBVC, 10) {}
652
653   ~CFG();
654
655   llvm::BumpPtrAllocator& getAllocator() {
656     return BlkBVC.getAllocator();
657   }
658   
659   BumpVectorContext &getBumpVectorContext() {
660     return BlkBVC;
661   }
662
663 private:
664   CFGBlock* Entry;
665   CFGBlock* Exit;
666   CFGBlock* IndirectGotoBlock;  // Special block to contain collective dispatch
667                                 // for indirect gotos
668   unsigned  NumBlockIDs;
669
670   // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
671   //  It represents a map from Expr* to integers to record the set of
672   //  block-level expressions and their "statement number" in the CFG.
673   void*     BlkExprMap;
674   
675   BumpVectorContext BlkBVC;
676   
677   CFGBlockListTy Blocks;
678
679 };
680 } // end namespace clang
681
682 //===----------------------------------------------------------------------===//
683 // GraphTraits specializations for CFG basic block graphs (source-level CFGs)
684 //===----------------------------------------------------------------------===//
685
686 namespace llvm {
687
688 /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
689 /// CFGTerminator to a specific Stmt class.
690 template <> struct simplify_type<const ::clang::CFGTerminator> {
691   typedef const ::clang::Stmt *SimpleType;
692   static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
693     return Val.getStmt();
694   }
695 };
696
697 template <> struct simplify_type< ::clang::CFGTerminator> {
698   typedef ::clang::Stmt *SimpleType;
699   static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
700     return const_cast<SimpleType>(Val.getStmt());
701   }
702 };
703
704 // Traits for: CFGBlock
705
706 template <> struct GraphTraits< ::clang::CFGBlock* > {
707   typedef ::clang::CFGBlock NodeType;
708   typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
709
710   static NodeType* getEntryNode(::clang::CFGBlock* BB)
711   { return BB; }
712
713   static inline ChildIteratorType child_begin(NodeType* N)
714   { return N->succ_begin(); }
715
716   static inline ChildIteratorType child_end(NodeType* N)
717   { return N->succ_end(); }
718 };
719
720 template <> struct GraphTraits< const ::clang::CFGBlock* > {
721   typedef const ::clang::CFGBlock NodeType;
722   typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
723
724   static NodeType* getEntryNode(const clang::CFGBlock* BB)
725   { return BB; }
726
727   static inline ChildIteratorType child_begin(NodeType* N)
728   { return N->succ_begin(); }
729
730   static inline ChildIteratorType child_end(NodeType* N)
731   { return N->succ_end(); }
732 };
733
734 template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
735   typedef const ::clang::CFGBlock NodeType;
736   typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
737
738   static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G)
739   { return G.Graph; }
740
741   static inline ChildIteratorType child_begin(NodeType* N)
742   { return N->pred_begin(); }
743
744   static inline ChildIteratorType child_end(NodeType* N)
745   { return N->pred_end(); }
746 };
747
748 // Traits for: CFG
749
750 template <> struct GraphTraits< ::clang::CFG* >
751     : public GraphTraits< ::clang::CFGBlock* >  {
752
753   typedef ::clang::CFG::iterator nodes_iterator;
754
755   static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
756   static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); }
757   static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); }
758 };
759
760 template <> struct GraphTraits<const ::clang::CFG* >
761     : public GraphTraits<const ::clang::CFGBlock* >  {
762
763   typedef ::clang::CFG::const_iterator nodes_iterator;
764
765   static NodeType *getEntryNode( const ::clang::CFG* F) {
766     return &F->getEntry();
767   }
768   static nodes_iterator nodes_begin( const ::clang::CFG* F) {
769     return F->begin();
770   }
771   static nodes_iterator nodes_end( const ::clang::CFG* F) {
772     return F->end();
773   }
774 };
775
776 template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
777   : public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
778
779   typedef ::clang::CFG::const_iterator nodes_iterator;
780
781   static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
782   static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();}
783   static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); }
784 };
785 } // end llvm namespace
786 #endif