1 //===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the CFG and CFGBuilder classes for representing and
11 // building Control-Flow Graphs (CFGs) from ASTs.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_CFG_H
16 #define LLVM_CLANG_CFG_H
18 #include "clang/AST/Stmt.h"
19 #include "clang/Analysis/Support/BumpVector.h"
20 #include "clang/Basic/SourceLocation.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/GraphTraits.h"
23 #include "llvm/ADT/Optional.h"
24 #include "llvm/ADT/OwningPtr.h"
25 #include "llvm/ADT/PointerIntPair.h"
26 #include "llvm/Support/Allocator.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/raw_ostream.h"
34 class CXXDestructorDecl;
40 class CXXCtorInitializer;
41 class CXXBaseSpecifier;
42 class CXXBindTemporaryExpr;
50 /// CFGElement - Represents a top-level expression in a basic block.
63 DTOR_BEGIN = AutomaticObjectDtor,
64 DTOR_END = TemporaryDtor
68 // The int bits are used to mark the kind.
69 llvm::PointerIntPair<void *, 2> Data1;
70 llvm::PointerIntPair<void *, 2> Data2;
72 CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0)
73 : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
74 Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {}
79 /// \brief Convert to the specified CFGElement type, asserting that this
80 /// CFGElement is of the desired type.
83 assert(T::isKind(*this));
90 /// \brief Convert to the specified CFGElement type, returning None if this
91 /// CFGElement is not of the desired type.
93 Optional<T> getAs() const {
94 if (!T::isKind(*this))
102 Kind getKind() const {
103 unsigned x = Data2.getInt();
110 class CFGStmt : public CFGElement {
112 CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
114 const Stmt *getStmt() const {
115 return static_cast<const Stmt *>(Data1.getPointer());
119 friend class CFGElement;
121 static bool isKind(const CFGElement &E) {
122 return E.getKind() == Statement;
126 /// CFGInitializer - Represents C++ base or member initializer from
127 /// constructor's initialization list.
128 class CFGInitializer : public CFGElement {
130 CFGInitializer(CXXCtorInitializer *initializer)
131 : CFGElement(Initializer, initializer) {}
133 CXXCtorInitializer* getInitializer() const {
134 return static_cast<CXXCtorInitializer*>(Data1.getPointer());
138 friend class CFGElement;
140 static bool isKind(const CFGElement &E) {
141 return E.getKind() == Initializer;
145 /// CFGImplicitDtor - Represents C++ object destructor implicitly generated
146 /// by compiler on various occasions.
147 class CFGImplicitDtor : public CFGElement {
150 CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0)
151 : CFGElement(kind, data1, data2) {
152 assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
156 const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const;
157 bool isNoReturn(ASTContext &astContext) const;
160 friend class CFGElement;
161 static bool isKind(const CFGElement &E) {
162 Kind kind = E.getKind();
163 return kind >= DTOR_BEGIN && kind <= DTOR_END;
167 /// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
168 /// for automatic object or temporary bound to const reference at the point
169 /// of leaving its local scope.
170 class CFGAutomaticObjDtor: public CFGImplicitDtor {
172 CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
173 : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {}
175 const VarDecl *getVarDecl() const {
176 return static_cast<VarDecl*>(Data1.getPointer());
179 // Get statement end of which triggered the destructor call.
180 const Stmt *getTriggerStmt() const {
181 return static_cast<Stmt*>(Data2.getPointer());
185 friend class CFGElement;
186 CFGAutomaticObjDtor() {}
187 static bool isKind(const CFGElement &elem) {
188 return elem.getKind() == AutomaticObjectDtor;
192 /// CFGDeleteDtor - Represents C++ object destructor generated
193 /// from a call to delete.
194 class CFGDeleteDtor : public CFGImplicitDtor {
196 CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
197 : CFGImplicitDtor(DeleteDtor, RD, DE) {}
199 const CXXRecordDecl *getCXXRecordDecl() const {
200 return static_cast<CXXRecordDecl*>(Data1.getPointer());
203 // Get Delete expression which triggered the destructor call.
204 const CXXDeleteExpr *getDeleteExpr() const {
205 return static_cast<CXXDeleteExpr *>(Data2.getPointer());
210 friend class CFGElement;
212 static bool isKind(const CFGElement &elem) {
213 return elem.getKind() == DeleteDtor;
217 /// CFGBaseDtor - Represents C++ object destructor implicitly generated for
218 /// base object in destructor.
219 class CFGBaseDtor : public CFGImplicitDtor {
221 CFGBaseDtor(const CXXBaseSpecifier *base)
222 : CFGImplicitDtor(BaseDtor, base) {}
224 const CXXBaseSpecifier *getBaseSpecifier() const {
225 return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
229 friend class CFGElement;
231 static bool isKind(const CFGElement &E) {
232 return E.getKind() == BaseDtor;
236 /// CFGMemberDtor - Represents C++ object destructor implicitly generated for
237 /// member object in destructor.
238 class CFGMemberDtor : public CFGImplicitDtor {
240 CFGMemberDtor(const FieldDecl *field)
241 : CFGImplicitDtor(MemberDtor, field, 0) {}
243 const FieldDecl *getFieldDecl() const {
244 return static_cast<const FieldDecl*>(Data1.getPointer());
248 friend class CFGElement;
250 static bool isKind(const CFGElement &E) {
251 return E.getKind() == MemberDtor;
255 /// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
256 /// at the end of full expression for temporary object.
257 class CFGTemporaryDtor : public CFGImplicitDtor {
259 CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
260 : CFGImplicitDtor(TemporaryDtor, expr, 0) {}
262 const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
263 return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
267 friend class CFGElement;
268 CFGTemporaryDtor() {}
269 static bool isKind(const CFGElement &E) {
270 return E.getKind() == TemporaryDtor;
274 /// CFGTerminator - Represents CFGBlock terminator statement.
276 /// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
277 /// in control flow of destructors of temporaries. In this case terminator
278 /// statement is the same statement that branches control flow in evaluation
279 /// of matching full expression.
280 class CFGTerminator {
281 llvm::PointerIntPair<Stmt *, 1> Data;
284 CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
285 : Data(S, TemporaryDtorsBranch) {}
287 Stmt *getStmt() { return Data.getPointer(); }
288 const Stmt *getStmt() const { return Data.getPointer(); }
290 bool isTemporaryDtorsBranch() const { return Data.getInt(); }
292 operator Stmt *() { return getStmt(); }
293 operator const Stmt *() const { return getStmt(); }
295 Stmt *operator->() { return getStmt(); }
296 const Stmt *operator->() const { return getStmt(); }
298 Stmt &operator*() { return *getStmt(); }
299 const Stmt &operator*() const { return *getStmt(); }
301 LLVM_EXPLICIT operator bool() const { return getStmt(); }
304 /// CFGBlock - Represents a single basic block in a source-level CFG.
307 /// (1) A set of statements/expressions (which may contain subexpressions).
308 /// (2) A "terminator" statement (not in the set of statements).
309 /// (3) A list of successors and predecessors.
311 /// Terminator: The terminator represents the type of control-flow that occurs
312 /// at the end of the basic block. The terminator is a Stmt* referring to an
313 /// AST node that has control-flow: if-statements, breaks, loops, etc.
314 /// If the control-flow is conditional, the condition expression will appear
315 /// within the set of statements in the block (usually the last statement).
317 /// Predecessors: the order in the set of predecessors is arbitrary.
319 /// Successors: the order in the set of successors is NOT arbitrary. We
320 /// currently have the following orderings based on the terminator:
322 /// Terminator Successor Ordering
323 /// -----------------------------------------------------
324 /// if Then Block; Else Block
325 /// ? operator LHS expression; RHS expression
326 /// &&, || expression that uses result of && or ||, RHS
328 /// But note that any of that may be NULL in case of optimized-out edges.
332 typedef BumpVector<CFGElement> ImplTy;
335 ElementList(BumpVectorContext &C) : Impl(C, 4) {}
337 typedef std::reverse_iterator<ImplTy::iterator> iterator;
338 typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
339 typedef ImplTy::iterator reverse_iterator;
340 typedef ImplTy::const_iterator const_reverse_iterator;
341 typedef ImplTy::const_reference const_reference;
343 void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
344 reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
345 BumpVectorContext &C) {
346 return Impl.insert(I, Cnt, E, C);
349 const_reference front() const { return Impl.back(); }
350 const_reference back() const { return Impl.front(); }
352 iterator begin() { return Impl.rbegin(); }
353 iterator end() { return Impl.rend(); }
354 const_iterator begin() const { return Impl.rbegin(); }
355 const_iterator end() const { return Impl.rend(); }
356 reverse_iterator rbegin() { return Impl.begin(); }
357 reverse_iterator rend() { return Impl.end(); }
358 const_reverse_iterator rbegin() const { return Impl.begin(); }
359 const_reverse_iterator rend() const { return Impl.end(); }
361 CFGElement operator[](size_t i) const {
362 assert(i < Impl.size());
363 return Impl[Impl.size() - 1 - i];
366 size_t size() const { return Impl.size(); }
367 bool empty() const { return Impl.empty(); }
370 /// Stmts - The set of statements in the basic block.
371 ElementList Elements;
373 /// Label - An (optional) label that prefixes the executable
374 /// statements in the block. When this variable is non-NULL, it is
375 /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
378 /// Terminator - The terminator for a basic block that
379 /// indicates the type of control-flow that occurs between a block
380 /// and its successors.
381 CFGTerminator Terminator;
383 /// LoopTarget - Some blocks are used to represent the "loop edge" to
384 /// the start of a loop from within the loop body. This Stmt* will be
385 /// refer to the loop statement for such blocks (and be null otherwise).
386 const Stmt *LoopTarget;
388 /// BlockID - A numerical ID assigned to a CFGBlock during construction
392 /// Predecessors/Successors - Keep track of the predecessor / successor
394 typedef BumpVector<CFGBlock*> AdjacentBlocks;
395 AdjacentBlocks Preds;
396 AdjacentBlocks Succs;
398 /// NoReturn - This bit is set when the basic block contains a function call
399 /// or implicit destructor that is attributed as 'noreturn'. In that case,
400 /// control cannot technically ever proceed past this block. All such blocks
401 /// will have a single immediate successor: the exit block. This allows them
402 /// to be easily reached from the exit block and using this bit quickly
403 /// recognized without scanning the contents of the block.
405 /// Optimization Note: This bit could be profitably folded with Terminator's
406 /// storage if the memory usage of CFGBlock becomes an issue.
407 unsigned HasNoReturnElement : 1;
409 /// Parent - The parent CFG that owns this CFGBlock.
413 explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
414 : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
415 BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
419 // Statement iterators
420 typedef ElementList::iterator iterator;
421 typedef ElementList::const_iterator const_iterator;
422 typedef ElementList::reverse_iterator reverse_iterator;
423 typedef ElementList::const_reverse_iterator const_reverse_iterator;
425 CFGElement front() const { return Elements.front(); }
426 CFGElement back() const { return Elements.back(); }
428 iterator begin() { return Elements.begin(); }
429 iterator end() { return Elements.end(); }
430 const_iterator begin() const { return Elements.begin(); }
431 const_iterator end() const { return Elements.end(); }
433 reverse_iterator rbegin() { return Elements.rbegin(); }
434 reverse_iterator rend() { return Elements.rend(); }
435 const_reverse_iterator rbegin() const { return Elements.rbegin(); }
436 const_reverse_iterator rend() const { return Elements.rend(); }
438 unsigned size() const { return Elements.size(); }
439 bool empty() const { return Elements.empty(); }
441 CFGElement operator[](size_t i) const { return Elements[i]; }
444 typedef AdjacentBlocks::iterator pred_iterator;
445 typedef AdjacentBlocks::const_iterator const_pred_iterator;
446 typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
447 typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
449 typedef AdjacentBlocks::iterator succ_iterator;
450 typedef AdjacentBlocks::const_iterator const_succ_iterator;
451 typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
452 typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
454 pred_iterator pred_begin() { return Preds.begin(); }
455 pred_iterator pred_end() { return Preds.end(); }
456 const_pred_iterator pred_begin() const { return Preds.begin(); }
457 const_pred_iterator pred_end() const { return Preds.end(); }
459 pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
460 pred_reverse_iterator pred_rend() { return Preds.rend(); }
461 const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
462 const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
464 succ_iterator succ_begin() { return Succs.begin(); }
465 succ_iterator succ_end() { return Succs.end(); }
466 const_succ_iterator succ_begin() const { return Succs.begin(); }
467 const_succ_iterator succ_end() const { return Succs.end(); }
469 succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
470 succ_reverse_iterator succ_rend() { return Succs.rend(); }
471 const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
472 const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
474 unsigned succ_size() const { return Succs.size(); }
475 bool succ_empty() const { return Succs.empty(); }
477 unsigned pred_size() const { return Preds.size(); }
478 bool pred_empty() const { return Preds.empty(); }
481 class FilterOptions {
484 IgnoreDefaultsWithCoveredEnums = 0;
487 unsigned IgnoreDefaultsWithCoveredEnums : 1;
490 static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
491 const CFGBlock *Dst);
493 template <typename IMPL, bool IsPred>
494 class FilteredCFGBlockIterator {
497 const FilterOptions F;
498 const CFGBlock *From;
500 explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
501 const CFGBlock *from,
502 const FilterOptions &f)
503 : I(i), E(e), F(f), From(from) {}
505 bool hasMore() const { return I != E; }
507 FilteredCFGBlockIterator &operator++() {
508 do { ++I; } while (hasMore() && Filter(*I));
512 const CFGBlock *operator*() const { return *I; }
514 bool Filter(const CFGBlock *To) {
515 return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
519 typedef FilteredCFGBlockIterator<const_pred_iterator, true>
520 filtered_pred_iterator;
522 typedef FilteredCFGBlockIterator<const_succ_iterator, false>
523 filtered_succ_iterator;
525 filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
526 return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
529 filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const {
530 return filtered_succ_iterator(succ_begin(), succ_end(), this, f);
533 // Manipulation of block contents
535 void setTerminator(Stmt *Statement) { Terminator = Statement; }
536 void setLabel(Stmt *Statement) { Label = Statement; }
537 void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
538 void setHasNoReturnElement() { HasNoReturnElement = true; }
540 CFGTerminator getTerminator() { return Terminator; }
541 const CFGTerminator getTerminator() const { return Terminator; }
543 Stmt *getTerminatorCondition();
545 const Stmt *getTerminatorCondition() const {
546 return const_cast<CFGBlock*>(this)->getTerminatorCondition();
549 const Stmt *getLoopTarget() const { return LoopTarget; }
551 Stmt *getLabel() { return Label; }
552 const Stmt *getLabel() const { return Label; }
554 bool hasNoReturnElement() const { return HasNoReturnElement; }
556 unsigned getBlockID() const { return BlockID; }
558 CFG *getParent() const { return Parent; }
560 void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
561 void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
562 bool ShowColors) const;
563 void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
564 void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
565 OS << "BB#" << getBlockID();
568 void addSuccessor(CFGBlock *Block, BumpVectorContext &C) {
570 Block->Preds.push_back(this, C);
571 Succs.push_back(Block, C);
574 void appendStmt(Stmt *statement, BumpVectorContext &C) {
575 Elements.push_back(CFGStmt(statement), C);
578 void appendInitializer(CXXCtorInitializer *initializer,
579 BumpVectorContext &C) {
580 Elements.push_back(CFGInitializer(initializer), C);
583 void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
584 Elements.push_back(CFGBaseDtor(BS), C);
587 void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
588 Elements.push_back(CFGMemberDtor(FD), C);
591 void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) {
592 Elements.push_back(CFGTemporaryDtor(E), C);
595 void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
596 Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
599 void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
600 Elements.push_back(CFGDeleteDtor(RD, DE), C);
603 // Destructors must be inserted in reversed order. So insertion is in two
604 // steps. First we prepare space for some number of elements, then we insert
605 // the elements beginning at the last position in prepared space.
606 iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
607 BumpVectorContext &C) {
608 return iterator(Elements.insert(I.base(), Cnt, CFGAutomaticObjDtor(0, 0), C));
610 iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
611 *I = CFGAutomaticObjDtor(VD, S);
616 /// CFG - Represents a source-level, intra-procedural CFG that represents the
617 /// control-flow of a Stmt. The Stmt can represent an entire function body,
618 /// or a single expression. A CFG will always contain one empty block that
619 /// represents the Exit point of the CFG. A CFG will also contain a designated
620 /// Entry block. The CFG solely represents control-flow; it consists of
621 /// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
622 /// was constructed from.
625 //===--------------------------------------------------------------------===//
626 // CFG Construction & Manipulation.
627 //===--------------------------------------------------------------------===//
630 std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
632 typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
633 ForcedBlkExprs **forcedBlkExprs;
635 bool PruneTriviallyFalseEdges;
637 bool AddInitializers;
638 bool AddImplicitDtors;
639 bool AddTemporaryDtors;
640 bool AddStaticInitBranches;
642 bool alwaysAdd(const Stmt *stmt) const {
643 return alwaysAddMask[stmt->getStmtClass()];
646 BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
647 alwaysAddMask[stmtClass] = val;
651 BuildOptions &setAllAlwaysAdd() {
657 : forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
659 ,AddInitializers(false)
660 ,AddImplicitDtors(false)
661 ,AddTemporaryDtors(false)
662 ,AddStaticInitBranches(false) {}
665 /// \brief Provides a custom implementation of the iterator class to have the
666 /// same interface as Function::iterator - iterator returns CFGBlock
667 /// (not a pointer to CFGBlock).
668 class graph_iterator {
670 typedef const CFGBlock value_type;
671 typedef value_type& reference;
672 typedef value_type* pointer;
673 typedef BumpVector<CFGBlock*>::iterator ImplTy;
675 graph_iterator(const ImplTy &i) : I(i) {}
677 bool operator==(const graph_iterator &X) const { return I == X.I; }
678 bool operator!=(const graph_iterator &X) const { return I != X.I; }
680 reference operator*() const { return **I; }
681 pointer operator->() const { return *I; }
682 operator CFGBlock* () { return *I; }
684 graph_iterator &operator++() { ++I; return *this; }
685 graph_iterator &operator--() { --I; return *this; }
691 class const_graph_iterator {
693 typedef const CFGBlock value_type;
694 typedef value_type& reference;
695 typedef value_type* pointer;
696 typedef BumpVector<CFGBlock*>::const_iterator ImplTy;
698 const_graph_iterator(const ImplTy &i) : I(i) {}
700 bool operator==(const const_graph_iterator &X) const { return I == X.I; }
701 bool operator!=(const const_graph_iterator &X) const { return I != X.I; }
703 reference operator*() const { return **I; }
704 pointer operator->() const { return *I; }
705 operator CFGBlock* () const { return *I; }
707 const_graph_iterator &operator++() { ++I; return *this; }
708 const_graph_iterator &operator--() { --I; return *this; }
714 /// buildCFG - Builds a CFG from an AST. The responsibility to free the
715 /// constructed CFG belongs to the caller.
716 static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
717 const BuildOptions &BO);
719 /// createBlock - Create a new block in the CFG. The CFG owns the block;
720 /// the caller should not directly free it.
721 CFGBlock *createBlock();
723 /// setEntry - Set the entry block of the CFG. This is typically used
724 /// only during CFG construction. Most CFG clients expect that the
725 /// entry block has no predecessors and contains no statements.
726 void setEntry(CFGBlock *B) { Entry = B; }
728 /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
729 /// This is typically used only during CFG construction.
730 void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
732 //===--------------------------------------------------------------------===//
734 //===--------------------------------------------------------------------===//
736 typedef BumpVector<CFGBlock*> CFGBlockListTy;
737 typedef CFGBlockListTy::iterator iterator;
738 typedef CFGBlockListTy::const_iterator const_iterator;
739 typedef std::reverse_iterator<iterator> reverse_iterator;
740 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
742 CFGBlock & front() { return *Blocks.front(); }
743 CFGBlock & back() { return *Blocks.back(); }
745 iterator begin() { return Blocks.begin(); }
746 iterator end() { return Blocks.end(); }
747 const_iterator begin() const { return Blocks.begin(); }
748 const_iterator end() const { return Blocks.end(); }
750 graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); }
751 graph_iterator nodes_end() { return graph_iterator(Blocks.end()); }
752 const_graph_iterator nodes_begin() const {
753 return const_graph_iterator(Blocks.begin());
755 const_graph_iterator nodes_end() const {
756 return const_graph_iterator(Blocks.end());
759 reverse_iterator rbegin() { return Blocks.rbegin(); }
760 reverse_iterator rend() { return Blocks.rend(); }
761 const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
762 const_reverse_iterator rend() const { return Blocks.rend(); }
764 CFGBlock & getEntry() { return *Entry; }
765 const CFGBlock & getEntry() const { return *Entry; }
766 CFGBlock & getExit() { return *Exit; }
767 const CFGBlock & getExit() const { return *Exit; }
769 CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; }
770 const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; }
772 typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator;
773 try_block_iterator try_blocks_begin() const {
774 return TryDispatchBlocks.begin();
776 try_block_iterator try_blocks_end() const {
777 return TryDispatchBlocks.end();
780 void addTryDispatchBlock(const CFGBlock *block) {
781 TryDispatchBlocks.push_back(block);
784 /// Records a synthetic DeclStmt and the DeclStmt it was constructed from.
786 /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains
788 void addSyntheticDeclStmt(const DeclStmt *Synthetic,
789 const DeclStmt *Source) {
790 assert(Synthetic->isSingleDecl() && "Can handle single declarations only");
791 assert(Synthetic != Source && "Don't include original DeclStmts in map");
792 assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");
793 SyntheticDeclStmts[Synthetic] = Source;
796 typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator
797 synthetic_stmt_iterator;
799 /// Iterates over synthetic DeclStmts in the CFG.
801 /// Each element is a (synthetic statement, source statement) pair.
803 /// \sa addSyntheticDeclStmt
804 synthetic_stmt_iterator synthetic_stmt_begin() const {
805 return SyntheticDeclStmts.begin();
808 /// \sa synthetic_stmt_begin
809 synthetic_stmt_iterator synthetic_stmt_end() const {
810 return SyntheticDeclStmts.end();
813 //===--------------------------------------------------------------------===//
814 // Member templates useful for various batch operations over CFGs.
815 //===--------------------------------------------------------------------===//
817 template <typename CALLBACK>
818 void VisitBlockStmts(CALLBACK& O) const {
819 for (const_iterator I=begin(), E=end(); I != E; ++I)
820 for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
822 if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
823 O(const_cast<Stmt*>(stmt->getStmt()));
827 //===--------------------------------------------------------------------===//
828 // CFG Introspection.
829 //===--------------------------------------------------------------------===//
831 /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
833 unsigned getNumBlockIDs() const { return NumBlockIDs; }
835 /// size - Return the total number of CFGBlocks within the CFG
836 /// This is simply a renaming of the getNumBlockIDs(). This is necessary
837 /// because the dominator implementation needs such an interface.
838 unsigned size() const { return NumBlockIDs; }
840 //===--------------------------------------------------------------------===//
841 // CFG Debugging: Pretty-Printing and Visualization.
842 //===--------------------------------------------------------------------===//
844 void viewCFG(const LangOptions &LO) const;
845 void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const;
846 void dump(const LangOptions &LO, bool ShowColors) const;
848 //===--------------------------------------------------------------------===//
849 // Internal: constructors and data.
850 //===--------------------------------------------------------------------===//
852 CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
853 Blocks(BlkBVC, 10) {}
855 llvm::BumpPtrAllocator& getAllocator() {
856 return BlkBVC.getAllocator();
859 BumpVectorContext &getBumpVectorContext() {
866 CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
867 // for indirect gotos
868 unsigned NumBlockIDs;
870 BumpVectorContext BlkBVC;
872 CFGBlockListTy Blocks;
874 /// C++ 'try' statements are modeled with an indirect dispatch block.
875 /// This is the collection of such blocks present in the CFG.
876 std::vector<const CFGBlock *> TryDispatchBlocks;
878 /// Collects DeclStmts synthesized for this CFG and maps each one back to its
880 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
882 } // end namespace clang
884 //===----------------------------------------------------------------------===//
885 // GraphTraits specializations for CFG basic block graphs (source-level CFGs)
886 //===----------------------------------------------------------------------===//
890 /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
891 /// CFGTerminator to a specific Stmt class.
892 template <> struct simplify_type< ::clang::CFGTerminator> {
893 typedef ::clang::Stmt *SimpleType;
894 static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) {
895 return Val.getStmt();
899 // Traits for: CFGBlock
901 template <> struct GraphTraits< ::clang::CFGBlock *> {
902 typedef ::clang::CFGBlock NodeType;
903 typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
905 static NodeType* getEntryNode(::clang::CFGBlock *BB)
908 static inline ChildIteratorType child_begin(NodeType* N)
909 { return N->succ_begin(); }
911 static inline ChildIteratorType child_end(NodeType* N)
912 { return N->succ_end(); }
915 template <> struct GraphTraits< const ::clang::CFGBlock *> {
916 typedef const ::clang::CFGBlock NodeType;
917 typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
919 static NodeType* getEntryNode(const clang::CFGBlock *BB)
922 static inline ChildIteratorType child_begin(NodeType* N)
923 { return N->succ_begin(); }
925 static inline ChildIteratorType child_end(NodeType* N)
926 { return N->succ_end(); }
929 template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > {
930 typedef ::clang::CFGBlock NodeType;
931 typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
933 static NodeType *getEntryNode(Inverse< ::clang::CFGBlock*> G)
936 static inline ChildIteratorType child_begin(NodeType* N)
937 { return N->pred_begin(); }
939 static inline ChildIteratorType child_end(NodeType* N)
940 { return N->pred_end(); }
943 template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
944 typedef const ::clang::CFGBlock NodeType;
945 typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
947 static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G)
950 static inline ChildIteratorType child_begin(NodeType* N)
951 { return N->pred_begin(); }
953 static inline ChildIteratorType child_end(NodeType* N)
954 { return N->pred_end(); }
959 template <> struct GraphTraits< ::clang::CFG* >
960 : public GraphTraits< ::clang::CFGBlock *> {
962 typedef ::clang::CFG::graph_iterator nodes_iterator;
964 static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
965 static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();}
966 static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); }
967 static unsigned size(::clang::CFG* F) { return F->size(); }
970 template <> struct GraphTraits<const ::clang::CFG* >
971 : public GraphTraits<const ::clang::CFGBlock *> {
973 typedef ::clang::CFG::const_graph_iterator nodes_iterator;
975 static NodeType *getEntryNode( const ::clang::CFG* F) {
976 return &F->getEntry();
978 static nodes_iterator nodes_begin( const ::clang::CFG* F) {
979 return F->nodes_begin();
981 static nodes_iterator nodes_end( const ::clang::CFG* F) {
982 return F->nodes_end();
984 static unsigned size(const ::clang::CFG* F) {
989 template <> struct GraphTraits<Inverse< ::clang::CFG*> >
990 : public GraphTraits<Inverse< ::clang::CFGBlock*> > {
992 typedef ::clang::CFG::graph_iterator nodes_iterator;
994 static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); }
995 static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();}
996 static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
999 template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
1000 : public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
1002 typedef ::clang::CFG::const_graph_iterator nodes_iterator;
1004 static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
1005 static nodes_iterator nodes_begin(const ::clang::CFG* F) {
1006 return F->nodes_begin();
1008 static nodes_iterator nodes_end(const ::clang::CFG* F) {
1009 return F->nodes_end();
1012 } // end llvm namespace