xref: /minix3/external/bsd/llvm/dist/clang/include/clang/Analysis/CFG.h (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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