1f4a2713aSLionel Sambuc //===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc // 10f4a2713aSLionel Sambuc // This file defines the CFG and CFGBuilder classes for representing and 11f4a2713aSLionel Sambuc // building Control-Flow Graphs (CFGs) from ASTs. 12f4a2713aSLionel Sambuc // 13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 14f4a2713aSLionel Sambuc 15*0a6a1f1dSLionel Sambuc #ifndef LLVM_CLANG_ANALYSIS_CFG_H 16*0a6a1f1dSLionel Sambuc #define LLVM_CLANG_ANALYSIS_CFG_H 17f4a2713aSLionel Sambuc 18f4a2713aSLionel Sambuc #include "clang/AST/Stmt.h" 19f4a2713aSLionel Sambuc #include "clang/Analysis/Support/BumpVector.h" 20f4a2713aSLionel Sambuc #include "clang/Basic/SourceLocation.h" 21f4a2713aSLionel Sambuc #include "llvm/ADT/DenseMap.h" 22f4a2713aSLionel Sambuc #include "llvm/ADT/GraphTraits.h" 23f4a2713aSLionel Sambuc #include "llvm/ADT/Optional.h" 24f4a2713aSLionel Sambuc #include "llvm/ADT/PointerIntPair.h" 25f4a2713aSLionel Sambuc #include "llvm/Support/Allocator.h" 26f4a2713aSLionel Sambuc #include "llvm/Support/Casting.h" 27*0a6a1f1dSLionel Sambuc #include "llvm/Support/raw_ostream.h" 28f4a2713aSLionel Sambuc #include <bitset> 29f4a2713aSLionel Sambuc #include <cassert> 30f4a2713aSLionel Sambuc #include <iterator> 31*0a6a1f1dSLionel Sambuc #include <memory> 32f4a2713aSLionel Sambuc 33f4a2713aSLionel Sambuc namespace clang { 34f4a2713aSLionel Sambuc class CXXDestructorDecl; 35f4a2713aSLionel Sambuc class Decl; 36f4a2713aSLionel Sambuc class Stmt; 37f4a2713aSLionel Sambuc class Expr; 38f4a2713aSLionel Sambuc class FieldDecl; 39f4a2713aSLionel Sambuc class VarDecl; 40f4a2713aSLionel Sambuc class CXXCtorInitializer; 41f4a2713aSLionel Sambuc class CXXBaseSpecifier; 42f4a2713aSLionel Sambuc class CXXBindTemporaryExpr; 43f4a2713aSLionel Sambuc class CFG; 44f4a2713aSLionel Sambuc class PrinterHelper; 45f4a2713aSLionel Sambuc class LangOptions; 46f4a2713aSLionel Sambuc class ASTContext; 47f4a2713aSLionel Sambuc class CXXRecordDecl; 48f4a2713aSLionel Sambuc class CXXDeleteExpr; 49*0a6a1f1dSLionel Sambuc class CXXNewExpr; 50*0a6a1f1dSLionel Sambuc class BinaryOperator; 51f4a2713aSLionel Sambuc 52f4a2713aSLionel Sambuc /// CFGElement - Represents a top-level expression in a basic block. 53f4a2713aSLionel Sambuc class CFGElement { 54f4a2713aSLionel Sambuc public: 55f4a2713aSLionel Sambuc enum Kind { 56f4a2713aSLionel Sambuc // main kind 57f4a2713aSLionel Sambuc Statement, 58f4a2713aSLionel Sambuc Initializer, 59*0a6a1f1dSLionel Sambuc NewAllocator, 60f4a2713aSLionel Sambuc // dtor kind 61f4a2713aSLionel Sambuc AutomaticObjectDtor, 62f4a2713aSLionel Sambuc DeleteDtor, 63f4a2713aSLionel Sambuc BaseDtor, 64f4a2713aSLionel Sambuc MemberDtor, 65f4a2713aSLionel Sambuc TemporaryDtor, 66f4a2713aSLionel Sambuc DTOR_BEGIN = AutomaticObjectDtor, 67f4a2713aSLionel Sambuc DTOR_END = TemporaryDtor 68f4a2713aSLionel Sambuc }; 69f4a2713aSLionel Sambuc 70f4a2713aSLionel Sambuc protected: 71f4a2713aSLionel Sambuc // The int bits are used to mark the kind. 72f4a2713aSLionel Sambuc llvm::PointerIntPair<void *, 2> Data1; 73f4a2713aSLionel Sambuc llvm::PointerIntPair<void *, 2> Data2; 74f4a2713aSLionel Sambuc 75*0a6a1f1dSLionel Sambuc CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) 76f4a2713aSLionel Sambuc : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), 77*0a6a1f1dSLionel Sambuc Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { 78*0a6a1f1dSLionel Sambuc assert(getKind() == kind); 79*0a6a1f1dSLionel Sambuc } 80f4a2713aSLionel Sambuc CFGElement()81f4a2713aSLionel Sambuc CFGElement() {} 82f4a2713aSLionel Sambuc public: 83f4a2713aSLionel Sambuc 84f4a2713aSLionel Sambuc /// \brief Convert to the specified CFGElement type, asserting that this 85f4a2713aSLionel Sambuc /// CFGElement is of the desired type. 86f4a2713aSLionel Sambuc template<typename T> castAs()87f4a2713aSLionel Sambuc T castAs() const { 88f4a2713aSLionel Sambuc assert(T::isKind(*this)); 89f4a2713aSLionel Sambuc T t; 90f4a2713aSLionel Sambuc CFGElement& e = t; 91f4a2713aSLionel Sambuc e = *this; 92f4a2713aSLionel Sambuc return t; 93f4a2713aSLionel Sambuc } 94f4a2713aSLionel Sambuc 95f4a2713aSLionel Sambuc /// \brief Convert to the specified CFGElement type, returning None if this 96f4a2713aSLionel Sambuc /// CFGElement is not of the desired type. 97f4a2713aSLionel Sambuc template<typename T> getAs()98f4a2713aSLionel Sambuc Optional<T> getAs() const { 99f4a2713aSLionel Sambuc if (!T::isKind(*this)) 100f4a2713aSLionel Sambuc return None; 101f4a2713aSLionel Sambuc T t; 102f4a2713aSLionel Sambuc CFGElement& e = t; 103f4a2713aSLionel Sambuc e = *this; 104f4a2713aSLionel Sambuc return t; 105f4a2713aSLionel Sambuc } 106f4a2713aSLionel Sambuc getKind()107f4a2713aSLionel Sambuc Kind getKind() const { 108f4a2713aSLionel Sambuc unsigned x = Data2.getInt(); 109f4a2713aSLionel Sambuc x <<= 2; 110f4a2713aSLionel Sambuc x |= Data1.getInt(); 111f4a2713aSLionel Sambuc return (Kind) x; 112f4a2713aSLionel Sambuc } 113f4a2713aSLionel Sambuc }; 114f4a2713aSLionel Sambuc 115f4a2713aSLionel Sambuc class CFGStmt : public CFGElement { 116f4a2713aSLionel Sambuc public: CFGStmt(Stmt * S)117f4a2713aSLionel Sambuc CFGStmt(Stmt *S) : CFGElement(Statement, S) {} 118f4a2713aSLionel Sambuc getStmt()119f4a2713aSLionel Sambuc const Stmt *getStmt() const { 120f4a2713aSLionel Sambuc return static_cast<const Stmt *>(Data1.getPointer()); 121f4a2713aSLionel Sambuc } 122f4a2713aSLionel Sambuc 123f4a2713aSLionel Sambuc private: 124f4a2713aSLionel Sambuc friend class CFGElement; CFGStmt()125f4a2713aSLionel Sambuc CFGStmt() {} isKind(const CFGElement & E)126f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 127f4a2713aSLionel Sambuc return E.getKind() == Statement; 128f4a2713aSLionel Sambuc } 129f4a2713aSLionel Sambuc }; 130f4a2713aSLionel Sambuc 131f4a2713aSLionel Sambuc /// CFGInitializer - Represents C++ base or member initializer from 132f4a2713aSLionel Sambuc /// constructor's initialization list. 133f4a2713aSLionel Sambuc class CFGInitializer : public CFGElement { 134f4a2713aSLionel Sambuc public: CFGInitializer(CXXCtorInitializer * initializer)135f4a2713aSLionel Sambuc CFGInitializer(CXXCtorInitializer *initializer) 136f4a2713aSLionel Sambuc : CFGElement(Initializer, initializer) {} 137f4a2713aSLionel Sambuc getInitializer()138f4a2713aSLionel Sambuc CXXCtorInitializer* getInitializer() const { 139f4a2713aSLionel Sambuc return static_cast<CXXCtorInitializer*>(Data1.getPointer()); 140f4a2713aSLionel Sambuc } 141f4a2713aSLionel Sambuc 142f4a2713aSLionel Sambuc private: 143f4a2713aSLionel Sambuc friend class CFGElement; CFGInitializer()144f4a2713aSLionel Sambuc CFGInitializer() {} isKind(const CFGElement & E)145f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 146f4a2713aSLionel Sambuc return E.getKind() == Initializer; 147f4a2713aSLionel Sambuc } 148f4a2713aSLionel Sambuc }; 149f4a2713aSLionel Sambuc 150*0a6a1f1dSLionel Sambuc /// CFGNewAllocator - Represents C++ allocator call. 151*0a6a1f1dSLionel Sambuc class CFGNewAllocator : public CFGElement { 152*0a6a1f1dSLionel Sambuc public: CFGNewAllocator(const CXXNewExpr * S)153*0a6a1f1dSLionel Sambuc explicit CFGNewAllocator(const CXXNewExpr *S) 154*0a6a1f1dSLionel Sambuc : CFGElement(NewAllocator, S) {} 155*0a6a1f1dSLionel Sambuc 156*0a6a1f1dSLionel Sambuc // Get the new expression. getAllocatorExpr()157*0a6a1f1dSLionel Sambuc const CXXNewExpr *getAllocatorExpr() const { 158*0a6a1f1dSLionel Sambuc return static_cast<CXXNewExpr *>(Data1.getPointer()); 159*0a6a1f1dSLionel Sambuc } 160*0a6a1f1dSLionel Sambuc 161*0a6a1f1dSLionel Sambuc private: 162*0a6a1f1dSLionel Sambuc friend class CFGElement; CFGNewAllocator()163*0a6a1f1dSLionel Sambuc CFGNewAllocator() {} isKind(const CFGElement & elem)164*0a6a1f1dSLionel Sambuc static bool isKind(const CFGElement &elem) { 165*0a6a1f1dSLionel Sambuc return elem.getKind() == NewAllocator; 166*0a6a1f1dSLionel Sambuc } 167*0a6a1f1dSLionel Sambuc }; 168*0a6a1f1dSLionel Sambuc 169f4a2713aSLionel Sambuc /// CFGImplicitDtor - Represents C++ object destructor implicitly generated 170f4a2713aSLionel Sambuc /// by compiler on various occasions. 171f4a2713aSLionel Sambuc class CFGImplicitDtor : public CFGElement { 172f4a2713aSLionel Sambuc protected: CFGImplicitDtor()173f4a2713aSLionel Sambuc CFGImplicitDtor() {} 174*0a6a1f1dSLionel Sambuc CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) CFGElement(kind,data1,data2)175f4a2713aSLionel Sambuc : CFGElement(kind, data1, data2) { 176f4a2713aSLionel Sambuc assert(kind >= DTOR_BEGIN && kind <= DTOR_END); 177f4a2713aSLionel Sambuc } 178f4a2713aSLionel Sambuc 179f4a2713aSLionel Sambuc public: 180f4a2713aSLionel Sambuc const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; 181f4a2713aSLionel Sambuc bool isNoReturn(ASTContext &astContext) const; 182f4a2713aSLionel Sambuc 183f4a2713aSLionel Sambuc private: 184f4a2713aSLionel Sambuc friend class CFGElement; isKind(const CFGElement & E)185f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 186f4a2713aSLionel Sambuc Kind kind = E.getKind(); 187f4a2713aSLionel Sambuc return kind >= DTOR_BEGIN && kind <= DTOR_END; 188f4a2713aSLionel Sambuc } 189f4a2713aSLionel Sambuc }; 190f4a2713aSLionel Sambuc 191f4a2713aSLionel Sambuc /// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated 192f4a2713aSLionel Sambuc /// for automatic object or temporary bound to const reference at the point 193f4a2713aSLionel Sambuc /// of leaving its local scope. 194f4a2713aSLionel Sambuc class CFGAutomaticObjDtor: public CFGImplicitDtor { 195f4a2713aSLionel Sambuc public: CFGAutomaticObjDtor(const VarDecl * var,const Stmt * stmt)196f4a2713aSLionel Sambuc CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt) 197f4a2713aSLionel Sambuc : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {} 198f4a2713aSLionel Sambuc getVarDecl()199f4a2713aSLionel Sambuc const VarDecl *getVarDecl() const { 200f4a2713aSLionel Sambuc return static_cast<VarDecl*>(Data1.getPointer()); 201f4a2713aSLionel Sambuc } 202f4a2713aSLionel Sambuc 203f4a2713aSLionel Sambuc // Get statement end of which triggered the destructor call. getTriggerStmt()204f4a2713aSLionel Sambuc const Stmt *getTriggerStmt() const { 205f4a2713aSLionel Sambuc return static_cast<Stmt*>(Data2.getPointer()); 206f4a2713aSLionel Sambuc } 207f4a2713aSLionel Sambuc 208f4a2713aSLionel Sambuc private: 209f4a2713aSLionel Sambuc friend class CFGElement; CFGAutomaticObjDtor()210f4a2713aSLionel Sambuc CFGAutomaticObjDtor() {} isKind(const CFGElement & elem)211f4a2713aSLionel Sambuc static bool isKind(const CFGElement &elem) { 212f4a2713aSLionel Sambuc return elem.getKind() == AutomaticObjectDtor; 213f4a2713aSLionel Sambuc } 214f4a2713aSLionel Sambuc }; 215f4a2713aSLionel Sambuc 216f4a2713aSLionel Sambuc /// CFGDeleteDtor - Represents C++ object destructor generated 217f4a2713aSLionel Sambuc /// from a call to delete. 218f4a2713aSLionel Sambuc class CFGDeleteDtor : public CFGImplicitDtor { 219f4a2713aSLionel Sambuc public: CFGDeleteDtor(const CXXRecordDecl * RD,const CXXDeleteExpr * DE)220f4a2713aSLionel Sambuc CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE) 221f4a2713aSLionel Sambuc : CFGImplicitDtor(DeleteDtor, RD, DE) {} 222f4a2713aSLionel Sambuc getCXXRecordDecl()223f4a2713aSLionel Sambuc const CXXRecordDecl *getCXXRecordDecl() const { 224f4a2713aSLionel Sambuc return static_cast<CXXRecordDecl*>(Data1.getPointer()); 225f4a2713aSLionel Sambuc } 226f4a2713aSLionel Sambuc 227f4a2713aSLionel Sambuc // Get Delete expression which triggered the destructor call. getDeleteExpr()228f4a2713aSLionel Sambuc const CXXDeleteExpr *getDeleteExpr() const { 229f4a2713aSLionel Sambuc return static_cast<CXXDeleteExpr *>(Data2.getPointer()); 230f4a2713aSLionel Sambuc } 231f4a2713aSLionel Sambuc 232f4a2713aSLionel Sambuc 233f4a2713aSLionel Sambuc private: 234f4a2713aSLionel Sambuc friend class CFGElement; CFGDeleteDtor()235f4a2713aSLionel Sambuc CFGDeleteDtor() {} isKind(const CFGElement & elem)236f4a2713aSLionel Sambuc static bool isKind(const CFGElement &elem) { 237f4a2713aSLionel Sambuc return elem.getKind() == DeleteDtor; 238f4a2713aSLionel Sambuc } 239f4a2713aSLionel Sambuc }; 240f4a2713aSLionel Sambuc 241f4a2713aSLionel Sambuc /// CFGBaseDtor - Represents C++ object destructor implicitly generated for 242f4a2713aSLionel Sambuc /// base object in destructor. 243f4a2713aSLionel Sambuc class CFGBaseDtor : public CFGImplicitDtor { 244f4a2713aSLionel Sambuc public: CFGBaseDtor(const CXXBaseSpecifier * base)245f4a2713aSLionel Sambuc CFGBaseDtor(const CXXBaseSpecifier *base) 246f4a2713aSLionel Sambuc : CFGImplicitDtor(BaseDtor, base) {} 247f4a2713aSLionel Sambuc getBaseSpecifier()248f4a2713aSLionel Sambuc const CXXBaseSpecifier *getBaseSpecifier() const { 249f4a2713aSLionel Sambuc return static_cast<const CXXBaseSpecifier*>(Data1.getPointer()); 250f4a2713aSLionel Sambuc } 251f4a2713aSLionel Sambuc 252f4a2713aSLionel Sambuc private: 253f4a2713aSLionel Sambuc friend class CFGElement; CFGBaseDtor()254f4a2713aSLionel Sambuc CFGBaseDtor() {} isKind(const CFGElement & E)255f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 256f4a2713aSLionel Sambuc return E.getKind() == BaseDtor; 257f4a2713aSLionel Sambuc } 258f4a2713aSLionel Sambuc }; 259f4a2713aSLionel Sambuc 260f4a2713aSLionel Sambuc /// CFGMemberDtor - Represents C++ object destructor implicitly generated for 261f4a2713aSLionel Sambuc /// member object in destructor. 262f4a2713aSLionel Sambuc class CFGMemberDtor : public CFGImplicitDtor { 263f4a2713aSLionel Sambuc public: CFGMemberDtor(const FieldDecl * field)264f4a2713aSLionel Sambuc CFGMemberDtor(const FieldDecl *field) 265*0a6a1f1dSLionel Sambuc : CFGImplicitDtor(MemberDtor, field, nullptr) {} 266f4a2713aSLionel Sambuc getFieldDecl()267f4a2713aSLionel Sambuc const FieldDecl *getFieldDecl() const { 268f4a2713aSLionel Sambuc return static_cast<const FieldDecl*>(Data1.getPointer()); 269f4a2713aSLionel Sambuc } 270f4a2713aSLionel Sambuc 271f4a2713aSLionel Sambuc private: 272f4a2713aSLionel Sambuc friend class CFGElement; CFGMemberDtor()273f4a2713aSLionel Sambuc CFGMemberDtor() {} isKind(const CFGElement & E)274f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 275f4a2713aSLionel Sambuc return E.getKind() == MemberDtor; 276f4a2713aSLionel Sambuc } 277f4a2713aSLionel Sambuc }; 278f4a2713aSLionel Sambuc 279f4a2713aSLionel Sambuc /// CFGTemporaryDtor - Represents C++ object destructor implicitly generated 280f4a2713aSLionel Sambuc /// at the end of full expression for temporary object. 281f4a2713aSLionel Sambuc class CFGTemporaryDtor : public CFGImplicitDtor { 282f4a2713aSLionel Sambuc public: CFGTemporaryDtor(CXXBindTemporaryExpr * expr)283f4a2713aSLionel Sambuc CFGTemporaryDtor(CXXBindTemporaryExpr *expr) 284*0a6a1f1dSLionel Sambuc : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {} 285f4a2713aSLionel Sambuc getBindTemporaryExpr()286f4a2713aSLionel Sambuc const CXXBindTemporaryExpr *getBindTemporaryExpr() const { 287f4a2713aSLionel Sambuc return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); 288f4a2713aSLionel Sambuc } 289f4a2713aSLionel Sambuc 290f4a2713aSLionel Sambuc private: 291f4a2713aSLionel Sambuc friend class CFGElement; CFGTemporaryDtor()292f4a2713aSLionel Sambuc CFGTemporaryDtor() {} isKind(const CFGElement & E)293f4a2713aSLionel Sambuc static bool isKind(const CFGElement &E) { 294f4a2713aSLionel Sambuc return E.getKind() == TemporaryDtor; 295f4a2713aSLionel Sambuc } 296f4a2713aSLionel Sambuc }; 297f4a2713aSLionel Sambuc 298f4a2713aSLionel Sambuc /// CFGTerminator - Represents CFGBlock terminator statement. 299f4a2713aSLionel Sambuc /// 300f4a2713aSLionel Sambuc /// TemporaryDtorsBranch bit is set to true if the terminator marks a branch 301f4a2713aSLionel Sambuc /// in control flow of destructors of temporaries. In this case terminator 302f4a2713aSLionel Sambuc /// statement is the same statement that branches control flow in evaluation 303f4a2713aSLionel Sambuc /// of matching full expression. 304f4a2713aSLionel Sambuc class CFGTerminator { 305f4a2713aSLionel Sambuc llvm::PointerIntPair<Stmt *, 1> Data; 306f4a2713aSLionel Sambuc public: CFGTerminator()307f4a2713aSLionel Sambuc CFGTerminator() {} 308f4a2713aSLionel Sambuc CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) Data(S,TemporaryDtorsBranch)309f4a2713aSLionel Sambuc : Data(S, TemporaryDtorsBranch) {} 310f4a2713aSLionel Sambuc getStmt()311f4a2713aSLionel Sambuc Stmt *getStmt() { return Data.getPointer(); } getStmt()312f4a2713aSLionel Sambuc const Stmt *getStmt() const { return Data.getPointer(); } 313f4a2713aSLionel Sambuc isTemporaryDtorsBranch()314f4a2713aSLionel Sambuc bool isTemporaryDtorsBranch() const { return Data.getInt(); } 315f4a2713aSLionel Sambuc 316f4a2713aSLionel Sambuc operator Stmt *() { return getStmt(); } 317f4a2713aSLionel Sambuc operator const Stmt *() const { return getStmt(); } 318f4a2713aSLionel Sambuc 319f4a2713aSLionel Sambuc Stmt *operator->() { return getStmt(); } 320f4a2713aSLionel Sambuc const Stmt *operator->() const { return getStmt(); } 321f4a2713aSLionel Sambuc 322f4a2713aSLionel Sambuc Stmt &operator*() { return *getStmt(); } 323f4a2713aSLionel Sambuc const Stmt &operator*() const { return *getStmt(); } 324f4a2713aSLionel Sambuc 325f4a2713aSLionel Sambuc LLVM_EXPLICIT operator bool() const { return getStmt(); } 326f4a2713aSLionel Sambuc }; 327f4a2713aSLionel Sambuc 328f4a2713aSLionel Sambuc /// CFGBlock - Represents a single basic block in a source-level CFG. 329f4a2713aSLionel Sambuc /// It consists of: 330f4a2713aSLionel Sambuc /// 331f4a2713aSLionel Sambuc /// (1) A set of statements/expressions (which may contain subexpressions). 332f4a2713aSLionel Sambuc /// (2) A "terminator" statement (not in the set of statements). 333f4a2713aSLionel Sambuc /// (3) A list of successors and predecessors. 334f4a2713aSLionel Sambuc /// 335f4a2713aSLionel Sambuc /// Terminator: The terminator represents the type of control-flow that occurs 336f4a2713aSLionel Sambuc /// at the end of the basic block. The terminator is a Stmt* referring to an 337f4a2713aSLionel Sambuc /// AST node that has control-flow: if-statements, breaks, loops, etc. 338f4a2713aSLionel Sambuc /// If the control-flow is conditional, the condition expression will appear 339f4a2713aSLionel Sambuc /// within the set of statements in the block (usually the last statement). 340f4a2713aSLionel Sambuc /// 341f4a2713aSLionel Sambuc /// Predecessors: the order in the set of predecessors is arbitrary. 342f4a2713aSLionel Sambuc /// 343f4a2713aSLionel Sambuc /// Successors: the order in the set of successors is NOT arbitrary. We 344f4a2713aSLionel Sambuc /// currently have the following orderings based on the terminator: 345f4a2713aSLionel Sambuc /// 346f4a2713aSLionel Sambuc /// Terminator Successor Ordering 347f4a2713aSLionel Sambuc /// ----------------------------------------------------- 348f4a2713aSLionel Sambuc /// if Then Block; Else Block 349f4a2713aSLionel Sambuc /// ? operator LHS expression; RHS expression 350f4a2713aSLionel Sambuc /// &&, || expression that uses result of && or ||, RHS 351f4a2713aSLionel Sambuc /// 352f4a2713aSLionel Sambuc /// But note that any of that may be NULL in case of optimized-out edges. 353f4a2713aSLionel Sambuc /// 354f4a2713aSLionel Sambuc class CFGBlock { 355f4a2713aSLionel Sambuc class ElementList { 356f4a2713aSLionel Sambuc typedef BumpVector<CFGElement> ImplTy; 357f4a2713aSLionel Sambuc ImplTy Impl; 358f4a2713aSLionel Sambuc public: ElementList(BumpVectorContext & C)359f4a2713aSLionel Sambuc ElementList(BumpVectorContext &C) : Impl(C, 4) {} 360f4a2713aSLionel Sambuc 361f4a2713aSLionel Sambuc typedef std::reverse_iterator<ImplTy::iterator> iterator; 362f4a2713aSLionel Sambuc typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; 363f4a2713aSLionel Sambuc typedef ImplTy::iterator reverse_iterator; 364f4a2713aSLionel Sambuc typedef ImplTy::const_iterator const_reverse_iterator; 365f4a2713aSLionel Sambuc typedef ImplTy::const_reference const_reference; 366f4a2713aSLionel Sambuc push_back(CFGElement e,BumpVectorContext & C)367f4a2713aSLionel Sambuc void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } insert(reverse_iterator I,size_t Cnt,CFGElement E,BumpVectorContext & C)368f4a2713aSLionel Sambuc reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, 369f4a2713aSLionel Sambuc BumpVectorContext &C) { 370f4a2713aSLionel Sambuc return Impl.insert(I, Cnt, E, C); 371f4a2713aSLionel Sambuc } 372f4a2713aSLionel Sambuc front()373f4a2713aSLionel Sambuc const_reference front() const { return Impl.back(); } back()374f4a2713aSLionel Sambuc const_reference back() const { return Impl.front(); } 375f4a2713aSLionel Sambuc begin()376f4a2713aSLionel Sambuc iterator begin() { return Impl.rbegin(); } end()377f4a2713aSLionel Sambuc iterator end() { return Impl.rend(); } begin()378f4a2713aSLionel Sambuc const_iterator begin() const { return Impl.rbegin(); } end()379f4a2713aSLionel Sambuc const_iterator end() const { return Impl.rend(); } rbegin()380f4a2713aSLionel Sambuc reverse_iterator rbegin() { return Impl.begin(); } rend()381f4a2713aSLionel Sambuc reverse_iterator rend() { return Impl.end(); } rbegin()382f4a2713aSLionel Sambuc const_reverse_iterator rbegin() const { return Impl.begin(); } rend()383f4a2713aSLionel Sambuc const_reverse_iterator rend() const { return Impl.end(); } 384f4a2713aSLionel Sambuc 385f4a2713aSLionel Sambuc CFGElement operator[](size_t i) const { 386f4a2713aSLionel Sambuc assert(i < Impl.size()); 387f4a2713aSLionel Sambuc return Impl[Impl.size() - 1 - i]; 388f4a2713aSLionel Sambuc } 389f4a2713aSLionel Sambuc size()390f4a2713aSLionel Sambuc size_t size() const { return Impl.size(); } empty()391f4a2713aSLionel Sambuc bool empty() const { return Impl.empty(); } 392f4a2713aSLionel Sambuc }; 393f4a2713aSLionel Sambuc 394f4a2713aSLionel Sambuc /// Stmts - The set of statements in the basic block. 395f4a2713aSLionel Sambuc ElementList Elements; 396f4a2713aSLionel Sambuc 397f4a2713aSLionel Sambuc /// Label - An (optional) label that prefixes the executable 398f4a2713aSLionel Sambuc /// statements in the block. When this variable is non-NULL, it is 399f4a2713aSLionel Sambuc /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. 400f4a2713aSLionel Sambuc Stmt *Label; 401f4a2713aSLionel Sambuc 402f4a2713aSLionel Sambuc /// Terminator - The terminator for a basic block that 403f4a2713aSLionel Sambuc /// indicates the type of control-flow that occurs between a block 404f4a2713aSLionel Sambuc /// and its successors. 405f4a2713aSLionel Sambuc CFGTerminator Terminator; 406f4a2713aSLionel Sambuc 407f4a2713aSLionel Sambuc /// LoopTarget - Some blocks are used to represent the "loop edge" to 408f4a2713aSLionel Sambuc /// the start of a loop from within the loop body. This Stmt* will be 409f4a2713aSLionel Sambuc /// refer to the loop statement for such blocks (and be null otherwise). 410f4a2713aSLionel Sambuc const Stmt *LoopTarget; 411f4a2713aSLionel Sambuc 412f4a2713aSLionel Sambuc /// BlockID - A numerical ID assigned to a CFGBlock during construction 413f4a2713aSLionel Sambuc /// of the CFG. 414f4a2713aSLionel Sambuc unsigned BlockID; 415f4a2713aSLionel Sambuc 416*0a6a1f1dSLionel Sambuc public: 417*0a6a1f1dSLionel Sambuc /// This class represents a potential adjacent block in the CFG. It encodes 418*0a6a1f1dSLionel Sambuc /// whether or not the block is actually reachable, or can be proved to be 419*0a6a1f1dSLionel Sambuc /// trivially unreachable. For some cases it allows one to encode scenarios 420*0a6a1f1dSLionel Sambuc /// where a block was substituted because the original (now alternate) block 421*0a6a1f1dSLionel Sambuc /// is unreachable. 422*0a6a1f1dSLionel Sambuc class AdjacentBlock { 423*0a6a1f1dSLionel Sambuc enum Kind { 424*0a6a1f1dSLionel Sambuc AB_Normal, 425*0a6a1f1dSLionel Sambuc AB_Unreachable, 426*0a6a1f1dSLionel Sambuc AB_Alternate 427*0a6a1f1dSLionel Sambuc }; 428*0a6a1f1dSLionel Sambuc 429*0a6a1f1dSLionel Sambuc CFGBlock *ReachableBlock; 430*0a6a1f1dSLionel Sambuc llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock; 431*0a6a1f1dSLionel Sambuc 432*0a6a1f1dSLionel Sambuc public: 433*0a6a1f1dSLionel Sambuc /// Construct an AdjacentBlock with a possibly unreachable block. 434*0a6a1f1dSLionel Sambuc AdjacentBlock(CFGBlock *B, bool IsReachable); 435*0a6a1f1dSLionel Sambuc 436*0a6a1f1dSLionel Sambuc /// Construct an AdjacentBlock with a reachable block and an alternate 437*0a6a1f1dSLionel Sambuc /// unreachable block. 438*0a6a1f1dSLionel Sambuc AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock); 439*0a6a1f1dSLionel Sambuc 440*0a6a1f1dSLionel Sambuc /// Get the reachable block, if one exists. getReachableBlock()441*0a6a1f1dSLionel Sambuc CFGBlock *getReachableBlock() const { 442*0a6a1f1dSLionel Sambuc return ReachableBlock; 443*0a6a1f1dSLionel Sambuc } 444*0a6a1f1dSLionel Sambuc 445*0a6a1f1dSLionel Sambuc /// Get the potentially unreachable block. getPossiblyUnreachableBlock()446*0a6a1f1dSLionel Sambuc CFGBlock *getPossiblyUnreachableBlock() const { 447*0a6a1f1dSLionel Sambuc return UnreachableBlock.getPointer(); 448*0a6a1f1dSLionel Sambuc } 449*0a6a1f1dSLionel Sambuc 450*0a6a1f1dSLionel Sambuc /// Provide an implicit conversion to CFGBlock* so that 451*0a6a1f1dSLionel Sambuc /// AdjacentBlock can be substituted for CFGBlock*. 452*0a6a1f1dSLionel Sambuc operator CFGBlock*() const { 453*0a6a1f1dSLionel Sambuc return getReachableBlock(); 454*0a6a1f1dSLionel Sambuc } 455*0a6a1f1dSLionel Sambuc 456*0a6a1f1dSLionel Sambuc CFGBlock& operator *() const { 457*0a6a1f1dSLionel Sambuc return *getReachableBlock(); 458*0a6a1f1dSLionel Sambuc } 459*0a6a1f1dSLionel Sambuc 460*0a6a1f1dSLionel Sambuc CFGBlock* operator ->() const { 461*0a6a1f1dSLionel Sambuc return getReachableBlock(); 462*0a6a1f1dSLionel Sambuc } 463*0a6a1f1dSLionel Sambuc isReachable()464*0a6a1f1dSLionel Sambuc bool isReachable() const { 465*0a6a1f1dSLionel Sambuc Kind K = (Kind) UnreachableBlock.getInt(); 466*0a6a1f1dSLionel Sambuc return K == AB_Normal || K == AB_Alternate; 467*0a6a1f1dSLionel Sambuc } 468*0a6a1f1dSLionel Sambuc }; 469*0a6a1f1dSLionel Sambuc 470*0a6a1f1dSLionel Sambuc private: 471f4a2713aSLionel Sambuc /// Predecessors/Successors - Keep track of the predecessor / successor 472f4a2713aSLionel Sambuc /// CFG blocks. 473*0a6a1f1dSLionel Sambuc typedef BumpVector<AdjacentBlock> AdjacentBlocks; 474f4a2713aSLionel Sambuc AdjacentBlocks Preds; 475f4a2713aSLionel Sambuc AdjacentBlocks Succs; 476f4a2713aSLionel Sambuc 477f4a2713aSLionel Sambuc /// NoReturn - This bit is set when the basic block contains a function call 478f4a2713aSLionel Sambuc /// or implicit destructor that is attributed as 'noreturn'. In that case, 479f4a2713aSLionel Sambuc /// control cannot technically ever proceed past this block. All such blocks 480f4a2713aSLionel Sambuc /// will have a single immediate successor: the exit block. This allows them 481f4a2713aSLionel Sambuc /// to be easily reached from the exit block and using this bit quickly 482f4a2713aSLionel Sambuc /// recognized without scanning the contents of the block. 483f4a2713aSLionel Sambuc /// 484f4a2713aSLionel Sambuc /// Optimization Note: This bit could be profitably folded with Terminator's 485f4a2713aSLionel Sambuc /// storage if the memory usage of CFGBlock becomes an issue. 486f4a2713aSLionel Sambuc unsigned HasNoReturnElement : 1; 487f4a2713aSLionel Sambuc 488f4a2713aSLionel Sambuc /// Parent - The parent CFG that owns this CFGBlock. 489f4a2713aSLionel Sambuc CFG *Parent; 490f4a2713aSLionel Sambuc 491f4a2713aSLionel Sambuc public: CFGBlock(unsigned blockid,BumpVectorContext & C,CFG * parent)492f4a2713aSLionel Sambuc explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) 493*0a6a1f1dSLionel Sambuc : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr), 494f4a2713aSLionel Sambuc BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), 495f4a2713aSLionel Sambuc Parent(parent) {} ~CFGBlock()496f4a2713aSLionel Sambuc ~CFGBlock() {} 497f4a2713aSLionel Sambuc 498f4a2713aSLionel Sambuc // Statement iterators 499f4a2713aSLionel Sambuc typedef ElementList::iterator iterator; 500f4a2713aSLionel Sambuc typedef ElementList::const_iterator const_iterator; 501f4a2713aSLionel Sambuc typedef ElementList::reverse_iterator reverse_iterator; 502f4a2713aSLionel Sambuc typedef ElementList::const_reverse_iterator const_reverse_iterator; 503f4a2713aSLionel Sambuc front()504f4a2713aSLionel Sambuc CFGElement front() const { return Elements.front(); } back()505f4a2713aSLionel Sambuc CFGElement back() const { return Elements.back(); } 506f4a2713aSLionel Sambuc begin()507f4a2713aSLionel Sambuc iterator begin() { return Elements.begin(); } end()508f4a2713aSLionel Sambuc iterator end() { return Elements.end(); } begin()509f4a2713aSLionel Sambuc const_iterator begin() const { return Elements.begin(); } end()510f4a2713aSLionel Sambuc const_iterator end() const { return Elements.end(); } 511f4a2713aSLionel Sambuc rbegin()512f4a2713aSLionel Sambuc reverse_iterator rbegin() { return Elements.rbegin(); } rend()513f4a2713aSLionel Sambuc reverse_iterator rend() { return Elements.rend(); } rbegin()514f4a2713aSLionel Sambuc const_reverse_iterator rbegin() const { return Elements.rbegin(); } rend()515f4a2713aSLionel Sambuc const_reverse_iterator rend() const { return Elements.rend(); } 516f4a2713aSLionel Sambuc size()517f4a2713aSLionel Sambuc unsigned size() const { return Elements.size(); } empty()518f4a2713aSLionel Sambuc bool empty() const { return Elements.empty(); } 519f4a2713aSLionel Sambuc 520f4a2713aSLionel Sambuc CFGElement operator[](size_t i) const { return Elements[i]; } 521f4a2713aSLionel Sambuc 522f4a2713aSLionel Sambuc // CFG iterators 523f4a2713aSLionel Sambuc typedef AdjacentBlocks::iterator pred_iterator; 524f4a2713aSLionel Sambuc typedef AdjacentBlocks::const_iterator const_pred_iterator; 525f4a2713aSLionel Sambuc typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; 526f4a2713aSLionel Sambuc typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; 527f4a2713aSLionel Sambuc 528f4a2713aSLionel Sambuc typedef AdjacentBlocks::iterator succ_iterator; 529f4a2713aSLionel Sambuc typedef AdjacentBlocks::const_iterator const_succ_iterator; 530f4a2713aSLionel Sambuc typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; 531f4a2713aSLionel Sambuc typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; 532f4a2713aSLionel Sambuc pred_begin()533f4a2713aSLionel Sambuc pred_iterator pred_begin() { return Preds.begin(); } pred_end()534f4a2713aSLionel Sambuc pred_iterator pred_end() { return Preds.end(); } pred_begin()535f4a2713aSLionel Sambuc const_pred_iterator pred_begin() const { return Preds.begin(); } pred_end()536f4a2713aSLionel Sambuc const_pred_iterator pred_end() const { return Preds.end(); } 537f4a2713aSLionel Sambuc pred_rbegin()538f4a2713aSLionel Sambuc pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); } pred_rend()539f4a2713aSLionel Sambuc pred_reverse_iterator pred_rend() { return Preds.rend(); } pred_rbegin()540f4a2713aSLionel Sambuc const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } pred_rend()541f4a2713aSLionel Sambuc const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } 542f4a2713aSLionel Sambuc succ_begin()543f4a2713aSLionel Sambuc succ_iterator succ_begin() { return Succs.begin(); } succ_end()544f4a2713aSLionel Sambuc succ_iterator succ_end() { return Succs.end(); } succ_begin()545f4a2713aSLionel Sambuc const_succ_iterator succ_begin() const { return Succs.begin(); } succ_end()546f4a2713aSLionel Sambuc const_succ_iterator succ_end() const { return Succs.end(); } 547f4a2713aSLionel Sambuc succ_rbegin()548f4a2713aSLionel Sambuc succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); } succ_rend()549f4a2713aSLionel Sambuc succ_reverse_iterator succ_rend() { return Succs.rend(); } succ_rbegin()550f4a2713aSLionel Sambuc const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } succ_rend()551f4a2713aSLionel Sambuc const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } 552f4a2713aSLionel Sambuc succ_size()553f4a2713aSLionel Sambuc unsigned succ_size() const { return Succs.size(); } succ_empty()554f4a2713aSLionel Sambuc bool succ_empty() const { return Succs.empty(); } 555f4a2713aSLionel Sambuc pred_size()556f4a2713aSLionel Sambuc unsigned pred_size() const { return Preds.size(); } pred_empty()557f4a2713aSLionel Sambuc bool pred_empty() const { return Preds.empty(); } 558f4a2713aSLionel Sambuc 559f4a2713aSLionel Sambuc 560f4a2713aSLionel Sambuc class FilterOptions { 561f4a2713aSLionel Sambuc public: FilterOptions()562f4a2713aSLionel Sambuc FilterOptions() { 563*0a6a1f1dSLionel Sambuc IgnoreNullPredecessors = 1; 564f4a2713aSLionel Sambuc IgnoreDefaultsWithCoveredEnums = 0; 565f4a2713aSLionel Sambuc } 566f4a2713aSLionel Sambuc 567*0a6a1f1dSLionel Sambuc unsigned IgnoreNullPredecessors : 1; 568f4a2713aSLionel Sambuc unsigned IgnoreDefaultsWithCoveredEnums : 1; 569f4a2713aSLionel Sambuc }; 570f4a2713aSLionel Sambuc 571f4a2713aSLionel Sambuc static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, 572f4a2713aSLionel Sambuc const CFGBlock *Dst); 573f4a2713aSLionel Sambuc 574f4a2713aSLionel Sambuc template <typename IMPL, bool IsPred> 575f4a2713aSLionel Sambuc class FilteredCFGBlockIterator { 576f4a2713aSLionel Sambuc private: 577f4a2713aSLionel Sambuc IMPL I, E; 578f4a2713aSLionel Sambuc const FilterOptions F; 579f4a2713aSLionel Sambuc const CFGBlock *From; 580f4a2713aSLionel Sambuc public: FilteredCFGBlockIterator(const IMPL & i,const IMPL & e,const CFGBlock * from,const FilterOptions & f)581f4a2713aSLionel Sambuc explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, 582f4a2713aSLionel Sambuc const CFGBlock *from, 583f4a2713aSLionel Sambuc const FilterOptions &f) 584*0a6a1f1dSLionel Sambuc : I(i), E(e), F(f), From(from) { 585*0a6a1f1dSLionel Sambuc while (hasMore() && Filter(*I)) 586*0a6a1f1dSLionel Sambuc ++I; 587*0a6a1f1dSLionel Sambuc } 588f4a2713aSLionel Sambuc hasMore()589f4a2713aSLionel Sambuc bool hasMore() const { return I != E; } 590f4a2713aSLionel Sambuc 591f4a2713aSLionel Sambuc FilteredCFGBlockIterator &operator++() { 592f4a2713aSLionel Sambuc do { ++I; } while (hasMore() && Filter(*I)); 593f4a2713aSLionel Sambuc return *this; 594f4a2713aSLionel Sambuc } 595f4a2713aSLionel Sambuc 596f4a2713aSLionel Sambuc const CFGBlock *operator*() const { return *I; } 597f4a2713aSLionel Sambuc private: Filter(const CFGBlock * To)598f4a2713aSLionel Sambuc bool Filter(const CFGBlock *To) { 599f4a2713aSLionel Sambuc return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To); 600f4a2713aSLionel Sambuc } 601f4a2713aSLionel Sambuc }; 602f4a2713aSLionel Sambuc 603f4a2713aSLionel Sambuc typedef FilteredCFGBlockIterator<const_pred_iterator, true> 604f4a2713aSLionel Sambuc filtered_pred_iterator; 605f4a2713aSLionel Sambuc 606f4a2713aSLionel Sambuc typedef FilteredCFGBlockIterator<const_succ_iterator, false> 607f4a2713aSLionel Sambuc filtered_succ_iterator; 608f4a2713aSLionel Sambuc filtered_pred_start_end(const FilterOptions & f)609f4a2713aSLionel Sambuc filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { 610f4a2713aSLionel Sambuc return filtered_pred_iterator(pred_begin(), pred_end(), this, f); 611f4a2713aSLionel Sambuc } 612f4a2713aSLionel Sambuc filtered_succ_start_end(const FilterOptions & f)613f4a2713aSLionel Sambuc filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const { 614f4a2713aSLionel Sambuc return filtered_succ_iterator(succ_begin(), succ_end(), this, f); 615f4a2713aSLionel Sambuc } 616f4a2713aSLionel Sambuc 617f4a2713aSLionel Sambuc // Manipulation of block contents 618f4a2713aSLionel Sambuc setTerminator(CFGTerminator Term)619*0a6a1f1dSLionel Sambuc void setTerminator(CFGTerminator Term) { Terminator = Term; } setLabel(Stmt * Statement)620f4a2713aSLionel Sambuc void setLabel(Stmt *Statement) { Label = Statement; } setLoopTarget(const Stmt * loopTarget)621f4a2713aSLionel Sambuc void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } setHasNoReturnElement()622f4a2713aSLionel Sambuc void setHasNoReturnElement() { HasNoReturnElement = true; } 623f4a2713aSLionel Sambuc getTerminator()624f4a2713aSLionel Sambuc CFGTerminator getTerminator() { return Terminator; } getTerminator()625f4a2713aSLionel Sambuc const CFGTerminator getTerminator() const { return Terminator; } 626f4a2713aSLionel Sambuc 627*0a6a1f1dSLionel Sambuc Stmt *getTerminatorCondition(bool StripParens = true); 628f4a2713aSLionel Sambuc 629*0a6a1f1dSLionel Sambuc const Stmt *getTerminatorCondition(bool StripParens = true) const { 630*0a6a1f1dSLionel Sambuc return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens); 631f4a2713aSLionel Sambuc } 632f4a2713aSLionel Sambuc getLoopTarget()633f4a2713aSLionel Sambuc const Stmt *getLoopTarget() const { return LoopTarget; } 634f4a2713aSLionel Sambuc getLabel()635f4a2713aSLionel Sambuc Stmt *getLabel() { return Label; } getLabel()636f4a2713aSLionel Sambuc const Stmt *getLabel() const { return Label; } 637f4a2713aSLionel Sambuc hasNoReturnElement()638f4a2713aSLionel Sambuc bool hasNoReturnElement() const { return HasNoReturnElement; } 639f4a2713aSLionel Sambuc getBlockID()640f4a2713aSLionel Sambuc unsigned getBlockID() const { return BlockID; } 641f4a2713aSLionel Sambuc getParent()642f4a2713aSLionel Sambuc CFG *getParent() const { return Parent; } 643f4a2713aSLionel Sambuc 644*0a6a1f1dSLionel Sambuc void dump() const; 645*0a6a1f1dSLionel Sambuc 646f4a2713aSLionel Sambuc void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const; 647f4a2713aSLionel Sambuc void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO, 648f4a2713aSLionel Sambuc bool ShowColors) const; 649f4a2713aSLionel Sambuc void printTerminator(raw_ostream &OS, const LangOptions &LO) const; printAsOperand(raw_ostream & OS,bool)650*0a6a1f1dSLionel Sambuc void printAsOperand(raw_ostream &OS, bool /*PrintType*/) { 651*0a6a1f1dSLionel Sambuc OS << "BB#" << getBlockID(); 652f4a2713aSLionel Sambuc } 653f4a2713aSLionel Sambuc 654*0a6a1f1dSLionel Sambuc /// Adds a (potentially unreachable) successor block to the current block. 655*0a6a1f1dSLionel Sambuc void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C); 656*0a6a1f1dSLionel Sambuc appendStmt(Stmt * statement,BumpVectorContext & C)657f4a2713aSLionel Sambuc void appendStmt(Stmt *statement, BumpVectorContext &C) { 658f4a2713aSLionel Sambuc Elements.push_back(CFGStmt(statement), C); 659f4a2713aSLionel Sambuc } 660f4a2713aSLionel Sambuc appendInitializer(CXXCtorInitializer * initializer,BumpVectorContext & C)661f4a2713aSLionel Sambuc void appendInitializer(CXXCtorInitializer *initializer, 662f4a2713aSLionel Sambuc BumpVectorContext &C) { 663f4a2713aSLionel Sambuc Elements.push_back(CFGInitializer(initializer), C); 664f4a2713aSLionel Sambuc } 665f4a2713aSLionel Sambuc appendNewAllocator(CXXNewExpr * NE,BumpVectorContext & C)666*0a6a1f1dSLionel Sambuc void appendNewAllocator(CXXNewExpr *NE, 667*0a6a1f1dSLionel Sambuc BumpVectorContext &C) { 668*0a6a1f1dSLionel Sambuc Elements.push_back(CFGNewAllocator(NE), C); 669*0a6a1f1dSLionel Sambuc } 670*0a6a1f1dSLionel Sambuc appendBaseDtor(const CXXBaseSpecifier * BS,BumpVectorContext & C)671f4a2713aSLionel Sambuc void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) { 672f4a2713aSLionel Sambuc Elements.push_back(CFGBaseDtor(BS), C); 673f4a2713aSLionel Sambuc } 674f4a2713aSLionel Sambuc appendMemberDtor(FieldDecl * FD,BumpVectorContext & C)675f4a2713aSLionel Sambuc void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) { 676f4a2713aSLionel Sambuc Elements.push_back(CFGMemberDtor(FD), C); 677f4a2713aSLionel Sambuc } 678f4a2713aSLionel Sambuc appendTemporaryDtor(CXXBindTemporaryExpr * E,BumpVectorContext & C)679f4a2713aSLionel Sambuc void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) { 680f4a2713aSLionel Sambuc Elements.push_back(CFGTemporaryDtor(E), C); 681f4a2713aSLionel Sambuc } 682f4a2713aSLionel Sambuc appendAutomaticObjDtor(VarDecl * VD,Stmt * S,BumpVectorContext & C)683f4a2713aSLionel Sambuc void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) { 684f4a2713aSLionel Sambuc Elements.push_back(CFGAutomaticObjDtor(VD, S), C); 685f4a2713aSLionel Sambuc } 686f4a2713aSLionel Sambuc appendDeleteDtor(CXXRecordDecl * RD,CXXDeleteExpr * DE,BumpVectorContext & C)687f4a2713aSLionel Sambuc void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { 688f4a2713aSLionel Sambuc Elements.push_back(CFGDeleteDtor(RD, DE), C); 689f4a2713aSLionel Sambuc } 690f4a2713aSLionel Sambuc 691f4a2713aSLionel Sambuc // Destructors must be inserted in reversed order. So insertion is in two 692f4a2713aSLionel Sambuc // steps. First we prepare space for some number of elements, then we insert 693f4a2713aSLionel Sambuc // the elements beginning at the last position in prepared space. beginAutomaticObjDtorsInsert(iterator I,size_t Cnt,BumpVectorContext & C)694f4a2713aSLionel Sambuc iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, 695f4a2713aSLionel Sambuc BumpVectorContext &C) { 696*0a6a1f1dSLionel Sambuc return iterator(Elements.insert(I.base(), Cnt, 697*0a6a1f1dSLionel Sambuc CFGAutomaticObjDtor(nullptr, 0), C)); 698f4a2713aSLionel Sambuc } insertAutomaticObjDtor(iterator I,VarDecl * VD,Stmt * S)699f4a2713aSLionel Sambuc iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) { 700f4a2713aSLionel Sambuc *I = CFGAutomaticObjDtor(VD, S); 701f4a2713aSLionel Sambuc return ++I; 702f4a2713aSLionel Sambuc } 703f4a2713aSLionel Sambuc }; 704f4a2713aSLionel Sambuc 705*0a6a1f1dSLionel Sambuc /// \brief CFGCallback defines methods that should be called when a logical 706*0a6a1f1dSLionel Sambuc /// operator error is found when building the CFG. 707*0a6a1f1dSLionel Sambuc class CFGCallback { 708*0a6a1f1dSLionel Sambuc public: CFGCallback()709*0a6a1f1dSLionel Sambuc CFGCallback() {} compareAlwaysTrue(const BinaryOperator * B,bool isAlwaysTrue)710*0a6a1f1dSLionel Sambuc virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} compareBitwiseEquality(const BinaryOperator * B,bool isAlwaysTrue)711*0a6a1f1dSLionel Sambuc virtual void compareBitwiseEquality(const BinaryOperator *B, 712*0a6a1f1dSLionel Sambuc bool isAlwaysTrue) {} ~CFGCallback()713*0a6a1f1dSLionel Sambuc virtual ~CFGCallback() {} 714*0a6a1f1dSLionel Sambuc }; 715*0a6a1f1dSLionel Sambuc 716f4a2713aSLionel Sambuc /// CFG - Represents a source-level, intra-procedural CFG that represents the 717f4a2713aSLionel Sambuc /// control-flow of a Stmt. The Stmt can represent an entire function body, 718f4a2713aSLionel Sambuc /// or a single expression. A CFG will always contain one empty block that 719f4a2713aSLionel Sambuc /// represents the Exit point of the CFG. A CFG will also contain a designated 720f4a2713aSLionel Sambuc /// Entry block. The CFG solely represents control-flow; it consists of 721f4a2713aSLionel Sambuc /// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG 722f4a2713aSLionel Sambuc /// was constructed from. 723f4a2713aSLionel Sambuc class CFG { 724f4a2713aSLionel Sambuc public: 725f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 726f4a2713aSLionel Sambuc // CFG Construction & Manipulation. 727f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 728f4a2713aSLionel Sambuc 729f4a2713aSLionel Sambuc class BuildOptions { 730f4a2713aSLionel Sambuc std::bitset<Stmt::lastStmtConstant> alwaysAddMask; 731f4a2713aSLionel Sambuc public: 732f4a2713aSLionel Sambuc typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; 733f4a2713aSLionel Sambuc ForcedBlkExprs **forcedBlkExprs; 734*0a6a1f1dSLionel Sambuc CFGCallback *Observer; 735f4a2713aSLionel Sambuc bool PruneTriviallyFalseEdges; 736f4a2713aSLionel Sambuc bool AddEHEdges; 737f4a2713aSLionel Sambuc bool AddInitializers; 738f4a2713aSLionel Sambuc bool AddImplicitDtors; 739f4a2713aSLionel Sambuc bool AddTemporaryDtors; 740f4a2713aSLionel Sambuc bool AddStaticInitBranches; 741*0a6a1f1dSLionel Sambuc bool AddCXXNewAllocator; 742f4a2713aSLionel Sambuc alwaysAdd(const Stmt * stmt)743f4a2713aSLionel Sambuc bool alwaysAdd(const Stmt *stmt) const { 744f4a2713aSLionel Sambuc return alwaysAddMask[stmt->getStmtClass()]; 745f4a2713aSLionel Sambuc } 746f4a2713aSLionel Sambuc 747f4a2713aSLionel Sambuc BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) { 748f4a2713aSLionel Sambuc alwaysAddMask[stmtClass] = val; 749f4a2713aSLionel Sambuc return *this; 750f4a2713aSLionel Sambuc } 751f4a2713aSLionel Sambuc setAllAlwaysAdd()752f4a2713aSLionel Sambuc BuildOptions &setAllAlwaysAdd() { 753f4a2713aSLionel Sambuc alwaysAddMask.set(); 754f4a2713aSLionel Sambuc return *this; 755f4a2713aSLionel Sambuc } 756f4a2713aSLionel Sambuc BuildOptions()757f4a2713aSLionel Sambuc BuildOptions() 758*0a6a1f1dSLionel Sambuc : forcedBlkExprs(nullptr), Observer(nullptr), 759*0a6a1f1dSLionel Sambuc PruneTriviallyFalseEdges(true), AddEHEdges(false), 760*0a6a1f1dSLionel Sambuc AddInitializers(false), AddImplicitDtors(false), 761*0a6a1f1dSLionel Sambuc AddTemporaryDtors(false), AddStaticInitBranches(false), 762*0a6a1f1dSLionel Sambuc AddCXXNewAllocator(false) {} 763f4a2713aSLionel Sambuc }; 764f4a2713aSLionel Sambuc 765f4a2713aSLionel Sambuc /// \brief Provides a custom implementation of the iterator class to have the 766f4a2713aSLionel Sambuc /// same interface as Function::iterator - iterator returns CFGBlock 767f4a2713aSLionel Sambuc /// (not a pointer to CFGBlock). 768f4a2713aSLionel Sambuc class graph_iterator { 769f4a2713aSLionel Sambuc public: 770f4a2713aSLionel Sambuc typedef const CFGBlock value_type; 771f4a2713aSLionel Sambuc typedef value_type& reference; 772f4a2713aSLionel Sambuc typedef value_type* pointer; 773f4a2713aSLionel Sambuc typedef BumpVector<CFGBlock*>::iterator ImplTy; 774f4a2713aSLionel Sambuc graph_iterator(const ImplTy & i)775f4a2713aSLionel Sambuc graph_iterator(const ImplTy &i) : I(i) {} 776f4a2713aSLionel Sambuc 777f4a2713aSLionel Sambuc bool operator==(const graph_iterator &X) const { return I == X.I; } 778f4a2713aSLionel Sambuc bool operator!=(const graph_iterator &X) const { return I != X.I; } 779f4a2713aSLionel Sambuc 780f4a2713aSLionel Sambuc reference operator*() const { return **I; } 781f4a2713aSLionel Sambuc pointer operator->() const { return *I; } 782f4a2713aSLionel Sambuc operator CFGBlock* () { return *I; } 783f4a2713aSLionel Sambuc 784f4a2713aSLionel Sambuc graph_iterator &operator++() { ++I; return *this; } 785f4a2713aSLionel Sambuc graph_iterator &operator--() { --I; return *this; } 786f4a2713aSLionel Sambuc 787f4a2713aSLionel Sambuc private: 788f4a2713aSLionel Sambuc ImplTy I; 789f4a2713aSLionel Sambuc }; 790f4a2713aSLionel Sambuc 791f4a2713aSLionel Sambuc class const_graph_iterator { 792f4a2713aSLionel Sambuc public: 793f4a2713aSLionel Sambuc typedef const CFGBlock value_type; 794f4a2713aSLionel Sambuc typedef value_type& reference; 795f4a2713aSLionel Sambuc typedef value_type* pointer; 796f4a2713aSLionel Sambuc typedef BumpVector<CFGBlock*>::const_iterator ImplTy; 797f4a2713aSLionel Sambuc const_graph_iterator(const ImplTy & i)798f4a2713aSLionel Sambuc const_graph_iterator(const ImplTy &i) : I(i) {} 799f4a2713aSLionel Sambuc 800f4a2713aSLionel Sambuc bool operator==(const const_graph_iterator &X) const { return I == X.I; } 801f4a2713aSLionel Sambuc bool operator!=(const const_graph_iterator &X) const { return I != X.I; } 802f4a2713aSLionel Sambuc 803f4a2713aSLionel Sambuc reference operator*() const { return **I; } 804f4a2713aSLionel Sambuc pointer operator->() const { return *I; } 805f4a2713aSLionel Sambuc operator CFGBlock* () const { return *I; } 806f4a2713aSLionel Sambuc 807f4a2713aSLionel Sambuc const_graph_iterator &operator++() { ++I; return *this; } 808f4a2713aSLionel Sambuc const_graph_iterator &operator--() { --I; return *this; } 809f4a2713aSLionel Sambuc 810f4a2713aSLionel Sambuc private: 811f4a2713aSLionel Sambuc ImplTy I; 812f4a2713aSLionel Sambuc }; 813f4a2713aSLionel Sambuc 814*0a6a1f1dSLionel Sambuc /// buildCFG - Builds a CFG from an AST. 815*0a6a1f1dSLionel Sambuc static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C, 816f4a2713aSLionel Sambuc const BuildOptions &BO); 817f4a2713aSLionel Sambuc 818f4a2713aSLionel Sambuc /// createBlock - Create a new block in the CFG. The CFG owns the block; 819f4a2713aSLionel Sambuc /// the caller should not directly free it. 820f4a2713aSLionel Sambuc CFGBlock *createBlock(); 821f4a2713aSLionel Sambuc 822f4a2713aSLionel Sambuc /// setEntry - Set the entry block of the CFG. This is typically used 823f4a2713aSLionel Sambuc /// only during CFG construction. Most CFG clients expect that the 824f4a2713aSLionel Sambuc /// entry block has no predecessors and contains no statements. setEntry(CFGBlock * B)825f4a2713aSLionel Sambuc void setEntry(CFGBlock *B) { Entry = B; } 826f4a2713aSLionel Sambuc 827f4a2713aSLionel Sambuc /// setIndirectGotoBlock - Set the block used for indirect goto jumps. 828f4a2713aSLionel Sambuc /// This is typically used only during CFG construction. setIndirectGotoBlock(CFGBlock * B)829f4a2713aSLionel Sambuc void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; } 830f4a2713aSLionel Sambuc 831f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 832f4a2713aSLionel Sambuc // Block Iterators 833f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 834f4a2713aSLionel Sambuc 835f4a2713aSLionel Sambuc typedef BumpVector<CFGBlock*> CFGBlockListTy; 836f4a2713aSLionel Sambuc typedef CFGBlockListTy::iterator iterator; 837f4a2713aSLionel Sambuc typedef CFGBlockListTy::const_iterator const_iterator; 838f4a2713aSLionel Sambuc typedef std::reverse_iterator<iterator> reverse_iterator; 839f4a2713aSLionel Sambuc typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 840f4a2713aSLionel Sambuc front()841f4a2713aSLionel Sambuc CFGBlock & front() { return *Blocks.front(); } back()842f4a2713aSLionel Sambuc CFGBlock & back() { return *Blocks.back(); } 843f4a2713aSLionel Sambuc begin()844f4a2713aSLionel Sambuc iterator begin() { return Blocks.begin(); } end()845f4a2713aSLionel Sambuc iterator end() { return Blocks.end(); } begin()846f4a2713aSLionel Sambuc const_iterator begin() const { return Blocks.begin(); } end()847f4a2713aSLionel Sambuc const_iterator end() const { return Blocks.end(); } 848f4a2713aSLionel Sambuc nodes_begin()849f4a2713aSLionel Sambuc graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); } nodes_end()850f4a2713aSLionel Sambuc graph_iterator nodes_end() { return graph_iterator(Blocks.end()); } nodes_begin()851f4a2713aSLionel Sambuc const_graph_iterator nodes_begin() const { 852f4a2713aSLionel Sambuc return const_graph_iterator(Blocks.begin()); 853f4a2713aSLionel Sambuc } nodes_end()854f4a2713aSLionel Sambuc const_graph_iterator nodes_end() const { 855f4a2713aSLionel Sambuc return const_graph_iterator(Blocks.end()); 856f4a2713aSLionel Sambuc } 857f4a2713aSLionel Sambuc rbegin()858f4a2713aSLionel Sambuc reverse_iterator rbegin() { return Blocks.rbegin(); } rend()859f4a2713aSLionel Sambuc reverse_iterator rend() { return Blocks.rend(); } rbegin()860f4a2713aSLionel Sambuc const_reverse_iterator rbegin() const { return Blocks.rbegin(); } rend()861f4a2713aSLionel Sambuc const_reverse_iterator rend() const { return Blocks.rend(); } 862f4a2713aSLionel Sambuc getEntry()863f4a2713aSLionel Sambuc CFGBlock & getEntry() { return *Entry; } getEntry()864f4a2713aSLionel Sambuc const CFGBlock & getEntry() const { return *Entry; } getExit()865f4a2713aSLionel Sambuc CFGBlock & getExit() { return *Exit; } getExit()866f4a2713aSLionel Sambuc const CFGBlock & getExit() const { return *Exit; } 867f4a2713aSLionel Sambuc getIndirectGotoBlock()868f4a2713aSLionel Sambuc CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } getIndirectGotoBlock()869f4a2713aSLionel Sambuc const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } 870f4a2713aSLionel Sambuc 871f4a2713aSLionel Sambuc typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator; try_blocks_begin()872f4a2713aSLionel Sambuc try_block_iterator try_blocks_begin() const { 873f4a2713aSLionel Sambuc return TryDispatchBlocks.begin(); 874f4a2713aSLionel Sambuc } try_blocks_end()875f4a2713aSLionel Sambuc try_block_iterator try_blocks_end() const { 876f4a2713aSLionel Sambuc return TryDispatchBlocks.end(); 877f4a2713aSLionel Sambuc } 878f4a2713aSLionel Sambuc addTryDispatchBlock(const CFGBlock * block)879f4a2713aSLionel Sambuc void addTryDispatchBlock(const CFGBlock *block) { 880f4a2713aSLionel Sambuc TryDispatchBlocks.push_back(block); 881f4a2713aSLionel Sambuc } 882f4a2713aSLionel Sambuc 883f4a2713aSLionel Sambuc /// Records a synthetic DeclStmt and the DeclStmt it was constructed from. 884f4a2713aSLionel Sambuc /// 885f4a2713aSLionel Sambuc /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains 886f4a2713aSLionel Sambuc /// multiple decls. addSyntheticDeclStmt(const DeclStmt * Synthetic,const DeclStmt * Source)887f4a2713aSLionel Sambuc void addSyntheticDeclStmt(const DeclStmt *Synthetic, 888f4a2713aSLionel Sambuc const DeclStmt *Source) { 889f4a2713aSLionel Sambuc assert(Synthetic->isSingleDecl() && "Can handle single declarations only"); 890f4a2713aSLionel Sambuc assert(Synthetic != Source && "Don't include original DeclStmts in map"); 891f4a2713aSLionel Sambuc assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map"); 892f4a2713aSLionel Sambuc SyntheticDeclStmts[Synthetic] = Source; 893f4a2713aSLionel Sambuc } 894f4a2713aSLionel Sambuc 895f4a2713aSLionel Sambuc typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator 896f4a2713aSLionel Sambuc synthetic_stmt_iterator; 897f4a2713aSLionel Sambuc 898f4a2713aSLionel Sambuc /// Iterates over synthetic DeclStmts in the CFG. 899f4a2713aSLionel Sambuc /// 900f4a2713aSLionel Sambuc /// Each element is a (synthetic statement, source statement) pair. 901f4a2713aSLionel Sambuc /// 902f4a2713aSLionel Sambuc /// \sa addSyntheticDeclStmt synthetic_stmt_begin()903f4a2713aSLionel Sambuc synthetic_stmt_iterator synthetic_stmt_begin() const { 904f4a2713aSLionel Sambuc return SyntheticDeclStmts.begin(); 905f4a2713aSLionel Sambuc } 906f4a2713aSLionel Sambuc 907f4a2713aSLionel Sambuc /// \sa synthetic_stmt_begin synthetic_stmt_end()908f4a2713aSLionel Sambuc synthetic_stmt_iterator synthetic_stmt_end() const { 909f4a2713aSLionel Sambuc return SyntheticDeclStmts.end(); 910f4a2713aSLionel Sambuc } 911f4a2713aSLionel Sambuc 912f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 913f4a2713aSLionel Sambuc // Member templates useful for various batch operations over CFGs. 914f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 915f4a2713aSLionel Sambuc 916f4a2713aSLionel Sambuc template <typename CALLBACK> VisitBlockStmts(CALLBACK & O)917f4a2713aSLionel Sambuc void VisitBlockStmts(CALLBACK& O) const { 918f4a2713aSLionel Sambuc for (const_iterator I=begin(), E=end(); I != E; ++I) 919f4a2713aSLionel Sambuc for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); 920f4a2713aSLionel Sambuc BI != BE; ++BI) { 921f4a2713aSLionel Sambuc if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>()) 922f4a2713aSLionel Sambuc O(const_cast<Stmt*>(stmt->getStmt())); 923f4a2713aSLionel Sambuc } 924f4a2713aSLionel Sambuc } 925f4a2713aSLionel Sambuc 926f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 927f4a2713aSLionel Sambuc // CFG Introspection. 928f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 929f4a2713aSLionel Sambuc 930f4a2713aSLionel Sambuc /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which 931f4a2713aSLionel Sambuc /// start at 0). getNumBlockIDs()932f4a2713aSLionel Sambuc unsigned getNumBlockIDs() const { return NumBlockIDs; } 933f4a2713aSLionel Sambuc 934f4a2713aSLionel Sambuc /// size - Return the total number of CFGBlocks within the CFG 935f4a2713aSLionel Sambuc /// This is simply a renaming of the getNumBlockIDs(). This is necessary 936f4a2713aSLionel Sambuc /// because the dominator implementation needs such an interface. size()937f4a2713aSLionel Sambuc unsigned size() const { return NumBlockIDs; } 938f4a2713aSLionel Sambuc 939f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 940f4a2713aSLionel Sambuc // CFG Debugging: Pretty-Printing and Visualization. 941f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 942f4a2713aSLionel Sambuc 943f4a2713aSLionel Sambuc void viewCFG(const LangOptions &LO) const; 944f4a2713aSLionel Sambuc void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const; 945f4a2713aSLionel Sambuc void dump(const LangOptions &LO, bool ShowColors) const; 946f4a2713aSLionel Sambuc 947f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 948f4a2713aSLionel Sambuc // Internal: constructors and data. 949f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===// 950f4a2713aSLionel Sambuc CFG()951*0a6a1f1dSLionel Sambuc CFG() 952*0a6a1f1dSLionel Sambuc : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0), 953f4a2713aSLionel Sambuc Blocks(BlkBVC, 10) {} 954f4a2713aSLionel Sambuc getAllocator()955f4a2713aSLionel Sambuc llvm::BumpPtrAllocator& getAllocator() { 956f4a2713aSLionel Sambuc return BlkBVC.getAllocator(); 957f4a2713aSLionel Sambuc } 958f4a2713aSLionel Sambuc getBumpVectorContext()959f4a2713aSLionel Sambuc BumpVectorContext &getBumpVectorContext() { 960f4a2713aSLionel Sambuc return BlkBVC; 961f4a2713aSLionel Sambuc } 962f4a2713aSLionel Sambuc 963f4a2713aSLionel Sambuc private: 964f4a2713aSLionel Sambuc CFGBlock *Entry; 965f4a2713aSLionel Sambuc CFGBlock *Exit; 966f4a2713aSLionel Sambuc CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch 967f4a2713aSLionel Sambuc // for indirect gotos 968f4a2713aSLionel Sambuc unsigned NumBlockIDs; 969f4a2713aSLionel Sambuc 970f4a2713aSLionel Sambuc BumpVectorContext BlkBVC; 971f4a2713aSLionel Sambuc 972f4a2713aSLionel Sambuc CFGBlockListTy Blocks; 973f4a2713aSLionel Sambuc 974f4a2713aSLionel Sambuc /// C++ 'try' statements are modeled with an indirect dispatch block. 975f4a2713aSLionel Sambuc /// This is the collection of such blocks present in the CFG. 976f4a2713aSLionel Sambuc std::vector<const CFGBlock *> TryDispatchBlocks; 977f4a2713aSLionel Sambuc 978f4a2713aSLionel Sambuc /// Collects DeclStmts synthesized for this CFG and maps each one back to its 979f4a2713aSLionel Sambuc /// source DeclStmt. 980f4a2713aSLionel Sambuc llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts; 981f4a2713aSLionel Sambuc }; 982f4a2713aSLionel Sambuc } // end namespace clang 983f4a2713aSLionel Sambuc 984f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 985f4a2713aSLionel Sambuc // GraphTraits specializations for CFG basic block graphs (source-level CFGs) 986f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 987f4a2713aSLionel Sambuc 988f4a2713aSLionel Sambuc namespace llvm { 989f4a2713aSLionel Sambuc 990f4a2713aSLionel Sambuc /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from 991f4a2713aSLionel Sambuc /// CFGTerminator to a specific Stmt class. 992f4a2713aSLionel Sambuc template <> struct simplify_type< ::clang::CFGTerminator> { 993f4a2713aSLionel Sambuc typedef ::clang::Stmt *SimpleType; 994f4a2713aSLionel Sambuc static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { 995f4a2713aSLionel Sambuc return Val.getStmt(); 996f4a2713aSLionel Sambuc } 997f4a2713aSLionel Sambuc }; 998f4a2713aSLionel Sambuc 999f4a2713aSLionel Sambuc // Traits for: CFGBlock 1000f4a2713aSLionel Sambuc 1001f4a2713aSLionel Sambuc template <> struct GraphTraits< ::clang::CFGBlock *> { 1002f4a2713aSLionel Sambuc typedef ::clang::CFGBlock NodeType; 1003f4a2713aSLionel Sambuc typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; 1004f4a2713aSLionel Sambuc 1005f4a2713aSLionel Sambuc static NodeType* getEntryNode(::clang::CFGBlock *BB) 1006f4a2713aSLionel Sambuc { return BB; } 1007f4a2713aSLionel Sambuc 1008f4a2713aSLionel Sambuc static inline ChildIteratorType child_begin(NodeType* N) 1009f4a2713aSLionel Sambuc { return N->succ_begin(); } 1010f4a2713aSLionel Sambuc 1011f4a2713aSLionel Sambuc static inline ChildIteratorType child_end(NodeType* N) 1012f4a2713aSLionel Sambuc { return N->succ_end(); } 1013f4a2713aSLionel Sambuc }; 1014f4a2713aSLionel Sambuc 1015f4a2713aSLionel Sambuc template <> struct GraphTraits< const ::clang::CFGBlock *> { 1016f4a2713aSLionel Sambuc typedef const ::clang::CFGBlock NodeType; 1017f4a2713aSLionel Sambuc typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; 1018f4a2713aSLionel Sambuc 1019f4a2713aSLionel Sambuc static NodeType* getEntryNode(const clang::CFGBlock *BB) 1020f4a2713aSLionel Sambuc { return BB; } 1021f4a2713aSLionel Sambuc 1022f4a2713aSLionel Sambuc static inline ChildIteratorType child_begin(NodeType* N) 1023f4a2713aSLionel Sambuc { return N->succ_begin(); } 1024f4a2713aSLionel Sambuc 1025f4a2713aSLionel Sambuc static inline ChildIteratorType child_end(NodeType* N) 1026f4a2713aSLionel Sambuc { return N->succ_end(); } 1027f4a2713aSLionel Sambuc }; 1028f4a2713aSLionel Sambuc 1029f4a2713aSLionel Sambuc template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > { 1030f4a2713aSLionel Sambuc typedef ::clang::CFGBlock NodeType; 1031f4a2713aSLionel Sambuc typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; 1032f4a2713aSLionel Sambuc 1033f4a2713aSLionel Sambuc static NodeType *getEntryNode(Inverse< ::clang::CFGBlock*> G) 1034f4a2713aSLionel Sambuc { return G.Graph; } 1035f4a2713aSLionel Sambuc 1036f4a2713aSLionel Sambuc static inline ChildIteratorType child_begin(NodeType* N) 1037f4a2713aSLionel Sambuc { return N->pred_begin(); } 1038f4a2713aSLionel Sambuc 1039f4a2713aSLionel Sambuc static inline ChildIteratorType child_end(NodeType* N) 1040f4a2713aSLionel Sambuc { return N->pred_end(); } 1041f4a2713aSLionel Sambuc }; 1042f4a2713aSLionel Sambuc 1043f4a2713aSLionel Sambuc template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { 1044f4a2713aSLionel Sambuc typedef const ::clang::CFGBlock NodeType; 1045f4a2713aSLionel Sambuc typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; 1046f4a2713aSLionel Sambuc 1047f4a2713aSLionel Sambuc static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G) 1048f4a2713aSLionel Sambuc { return G.Graph; } 1049f4a2713aSLionel Sambuc 1050f4a2713aSLionel Sambuc static inline ChildIteratorType child_begin(NodeType* N) 1051f4a2713aSLionel Sambuc { return N->pred_begin(); } 1052f4a2713aSLionel Sambuc 1053f4a2713aSLionel Sambuc static inline ChildIteratorType child_end(NodeType* N) 1054f4a2713aSLionel Sambuc { return N->pred_end(); } 1055f4a2713aSLionel Sambuc }; 1056f4a2713aSLionel Sambuc 1057f4a2713aSLionel Sambuc // Traits for: CFG 1058f4a2713aSLionel Sambuc 1059f4a2713aSLionel Sambuc template <> struct GraphTraits< ::clang::CFG* > 1060f4a2713aSLionel Sambuc : public GraphTraits< ::clang::CFGBlock *> { 1061f4a2713aSLionel Sambuc 1062f4a2713aSLionel Sambuc typedef ::clang::CFG::graph_iterator nodes_iterator; 1063f4a2713aSLionel Sambuc 1064f4a2713aSLionel Sambuc static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); } 1065f4a2713aSLionel Sambuc static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} 1066f4a2713aSLionel Sambuc static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); } 1067f4a2713aSLionel Sambuc static unsigned size(::clang::CFG* F) { return F->size(); } 1068f4a2713aSLionel Sambuc }; 1069f4a2713aSLionel Sambuc 1070f4a2713aSLionel Sambuc template <> struct GraphTraits<const ::clang::CFG* > 1071f4a2713aSLionel Sambuc : public GraphTraits<const ::clang::CFGBlock *> { 1072f4a2713aSLionel Sambuc 1073f4a2713aSLionel Sambuc typedef ::clang::CFG::const_graph_iterator nodes_iterator; 1074f4a2713aSLionel Sambuc 1075f4a2713aSLionel Sambuc static NodeType *getEntryNode( const ::clang::CFG* F) { 1076f4a2713aSLionel Sambuc return &F->getEntry(); 1077f4a2713aSLionel Sambuc } 1078f4a2713aSLionel Sambuc static nodes_iterator nodes_begin( const ::clang::CFG* F) { 1079f4a2713aSLionel Sambuc return F->nodes_begin(); 1080f4a2713aSLionel Sambuc } 1081f4a2713aSLionel Sambuc static nodes_iterator nodes_end( const ::clang::CFG* F) { 1082f4a2713aSLionel Sambuc return F->nodes_end(); 1083f4a2713aSLionel Sambuc } 1084f4a2713aSLionel Sambuc static unsigned size(const ::clang::CFG* F) { 1085f4a2713aSLionel Sambuc return F->size(); 1086f4a2713aSLionel Sambuc } 1087f4a2713aSLionel Sambuc }; 1088f4a2713aSLionel Sambuc 1089f4a2713aSLionel Sambuc template <> struct GraphTraits<Inverse< ::clang::CFG*> > 1090f4a2713aSLionel Sambuc : public GraphTraits<Inverse< ::clang::CFGBlock*> > { 1091f4a2713aSLionel Sambuc 1092f4a2713aSLionel Sambuc typedef ::clang::CFG::graph_iterator nodes_iterator; 1093f4a2713aSLionel Sambuc 1094f4a2713aSLionel Sambuc static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); } 1095f4a2713aSLionel Sambuc static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} 1096f4a2713aSLionel Sambuc static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } 1097f4a2713aSLionel Sambuc }; 1098f4a2713aSLionel Sambuc 1099f4a2713aSLionel Sambuc template <> struct GraphTraits<Inverse<const ::clang::CFG*> > 1100f4a2713aSLionel Sambuc : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { 1101f4a2713aSLionel Sambuc 1102f4a2713aSLionel Sambuc typedef ::clang::CFG::const_graph_iterator nodes_iterator; 1103f4a2713aSLionel Sambuc 1104f4a2713aSLionel Sambuc static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); } 1105f4a2713aSLionel Sambuc static nodes_iterator nodes_begin(const ::clang::CFG* F) { 1106f4a2713aSLionel Sambuc return F->nodes_begin(); 1107f4a2713aSLionel Sambuc } 1108f4a2713aSLionel Sambuc static nodes_iterator nodes_end(const ::clang::CFG* F) { 1109f4a2713aSLionel Sambuc return F->nodes_end(); 1110f4a2713aSLionel Sambuc } 1111f4a2713aSLionel Sambuc }; 1112f4a2713aSLionel Sambuc } // end llvm namespace 1113f4a2713aSLionel Sambuc #endif 1114