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