]> granicus.if.org Git - clang/blob - include/clang/Analysis/CFG.h
Update stale comment.
[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/GraphTraits.h"
19 #include "llvm/Support/Allocator.h"
20 #include <list>
21 #include <vector>
22 #include <cassert>
23
24 namespace llvm {
25   class raw_ostream;
26 }
27 namespace clang {
28   class Stmt;
29   class Expr;
30   class CFG;
31   class PrinterHelper;
32   class LangOptions;
33   class ASTContext;
34
35 /// CFGBlock - Represents a single basic block in a source-level CFG.
36 ///  It consists of:
37 ///
38 ///  (1) A set of statements/expressions (which may contain subexpressions).
39 ///  (2) A "terminator" statement (not in the set of statements).
40 ///  (3) A list of successors and predecessors.
41 ///
42 /// Terminator: The terminator represents the type of control-flow that occurs
43 /// at the end of the basic block.  The terminator is a Stmt* referring to an
44 /// AST node that has control-flow: if-statements, breaks, loops, etc.
45 /// If the control-flow is conditional, the condition expression will appear
46 /// within the set of statements in the block (usually the last statement).
47 ///
48 /// Predecessors: the order in the set of predecessors is arbitrary.
49 ///
50 /// Successors: the order in the set of successors is NOT arbitrary.  We
51 ///  currently have the following orderings based on the terminator:
52 ///
53 ///     Terminator       Successor Ordering
54 ///  -----------------------------------------------------
55 ///       if            Then Block;  Else Block
56 ///     ? operator      LHS expression;  RHS expression
57 ///     &&, ||          expression that uses result of && or ||, RHS
58 ///
59 class CFGBlock {
60   typedef std::vector<Stmt*> StatementListTy;
61   /// Stmts - The set of statements in the basic block.
62   StatementListTy Stmts;
63
64   /// Label - An (optional) label that prefixes the executable
65   ///  statements in the block.  When this variable is non-NULL, it is
66   ///  either an instance of LabelStmt or SwitchCase.
67   Stmt *Label;
68   
69   /// Terminator - The terminator for a basic block that
70   ///  indicates the type of control-flow that occurs between a block
71   ///  and its successors.
72   Stmt *Terminator;
73   
74   /// LoopTarget - Some blocks are used to represent the "loop edge" to
75   ///  the start of a loop from within the loop body.  This Stmt* will be
76   ///  refer to the loop statement for such blocks (and be null otherwise).
77   const Stmt *LoopTarget; 
78   
79   /// BlockID - A numerical ID assigned to a CFGBlock during construction
80   ///   of the CFG.
81   unsigned BlockID;
82   
83   /// Predecessors/Successors - Keep track of the predecessor / successor
84   /// CFG blocks.
85   typedef std::vector<CFGBlock*> AdjacentBlocks;
86   AdjacentBlocks Preds;
87   AdjacentBlocks Succs;
88   
89 public:
90   explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
91                                         LoopTarget(NULL), BlockID(blockid) {}
92   ~CFGBlock() {};
93
94   // Statement iterators
95   typedef StatementListTy::iterator                                  iterator;
96   typedef StatementListTy::const_iterator                      const_iterator;
97   typedef std::reverse_iterator<const_iterator>        const_reverse_iterator;
98   typedef std::reverse_iterator<iterator>                    reverse_iterator;
99   
100   Stmt*                        front()       const { return Stmts.front();   }
101   Stmt*                        back()        const { return Stmts.back();    }
102   
103   iterator                     begin()             { return Stmts.begin();   }
104   iterator                     end()               { return Stmts.end();     }
105   const_iterator               begin()       const { return Stmts.begin();   }
106   const_iterator               end()         const { return Stmts.end();     } 
107
108   reverse_iterator             rbegin()            { return Stmts.rbegin();  }
109   reverse_iterator             rend()              { return Stmts.rend();    }
110   const_reverse_iterator       rbegin()      const { return Stmts.rbegin();  }
111   const_reverse_iterator       rend()        const { return Stmts.rend();    }
112   
113   unsigned                     size()        const { return Stmts.size();    }
114   bool                         empty()       const { return Stmts.empty();   }
115
116   Stmt*  operator[](size_t i) const  { assert (i < size()); return Stmts[i]; }
117   
118   // CFG iterators
119   typedef AdjacentBlocks::iterator                              pred_iterator;
120   typedef AdjacentBlocks::const_iterator                  const_pred_iterator;
121   typedef AdjacentBlocks::reverse_iterator              pred_reverse_iterator;
122   typedef AdjacentBlocks::const_reverse_iterator  const_pred_reverse_iterator;
123
124   typedef AdjacentBlocks::iterator                              succ_iterator;
125   typedef AdjacentBlocks::const_iterator                  const_succ_iterator;
126   typedef AdjacentBlocks::reverse_iterator              succ_reverse_iterator;
127   typedef AdjacentBlocks::const_reverse_iterator  const_succ_reverse_iterator;
128   
129   pred_iterator                pred_begin()        { return Preds.begin();   }
130   pred_iterator                pred_end()          { return Preds.end();     }
131   const_pred_iterator          pred_begin()  const { return Preds.begin();   }
132   const_pred_iterator          pred_end()    const { return Preds.end();     }
133   
134   pred_reverse_iterator        pred_rbegin()       { return Preds.rbegin();  }
135   pred_reverse_iterator        pred_rend()         { return Preds.rend();    }  
136   const_pred_reverse_iterator  pred_rbegin() const { return Preds.rbegin();  }
137   const_pred_reverse_iterator  pred_rend()   const { return Preds.rend();    }
138
139   succ_iterator                succ_begin()        { return Succs.begin();   }    
140   succ_iterator                succ_end()          { return Succs.end();     }
141   const_succ_iterator          succ_begin()  const { return Succs.begin();   }
142   const_succ_iterator          succ_end()    const { return Succs.end();     }  
143     
144   succ_reverse_iterator        succ_rbegin()       { return Succs.rbegin();  }
145   succ_reverse_iterator        succ_rend()         { return Succs.rend();    }
146   const_succ_reverse_iterator  succ_rbegin() const { return Succs.rbegin();  }
147   const_succ_reverse_iterator  succ_rend()   const { return Succs.rend();    }
148
149   unsigned                     succ_size()   const { return Succs.size();    }
150   bool                         succ_empty()  const { return Succs.empty();   }
151
152   unsigned                     pred_size()   const { return Preds.size();    }
153   bool                         pred_empty()  const { return Preds.empty();   }
154   
155   // Manipulation of block contents
156   
157   void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
158   void setTerminator(Stmt* Statement) { Terminator = Statement; }
159   void setLabel(Stmt* Statement) { Label = Statement; }
160   void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
161
162   Stmt* getTerminator() { return Terminator; }
163   const Stmt* getTerminator() const { return Terminator; }
164   
165   Stmt* getTerminatorCondition();
166   
167   const Stmt* getTerminatorCondition() const {
168     return const_cast<CFGBlock*>(this)->getTerminatorCondition();
169   }
170   
171   const Stmt *getLoopTarget() const { return LoopTarget; }
172   
173   bool hasBinaryBranchTerminator() const;
174   
175   Stmt* getLabel() { return Label; }
176   const Stmt* getLabel() const { return Label; }
177   
178   void reverseStmts();
179   
180   void addSuccessor(CFGBlock* Block) {
181     if (Block)
182       Block->Preds.push_back(this);
183     Succs.push_back(Block);
184   }
185   
186   unsigned getBlockID() const { return BlockID; }
187   
188   void dump(const CFG *cfg, const LangOptions &LO) const;
189   void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
190   void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const;
191 };
192   
193
194 /// CFG - Represents a source-level, intra-procedural CFG that represents the
195 ///  control-flow of a Stmt.  The Stmt can represent an entire function body,
196 ///  or a single expression.  A CFG will always contain one empty block that
197 ///  represents the Exit point of the CFG.  A CFG will also contain a designated
198 ///  Entry block.  The CFG solely represents control-flow; it consists of
199 ///  CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
200 ///  was constructed from.
201 class CFG {
202 public:
203   //===--------------------------------------------------------------------===//
204   // CFG Construction & Manipulation.
205   //===--------------------------------------------------------------------===//
206
207   /// buildCFG - Builds a CFG from an AST.  The responsibility to free the
208   ///   constructed CFG belongs to the caller.  
209   static CFG* buildCFG(Stmt* AST, ASTContext *C);  
210   
211   /// createBlock - Create a new block in the CFG.  The CFG owns the block;
212   ///  the caller should not directly free it.
213   CFGBlock* createBlock();
214   
215   /// setEntry - Set the entry block of the CFG.  This is typically used
216   ///  only during CFG construction.  Most CFG clients expect that the
217   ///  entry block has no predecessors and contains no statements.
218   void setEntry(CFGBlock *B) { Entry = B; }
219   
220   /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
221   ///  This is typically used only during CFG construction.
222   void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
223   
224   //===--------------------------------------------------------------------===//
225   // Block Iterators
226   //===--------------------------------------------------------------------===//
227
228   typedef std::list<CFGBlock>                      CFGBlockListTy;
229   
230   typedef CFGBlockListTy::iterator                 iterator;
231   typedef CFGBlockListTy::const_iterator           const_iterator;
232   typedef std::reverse_iterator<iterator>          reverse_iterator;
233   typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;
234
235   CFGBlock&                 front()                { return Blocks.front(); }
236   CFGBlock&                 back()                 { return Blocks.back(); }
237   
238   iterator                  begin()                { return Blocks.begin(); }
239   iterator                  end()                  { return Blocks.end(); }
240   const_iterator            begin()       const    { return Blocks.begin(); }
241   const_iterator            end()         const    { return Blocks.end(); } 
242   
243   reverse_iterator          rbegin()               { return Blocks.rbegin(); }
244   reverse_iterator          rend()                 { return Blocks.rend(); }
245   const_reverse_iterator    rbegin()      const    { return Blocks.rbegin(); }
246   const_reverse_iterator    rend()        const    { return Blocks.rend(); }
247   
248   CFGBlock&                 getEntry()             { return *Entry; }
249   const CFGBlock&           getEntry()    const    { return *Entry; }
250   CFGBlock&                 getExit()              { return *Exit; }
251   const CFGBlock&           getExit()     const    { return *Exit; }
252
253   CFGBlock*        getIndirectGotoBlock() { return IndirectGotoBlock; }
254   const CFGBlock*  getIndirectGotoBlock() const { return IndirectGotoBlock; }
255   
256   //===--------------------------------------------------------------------===//
257   // Member templates useful for various batch operations over CFGs.
258   //===--------------------------------------------------------------------===//
259   
260   template <typename CALLBACK>
261   void VisitBlockStmts(CALLBACK& O) const {
262     for (const_iterator I=begin(), E=end(); I != E; ++I)
263       for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI != BE; ++BI)
264         O(*BI);
265   }  
266   
267   //===--------------------------------------------------------------------===//
268   // CFG Introspection.
269   //===--------------------------------------------------------------------===//
270
271   struct   BlkExprNumTy {
272     const signed Idx;
273     explicit BlkExprNumTy(signed idx) : Idx(idx) {}
274     explicit BlkExprNumTy() : Idx(-1) {}
275     operator bool() const { return Idx >= 0; }
276     operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
277   };
278     
279   bool          isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
280   BlkExprNumTy  getBlkExprNum(const Stmt* S);
281   unsigned      getNumBlkExprs();
282   
283   unsigned getNumBlockIDs() const { return NumBlockIDs; }
284
285   //===--------------------------------------------------------------------===//
286   // CFG Debugging: Pretty-Printing and Visualization.
287   //===--------------------------------------------------------------------===//
288
289   void viewCFG(const LangOptions &LO) const;
290   void print(llvm::raw_ostream& OS, const LangOptions &LO) const;
291   void dump(const LangOptions &LO) const;
292
293   //===--------------------------------------------------------------------===//
294   // Internal: constructors and data.
295   //===--------------------------------------------------------------------===//
296
297   CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), 
298           BlkExprMap(NULL) {};
299   
300   ~CFG();
301   
302   llvm::BumpPtrAllocator& getAllocator() {
303     return Alloc;
304   }
305     
306 private:
307   CFGBlock* Entry;
308   CFGBlock* Exit;
309   CFGBlock* IndirectGotoBlock;  // Special block to contain collective dispatch
310   // for indirect gotos
311   CFGBlockListTy Blocks;
312   unsigned  NumBlockIDs;
313   
314   // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
315   //  It represents a map from Expr* to integers to record the set of 
316   //  block-level expressions and their "statement number" in the CFG.
317   void*     BlkExprMap;
318     
319   /// Alloc - An internal allocator.
320   llvm::BumpPtrAllocator Alloc;  
321 };
322 } // end namespace clang
323
324 //===----------------------------------------------------------------------===//
325 // GraphTraits specializations for CFG basic block graphs (source-level CFGs)
326 //===----------------------------------------------------------------------===//
327
328 namespace llvm {
329
330 // Traits for: CFGBlock
331
332 template <> struct GraphTraits<clang::CFGBlock* > {
333   typedef clang::CFGBlock NodeType;
334   typedef clang::CFGBlock::succ_iterator ChildIteratorType;
335   
336   static NodeType* getEntryNode(clang::CFGBlock* BB)
337   { return BB; }
338
339   static inline ChildIteratorType child_begin(NodeType* N)
340   { return N->succ_begin(); }
341     
342   static inline ChildIteratorType child_end(NodeType* N)
343   { return N->succ_end(); }
344 };
345
346 template <> struct GraphTraits<const clang::CFGBlock* > {
347   typedef const clang::CFGBlock NodeType;
348   typedef clang::CFGBlock::const_succ_iterator ChildIteratorType;
349   
350   static NodeType* getEntryNode(const clang::CFGBlock* BB)
351   { return BB; }
352   
353   static inline ChildIteratorType child_begin(NodeType* N)
354   { return N->succ_begin(); }
355   
356   static inline ChildIteratorType child_end(NodeType* N)
357   { return N->succ_end(); }
358 };
359
360 template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > {
361   typedef const clang::CFGBlock NodeType;
362   typedef clang::CFGBlock::const_pred_iterator ChildIteratorType;
363
364   static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G)
365   { return G.Graph; }
366
367   static inline ChildIteratorType child_begin(NodeType* N)
368   { return N->pred_begin(); }
369   
370   static inline ChildIteratorType child_end(NodeType* N)
371   { return N->pred_end(); }
372 };
373
374 // Traits for: CFG
375
376 template <> struct GraphTraits<clang::CFG* > 
377             : public GraphTraits<clang::CFGBlock* >  {
378
379   typedef clang::CFG::iterator nodes_iterator;
380   
381   static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); }  
382   static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); }
383   static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); }
384 };
385
386 template <> struct GraphTraits< const clang::CFG* > 
387             : public GraphTraits< const clang::CFGBlock* >  {
388
389   typedef clang::CFG::const_iterator nodes_iterator;            
390
391   static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); }
392   static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); }
393   static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); }
394 };
395
396 template <> struct GraphTraits<Inverse<const clang::CFG*> >
397             : public GraphTraits<Inverse<const clang::CFGBlock*> > {
398
399   typedef clang::CFG::const_iterator nodes_iterator;
400
401   static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); }
402   static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();}
403   static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); }
404 };
405   
406 } // end llvm namespace
407
408 #endif