1f4a2713aSLionel Sambuc //===--- CFG.cpp - 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
15f4a2713aSLionel Sambuc #include "clang/Analysis/CFG.h"
16f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
17f4a2713aSLionel Sambuc #include "clang/AST/Attr.h"
18f4a2713aSLionel Sambuc #include "clang/AST/CharUnits.h"
19f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
20f4a2713aSLionel Sambuc #include "clang/AST/PrettyPrinter.h"
21f4a2713aSLionel Sambuc #include "clang/AST/StmtVisitor.h"
22f4a2713aSLionel Sambuc #include "clang/Basic/Builtins.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/DenseMap.h"
24*0a6a1f1dSLionel Sambuc #include <memory>
25f4a2713aSLionel Sambuc #include "llvm/ADT/SmallPtrSet.h"
26f4a2713aSLionel Sambuc #include "llvm/Support/Allocator.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/GraphWriter.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/SaveAndRestore.h"
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc using namespace clang;
32f4a2713aSLionel Sambuc
33f4a2713aSLionel Sambuc namespace {
34f4a2713aSLionel Sambuc
GetEndLoc(Decl * D)35f4a2713aSLionel Sambuc static SourceLocation GetEndLoc(Decl *D) {
36f4a2713aSLionel Sambuc if (VarDecl *VD = dyn_cast<VarDecl>(D))
37f4a2713aSLionel Sambuc if (Expr *Ex = VD->getInit())
38f4a2713aSLionel Sambuc return Ex->getSourceRange().getEnd();
39f4a2713aSLionel Sambuc return D->getLocation();
40f4a2713aSLionel Sambuc }
41f4a2713aSLionel Sambuc
42f4a2713aSLionel Sambuc class CFGBuilder;
43f4a2713aSLionel Sambuc
44f4a2713aSLionel Sambuc /// The CFG builder uses a recursive algorithm to build the CFG. When
45f4a2713aSLionel Sambuc /// we process an expression, sometimes we know that we must add the
46f4a2713aSLionel Sambuc /// subexpressions as block-level expressions. For example:
47f4a2713aSLionel Sambuc ///
48f4a2713aSLionel Sambuc /// exp1 || exp2
49f4a2713aSLionel Sambuc ///
50f4a2713aSLionel Sambuc /// When processing the '||' expression, we know that exp1 and exp2
51f4a2713aSLionel Sambuc /// need to be added as block-level expressions, even though they
52f4a2713aSLionel Sambuc /// might not normally need to be. AddStmtChoice records this
53f4a2713aSLionel Sambuc /// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then
54f4a2713aSLionel Sambuc /// the builder has an option not to add a subexpression as a
55f4a2713aSLionel Sambuc /// block-level expression.
56f4a2713aSLionel Sambuc ///
57f4a2713aSLionel Sambuc class AddStmtChoice {
58f4a2713aSLionel Sambuc public:
59f4a2713aSLionel Sambuc enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
60f4a2713aSLionel Sambuc
AddStmtChoice(Kind a_kind=NotAlwaysAdd)61f4a2713aSLionel Sambuc AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuc bool alwaysAdd(CFGBuilder &builder,
64f4a2713aSLionel Sambuc const Stmt *stmt) const;
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc /// Return a copy of this object, except with the 'always-add' bit
67f4a2713aSLionel Sambuc /// set as specified.
withAlwaysAdd(bool alwaysAdd) const68f4a2713aSLionel Sambuc AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {
69f4a2713aSLionel Sambuc return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
70f4a2713aSLionel Sambuc }
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc private:
73f4a2713aSLionel Sambuc Kind kind;
74f4a2713aSLionel Sambuc };
75f4a2713aSLionel Sambuc
76f4a2713aSLionel Sambuc /// LocalScope - Node in tree of local scopes created for C++ implicit
77f4a2713aSLionel Sambuc /// destructor calls generation. It contains list of automatic variables
78f4a2713aSLionel Sambuc /// declared in the scope and link to position in previous scope this scope
79f4a2713aSLionel Sambuc /// began in.
80f4a2713aSLionel Sambuc ///
81f4a2713aSLionel Sambuc /// The process of creating local scopes is as follows:
82f4a2713aSLionel Sambuc /// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),
83f4a2713aSLionel Sambuc /// - Before processing statements in scope (e.g. CompoundStmt) create
84f4a2713aSLionel Sambuc /// LocalScope object using CFGBuilder::ScopePos as link to previous scope
85f4a2713aSLionel Sambuc /// and set CFGBuilder::ScopePos to the end of new scope,
86f4a2713aSLionel Sambuc /// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points
87f4a2713aSLionel Sambuc /// at this VarDecl,
88f4a2713aSLionel Sambuc /// - For every normal (without jump) end of scope add to CFGBlock destructors
89f4a2713aSLionel Sambuc /// for objects in the current scope,
90f4a2713aSLionel Sambuc /// - For every jump add to CFGBlock destructors for objects
91f4a2713aSLionel Sambuc /// between CFGBuilder::ScopePos and local scope position saved for jump
92f4a2713aSLionel Sambuc /// target. Thanks to C++ restrictions on goto jumps we can be sure that
93f4a2713aSLionel Sambuc /// jump target position will be on the path to root from CFGBuilder::ScopePos
94f4a2713aSLionel Sambuc /// (adding any variable that doesn't need constructor to be called to
95f4a2713aSLionel Sambuc /// LocalScope can break this assumption),
96f4a2713aSLionel Sambuc ///
97f4a2713aSLionel Sambuc class LocalScope {
98f4a2713aSLionel Sambuc public:
99f4a2713aSLionel Sambuc typedef BumpVector<VarDecl*> AutomaticVarsTy;
100f4a2713aSLionel Sambuc
101f4a2713aSLionel Sambuc /// const_iterator - Iterates local scope backwards and jumps to previous
102f4a2713aSLionel Sambuc /// scope on reaching the beginning of currently iterated scope.
103f4a2713aSLionel Sambuc class const_iterator {
104f4a2713aSLionel Sambuc const LocalScope* Scope;
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc /// VarIter is guaranteed to be greater then 0 for every valid iterator.
107f4a2713aSLionel Sambuc /// Invalid iterator (with null Scope) has VarIter equal to 0.
108f4a2713aSLionel Sambuc unsigned VarIter;
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc public:
111f4a2713aSLionel Sambuc /// Create invalid iterator. Dereferencing invalid iterator is not allowed.
112f4a2713aSLionel Sambuc /// Incrementing invalid iterator is allowed and will result in invalid
113f4a2713aSLionel Sambuc /// iterator.
const_iterator()114f4a2713aSLionel Sambuc const_iterator()
115*0a6a1f1dSLionel Sambuc : Scope(nullptr), VarIter(0) {}
116f4a2713aSLionel Sambuc
117f4a2713aSLionel Sambuc /// Create valid iterator. In case when S.Prev is an invalid iterator and
118f4a2713aSLionel Sambuc /// I is equal to 0, this will create invalid iterator.
const_iterator(const LocalScope & S,unsigned I)119f4a2713aSLionel Sambuc const_iterator(const LocalScope& S, unsigned I)
120f4a2713aSLionel Sambuc : Scope(&S), VarIter(I) {
121f4a2713aSLionel Sambuc // Iterator to "end" of scope is not allowed. Handle it by going up
122f4a2713aSLionel Sambuc // in scopes tree possibly up to invalid iterator in the root.
123f4a2713aSLionel Sambuc if (VarIter == 0 && Scope)
124f4a2713aSLionel Sambuc *this = Scope->Prev;
125f4a2713aSLionel Sambuc }
126f4a2713aSLionel Sambuc
operator ->() const127f4a2713aSLionel Sambuc VarDecl *const* operator->() const {
128f4a2713aSLionel Sambuc assert (Scope && "Dereferencing invalid iterator is not allowed");
129f4a2713aSLionel Sambuc assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
130f4a2713aSLionel Sambuc return &Scope->Vars[VarIter - 1];
131f4a2713aSLionel Sambuc }
operator *() const132f4a2713aSLionel Sambuc VarDecl *operator*() const {
133f4a2713aSLionel Sambuc return *this->operator->();
134f4a2713aSLionel Sambuc }
135f4a2713aSLionel Sambuc
operator ++()136f4a2713aSLionel Sambuc const_iterator &operator++() {
137f4a2713aSLionel Sambuc if (!Scope)
138f4a2713aSLionel Sambuc return *this;
139f4a2713aSLionel Sambuc
140f4a2713aSLionel Sambuc assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
141f4a2713aSLionel Sambuc --VarIter;
142f4a2713aSLionel Sambuc if (VarIter == 0)
143f4a2713aSLionel Sambuc *this = Scope->Prev;
144f4a2713aSLionel Sambuc return *this;
145f4a2713aSLionel Sambuc }
operator ++(int)146f4a2713aSLionel Sambuc const_iterator operator++(int) {
147f4a2713aSLionel Sambuc const_iterator P = *this;
148f4a2713aSLionel Sambuc ++*this;
149f4a2713aSLionel Sambuc return P;
150f4a2713aSLionel Sambuc }
151f4a2713aSLionel Sambuc
operator ==(const const_iterator & rhs) const152f4a2713aSLionel Sambuc bool operator==(const const_iterator &rhs) const {
153f4a2713aSLionel Sambuc return Scope == rhs.Scope && VarIter == rhs.VarIter;
154f4a2713aSLionel Sambuc }
operator !=(const const_iterator & rhs) const155f4a2713aSLionel Sambuc bool operator!=(const const_iterator &rhs) const {
156f4a2713aSLionel Sambuc return !(*this == rhs);
157f4a2713aSLionel Sambuc }
158f4a2713aSLionel Sambuc
operator bool() const159f4a2713aSLionel Sambuc LLVM_EXPLICIT operator bool() const {
160f4a2713aSLionel Sambuc return *this != const_iterator();
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc
163f4a2713aSLionel Sambuc int distance(const_iterator L);
164f4a2713aSLionel Sambuc };
165f4a2713aSLionel Sambuc
166f4a2713aSLionel Sambuc friend class const_iterator;
167f4a2713aSLionel Sambuc
168f4a2713aSLionel Sambuc private:
169f4a2713aSLionel Sambuc BumpVectorContext ctx;
170f4a2713aSLionel Sambuc
171f4a2713aSLionel Sambuc /// Automatic variables in order of declaration.
172f4a2713aSLionel Sambuc AutomaticVarsTy Vars;
173f4a2713aSLionel Sambuc /// Iterator to variable in previous scope that was declared just before
174f4a2713aSLionel Sambuc /// begin of this scope.
175f4a2713aSLionel Sambuc const_iterator Prev;
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc public:
178f4a2713aSLionel Sambuc /// Constructs empty scope linked to previous scope in specified place.
LocalScope(BumpVectorContext & ctx,const_iterator P)179f4a2713aSLionel Sambuc LocalScope(BumpVectorContext &ctx, const_iterator P)
180f4a2713aSLionel Sambuc : ctx(ctx), Vars(ctx, 4), Prev(P) {}
181f4a2713aSLionel Sambuc
182f4a2713aSLionel Sambuc /// Begin of scope in direction of CFG building (backwards).
begin() const183f4a2713aSLionel Sambuc const_iterator begin() const { return const_iterator(*this, Vars.size()); }
184f4a2713aSLionel Sambuc
addVar(VarDecl * VD)185f4a2713aSLionel Sambuc void addVar(VarDecl *VD) {
186f4a2713aSLionel Sambuc Vars.push_back(VD, ctx);
187f4a2713aSLionel Sambuc }
188f4a2713aSLionel Sambuc };
189f4a2713aSLionel Sambuc
190f4a2713aSLionel Sambuc /// distance - Calculates distance from this to L. L must be reachable from this
191f4a2713aSLionel Sambuc /// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.
192f4a2713aSLionel Sambuc /// number of scopes between this and L.
distance(LocalScope::const_iterator L)193f4a2713aSLionel Sambuc int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
194f4a2713aSLionel Sambuc int D = 0;
195f4a2713aSLionel Sambuc const_iterator F = *this;
196f4a2713aSLionel Sambuc while (F.Scope != L.Scope) {
197f4a2713aSLionel Sambuc assert (F != const_iterator()
198f4a2713aSLionel Sambuc && "L iterator is not reachable from F iterator.");
199f4a2713aSLionel Sambuc D += F.VarIter;
200f4a2713aSLionel Sambuc F = F.Scope->Prev;
201f4a2713aSLionel Sambuc }
202f4a2713aSLionel Sambuc D += F.VarIter - L.VarIter;
203f4a2713aSLionel Sambuc return D;
204f4a2713aSLionel Sambuc }
205f4a2713aSLionel Sambuc
206f4a2713aSLionel Sambuc /// BlockScopePosPair - Structure for specifying position in CFG during its
207f4a2713aSLionel Sambuc /// build process. It consists of CFGBlock that specifies position in CFG graph
208f4a2713aSLionel Sambuc /// and LocalScope::const_iterator that specifies position in LocalScope graph.
209f4a2713aSLionel Sambuc struct BlockScopePosPair {
BlockScopePosPair__anon557f5a500111::BlockScopePosPair210*0a6a1f1dSLionel Sambuc BlockScopePosPair() : block(nullptr) {}
BlockScopePosPair__anon557f5a500111::BlockScopePosPair211f4a2713aSLionel Sambuc BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
212f4a2713aSLionel Sambuc : block(b), scopePosition(scopePos) {}
213f4a2713aSLionel Sambuc
214f4a2713aSLionel Sambuc CFGBlock *block;
215f4a2713aSLionel Sambuc LocalScope::const_iterator scopePosition;
216f4a2713aSLionel Sambuc };
217f4a2713aSLionel Sambuc
218f4a2713aSLionel Sambuc /// TryResult - a class representing a variant over the values
219f4a2713aSLionel Sambuc /// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool,
220f4a2713aSLionel Sambuc /// and is used by the CFGBuilder to decide if a branch condition
221f4a2713aSLionel Sambuc /// can be decided up front during CFG construction.
222f4a2713aSLionel Sambuc class TryResult {
223f4a2713aSLionel Sambuc int X;
224f4a2713aSLionel Sambuc public:
TryResult(bool b)225f4a2713aSLionel Sambuc TryResult(bool b) : X(b ? 1 : 0) {}
TryResult()226f4a2713aSLionel Sambuc TryResult() : X(-1) {}
227f4a2713aSLionel Sambuc
isTrue() const228f4a2713aSLionel Sambuc bool isTrue() const { return X == 1; }
isFalse() const229f4a2713aSLionel Sambuc bool isFalse() const { return X == 0; }
isKnown() const230f4a2713aSLionel Sambuc bool isKnown() const { return X >= 0; }
negate()231f4a2713aSLionel Sambuc void negate() {
232f4a2713aSLionel Sambuc assert(isKnown());
233f4a2713aSLionel Sambuc X ^= 0x1;
234f4a2713aSLionel Sambuc }
235f4a2713aSLionel Sambuc };
236f4a2713aSLionel Sambuc
bothKnownTrue(TryResult R1,TryResult R2)237*0a6a1f1dSLionel Sambuc TryResult bothKnownTrue(TryResult R1, TryResult R2) {
238*0a6a1f1dSLionel Sambuc if (!R1.isKnown() || !R2.isKnown())
239*0a6a1f1dSLionel Sambuc return TryResult();
240*0a6a1f1dSLionel Sambuc return TryResult(R1.isTrue() && R2.isTrue());
241*0a6a1f1dSLionel Sambuc }
242*0a6a1f1dSLionel Sambuc
243f4a2713aSLionel Sambuc class reverse_children {
244f4a2713aSLionel Sambuc llvm::SmallVector<Stmt *, 12> childrenBuf;
245f4a2713aSLionel Sambuc ArrayRef<Stmt*> children;
246f4a2713aSLionel Sambuc public:
247f4a2713aSLionel Sambuc reverse_children(Stmt *S);
248f4a2713aSLionel Sambuc
249f4a2713aSLionel Sambuc typedef ArrayRef<Stmt*>::reverse_iterator iterator;
begin() const250f4a2713aSLionel Sambuc iterator begin() const { return children.rbegin(); }
end() const251f4a2713aSLionel Sambuc iterator end() const { return children.rend(); }
252f4a2713aSLionel Sambuc };
253f4a2713aSLionel Sambuc
254f4a2713aSLionel Sambuc
reverse_children(Stmt * S)255f4a2713aSLionel Sambuc reverse_children::reverse_children(Stmt *S) {
256f4a2713aSLionel Sambuc if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
257f4a2713aSLionel Sambuc children = CE->getRawSubExprs();
258f4a2713aSLionel Sambuc return;
259f4a2713aSLionel Sambuc }
260f4a2713aSLionel Sambuc switch (S->getStmtClass()) {
261f4a2713aSLionel Sambuc // Note: Fill in this switch with more cases we want to optimize.
262f4a2713aSLionel Sambuc case Stmt::InitListExprClass: {
263f4a2713aSLionel Sambuc InitListExpr *IE = cast<InitListExpr>(S);
264f4a2713aSLionel Sambuc children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()),
265f4a2713aSLionel Sambuc IE->getNumInits());
266f4a2713aSLionel Sambuc return;
267f4a2713aSLionel Sambuc }
268f4a2713aSLionel Sambuc default:
269f4a2713aSLionel Sambuc break;
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc
272f4a2713aSLionel Sambuc // Default case for all other statements.
273f4a2713aSLionel Sambuc for (Stmt::child_range I = S->children(); I; ++I) {
274f4a2713aSLionel Sambuc childrenBuf.push_back(*I);
275f4a2713aSLionel Sambuc }
276f4a2713aSLionel Sambuc
277f4a2713aSLionel Sambuc // This needs to be done *after* childrenBuf has been populated.
278f4a2713aSLionel Sambuc children = childrenBuf;
279f4a2713aSLionel Sambuc }
280f4a2713aSLionel Sambuc
281f4a2713aSLionel Sambuc /// CFGBuilder - This class implements CFG construction from an AST.
282f4a2713aSLionel Sambuc /// The builder is stateful: an instance of the builder should be used to only
283f4a2713aSLionel Sambuc /// construct a single CFG.
284f4a2713aSLionel Sambuc ///
285f4a2713aSLionel Sambuc /// Example usage:
286f4a2713aSLionel Sambuc ///
287f4a2713aSLionel Sambuc /// CFGBuilder builder;
288f4a2713aSLionel Sambuc /// CFG* cfg = builder.BuildAST(stmt1);
289f4a2713aSLionel Sambuc ///
290f4a2713aSLionel Sambuc /// CFG construction is done via a recursive walk of an AST. We actually parse
291f4a2713aSLionel Sambuc /// the AST in reverse order so that the successor of a basic block is
292f4a2713aSLionel Sambuc /// constructed prior to its predecessor. This allows us to nicely capture
293f4a2713aSLionel Sambuc /// implicit fall-throughs without extra basic blocks.
294f4a2713aSLionel Sambuc ///
295f4a2713aSLionel Sambuc class CFGBuilder {
296f4a2713aSLionel Sambuc typedef BlockScopePosPair JumpTarget;
297f4a2713aSLionel Sambuc typedef BlockScopePosPair JumpSource;
298f4a2713aSLionel Sambuc
299f4a2713aSLionel Sambuc ASTContext *Context;
300*0a6a1f1dSLionel Sambuc std::unique_ptr<CFG> cfg;
301f4a2713aSLionel Sambuc
302f4a2713aSLionel Sambuc CFGBlock *Block;
303f4a2713aSLionel Sambuc CFGBlock *Succ;
304f4a2713aSLionel Sambuc JumpTarget ContinueJumpTarget;
305f4a2713aSLionel Sambuc JumpTarget BreakJumpTarget;
306f4a2713aSLionel Sambuc CFGBlock *SwitchTerminatedBlock;
307f4a2713aSLionel Sambuc CFGBlock *DefaultCaseBlock;
308f4a2713aSLionel Sambuc CFGBlock *TryTerminatedBlock;
309f4a2713aSLionel Sambuc
310f4a2713aSLionel Sambuc // Current position in local scope.
311f4a2713aSLionel Sambuc LocalScope::const_iterator ScopePos;
312f4a2713aSLionel Sambuc
313f4a2713aSLionel Sambuc // LabelMap records the mapping from Label expressions to their jump targets.
314f4a2713aSLionel Sambuc typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
315f4a2713aSLionel Sambuc LabelMapTy LabelMap;
316f4a2713aSLionel Sambuc
317f4a2713aSLionel Sambuc // A list of blocks that end with a "goto" that must be backpatched to their
318f4a2713aSLionel Sambuc // resolved targets upon completion of CFG construction.
319f4a2713aSLionel Sambuc typedef std::vector<JumpSource> BackpatchBlocksTy;
320f4a2713aSLionel Sambuc BackpatchBlocksTy BackpatchBlocks;
321f4a2713aSLionel Sambuc
322f4a2713aSLionel Sambuc // A list of labels whose address has been taken (for indirect gotos).
323f4a2713aSLionel Sambuc typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
324f4a2713aSLionel Sambuc LabelSetTy AddressTakenLabels;
325f4a2713aSLionel Sambuc
326f4a2713aSLionel Sambuc bool badCFG;
327f4a2713aSLionel Sambuc const CFG::BuildOptions &BuildOpts;
328f4a2713aSLionel Sambuc
329f4a2713aSLionel Sambuc // State to track for building switch statements.
330f4a2713aSLionel Sambuc bool switchExclusivelyCovered;
331f4a2713aSLionel Sambuc Expr::EvalResult *switchCond;
332f4a2713aSLionel Sambuc
333f4a2713aSLionel Sambuc CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
334f4a2713aSLionel Sambuc const Stmt *lastLookup;
335f4a2713aSLionel Sambuc
336f4a2713aSLionel Sambuc // Caches boolean evaluations of expressions to avoid multiple re-evaluations
337f4a2713aSLionel Sambuc // during construction of branches for chained logical operators.
338f4a2713aSLionel Sambuc typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy;
339f4a2713aSLionel Sambuc CachedBoolEvalsTy CachedBoolEvals;
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc public:
CFGBuilder(ASTContext * astContext,const CFG::BuildOptions & buildOpts)342f4a2713aSLionel Sambuc explicit CFGBuilder(ASTContext *astContext,
343f4a2713aSLionel Sambuc const CFG::BuildOptions &buildOpts)
344f4a2713aSLionel Sambuc : Context(astContext), cfg(new CFG()), // crew a new CFG
345*0a6a1f1dSLionel Sambuc Block(nullptr), Succ(nullptr),
346*0a6a1f1dSLionel Sambuc SwitchTerminatedBlock(nullptr), DefaultCaseBlock(nullptr),
347*0a6a1f1dSLionel Sambuc TryTerminatedBlock(nullptr), badCFG(false), BuildOpts(buildOpts),
348*0a6a1f1dSLionel Sambuc switchExclusivelyCovered(false), switchCond(nullptr),
349*0a6a1f1dSLionel Sambuc cachedEntry(nullptr), lastLookup(nullptr) {}
350f4a2713aSLionel Sambuc
351f4a2713aSLionel Sambuc // buildCFG - Used by external clients to construct the CFG.
352*0a6a1f1dSLionel Sambuc std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);
353f4a2713aSLionel Sambuc
354f4a2713aSLionel Sambuc bool alwaysAdd(const Stmt *stmt);
355f4a2713aSLionel Sambuc
356f4a2713aSLionel Sambuc private:
357f4a2713aSLionel Sambuc // Visitors to walk an AST and construct the CFG.
358f4a2713aSLionel Sambuc CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
359f4a2713aSLionel Sambuc CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
360f4a2713aSLionel Sambuc CFGBlock *VisitBreakStmt(BreakStmt *B);
361f4a2713aSLionel Sambuc CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
362f4a2713aSLionel Sambuc CFGBlock *VisitCaseStmt(CaseStmt *C);
363f4a2713aSLionel Sambuc CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
364f4a2713aSLionel Sambuc CFGBlock *VisitCompoundStmt(CompoundStmt *C);
365f4a2713aSLionel Sambuc CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,
366f4a2713aSLionel Sambuc AddStmtChoice asc);
367f4a2713aSLionel Sambuc CFGBlock *VisitContinueStmt(ContinueStmt *C);
368f4a2713aSLionel Sambuc CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
369f4a2713aSLionel Sambuc AddStmtChoice asc);
370f4a2713aSLionel Sambuc CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
371f4a2713aSLionel Sambuc CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
372*0a6a1f1dSLionel Sambuc CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
373f4a2713aSLionel Sambuc CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
374f4a2713aSLionel Sambuc CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
375f4a2713aSLionel Sambuc CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
376f4a2713aSLionel Sambuc AddStmtChoice asc);
377f4a2713aSLionel Sambuc CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
378f4a2713aSLionel Sambuc AddStmtChoice asc);
379f4a2713aSLionel Sambuc CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
380f4a2713aSLionel Sambuc CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
381f4a2713aSLionel Sambuc CFGBlock *VisitDeclStmt(DeclStmt *DS);
382f4a2713aSLionel Sambuc CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
383f4a2713aSLionel Sambuc CFGBlock *VisitDefaultStmt(DefaultStmt *D);
384f4a2713aSLionel Sambuc CFGBlock *VisitDoStmt(DoStmt *D);
385f4a2713aSLionel Sambuc CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc);
386f4a2713aSLionel Sambuc CFGBlock *VisitForStmt(ForStmt *F);
387f4a2713aSLionel Sambuc CFGBlock *VisitGotoStmt(GotoStmt *G);
388f4a2713aSLionel Sambuc CFGBlock *VisitIfStmt(IfStmt *I);
389f4a2713aSLionel Sambuc CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
390f4a2713aSLionel Sambuc CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
391f4a2713aSLionel Sambuc CFGBlock *VisitLabelStmt(LabelStmt *L);
392f4a2713aSLionel Sambuc CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
393f4a2713aSLionel Sambuc CFGBlock *VisitLogicalOperator(BinaryOperator *B);
394f4a2713aSLionel Sambuc std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
395f4a2713aSLionel Sambuc Stmt *Term,
396f4a2713aSLionel Sambuc CFGBlock *TrueBlock,
397f4a2713aSLionel Sambuc CFGBlock *FalseBlock);
398f4a2713aSLionel Sambuc CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
399f4a2713aSLionel Sambuc CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
400f4a2713aSLionel Sambuc CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
401f4a2713aSLionel Sambuc CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
402f4a2713aSLionel Sambuc CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
403f4a2713aSLionel Sambuc CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
404f4a2713aSLionel Sambuc CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
405f4a2713aSLionel Sambuc CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
406f4a2713aSLionel Sambuc CFGBlock *VisitReturnStmt(ReturnStmt *R);
407f4a2713aSLionel Sambuc CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
408f4a2713aSLionel Sambuc CFGBlock *VisitSwitchStmt(SwitchStmt *S);
409f4a2713aSLionel Sambuc CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
410f4a2713aSLionel Sambuc AddStmtChoice asc);
411f4a2713aSLionel Sambuc CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
412f4a2713aSLionel Sambuc CFGBlock *VisitWhileStmt(WhileStmt *W);
413f4a2713aSLionel Sambuc
414f4a2713aSLionel Sambuc CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
415f4a2713aSLionel Sambuc CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
416f4a2713aSLionel Sambuc CFGBlock *VisitChildren(Stmt *S);
417f4a2713aSLionel Sambuc CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
418f4a2713aSLionel Sambuc
419*0a6a1f1dSLionel Sambuc /// When creating the CFG for temporary destructors, we want to mirror the
420*0a6a1f1dSLionel Sambuc /// branch structure of the corresponding constructor calls.
421*0a6a1f1dSLionel Sambuc /// Thus, while visiting a statement for temporary destructors, we keep a
422*0a6a1f1dSLionel Sambuc /// context to keep track of the following information:
423*0a6a1f1dSLionel Sambuc /// - whether a subexpression is executed unconditionally
424*0a6a1f1dSLionel Sambuc /// - if a subexpression is executed conditionally, the first
425*0a6a1f1dSLionel Sambuc /// CXXBindTemporaryExpr we encounter in that subexpression (which
426*0a6a1f1dSLionel Sambuc /// corresponds to the last temporary destructor we have to call for this
427*0a6a1f1dSLionel Sambuc /// subexpression) and the CFG block at that point (which will become the
428*0a6a1f1dSLionel Sambuc /// successor block when inserting the decision point).
429*0a6a1f1dSLionel Sambuc ///
430*0a6a1f1dSLionel Sambuc /// That way, we can build the branch structure for temporary destructors as
431*0a6a1f1dSLionel Sambuc /// follows:
432*0a6a1f1dSLionel Sambuc /// 1. If a subexpression is executed unconditionally, we add the temporary
433*0a6a1f1dSLionel Sambuc /// destructor calls to the current block.
434*0a6a1f1dSLionel Sambuc /// 2. If a subexpression is executed conditionally, when we encounter a
435*0a6a1f1dSLionel Sambuc /// CXXBindTemporaryExpr:
436*0a6a1f1dSLionel Sambuc /// a) If it is the first temporary destructor call in the subexpression,
437*0a6a1f1dSLionel Sambuc /// we remember the CXXBindTemporaryExpr and the current block in the
438*0a6a1f1dSLionel Sambuc /// TempDtorContext; we start a new block, and insert the temporary
439*0a6a1f1dSLionel Sambuc /// destructor call.
440*0a6a1f1dSLionel Sambuc /// b) Otherwise, add the temporary destructor call to the current block.
441*0a6a1f1dSLionel Sambuc /// 3. When we finished visiting a conditionally executed subexpression,
442*0a6a1f1dSLionel Sambuc /// and we found at least one temporary constructor during the visitation
443*0a6a1f1dSLionel Sambuc /// (2.a has executed), we insert a decision block that uses the
444*0a6a1f1dSLionel Sambuc /// CXXBindTemporaryExpr as terminator, and branches to the current block
445*0a6a1f1dSLionel Sambuc /// if the CXXBindTemporaryExpr was marked executed, and otherwise
446*0a6a1f1dSLionel Sambuc /// branches to the stored successor.
447*0a6a1f1dSLionel Sambuc struct TempDtorContext {
TempDtorContext__anon557f5a500111::CFGBuilder::TempDtorContext448*0a6a1f1dSLionel Sambuc TempDtorContext()
449*0a6a1f1dSLionel Sambuc : IsConditional(false), KnownExecuted(true), Succ(nullptr),
450*0a6a1f1dSLionel Sambuc TerminatorExpr(nullptr) {}
451*0a6a1f1dSLionel Sambuc
TempDtorContext__anon557f5a500111::CFGBuilder::TempDtorContext452*0a6a1f1dSLionel Sambuc TempDtorContext(TryResult KnownExecuted)
453*0a6a1f1dSLionel Sambuc : IsConditional(true), KnownExecuted(KnownExecuted), Succ(nullptr),
454*0a6a1f1dSLionel Sambuc TerminatorExpr(nullptr) {}
455*0a6a1f1dSLionel Sambuc
456*0a6a1f1dSLionel Sambuc /// Returns whether we need to start a new branch for a temporary destructor
457*0a6a1f1dSLionel Sambuc /// call. This is the case when the the temporary destructor is
458*0a6a1f1dSLionel Sambuc /// conditionally executed, and it is the first one we encounter while
459*0a6a1f1dSLionel Sambuc /// visiting a subexpression - other temporary destructors at the same level
460*0a6a1f1dSLionel Sambuc /// will be added to the same block and are executed under the same
461*0a6a1f1dSLionel Sambuc /// condition.
needsTempDtorBranch__anon557f5a500111::CFGBuilder::TempDtorContext462*0a6a1f1dSLionel Sambuc bool needsTempDtorBranch() const {
463*0a6a1f1dSLionel Sambuc return IsConditional && !TerminatorExpr;
464*0a6a1f1dSLionel Sambuc }
465*0a6a1f1dSLionel Sambuc
466*0a6a1f1dSLionel Sambuc /// Remember the successor S of a temporary destructor decision branch for
467*0a6a1f1dSLionel Sambuc /// the corresponding CXXBindTemporaryExpr E.
setDecisionPoint__anon557f5a500111::CFGBuilder::TempDtorContext468*0a6a1f1dSLionel Sambuc void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
469*0a6a1f1dSLionel Sambuc Succ = S;
470*0a6a1f1dSLionel Sambuc TerminatorExpr = E;
471*0a6a1f1dSLionel Sambuc }
472*0a6a1f1dSLionel Sambuc
473*0a6a1f1dSLionel Sambuc const bool IsConditional;
474*0a6a1f1dSLionel Sambuc const TryResult KnownExecuted;
475*0a6a1f1dSLionel Sambuc CFGBlock *Succ;
476*0a6a1f1dSLionel Sambuc CXXBindTemporaryExpr *TerminatorExpr;
477*0a6a1f1dSLionel Sambuc };
478*0a6a1f1dSLionel Sambuc
479f4a2713aSLionel Sambuc // Visitors to walk an AST and generate destructors of temporaries in
480f4a2713aSLionel Sambuc // full expression.
481*0a6a1f1dSLionel Sambuc CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary,
482*0a6a1f1dSLionel Sambuc TempDtorContext &Context);
483*0a6a1f1dSLionel Sambuc CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E, TempDtorContext &Context);
484*0a6a1f1dSLionel Sambuc CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,
485*0a6a1f1dSLionel Sambuc TempDtorContext &Context);
486*0a6a1f1dSLionel Sambuc CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
487*0a6a1f1dSLionel Sambuc CXXBindTemporaryExpr *E, bool BindToTemporary, TempDtorContext &Context);
488*0a6a1f1dSLionel Sambuc CFGBlock *VisitConditionalOperatorForTemporaryDtors(
489*0a6a1f1dSLionel Sambuc AbstractConditionalOperator *E, bool BindToTemporary,
490*0a6a1f1dSLionel Sambuc TempDtorContext &Context);
491*0a6a1f1dSLionel Sambuc void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
492*0a6a1f1dSLionel Sambuc CFGBlock *FalseSucc = nullptr);
493f4a2713aSLionel Sambuc
494f4a2713aSLionel Sambuc // NYS == Not Yet Supported
NYS()495f4a2713aSLionel Sambuc CFGBlock *NYS() {
496f4a2713aSLionel Sambuc badCFG = true;
497f4a2713aSLionel Sambuc return Block;
498f4a2713aSLionel Sambuc }
499f4a2713aSLionel Sambuc
autoCreateBlock()500f4a2713aSLionel Sambuc void autoCreateBlock() { if (!Block) Block = createBlock(); }
501f4a2713aSLionel Sambuc CFGBlock *createBlock(bool add_successor = true);
502f4a2713aSLionel Sambuc CFGBlock *createNoReturnBlock();
503f4a2713aSLionel Sambuc
addStmt(Stmt * S)504f4a2713aSLionel Sambuc CFGBlock *addStmt(Stmt *S) {
505f4a2713aSLionel Sambuc return Visit(S, AddStmtChoice::AlwaysAdd);
506f4a2713aSLionel Sambuc }
507f4a2713aSLionel Sambuc CFGBlock *addInitializer(CXXCtorInitializer *I);
508f4a2713aSLionel Sambuc void addAutomaticObjDtors(LocalScope::const_iterator B,
509f4a2713aSLionel Sambuc LocalScope::const_iterator E, Stmt *S);
510f4a2713aSLionel Sambuc void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
511f4a2713aSLionel Sambuc
512f4a2713aSLionel Sambuc // Local scopes creation.
513f4a2713aSLionel Sambuc LocalScope* createOrReuseLocalScope(LocalScope* Scope);
514f4a2713aSLionel Sambuc
515f4a2713aSLionel Sambuc void addLocalScopeForStmt(Stmt *S);
516*0a6a1f1dSLionel Sambuc LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
517*0a6a1f1dSLionel Sambuc LocalScope* Scope = nullptr);
518*0a6a1f1dSLionel Sambuc LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
519f4a2713aSLionel Sambuc
520f4a2713aSLionel Sambuc void addLocalScopeAndDtors(Stmt *S);
521f4a2713aSLionel Sambuc
522f4a2713aSLionel Sambuc // Interface to CFGBlock - adding CFGElements.
appendStmt(CFGBlock * B,const Stmt * S)523f4a2713aSLionel Sambuc void appendStmt(CFGBlock *B, const Stmt *S) {
524f4a2713aSLionel Sambuc if (alwaysAdd(S) && cachedEntry)
525f4a2713aSLionel Sambuc cachedEntry->second = B;
526f4a2713aSLionel Sambuc
527f4a2713aSLionel Sambuc // All block-level expressions should have already been IgnoreParens()ed.
528f4a2713aSLionel Sambuc assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
529f4a2713aSLionel Sambuc B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
530f4a2713aSLionel Sambuc }
appendInitializer(CFGBlock * B,CXXCtorInitializer * I)531f4a2713aSLionel Sambuc void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
532f4a2713aSLionel Sambuc B->appendInitializer(I, cfg->getBumpVectorContext());
533f4a2713aSLionel Sambuc }
appendNewAllocator(CFGBlock * B,CXXNewExpr * NE)534*0a6a1f1dSLionel Sambuc void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
535*0a6a1f1dSLionel Sambuc B->appendNewAllocator(NE, cfg->getBumpVectorContext());
536*0a6a1f1dSLionel Sambuc }
appendBaseDtor(CFGBlock * B,const CXXBaseSpecifier * BS)537f4a2713aSLionel Sambuc void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
538f4a2713aSLionel Sambuc B->appendBaseDtor(BS, cfg->getBumpVectorContext());
539f4a2713aSLionel Sambuc }
appendMemberDtor(CFGBlock * B,FieldDecl * FD)540f4a2713aSLionel Sambuc void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
541f4a2713aSLionel Sambuc B->appendMemberDtor(FD, cfg->getBumpVectorContext());
542f4a2713aSLionel Sambuc }
appendTemporaryDtor(CFGBlock * B,CXXBindTemporaryExpr * E)543f4a2713aSLionel Sambuc void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
544f4a2713aSLionel Sambuc B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
545f4a2713aSLionel Sambuc }
appendAutomaticObjDtor(CFGBlock * B,VarDecl * VD,Stmt * S)546f4a2713aSLionel Sambuc void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
547f4a2713aSLionel Sambuc B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
548f4a2713aSLionel Sambuc }
549f4a2713aSLionel Sambuc
appendDeleteDtor(CFGBlock * B,CXXRecordDecl * RD,CXXDeleteExpr * DE)550f4a2713aSLionel Sambuc void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
551f4a2713aSLionel Sambuc B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
552f4a2713aSLionel Sambuc }
553f4a2713aSLionel Sambuc
554f4a2713aSLionel Sambuc void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
555f4a2713aSLionel Sambuc LocalScope::const_iterator B, LocalScope::const_iterator E);
556f4a2713aSLionel Sambuc
addSuccessor(CFGBlock * B,CFGBlock * S,bool IsReachable=true)557*0a6a1f1dSLionel Sambuc void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
558*0a6a1f1dSLionel Sambuc B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
559*0a6a1f1dSLionel Sambuc cfg->getBumpVectorContext());
560*0a6a1f1dSLionel Sambuc }
561*0a6a1f1dSLionel Sambuc
562*0a6a1f1dSLionel Sambuc /// Add a reachable successor to a block, with the alternate variant that is
563*0a6a1f1dSLionel Sambuc /// unreachable.
addSuccessor(CFGBlock * B,CFGBlock * ReachableBlock,CFGBlock * AltBlock)564*0a6a1f1dSLionel Sambuc void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
565*0a6a1f1dSLionel Sambuc B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
566*0a6a1f1dSLionel Sambuc cfg->getBumpVectorContext());
567*0a6a1f1dSLionel Sambuc }
568*0a6a1f1dSLionel Sambuc
569*0a6a1f1dSLionel Sambuc /// \brief Find a relational comparison with an expression evaluating to a
570*0a6a1f1dSLionel Sambuc /// boolean and a constant other than 0 and 1.
571*0a6a1f1dSLionel Sambuc /// e.g. if ((x < y) == 10)
checkIncorrectRelationalOperator(const BinaryOperator * B)572*0a6a1f1dSLionel Sambuc TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
573*0a6a1f1dSLionel Sambuc const Expr *LHSExpr = B->getLHS()->IgnoreParens();
574*0a6a1f1dSLionel Sambuc const Expr *RHSExpr = B->getRHS()->IgnoreParens();
575*0a6a1f1dSLionel Sambuc
576*0a6a1f1dSLionel Sambuc const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
577*0a6a1f1dSLionel Sambuc const Expr *BoolExpr = RHSExpr;
578*0a6a1f1dSLionel Sambuc bool IntFirst = true;
579*0a6a1f1dSLionel Sambuc if (!IntLiteral) {
580*0a6a1f1dSLionel Sambuc IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
581*0a6a1f1dSLionel Sambuc BoolExpr = LHSExpr;
582*0a6a1f1dSLionel Sambuc IntFirst = false;
583*0a6a1f1dSLionel Sambuc }
584*0a6a1f1dSLionel Sambuc
585*0a6a1f1dSLionel Sambuc if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue())
586*0a6a1f1dSLionel Sambuc return TryResult();
587*0a6a1f1dSLionel Sambuc
588*0a6a1f1dSLionel Sambuc llvm::APInt IntValue = IntLiteral->getValue();
589*0a6a1f1dSLionel Sambuc if ((IntValue == 1) || (IntValue == 0))
590*0a6a1f1dSLionel Sambuc return TryResult();
591*0a6a1f1dSLionel Sambuc
592*0a6a1f1dSLionel Sambuc bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() ||
593*0a6a1f1dSLionel Sambuc !IntValue.isNegative();
594*0a6a1f1dSLionel Sambuc
595*0a6a1f1dSLionel Sambuc BinaryOperatorKind Bok = B->getOpcode();
596*0a6a1f1dSLionel Sambuc if (Bok == BO_GT || Bok == BO_GE) {
597*0a6a1f1dSLionel Sambuc // Always true for 10 > bool and bool > -1
598*0a6a1f1dSLionel Sambuc // Always false for -1 > bool and bool > 10
599*0a6a1f1dSLionel Sambuc return TryResult(IntFirst == IntLarger);
600*0a6a1f1dSLionel Sambuc } else {
601*0a6a1f1dSLionel Sambuc // Always true for -1 < bool and bool < 10
602*0a6a1f1dSLionel Sambuc // Always false for 10 < bool and bool < -1
603*0a6a1f1dSLionel Sambuc return TryResult(IntFirst != IntLarger);
604*0a6a1f1dSLionel Sambuc }
605*0a6a1f1dSLionel Sambuc }
606*0a6a1f1dSLionel Sambuc
607*0a6a1f1dSLionel Sambuc /// Find an incorrect equality comparison. Either with an expression
608*0a6a1f1dSLionel Sambuc /// evaluating to a boolean and a constant other than 0 and 1.
609*0a6a1f1dSLionel Sambuc /// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to
610*0a6a1f1dSLionel Sambuc /// true/false e.q. (x & 8) == 4.
checkIncorrectEqualityOperator(const BinaryOperator * B)611*0a6a1f1dSLionel Sambuc TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {
612*0a6a1f1dSLionel Sambuc const Expr *LHSExpr = B->getLHS()->IgnoreParens();
613*0a6a1f1dSLionel Sambuc const Expr *RHSExpr = B->getRHS()->IgnoreParens();
614*0a6a1f1dSLionel Sambuc
615*0a6a1f1dSLionel Sambuc const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
616*0a6a1f1dSLionel Sambuc const Expr *BoolExpr = RHSExpr;
617*0a6a1f1dSLionel Sambuc
618*0a6a1f1dSLionel Sambuc if (!IntLiteral) {
619*0a6a1f1dSLionel Sambuc IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
620*0a6a1f1dSLionel Sambuc BoolExpr = LHSExpr;
621*0a6a1f1dSLionel Sambuc }
622*0a6a1f1dSLionel Sambuc
623*0a6a1f1dSLionel Sambuc if (!IntLiteral)
624*0a6a1f1dSLionel Sambuc return TryResult();
625*0a6a1f1dSLionel Sambuc
626*0a6a1f1dSLionel Sambuc const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
627*0a6a1f1dSLionel Sambuc if (BitOp && (BitOp->getOpcode() == BO_And ||
628*0a6a1f1dSLionel Sambuc BitOp->getOpcode() == BO_Or)) {
629*0a6a1f1dSLionel Sambuc const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens();
630*0a6a1f1dSLionel Sambuc const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens();
631*0a6a1f1dSLionel Sambuc
632*0a6a1f1dSLionel Sambuc const IntegerLiteral *IntLiteral2 = dyn_cast<IntegerLiteral>(LHSExpr2);
633*0a6a1f1dSLionel Sambuc
634*0a6a1f1dSLionel Sambuc if (!IntLiteral2)
635*0a6a1f1dSLionel Sambuc IntLiteral2 = dyn_cast<IntegerLiteral>(RHSExpr2);
636*0a6a1f1dSLionel Sambuc
637*0a6a1f1dSLionel Sambuc if (!IntLiteral2)
638*0a6a1f1dSLionel Sambuc return TryResult();
639*0a6a1f1dSLionel Sambuc
640*0a6a1f1dSLionel Sambuc llvm::APInt L1 = IntLiteral->getValue();
641*0a6a1f1dSLionel Sambuc llvm::APInt L2 = IntLiteral2->getValue();
642*0a6a1f1dSLionel Sambuc if ((BitOp->getOpcode() == BO_And && (L2 & L1) != L1) ||
643*0a6a1f1dSLionel Sambuc (BitOp->getOpcode() == BO_Or && (L2 | L1) != L1)) {
644*0a6a1f1dSLionel Sambuc if (BuildOpts.Observer)
645*0a6a1f1dSLionel Sambuc BuildOpts.Observer->compareBitwiseEquality(B,
646*0a6a1f1dSLionel Sambuc B->getOpcode() != BO_EQ);
647*0a6a1f1dSLionel Sambuc TryResult(B->getOpcode() != BO_EQ);
648*0a6a1f1dSLionel Sambuc }
649*0a6a1f1dSLionel Sambuc } else if (BoolExpr->isKnownToHaveBooleanValue()) {
650*0a6a1f1dSLionel Sambuc llvm::APInt IntValue = IntLiteral->getValue();
651*0a6a1f1dSLionel Sambuc if ((IntValue == 1) || (IntValue == 0)) {
652*0a6a1f1dSLionel Sambuc return TryResult();
653*0a6a1f1dSLionel Sambuc }
654*0a6a1f1dSLionel Sambuc return TryResult(B->getOpcode() != BO_EQ);
655*0a6a1f1dSLionel Sambuc }
656*0a6a1f1dSLionel Sambuc
657*0a6a1f1dSLionel Sambuc return TryResult();
658*0a6a1f1dSLionel Sambuc }
659*0a6a1f1dSLionel Sambuc
analyzeLogicOperatorCondition(BinaryOperatorKind Relation,const llvm::APSInt & Value1,const llvm::APSInt & Value2)660*0a6a1f1dSLionel Sambuc TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,
661*0a6a1f1dSLionel Sambuc const llvm::APSInt &Value1,
662*0a6a1f1dSLionel Sambuc const llvm::APSInt &Value2) {
663*0a6a1f1dSLionel Sambuc assert(Value1.isSigned() == Value2.isSigned());
664*0a6a1f1dSLionel Sambuc switch (Relation) {
665*0a6a1f1dSLionel Sambuc default:
666*0a6a1f1dSLionel Sambuc return TryResult();
667*0a6a1f1dSLionel Sambuc case BO_EQ:
668*0a6a1f1dSLionel Sambuc return TryResult(Value1 == Value2);
669*0a6a1f1dSLionel Sambuc case BO_NE:
670*0a6a1f1dSLionel Sambuc return TryResult(Value1 != Value2);
671*0a6a1f1dSLionel Sambuc case BO_LT:
672*0a6a1f1dSLionel Sambuc return TryResult(Value1 < Value2);
673*0a6a1f1dSLionel Sambuc case BO_LE:
674*0a6a1f1dSLionel Sambuc return TryResult(Value1 <= Value2);
675*0a6a1f1dSLionel Sambuc case BO_GT:
676*0a6a1f1dSLionel Sambuc return TryResult(Value1 > Value2);
677*0a6a1f1dSLionel Sambuc case BO_GE:
678*0a6a1f1dSLionel Sambuc return TryResult(Value1 >= Value2);
679*0a6a1f1dSLionel Sambuc }
680*0a6a1f1dSLionel Sambuc }
681*0a6a1f1dSLionel Sambuc
682*0a6a1f1dSLionel Sambuc /// \brief Find a pair of comparison expressions with or without parentheses
683*0a6a1f1dSLionel Sambuc /// with a shared variable and constants and a logical operator between them
684*0a6a1f1dSLionel Sambuc /// that always evaluates to either true or false.
685*0a6a1f1dSLionel Sambuc /// e.g. if (x != 3 || x != 4)
checkIncorrectLogicOperator(const BinaryOperator * B)686*0a6a1f1dSLionel Sambuc TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {
687*0a6a1f1dSLionel Sambuc assert(B->isLogicalOp());
688*0a6a1f1dSLionel Sambuc const BinaryOperator *LHS =
689*0a6a1f1dSLionel Sambuc dyn_cast<BinaryOperator>(B->getLHS()->IgnoreParens());
690*0a6a1f1dSLionel Sambuc const BinaryOperator *RHS =
691*0a6a1f1dSLionel Sambuc dyn_cast<BinaryOperator>(B->getRHS()->IgnoreParens());
692*0a6a1f1dSLionel Sambuc if (!LHS || !RHS)
693*0a6a1f1dSLionel Sambuc return TryResult();
694*0a6a1f1dSLionel Sambuc
695*0a6a1f1dSLionel Sambuc if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
696*0a6a1f1dSLionel Sambuc return TryResult();
697*0a6a1f1dSLionel Sambuc
698*0a6a1f1dSLionel Sambuc BinaryOperatorKind BO1 = LHS->getOpcode();
699*0a6a1f1dSLionel Sambuc const DeclRefExpr *Decl1 =
700*0a6a1f1dSLionel Sambuc dyn_cast<DeclRefExpr>(LHS->getLHS()->IgnoreParenImpCasts());
701*0a6a1f1dSLionel Sambuc const IntegerLiteral *Literal1 =
702*0a6a1f1dSLionel Sambuc dyn_cast<IntegerLiteral>(LHS->getRHS()->IgnoreParens());
703*0a6a1f1dSLionel Sambuc if (!Decl1 && !Literal1) {
704*0a6a1f1dSLionel Sambuc if (BO1 == BO_GT)
705*0a6a1f1dSLionel Sambuc BO1 = BO_LT;
706*0a6a1f1dSLionel Sambuc else if (BO1 == BO_GE)
707*0a6a1f1dSLionel Sambuc BO1 = BO_LE;
708*0a6a1f1dSLionel Sambuc else if (BO1 == BO_LT)
709*0a6a1f1dSLionel Sambuc BO1 = BO_GT;
710*0a6a1f1dSLionel Sambuc else if (BO1 == BO_LE)
711*0a6a1f1dSLionel Sambuc BO1 = BO_GE;
712*0a6a1f1dSLionel Sambuc Decl1 = dyn_cast<DeclRefExpr>(LHS->getRHS()->IgnoreParenImpCasts());
713*0a6a1f1dSLionel Sambuc Literal1 = dyn_cast<IntegerLiteral>(LHS->getLHS()->IgnoreParens());
714*0a6a1f1dSLionel Sambuc }
715*0a6a1f1dSLionel Sambuc
716*0a6a1f1dSLionel Sambuc if (!Decl1 || !Literal1)
717*0a6a1f1dSLionel Sambuc return TryResult();
718*0a6a1f1dSLionel Sambuc
719*0a6a1f1dSLionel Sambuc BinaryOperatorKind BO2 = RHS->getOpcode();
720*0a6a1f1dSLionel Sambuc const DeclRefExpr *Decl2 =
721*0a6a1f1dSLionel Sambuc dyn_cast<DeclRefExpr>(RHS->getLHS()->IgnoreParenImpCasts());
722*0a6a1f1dSLionel Sambuc const IntegerLiteral *Literal2 =
723*0a6a1f1dSLionel Sambuc dyn_cast<IntegerLiteral>(RHS->getRHS()->IgnoreParens());
724*0a6a1f1dSLionel Sambuc if (!Decl2 && !Literal2) {
725*0a6a1f1dSLionel Sambuc if (BO2 == BO_GT)
726*0a6a1f1dSLionel Sambuc BO2 = BO_LT;
727*0a6a1f1dSLionel Sambuc else if (BO2 == BO_GE)
728*0a6a1f1dSLionel Sambuc BO2 = BO_LE;
729*0a6a1f1dSLionel Sambuc else if (BO2 == BO_LT)
730*0a6a1f1dSLionel Sambuc BO2 = BO_GT;
731*0a6a1f1dSLionel Sambuc else if (BO2 == BO_LE)
732*0a6a1f1dSLionel Sambuc BO2 = BO_GE;
733*0a6a1f1dSLionel Sambuc Decl2 = dyn_cast<DeclRefExpr>(RHS->getRHS()->IgnoreParenImpCasts());
734*0a6a1f1dSLionel Sambuc Literal2 = dyn_cast<IntegerLiteral>(RHS->getLHS()->IgnoreParens());
735*0a6a1f1dSLionel Sambuc }
736*0a6a1f1dSLionel Sambuc
737*0a6a1f1dSLionel Sambuc if (!Decl2 || !Literal2)
738*0a6a1f1dSLionel Sambuc return TryResult();
739*0a6a1f1dSLionel Sambuc
740*0a6a1f1dSLionel Sambuc // Check that it is the same variable on both sides.
741*0a6a1f1dSLionel Sambuc if (Decl1->getDecl() != Decl2->getDecl())
742*0a6a1f1dSLionel Sambuc return TryResult();
743*0a6a1f1dSLionel Sambuc
744*0a6a1f1dSLionel Sambuc llvm::APSInt L1, L2;
745*0a6a1f1dSLionel Sambuc
746*0a6a1f1dSLionel Sambuc if (!Literal1->EvaluateAsInt(L1, *Context) ||
747*0a6a1f1dSLionel Sambuc !Literal2->EvaluateAsInt(L2, *Context))
748*0a6a1f1dSLionel Sambuc return TryResult();
749*0a6a1f1dSLionel Sambuc
750*0a6a1f1dSLionel Sambuc // Can't compare signed with unsigned or with different bit width.
751*0a6a1f1dSLionel Sambuc if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
752*0a6a1f1dSLionel Sambuc return TryResult();
753*0a6a1f1dSLionel Sambuc
754*0a6a1f1dSLionel Sambuc // Values that will be used to determine if result of logical
755*0a6a1f1dSLionel Sambuc // operator is always true/false
756*0a6a1f1dSLionel Sambuc const llvm::APSInt Values[] = {
757*0a6a1f1dSLionel Sambuc // Value less than both Value1 and Value2
758*0a6a1f1dSLionel Sambuc llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
759*0a6a1f1dSLionel Sambuc // L1
760*0a6a1f1dSLionel Sambuc L1,
761*0a6a1f1dSLionel Sambuc // Value between Value1 and Value2
762*0a6a1f1dSLionel Sambuc ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
763*0a6a1f1dSLionel Sambuc L1.isUnsigned()),
764*0a6a1f1dSLionel Sambuc // L2
765*0a6a1f1dSLionel Sambuc L2,
766*0a6a1f1dSLionel Sambuc // Value greater than both Value1 and Value2
767*0a6a1f1dSLionel Sambuc llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
768*0a6a1f1dSLionel Sambuc };
769*0a6a1f1dSLionel Sambuc
770*0a6a1f1dSLionel Sambuc // Check whether expression is always true/false by evaluating the following
771*0a6a1f1dSLionel Sambuc // * variable x is less than the smallest literal.
772*0a6a1f1dSLionel Sambuc // * variable x is equal to the smallest literal.
773*0a6a1f1dSLionel Sambuc // * Variable x is between smallest and largest literal.
774*0a6a1f1dSLionel Sambuc // * Variable x is equal to the largest literal.
775*0a6a1f1dSLionel Sambuc // * Variable x is greater than largest literal.
776*0a6a1f1dSLionel Sambuc bool AlwaysTrue = true, AlwaysFalse = true;
777*0a6a1f1dSLionel Sambuc for (unsigned int ValueIndex = 0;
778*0a6a1f1dSLionel Sambuc ValueIndex < sizeof(Values) / sizeof(Values[0]);
779*0a6a1f1dSLionel Sambuc ++ValueIndex) {
780*0a6a1f1dSLionel Sambuc llvm::APSInt Value = Values[ValueIndex];
781*0a6a1f1dSLionel Sambuc TryResult Res1, Res2;
782*0a6a1f1dSLionel Sambuc Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
783*0a6a1f1dSLionel Sambuc Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
784*0a6a1f1dSLionel Sambuc
785*0a6a1f1dSLionel Sambuc if (!Res1.isKnown() || !Res2.isKnown())
786*0a6a1f1dSLionel Sambuc return TryResult();
787*0a6a1f1dSLionel Sambuc
788*0a6a1f1dSLionel Sambuc if (B->getOpcode() == BO_LAnd) {
789*0a6a1f1dSLionel Sambuc AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
790*0a6a1f1dSLionel Sambuc AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
791*0a6a1f1dSLionel Sambuc } else {
792*0a6a1f1dSLionel Sambuc AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
793*0a6a1f1dSLionel Sambuc AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
794*0a6a1f1dSLionel Sambuc }
795*0a6a1f1dSLionel Sambuc }
796*0a6a1f1dSLionel Sambuc
797*0a6a1f1dSLionel Sambuc if (AlwaysTrue || AlwaysFalse) {
798*0a6a1f1dSLionel Sambuc if (BuildOpts.Observer)
799*0a6a1f1dSLionel Sambuc BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
800*0a6a1f1dSLionel Sambuc return TryResult(AlwaysTrue);
801*0a6a1f1dSLionel Sambuc }
802*0a6a1f1dSLionel Sambuc return TryResult();
803f4a2713aSLionel Sambuc }
804f4a2713aSLionel Sambuc
805f4a2713aSLionel Sambuc /// Try and evaluate an expression to an integer constant.
tryEvaluate(Expr * S,Expr::EvalResult & outResult)806f4a2713aSLionel Sambuc bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
807f4a2713aSLionel Sambuc if (!BuildOpts.PruneTriviallyFalseEdges)
808f4a2713aSLionel Sambuc return false;
809f4a2713aSLionel Sambuc return !S->isTypeDependent() &&
810f4a2713aSLionel Sambuc !S->isValueDependent() &&
811f4a2713aSLionel Sambuc S->EvaluateAsRValue(outResult, *Context);
812f4a2713aSLionel Sambuc }
813f4a2713aSLionel Sambuc
814f4a2713aSLionel Sambuc /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
815f4a2713aSLionel Sambuc /// if we can evaluate to a known value, otherwise return -1.
tryEvaluateBool(Expr * S)816f4a2713aSLionel Sambuc TryResult tryEvaluateBool(Expr *S) {
817f4a2713aSLionel Sambuc if (!BuildOpts.PruneTriviallyFalseEdges ||
818f4a2713aSLionel Sambuc S->isTypeDependent() || S->isValueDependent())
819f4a2713aSLionel Sambuc return TryResult();
820f4a2713aSLionel Sambuc
821f4a2713aSLionel Sambuc if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
822f4a2713aSLionel Sambuc if (Bop->isLogicalOp()) {
823f4a2713aSLionel Sambuc // Check the cache first.
824f4a2713aSLionel Sambuc CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
825f4a2713aSLionel Sambuc if (I != CachedBoolEvals.end())
826f4a2713aSLionel Sambuc return I->second; // already in map;
827f4a2713aSLionel Sambuc
828f4a2713aSLionel Sambuc // Retrieve result at first, or the map might be updated.
829f4a2713aSLionel Sambuc TryResult Result = evaluateAsBooleanConditionNoCache(S);
830f4a2713aSLionel Sambuc CachedBoolEvals[S] = Result; // update or insert
831f4a2713aSLionel Sambuc return Result;
832f4a2713aSLionel Sambuc }
833f4a2713aSLionel Sambuc else {
834f4a2713aSLionel Sambuc switch (Bop->getOpcode()) {
835f4a2713aSLionel Sambuc default: break;
836f4a2713aSLionel Sambuc // For 'x & 0' and 'x * 0', we can determine that
837f4a2713aSLionel Sambuc // the value is always false.
838f4a2713aSLionel Sambuc case BO_Mul:
839f4a2713aSLionel Sambuc case BO_And: {
840f4a2713aSLionel Sambuc // If either operand is zero, we know the value
841f4a2713aSLionel Sambuc // must be false.
842f4a2713aSLionel Sambuc llvm::APSInt IntVal;
843f4a2713aSLionel Sambuc if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) {
844f4a2713aSLionel Sambuc if (IntVal.getBoolValue() == false) {
845f4a2713aSLionel Sambuc return TryResult(false);
846f4a2713aSLionel Sambuc }
847f4a2713aSLionel Sambuc }
848f4a2713aSLionel Sambuc if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) {
849f4a2713aSLionel Sambuc if (IntVal.getBoolValue() == false) {
850f4a2713aSLionel Sambuc return TryResult(false);
851f4a2713aSLionel Sambuc }
852f4a2713aSLionel Sambuc }
853f4a2713aSLionel Sambuc }
854f4a2713aSLionel Sambuc break;
855f4a2713aSLionel Sambuc }
856f4a2713aSLionel Sambuc }
857f4a2713aSLionel Sambuc }
858f4a2713aSLionel Sambuc
859f4a2713aSLionel Sambuc return evaluateAsBooleanConditionNoCache(S);
860f4a2713aSLionel Sambuc }
861f4a2713aSLionel Sambuc
862f4a2713aSLionel Sambuc /// \brief Evaluate as boolean \param E without using the cache.
evaluateAsBooleanConditionNoCache(Expr * E)863f4a2713aSLionel Sambuc TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
864f4a2713aSLionel Sambuc if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
865f4a2713aSLionel Sambuc if (Bop->isLogicalOp()) {
866f4a2713aSLionel Sambuc TryResult LHS = tryEvaluateBool(Bop->getLHS());
867f4a2713aSLionel Sambuc if (LHS.isKnown()) {
868f4a2713aSLionel Sambuc // We were able to evaluate the LHS, see if we can get away with not
869f4a2713aSLionel Sambuc // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
870f4a2713aSLionel Sambuc if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
871f4a2713aSLionel Sambuc return LHS.isTrue();
872f4a2713aSLionel Sambuc
873f4a2713aSLionel Sambuc TryResult RHS = tryEvaluateBool(Bop->getRHS());
874f4a2713aSLionel Sambuc if (RHS.isKnown()) {
875f4a2713aSLionel Sambuc if (Bop->getOpcode() == BO_LOr)
876f4a2713aSLionel Sambuc return LHS.isTrue() || RHS.isTrue();
877f4a2713aSLionel Sambuc else
878f4a2713aSLionel Sambuc return LHS.isTrue() && RHS.isTrue();
879f4a2713aSLionel Sambuc }
880f4a2713aSLionel Sambuc } else {
881f4a2713aSLionel Sambuc TryResult RHS = tryEvaluateBool(Bop->getRHS());
882f4a2713aSLionel Sambuc if (RHS.isKnown()) {
883f4a2713aSLionel Sambuc // We can't evaluate the LHS; however, sometimes the result
884f4a2713aSLionel Sambuc // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
885f4a2713aSLionel Sambuc if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
886f4a2713aSLionel Sambuc return RHS.isTrue();
887*0a6a1f1dSLionel Sambuc } else {
888*0a6a1f1dSLionel Sambuc TryResult BopRes = checkIncorrectLogicOperator(Bop);
889*0a6a1f1dSLionel Sambuc if (BopRes.isKnown())
890*0a6a1f1dSLionel Sambuc return BopRes.isTrue();
891f4a2713aSLionel Sambuc }
892f4a2713aSLionel Sambuc }
893f4a2713aSLionel Sambuc
894f4a2713aSLionel Sambuc return TryResult();
895*0a6a1f1dSLionel Sambuc } else if (Bop->isEqualityOp()) {
896*0a6a1f1dSLionel Sambuc TryResult BopRes = checkIncorrectEqualityOperator(Bop);
897*0a6a1f1dSLionel Sambuc if (BopRes.isKnown())
898*0a6a1f1dSLionel Sambuc return BopRes.isTrue();
899*0a6a1f1dSLionel Sambuc } else if (Bop->isRelationalOp()) {
900*0a6a1f1dSLionel Sambuc TryResult BopRes = checkIncorrectRelationalOperator(Bop);
901*0a6a1f1dSLionel Sambuc if (BopRes.isKnown())
902*0a6a1f1dSLionel Sambuc return BopRes.isTrue();
903f4a2713aSLionel Sambuc }
904f4a2713aSLionel Sambuc }
905f4a2713aSLionel Sambuc
906f4a2713aSLionel Sambuc bool Result;
907f4a2713aSLionel Sambuc if (E->EvaluateAsBooleanCondition(Result, *Context))
908f4a2713aSLionel Sambuc return Result;
909f4a2713aSLionel Sambuc
910f4a2713aSLionel Sambuc return TryResult();
911f4a2713aSLionel Sambuc }
912f4a2713aSLionel Sambuc
913f4a2713aSLionel Sambuc };
914f4a2713aSLionel Sambuc
alwaysAdd(CFGBuilder & builder,const Stmt * stmt) const915f4a2713aSLionel Sambuc inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
916f4a2713aSLionel Sambuc const Stmt *stmt) const {
917f4a2713aSLionel Sambuc return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
918f4a2713aSLionel Sambuc }
919f4a2713aSLionel Sambuc
alwaysAdd(const Stmt * stmt)920f4a2713aSLionel Sambuc bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
921f4a2713aSLionel Sambuc bool shouldAdd = BuildOpts.alwaysAdd(stmt);
922f4a2713aSLionel Sambuc
923f4a2713aSLionel Sambuc if (!BuildOpts.forcedBlkExprs)
924f4a2713aSLionel Sambuc return shouldAdd;
925f4a2713aSLionel Sambuc
926f4a2713aSLionel Sambuc if (lastLookup == stmt) {
927f4a2713aSLionel Sambuc if (cachedEntry) {
928f4a2713aSLionel Sambuc assert(cachedEntry->first == stmt);
929f4a2713aSLionel Sambuc return true;
930f4a2713aSLionel Sambuc }
931f4a2713aSLionel Sambuc return shouldAdd;
932f4a2713aSLionel Sambuc }
933f4a2713aSLionel Sambuc
934f4a2713aSLionel Sambuc lastLookup = stmt;
935f4a2713aSLionel Sambuc
936f4a2713aSLionel Sambuc // Perform the lookup!
937f4a2713aSLionel Sambuc CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;
938f4a2713aSLionel Sambuc
939f4a2713aSLionel Sambuc if (!fb) {
940f4a2713aSLionel Sambuc // No need to update 'cachedEntry', since it will always be null.
941*0a6a1f1dSLionel Sambuc assert(!cachedEntry);
942f4a2713aSLionel Sambuc return shouldAdd;
943f4a2713aSLionel Sambuc }
944f4a2713aSLionel Sambuc
945f4a2713aSLionel Sambuc CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
946f4a2713aSLionel Sambuc if (itr == fb->end()) {
947*0a6a1f1dSLionel Sambuc cachedEntry = nullptr;
948f4a2713aSLionel Sambuc return shouldAdd;
949f4a2713aSLionel Sambuc }
950f4a2713aSLionel Sambuc
951f4a2713aSLionel Sambuc cachedEntry = &*itr;
952f4a2713aSLionel Sambuc return true;
953f4a2713aSLionel Sambuc }
954f4a2713aSLionel Sambuc
955f4a2713aSLionel Sambuc // FIXME: Add support for dependent-sized array types in C++?
956f4a2713aSLionel Sambuc // Does it even make sense to build a CFG for an uninstantiated template?
FindVA(const Type * t)957f4a2713aSLionel Sambuc static const VariableArrayType *FindVA(const Type *t) {
958f4a2713aSLionel Sambuc while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
959f4a2713aSLionel Sambuc if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
960f4a2713aSLionel Sambuc if (vat->getSizeExpr())
961f4a2713aSLionel Sambuc return vat;
962f4a2713aSLionel Sambuc
963f4a2713aSLionel Sambuc t = vt->getElementType().getTypePtr();
964f4a2713aSLionel Sambuc }
965f4a2713aSLionel Sambuc
966*0a6a1f1dSLionel Sambuc return nullptr;
967f4a2713aSLionel Sambuc }
968f4a2713aSLionel Sambuc
969f4a2713aSLionel Sambuc /// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an
970f4a2713aSLionel Sambuc /// arbitrary statement. Examples include a single expression or a function
971f4a2713aSLionel Sambuc /// body (compound statement). The ownership of the returned CFG is
972f4a2713aSLionel Sambuc /// transferred to the caller. If CFG construction fails, this method returns
973f4a2713aSLionel Sambuc /// NULL.
buildCFG(const Decl * D,Stmt * Statement)974*0a6a1f1dSLionel Sambuc std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
975f4a2713aSLionel Sambuc assert(cfg.get());
976f4a2713aSLionel Sambuc if (!Statement)
977*0a6a1f1dSLionel Sambuc return nullptr;
978f4a2713aSLionel Sambuc
979f4a2713aSLionel Sambuc // Create an empty block that will serve as the exit block for the CFG. Since
980f4a2713aSLionel Sambuc // this is the first block added to the CFG, it will be implicitly registered
981f4a2713aSLionel Sambuc // as the exit block.
982f4a2713aSLionel Sambuc Succ = createBlock();
983f4a2713aSLionel Sambuc assert(Succ == &cfg->getExit());
984*0a6a1f1dSLionel Sambuc Block = nullptr; // the EXIT block is empty. Create all other blocks lazily.
985f4a2713aSLionel Sambuc
986f4a2713aSLionel Sambuc if (BuildOpts.AddImplicitDtors)
987f4a2713aSLionel Sambuc if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
988f4a2713aSLionel Sambuc addImplicitDtorsForDestructor(DD);
989f4a2713aSLionel Sambuc
990f4a2713aSLionel Sambuc // Visit the statements and create the CFG.
991f4a2713aSLionel Sambuc CFGBlock *B = addStmt(Statement);
992f4a2713aSLionel Sambuc
993f4a2713aSLionel Sambuc if (badCFG)
994*0a6a1f1dSLionel Sambuc return nullptr;
995f4a2713aSLionel Sambuc
996f4a2713aSLionel Sambuc // For C++ constructor add initializers to CFG.
997f4a2713aSLionel Sambuc if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
998f4a2713aSLionel Sambuc for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(),
999f4a2713aSLionel Sambuc E = CD->init_rend(); I != E; ++I) {
1000f4a2713aSLionel Sambuc B = addInitializer(*I);
1001f4a2713aSLionel Sambuc if (badCFG)
1002*0a6a1f1dSLionel Sambuc return nullptr;
1003f4a2713aSLionel Sambuc }
1004f4a2713aSLionel Sambuc }
1005f4a2713aSLionel Sambuc
1006f4a2713aSLionel Sambuc if (B)
1007f4a2713aSLionel Sambuc Succ = B;
1008f4a2713aSLionel Sambuc
1009f4a2713aSLionel Sambuc // Backpatch the gotos whose label -> block mappings we didn't know when we
1010f4a2713aSLionel Sambuc // encountered them.
1011f4a2713aSLionel Sambuc for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1012f4a2713aSLionel Sambuc E = BackpatchBlocks.end(); I != E; ++I ) {
1013f4a2713aSLionel Sambuc
1014f4a2713aSLionel Sambuc CFGBlock *B = I->block;
1015f4a2713aSLionel Sambuc const GotoStmt *G = cast<GotoStmt>(B->getTerminator());
1016f4a2713aSLionel Sambuc LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1017f4a2713aSLionel Sambuc
1018f4a2713aSLionel Sambuc // If there is no target for the goto, then we are looking at an
1019f4a2713aSLionel Sambuc // incomplete AST. Handle this by not registering a successor.
1020f4a2713aSLionel Sambuc if (LI == LabelMap.end()) continue;
1021f4a2713aSLionel Sambuc
1022f4a2713aSLionel Sambuc JumpTarget JT = LI->second;
1023f4a2713aSLionel Sambuc prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1024f4a2713aSLionel Sambuc JT.scopePosition);
1025f4a2713aSLionel Sambuc addSuccessor(B, JT.block);
1026f4a2713aSLionel Sambuc }
1027f4a2713aSLionel Sambuc
1028f4a2713aSLionel Sambuc // Add successors to the Indirect Goto Dispatch block (if we have one).
1029f4a2713aSLionel Sambuc if (CFGBlock *B = cfg->getIndirectGotoBlock())
1030f4a2713aSLionel Sambuc for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1031f4a2713aSLionel Sambuc E = AddressTakenLabels.end(); I != E; ++I ) {
1032f4a2713aSLionel Sambuc
1033f4a2713aSLionel Sambuc // Lookup the target block.
1034f4a2713aSLionel Sambuc LabelMapTy::iterator LI = LabelMap.find(*I);
1035f4a2713aSLionel Sambuc
1036f4a2713aSLionel Sambuc // If there is no target block that contains label, then we are looking
1037f4a2713aSLionel Sambuc // at an incomplete AST. Handle this by not registering a successor.
1038f4a2713aSLionel Sambuc if (LI == LabelMap.end()) continue;
1039f4a2713aSLionel Sambuc
1040f4a2713aSLionel Sambuc addSuccessor(B, LI->second.block);
1041f4a2713aSLionel Sambuc }
1042f4a2713aSLionel Sambuc
1043f4a2713aSLionel Sambuc // Create an empty entry block that has no predecessors.
1044f4a2713aSLionel Sambuc cfg->setEntry(createBlock());
1045f4a2713aSLionel Sambuc
1046*0a6a1f1dSLionel Sambuc return std::move(cfg);
1047f4a2713aSLionel Sambuc }
1048f4a2713aSLionel Sambuc
1049f4a2713aSLionel Sambuc /// createBlock - Used to lazily create blocks that are connected
1050f4a2713aSLionel Sambuc /// to the current (global) succcessor.
createBlock(bool add_successor)1051f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::createBlock(bool add_successor) {
1052f4a2713aSLionel Sambuc CFGBlock *B = cfg->createBlock();
1053f4a2713aSLionel Sambuc if (add_successor && Succ)
1054f4a2713aSLionel Sambuc addSuccessor(B, Succ);
1055f4a2713aSLionel Sambuc return B;
1056f4a2713aSLionel Sambuc }
1057f4a2713aSLionel Sambuc
1058f4a2713aSLionel Sambuc /// createNoReturnBlock - Used to create a block is a 'noreturn' point in the
1059f4a2713aSLionel Sambuc /// CFG. It is *not* connected to the current (global) successor, and instead
1060f4a2713aSLionel Sambuc /// directly tied to the exit block in order to be reachable.
createNoReturnBlock()1061f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::createNoReturnBlock() {
1062f4a2713aSLionel Sambuc CFGBlock *B = createBlock(false);
1063f4a2713aSLionel Sambuc B->setHasNoReturnElement();
1064*0a6a1f1dSLionel Sambuc addSuccessor(B, &cfg->getExit(), Succ);
1065f4a2713aSLionel Sambuc return B;
1066f4a2713aSLionel Sambuc }
1067f4a2713aSLionel Sambuc
1068f4a2713aSLionel Sambuc /// addInitializer - Add C++ base or member initializer element to CFG.
addInitializer(CXXCtorInitializer * I)1069f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
1070f4a2713aSLionel Sambuc if (!BuildOpts.AddInitializers)
1071f4a2713aSLionel Sambuc return Block;
1072f4a2713aSLionel Sambuc
1073f4a2713aSLionel Sambuc bool HasTemporaries = false;
1074f4a2713aSLionel Sambuc
1075f4a2713aSLionel Sambuc // Destructors of temporaries in initialization expression should be called
1076f4a2713aSLionel Sambuc // after initialization finishes.
1077f4a2713aSLionel Sambuc Expr *Init = I->getInit();
1078f4a2713aSLionel Sambuc if (Init) {
1079f4a2713aSLionel Sambuc HasTemporaries = isa<ExprWithCleanups>(Init);
1080f4a2713aSLionel Sambuc
1081f4a2713aSLionel Sambuc if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1082f4a2713aSLionel Sambuc // Generate destructors for temporaries in initialization expression.
1083*0a6a1f1dSLionel Sambuc TempDtorContext Context;
1084f4a2713aSLionel Sambuc VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1085*0a6a1f1dSLionel Sambuc /*BindToTemporary=*/false, Context);
1086f4a2713aSLionel Sambuc }
1087f4a2713aSLionel Sambuc }
1088f4a2713aSLionel Sambuc
1089f4a2713aSLionel Sambuc autoCreateBlock();
1090f4a2713aSLionel Sambuc appendInitializer(Block, I);
1091f4a2713aSLionel Sambuc
1092f4a2713aSLionel Sambuc if (Init) {
1093f4a2713aSLionel Sambuc if (HasTemporaries) {
1094f4a2713aSLionel Sambuc // For expression with temporaries go directly to subexpression to omit
1095f4a2713aSLionel Sambuc // generating destructors for the second time.
1096f4a2713aSLionel Sambuc return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1097f4a2713aSLionel Sambuc }
1098f4a2713aSLionel Sambuc return Visit(Init);
1099f4a2713aSLionel Sambuc }
1100f4a2713aSLionel Sambuc
1101f4a2713aSLionel Sambuc return Block;
1102f4a2713aSLionel Sambuc }
1103f4a2713aSLionel Sambuc
1104f4a2713aSLionel Sambuc /// \brief Retrieve the type of the temporary object whose lifetime was
1105f4a2713aSLionel Sambuc /// extended by a local reference with the given initializer.
getReferenceInitTemporaryType(ASTContext & Context,const Expr * Init)1106f4a2713aSLionel Sambuc static QualType getReferenceInitTemporaryType(ASTContext &Context,
1107f4a2713aSLionel Sambuc const Expr *Init) {
1108f4a2713aSLionel Sambuc while (true) {
1109f4a2713aSLionel Sambuc // Skip parentheses.
1110f4a2713aSLionel Sambuc Init = Init->IgnoreParens();
1111f4a2713aSLionel Sambuc
1112f4a2713aSLionel Sambuc // Skip through cleanups.
1113f4a2713aSLionel Sambuc if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) {
1114f4a2713aSLionel Sambuc Init = EWC->getSubExpr();
1115f4a2713aSLionel Sambuc continue;
1116f4a2713aSLionel Sambuc }
1117f4a2713aSLionel Sambuc
1118f4a2713aSLionel Sambuc // Skip through the temporary-materialization expression.
1119f4a2713aSLionel Sambuc if (const MaterializeTemporaryExpr *MTE
1120f4a2713aSLionel Sambuc = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1121f4a2713aSLionel Sambuc Init = MTE->GetTemporaryExpr();
1122f4a2713aSLionel Sambuc continue;
1123f4a2713aSLionel Sambuc }
1124f4a2713aSLionel Sambuc
1125f4a2713aSLionel Sambuc // Skip derived-to-base and no-op casts.
1126f4a2713aSLionel Sambuc if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) {
1127f4a2713aSLionel Sambuc if ((CE->getCastKind() == CK_DerivedToBase ||
1128f4a2713aSLionel Sambuc CE->getCastKind() == CK_UncheckedDerivedToBase ||
1129f4a2713aSLionel Sambuc CE->getCastKind() == CK_NoOp) &&
1130f4a2713aSLionel Sambuc Init->getType()->isRecordType()) {
1131f4a2713aSLionel Sambuc Init = CE->getSubExpr();
1132f4a2713aSLionel Sambuc continue;
1133f4a2713aSLionel Sambuc }
1134f4a2713aSLionel Sambuc }
1135f4a2713aSLionel Sambuc
1136f4a2713aSLionel Sambuc // Skip member accesses into rvalues.
1137f4a2713aSLionel Sambuc if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) {
1138f4a2713aSLionel Sambuc if (!ME->isArrow() && ME->getBase()->isRValue()) {
1139f4a2713aSLionel Sambuc Init = ME->getBase();
1140f4a2713aSLionel Sambuc continue;
1141f4a2713aSLionel Sambuc }
1142f4a2713aSLionel Sambuc }
1143f4a2713aSLionel Sambuc
1144f4a2713aSLionel Sambuc break;
1145f4a2713aSLionel Sambuc }
1146f4a2713aSLionel Sambuc
1147f4a2713aSLionel Sambuc return Init->getType();
1148f4a2713aSLionel Sambuc }
1149f4a2713aSLionel Sambuc
1150f4a2713aSLionel Sambuc /// addAutomaticObjDtors - Add to current block automatic objects destructors
1151f4a2713aSLionel Sambuc /// for objects in range of local scope positions. Use S as trigger statement
1152f4a2713aSLionel Sambuc /// for destructors.
addAutomaticObjDtors(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1153f4a2713aSLionel Sambuc void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1154f4a2713aSLionel Sambuc LocalScope::const_iterator E, Stmt *S) {
1155f4a2713aSLionel Sambuc if (!BuildOpts.AddImplicitDtors)
1156f4a2713aSLionel Sambuc return;
1157f4a2713aSLionel Sambuc
1158f4a2713aSLionel Sambuc if (B == E)
1159f4a2713aSLionel Sambuc return;
1160f4a2713aSLionel Sambuc
1161f4a2713aSLionel Sambuc // We need to append the destructors in reverse order, but any one of them
1162f4a2713aSLionel Sambuc // may be a no-return destructor which changes the CFG. As a result, buffer
1163f4a2713aSLionel Sambuc // this sequence up and replay them in reverse order when appending onto the
1164f4a2713aSLionel Sambuc // CFGBlock(s).
1165f4a2713aSLionel Sambuc SmallVector<VarDecl*, 10> Decls;
1166f4a2713aSLionel Sambuc Decls.reserve(B.distance(E));
1167f4a2713aSLionel Sambuc for (LocalScope::const_iterator I = B; I != E; ++I)
1168f4a2713aSLionel Sambuc Decls.push_back(*I);
1169f4a2713aSLionel Sambuc
1170f4a2713aSLionel Sambuc for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(),
1171f4a2713aSLionel Sambuc E = Decls.rend();
1172f4a2713aSLionel Sambuc I != E; ++I) {
1173f4a2713aSLionel Sambuc // If this destructor is marked as a no-return destructor, we need to
1174f4a2713aSLionel Sambuc // create a new block for the destructor which does not have as a successor
1175f4a2713aSLionel Sambuc // anything built thus far: control won't flow out of this block.
1176f4a2713aSLionel Sambuc QualType Ty = (*I)->getType();
1177f4a2713aSLionel Sambuc if (Ty->isReferenceType()) {
1178f4a2713aSLionel Sambuc Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit());
1179f4a2713aSLionel Sambuc }
1180f4a2713aSLionel Sambuc Ty = Context->getBaseElementType(Ty);
1181f4a2713aSLionel Sambuc
1182f4a2713aSLionel Sambuc const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
1183f4a2713aSLionel Sambuc if (Dtor->isNoReturn())
1184f4a2713aSLionel Sambuc Block = createNoReturnBlock();
1185f4a2713aSLionel Sambuc else
1186f4a2713aSLionel Sambuc autoCreateBlock();
1187f4a2713aSLionel Sambuc
1188f4a2713aSLionel Sambuc appendAutomaticObjDtor(Block, *I, S);
1189f4a2713aSLionel Sambuc }
1190f4a2713aSLionel Sambuc }
1191f4a2713aSLionel Sambuc
1192f4a2713aSLionel Sambuc /// addImplicitDtorsForDestructor - Add implicit destructors generated for
1193f4a2713aSLionel Sambuc /// base and member objects in destructor.
addImplicitDtorsForDestructor(const CXXDestructorDecl * DD)1194f4a2713aSLionel Sambuc void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
1195f4a2713aSLionel Sambuc assert (BuildOpts.AddImplicitDtors
1196f4a2713aSLionel Sambuc && "Can be called only when dtors should be added");
1197f4a2713aSLionel Sambuc const CXXRecordDecl *RD = DD->getParent();
1198f4a2713aSLionel Sambuc
1199f4a2713aSLionel Sambuc // At the end destroy virtual base objects.
1200*0a6a1f1dSLionel Sambuc for (const auto &VI : RD->vbases()) {
1201*0a6a1f1dSLionel Sambuc const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1202f4a2713aSLionel Sambuc if (!CD->hasTrivialDestructor()) {
1203f4a2713aSLionel Sambuc autoCreateBlock();
1204*0a6a1f1dSLionel Sambuc appendBaseDtor(Block, &VI);
1205f4a2713aSLionel Sambuc }
1206f4a2713aSLionel Sambuc }
1207f4a2713aSLionel Sambuc
1208f4a2713aSLionel Sambuc // Before virtual bases destroy direct base objects.
1209*0a6a1f1dSLionel Sambuc for (const auto &BI : RD->bases()) {
1210*0a6a1f1dSLionel Sambuc if (!BI.isVirtual()) {
1211*0a6a1f1dSLionel Sambuc const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1212f4a2713aSLionel Sambuc if (!CD->hasTrivialDestructor()) {
1213f4a2713aSLionel Sambuc autoCreateBlock();
1214*0a6a1f1dSLionel Sambuc appendBaseDtor(Block, &BI);
1215f4a2713aSLionel Sambuc }
1216f4a2713aSLionel Sambuc }
1217f4a2713aSLionel Sambuc }
1218f4a2713aSLionel Sambuc
1219f4a2713aSLionel Sambuc // First destroy member objects.
1220*0a6a1f1dSLionel Sambuc for (auto *FI : RD->fields()) {
1221f4a2713aSLionel Sambuc // Check for constant size array. Set type to array element type.
1222f4a2713aSLionel Sambuc QualType QT = FI->getType();
1223f4a2713aSLionel Sambuc if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
1224f4a2713aSLionel Sambuc if (AT->getSize() == 0)
1225f4a2713aSLionel Sambuc continue;
1226f4a2713aSLionel Sambuc QT = AT->getElementType();
1227f4a2713aSLionel Sambuc }
1228f4a2713aSLionel Sambuc
1229f4a2713aSLionel Sambuc if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
1230f4a2713aSLionel Sambuc if (!CD->hasTrivialDestructor()) {
1231f4a2713aSLionel Sambuc autoCreateBlock();
1232*0a6a1f1dSLionel Sambuc appendMemberDtor(Block, FI);
1233f4a2713aSLionel Sambuc }
1234f4a2713aSLionel Sambuc }
1235f4a2713aSLionel Sambuc }
1236f4a2713aSLionel Sambuc
1237f4a2713aSLionel Sambuc /// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
1238f4a2713aSLionel Sambuc /// way return valid LocalScope object.
createOrReuseLocalScope(LocalScope * Scope)1239f4a2713aSLionel Sambuc LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
1240f4a2713aSLionel Sambuc if (!Scope) {
1241f4a2713aSLionel Sambuc llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1242f4a2713aSLionel Sambuc Scope = alloc.Allocate<LocalScope>();
1243f4a2713aSLionel Sambuc BumpVectorContext ctx(alloc);
1244f4a2713aSLionel Sambuc new (Scope) LocalScope(ctx, ScopePos);
1245f4a2713aSLionel Sambuc }
1246f4a2713aSLionel Sambuc return Scope;
1247f4a2713aSLionel Sambuc }
1248f4a2713aSLionel Sambuc
1249f4a2713aSLionel Sambuc /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
1250f4a2713aSLionel Sambuc /// that should create implicit scope (e.g. if/else substatements).
addLocalScopeForStmt(Stmt * S)1251f4a2713aSLionel Sambuc void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
1252f4a2713aSLionel Sambuc if (!BuildOpts.AddImplicitDtors)
1253f4a2713aSLionel Sambuc return;
1254f4a2713aSLionel Sambuc
1255*0a6a1f1dSLionel Sambuc LocalScope *Scope = nullptr;
1256f4a2713aSLionel Sambuc
1257f4a2713aSLionel Sambuc // For compound statement we will be creating explicit scope.
1258f4a2713aSLionel Sambuc if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
1259*0a6a1f1dSLionel Sambuc for (auto *BI : CS->body()) {
1260*0a6a1f1dSLionel Sambuc Stmt *SI = BI->stripLabelLikeStatements();
1261f4a2713aSLionel Sambuc if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
1262f4a2713aSLionel Sambuc Scope = addLocalScopeForDeclStmt(DS, Scope);
1263f4a2713aSLionel Sambuc }
1264f4a2713aSLionel Sambuc return;
1265f4a2713aSLionel Sambuc }
1266f4a2713aSLionel Sambuc
1267f4a2713aSLionel Sambuc // For any other statement scope will be implicit and as such will be
1268f4a2713aSLionel Sambuc // interesting only for DeclStmt.
1269f4a2713aSLionel Sambuc if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
1270f4a2713aSLionel Sambuc addLocalScopeForDeclStmt(DS);
1271f4a2713aSLionel Sambuc }
1272f4a2713aSLionel Sambuc
1273f4a2713aSLionel Sambuc /// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will
1274f4a2713aSLionel Sambuc /// reuse Scope if not NULL.
addLocalScopeForDeclStmt(DeclStmt * DS,LocalScope * Scope)1275f4a2713aSLionel Sambuc LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
1276f4a2713aSLionel Sambuc LocalScope* Scope) {
1277f4a2713aSLionel Sambuc if (!BuildOpts.AddImplicitDtors)
1278f4a2713aSLionel Sambuc return Scope;
1279f4a2713aSLionel Sambuc
1280*0a6a1f1dSLionel Sambuc for (auto *DI : DS->decls())
1281*0a6a1f1dSLionel Sambuc if (VarDecl *VD = dyn_cast<VarDecl>(DI))
1282f4a2713aSLionel Sambuc Scope = addLocalScopeForVarDecl(VD, Scope);
1283f4a2713aSLionel Sambuc return Scope;
1284f4a2713aSLionel Sambuc }
1285f4a2713aSLionel Sambuc
1286f4a2713aSLionel Sambuc /// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will
1287f4a2713aSLionel Sambuc /// create add scope for automatic objects and temporary objects bound to
1288f4a2713aSLionel Sambuc /// const reference. Will reuse Scope if not NULL.
addLocalScopeForVarDecl(VarDecl * VD,LocalScope * Scope)1289f4a2713aSLionel Sambuc LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
1290f4a2713aSLionel Sambuc LocalScope* Scope) {
1291f4a2713aSLionel Sambuc if (!BuildOpts.AddImplicitDtors)
1292f4a2713aSLionel Sambuc return Scope;
1293f4a2713aSLionel Sambuc
1294f4a2713aSLionel Sambuc // Check if variable is local.
1295f4a2713aSLionel Sambuc switch (VD->getStorageClass()) {
1296f4a2713aSLionel Sambuc case SC_None:
1297f4a2713aSLionel Sambuc case SC_Auto:
1298f4a2713aSLionel Sambuc case SC_Register:
1299f4a2713aSLionel Sambuc break;
1300f4a2713aSLionel Sambuc default: return Scope;
1301f4a2713aSLionel Sambuc }
1302f4a2713aSLionel Sambuc
1303f4a2713aSLionel Sambuc // Check for const references bound to temporary. Set type to pointee.
1304f4a2713aSLionel Sambuc QualType QT = VD->getType();
1305f4a2713aSLionel Sambuc if (QT.getTypePtr()->isReferenceType()) {
1306f4a2713aSLionel Sambuc // Attempt to determine whether this declaration lifetime-extends a
1307f4a2713aSLionel Sambuc // temporary.
1308f4a2713aSLionel Sambuc //
1309f4a2713aSLionel Sambuc // FIXME: This is incorrect. Non-reference declarations can lifetime-extend
1310f4a2713aSLionel Sambuc // temporaries, and a single declaration can extend multiple temporaries.
1311f4a2713aSLionel Sambuc // We should look at the storage duration on each nested
1312f4a2713aSLionel Sambuc // MaterializeTemporaryExpr instead.
1313f4a2713aSLionel Sambuc const Expr *Init = VD->getInit();
1314f4a2713aSLionel Sambuc if (!Init)
1315f4a2713aSLionel Sambuc return Scope;
1316f4a2713aSLionel Sambuc if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init))
1317f4a2713aSLionel Sambuc Init = EWC->getSubExpr();
1318f4a2713aSLionel Sambuc if (!isa<MaterializeTemporaryExpr>(Init))
1319f4a2713aSLionel Sambuc return Scope;
1320f4a2713aSLionel Sambuc
1321f4a2713aSLionel Sambuc // Lifetime-extending a temporary.
1322f4a2713aSLionel Sambuc QT = getReferenceInitTemporaryType(*Context, Init);
1323f4a2713aSLionel Sambuc }
1324f4a2713aSLionel Sambuc
1325f4a2713aSLionel Sambuc // Check for constant size array. Set type to array element type.
1326f4a2713aSLionel Sambuc while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
1327f4a2713aSLionel Sambuc if (AT->getSize() == 0)
1328f4a2713aSLionel Sambuc return Scope;
1329f4a2713aSLionel Sambuc QT = AT->getElementType();
1330f4a2713aSLionel Sambuc }
1331f4a2713aSLionel Sambuc
1332f4a2713aSLionel Sambuc // Check if type is a C++ class with non-trivial destructor.
1333f4a2713aSLionel Sambuc if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
1334f4a2713aSLionel Sambuc if (!CD->hasTrivialDestructor()) {
1335f4a2713aSLionel Sambuc // Add the variable to scope
1336f4a2713aSLionel Sambuc Scope = createOrReuseLocalScope(Scope);
1337f4a2713aSLionel Sambuc Scope->addVar(VD);
1338f4a2713aSLionel Sambuc ScopePos = Scope->begin();
1339f4a2713aSLionel Sambuc }
1340f4a2713aSLionel Sambuc return Scope;
1341f4a2713aSLionel Sambuc }
1342f4a2713aSLionel Sambuc
1343f4a2713aSLionel Sambuc /// addLocalScopeAndDtors - For given statement add local scope for it and
1344f4a2713aSLionel Sambuc /// add destructors that will cleanup the scope. Will reuse Scope if not NULL.
addLocalScopeAndDtors(Stmt * S)1345f4a2713aSLionel Sambuc void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
1346f4a2713aSLionel Sambuc if (!BuildOpts.AddImplicitDtors)
1347f4a2713aSLionel Sambuc return;
1348f4a2713aSLionel Sambuc
1349f4a2713aSLionel Sambuc LocalScope::const_iterator scopeBeginPos = ScopePos;
1350f4a2713aSLionel Sambuc addLocalScopeForStmt(S);
1351f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
1352f4a2713aSLionel Sambuc }
1353f4a2713aSLionel Sambuc
1354f4a2713aSLionel Sambuc /// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for
1355f4a2713aSLionel Sambuc /// variables with automatic storage duration to CFGBlock's elements vector.
1356f4a2713aSLionel Sambuc /// Elements will be prepended to physical beginning of the vector which
1357f4a2713aSLionel Sambuc /// happens to be logical end. Use blocks terminator as statement that specifies
1358f4a2713aSLionel Sambuc /// destructors call site.
1359f4a2713aSLionel Sambuc /// FIXME: This mechanism for adding automatic destructors doesn't handle
1360f4a2713aSLionel Sambuc /// no-return destructors properly.
prependAutomaticObjDtorsWithTerminator(CFGBlock * Blk,LocalScope::const_iterator B,LocalScope::const_iterator E)1361f4a2713aSLionel Sambuc void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
1362f4a2713aSLionel Sambuc LocalScope::const_iterator B, LocalScope::const_iterator E) {
1363f4a2713aSLionel Sambuc BumpVectorContext &C = cfg->getBumpVectorContext();
1364f4a2713aSLionel Sambuc CFGBlock::iterator InsertPos
1365f4a2713aSLionel Sambuc = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C);
1366f4a2713aSLionel Sambuc for (LocalScope::const_iterator I = B; I != E; ++I)
1367f4a2713aSLionel Sambuc InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I,
1368f4a2713aSLionel Sambuc Blk->getTerminator());
1369f4a2713aSLionel Sambuc }
1370f4a2713aSLionel Sambuc
1371f4a2713aSLionel Sambuc /// Visit - Walk the subtree of a statement and add extra
1372f4a2713aSLionel Sambuc /// blocks for ternary operators, &&, and ||. We also process "," and
1373f4a2713aSLionel Sambuc /// DeclStmts (which may contain nested control-flow).
Visit(Stmt * S,AddStmtChoice asc)1374f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
1375f4a2713aSLionel Sambuc if (!S) {
1376f4a2713aSLionel Sambuc badCFG = true;
1377*0a6a1f1dSLionel Sambuc return nullptr;
1378f4a2713aSLionel Sambuc }
1379f4a2713aSLionel Sambuc
1380f4a2713aSLionel Sambuc if (Expr *E = dyn_cast<Expr>(S))
1381f4a2713aSLionel Sambuc S = E->IgnoreParens();
1382f4a2713aSLionel Sambuc
1383f4a2713aSLionel Sambuc switch (S->getStmtClass()) {
1384f4a2713aSLionel Sambuc default:
1385f4a2713aSLionel Sambuc return VisitStmt(S, asc);
1386f4a2713aSLionel Sambuc
1387f4a2713aSLionel Sambuc case Stmt::AddrLabelExprClass:
1388f4a2713aSLionel Sambuc return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
1389f4a2713aSLionel Sambuc
1390f4a2713aSLionel Sambuc case Stmt::BinaryConditionalOperatorClass:
1391f4a2713aSLionel Sambuc return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
1392f4a2713aSLionel Sambuc
1393f4a2713aSLionel Sambuc case Stmt::BinaryOperatorClass:
1394f4a2713aSLionel Sambuc return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
1395f4a2713aSLionel Sambuc
1396f4a2713aSLionel Sambuc case Stmt::BlockExprClass:
1397f4a2713aSLionel Sambuc return VisitNoRecurse(cast<Expr>(S), asc);
1398f4a2713aSLionel Sambuc
1399f4a2713aSLionel Sambuc case Stmt::BreakStmtClass:
1400f4a2713aSLionel Sambuc return VisitBreakStmt(cast<BreakStmt>(S));
1401f4a2713aSLionel Sambuc
1402f4a2713aSLionel Sambuc case Stmt::CallExprClass:
1403f4a2713aSLionel Sambuc case Stmt::CXXOperatorCallExprClass:
1404f4a2713aSLionel Sambuc case Stmt::CXXMemberCallExprClass:
1405f4a2713aSLionel Sambuc case Stmt::UserDefinedLiteralClass:
1406f4a2713aSLionel Sambuc return VisitCallExpr(cast<CallExpr>(S), asc);
1407f4a2713aSLionel Sambuc
1408f4a2713aSLionel Sambuc case Stmt::CaseStmtClass:
1409f4a2713aSLionel Sambuc return VisitCaseStmt(cast<CaseStmt>(S));
1410f4a2713aSLionel Sambuc
1411f4a2713aSLionel Sambuc case Stmt::ChooseExprClass:
1412f4a2713aSLionel Sambuc return VisitChooseExpr(cast<ChooseExpr>(S), asc);
1413f4a2713aSLionel Sambuc
1414f4a2713aSLionel Sambuc case Stmt::CompoundStmtClass:
1415f4a2713aSLionel Sambuc return VisitCompoundStmt(cast<CompoundStmt>(S));
1416f4a2713aSLionel Sambuc
1417f4a2713aSLionel Sambuc case Stmt::ConditionalOperatorClass:
1418f4a2713aSLionel Sambuc return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
1419f4a2713aSLionel Sambuc
1420f4a2713aSLionel Sambuc case Stmt::ContinueStmtClass:
1421f4a2713aSLionel Sambuc return VisitContinueStmt(cast<ContinueStmt>(S));
1422f4a2713aSLionel Sambuc
1423f4a2713aSLionel Sambuc case Stmt::CXXCatchStmtClass:
1424f4a2713aSLionel Sambuc return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
1425f4a2713aSLionel Sambuc
1426f4a2713aSLionel Sambuc case Stmt::ExprWithCleanupsClass:
1427f4a2713aSLionel Sambuc return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
1428f4a2713aSLionel Sambuc
1429f4a2713aSLionel Sambuc case Stmt::CXXDefaultArgExprClass:
1430f4a2713aSLionel Sambuc case Stmt::CXXDefaultInitExprClass:
1431f4a2713aSLionel Sambuc // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
1432f4a2713aSLionel Sambuc // called function's declaration, not by the caller. If we simply add
1433f4a2713aSLionel Sambuc // this expression to the CFG, we could end up with the same Expr
1434f4a2713aSLionel Sambuc // appearing multiple times.
1435f4a2713aSLionel Sambuc // PR13385 / <rdar://problem/12156507>
1436f4a2713aSLionel Sambuc //
1437f4a2713aSLionel Sambuc // It's likewise possible for multiple CXXDefaultInitExprs for the same
1438f4a2713aSLionel Sambuc // expression to be used in the same function (through aggregate
1439f4a2713aSLionel Sambuc // initialization).
1440f4a2713aSLionel Sambuc return VisitStmt(S, asc);
1441f4a2713aSLionel Sambuc
1442f4a2713aSLionel Sambuc case Stmt::CXXBindTemporaryExprClass:
1443f4a2713aSLionel Sambuc return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
1444f4a2713aSLionel Sambuc
1445f4a2713aSLionel Sambuc case Stmt::CXXConstructExprClass:
1446f4a2713aSLionel Sambuc return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
1447f4a2713aSLionel Sambuc
1448*0a6a1f1dSLionel Sambuc case Stmt::CXXNewExprClass:
1449*0a6a1f1dSLionel Sambuc return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
1450*0a6a1f1dSLionel Sambuc
1451f4a2713aSLionel Sambuc case Stmt::CXXDeleteExprClass:
1452f4a2713aSLionel Sambuc return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
1453f4a2713aSLionel Sambuc
1454f4a2713aSLionel Sambuc case Stmt::CXXFunctionalCastExprClass:
1455f4a2713aSLionel Sambuc return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
1456f4a2713aSLionel Sambuc
1457f4a2713aSLionel Sambuc case Stmt::CXXTemporaryObjectExprClass:
1458f4a2713aSLionel Sambuc return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
1459f4a2713aSLionel Sambuc
1460f4a2713aSLionel Sambuc case Stmt::CXXThrowExprClass:
1461f4a2713aSLionel Sambuc return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
1462f4a2713aSLionel Sambuc
1463f4a2713aSLionel Sambuc case Stmt::CXXTryStmtClass:
1464f4a2713aSLionel Sambuc return VisitCXXTryStmt(cast<CXXTryStmt>(S));
1465f4a2713aSLionel Sambuc
1466f4a2713aSLionel Sambuc case Stmt::CXXForRangeStmtClass:
1467f4a2713aSLionel Sambuc return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
1468f4a2713aSLionel Sambuc
1469f4a2713aSLionel Sambuc case Stmt::DeclStmtClass:
1470f4a2713aSLionel Sambuc return VisitDeclStmt(cast<DeclStmt>(S));
1471f4a2713aSLionel Sambuc
1472f4a2713aSLionel Sambuc case Stmt::DefaultStmtClass:
1473f4a2713aSLionel Sambuc return VisitDefaultStmt(cast<DefaultStmt>(S));
1474f4a2713aSLionel Sambuc
1475f4a2713aSLionel Sambuc case Stmt::DoStmtClass:
1476f4a2713aSLionel Sambuc return VisitDoStmt(cast<DoStmt>(S));
1477f4a2713aSLionel Sambuc
1478f4a2713aSLionel Sambuc case Stmt::ForStmtClass:
1479f4a2713aSLionel Sambuc return VisitForStmt(cast<ForStmt>(S));
1480f4a2713aSLionel Sambuc
1481f4a2713aSLionel Sambuc case Stmt::GotoStmtClass:
1482f4a2713aSLionel Sambuc return VisitGotoStmt(cast<GotoStmt>(S));
1483f4a2713aSLionel Sambuc
1484f4a2713aSLionel Sambuc case Stmt::IfStmtClass:
1485f4a2713aSLionel Sambuc return VisitIfStmt(cast<IfStmt>(S));
1486f4a2713aSLionel Sambuc
1487f4a2713aSLionel Sambuc case Stmt::ImplicitCastExprClass:
1488f4a2713aSLionel Sambuc return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
1489f4a2713aSLionel Sambuc
1490f4a2713aSLionel Sambuc case Stmt::IndirectGotoStmtClass:
1491f4a2713aSLionel Sambuc return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
1492f4a2713aSLionel Sambuc
1493f4a2713aSLionel Sambuc case Stmt::LabelStmtClass:
1494f4a2713aSLionel Sambuc return VisitLabelStmt(cast<LabelStmt>(S));
1495f4a2713aSLionel Sambuc
1496f4a2713aSLionel Sambuc case Stmt::LambdaExprClass:
1497f4a2713aSLionel Sambuc return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
1498f4a2713aSLionel Sambuc
1499f4a2713aSLionel Sambuc case Stmt::MemberExprClass:
1500f4a2713aSLionel Sambuc return VisitMemberExpr(cast<MemberExpr>(S), asc);
1501f4a2713aSLionel Sambuc
1502f4a2713aSLionel Sambuc case Stmt::NullStmtClass:
1503f4a2713aSLionel Sambuc return Block;
1504f4a2713aSLionel Sambuc
1505f4a2713aSLionel Sambuc case Stmt::ObjCAtCatchStmtClass:
1506f4a2713aSLionel Sambuc return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
1507f4a2713aSLionel Sambuc
1508f4a2713aSLionel Sambuc case Stmt::ObjCAutoreleasePoolStmtClass:
1509f4a2713aSLionel Sambuc return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
1510f4a2713aSLionel Sambuc
1511f4a2713aSLionel Sambuc case Stmt::ObjCAtSynchronizedStmtClass:
1512f4a2713aSLionel Sambuc return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
1513f4a2713aSLionel Sambuc
1514f4a2713aSLionel Sambuc case Stmt::ObjCAtThrowStmtClass:
1515f4a2713aSLionel Sambuc return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
1516f4a2713aSLionel Sambuc
1517f4a2713aSLionel Sambuc case Stmt::ObjCAtTryStmtClass:
1518f4a2713aSLionel Sambuc return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
1519f4a2713aSLionel Sambuc
1520f4a2713aSLionel Sambuc case Stmt::ObjCForCollectionStmtClass:
1521f4a2713aSLionel Sambuc return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
1522f4a2713aSLionel Sambuc
1523f4a2713aSLionel Sambuc case Stmt::OpaqueValueExprClass:
1524f4a2713aSLionel Sambuc return Block;
1525f4a2713aSLionel Sambuc
1526f4a2713aSLionel Sambuc case Stmt::PseudoObjectExprClass:
1527f4a2713aSLionel Sambuc return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
1528f4a2713aSLionel Sambuc
1529f4a2713aSLionel Sambuc case Stmt::ReturnStmtClass:
1530f4a2713aSLionel Sambuc return VisitReturnStmt(cast<ReturnStmt>(S));
1531f4a2713aSLionel Sambuc
1532f4a2713aSLionel Sambuc case Stmt::UnaryExprOrTypeTraitExprClass:
1533f4a2713aSLionel Sambuc return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
1534f4a2713aSLionel Sambuc asc);
1535f4a2713aSLionel Sambuc
1536f4a2713aSLionel Sambuc case Stmt::StmtExprClass:
1537f4a2713aSLionel Sambuc return VisitStmtExpr(cast<StmtExpr>(S), asc);
1538f4a2713aSLionel Sambuc
1539f4a2713aSLionel Sambuc case Stmt::SwitchStmtClass:
1540f4a2713aSLionel Sambuc return VisitSwitchStmt(cast<SwitchStmt>(S));
1541f4a2713aSLionel Sambuc
1542f4a2713aSLionel Sambuc case Stmt::UnaryOperatorClass:
1543f4a2713aSLionel Sambuc return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
1544f4a2713aSLionel Sambuc
1545f4a2713aSLionel Sambuc case Stmt::WhileStmtClass:
1546f4a2713aSLionel Sambuc return VisitWhileStmt(cast<WhileStmt>(S));
1547f4a2713aSLionel Sambuc }
1548f4a2713aSLionel Sambuc }
1549f4a2713aSLionel Sambuc
VisitStmt(Stmt * S,AddStmtChoice asc)1550f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
1551f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, S)) {
1552f4a2713aSLionel Sambuc autoCreateBlock();
1553f4a2713aSLionel Sambuc appendStmt(Block, S);
1554f4a2713aSLionel Sambuc }
1555f4a2713aSLionel Sambuc
1556f4a2713aSLionel Sambuc return VisitChildren(S);
1557f4a2713aSLionel Sambuc }
1558f4a2713aSLionel Sambuc
1559f4a2713aSLionel Sambuc /// VisitChildren - Visit the children of a Stmt.
VisitChildren(Stmt * S)1560f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
1561f4a2713aSLionel Sambuc CFGBlock *B = Block;
1562f4a2713aSLionel Sambuc
1563f4a2713aSLionel Sambuc // Visit the children in their reverse order so that they appear in
1564f4a2713aSLionel Sambuc // left-to-right (natural) order in the CFG.
1565f4a2713aSLionel Sambuc reverse_children RChildren(S);
1566f4a2713aSLionel Sambuc for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
1567f4a2713aSLionel Sambuc I != E; ++I) {
1568f4a2713aSLionel Sambuc if (Stmt *Child = *I)
1569f4a2713aSLionel Sambuc if (CFGBlock *R = Visit(Child))
1570f4a2713aSLionel Sambuc B = R;
1571f4a2713aSLionel Sambuc }
1572f4a2713aSLionel Sambuc return B;
1573f4a2713aSLionel Sambuc }
1574f4a2713aSLionel Sambuc
VisitAddrLabelExpr(AddrLabelExpr * A,AddStmtChoice asc)1575f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
1576f4a2713aSLionel Sambuc AddStmtChoice asc) {
1577f4a2713aSLionel Sambuc AddressTakenLabels.insert(A->getLabel());
1578f4a2713aSLionel Sambuc
1579f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, A)) {
1580f4a2713aSLionel Sambuc autoCreateBlock();
1581f4a2713aSLionel Sambuc appendStmt(Block, A);
1582f4a2713aSLionel Sambuc }
1583f4a2713aSLionel Sambuc
1584f4a2713aSLionel Sambuc return Block;
1585f4a2713aSLionel Sambuc }
1586f4a2713aSLionel Sambuc
VisitUnaryOperator(UnaryOperator * U,AddStmtChoice asc)1587f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U,
1588f4a2713aSLionel Sambuc AddStmtChoice asc) {
1589f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, U)) {
1590f4a2713aSLionel Sambuc autoCreateBlock();
1591f4a2713aSLionel Sambuc appendStmt(Block, U);
1592f4a2713aSLionel Sambuc }
1593f4a2713aSLionel Sambuc
1594f4a2713aSLionel Sambuc return Visit(U->getSubExpr(), AddStmtChoice());
1595f4a2713aSLionel Sambuc }
1596f4a2713aSLionel Sambuc
VisitLogicalOperator(BinaryOperator * B)1597f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
1598f4a2713aSLionel Sambuc CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1599f4a2713aSLionel Sambuc appendStmt(ConfluenceBlock, B);
1600f4a2713aSLionel Sambuc
1601f4a2713aSLionel Sambuc if (badCFG)
1602*0a6a1f1dSLionel Sambuc return nullptr;
1603f4a2713aSLionel Sambuc
1604*0a6a1f1dSLionel Sambuc return VisitLogicalOperator(B, nullptr, ConfluenceBlock,
1605*0a6a1f1dSLionel Sambuc ConfluenceBlock).first;
1606f4a2713aSLionel Sambuc }
1607f4a2713aSLionel Sambuc
1608f4a2713aSLionel Sambuc std::pair<CFGBlock*, CFGBlock*>
VisitLogicalOperator(BinaryOperator * B,Stmt * Term,CFGBlock * TrueBlock,CFGBlock * FalseBlock)1609f4a2713aSLionel Sambuc CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
1610f4a2713aSLionel Sambuc Stmt *Term,
1611f4a2713aSLionel Sambuc CFGBlock *TrueBlock,
1612f4a2713aSLionel Sambuc CFGBlock *FalseBlock) {
1613f4a2713aSLionel Sambuc
1614f4a2713aSLionel Sambuc // Introspect the RHS. If it is a nested logical operation, we recursively
1615f4a2713aSLionel Sambuc // build the CFG using this function. Otherwise, resort to default
1616f4a2713aSLionel Sambuc // CFG construction behavior.
1617f4a2713aSLionel Sambuc Expr *RHS = B->getRHS()->IgnoreParens();
1618f4a2713aSLionel Sambuc CFGBlock *RHSBlock, *ExitBlock;
1619f4a2713aSLionel Sambuc
1620f4a2713aSLionel Sambuc do {
1621f4a2713aSLionel Sambuc if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
1622f4a2713aSLionel Sambuc if (B_RHS->isLogicalOp()) {
1623*0a6a1f1dSLionel Sambuc std::tie(RHSBlock, ExitBlock) =
1624f4a2713aSLionel Sambuc VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
1625f4a2713aSLionel Sambuc break;
1626f4a2713aSLionel Sambuc }
1627f4a2713aSLionel Sambuc
1628f4a2713aSLionel Sambuc // The RHS is not a nested logical operation. Don't push the terminator
1629f4a2713aSLionel Sambuc // down further, but instead visit RHS and construct the respective
1630f4a2713aSLionel Sambuc // pieces of the CFG, and link up the RHSBlock with the terminator
1631f4a2713aSLionel Sambuc // we have been provided.
1632f4a2713aSLionel Sambuc ExitBlock = RHSBlock = createBlock(false);
1633f4a2713aSLionel Sambuc
1634f4a2713aSLionel Sambuc if (!Term) {
1635f4a2713aSLionel Sambuc assert(TrueBlock == FalseBlock);
1636f4a2713aSLionel Sambuc addSuccessor(RHSBlock, TrueBlock);
1637f4a2713aSLionel Sambuc }
1638f4a2713aSLionel Sambuc else {
1639f4a2713aSLionel Sambuc RHSBlock->setTerminator(Term);
1640f4a2713aSLionel Sambuc TryResult KnownVal = tryEvaluateBool(RHS);
1641*0a6a1f1dSLionel Sambuc if (!KnownVal.isKnown())
1642*0a6a1f1dSLionel Sambuc KnownVal = tryEvaluateBool(B);
1643*0a6a1f1dSLionel Sambuc addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
1644*0a6a1f1dSLionel Sambuc addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
1645f4a2713aSLionel Sambuc }
1646f4a2713aSLionel Sambuc
1647f4a2713aSLionel Sambuc Block = RHSBlock;
1648f4a2713aSLionel Sambuc RHSBlock = addStmt(RHS);
1649f4a2713aSLionel Sambuc }
1650f4a2713aSLionel Sambuc while (false);
1651f4a2713aSLionel Sambuc
1652f4a2713aSLionel Sambuc if (badCFG)
1653*0a6a1f1dSLionel Sambuc return std::make_pair(nullptr, nullptr);
1654f4a2713aSLionel Sambuc
1655f4a2713aSLionel Sambuc // Generate the blocks for evaluating the LHS.
1656f4a2713aSLionel Sambuc Expr *LHS = B->getLHS()->IgnoreParens();
1657f4a2713aSLionel Sambuc
1658f4a2713aSLionel Sambuc if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
1659f4a2713aSLionel Sambuc if (B_LHS->isLogicalOp()) {
1660f4a2713aSLionel Sambuc if (B->getOpcode() == BO_LOr)
1661f4a2713aSLionel Sambuc FalseBlock = RHSBlock;
1662f4a2713aSLionel Sambuc else
1663f4a2713aSLionel Sambuc TrueBlock = RHSBlock;
1664f4a2713aSLionel Sambuc
1665f4a2713aSLionel Sambuc // For the LHS, treat 'B' as the terminator that we want to sink
1666f4a2713aSLionel Sambuc // into the nested branch. The RHS always gets the top-most
1667f4a2713aSLionel Sambuc // terminator.
1668f4a2713aSLionel Sambuc return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
1669f4a2713aSLionel Sambuc }
1670f4a2713aSLionel Sambuc
1671f4a2713aSLionel Sambuc // Create the block evaluating the LHS.
1672f4a2713aSLionel Sambuc // This contains the '&&' or '||' as the terminator.
1673f4a2713aSLionel Sambuc CFGBlock *LHSBlock = createBlock(false);
1674f4a2713aSLionel Sambuc LHSBlock->setTerminator(B);
1675f4a2713aSLionel Sambuc
1676f4a2713aSLionel Sambuc Block = LHSBlock;
1677f4a2713aSLionel Sambuc CFGBlock *EntryLHSBlock = addStmt(LHS);
1678f4a2713aSLionel Sambuc
1679f4a2713aSLionel Sambuc if (badCFG)
1680*0a6a1f1dSLionel Sambuc return std::make_pair(nullptr, nullptr);
1681f4a2713aSLionel Sambuc
1682f4a2713aSLionel Sambuc // See if this is a known constant.
1683f4a2713aSLionel Sambuc TryResult KnownVal = tryEvaluateBool(LHS);
1684f4a2713aSLionel Sambuc
1685f4a2713aSLionel Sambuc // Now link the LHSBlock with RHSBlock.
1686f4a2713aSLionel Sambuc if (B->getOpcode() == BO_LOr) {
1687*0a6a1f1dSLionel Sambuc addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
1688*0a6a1f1dSLionel Sambuc addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
1689f4a2713aSLionel Sambuc } else {
1690f4a2713aSLionel Sambuc assert(B->getOpcode() == BO_LAnd);
1691*0a6a1f1dSLionel Sambuc addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
1692*0a6a1f1dSLionel Sambuc addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
1693f4a2713aSLionel Sambuc }
1694f4a2713aSLionel Sambuc
1695f4a2713aSLionel Sambuc return std::make_pair(EntryLHSBlock, ExitBlock);
1696f4a2713aSLionel Sambuc }
1697f4a2713aSLionel Sambuc
1698f4a2713aSLionel Sambuc
VisitBinaryOperator(BinaryOperator * B,AddStmtChoice asc)1699f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
1700f4a2713aSLionel Sambuc AddStmtChoice asc) {
1701f4a2713aSLionel Sambuc // && or ||
1702f4a2713aSLionel Sambuc if (B->isLogicalOp())
1703f4a2713aSLionel Sambuc return VisitLogicalOperator(B);
1704f4a2713aSLionel Sambuc
1705f4a2713aSLionel Sambuc if (B->getOpcode() == BO_Comma) { // ,
1706f4a2713aSLionel Sambuc autoCreateBlock();
1707f4a2713aSLionel Sambuc appendStmt(Block, B);
1708f4a2713aSLionel Sambuc addStmt(B->getRHS());
1709f4a2713aSLionel Sambuc return addStmt(B->getLHS());
1710f4a2713aSLionel Sambuc }
1711f4a2713aSLionel Sambuc
1712f4a2713aSLionel Sambuc if (B->isAssignmentOp()) {
1713f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, B)) {
1714f4a2713aSLionel Sambuc autoCreateBlock();
1715f4a2713aSLionel Sambuc appendStmt(Block, B);
1716f4a2713aSLionel Sambuc }
1717f4a2713aSLionel Sambuc Visit(B->getLHS());
1718f4a2713aSLionel Sambuc return Visit(B->getRHS());
1719f4a2713aSLionel Sambuc }
1720f4a2713aSLionel Sambuc
1721f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, B)) {
1722f4a2713aSLionel Sambuc autoCreateBlock();
1723f4a2713aSLionel Sambuc appendStmt(Block, B);
1724f4a2713aSLionel Sambuc }
1725f4a2713aSLionel Sambuc
1726f4a2713aSLionel Sambuc CFGBlock *RBlock = Visit(B->getRHS());
1727f4a2713aSLionel Sambuc CFGBlock *LBlock = Visit(B->getLHS());
1728f4a2713aSLionel Sambuc // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
1729f4a2713aSLionel Sambuc // containing a DoStmt, and the LHS doesn't create a new block, then we should
1730f4a2713aSLionel Sambuc // return RBlock. Otherwise we'll incorrectly return NULL.
1731f4a2713aSLionel Sambuc return (LBlock ? LBlock : RBlock);
1732f4a2713aSLionel Sambuc }
1733f4a2713aSLionel Sambuc
VisitNoRecurse(Expr * E,AddStmtChoice asc)1734f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
1735f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, E)) {
1736f4a2713aSLionel Sambuc autoCreateBlock();
1737f4a2713aSLionel Sambuc appendStmt(Block, E);
1738f4a2713aSLionel Sambuc }
1739f4a2713aSLionel Sambuc return Block;
1740f4a2713aSLionel Sambuc }
1741f4a2713aSLionel Sambuc
VisitBreakStmt(BreakStmt * B)1742f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
1743f4a2713aSLionel Sambuc // "break" is a control-flow statement. Thus we stop processing the current
1744f4a2713aSLionel Sambuc // block.
1745f4a2713aSLionel Sambuc if (badCFG)
1746*0a6a1f1dSLionel Sambuc return nullptr;
1747f4a2713aSLionel Sambuc
1748f4a2713aSLionel Sambuc // Now create a new block that ends with the break statement.
1749f4a2713aSLionel Sambuc Block = createBlock(false);
1750f4a2713aSLionel Sambuc Block->setTerminator(B);
1751f4a2713aSLionel Sambuc
1752f4a2713aSLionel Sambuc // If there is no target for the break, then we are looking at an incomplete
1753f4a2713aSLionel Sambuc // AST. This means that the CFG cannot be constructed.
1754f4a2713aSLionel Sambuc if (BreakJumpTarget.block) {
1755f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
1756f4a2713aSLionel Sambuc addSuccessor(Block, BreakJumpTarget.block);
1757f4a2713aSLionel Sambuc } else
1758f4a2713aSLionel Sambuc badCFG = true;
1759f4a2713aSLionel Sambuc
1760f4a2713aSLionel Sambuc
1761f4a2713aSLionel Sambuc return Block;
1762f4a2713aSLionel Sambuc }
1763f4a2713aSLionel Sambuc
CanThrow(Expr * E,ASTContext & Ctx)1764f4a2713aSLionel Sambuc static bool CanThrow(Expr *E, ASTContext &Ctx) {
1765f4a2713aSLionel Sambuc QualType Ty = E->getType();
1766f4a2713aSLionel Sambuc if (Ty->isFunctionPointerType())
1767f4a2713aSLionel Sambuc Ty = Ty->getAs<PointerType>()->getPointeeType();
1768f4a2713aSLionel Sambuc else if (Ty->isBlockPointerType())
1769f4a2713aSLionel Sambuc Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
1770f4a2713aSLionel Sambuc
1771f4a2713aSLionel Sambuc const FunctionType *FT = Ty->getAs<FunctionType>();
1772f4a2713aSLionel Sambuc if (FT) {
1773f4a2713aSLionel Sambuc if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
1774f4a2713aSLionel Sambuc if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&
1775f4a2713aSLionel Sambuc Proto->isNothrow(Ctx))
1776f4a2713aSLionel Sambuc return false;
1777f4a2713aSLionel Sambuc }
1778f4a2713aSLionel Sambuc return true;
1779f4a2713aSLionel Sambuc }
1780f4a2713aSLionel Sambuc
VisitCallExpr(CallExpr * C,AddStmtChoice asc)1781f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
1782f4a2713aSLionel Sambuc // Compute the callee type.
1783f4a2713aSLionel Sambuc QualType calleeType = C->getCallee()->getType();
1784f4a2713aSLionel Sambuc if (calleeType == Context->BoundMemberTy) {
1785f4a2713aSLionel Sambuc QualType boundType = Expr::findBoundMemberType(C->getCallee());
1786f4a2713aSLionel Sambuc
1787f4a2713aSLionel Sambuc // We should only get a null bound type if processing a dependent
1788f4a2713aSLionel Sambuc // CFG. Recover by assuming nothing.
1789f4a2713aSLionel Sambuc if (!boundType.isNull()) calleeType = boundType;
1790f4a2713aSLionel Sambuc }
1791f4a2713aSLionel Sambuc
1792f4a2713aSLionel Sambuc // If this is a call to a no-return function, this stops the block here.
1793f4a2713aSLionel Sambuc bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
1794f4a2713aSLionel Sambuc
1795f4a2713aSLionel Sambuc bool AddEHEdge = false;
1796f4a2713aSLionel Sambuc
1797f4a2713aSLionel Sambuc // Languages without exceptions are assumed to not throw.
1798f4a2713aSLionel Sambuc if (Context->getLangOpts().Exceptions) {
1799f4a2713aSLionel Sambuc if (BuildOpts.AddEHEdges)
1800f4a2713aSLionel Sambuc AddEHEdge = true;
1801f4a2713aSLionel Sambuc }
1802f4a2713aSLionel Sambuc
1803f4a2713aSLionel Sambuc // If this is a call to a builtin function, it might not actually evaluate
1804f4a2713aSLionel Sambuc // its arguments. Don't add them to the CFG if this is the case.
1805f4a2713aSLionel Sambuc bool OmitArguments = false;
1806f4a2713aSLionel Sambuc
1807f4a2713aSLionel Sambuc if (FunctionDecl *FD = C->getDirectCallee()) {
1808f4a2713aSLionel Sambuc if (FD->isNoReturn())
1809f4a2713aSLionel Sambuc NoReturn = true;
1810f4a2713aSLionel Sambuc if (FD->hasAttr<NoThrowAttr>())
1811f4a2713aSLionel Sambuc AddEHEdge = false;
1812f4a2713aSLionel Sambuc if (FD->getBuiltinID() == Builtin::BI__builtin_object_size)
1813f4a2713aSLionel Sambuc OmitArguments = true;
1814f4a2713aSLionel Sambuc }
1815f4a2713aSLionel Sambuc
1816f4a2713aSLionel Sambuc if (!CanThrow(C->getCallee(), *Context))
1817f4a2713aSLionel Sambuc AddEHEdge = false;
1818f4a2713aSLionel Sambuc
1819f4a2713aSLionel Sambuc if (OmitArguments) {
1820f4a2713aSLionel Sambuc assert(!NoReturn && "noreturn calls with unevaluated args not implemented");
1821f4a2713aSLionel Sambuc assert(!AddEHEdge && "EH calls with unevaluated args not implemented");
1822f4a2713aSLionel Sambuc autoCreateBlock();
1823f4a2713aSLionel Sambuc appendStmt(Block, C);
1824f4a2713aSLionel Sambuc return Visit(C->getCallee());
1825f4a2713aSLionel Sambuc }
1826f4a2713aSLionel Sambuc
1827f4a2713aSLionel Sambuc if (!NoReturn && !AddEHEdge) {
1828f4a2713aSLionel Sambuc return VisitStmt(C, asc.withAlwaysAdd(true));
1829f4a2713aSLionel Sambuc }
1830f4a2713aSLionel Sambuc
1831f4a2713aSLionel Sambuc if (Block) {
1832f4a2713aSLionel Sambuc Succ = Block;
1833f4a2713aSLionel Sambuc if (badCFG)
1834*0a6a1f1dSLionel Sambuc return nullptr;
1835f4a2713aSLionel Sambuc }
1836f4a2713aSLionel Sambuc
1837f4a2713aSLionel Sambuc if (NoReturn)
1838f4a2713aSLionel Sambuc Block = createNoReturnBlock();
1839f4a2713aSLionel Sambuc else
1840f4a2713aSLionel Sambuc Block = createBlock();
1841f4a2713aSLionel Sambuc
1842f4a2713aSLionel Sambuc appendStmt(Block, C);
1843f4a2713aSLionel Sambuc
1844f4a2713aSLionel Sambuc if (AddEHEdge) {
1845f4a2713aSLionel Sambuc // Add exceptional edges.
1846f4a2713aSLionel Sambuc if (TryTerminatedBlock)
1847f4a2713aSLionel Sambuc addSuccessor(Block, TryTerminatedBlock);
1848f4a2713aSLionel Sambuc else
1849f4a2713aSLionel Sambuc addSuccessor(Block, &cfg->getExit());
1850f4a2713aSLionel Sambuc }
1851f4a2713aSLionel Sambuc
1852f4a2713aSLionel Sambuc return VisitChildren(C);
1853f4a2713aSLionel Sambuc }
1854f4a2713aSLionel Sambuc
VisitChooseExpr(ChooseExpr * C,AddStmtChoice asc)1855f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
1856f4a2713aSLionel Sambuc AddStmtChoice asc) {
1857f4a2713aSLionel Sambuc CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1858f4a2713aSLionel Sambuc appendStmt(ConfluenceBlock, C);
1859f4a2713aSLionel Sambuc if (badCFG)
1860*0a6a1f1dSLionel Sambuc return nullptr;
1861f4a2713aSLionel Sambuc
1862f4a2713aSLionel Sambuc AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
1863f4a2713aSLionel Sambuc Succ = ConfluenceBlock;
1864*0a6a1f1dSLionel Sambuc Block = nullptr;
1865f4a2713aSLionel Sambuc CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);
1866f4a2713aSLionel Sambuc if (badCFG)
1867*0a6a1f1dSLionel Sambuc return nullptr;
1868f4a2713aSLionel Sambuc
1869f4a2713aSLionel Sambuc Succ = ConfluenceBlock;
1870*0a6a1f1dSLionel Sambuc Block = nullptr;
1871f4a2713aSLionel Sambuc CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);
1872f4a2713aSLionel Sambuc if (badCFG)
1873*0a6a1f1dSLionel Sambuc return nullptr;
1874f4a2713aSLionel Sambuc
1875f4a2713aSLionel Sambuc Block = createBlock(false);
1876f4a2713aSLionel Sambuc // See if this is a known constant.
1877f4a2713aSLionel Sambuc const TryResult& KnownVal = tryEvaluateBool(C->getCond());
1878*0a6a1f1dSLionel Sambuc addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
1879*0a6a1f1dSLionel Sambuc addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
1880f4a2713aSLionel Sambuc Block->setTerminator(C);
1881f4a2713aSLionel Sambuc return addStmt(C->getCond());
1882f4a2713aSLionel Sambuc }
1883f4a2713aSLionel Sambuc
1884f4a2713aSLionel Sambuc
VisitCompoundStmt(CompoundStmt * C)1885f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) {
1886f4a2713aSLionel Sambuc addLocalScopeAndDtors(C);
1887f4a2713aSLionel Sambuc CFGBlock *LastBlock = Block;
1888f4a2713aSLionel Sambuc
1889f4a2713aSLionel Sambuc for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
1890f4a2713aSLionel Sambuc I != E; ++I ) {
1891f4a2713aSLionel Sambuc // If we hit a segment of code just containing ';' (NullStmts), we can
1892f4a2713aSLionel Sambuc // get a null block back. In such cases, just use the LastBlock
1893f4a2713aSLionel Sambuc if (CFGBlock *newBlock = addStmt(*I))
1894f4a2713aSLionel Sambuc LastBlock = newBlock;
1895f4a2713aSLionel Sambuc
1896f4a2713aSLionel Sambuc if (badCFG)
1897*0a6a1f1dSLionel Sambuc return nullptr;
1898f4a2713aSLionel Sambuc }
1899f4a2713aSLionel Sambuc
1900f4a2713aSLionel Sambuc return LastBlock;
1901f4a2713aSLionel Sambuc }
1902f4a2713aSLionel Sambuc
VisitConditionalOperator(AbstractConditionalOperator * C,AddStmtChoice asc)1903f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
1904f4a2713aSLionel Sambuc AddStmtChoice asc) {
1905f4a2713aSLionel Sambuc const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);
1906*0a6a1f1dSLionel Sambuc const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);
1907f4a2713aSLionel Sambuc
1908f4a2713aSLionel Sambuc // Create the confluence block that will "merge" the results of the ternary
1909f4a2713aSLionel Sambuc // expression.
1910f4a2713aSLionel Sambuc CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
1911f4a2713aSLionel Sambuc appendStmt(ConfluenceBlock, C);
1912f4a2713aSLionel Sambuc if (badCFG)
1913*0a6a1f1dSLionel Sambuc return nullptr;
1914f4a2713aSLionel Sambuc
1915f4a2713aSLionel Sambuc AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
1916f4a2713aSLionel Sambuc
1917f4a2713aSLionel Sambuc // Create a block for the LHS expression if there is an LHS expression. A
1918f4a2713aSLionel Sambuc // GCC extension allows LHS to be NULL, causing the condition to be the
1919f4a2713aSLionel Sambuc // value that is returned instead.
1920f4a2713aSLionel Sambuc // e.g: x ?: y is shorthand for: x ? x : y;
1921f4a2713aSLionel Sambuc Succ = ConfluenceBlock;
1922*0a6a1f1dSLionel Sambuc Block = nullptr;
1923*0a6a1f1dSLionel Sambuc CFGBlock *LHSBlock = nullptr;
1924f4a2713aSLionel Sambuc const Expr *trueExpr = C->getTrueExpr();
1925f4a2713aSLionel Sambuc if (trueExpr != opaqueValue) {
1926f4a2713aSLionel Sambuc LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
1927f4a2713aSLionel Sambuc if (badCFG)
1928*0a6a1f1dSLionel Sambuc return nullptr;
1929*0a6a1f1dSLionel Sambuc Block = nullptr;
1930f4a2713aSLionel Sambuc }
1931f4a2713aSLionel Sambuc else
1932f4a2713aSLionel Sambuc LHSBlock = ConfluenceBlock;
1933f4a2713aSLionel Sambuc
1934f4a2713aSLionel Sambuc // Create the block for the RHS expression.
1935f4a2713aSLionel Sambuc Succ = ConfluenceBlock;
1936f4a2713aSLionel Sambuc CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
1937f4a2713aSLionel Sambuc if (badCFG)
1938*0a6a1f1dSLionel Sambuc return nullptr;
1939f4a2713aSLionel Sambuc
1940f4a2713aSLionel Sambuc // If the condition is a logical '&&' or '||', build a more accurate CFG.
1941f4a2713aSLionel Sambuc if (BinaryOperator *Cond =
1942f4a2713aSLionel Sambuc dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens()))
1943f4a2713aSLionel Sambuc if (Cond->isLogicalOp())
1944f4a2713aSLionel Sambuc return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
1945f4a2713aSLionel Sambuc
1946f4a2713aSLionel Sambuc // Create the block that will contain the condition.
1947f4a2713aSLionel Sambuc Block = createBlock(false);
1948f4a2713aSLionel Sambuc
1949f4a2713aSLionel Sambuc // See if this is a known constant.
1950f4a2713aSLionel Sambuc const TryResult& KnownVal = tryEvaluateBool(C->getCond());
1951*0a6a1f1dSLionel Sambuc addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
1952*0a6a1f1dSLionel Sambuc addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
1953f4a2713aSLionel Sambuc Block->setTerminator(C);
1954f4a2713aSLionel Sambuc Expr *condExpr = C->getCond();
1955f4a2713aSLionel Sambuc
1956f4a2713aSLionel Sambuc if (opaqueValue) {
1957f4a2713aSLionel Sambuc // Run the condition expression if it's not trivially expressed in
1958f4a2713aSLionel Sambuc // terms of the opaque value (or if there is no opaque value).
1959f4a2713aSLionel Sambuc if (condExpr != opaqueValue)
1960f4a2713aSLionel Sambuc addStmt(condExpr);
1961f4a2713aSLionel Sambuc
1962f4a2713aSLionel Sambuc // Before that, run the common subexpression if there was one.
1963f4a2713aSLionel Sambuc // At least one of this or the above will be run.
1964f4a2713aSLionel Sambuc return addStmt(BCO->getCommon());
1965f4a2713aSLionel Sambuc }
1966f4a2713aSLionel Sambuc
1967f4a2713aSLionel Sambuc return addStmt(condExpr);
1968f4a2713aSLionel Sambuc }
1969f4a2713aSLionel Sambuc
VisitDeclStmt(DeclStmt * DS)1970f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
1971f4a2713aSLionel Sambuc // Check if the Decl is for an __label__. If so, elide it from the
1972f4a2713aSLionel Sambuc // CFG entirely.
1973f4a2713aSLionel Sambuc if (isa<LabelDecl>(*DS->decl_begin()))
1974f4a2713aSLionel Sambuc return Block;
1975f4a2713aSLionel Sambuc
1976f4a2713aSLionel Sambuc // This case also handles static_asserts.
1977f4a2713aSLionel Sambuc if (DS->isSingleDecl())
1978f4a2713aSLionel Sambuc return VisitDeclSubExpr(DS);
1979f4a2713aSLionel Sambuc
1980*0a6a1f1dSLionel Sambuc CFGBlock *B = nullptr;
1981f4a2713aSLionel Sambuc
1982f4a2713aSLionel Sambuc // Build an individual DeclStmt for each decl.
1983f4a2713aSLionel Sambuc for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),
1984f4a2713aSLionel Sambuc E = DS->decl_rend();
1985f4a2713aSLionel Sambuc I != E; ++I) {
1986f4a2713aSLionel Sambuc // Get the alignment of the new DeclStmt, padding out to >=8 bytes.
1987f4a2713aSLionel Sambuc unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
1988f4a2713aSLionel Sambuc ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
1989f4a2713aSLionel Sambuc
1990f4a2713aSLionel Sambuc // Allocate the DeclStmt using the BumpPtrAllocator. It will get
1991f4a2713aSLionel Sambuc // automatically freed with the CFG.
1992f4a2713aSLionel Sambuc DeclGroupRef DG(*I);
1993f4a2713aSLionel Sambuc Decl *D = *I;
1994f4a2713aSLionel Sambuc void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
1995f4a2713aSLionel Sambuc DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
1996f4a2713aSLionel Sambuc cfg->addSyntheticDeclStmt(DSNew, DS);
1997f4a2713aSLionel Sambuc
1998f4a2713aSLionel Sambuc // Append the fake DeclStmt to block.
1999f4a2713aSLionel Sambuc B = VisitDeclSubExpr(DSNew);
2000f4a2713aSLionel Sambuc }
2001f4a2713aSLionel Sambuc
2002f4a2713aSLionel Sambuc return B;
2003f4a2713aSLionel Sambuc }
2004f4a2713aSLionel Sambuc
2005f4a2713aSLionel Sambuc /// VisitDeclSubExpr - Utility method to add block-level expressions for
2006f4a2713aSLionel Sambuc /// DeclStmts and initializers in them.
VisitDeclSubExpr(DeclStmt * DS)2007f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
2008f4a2713aSLionel Sambuc assert(DS->isSingleDecl() && "Can handle single declarations only.");
2009f4a2713aSLionel Sambuc VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
2010f4a2713aSLionel Sambuc
2011f4a2713aSLionel Sambuc if (!VD) {
2012f4a2713aSLionel Sambuc // Of everything that can be declared in a DeclStmt, only VarDecls impact
2013f4a2713aSLionel Sambuc // runtime semantics.
2014f4a2713aSLionel Sambuc return Block;
2015f4a2713aSLionel Sambuc }
2016f4a2713aSLionel Sambuc
2017f4a2713aSLionel Sambuc bool HasTemporaries = false;
2018f4a2713aSLionel Sambuc
2019f4a2713aSLionel Sambuc // Guard static initializers under a branch.
2020*0a6a1f1dSLionel Sambuc CFGBlock *blockAfterStaticInit = nullptr;
2021f4a2713aSLionel Sambuc
2022f4a2713aSLionel Sambuc if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2023f4a2713aSLionel Sambuc // For static variables, we need to create a branch to track
2024f4a2713aSLionel Sambuc // whether or not they are initialized.
2025f4a2713aSLionel Sambuc if (Block) {
2026f4a2713aSLionel Sambuc Succ = Block;
2027*0a6a1f1dSLionel Sambuc Block = nullptr;
2028f4a2713aSLionel Sambuc if (badCFG)
2029*0a6a1f1dSLionel Sambuc return nullptr;
2030f4a2713aSLionel Sambuc }
2031f4a2713aSLionel Sambuc blockAfterStaticInit = Succ;
2032f4a2713aSLionel Sambuc }
2033f4a2713aSLionel Sambuc
2034f4a2713aSLionel Sambuc // Destructors of temporaries in initialization expression should be called
2035f4a2713aSLionel Sambuc // after initialization finishes.
2036f4a2713aSLionel Sambuc Expr *Init = VD->getInit();
2037f4a2713aSLionel Sambuc if (Init) {
2038f4a2713aSLionel Sambuc HasTemporaries = isa<ExprWithCleanups>(Init);
2039f4a2713aSLionel Sambuc
2040f4a2713aSLionel Sambuc if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2041f4a2713aSLionel Sambuc // Generate destructors for temporaries in initialization expression.
2042*0a6a1f1dSLionel Sambuc TempDtorContext Context;
2043f4a2713aSLionel Sambuc VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2044*0a6a1f1dSLionel Sambuc /*BindToTemporary=*/false, Context);
2045f4a2713aSLionel Sambuc }
2046f4a2713aSLionel Sambuc }
2047f4a2713aSLionel Sambuc
2048f4a2713aSLionel Sambuc autoCreateBlock();
2049f4a2713aSLionel Sambuc appendStmt(Block, DS);
2050f4a2713aSLionel Sambuc
2051f4a2713aSLionel Sambuc // Keep track of the last non-null block, as 'Block' can be nulled out
2052f4a2713aSLionel Sambuc // if the initializer expression is something like a 'while' in a
2053f4a2713aSLionel Sambuc // statement-expression.
2054f4a2713aSLionel Sambuc CFGBlock *LastBlock = Block;
2055f4a2713aSLionel Sambuc
2056f4a2713aSLionel Sambuc if (Init) {
2057f4a2713aSLionel Sambuc if (HasTemporaries) {
2058f4a2713aSLionel Sambuc // For expression with temporaries go directly to subexpression to omit
2059f4a2713aSLionel Sambuc // generating destructors for the second time.
2060f4a2713aSLionel Sambuc ExprWithCleanups *EC = cast<ExprWithCleanups>(Init);
2061f4a2713aSLionel Sambuc if (CFGBlock *newBlock = Visit(EC->getSubExpr()))
2062f4a2713aSLionel Sambuc LastBlock = newBlock;
2063f4a2713aSLionel Sambuc }
2064f4a2713aSLionel Sambuc else {
2065f4a2713aSLionel Sambuc if (CFGBlock *newBlock = Visit(Init))
2066f4a2713aSLionel Sambuc LastBlock = newBlock;
2067f4a2713aSLionel Sambuc }
2068f4a2713aSLionel Sambuc }
2069f4a2713aSLionel Sambuc
2070f4a2713aSLionel Sambuc // If the type of VD is a VLA, then we must process its size expressions.
2071f4a2713aSLionel Sambuc for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());
2072*0a6a1f1dSLionel Sambuc VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {
2073f4a2713aSLionel Sambuc if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
2074f4a2713aSLionel Sambuc LastBlock = newBlock;
2075f4a2713aSLionel Sambuc }
2076f4a2713aSLionel Sambuc
2077f4a2713aSLionel Sambuc // Remove variable from local scope.
2078f4a2713aSLionel Sambuc if (ScopePos && VD == *ScopePos)
2079f4a2713aSLionel Sambuc ++ScopePos;
2080f4a2713aSLionel Sambuc
2081f4a2713aSLionel Sambuc CFGBlock *B = LastBlock;
2082f4a2713aSLionel Sambuc if (blockAfterStaticInit) {
2083f4a2713aSLionel Sambuc Succ = B;
2084f4a2713aSLionel Sambuc Block = createBlock(false);
2085f4a2713aSLionel Sambuc Block->setTerminator(DS);
2086f4a2713aSLionel Sambuc addSuccessor(Block, blockAfterStaticInit);
2087f4a2713aSLionel Sambuc addSuccessor(Block, B);
2088f4a2713aSLionel Sambuc B = Block;
2089f4a2713aSLionel Sambuc }
2090f4a2713aSLionel Sambuc
2091f4a2713aSLionel Sambuc return B;
2092f4a2713aSLionel Sambuc }
2093f4a2713aSLionel Sambuc
VisitIfStmt(IfStmt * I)2094f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
2095f4a2713aSLionel Sambuc // We may see an if statement in the middle of a basic block, or it may be the
2096f4a2713aSLionel Sambuc // first statement we are processing. In either case, we create a new basic
2097f4a2713aSLionel Sambuc // block. First, we create the blocks for the then...else statements, and
2098f4a2713aSLionel Sambuc // then we create the block containing the if statement. If we were in the
2099f4a2713aSLionel Sambuc // middle of a block, we stop processing that block. That block is then the
2100f4a2713aSLionel Sambuc // implicit successor for the "then" and "else" clauses.
2101f4a2713aSLionel Sambuc
2102f4a2713aSLionel Sambuc // Save local scope position because in case of condition variable ScopePos
2103f4a2713aSLionel Sambuc // won't be restored when traversing AST.
2104f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
2105f4a2713aSLionel Sambuc
2106f4a2713aSLionel Sambuc // Create local scope for possible condition variable.
2107f4a2713aSLionel Sambuc // Store scope position. Add implicit destructor.
2108f4a2713aSLionel Sambuc if (VarDecl *VD = I->getConditionVariable()) {
2109f4a2713aSLionel Sambuc LocalScope::const_iterator BeginScopePos = ScopePos;
2110f4a2713aSLionel Sambuc addLocalScopeForVarDecl(VD);
2111f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, BeginScopePos, I);
2112f4a2713aSLionel Sambuc }
2113f4a2713aSLionel Sambuc
2114f4a2713aSLionel Sambuc // The block we were processing is now finished. Make it the successor
2115f4a2713aSLionel Sambuc // block.
2116f4a2713aSLionel Sambuc if (Block) {
2117f4a2713aSLionel Sambuc Succ = Block;
2118f4a2713aSLionel Sambuc if (badCFG)
2119*0a6a1f1dSLionel Sambuc return nullptr;
2120f4a2713aSLionel Sambuc }
2121f4a2713aSLionel Sambuc
2122f4a2713aSLionel Sambuc // Process the false branch.
2123f4a2713aSLionel Sambuc CFGBlock *ElseBlock = Succ;
2124f4a2713aSLionel Sambuc
2125f4a2713aSLionel Sambuc if (Stmt *Else = I->getElse()) {
2126f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> sv(Succ);
2127f4a2713aSLionel Sambuc
2128f4a2713aSLionel Sambuc // NULL out Block so that the recursive call to Visit will
2129f4a2713aSLionel Sambuc // create a new basic block.
2130*0a6a1f1dSLionel Sambuc Block = nullptr;
2131f4a2713aSLionel Sambuc
2132f4a2713aSLionel Sambuc // If branch is not a compound statement create implicit scope
2133f4a2713aSLionel Sambuc // and add destructors.
2134f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(Else))
2135f4a2713aSLionel Sambuc addLocalScopeAndDtors(Else);
2136f4a2713aSLionel Sambuc
2137f4a2713aSLionel Sambuc ElseBlock = addStmt(Else);
2138f4a2713aSLionel Sambuc
2139f4a2713aSLionel Sambuc if (!ElseBlock) // Can occur when the Else body has all NullStmts.
2140f4a2713aSLionel Sambuc ElseBlock = sv.get();
2141f4a2713aSLionel Sambuc else if (Block) {
2142f4a2713aSLionel Sambuc if (badCFG)
2143*0a6a1f1dSLionel Sambuc return nullptr;
2144f4a2713aSLionel Sambuc }
2145f4a2713aSLionel Sambuc }
2146f4a2713aSLionel Sambuc
2147f4a2713aSLionel Sambuc // Process the true branch.
2148f4a2713aSLionel Sambuc CFGBlock *ThenBlock;
2149f4a2713aSLionel Sambuc {
2150f4a2713aSLionel Sambuc Stmt *Then = I->getThen();
2151f4a2713aSLionel Sambuc assert(Then);
2152f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> sv(Succ);
2153*0a6a1f1dSLionel Sambuc Block = nullptr;
2154f4a2713aSLionel Sambuc
2155f4a2713aSLionel Sambuc // If branch is not a compound statement create implicit scope
2156f4a2713aSLionel Sambuc // and add destructors.
2157f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(Then))
2158f4a2713aSLionel Sambuc addLocalScopeAndDtors(Then);
2159f4a2713aSLionel Sambuc
2160f4a2713aSLionel Sambuc ThenBlock = addStmt(Then);
2161f4a2713aSLionel Sambuc
2162f4a2713aSLionel Sambuc if (!ThenBlock) {
2163f4a2713aSLionel Sambuc // We can reach here if the "then" body has all NullStmts.
2164f4a2713aSLionel Sambuc // Create an empty block so we can distinguish between true and false
2165f4a2713aSLionel Sambuc // branches in path-sensitive analyses.
2166f4a2713aSLionel Sambuc ThenBlock = createBlock(false);
2167f4a2713aSLionel Sambuc addSuccessor(ThenBlock, sv.get());
2168f4a2713aSLionel Sambuc } else if (Block) {
2169f4a2713aSLionel Sambuc if (badCFG)
2170*0a6a1f1dSLionel Sambuc return nullptr;
2171f4a2713aSLionel Sambuc }
2172f4a2713aSLionel Sambuc }
2173f4a2713aSLionel Sambuc
2174f4a2713aSLionel Sambuc // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by
2175f4a2713aSLionel Sambuc // having these handle the actual control-flow jump. Note that
2176f4a2713aSLionel Sambuc // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)"
2177f4a2713aSLionel Sambuc // we resort to the old control-flow behavior. This special handling
2178f4a2713aSLionel Sambuc // removes infeasible paths from the control-flow graph by having the
2179f4a2713aSLionel Sambuc // control-flow transfer of '&&' or '||' go directly into the then/else
2180f4a2713aSLionel Sambuc // blocks directly.
2181f4a2713aSLionel Sambuc if (!I->getConditionVariable())
2182f4a2713aSLionel Sambuc if (BinaryOperator *Cond =
2183f4a2713aSLionel Sambuc dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens()))
2184f4a2713aSLionel Sambuc if (Cond->isLogicalOp())
2185f4a2713aSLionel Sambuc return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
2186f4a2713aSLionel Sambuc
2187f4a2713aSLionel Sambuc // Now create a new block containing the if statement.
2188f4a2713aSLionel Sambuc Block = createBlock(false);
2189f4a2713aSLionel Sambuc
2190f4a2713aSLionel Sambuc // Set the terminator of the new block to the If statement.
2191f4a2713aSLionel Sambuc Block->setTerminator(I);
2192f4a2713aSLionel Sambuc
2193f4a2713aSLionel Sambuc // See if this is a known constant.
2194f4a2713aSLionel Sambuc const TryResult &KnownVal = tryEvaluateBool(I->getCond());
2195f4a2713aSLionel Sambuc
2196*0a6a1f1dSLionel Sambuc // Add the successors. If we know that specific branches are
2197*0a6a1f1dSLionel Sambuc // unreachable, inform addSuccessor() of that knowledge.
2198*0a6a1f1dSLionel Sambuc addSuccessor(Block, ThenBlock, /* isReachable = */ !KnownVal.isFalse());
2199*0a6a1f1dSLionel Sambuc addSuccessor(Block, ElseBlock, /* isReachable = */ !KnownVal.isTrue());
2200f4a2713aSLionel Sambuc
2201f4a2713aSLionel Sambuc // Add the condition as the last statement in the new block. This may create
2202f4a2713aSLionel Sambuc // new blocks as the condition may contain control-flow. Any newly created
2203f4a2713aSLionel Sambuc // blocks will be pointed to be "Block".
2204f4a2713aSLionel Sambuc CFGBlock *LastBlock = addStmt(I->getCond());
2205f4a2713aSLionel Sambuc
2206*0a6a1f1dSLionel Sambuc // Finally, if the IfStmt contains a condition variable, add it and its
2207*0a6a1f1dSLionel Sambuc // initializer to the CFG.
2208*0a6a1f1dSLionel Sambuc if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {
2209f4a2713aSLionel Sambuc autoCreateBlock();
2210*0a6a1f1dSLionel Sambuc LastBlock = addStmt(const_cast<DeclStmt *>(DS));
2211f4a2713aSLionel Sambuc }
2212f4a2713aSLionel Sambuc
2213f4a2713aSLionel Sambuc return LastBlock;
2214f4a2713aSLionel Sambuc }
2215f4a2713aSLionel Sambuc
2216f4a2713aSLionel Sambuc
VisitReturnStmt(ReturnStmt * R)2217f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) {
2218f4a2713aSLionel Sambuc // If we were in the middle of a block we stop processing that block.
2219f4a2713aSLionel Sambuc //
2220f4a2713aSLionel Sambuc // NOTE: If a "return" appears in the middle of a block, this means that the
2221f4a2713aSLionel Sambuc // code afterwards is DEAD (unreachable). We still keep a basic block
2222f4a2713aSLionel Sambuc // for that code; a simple "mark-and-sweep" from the entry block will be
2223f4a2713aSLionel Sambuc // able to report such dead blocks.
2224f4a2713aSLionel Sambuc
2225f4a2713aSLionel Sambuc // Create the new block.
2226f4a2713aSLionel Sambuc Block = createBlock(false);
2227f4a2713aSLionel Sambuc
2228f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
2229f4a2713aSLionel Sambuc
2230f4a2713aSLionel Sambuc // If the one of the destructors does not return, we already have the Exit
2231f4a2713aSLionel Sambuc // block as a successor.
2232f4a2713aSLionel Sambuc if (!Block->hasNoReturnElement())
2233f4a2713aSLionel Sambuc addSuccessor(Block, &cfg->getExit());
2234f4a2713aSLionel Sambuc
2235f4a2713aSLionel Sambuc // Add the return statement to the block. This may create new blocks if R
2236f4a2713aSLionel Sambuc // contains control-flow (short-circuit operations).
2237f4a2713aSLionel Sambuc return VisitStmt(R, AddStmtChoice::AlwaysAdd);
2238f4a2713aSLionel Sambuc }
2239f4a2713aSLionel Sambuc
VisitLabelStmt(LabelStmt * L)2240f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
2241f4a2713aSLionel Sambuc // Get the block of the labeled statement. Add it to our map.
2242f4a2713aSLionel Sambuc addStmt(L->getSubStmt());
2243f4a2713aSLionel Sambuc CFGBlock *LabelBlock = Block;
2244f4a2713aSLionel Sambuc
2245f4a2713aSLionel Sambuc if (!LabelBlock) // This can happen when the body is empty, i.e.
2246f4a2713aSLionel Sambuc LabelBlock = createBlock(); // scopes that only contains NullStmts.
2247f4a2713aSLionel Sambuc
2248f4a2713aSLionel Sambuc assert(LabelMap.find(L->getDecl()) == LabelMap.end() &&
2249f4a2713aSLionel Sambuc "label already in map");
2250f4a2713aSLionel Sambuc LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
2251f4a2713aSLionel Sambuc
2252f4a2713aSLionel Sambuc // Labels partition blocks, so this is the end of the basic block we were
2253f4a2713aSLionel Sambuc // processing (L is the block's label). Because this is label (and we have
2254f4a2713aSLionel Sambuc // already processed the substatement) there is no extra control-flow to worry
2255f4a2713aSLionel Sambuc // about.
2256f4a2713aSLionel Sambuc LabelBlock->setLabel(L);
2257f4a2713aSLionel Sambuc if (badCFG)
2258*0a6a1f1dSLionel Sambuc return nullptr;
2259f4a2713aSLionel Sambuc
2260f4a2713aSLionel Sambuc // We set Block to NULL to allow lazy creation of a new block (if necessary);
2261*0a6a1f1dSLionel Sambuc Block = nullptr;
2262f4a2713aSLionel Sambuc
2263f4a2713aSLionel Sambuc // This block is now the implicit successor of other blocks.
2264f4a2713aSLionel Sambuc Succ = LabelBlock;
2265f4a2713aSLionel Sambuc
2266f4a2713aSLionel Sambuc return LabelBlock;
2267f4a2713aSLionel Sambuc }
2268f4a2713aSLionel Sambuc
VisitLambdaExpr(LambdaExpr * E,AddStmtChoice asc)2269f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
2270f4a2713aSLionel Sambuc CFGBlock *LastBlock = VisitNoRecurse(E, asc);
2271f4a2713aSLionel Sambuc for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(),
2272f4a2713aSLionel Sambuc et = E->capture_init_end(); it != et; ++it) {
2273f4a2713aSLionel Sambuc if (Expr *Init = *it) {
2274f4a2713aSLionel Sambuc CFGBlock *Tmp = Visit(Init);
2275*0a6a1f1dSLionel Sambuc if (Tmp)
2276f4a2713aSLionel Sambuc LastBlock = Tmp;
2277f4a2713aSLionel Sambuc }
2278f4a2713aSLionel Sambuc }
2279f4a2713aSLionel Sambuc return LastBlock;
2280f4a2713aSLionel Sambuc }
2281f4a2713aSLionel Sambuc
VisitGotoStmt(GotoStmt * G)2282f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
2283f4a2713aSLionel Sambuc // Goto is a control-flow statement. Thus we stop processing the current
2284f4a2713aSLionel Sambuc // block and create a new one.
2285f4a2713aSLionel Sambuc
2286f4a2713aSLionel Sambuc Block = createBlock(false);
2287f4a2713aSLionel Sambuc Block->setTerminator(G);
2288f4a2713aSLionel Sambuc
2289f4a2713aSLionel Sambuc // If we already know the mapping to the label block add the successor now.
2290f4a2713aSLionel Sambuc LabelMapTy::iterator I = LabelMap.find(G->getLabel());
2291f4a2713aSLionel Sambuc
2292f4a2713aSLionel Sambuc if (I == LabelMap.end())
2293f4a2713aSLionel Sambuc // We will need to backpatch this block later.
2294f4a2713aSLionel Sambuc BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
2295f4a2713aSLionel Sambuc else {
2296f4a2713aSLionel Sambuc JumpTarget JT = I->second;
2297f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, JT.scopePosition, G);
2298f4a2713aSLionel Sambuc addSuccessor(Block, JT.block);
2299f4a2713aSLionel Sambuc }
2300f4a2713aSLionel Sambuc
2301f4a2713aSLionel Sambuc return Block;
2302f4a2713aSLionel Sambuc }
2303f4a2713aSLionel Sambuc
VisitForStmt(ForStmt * F)2304f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
2305*0a6a1f1dSLionel Sambuc CFGBlock *LoopSuccessor = nullptr;
2306f4a2713aSLionel Sambuc
2307f4a2713aSLionel Sambuc // Save local scope position because in case of condition variable ScopePos
2308f4a2713aSLionel Sambuc // won't be restored when traversing AST.
2309f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
2310f4a2713aSLionel Sambuc
2311f4a2713aSLionel Sambuc // Create local scope for init statement and possible condition variable.
2312f4a2713aSLionel Sambuc // Add destructor for init statement and condition variable.
2313f4a2713aSLionel Sambuc // Store scope position for continue statement.
2314f4a2713aSLionel Sambuc if (Stmt *Init = F->getInit())
2315f4a2713aSLionel Sambuc addLocalScopeForStmt(Init);
2316f4a2713aSLionel Sambuc LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2317f4a2713aSLionel Sambuc
2318f4a2713aSLionel Sambuc if (VarDecl *VD = F->getConditionVariable())
2319f4a2713aSLionel Sambuc addLocalScopeForVarDecl(VD);
2320f4a2713aSLionel Sambuc LocalScope::const_iterator ContinueScopePos = ScopePos;
2321f4a2713aSLionel Sambuc
2322f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
2323f4a2713aSLionel Sambuc
2324f4a2713aSLionel Sambuc // "for" is a control-flow statement. Thus we stop processing the current
2325f4a2713aSLionel Sambuc // block.
2326f4a2713aSLionel Sambuc if (Block) {
2327f4a2713aSLionel Sambuc if (badCFG)
2328*0a6a1f1dSLionel Sambuc return nullptr;
2329f4a2713aSLionel Sambuc LoopSuccessor = Block;
2330f4a2713aSLionel Sambuc } else
2331f4a2713aSLionel Sambuc LoopSuccessor = Succ;
2332f4a2713aSLionel Sambuc
2333f4a2713aSLionel Sambuc // Save the current value for the break targets.
2334f4a2713aSLionel Sambuc // All breaks should go to the code following the loop.
2335f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
2336f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2337f4a2713aSLionel Sambuc
2338*0a6a1f1dSLionel Sambuc CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
2339f4a2713aSLionel Sambuc
2340f4a2713aSLionel Sambuc // Now create the loop body.
2341f4a2713aSLionel Sambuc {
2342f4a2713aSLionel Sambuc assert(F->getBody());
2343f4a2713aSLionel Sambuc
2344f4a2713aSLionel Sambuc // Save the current values for Block, Succ, continue and break targets.
2345f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
2346f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
2347f4a2713aSLionel Sambuc
2348f4a2713aSLionel Sambuc // Create an empty block to represent the transition block for looping back
2349f4a2713aSLionel Sambuc // to the head of the loop. If we have increment code, it will
2350f4a2713aSLionel Sambuc // go in this block as well.
2351f4a2713aSLionel Sambuc Block = Succ = TransitionBlock = createBlock(false);
2352f4a2713aSLionel Sambuc TransitionBlock->setLoopTarget(F);
2353f4a2713aSLionel Sambuc
2354f4a2713aSLionel Sambuc if (Stmt *I = F->getInc()) {
2355f4a2713aSLionel Sambuc // Generate increment code in its own basic block. This is the target of
2356f4a2713aSLionel Sambuc // continue statements.
2357f4a2713aSLionel Sambuc Succ = addStmt(I);
2358f4a2713aSLionel Sambuc }
2359f4a2713aSLionel Sambuc
2360f4a2713aSLionel Sambuc // Finish up the increment (or empty) block if it hasn't been already.
2361f4a2713aSLionel Sambuc if (Block) {
2362f4a2713aSLionel Sambuc assert(Block == Succ);
2363f4a2713aSLionel Sambuc if (badCFG)
2364*0a6a1f1dSLionel Sambuc return nullptr;
2365*0a6a1f1dSLionel Sambuc Block = nullptr;
2366f4a2713aSLionel Sambuc }
2367f4a2713aSLionel Sambuc
2368f4a2713aSLionel Sambuc // The starting block for the loop increment is the block that should
2369f4a2713aSLionel Sambuc // represent the 'loop target' for looping back to the start of the loop.
2370f4a2713aSLionel Sambuc ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
2371f4a2713aSLionel Sambuc ContinueJumpTarget.block->setLoopTarget(F);
2372f4a2713aSLionel Sambuc
2373f4a2713aSLionel Sambuc // Loop body should end with destructor of Condition variable (if any).
2374f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F);
2375f4a2713aSLionel Sambuc
2376f4a2713aSLionel Sambuc // If body is not a compound statement create implicit scope
2377f4a2713aSLionel Sambuc // and add destructors.
2378f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(F->getBody()))
2379f4a2713aSLionel Sambuc addLocalScopeAndDtors(F->getBody());
2380f4a2713aSLionel Sambuc
2381f4a2713aSLionel Sambuc // Now populate the body block, and in the process create new blocks as we
2382f4a2713aSLionel Sambuc // walk the body of the loop.
2383f4a2713aSLionel Sambuc BodyBlock = addStmt(F->getBody());
2384f4a2713aSLionel Sambuc
2385f4a2713aSLionel Sambuc if (!BodyBlock) {
2386f4a2713aSLionel Sambuc // In the case of "for (...;...;...);" we can have a null BodyBlock.
2387f4a2713aSLionel Sambuc // Use the continue jump target as the proxy for the body.
2388f4a2713aSLionel Sambuc BodyBlock = ContinueJumpTarget.block;
2389f4a2713aSLionel Sambuc }
2390f4a2713aSLionel Sambuc else if (badCFG)
2391*0a6a1f1dSLionel Sambuc return nullptr;
2392f4a2713aSLionel Sambuc }
2393f4a2713aSLionel Sambuc
2394f4a2713aSLionel Sambuc // Because of short-circuit evaluation, the condition of the loop can span
2395f4a2713aSLionel Sambuc // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
2396f4a2713aSLionel Sambuc // evaluate the condition.
2397*0a6a1f1dSLionel Sambuc CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
2398f4a2713aSLionel Sambuc
2399f4a2713aSLionel Sambuc do {
2400f4a2713aSLionel Sambuc Expr *C = F->getCond();
2401f4a2713aSLionel Sambuc
2402f4a2713aSLionel Sambuc // Specially handle logical operators, which have a slightly
2403f4a2713aSLionel Sambuc // more optimal CFG representation.
2404f4a2713aSLionel Sambuc if (BinaryOperator *Cond =
2405*0a6a1f1dSLionel Sambuc dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr))
2406f4a2713aSLionel Sambuc if (Cond->isLogicalOp()) {
2407*0a6a1f1dSLionel Sambuc std::tie(EntryConditionBlock, ExitConditionBlock) =
2408f4a2713aSLionel Sambuc VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
2409f4a2713aSLionel Sambuc break;
2410f4a2713aSLionel Sambuc }
2411f4a2713aSLionel Sambuc
2412f4a2713aSLionel Sambuc // The default case when not handling logical operators.
2413f4a2713aSLionel Sambuc EntryConditionBlock = ExitConditionBlock = createBlock(false);
2414f4a2713aSLionel Sambuc ExitConditionBlock->setTerminator(F);
2415f4a2713aSLionel Sambuc
2416f4a2713aSLionel Sambuc // See if this is a known constant.
2417f4a2713aSLionel Sambuc TryResult KnownVal(true);
2418f4a2713aSLionel Sambuc
2419f4a2713aSLionel Sambuc if (C) {
2420f4a2713aSLionel Sambuc // Now add the actual condition to the condition block.
2421f4a2713aSLionel Sambuc // Because the condition itself may contain control-flow, new blocks may
2422f4a2713aSLionel Sambuc // be created. Thus we update "Succ" after adding the condition.
2423f4a2713aSLionel Sambuc Block = ExitConditionBlock;
2424f4a2713aSLionel Sambuc EntryConditionBlock = addStmt(C);
2425f4a2713aSLionel Sambuc
2426f4a2713aSLionel Sambuc // If this block contains a condition variable, add both the condition
2427f4a2713aSLionel Sambuc // variable and initializer to the CFG.
2428f4a2713aSLionel Sambuc if (VarDecl *VD = F->getConditionVariable()) {
2429f4a2713aSLionel Sambuc if (Expr *Init = VD->getInit()) {
2430f4a2713aSLionel Sambuc autoCreateBlock();
2431f4a2713aSLionel Sambuc appendStmt(Block, F->getConditionVariableDeclStmt());
2432f4a2713aSLionel Sambuc EntryConditionBlock = addStmt(Init);
2433f4a2713aSLionel Sambuc assert(Block == EntryConditionBlock);
2434f4a2713aSLionel Sambuc }
2435f4a2713aSLionel Sambuc }
2436f4a2713aSLionel Sambuc
2437f4a2713aSLionel Sambuc if (Block && badCFG)
2438*0a6a1f1dSLionel Sambuc return nullptr;
2439f4a2713aSLionel Sambuc
2440f4a2713aSLionel Sambuc KnownVal = tryEvaluateBool(C);
2441f4a2713aSLionel Sambuc }
2442f4a2713aSLionel Sambuc
2443f4a2713aSLionel Sambuc // Add the loop body entry as a successor to the condition.
2444*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
2445f4a2713aSLionel Sambuc // Link up the condition block with the code that follows the loop. (the
2446f4a2713aSLionel Sambuc // false branch).
2447*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock,
2448*0a6a1f1dSLionel Sambuc KnownVal.isTrue() ? nullptr : LoopSuccessor);
2449f4a2713aSLionel Sambuc
2450f4a2713aSLionel Sambuc } while (false);
2451f4a2713aSLionel Sambuc
2452f4a2713aSLionel Sambuc // Link up the loop-back block to the entry condition block.
2453f4a2713aSLionel Sambuc addSuccessor(TransitionBlock, EntryConditionBlock);
2454f4a2713aSLionel Sambuc
2455f4a2713aSLionel Sambuc // The condition block is the implicit successor for any code above the loop.
2456f4a2713aSLionel Sambuc Succ = EntryConditionBlock;
2457f4a2713aSLionel Sambuc
2458f4a2713aSLionel Sambuc // If the loop contains initialization, create a new block for those
2459f4a2713aSLionel Sambuc // statements. This block can also contain statements that precede the loop.
2460f4a2713aSLionel Sambuc if (Stmt *I = F->getInit()) {
2461f4a2713aSLionel Sambuc Block = createBlock();
2462f4a2713aSLionel Sambuc return addStmt(I);
2463f4a2713aSLionel Sambuc }
2464f4a2713aSLionel Sambuc
2465f4a2713aSLionel Sambuc // There is no loop initialization. We are thus basically a while loop.
2466f4a2713aSLionel Sambuc // NULL out Block to force lazy block construction.
2467*0a6a1f1dSLionel Sambuc Block = nullptr;
2468f4a2713aSLionel Sambuc Succ = EntryConditionBlock;
2469f4a2713aSLionel Sambuc return EntryConditionBlock;
2470f4a2713aSLionel Sambuc }
2471f4a2713aSLionel Sambuc
VisitMemberExpr(MemberExpr * M,AddStmtChoice asc)2472f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
2473f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, M)) {
2474f4a2713aSLionel Sambuc autoCreateBlock();
2475f4a2713aSLionel Sambuc appendStmt(Block, M);
2476f4a2713aSLionel Sambuc }
2477f4a2713aSLionel Sambuc return Visit(M->getBase());
2478f4a2713aSLionel Sambuc }
2479f4a2713aSLionel Sambuc
VisitObjCForCollectionStmt(ObjCForCollectionStmt * S)2480f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
2481f4a2713aSLionel Sambuc // Objective-C fast enumeration 'for' statements:
2482f4a2713aSLionel Sambuc // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
2483f4a2713aSLionel Sambuc //
2484f4a2713aSLionel Sambuc // for ( Type newVariable in collection_expression ) { statements }
2485f4a2713aSLionel Sambuc //
2486f4a2713aSLionel Sambuc // becomes:
2487f4a2713aSLionel Sambuc //
2488f4a2713aSLionel Sambuc // prologue:
2489f4a2713aSLionel Sambuc // 1. collection_expression
2490f4a2713aSLionel Sambuc // T. jump to loop_entry
2491f4a2713aSLionel Sambuc // loop_entry:
2492f4a2713aSLionel Sambuc // 1. side-effects of element expression
2493f4a2713aSLionel Sambuc // 1. ObjCForCollectionStmt [performs binding to newVariable]
2494f4a2713aSLionel Sambuc // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]
2495f4a2713aSLionel Sambuc // TB:
2496f4a2713aSLionel Sambuc // statements
2497f4a2713aSLionel Sambuc // T. jump to loop_entry
2498f4a2713aSLionel Sambuc // FB:
2499f4a2713aSLionel Sambuc // what comes after
2500f4a2713aSLionel Sambuc //
2501f4a2713aSLionel Sambuc // and
2502f4a2713aSLionel Sambuc //
2503f4a2713aSLionel Sambuc // Type existingItem;
2504f4a2713aSLionel Sambuc // for ( existingItem in expression ) { statements }
2505f4a2713aSLionel Sambuc //
2506f4a2713aSLionel Sambuc // becomes:
2507f4a2713aSLionel Sambuc //
2508f4a2713aSLionel Sambuc // the same with newVariable replaced with existingItem; the binding works
2509f4a2713aSLionel Sambuc // the same except that for one ObjCForCollectionStmt::getElement() returns
2510f4a2713aSLionel Sambuc // a DeclStmt and the other returns a DeclRefExpr.
2511f4a2713aSLionel Sambuc //
2512f4a2713aSLionel Sambuc
2513*0a6a1f1dSLionel Sambuc CFGBlock *LoopSuccessor = nullptr;
2514f4a2713aSLionel Sambuc
2515f4a2713aSLionel Sambuc if (Block) {
2516f4a2713aSLionel Sambuc if (badCFG)
2517*0a6a1f1dSLionel Sambuc return nullptr;
2518f4a2713aSLionel Sambuc LoopSuccessor = Block;
2519*0a6a1f1dSLionel Sambuc Block = nullptr;
2520f4a2713aSLionel Sambuc } else
2521f4a2713aSLionel Sambuc LoopSuccessor = Succ;
2522f4a2713aSLionel Sambuc
2523f4a2713aSLionel Sambuc // Build the condition blocks.
2524f4a2713aSLionel Sambuc CFGBlock *ExitConditionBlock = createBlock(false);
2525f4a2713aSLionel Sambuc
2526f4a2713aSLionel Sambuc // Set the terminator for the "exit" condition block.
2527f4a2713aSLionel Sambuc ExitConditionBlock->setTerminator(S);
2528f4a2713aSLionel Sambuc
2529f4a2713aSLionel Sambuc // The last statement in the block should be the ObjCForCollectionStmt, which
2530f4a2713aSLionel Sambuc // performs the actual binding to 'element' and determines if there are any
2531f4a2713aSLionel Sambuc // more items in the collection.
2532f4a2713aSLionel Sambuc appendStmt(ExitConditionBlock, S);
2533f4a2713aSLionel Sambuc Block = ExitConditionBlock;
2534f4a2713aSLionel Sambuc
2535f4a2713aSLionel Sambuc // Walk the 'element' expression to see if there are any side-effects. We
2536f4a2713aSLionel Sambuc // generate new blocks as necessary. We DON'T add the statement by default to
2537f4a2713aSLionel Sambuc // the CFG unless it contains control-flow.
2538f4a2713aSLionel Sambuc CFGBlock *EntryConditionBlock = Visit(S->getElement(),
2539f4a2713aSLionel Sambuc AddStmtChoice::NotAlwaysAdd);
2540f4a2713aSLionel Sambuc if (Block) {
2541f4a2713aSLionel Sambuc if (badCFG)
2542*0a6a1f1dSLionel Sambuc return nullptr;
2543*0a6a1f1dSLionel Sambuc Block = nullptr;
2544f4a2713aSLionel Sambuc }
2545f4a2713aSLionel Sambuc
2546f4a2713aSLionel Sambuc // The condition block is the implicit successor for the loop body as well as
2547f4a2713aSLionel Sambuc // any code above the loop.
2548f4a2713aSLionel Sambuc Succ = EntryConditionBlock;
2549f4a2713aSLionel Sambuc
2550f4a2713aSLionel Sambuc // Now create the true branch.
2551f4a2713aSLionel Sambuc {
2552f4a2713aSLionel Sambuc // Save the current values for Succ, continue and break targets.
2553f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
2554f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
2555f4a2713aSLionel Sambuc save_break(BreakJumpTarget);
2556f4a2713aSLionel Sambuc
2557f4a2713aSLionel Sambuc // Add an intermediate block between the BodyBlock and the
2558f4a2713aSLionel Sambuc // EntryConditionBlock to represent the "loop back" transition, for looping
2559f4a2713aSLionel Sambuc // back to the head of the loop.
2560*0a6a1f1dSLionel Sambuc CFGBlock *LoopBackBlock = nullptr;
2561f4a2713aSLionel Sambuc Succ = LoopBackBlock = createBlock();
2562f4a2713aSLionel Sambuc LoopBackBlock->setLoopTarget(S);
2563f4a2713aSLionel Sambuc
2564f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2565f4a2713aSLionel Sambuc ContinueJumpTarget = JumpTarget(Succ, ScopePos);
2566f4a2713aSLionel Sambuc
2567f4a2713aSLionel Sambuc CFGBlock *BodyBlock = addStmt(S->getBody());
2568f4a2713aSLionel Sambuc
2569f4a2713aSLionel Sambuc if (!BodyBlock)
2570f4a2713aSLionel Sambuc BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;"
2571f4a2713aSLionel Sambuc else if (Block) {
2572f4a2713aSLionel Sambuc if (badCFG)
2573*0a6a1f1dSLionel Sambuc return nullptr;
2574f4a2713aSLionel Sambuc }
2575f4a2713aSLionel Sambuc
2576f4a2713aSLionel Sambuc // This new body block is a successor to our "exit" condition block.
2577f4a2713aSLionel Sambuc addSuccessor(ExitConditionBlock, BodyBlock);
2578f4a2713aSLionel Sambuc }
2579f4a2713aSLionel Sambuc
2580f4a2713aSLionel Sambuc // Link up the condition block with the code that follows the loop.
2581f4a2713aSLionel Sambuc // (the false branch).
2582f4a2713aSLionel Sambuc addSuccessor(ExitConditionBlock, LoopSuccessor);
2583f4a2713aSLionel Sambuc
2584f4a2713aSLionel Sambuc // Now create a prologue block to contain the collection expression.
2585f4a2713aSLionel Sambuc Block = createBlock();
2586f4a2713aSLionel Sambuc return addStmt(S->getCollection());
2587f4a2713aSLionel Sambuc }
2588f4a2713aSLionel Sambuc
VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt * S)2589f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
2590f4a2713aSLionel Sambuc // Inline the body.
2591f4a2713aSLionel Sambuc return addStmt(S->getSubStmt());
2592f4a2713aSLionel Sambuc // TODO: consider adding cleanups for the end of @autoreleasepool scope.
2593f4a2713aSLionel Sambuc }
2594f4a2713aSLionel Sambuc
VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt * S)2595f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
2596f4a2713aSLionel Sambuc // FIXME: Add locking 'primitives' to CFG for @synchronized.
2597f4a2713aSLionel Sambuc
2598f4a2713aSLionel Sambuc // Inline the body.
2599f4a2713aSLionel Sambuc CFGBlock *SyncBlock = addStmt(S->getSynchBody());
2600f4a2713aSLionel Sambuc
2601f4a2713aSLionel Sambuc // The sync body starts its own basic block. This makes it a little easier
2602f4a2713aSLionel Sambuc // for diagnostic clients.
2603f4a2713aSLionel Sambuc if (SyncBlock) {
2604f4a2713aSLionel Sambuc if (badCFG)
2605*0a6a1f1dSLionel Sambuc return nullptr;
2606f4a2713aSLionel Sambuc
2607*0a6a1f1dSLionel Sambuc Block = nullptr;
2608f4a2713aSLionel Sambuc Succ = SyncBlock;
2609f4a2713aSLionel Sambuc }
2610f4a2713aSLionel Sambuc
2611f4a2713aSLionel Sambuc // Add the @synchronized to the CFG.
2612f4a2713aSLionel Sambuc autoCreateBlock();
2613f4a2713aSLionel Sambuc appendStmt(Block, S);
2614f4a2713aSLionel Sambuc
2615f4a2713aSLionel Sambuc // Inline the sync expression.
2616f4a2713aSLionel Sambuc return addStmt(S->getSynchExpr());
2617f4a2713aSLionel Sambuc }
2618f4a2713aSLionel Sambuc
VisitObjCAtTryStmt(ObjCAtTryStmt * S)2619f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
2620f4a2713aSLionel Sambuc // FIXME
2621f4a2713aSLionel Sambuc return NYS();
2622f4a2713aSLionel Sambuc }
2623f4a2713aSLionel Sambuc
VisitPseudoObjectExpr(PseudoObjectExpr * E)2624f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
2625f4a2713aSLionel Sambuc autoCreateBlock();
2626f4a2713aSLionel Sambuc
2627f4a2713aSLionel Sambuc // Add the PseudoObject as the last thing.
2628f4a2713aSLionel Sambuc appendStmt(Block, E);
2629f4a2713aSLionel Sambuc
2630f4a2713aSLionel Sambuc CFGBlock *lastBlock = Block;
2631f4a2713aSLionel Sambuc
2632f4a2713aSLionel Sambuc // Before that, evaluate all of the semantics in order. In
2633f4a2713aSLionel Sambuc // CFG-land, that means appending them in reverse order.
2634f4a2713aSLionel Sambuc for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {
2635f4a2713aSLionel Sambuc Expr *Semantic = E->getSemanticExpr(--i);
2636f4a2713aSLionel Sambuc
2637f4a2713aSLionel Sambuc // If the semantic is an opaque value, we're being asked to bind
2638f4a2713aSLionel Sambuc // it to its source expression.
2639f4a2713aSLionel Sambuc if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
2640f4a2713aSLionel Sambuc Semantic = OVE->getSourceExpr();
2641f4a2713aSLionel Sambuc
2642f4a2713aSLionel Sambuc if (CFGBlock *B = Visit(Semantic))
2643f4a2713aSLionel Sambuc lastBlock = B;
2644f4a2713aSLionel Sambuc }
2645f4a2713aSLionel Sambuc
2646f4a2713aSLionel Sambuc return lastBlock;
2647f4a2713aSLionel Sambuc }
2648f4a2713aSLionel Sambuc
VisitWhileStmt(WhileStmt * W)2649f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
2650*0a6a1f1dSLionel Sambuc CFGBlock *LoopSuccessor = nullptr;
2651f4a2713aSLionel Sambuc
2652f4a2713aSLionel Sambuc // Save local scope position because in case of condition variable ScopePos
2653f4a2713aSLionel Sambuc // won't be restored when traversing AST.
2654f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
2655f4a2713aSLionel Sambuc
2656f4a2713aSLionel Sambuc // Create local scope for possible condition variable.
2657f4a2713aSLionel Sambuc // Store scope position for continue statement.
2658f4a2713aSLionel Sambuc LocalScope::const_iterator LoopBeginScopePos = ScopePos;
2659f4a2713aSLionel Sambuc if (VarDecl *VD = W->getConditionVariable()) {
2660f4a2713aSLionel Sambuc addLocalScopeForVarDecl(VD);
2661f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2662f4a2713aSLionel Sambuc }
2663f4a2713aSLionel Sambuc
2664f4a2713aSLionel Sambuc // "while" is a control-flow statement. Thus we stop processing the current
2665f4a2713aSLionel Sambuc // block.
2666f4a2713aSLionel Sambuc if (Block) {
2667f4a2713aSLionel Sambuc if (badCFG)
2668*0a6a1f1dSLionel Sambuc return nullptr;
2669f4a2713aSLionel Sambuc LoopSuccessor = Block;
2670*0a6a1f1dSLionel Sambuc Block = nullptr;
2671f4a2713aSLionel Sambuc } else {
2672f4a2713aSLionel Sambuc LoopSuccessor = Succ;
2673f4a2713aSLionel Sambuc }
2674f4a2713aSLionel Sambuc
2675*0a6a1f1dSLionel Sambuc CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
2676f4a2713aSLionel Sambuc
2677f4a2713aSLionel Sambuc // Process the loop body.
2678f4a2713aSLionel Sambuc {
2679f4a2713aSLionel Sambuc assert(W->getBody());
2680f4a2713aSLionel Sambuc
2681f4a2713aSLionel Sambuc // Save the current values for Block, Succ, continue and break targets.
2682f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
2683f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
2684f4a2713aSLionel Sambuc save_break(BreakJumpTarget);
2685f4a2713aSLionel Sambuc
2686f4a2713aSLionel Sambuc // Create an empty block to represent the transition block for looping back
2687f4a2713aSLionel Sambuc // to the head of the loop.
2688f4a2713aSLionel Sambuc Succ = TransitionBlock = createBlock(false);
2689f4a2713aSLionel Sambuc TransitionBlock->setLoopTarget(W);
2690f4a2713aSLionel Sambuc ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
2691f4a2713aSLionel Sambuc
2692f4a2713aSLionel Sambuc // All breaks should go to the code following the loop.
2693f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2694f4a2713aSLionel Sambuc
2695f4a2713aSLionel Sambuc // Loop body should end with destructor of Condition variable (if any).
2696f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
2697f4a2713aSLionel Sambuc
2698f4a2713aSLionel Sambuc // If body is not a compound statement create implicit scope
2699f4a2713aSLionel Sambuc // and add destructors.
2700f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(W->getBody()))
2701f4a2713aSLionel Sambuc addLocalScopeAndDtors(W->getBody());
2702f4a2713aSLionel Sambuc
2703f4a2713aSLionel Sambuc // Create the body. The returned block is the entry to the loop body.
2704f4a2713aSLionel Sambuc BodyBlock = addStmt(W->getBody());
2705f4a2713aSLionel Sambuc
2706f4a2713aSLionel Sambuc if (!BodyBlock)
2707f4a2713aSLionel Sambuc BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
2708f4a2713aSLionel Sambuc else if (Block && badCFG)
2709*0a6a1f1dSLionel Sambuc return nullptr;
2710f4a2713aSLionel Sambuc }
2711f4a2713aSLionel Sambuc
2712f4a2713aSLionel Sambuc // Because of short-circuit evaluation, the condition of the loop can span
2713f4a2713aSLionel Sambuc // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
2714f4a2713aSLionel Sambuc // evaluate the condition.
2715*0a6a1f1dSLionel Sambuc CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
2716f4a2713aSLionel Sambuc
2717f4a2713aSLionel Sambuc do {
2718f4a2713aSLionel Sambuc Expr *C = W->getCond();
2719f4a2713aSLionel Sambuc
2720f4a2713aSLionel Sambuc // Specially handle logical operators, which have a slightly
2721f4a2713aSLionel Sambuc // more optimal CFG representation.
2722f4a2713aSLionel Sambuc if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))
2723f4a2713aSLionel Sambuc if (Cond->isLogicalOp()) {
2724*0a6a1f1dSLionel Sambuc std::tie(EntryConditionBlock, ExitConditionBlock) =
2725*0a6a1f1dSLionel Sambuc VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
2726f4a2713aSLionel Sambuc break;
2727f4a2713aSLionel Sambuc }
2728f4a2713aSLionel Sambuc
2729f4a2713aSLionel Sambuc // The default case when not handling logical operators.
2730f4a2713aSLionel Sambuc ExitConditionBlock = createBlock(false);
2731f4a2713aSLionel Sambuc ExitConditionBlock->setTerminator(W);
2732f4a2713aSLionel Sambuc
2733f4a2713aSLionel Sambuc // Now add the actual condition to the condition block.
2734f4a2713aSLionel Sambuc // Because the condition itself may contain control-flow, new blocks may
2735f4a2713aSLionel Sambuc // be created. Thus we update "Succ" after adding the condition.
2736f4a2713aSLionel Sambuc Block = ExitConditionBlock;
2737f4a2713aSLionel Sambuc Block = EntryConditionBlock = addStmt(C);
2738f4a2713aSLionel Sambuc
2739f4a2713aSLionel Sambuc // If this block contains a condition variable, add both the condition
2740f4a2713aSLionel Sambuc // variable and initializer to the CFG.
2741f4a2713aSLionel Sambuc if (VarDecl *VD = W->getConditionVariable()) {
2742f4a2713aSLionel Sambuc if (Expr *Init = VD->getInit()) {
2743f4a2713aSLionel Sambuc autoCreateBlock();
2744f4a2713aSLionel Sambuc appendStmt(Block, W->getConditionVariableDeclStmt());
2745f4a2713aSLionel Sambuc EntryConditionBlock = addStmt(Init);
2746f4a2713aSLionel Sambuc assert(Block == EntryConditionBlock);
2747f4a2713aSLionel Sambuc }
2748f4a2713aSLionel Sambuc }
2749f4a2713aSLionel Sambuc
2750f4a2713aSLionel Sambuc if (Block && badCFG)
2751*0a6a1f1dSLionel Sambuc return nullptr;
2752f4a2713aSLionel Sambuc
2753f4a2713aSLionel Sambuc // See if this is a known constant.
2754f4a2713aSLionel Sambuc const TryResult& KnownVal = tryEvaluateBool(C);
2755f4a2713aSLionel Sambuc
2756f4a2713aSLionel Sambuc // Add the loop body entry as a successor to the condition.
2757*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
2758f4a2713aSLionel Sambuc // Link up the condition block with the code that follows the loop. (the
2759f4a2713aSLionel Sambuc // false branch).
2760*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock,
2761*0a6a1f1dSLionel Sambuc KnownVal.isTrue() ? nullptr : LoopSuccessor);
2762f4a2713aSLionel Sambuc
2763f4a2713aSLionel Sambuc } while(false);
2764f4a2713aSLionel Sambuc
2765f4a2713aSLionel Sambuc // Link up the loop-back block to the entry condition block.
2766f4a2713aSLionel Sambuc addSuccessor(TransitionBlock, EntryConditionBlock);
2767f4a2713aSLionel Sambuc
2768f4a2713aSLionel Sambuc // There can be no more statements in the condition block since we loop back
2769f4a2713aSLionel Sambuc // to this block. NULL out Block to force lazy creation of another block.
2770*0a6a1f1dSLionel Sambuc Block = nullptr;
2771f4a2713aSLionel Sambuc
2772f4a2713aSLionel Sambuc // Return the condition block, which is the dominating block for the loop.
2773f4a2713aSLionel Sambuc Succ = EntryConditionBlock;
2774f4a2713aSLionel Sambuc return EntryConditionBlock;
2775f4a2713aSLionel Sambuc }
2776f4a2713aSLionel Sambuc
2777f4a2713aSLionel Sambuc
VisitObjCAtCatchStmt(ObjCAtCatchStmt * S)2778f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
2779f4a2713aSLionel Sambuc // FIXME: For now we pretend that @catch and the code it contains does not
2780f4a2713aSLionel Sambuc // exit.
2781f4a2713aSLionel Sambuc return Block;
2782f4a2713aSLionel Sambuc }
2783f4a2713aSLionel Sambuc
VisitObjCAtThrowStmt(ObjCAtThrowStmt * S)2784f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
2785f4a2713aSLionel Sambuc // FIXME: This isn't complete. We basically treat @throw like a return
2786f4a2713aSLionel Sambuc // statement.
2787f4a2713aSLionel Sambuc
2788f4a2713aSLionel Sambuc // If we were in the middle of a block we stop processing that block.
2789f4a2713aSLionel Sambuc if (badCFG)
2790*0a6a1f1dSLionel Sambuc return nullptr;
2791f4a2713aSLionel Sambuc
2792f4a2713aSLionel Sambuc // Create the new block.
2793f4a2713aSLionel Sambuc Block = createBlock(false);
2794f4a2713aSLionel Sambuc
2795f4a2713aSLionel Sambuc // The Exit block is the only successor.
2796f4a2713aSLionel Sambuc addSuccessor(Block, &cfg->getExit());
2797f4a2713aSLionel Sambuc
2798f4a2713aSLionel Sambuc // Add the statement to the block. This may create new blocks if S contains
2799f4a2713aSLionel Sambuc // control-flow (short-circuit operations).
2800f4a2713aSLionel Sambuc return VisitStmt(S, AddStmtChoice::AlwaysAdd);
2801f4a2713aSLionel Sambuc }
2802f4a2713aSLionel Sambuc
VisitCXXThrowExpr(CXXThrowExpr * T)2803f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
2804f4a2713aSLionel Sambuc // If we were in the middle of a block we stop processing that block.
2805f4a2713aSLionel Sambuc if (badCFG)
2806*0a6a1f1dSLionel Sambuc return nullptr;
2807f4a2713aSLionel Sambuc
2808f4a2713aSLionel Sambuc // Create the new block.
2809f4a2713aSLionel Sambuc Block = createBlock(false);
2810f4a2713aSLionel Sambuc
2811f4a2713aSLionel Sambuc if (TryTerminatedBlock)
2812f4a2713aSLionel Sambuc // The current try statement is the only successor.
2813f4a2713aSLionel Sambuc addSuccessor(Block, TryTerminatedBlock);
2814f4a2713aSLionel Sambuc else
2815f4a2713aSLionel Sambuc // otherwise the Exit block is the only successor.
2816f4a2713aSLionel Sambuc addSuccessor(Block, &cfg->getExit());
2817f4a2713aSLionel Sambuc
2818f4a2713aSLionel Sambuc // Add the statement to the block. This may create new blocks if S contains
2819f4a2713aSLionel Sambuc // control-flow (short-circuit operations).
2820f4a2713aSLionel Sambuc return VisitStmt(T, AddStmtChoice::AlwaysAdd);
2821f4a2713aSLionel Sambuc }
2822f4a2713aSLionel Sambuc
VisitDoStmt(DoStmt * D)2823f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
2824*0a6a1f1dSLionel Sambuc CFGBlock *LoopSuccessor = nullptr;
2825f4a2713aSLionel Sambuc
2826f4a2713aSLionel Sambuc // "do...while" is a control-flow statement. Thus we stop processing the
2827f4a2713aSLionel Sambuc // current block.
2828f4a2713aSLionel Sambuc if (Block) {
2829f4a2713aSLionel Sambuc if (badCFG)
2830*0a6a1f1dSLionel Sambuc return nullptr;
2831f4a2713aSLionel Sambuc LoopSuccessor = Block;
2832f4a2713aSLionel Sambuc } else
2833f4a2713aSLionel Sambuc LoopSuccessor = Succ;
2834f4a2713aSLionel Sambuc
2835f4a2713aSLionel Sambuc // Because of short-circuit evaluation, the condition of the loop can span
2836f4a2713aSLionel Sambuc // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
2837f4a2713aSLionel Sambuc // evaluate the condition.
2838f4a2713aSLionel Sambuc CFGBlock *ExitConditionBlock = createBlock(false);
2839f4a2713aSLionel Sambuc CFGBlock *EntryConditionBlock = ExitConditionBlock;
2840f4a2713aSLionel Sambuc
2841f4a2713aSLionel Sambuc // Set the terminator for the "exit" condition block.
2842f4a2713aSLionel Sambuc ExitConditionBlock->setTerminator(D);
2843f4a2713aSLionel Sambuc
2844f4a2713aSLionel Sambuc // Now add the actual condition to the condition block. Because the condition
2845f4a2713aSLionel Sambuc // itself may contain control-flow, new blocks may be created.
2846f4a2713aSLionel Sambuc if (Stmt *C = D->getCond()) {
2847f4a2713aSLionel Sambuc Block = ExitConditionBlock;
2848f4a2713aSLionel Sambuc EntryConditionBlock = addStmt(C);
2849f4a2713aSLionel Sambuc if (Block) {
2850f4a2713aSLionel Sambuc if (badCFG)
2851*0a6a1f1dSLionel Sambuc return nullptr;
2852f4a2713aSLionel Sambuc }
2853f4a2713aSLionel Sambuc }
2854f4a2713aSLionel Sambuc
2855f4a2713aSLionel Sambuc // The condition block is the implicit successor for the loop body.
2856f4a2713aSLionel Sambuc Succ = EntryConditionBlock;
2857f4a2713aSLionel Sambuc
2858f4a2713aSLionel Sambuc // See if this is a known constant.
2859f4a2713aSLionel Sambuc const TryResult &KnownVal = tryEvaluateBool(D->getCond());
2860f4a2713aSLionel Sambuc
2861f4a2713aSLionel Sambuc // Process the loop body.
2862*0a6a1f1dSLionel Sambuc CFGBlock *BodyBlock = nullptr;
2863f4a2713aSLionel Sambuc {
2864f4a2713aSLionel Sambuc assert(D->getBody());
2865f4a2713aSLionel Sambuc
2866f4a2713aSLionel Sambuc // Save the current values for Block, Succ, and continue and break targets
2867f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
2868f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
2869f4a2713aSLionel Sambuc save_break(BreakJumpTarget);
2870f4a2713aSLionel Sambuc
2871f4a2713aSLionel Sambuc // All continues within this loop should go to the condition block
2872f4a2713aSLionel Sambuc ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
2873f4a2713aSLionel Sambuc
2874f4a2713aSLionel Sambuc // All breaks should go to the code following the loop.
2875f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
2876f4a2713aSLionel Sambuc
2877f4a2713aSLionel Sambuc // NULL out Block to force lazy instantiation of blocks for the body.
2878*0a6a1f1dSLionel Sambuc Block = nullptr;
2879f4a2713aSLionel Sambuc
2880f4a2713aSLionel Sambuc // If body is not a compound statement create implicit scope
2881f4a2713aSLionel Sambuc // and add destructors.
2882f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(D->getBody()))
2883f4a2713aSLionel Sambuc addLocalScopeAndDtors(D->getBody());
2884f4a2713aSLionel Sambuc
2885f4a2713aSLionel Sambuc // Create the body. The returned block is the entry to the loop body.
2886f4a2713aSLionel Sambuc BodyBlock = addStmt(D->getBody());
2887f4a2713aSLionel Sambuc
2888f4a2713aSLionel Sambuc if (!BodyBlock)
2889f4a2713aSLionel Sambuc BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
2890f4a2713aSLionel Sambuc else if (Block) {
2891f4a2713aSLionel Sambuc if (badCFG)
2892*0a6a1f1dSLionel Sambuc return nullptr;
2893f4a2713aSLionel Sambuc }
2894f4a2713aSLionel Sambuc
2895f4a2713aSLionel Sambuc if (!KnownVal.isFalse()) {
2896f4a2713aSLionel Sambuc // Add an intermediate block between the BodyBlock and the
2897f4a2713aSLionel Sambuc // ExitConditionBlock to represent the "loop back" transition. Create an
2898f4a2713aSLionel Sambuc // empty block to represent the transition block for looping back to the
2899f4a2713aSLionel Sambuc // head of the loop.
2900f4a2713aSLionel Sambuc // FIXME: Can we do this more efficiently without adding another block?
2901*0a6a1f1dSLionel Sambuc Block = nullptr;
2902f4a2713aSLionel Sambuc Succ = BodyBlock;
2903f4a2713aSLionel Sambuc CFGBlock *LoopBackBlock = createBlock();
2904f4a2713aSLionel Sambuc LoopBackBlock->setLoopTarget(D);
2905f4a2713aSLionel Sambuc
2906f4a2713aSLionel Sambuc // Add the loop body entry as a successor to the condition.
2907f4a2713aSLionel Sambuc addSuccessor(ExitConditionBlock, LoopBackBlock);
2908f4a2713aSLionel Sambuc }
2909f4a2713aSLionel Sambuc else
2910*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock, nullptr);
2911f4a2713aSLionel Sambuc }
2912f4a2713aSLionel Sambuc
2913f4a2713aSLionel Sambuc // Link up the condition block with the code that follows the loop.
2914f4a2713aSLionel Sambuc // (the false branch).
2915*0a6a1f1dSLionel Sambuc addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
2916f4a2713aSLionel Sambuc
2917f4a2713aSLionel Sambuc // There can be no more statements in the body block(s) since we loop back to
2918f4a2713aSLionel Sambuc // the body. NULL out Block to force lazy creation of another block.
2919*0a6a1f1dSLionel Sambuc Block = nullptr;
2920f4a2713aSLionel Sambuc
2921f4a2713aSLionel Sambuc // Return the loop body, which is the dominating block for the loop.
2922f4a2713aSLionel Sambuc Succ = BodyBlock;
2923f4a2713aSLionel Sambuc return BodyBlock;
2924f4a2713aSLionel Sambuc }
2925f4a2713aSLionel Sambuc
VisitContinueStmt(ContinueStmt * C)2926f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
2927f4a2713aSLionel Sambuc // "continue" is a control-flow statement. Thus we stop processing the
2928f4a2713aSLionel Sambuc // current block.
2929f4a2713aSLionel Sambuc if (badCFG)
2930*0a6a1f1dSLionel Sambuc return nullptr;
2931f4a2713aSLionel Sambuc
2932f4a2713aSLionel Sambuc // Now create a new block that ends with the continue statement.
2933f4a2713aSLionel Sambuc Block = createBlock(false);
2934f4a2713aSLionel Sambuc Block->setTerminator(C);
2935f4a2713aSLionel Sambuc
2936f4a2713aSLionel Sambuc // If there is no target for the continue, then we are looking at an
2937f4a2713aSLionel Sambuc // incomplete AST. This means the CFG cannot be constructed.
2938f4a2713aSLionel Sambuc if (ContinueJumpTarget.block) {
2939f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
2940f4a2713aSLionel Sambuc addSuccessor(Block, ContinueJumpTarget.block);
2941f4a2713aSLionel Sambuc } else
2942f4a2713aSLionel Sambuc badCFG = true;
2943f4a2713aSLionel Sambuc
2944f4a2713aSLionel Sambuc return Block;
2945f4a2713aSLionel Sambuc }
2946f4a2713aSLionel Sambuc
VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr * E,AddStmtChoice asc)2947f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
2948f4a2713aSLionel Sambuc AddStmtChoice asc) {
2949f4a2713aSLionel Sambuc
2950f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, E)) {
2951f4a2713aSLionel Sambuc autoCreateBlock();
2952f4a2713aSLionel Sambuc appendStmt(Block, E);
2953f4a2713aSLionel Sambuc }
2954f4a2713aSLionel Sambuc
2955f4a2713aSLionel Sambuc // VLA types have expressions that must be evaluated.
2956f4a2713aSLionel Sambuc CFGBlock *lastBlock = Block;
2957f4a2713aSLionel Sambuc
2958f4a2713aSLionel Sambuc if (E->isArgumentType()) {
2959f4a2713aSLionel Sambuc for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
2960*0a6a1f1dSLionel Sambuc VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
2961f4a2713aSLionel Sambuc lastBlock = addStmt(VA->getSizeExpr());
2962f4a2713aSLionel Sambuc }
2963f4a2713aSLionel Sambuc return lastBlock;
2964f4a2713aSLionel Sambuc }
2965f4a2713aSLionel Sambuc
2966f4a2713aSLionel Sambuc /// VisitStmtExpr - Utility method to handle (nested) statement
2967f4a2713aSLionel Sambuc /// expressions (a GCC extension).
VisitStmtExpr(StmtExpr * SE,AddStmtChoice asc)2968f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
2969f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, SE)) {
2970f4a2713aSLionel Sambuc autoCreateBlock();
2971f4a2713aSLionel Sambuc appendStmt(Block, SE);
2972f4a2713aSLionel Sambuc }
2973f4a2713aSLionel Sambuc return VisitCompoundStmt(SE->getSubStmt());
2974f4a2713aSLionel Sambuc }
2975f4a2713aSLionel Sambuc
VisitSwitchStmt(SwitchStmt * Terminator)2976f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
2977f4a2713aSLionel Sambuc // "switch" is a control-flow statement. Thus we stop processing the current
2978f4a2713aSLionel Sambuc // block.
2979*0a6a1f1dSLionel Sambuc CFGBlock *SwitchSuccessor = nullptr;
2980f4a2713aSLionel Sambuc
2981f4a2713aSLionel Sambuc // Save local scope position because in case of condition variable ScopePos
2982f4a2713aSLionel Sambuc // won't be restored when traversing AST.
2983f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
2984f4a2713aSLionel Sambuc
2985f4a2713aSLionel Sambuc // Create local scope for possible condition variable.
2986f4a2713aSLionel Sambuc // Store scope position. Add implicit destructor.
2987f4a2713aSLionel Sambuc if (VarDecl *VD = Terminator->getConditionVariable()) {
2988f4a2713aSLionel Sambuc LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
2989f4a2713aSLionel Sambuc addLocalScopeForVarDecl(VD);
2990f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
2991f4a2713aSLionel Sambuc }
2992f4a2713aSLionel Sambuc
2993f4a2713aSLionel Sambuc if (Block) {
2994f4a2713aSLionel Sambuc if (badCFG)
2995*0a6a1f1dSLionel Sambuc return nullptr;
2996f4a2713aSLionel Sambuc SwitchSuccessor = Block;
2997f4a2713aSLionel Sambuc } else SwitchSuccessor = Succ;
2998f4a2713aSLionel Sambuc
2999f4a2713aSLionel Sambuc // Save the current "switch" context.
3000f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
3001f4a2713aSLionel Sambuc save_default(DefaultCaseBlock);
3002f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
3003f4a2713aSLionel Sambuc
3004f4a2713aSLionel Sambuc // Set the "default" case to be the block after the switch statement. If the
3005f4a2713aSLionel Sambuc // switch statement contains a "default:", this value will be overwritten with
3006f4a2713aSLionel Sambuc // the block for that code.
3007f4a2713aSLionel Sambuc DefaultCaseBlock = SwitchSuccessor;
3008f4a2713aSLionel Sambuc
3009f4a2713aSLionel Sambuc // Create a new block that will contain the switch statement.
3010f4a2713aSLionel Sambuc SwitchTerminatedBlock = createBlock(false);
3011f4a2713aSLionel Sambuc
3012f4a2713aSLionel Sambuc // Now process the switch body. The code after the switch is the implicit
3013f4a2713aSLionel Sambuc // successor.
3014f4a2713aSLionel Sambuc Succ = SwitchSuccessor;
3015f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
3016f4a2713aSLionel Sambuc
3017f4a2713aSLionel Sambuc // When visiting the body, the case statements should automatically get linked
3018f4a2713aSLionel Sambuc // up to the switch. We also don't keep a pointer to the body, since all
3019f4a2713aSLionel Sambuc // control-flow from the switch goes to case/default statements.
3020f4a2713aSLionel Sambuc assert(Terminator->getBody() && "switch must contain a non-NULL body");
3021*0a6a1f1dSLionel Sambuc Block = nullptr;
3022f4a2713aSLionel Sambuc
3023f4a2713aSLionel Sambuc // For pruning unreachable case statements, save the current state
3024f4a2713aSLionel Sambuc // for tracking the condition value.
3025f4a2713aSLionel Sambuc SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered,
3026f4a2713aSLionel Sambuc false);
3027f4a2713aSLionel Sambuc
3028f4a2713aSLionel Sambuc // Determine if the switch condition can be explicitly evaluated.
3029f4a2713aSLionel Sambuc assert(Terminator->getCond() && "switch condition must be non-NULL");
3030f4a2713aSLionel Sambuc Expr::EvalResult result;
3031f4a2713aSLionel Sambuc bool b = tryEvaluate(Terminator->getCond(), result);
3032f4a2713aSLionel Sambuc SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond,
3033*0a6a1f1dSLionel Sambuc b ? &result : nullptr);
3034f4a2713aSLionel Sambuc
3035f4a2713aSLionel Sambuc // If body is not a compound statement create implicit scope
3036f4a2713aSLionel Sambuc // and add destructors.
3037f4a2713aSLionel Sambuc if (!isa<CompoundStmt>(Terminator->getBody()))
3038f4a2713aSLionel Sambuc addLocalScopeAndDtors(Terminator->getBody());
3039f4a2713aSLionel Sambuc
3040f4a2713aSLionel Sambuc addStmt(Terminator->getBody());
3041f4a2713aSLionel Sambuc if (Block) {
3042f4a2713aSLionel Sambuc if (badCFG)
3043*0a6a1f1dSLionel Sambuc return nullptr;
3044f4a2713aSLionel Sambuc }
3045f4a2713aSLionel Sambuc
3046f4a2713aSLionel Sambuc // If we have no "default:" case, the default transition is to the code
3047f4a2713aSLionel Sambuc // following the switch body. Moreover, take into account if all the
3048f4a2713aSLionel Sambuc // cases of a switch are covered (e.g., switching on an enum value).
3049f4a2713aSLionel Sambuc //
3050f4a2713aSLionel Sambuc // Note: We add a successor to a switch that is considered covered yet has no
3051f4a2713aSLionel Sambuc // case statements if the enumeration has no enumerators.
3052f4a2713aSLionel Sambuc bool SwitchAlwaysHasSuccessor = false;
3053f4a2713aSLionel Sambuc SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
3054f4a2713aSLionel Sambuc SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() &&
3055f4a2713aSLionel Sambuc Terminator->getSwitchCaseList();
3056*0a6a1f1dSLionel Sambuc addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
3057*0a6a1f1dSLionel Sambuc !SwitchAlwaysHasSuccessor);
3058f4a2713aSLionel Sambuc
3059f4a2713aSLionel Sambuc // Add the terminator and condition in the switch block.
3060f4a2713aSLionel Sambuc SwitchTerminatedBlock->setTerminator(Terminator);
3061f4a2713aSLionel Sambuc Block = SwitchTerminatedBlock;
3062f4a2713aSLionel Sambuc CFGBlock *LastBlock = addStmt(Terminator->getCond());
3063f4a2713aSLionel Sambuc
3064f4a2713aSLionel Sambuc // Finally, if the SwitchStmt contains a condition variable, add both the
3065f4a2713aSLionel Sambuc // SwitchStmt and the condition variable initialization to the CFG.
3066f4a2713aSLionel Sambuc if (VarDecl *VD = Terminator->getConditionVariable()) {
3067f4a2713aSLionel Sambuc if (Expr *Init = VD->getInit()) {
3068f4a2713aSLionel Sambuc autoCreateBlock();
3069f4a2713aSLionel Sambuc appendStmt(Block, Terminator->getConditionVariableDeclStmt());
3070f4a2713aSLionel Sambuc LastBlock = addStmt(Init);
3071f4a2713aSLionel Sambuc }
3072f4a2713aSLionel Sambuc }
3073f4a2713aSLionel Sambuc
3074f4a2713aSLionel Sambuc return LastBlock;
3075f4a2713aSLionel Sambuc }
3076f4a2713aSLionel Sambuc
shouldAddCase(bool & switchExclusivelyCovered,const Expr::EvalResult * switchCond,const CaseStmt * CS,ASTContext & Ctx)3077f4a2713aSLionel Sambuc static bool shouldAddCase(bool &switchExclusivelyCovered,
3078f4a2713aSLionel Sambuc const Expr::EvalResult *switchCond,
3079f4a2713aSLionel Sambuc const CaseStmt *CS,
3080f4a2713aSLionel Sambuc ASTContext &Ctx) {
3081f4a2713aSLionel Sambuc if (!switchCond)
3082f4a2713aSLionel Sambuc return true;
3083f4a2713aSLionel Sambuc
3084f4a2713aSLionel Sambuc bool addCase = false;
3085f4a2713aSLionel Sambuc
3086f4a2713aSLionel Sambuc if (!switchExclusivelyCovered) {
3087f4a2713aSLionel Sambuc if (switchCond->Val.isInt()) {
3088f4a2713aSLionel Sambuc // Evaluate the LHS of the case value.
3089f4a2713aSLionel Sambuc const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx);
3090f4a2713aSLionel Sambuc const llvm::APSInt &condInt = switchCond->Val.getInt();
3091f4a2713aSLionel Sambuc
3092f4a2713aSLionel Sambuc if (condInt == lhsInt) {
3093f4a2713aSLionel Sambuc addCase = true;
3094f4a2713aSLionel Sambuc switchExclusivelyCovered = true;
3095f4a2713aSLionel Sambuc }
3096f4a2713aSLionel Sambuc else if (condInt < lhsInt) {
3097f4a2713aSLionel Sambuc if (const Expr *RHS = CS->getRHS()) {
3098f4a2713aSLionel Sambuc // Evaluate the RHS of the case value.
3099f4a2713aSLionel Sambuc const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
3100f4a2713aSLionel Sambuc if (V2 <= condInt) {
3101f4a2713aSLionel Sambuc addCase = true;
3102f4a2713aSLionel Sambuc switchExclusivelyCovered = true;
3103f4a2713aSLionel Sambuc }
3104f4a2713aSLionel Sambuc }
3105f4a2713aSLionel Sambuc }
3106f4a2713aSLionel Sambuc }
3107f4a2713aSLionel Sambuc else
3108f4a2713aSLionel Sambuc addCase = true;
3109f4a2713aSLionel Sambuc }
3110f4a2713aSLionel Sambuc return addCase;
3111f4a2713aSLionel Sambuc }
3112f4a2713aSLionel Sambuc
VisitCaseStmt(CaseStmt * CS)3113f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
3114f4a2713aSLionel Sambuc // CaseStmts are essentially labels, so they are the first statement in a
3115f4a2713aSLionel Sambuc // block.
3116*0a6a1f1dSLionel Sambuc CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;
3117f4a2713aSLionel Sambuc
3118f4a2713aSLionel Sambuc if (Stmt *Sub = CS->getSubStmt()) {
3119f4a2713aSLionel Sambuc // For deeply nested chains of CaseStmts, instead of doing a recursion
3120f4a2713aSLionel Sambuc // (which can blow out the stack), manually unroll and create blocks
3121f4a2713aSLionel Sambuc // along the way.
3122f4a2713aSLionel Sambuc while (isa<CaseStmt>(Sub)) {
3123f4a2713aSLionel Sambuc CFGBlock *currentBlock = createBlock(false);
3124f4a2713aSLionel Sambuc currentBlock->setLabel(CS);
3125f4a2713aSLionel Sambuc
3126f4a2713aSLionel Sambuc if (TopBlock)
3127f4a2713aSLionel Sambuc addSuccessor(LastBlock, currentBlock);
3128f4a2713aSLionel Sambuc else
3129f4a2713aSLionel Sambuc TopBlock = currentBlock;
3130f4a2713aSLionel Sambuc
3131f4a2713aSLionel Sambuc addSuccessor(SwitchTerminatedBlock,
3132f4a2713aSLionel Sambuc shouldAddCase(switchExclusivelyCovered, switchCond,
3133f4a2713aSLionel Sambuc CS, *Context)
3134*0a6a1f1dSLionel Sambuc ? currentBlock : nullptr);
3135f4a2713aSLionel Sambuc
3136f4a2713aSLionel Sambuc LastBlock = currentBlock;
3137f4a2713aSLionel Sambuc CS = cast<CaseStmt>(Sub);
3138f4a2713aSLionel Sambuc Sub = CS->getSubStmt();
3139f4a2713aSLionel Sambuc }
3140f4a2713aSLionel Sambuc
3141f4a2713aSLionel Sambuc addStmt(Sub);
3142f4a2713aSLionel Sambuc }
3143f4a2713aSLionel Sambuc
3144f4a2713aSLionel Sambuc CFGBlock *CaseBlock = Block;
3145f4a2713aSLionel Sambuc if (!CaseBlock)
3146f4a2713aSLionel Sambuc CaseBlock = createBlock();
3147f4a2713aSLionel Sambuc
3148f4a2713aSLionel Sambuc // Cases statements partition blocks, so this is the top of the basic block we
3149f4a2713aSLionel Sambuc // were processing (the "case XXX:" is the label).
3150f4a2713aSLionel Sambuc CaseBlock->setLabel(CS);
3151f4a2713aSLionel Sambuc
3152f4a2713aSLionel Sambuc if (badCFG)
3153*0a6a1f1dSLionel Sambuc return nullptr;
3154f4a2713aSLionel Sambuc
3155f4a2713aSLionel Sambuc // Add this block to the list of successors for the block with the switch
3156f4a2713aSLionel Sambuc // statement.
3157f4a2713aSLionel Sambuc assert(SwitchTerminatedBlock);
3158*0a6a1f1dSLionel Sambuc addSuccessor(SwitchTerminatedBlock, CaseBlock,
3159f4a2713aSLionel Sambuc shouldAddCase(switchExclusivelyCovered, switchCond,
3160*0a6a1f1dSLionel Sambuc CS, *Context));
3161f4a2713aSLionel Sambuc
3162f4a2713aSLionel Sambuc // We set Block to NULL to allow lazy creation of a new block (if necessary)
3163*0a6a1f1dSLionel Sambuc Block = nullptr;
3164f4a2713aSLionel Sambuc
3165f4a2713aSLionel Sambuc if (TopBlock) {
3166f4a2713aSLionel Sambuc addSuccessor(LastBlock, CaseBlock);
3167f4a2713aSLionel Sambuc Succ = TopBlock;
3168f4a2713aSLionel Sambuc } else {
3169f4a2713aSLionel Sambuc // This block is now the implicit successor of other blocks.
3170f4a2713aSLionel Sambuc Succ = CaseBlock;
3171f4a2713aSLionel Sambuc }
3172f4a2713aSLionel Sambuc
3173f4a2713aSLionel Sambuc return Succ;
3174f4a2713aSLionel Sambuc }
3175f4a2713aSLionel Sambuc
VisitDefaultStmt(DefaultStmt * Terminator)3176f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
3177f4a2713aSLionel Sambuc if (Terminator->getSubStmt())
3178f4a2713aSLionel Sambuc addStmt(Terminator->getSubStmt());
3179f4a2713aSLionel Sambuc
3180f4a2713aSLionel Sambuc DefaultCaseBlock = Block;
3181f4a2713aSLionel Sambuc
3182f4a2713aSLionel Sambuc if (!DefaultCaseBlock)
3183f4a2713aSLionel Sambuc DefaultCaseBlock = createBlock();
3184f4a2713aSLionel Sambuc
3185f4a2713aSLionel Sambuc // Default statements partition blocks, so this is the top of the basic block
3186f4a2713aSLionel Sambuc // we were processing (the "default:" is the label).
3187f4a2713aSLionel Sambuc DefaultCaseBlock->setLabel(Terminator);
3188f4a2713aSLionel Sambuc
3189f4a2713aSLionel Sambuc if (badCFG)
3190*0a6a1f1dSLionel Sambuc return nullptr;
3191f4a2713aSLionel Sambuc
3192f4a2713aSLionel Sambuc // Unlike case statements, we don't add the default block to the successors
3193f4a2713aSLionel Sambuc // for the switch statement immediately. This is done when we finish
3194f4a2713aSLionel Sambuc // processing the switch statement. This allows for the default case
3195f4a2713aSLionel Sambuc // (including a fall-through to the code after the switch statement) to always
3196f4a2713aSLionel Sambuc // be the last successor of a switch-terminated block.
3197f4a2713aSLionel Sambuc
3198f4a2713aSLionel Sambuc // We set Block to NULL to allow lazy creation of a new block (if necessary)
3199*0a6a1f1dSLionel Sambuc Block = nullptr;
3200f4a2713aSLionel Sambuc
3201f4a2713aSLionel Sambuc // This block is now the implicit successor of other blocks.
3202f4a2713aSLionel Sambuc Succ = DefaultCaseBlock;
3203f4a2713aSLionel Sambuc
3204f4a2713aSLionel Sambuc return DefaultCaseBlock;
3205f4a2713aSLionel Sambuc }
3206f4a2713aSLionel Sambuc
VisitCXXTryStmt(CXXTryStmt * Terminator)3207f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
3208f4a2713aSLionel Sambuc // "try"/"catch" is a control-flow statement. Thus we stop processing the
3209f4a2713aSLionel Sambuc // current block.
3210*0a6a1f1dSLionel Sambuc CFGBlock *TrySuccessor = nullptr;
3211f4a2713aSLionel Sambuc
3212f4a2713aSLionel Sambuc if (Block) {
3213f4a2713aSLionel Sambuc if (badCFG)
3214*0a6a1f1dSLionel Sambuc return nullptr;
3215f4a2713aSLionel Sambuc TrySuccessor = Block;
3216f4a2713aSLionel Sambuc } else TrySuccessor = Succ;
3217f4a2713aSLionel Sambuc
3218f4a2713aSLionel Sambuc CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
3219f4a2713aSLionel Sambuc
3220f4a2713aSLionel Sambuc // Create a new block that will contain the try statement.
3221f4a2713aSLionel Sambuc CFGBlock *NewTryTerminatedBlock = createBlock(false);
3222f4a2713aSLionel Sambuc // Add the terminator in the try block.
3223f4a2713aSLionel Sambuc NewTryTerminatedBlock->setTerminator(Terminator);
3224f4a2713aSLionel Sambuc
3225f4a2713aSLionel Sambuc bool HasCatchAll = false;
3226f4a2713aSLionel Sambuc for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
3227f4a2713aSLionel Sambuc // The code after the try is the implicit successor.
3228f4a2713aSLionel Sambuc Succ = TrySuccessor;
3229f4a2713aSLionel Sambuc CXXCatchStmt *CS = Terminator->getHandler(h);
3230*0a6a1f1dSLionel Sambuc if (CS->getExceptionDecl() == nullptr) {
3231f4a2713aSLionel Sambuc HasCatchAll = true;
3232f4a2713aSLionel Sambuc }
3233*0a6a1f1dSLionel Sambuc Block = nullptr;
3234f4a2713aSLionel Sambuc CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
3235*0a6a1f1dSLionel Sambuc if (!CatchBlock)
3236*0a6a1f1dSLionel Sambuc return nullptr;
3237f4a2713aSLionel Sambuc // Add this block to the list of successors for the block with the try
3238f4a2713aSLionel Sambuc // statement.
3239f4a2713aSLionel Sambuc addSuccessor(NewTryTerminatedBlock, CatchBlock);
3240f4a2713aSLionel Sambuc }
3241f4a2713aSLionel Sambuc if (!HasCatchAll) {
3242f4a2713aSLionel Sambuc if (PrevTryTerminatedBlock)
3243f4a2713aSLionel Sambuc addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
3244f4a2713aSLionel Sambuc else
3245f4a2713aSLionel Sambuc addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3246f4a2713aSLionel Sambuc }
3247f4a2713aSLionel Sambuc
3248f4a2713aSLionel Sambuc // The code after the try is the implicit successor.
3249f4a2713aSLionel Sambuc Succ = TrySuccessor;
3250f4a2713aSLionel Sambuc
3251f4a2713aSLionel Sambuc // Save the current "try" context.
3252f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock);
3253f4a2713aSLionel Sambuc cfg->addTryDispatchBlock(TryTerminatedBlock);
3254f4a2713aSLionel Sambuc
3255f4a2713aSLionel Sambuc assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
3256*0a6a1f1dSLionel Sambuc Block = nullptr;
3257f4a2713aSLionel Sambuc return addStmt(Terminator->getTryBlock());
3258f4a2713aSLionel Sambuc }
3259f4a2713aSLionel Sambuc
VisitCXXCatchStmt(CXXCatchStmt * CS)3260f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
3261f4a2713aSLionel Sambuc // CXXCatchStmt are treated like labels, so they are the first statement in a
3262f4a2713aSLionel Sambuc // block.
3263f4a2713aSLionel Sambuc
3264f4a2713aSLionel Sambuc // Save local scope position because in case of exception variable ScopePos
3265f4a2713aSLionel Sambuc // won't be restored when traversing AST.
3266f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
3267f4a2713aSLionel Sambuc
3268f4a2713aSLionel Sambuc // Create local scope for possible exception variable.
3269f4a2713aSLionel Sambuc // Store scope position. Add implicit destructor.
3270f4a2713aSLionel Sambuc if (VarDecl *VD = CS->getExceptionDecl()) {
3271f4a2713aSLionel Sambuc LocalScope::const_iterator BeginScopePos = ScopePos;
3272f4a2713aSLionel Sambuc addLocalScopeForVarDecl(VD);
3273f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
3274f4a2713aSLionel Sambuc }
3275f4a2713aSLionel Sambuc
3276f4a2713aSLionel Sambuc if (CS->getHandlerBlock())
3277f4a2713aSLionel Sambuc addStmt(CS->getHandlerBlock());
3278f4a2713aSLionel Sambuc
3279f4a2713aSLionel Sambuc CFGBlock *CatchBlock = Block;
3280f4a2713aSLionel Sambuc if (!CatchBlock)
3281f4a2713aSLionel Sambuc CatchBlock = createBlock();
3282f4a2713aSLionel Sambuc
3283f4a2713aSLionel Sambuc // CXXCatchStmt is more than just a label. They have semantic meaning
3284f4a2713aSLionel Sambuc // as well, as they implicitly "initialize" the catch variable. Add
3285f4a2713aSLionel Sambuc // it to the CFG as a CFGElement so that the control-flow of these
3286f4a2713aSLionel Sambuc // semantics gets captured.
3287f4a2713aSLionel Sambuc appendStmt(CatchBlock, CS);
3288f4a2713aSLionel Sambuc
3289f4a2713aSLionel Sambuc // Also add the CXXCatchStmt as a label, to mirror handling of regular
3290f4a2713aSLionel Sambuc // labels.
3291f4a2713aSLionel Sambuc CatchBlock->setLabel(CS);
3292f4a2713aSLionel Sambuc
3293f4a2713aSLionel Sambuc // Bail out if the CFG is bad.
3294f4a2713aSLionel Sambuc if (badCFG)
3295*0a6a1f1dSLionel Sambuc return nullptr;
3296f4a2713aSLionel Sambuc
3297f4a2713aSLionel Sambuc // We set Block to NULL to allow lazy creation of a new block (if necessary)
3298*0a6a1f1dSLionel Sambuc Block = nullptr;
3299f4a2713aSLionel Sambuc
3300f4a2713aSLionel Sambuc return CatchBlock;
3301f4a2713aSLionel Sambuc }
3302f4a2713aSLionel Sambuc
VisitCXXForRangeStmt(CXXForRangeStmt * S)3303f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
3304f4a2713aSLionel Sambuc // C++0x for-range statements are specified as [stmt.ranged]:
3305f4a2713aSLionel Sambuc //
3306f4a2713aSLionel Sambuc // {
3307f4a2713aSLionel Sambuc // auto && __range = range-init;
3308f4a2713aSLionel Sambuc // for ( auto __begin = begin-expr,
3309f4a2713aSLionel Sambuc // __end = end-expr;
3310f4a2713aSLionel Sambuc // __begin != __end;
3311f4a2713aSLionel Sambuc // ++__begin ) {
3312f4a2713aSLionel Sambuc // for-range-declaration = *__begin;
3313f4a2713aSLionel Sambuc // statement
3314f4a2713aSLionel Sambuc // }
3315f4a2713aSLionel Sambuc // }
3316f4a2713aSLionel Sambuc
3317f4a2713aSLionel Sambuc // Save local scope position before the addition of the implicit variables.
3318f4a2713aSLionel Sambuc SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos);
3319f4a2713aSLionel Sambuc
3320f4a2713aSLionel Sambuc // Create local scopes and destructors for range, begin and end variables.
3321f4a2713aSLionel Sambuc if (Stmt *Range = S->getRangeStmt())
3322f4a2713aSLionel Sambuc addLocalScopeForStmt(Range);
3323f4a2713aSLionel Sambuc if (Stmt *BeginEnd = S->getBeginEndStmt())
3324f4a2713aSLionel Sambuc addLocalScopeForStmt(BeginEnd);
3325f4a2713aSLionel Sambuc addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S);
3326f4a2713aSLionel Sambuc
3327f4a2713aSLionel Sambuc LocalScope::const_iterator ContinueScopePos = ScopePos;
3328f4a2713aSLionel Sambuc
3329f4a2713aSLionel Sambuc // "for" is a control-flow statement. Thus we stop processing the current
3330f4a2713aSLionel Sambuc // block.
3331*0a6a1f1dSLionel Sambuc CFGBlock *LoopSuccessor = nullptr;
3332f4a2713aSLionel Sambuc if (Block) {
3333f4a2713aSLionel Sambuc if (badCFG)
3334*0a6a1f1dSLionel Sambuc return nullptr;
3335f4a2713aSLionel Sambuc LoopSuccessor = Block;
3336f4a2713aSLionel Sambuc } else
3337f4a2713aSLionel Sambuc LoopSuccessor = Succ;
3338f4a2713aSLionel Sambuc
3339f4a2713aSLionel Sambuc // Save the current value for the break targets.
3340f4a2713aSLionel Sambuc // All breaks should go to the code following the loop.
3341f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
3342f4a2713aSLionel Sambuc BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3343f4a2713aSLionel Sambuc
3344f4a2713aSLionel Sambuc // The block for the __begin != __end expression.
3345f4a2713aSLionel Sambuc CFGBlock *ConditionBlock = createBlock(false);
3346f4a2713aSLionel Sambuc ConditionBlock->setTerminator(S);
3347f4a2713aSLionel Sambuc
3348f4a2713aSLionel Sambuc // Now add the actual condition to the condition block.
3349f4a2713aSLionel Sambuc if (Expr *C = S->getCond()) {
3350f4a2713aSLionel Sambuc Block = ConditionBlock;
3351f4a2713aSLionel Sambuc CFGBlock *BeginConditionBlock = addStmt(C);
3352f4a2713aSLionel Sambuc if (badCFG)
3353*0a6a1f1dSLionel Sambuc return nullptr;
3354f4a2713aSLionel Sambuc assert(BeginConditionBlock == ConditionBlock &&
3355f4a2713aSLionel Sambuc "condition block in for-range was unexpectedly complex");
3356f4a2713aSLionel Sambuc (void)BeginConditionBlock;
3357f4a2713aSLionel Sambuc }
3358f4a2713aSLionel Sambuc
3359f4a2713aSLionel Sambuc // The condition block is the implicit successor for the loop body as well as
3360f4a2713aSLionel Sambuc // any code above the loop.
3361f4a2713aSLionel Sambuc Succ = ConditionBlock;
3362f4a2713aSLionel Sambuc
3363f4a2713aSLionel Sambuc // See if this is a known constant.
3364f4a2713aSLionel Sambuc TryResult KnownVal(true);
3365f4a2713aSLionel Sambuc
3366f4a2713aSLionel Sambuc if (S->getCond())
3367f4a2713aSLionel Sambuc KnownVal = tryEvaluateBool(S->getCond());
3368f4a2713aSLionel Sambuc
3369f4a2713aSLionel Sambuc // Now create the loop body.
3370f4a2713aSLionel Sambuc {
3371f4a2713aSLionel Sambuc assert(S->getBody());
3372f4a2713aSLionel Sambuc
3373f4a2713aSLionel Sambuc // Save the current values for Block, Succ, and continue targets.
3374f4a2713aSLionel Sambuc SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
3375f4a2713aSLionel Sambuc SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
3376f4a2713aSLionel Sambuc
3377f4a2713aSLionel Sambuc // Generate increment code in its own basic block. This is the target of
3378f4a2713aSLionel Sambuc // continue statements.
3379*0a6a1f1dSLionel Sambuc Block = nullptr;
3380f4a2713aSLionel Sambuc Succ = addStmt(S->getInc());
3381f4a2713aSLionel Sambuc ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3382f4a2713aSLionel Sambuc
3383f4a2713aSLionel Sambuc // The starting block for the loop increment is the block that should
3384f4a2713aSLionel Sambuc // represent the 'loop target' for looping back to the start of the loop.
3385f4a2713aSLionel Sambuc ContinueJumpTarget.block->setLoopTarget(S);
3386f4a2713aSLionel Sambuc
3387f4a2713aSLionel Sambuc // Finish up the increment block and prepare to start the loop body.
3388f4a2713aSLionel Sambuc assert(Block);
3389f4a2713aSLionel Sambuc if (badCFG)
3390*0a6a1f1dSLionel Sambuc return nullptr;
3391*0a6a1f1dSLionel Sambuc Block = nullptr;
3392f4a2713aSLionel Sambuc
3393f4a2713aSLionel Sambuc // Add implicit scope and dtors for loop variable.
3394f4a2713aSLionel Sambuc addLocalScopeAndDtors(S->getLoopVarStmt());
3395f4a2713aSLionel Sambuc
3396f4a2713aSLionel Sambuc // Populate a new block to contain the loop body and loop variable.
3397f4a2713aSLionel Sambuc addStmt(S->getBody());
3398f4a2713aSLionel Sambuc if (badCFG)
3399*0a6a1f1dSLionel Sambuc return nullptr;
3400f4a2713aSLionel Sambuc CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
3401f4a2713aSLionel Sambuc if (badCFG)
3402*0a6a1f1dSLionel Sambuc return nullptr;
3403f4a2713aSLionel Sambuc
3404f4a2713aSLionel Sambuc // This new body block is a successor to our condition block.
3405*0a6a1f1dSLionel Sambuc addSuccessor(ConditionBlock,
3406*0a6a1f1dSLionel Sambuc KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
3407f4a2713aSLionel Sambuc }
3408f4a2713aSLionel Sambuc
3409f4a2713aSLionel Sambuc // Link up the condition block with the code that follows the loop (the
3410f4a2713aSLionel Sambuc // false branch).
3411*0a6a1f1dSLionel Sambuc addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
3412f4a2713aSLionel Sambuc
3413f4a2713aSLionel Sambuc // Add the initialization statements.
3414f4a2713aSLionel Sambuc Block = createBlock();
3415f4a2713aSLionel Sambuc addStmt(S->getBeginEndStmt());
3416f4a2713aSLionel Sambuc return addStmt(S->getRangeStmt());
3417f4a2713aSLionel Sambuc }
3418f4a2713aSLionel Sambuc
VisitExprWithCleanups(ExprWithCleanups * E,AddStmtChoice asc)3419f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
3420f4a2713aSLionel Sambuc AddStmtChoice asc) {
3421f4a2713aSLionel Sambuc if (BuildOpts.AddTemporaryDtors) {
3422f4a2713aSLionel Sambuc // If adding implicit destructors visit the full expression for adding
3423f4a2713aSLionel Sambuc // destructors of temporaries.
3424*0a6a1f1dSLionel Sambuc TempDtorContext Context;
3425*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getSubExpr(), false, Context);
3426f4a2713aSLionel Sambuc
3427f4a2713aSLionel Sambuc // Full expression has to be added as CFGStmt so it will be sequenced
3428f4a2713aSLionel Sambuc // before destructors of it's temporaries.
3429f4a2713aSLionel Sambuc asc = asc.withAlwaysAdd(true);
3430f4a2713aSLionel Sambuc }
3431f4a2713aSLionel Sambuc return Visit(E->getSubExpr(), asc);
3432f4a2713aSLionel Sambuc }
3433f4a2713aSLionel Sambuc
VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr * E,AddStmtChoice asc)3434f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
3435f4a2713aSLionel Sambuc AddStmtChoice asc) {
3436f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, E)) {
3437f4a2713aSLionel Sambuc autoCreateBlock();
3438f4a2713aSLionel Sambuc appendStmt(Block, E);
3439f4a2713aSLionel Sambuc
3440f4a2713aSLionel Sambuc // We do not want to propagate the AlwaysAdd property.
3441f4a2713aSLionel Sambuc asc = asc.withAlwaysAdd(false);
3442f4a2713aSLionel Sambuc }
3443f4a2713aSLionel Sambuc return Visit(E->getSubExpr(), asc);
3444f4a2713aSLionel Sambuc }
3445f4a2713aSLionel Sambuc
VisitCXXConstructExpr(CXXConstructExpr * C,AddStmtChoice asc)3446f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
3447f4a2713aSLionel Sambuc AddStmtChoice asc) {
3448f4a2713aSLionel Sambuc autoCreateBlock();
3449f4a2713aSLionel Sambuc appendStmt(Block, C);
3450f4a2713aSLionel Sambuc
3451f4a2713aSLionel Sambuc return VisitChildren(C);
3452f4a2713aSLionel Sambuc }
3453f4a2713aSLionel Sambuc
VisitCXXNewExpr(CXXNewExpr * NE,AddStmtChoice asc)3454*0a6a1f1dSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
3455*0a6a1f1dSLionel Sambuc AddStmtChoice asc) {
3456*0a6a1f1dSLionel Sambuc
3457*0a6a1f1dSLionel Sambuc autoCreateBlock();
3458*0a6a1f1dSLionel Sambuc appendStmt(Block, NE);
3459*0a6a1f1dSLionel Sambuc
3460*0a6a1f1dSLionel Sambuc if (NE->getInitializer())
3461*0a6a1f1dSLionel Sambuc Block = Visit(NE->getInitializer());
3462*0a6a1f1dSLionel Sambuc if (BuildOpts.AddCXXNewAllocator)
3463*0a6a1f1dSLionel Sambuc appendNewAllocator(Block, NE);
3464*0a6a1f1dSLionel Sambuc if (NE->isArray())
3465*0a6a1f1dSLionel Sambuc Block = Visit(NE->getArraySize());
3466*0a6a1f1dSLionel Sambuc for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),
3467*0a6a1f1dSLionel Sambuc E = NE->placement_arg_end(); I != E; ++I)
3468*0a6a1f1dSLionel Sambuc Block = Visit(*I);
3469*0a6a1f1dSLionel Sambuc return Block;
3470*0a6a1f1dSLionel Sambuc }
3471f4a2713aSLionel Sambuc
VisitCXXDeleteExpr(CXXDeleteExpr * DE,AddStmtChoice asc)3472f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
3473f4a2713aSLionel Sambuc AddStmtChoice asc) {
3474f4a2713aSLionel Sambuc autoCreateBlock();
3475f4a2713aSLionel Sambuc appendStmt(Block, DE);
3476f4a2713aSLionel Sambuc QualType DTy = DE->getDestroyedType();
3477f4a2713aSLionel Sambuc DTy = DTy.getNonReferenceType();
3478f4a2713aSLionel Sambuc CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
3479f4a2713aSLionel Sambuc if (RD) {
3480f4a2713aSLionel Sambuc if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
3481f4a2713aSLionel Sambuc appendDeleteDtor(Block, RD, DE);
3482f4a2713aSLionel Sambuc }
3483f4a2713aSLionel Sambuc
3484f4a2713aSLionel Sambuc return VisitChildren(DE);
3485f4a2713aSLionel Sambuc }
3486f4a2713aSLionel Sambuc
VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr * E,AddStmtChoice asc)3487f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
3488f4a2713aSLionel Sambuc AddStmtChoice asc) {
3489f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, E)) {
3490f4a2713aSLionel Sambuc autoCreateBlock();
3491f4a2713aSLionel Sambuc appendStmt(Block, E);
3492f4a2713aSLionel Sambuc // We do not want to propagate the AlwaysAdd property.
3493f4a2713aSLionel Sambuc asc = asc.withAlwaysAdd(false);
3494f4a2713aSLionel Sambuc }
3495f4a2713aSLionel Sambuc return Visit(E->getSubExpr(), asc);
3496f4a2713aSLionel Sambuc }
3497f4a2713aSLionel Sambuc
VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr * C,AddStmtChoice asc)3498f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
3499f4a2713aSLionel Sambuc AddStmtChoice asc) {
3500f4a2713aSLionel Sambuc autoCreateBlock();
3501f4a2713aSLionel Sambuc appendStmt(Block, C);
3502f4a2713aSLionel Sambuc return VisitChildren(C);
3503f4a2713aSLionel Sambuc }
3504f4a2713aSLionel Sambuc
VisitImplicitCastExpr(ImplicitCastExpr * E,AddStmtChoice asc)3505f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
3506f4a2713aSLionel Sambuc AddStmtChoice asc) {
3507f4a2713aSLionel Sambuc if (asc.alwaysAdd(*this, E)) {
3508f4a2713aSLionel Sambuc autoCreateBlock();
3509f4a2713aSLionel Sambuc appendStmt(Block, E);
3510f4a2713aSLionel Sambuc }
3511f4a2713aSLionel Sambuc return Visit(E->getSubExpr(), AddStmtChoice());
3512f4a2713aSLionel Sambuc }
3513f4a2713aSLionel Sambuc
VisitIndirectGotoStmt(IndirectGotoStmt * I)3514f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
3515f4a2713aSLionel Sambuc // Lazily create the indirect-goto dispatch block if there isn't one already.
3516f4a2713aSLionel Sambuc CFGBlock *IBlock = cfg->getIndirectGotoBlock();
3517f4a2713aSLionel Sambuc
3518f4a2713aSLionel Sambuc if (!IBlock) {
3519f4a2713aSLionel Sambuc IBlock = createBlock(false);
3520f4a2713aSLionel Sambuc cfg->setIndirectGotoBlock(IBlock);
3521f4a2713aSLionel Sambuc }
3522f4a2713aSLionel Sambuc
3523f4a2713aSLionel Sambuc // IndirectGoto is a control-flow statement. Thus we stop processing the
3524f4a2713aSLionel Sambuc // current block and create a new one.
3525f4a2713aSLionel Sambuc if (badCFG)
3526*0a6a1f1dSLionel Sambuc return nullptr;
3527f4a2713aSLionel Sambuc
3528f4a2713aSLionel Sambuc Block = createBlock(false);
3529f4a2713aSLionel Sambuc Block->setTerminator(I);
3530f4a2713aSLionel Sambuc addSuccessor(Block, IBlock);
3531f4a2713aSLionel Sambuc return addStmt(I->getTarget());
3532f4a2713aSLionel Sambuc }
3533f4a2713aSLionel Sambuc
VisitForTemporaryDtors(Stmt * E,bool BindToTemporary,TempDtorContext & Context)3534*0a6a1f1dSLionel Sambuc CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary,
3535*0a6a1f1dSLionel Sambuc TempDtorContext &Context) {
3536f4a2713aSLionel Sambuc assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
3537f4a2713aSLionel Sambuc
3538f4a2713aSLionel Sambuc tryAgain:
3539f4a2713aSLionel Sambuc if (!E) {
3540f4a2713aSLionel Sambuc badCFG = true;
3541*0a6a1f1dSLionel Sambuc return nullptr;
3542f4a2713aSLionel Sambuc }
3543f4a2713aSLionel Sambuc switch (E->getStmtClass()) {
3544f4a2713aSLionel Sambuc default:
3545*0a6a1f1dSLionel Sambuc return VisitChildrenForTemporaryDtors(E, Context);
3546f4a2713aSLionel Sambuc
3547f4a2713aSLionel Sambuc case Stmt::BinaryOperatorClass:
3548*0a6a1f1dSLionel Sambuc return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
3549*0a6a1f1dSLionel Sambuc Context);
3550f4a2713aSLionel Sambuc
3551f4a2713aSLionel Sambuc case Stmt::CXXBindTemporaryExprClass:
3552f4a2713aSLionel Sambuc return VisitCXXBindTemporaryExprForTemporaryDtors(
3553*0a6a1f1dSLionel Sambuc cast<CXXBindTemporaryExpr>(E), BindToTemporary, Context);
3554f4a2713aSLionel Sambuc
3555f4a2713aSLionel Sambuc case Stmt::BinaryConditionalOperatorClass:
3556f4a2713aSLionel Sambuc case Stmt::ConditionalOperatorClass:
3557f4a2713aSLionel Sambuc return VisitConditionalOperatorForTemporaryDtors(
3558*0a6a1f1dSLionel Sambuc cast<AbstractConditionalOperator>(E), BindToTemporary, Context);
3559f4a2713aSLionel Sambuc
3560f4a2713aSLionel Sambuc case Stmt::ImplicitCastExprClass:
3561f4a2713aSLionel Sambuc // For implicit cast we want BindToTemporary to be passed further.
3562f4a2713aSLionel Sambuc E = cast<CastExpr>(E)->getSubExpr();
3563f4a2713aSLionel Sambuc goto tryAgain;
3564f4a2713aSLionel Sambuc
3565*0a6a1f1dSLionel Sambuc case Stmt::CXXFunctionalCastExprClass:
3566*0a6a1f1dSLionel Sambuc // For functional cast we want BindToTemporary to be passed further.
3567*0a6a1f1dSLionel Sambuc E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
3568*0a6a1f1dSLionel Sambuc goto tryAgain;
3569*0a6a1f1dSLionel Sambuc
3570f4a2713aSLionel Sambuc case Stmt::ParenExprClass:
3571f4a2713aSLionel Sambuc E = cast<ParenExpr>(E)->getSubExpr();
3572f4a2713aSLionel Sambuc goto tryAgain;
3573f4a2713aSLionel Sambuc
3574*0a6a1f1dSLionel Sambuc case Stmt::MaterializeTemporaryExprClass: {
3575*0a6a1f1dSLionel Sambuc const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E);
3576*0a6a1f1dSLionel Sambuc BindToTemporary = (MTE->getStorageDuration() != SD_FullExpression);
3577*0a6a1f1dSLionel Sambuc SmallVector<const Expr *, 2> CommaLHSs;
3578*0a6a1f1dSLionel Sambuc SmallVector<SubobjectAdjustment, 2> Adjustments;
3579*0a6a1f1dSLionel Sambuc // Find the expression whose lifetime needs to be extended.
3580*0a6a1f1dSLionel Sambuc E = const_cast<Expr *>(
3581*0a6a1f1dSLionel Sambuc cast<MaterializeTemporaryExpr>(E)
3582*0a6a1f1dSLionel Sambuc ->GetTemporaryExpr()
3583*0a6a1f1dSLionel Sambuc ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
3584*0a6a1f1dSLionel Sambuc // Visit the skipped comma operator left-hand sides for other temporaries.
3585*0a6a1f1dSLionel Sambuc for (const Expr *CommaLHS : CommaLHSs) {
3586*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
3587*0a6a1f1dSLionel Sambuc /*BindToTemporary=*/false, Context);
3588*0a6a1f1dSLionel Sambuc }
3589*0a6a1f1dSLionel Sambuc goto tryAgain;
3590*0a6a1f1dSLionel Sambuc }
3591*0a6a1f1dSLionel Sambuc
3592*0a6a1f1dSLionel Sambuc case Stmt::BlockExprClass:
3593*0a6a1f1dSLionel Sambuc // Don't recurse into blocks; their subexpressions don't get evaluated
3594*0a6a1f1dSLionel Sambuc // here.
3595*0a6a1f1dSLionel Sambuc return Block;
3596*0a6a1f1dSLionel Sambuc
3597*0a6a1f1dSLionel Sambuc case Stmt::LambdaExprClass: {
3598*0a6a1f1dSLionel Sambuc // For lambda expressions, only recurse into the capture initializers,
3599*0a6a1f1dSLionel Sambuc // and not the body.
3600*0a6a1f1dSLionel Sambuc auto *LE = cast<LambdaExpr>(E);
3601*0a6a1f1dSLionel Sambuc CFGBlock *B = Block;
3602*0a6a1f1dSLionel Sambuc for (Expr *Init : LE->capture_inits()) {
3603*0a6a1f1dSLionel Sambuc if (CFGBlock *R = VisitForTemporaryDtors(
3604*0a6a1f1dSLionel Sambuc Init, /*BindToTemporary=*/false, Context))
3605*0a6a1f1dSLionel Sambuc B = R;
3606*0a6a1f1dSLionel Sambuc }
3607*0a6a1f1dSLionel Sambuc return B;
3608*0a6a1f1dSLionel Sambuc }
3609*0a6a1f1dSLionel Sambuc
3610*0a6a1f1dSLionel Sambuc case Stmt::CXXDefaultArgExprClass:
3611*0a6a1f1dSLionel Sambuc E = cast<CXXDefaultArgExpr>(E)->getExpr();
3612*0a6a1f1dSLionel Sambuc goto tryAgain;
3613*0a6a1f1dSLionel Sambuc
3614*0a6a1f1dSLionel Sambuc case Stmt::CXXDefaultInitExprClass:
3615*0a6a1f1dSLionel Sambuc E = cast<CXXDefaultInitExpr>(E)->getExpr();
3616f4a2713aSLionel Sambuc goto tryAgain;
3617f4a2713aSLionel Sambuc }
3618f4a2713aSLionel Sambuc }
3619f4a2713aSLionel Sambuc
VisitChildrenForTemporaryDtors(Stmt * E,TempDtorContext & Context)3620*0a6a1f1dSLionel Sambuc CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
3621*0a6a1f1dSLionel Sambuc TempDtorContext &Context) {
3622*0a6a1f1dSLionel Sambuc if (isa<LambdaExpr>(E)) {
3623*0a6a1f1dSLionel Sambuc // Do not visit the children of lambdas; they have their own CFGs.
3624*0a6a1f1dSLionel Sambuc return Block;
3625*0a6a1f1dSLionel Sambuc }
3626*0a6a1f1dSLionel Sambuc
3627f4a2713aSLionel Sambuc // When visiting children for destructors we want to visit them in reverse
3628f4a2713aSLionel Sambuc // order that they will appear in the CFG. Because the CFG is built
3629f4a2713aSLionel Sambuc // bottom-up, this means we visit them in their natural order, which
3630f4a2713aSLionel Sambuc // reverses them in the CFG.
3631f4a2713aSLionel Sambuc CFGBlock *B = Block;
3632f4a2713aSLionel Sambuc for (Stmt::child_range I = E->children(); I; ++I) {
3633f4a2713aSLionel Sambuc if (Stmt *Child = *I)
3634*0a6a1f1dSLionel Sambuc if (CFGBlock *R = VisitForTemporaryDtors(Child, false, Context))
3635f4a2713aSLionel Sambuc B = R;
3636f4a2713aSLionel Sambuc }
3637f4a2713aSLionel Sambuc return B;
3638f4a2713aSLionel Sambuc }
3639f4a2713aSLionel Sambuc
VisitBinaryOperatorForTemporaryDtors(BinaryOperator * E,TempDtorContext & Context)3640*0a6a1f1dSLionel Sambuc CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
3641*0a6a1f1dSLionel Sambuc BinaryOperator *E, TempDtorContext &Context) {
3642f4a2713aSLionel Sambuc if (E->isLogicalOp()) {
3643*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getLHS(), false, Context);
3644*0a6a1f1dSLionel Sambuc TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
3645*0a6a1f1dSLionel Sambuc if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
3646*0a6a1f1dSLionel Sambuc RHSExecuted.negate();
3647f4a2713aSLionel Sambuc
3648*0a6a1f1dSLionel Sambuc // We do not know at CFG-construction time whether the right-hand-side was
3649*0a6a1f1dSLionel Sambuc // executed, thus we add a branch node that depends on the temporary
3650*0a6a1f1dSLionel Sambuc // constructor call.
3651*0a6a1f1dSLionel Sambuc TempDtorContext RHSContext(
3652*0a6a1f1dSLionel Sambuc bothKnownTrue(Context.KnownExecuted, RHSExecuted));
3653*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
3654*0a6a1f1dSLionel Sambuc InsertTempDtorDecisionBlock(RHSContext);
3655f4a2713aSLionel Sambuc
3656*0a6a1f1dSLionel Sambuc return Block;
3657f4a2713aSLionel Sambuc }
3658f4a2713aSLionel Sambuc
3659f4a2713aSLionel Sambuc if (E->isAssignmentOp()) {
3660f4a2713aSLionel Sambuc // For assignment operator (=) LHS expression is visited
3661f4a2713aSLionel Sambuc // before RHS expression. For destructors visit them in reverse order.
3662*0a6a1f1dSLionel Sambuc CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);
3663*0a6a1f1dSLionel Sambuc CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
3664f4a2713aSLionel Sambuc return LHSBlock ? LHSBlock : RHSBlock;
3665f4a2713aSLionel Sambuc }
3666f4a2713aSLionel Sambuc
3667f4a2713aSLionel Sambuc // For any other binary operator RHS expression is visited before
3668f4a2713aSLionel Sambuc // LHS expression (order of children). For destructors visit them in reverse
3669f4a2713aSLionel Sambuc // order.
3670*0a6a1f1dSLionel Sambuc CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
3671*0a6a1f1dSLionel Sambuc CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);
3672f4a2713aSLionel Sambuc return RHSBlock ? RHSBlock : LHSBlock;
3673f4a2713aSLionel Sambuc }
3674f4a2713aSLionel Sambuc
VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr * E,bool BindToTemporary,TempDtorContext & Context)3675f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
3676*0a6a1f1dSLionel Sambuc CXXBindTemporaryExpr *E, bool BindToTemporary, TempDtorContext &Context) {
3677f4a2713aSLionel Sambuc // First add destructors for temporaries in subexpression.
3678*0a6a1f1dSLionel Sambuc CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), false, Context);
3679f4a2713aSLionel Sambuc if (!BindToTemporary) {
3680f4a2713aSLionel Sambuc // If lifetime of temporary is not prolonged (by assigning to constant
3681f4a2713aSLionel Sambuc // reference) add destructor for it.
3682f4a2713aSLionel Sambuc
3683f4a2713aSLionel Sambuc const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
3684f4a2713aSLionel Sambuc
3685*0a6a1f1dSLionel Sambuc if (Dtor->isNoReturn()) {
3686*0a6a1f1dSLionel Sambuc // If the destructor is marked as a no-return destructor, we need to
3687*0a6a1f1dSLionel Sambuc // create a new block for the destructor which does not have as a
3688*0a6a1f1dSLionel Sambuc // successor anything built thus far. Control won't flow out of this
3689*0a6a1f1dSLionel Sambuc // block.
3690*0a6a1f1dSLionel Sambuc if (B) Succ = B;
3691*0a6a1f1dSLionel Sambuc Block = createNoReturnBlock();
3692*0a6a1f1dSLionel Sambuc } else if (Context.needsTempDtorBranch()) {
3693*0a6a1f1dSLionel Sambuc // If we need to introduce a branch, we add a new block that we will hook
3694*0a6a1f1dSLionel Sambuc // up to a decision block later.
3695*0a6a1f1dSLionel Sambuc if (B) Succ = B;
3696*0a6a1f1dSLionel Sambuc Block = createBlock();
3697*0a6a1f1dSLionel Sambuc } else {
3698*0a6a1f1dSLionel Sambuc autoCreateBlock();
3699*0a6a1f1dSLionel Sambuc }
3700*0a6a1f1dSLionel Sambuc if (Context.needsTempDtorBranch()) {
3701*0a6a1f1dSLionel Sambuc Context.setDecisionPoint(Succ, E);
3702*0a6a1f1dSLionel Sambuc }
3703f4a2713aSLionel Sambuc appendTemporaryDtor(Block, E);
3704*0a6a1f1dSLionel Sambuc
3705f4a2713aSLionel Sambuc B = Block;
3706f4a2713aSLionel Sambuc }
3707f4a2713aSLionel Sambuc return B;
3708f4a2713aSLionel Sambuc }
3709f4a2713aSLionel Sambuc
InsertTempDtorDecisionBlock(const TempDtorContext & Context,CFGBlock * FalseSucc)3710*0a6a1f1dSLionel Sambuc void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
3711*0a6a1f1dSLionel Sambuc CFGBlock *FalseSucc) {
3712*0a6a1f1dSLionel Sambuc if (!Context.TerminatorExpr) {
3713*0a6a1f1dSLionel Sambuc // If no temporary was found, we do not need to insert a decision point.
3714*0a6a1f1dSLionel Sambuc return;
3715*0a6a1f1dSLionel Sambuc }
3716*0a6a1f1dSLionel Sambuc assert(Context.TerminatorExpr);
3717*0a6a1f1dSLionel Sambuc CFGBlock *Decision = createBlock(false);
3718*0a6a1f1dSLionel Sambuc Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true));
3719*0a6a1f1dSLionel Sambuc addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
3720*0a6a1f1dSLionel Sambuc addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
3721*0a6a1f1dSLionel Sambuc !Context.KnownExecuted.isTrue());
3722*0a6a1f1dSLionel Sambuc Block = Decision;
3723*0a6a1f1dSLionel Sambuc }
3724*0a6a1f1dSLionel Sambuc
VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator * E,bool BindToTemporary,TempDtorContext & Context)3725f4a2713aSLionel Sambuc CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
3726*0a6a1f1dSLionel Sambuc AbstractConditionalOperator *E, bool BindToTemporary,
3727*0a6a1f1dSLionel Sambuc TempDtorContext &Context) {
3728*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getCond(), false, Context);
3729*0a6a1f1dSLionel Sambuc CFGBlock *ConditionBlock = Block;
3730*0a6a1f1dSLionel Sambuc CFGBlock *ConditionSucc = Succ;
3731*0a6a1f1dSLionel Sambuc TryResult ConditionVal = tryEvaluateBool(E->getCond());
3732*0a6a1f1dSLionel Sambuc TryResult NegatedVal = ConditionVal;
3733*0a6a1f1dSLionel Sambuc if (NegatedVal.isKnown()) NegatedVal.negate();
3734f4a2713aSLionel Sambuc
3735*0a6a1f1dSLionel Sambuc TempDtorContext TrueContext(
3736*0a6a1f1dSLionel Sambuc bothKnownTrue(Context.KnownExecuted, ConditionVal));
3737*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary, TrueContext);
3738*0a6a1f1dSLionel Sambuc CFGBlock *TrueBlock = Block;
3739f4a2713aSLionel Sambuc
3740*0a6a1f1dSLionel Sambuc Block = ConditionBlock;
3741*0a6a1f1dSLionel Sambuc Succ = ConditionSucc;
3742*0a6a1f1dSLionel Sambuc TempDtorContext FalseContext(
3743*0a6a1f1dSLionel Sambuc bothKnownTrue(Context.KnownExecuted, NegatedVal));
3744*0a6a1f1dSLionel Sambuc VisitForTemporaryDtors(E->getFalseExpr(), BindToTemporary, FalseContext);
3745f4a2713aSLionel Sambuc
3746*0a6a1f1dSLionel Sambuc if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
3747*0a6a1f1dSLionel Sambuc InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
3748*0a6a1f1dSLionel Sambuc } else if (TrueContext.TerminatorExpr) {
3749*0a6a1f1dSLionel Sambuc Block = TrueBlock;
3750*0a6a1f1dSLionel Sambuc InsertTempDtorDecisionBlock(TrueContext);
3751f4a2713aSLionel Sambuc } else {
3752*0a6a1f1dSLionel Sambuc InsertTempDtorDecisionBlock(FalseContext);
3753f4a2713aSLionel Sambuc }
3754f4a2713aSLionel Sambuc return Block;
3755f4a2713aSLionel Sambuc }
3756f4a2713aSLionel Sambuc
3757f4a2713aSLionel Sambuc } // end anonymous namespace
3758f4a2713aSLionel Sambuc
3759f4a2713aSLionel Sambuc /// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has
3760f4a2713aSLionel Sambuc /// no successors or predecessors. If this is the first block created in the
3761f4a2713aSLionel Sambuc /// CFG, it is automatically set to be the Entry and Exit of the CFG.
createBlock()3762f4a2713aSLionel Sambuc CFGBlock *CFG::createBlock() {
3763f4a2713aSLionel Sambuc bool first_block = begin() == end();
3764f4a2713aSLionel Sambuc
3765f4a2713aSLionel Sambuc // Create the block.
3766f4a2713aSLionel Sambuc CFGBlock *Mem = getAllocator().Allocate<CFGBlock>();
3767f4a2713aSLionel Sambuc new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);
3768f4a2713aSLionel Sambuc Blocks.push_back(Mem, BlkBVC);
3769f4a2713aSLionel Sambuc
3770f4a2713aSLionel Sambuc // If this is the first block, set it as the Entry and Exit.
3771f4a2713aSLionel Sambuc if (first_block)
3772f4a2713aSLionel Sambuc Entry = Exit = &back();
3773f4a2713aSLionel Sambuc
3774f4a2713aSLionel Sambuc // Return the block.
3775f4a2713aSLionel Sambuc return &back();
3776f4a2713aSLionel Sambuc }
3777f4a2713aSLionel Sambuc
3778*0a6a1f1dSLionel Sambuc /// buildCFG - Constructs a CFG from an AST.
buildCFG(const Decl * D,Stmt * Statement,ASTContext * C,const BuildOptions & BO)3779*0a6a1f1dSLionel Sambuc std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,
3780*0a6a1f1dSLionel Sambuc ASTContext *C, const BuildOptions &BO) {
3781f4a2713aSLionel Sambuc CFGBuilder Builder(C, BO);
3782f4a2713aSLionel Sambuc return Builder.buildCFG(D, Statement);
3783f4a2713aSLionel Sambuc }
3784f4a2713aSLionel Sambuc
3785f4a2713aSLionel Sambuc const CXXDestructorDecl *
getDestructorDecl(ASTContext & astContext) const3786f4a2713aSLionel Sambuc CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
3787f4a2713aSLionel Sambuc switch (getKind()) {
3788f4a2713aSLionel Sambuc case CFGElement::Statement:
3789f4a2713aSLionel Sambuc case CFGElement::Initializer:
3790*0a6a1f1dSLionel Sambuc case CFGElement::NewAllocator:
3791f4a2713aSLionel Sambuc llvm_unreachable("getDestructorDecl should only be used with "
3792f4a2713aSLionel Sambuc "ImplicitDtors");
3793f4a2713aSLionel Sambuc case CFGElement::AutomaticObjectDtor: {
3794f4a2713aSLionel Sambuc const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
3795f4a2713aSLionel Sambuc QualType ty = var->getType();
3796f4a2713aSLionel Sambuc ty = ty.getNonReferenceType();
3797f4a2713aSLionel Sambuc while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
3798f4a2713aSLionel Sambuc ty = arrayType->getElementType();
3799f4a2713aSLionel Sambuc }
3800f4a2713aSLionel Sambuc const RecordType *recordType = ty->getAs<RecordType>();
3801f4a2713aSLionel Sambuc const CXXRecordDecl *classDecl =
3802f4a2713aSLionel Sambuc cast<CXXRecordDecl>(recordType->getDecl());
3803f4a2713aSLionel Sambuc return classDecl->getDestructor();
3804f4a2713aSLionel Sambuc }
3805f4a2713aSLionel Sambuc case CFGElement::DeleteDtor: {
3806f4a2713aSLionel Sambuc const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
3807f4a2713aSLionel Sambuc QualType DTy = DE->getDestroyedType();
3808f4a2713aSLionel Sambuc DTy = DTy.getNonReferenceType();
3809f4a2713aSLionel Sambuc const CXXRecordDecl *classDecl =
3810f4a2713aSLionel Sambuc astContext.getBaseElementType(DTy)->getAsCXXRecordDecl();
3811f4a2713aSLionel Sambuc return classDecl->getDestructor();
3812f4a2713aSLionel Sambuc }
3813f4a2713aSLionel Sambuc case CFGElement::TemporaryDtor: {
3814f4a2713aSLionel Sambuc const CXXBindTemporaryExpr *bindExpr =
3815f4a2713aSLionel Sambuc castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
3816f4a2713aSLionel Sambuc const CXXTemporary *temp = bindExpr->getTemporary();
3817f4a2713aSLionel Sambuc return temp->getDestructor();
3818f4a2713aSLionel Sambuc }
3819f4a2713aSLionel Sambuc case CFGElement::BaseDtor:
3820f4a2713aSLionel Sambuc case CFGElement::MemberDtor:
3821f4a2713aSLionel Sambuc
3822f4a2713aSLionel Sambuc // Not yet supported.
3823*0a6a1f1dSLionel Sambuc return nullptr;
3824f4a2713aSLionel Sambuc }
3825f4a2713aSLionel Sambuc llvm_unreachable("getKind() returned bogus value");
3826f4a2713aSLionel Sambuc }
3827f4a2713aSLionel Sambuc
isNoReturn(ASTContext & astContext) const3828f4a2713aSLionel Sambuc bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const {
3829f4a2713aSLionel Sambuc if (const CXXDestructorDecl *DD = getDestructorDecl(astContext))
3830f4a2713aSLionel Sambuc return DD->isNoReturn();
3831f4a2713aSLionel Sambuc return false;
3832f4a2713aSLionel Sambuc }
3833f4a2713aSLionel Sambuc
3834f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3835*0a6a1f1dSLionel Sambuc // CFGBlock operations.
3836f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3837f4a2713aSLionel Sambuc
AdjacentBlock(CFGBlock * B,bool IsReachable)3838*0a6a1f1dSLionel Sambuc CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
3839*0a6a1f1dSLionel Sambuc : ReachableBlock(IsReachable ? B : nullptr),
3840*0a6a1f1dSLionel Sambuc UnreachableBlock(!IsReachable ? B : nullptr,
3841*0a6a1f1dSLionel Sambuc B && IsReachable ? AB_Normal : AB_Unreachable) {}
3842*0a6a1f1dSLionel Sambuc
AdjacentBlock(CFGBlock * B,CFGBlock * AlternateBlock)3843*0a6a1f1dSLionel Sambuc CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
3844*0a6a1f1dSLionel Sambuc : ReachableBlock(B),
3845*0a6a1f1dSLionel Sambuc UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
3846*0a6a1f1dSLionel Sambuc B == AlternateBlock ? AB_Alternate : AB_Normal) {}
3847*0a6a1f1dSLionel Sambuc
addSuccessor(AdjacentBlock Succ,BumpVectorContext & C)3848*0a6a1f1dSLionel Sambuc void CFGBlock::addSuccessor(AdjacentBlock Succ,
3849*0a6a1f1dSLionel Sambuc BumpVectorContext &C) {
3850*0a6a1f1dSLionel Sambuc if (CFGBlock *B = Succ.getReachableBlock())
3851*0a6a1f1dSLionel Sambuc B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C);
3852*0a6a1f1dSLionel Sambuc
3853*0a6a1f1dSLionel Sambuc if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock())
3854*0a6a1f1dSLionel Sambuc UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);
3855*0a6a1f1dSLionel Sambuc
3856*0a6a1f1dSLionel Sambuc Succs.push_back(Succ, C);
3857*0a6a1f1dSLionel Sambuc }
3858*0a6a1f1dSLionel Sambuc
FilterEdge(const CFGBlock::FilterOptions & F,const CFGBlock * From,const CFGBlock * To)3859f4a2713aSLionel Sambuc bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
3860f4a2713aSLionel Sambuc const CFGBlock *From, const CFGBlock *To) {
3861f4a2713aSLionel Sambuc
3862*0a6a1f1dSLionel Sambuc if (F.IgnoreNullPredecessors && !From)
3863*0a6a1f1dSLionel Sambuc return true;
3864*0a6a1f1dSLionel Sambuc
3865*0a6a1f1dSLionel Sambuc if (To && From && F.IgnoreDefaultsWithCoveredEnums) {
3866f4a2713aSLionel Sambuc // If the 'To' has no label or is labeled but the label isn't a
3867f4a2713aSLionel Sambuc // CaseStmt then filter this edge.
3868f4a2713aSLionel Sambuc if (const SwitchStmt *S =
3869f4a2713aSLionel Sambuc dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) {
3870f4a2713aSLionel Sambuc if (S->isAllEnumCasesCovered()) {
3871f4a2713aSLionel Sambuc const Stmt *L = To->getLabel();
3872f4a2713aSLionel Sambuc if (!L || !isa<CaseStmt>(L))
3873f4a2713aSLionel Sambuc return true;
3874f4a2713aSLionel Sambuc }
3875f4a2713aSLionel Sambuc }
3876f4a2713aSLionel Sambuc }
3877f4a2713aSLionel Sambuc
3878f4a2713aSLionel Sambuc return false;
3879f4a2713aSLionel Sambuc }
3880f4a2713aSLionel Sambuc
3881f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3882f4a2713aSLionel Sambuc // CFG pretty printing
3883f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3884f4a2713aSLionel Sambuc
3885f4a2713aSLionel Sambuc namespace {
3886f4a2713aSLionel Sambuc
3887f4a2713aSLionel Sambuc class StmtPrinterHelper : public PrinterHelper {
3888f4a2713aSLionel Sambuc typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
3889f4a2713aSLionel Sambuc typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy;
3890f4a2713aSLionel Sambuc StmtMapTy StmtMap;
3891f4a2713aSLionel Sambuc DeclMapTy DeclMap;
3892f4a2713aSLionel Sambuc signed currentBlock;
3893f4a2713aSLionel Sambuc unsigned currStmt;
3894f4a2713aSLionel Sambuc const LangOptions &LangOpts;
3895f4a2713aSLionel Sambuc public:
3896f4a2713aSLionel Sambuc
StmtPrinterHelper(const CFG * cfg,const LangOptions & LO)3897f4a2713aSLionel Sambuc StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
3898f4a2713aSLionel Sambuc : currentBlock(0), currStmt(0), LangOpts(LO)
3899f4a2713aSLionel Sambuc {
3900f4a2713aSLionel Sambuc for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
3901f4a2713aSLionel Sambuc unsigned j = 1;
3902f4a2713aSLionel Sambuc for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
3903f4a2713aSLionel Sambuc BI != BEnd; ++BI, ++j ) {
3904f4a2713aSLionel Sambuc if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
3905f4a2713aSLionel Sambuc const Stmt *stmt= SE->getStmt();
3906f4a2713aSLionel Sambuc std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
3907f4a2713aSLionel Sambuc StmtMap[stmt] = P;
3908f4a2713aSLionel Sambuc
3909f4a2713aSLionel Sambuc switch (stmt->getStmtClass()) {
3910f4a2713aSLionel Sambuc case Stmt::DeclStmtClass:
3911f4a2713aSLionel Sambuc DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
3912f4a2713aSLionel Sambuc break;
3913f4a2713aSLionel Sambuc case Stmt::IfStmtClass: {
3914f4a2713aSLionel Sambuc const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
3915f4a2713aSLionel Sambuc if (var)
3916f4a2713aSLionel Sambuc DeclMap[var] = P;
3917f4a2713aSLionel Sambuc break;
3918f4a2713aSLionel Sambuc }
3919f4a2713aSLionel Sambuc case Stmt::ForStmtClass: {
3920f4a2713aSLionel Sambuc const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
3921f4a2713aSLionel Sambuc if (var)
3922f4a2713aSLionel Sambuc DeclMap[var] = P;
3923f4a2713aSLionel Sambuc break;
3924f4a2713aSLionel Sambuc }
3925f4a2713aSLionel Sambuc case Stmt::WhileStmtClass: {
3926f4a2713aSLionel Sambuc const VarDecl *var =
3927f4a2713aSLionel Sambuc cast<WhileStmt>(stmt)->getConditionVariable();
3928f4a2713aSLionel Sambuc if (var)
3929f4a2713aSLionel Sambuc DeclMap[var] = P;
3930f4a2713aSLionel Sambuc break;
3931f4a2713aSLionel Sambuc }
3932f4a2713aSLionel Sambuc case Stmt::SwitchStmtClass: {
3933f4a2713aSLionel Sambuc const VarDecl *var =
3934f4a2713aSLionel Sambuc cast<SwitchStmt>(stmt)->getConditionVariable();
3935f4a2713aSLionel Sambuc if (var)
3936f4a2713aSLionel Sambuc DeclMap[var] = P;
3937f4a2713aSLionel Sambuc break;
3938f4a2713aSLionel Sambuc }
3939f4a2713aSLionel Sambuc case Stmt::CXXCatchStmtClass: {
3940f4a2713aSLionel Sambuc const VarDecl *var =
3941f4a2713aSLionel Sambuc cast<CXXCatchStmt>(stmt)->getExceptionDecl();
3942f4a2713aSLionel Sambuc if (var)
3943f4a2713aSLionel Sambuc DeclMap[var] = P;
3944f4a2713aSLionel Sambuc break;
3945f4a2713aSLionel Sambuc }
3946f4a2713aSLionel Sambuc default:
3947f4a2713aSLionel Sambuc break;
3948f4a2713aSLionel Sambuc }
3949f4a2713aSLionel Sambuc }
3950f4a2713aSLionel Sambuc }
3951f4a2713aSLionel Sambuc }
3952f4a2713aSLionel Sambuc }
3953f4a2713aSLionel Sambuc
3954f4a2713aSLionel Sambuc
~StmtPrinterHelper()3955f4a2713aSLionel Sambuc virtual ~StmtPrinterHelper() {}
3956f4a2713aSLionel Sambuc
getLangOpts() const3957f4a2713aSLionel Sambuc const LangOptions &getLangOpts() const { return LangOpts; }
setBlockID(signed i)3958f4a2713aSLionel Sambuc void setBlockID(signed i) { currentBlock = i; }
setStmtID(unsigned i)3959f4a2713aSLionel Sambuc void setStmtID(unsigned i) { currStmt = i; }
3960f4a2713aSLionel Sambuc
handledStmt(Stmt * S,raw_ostream & OS)3961*0a6a1f1dSLionel Sambuc bool handledStmt(Stmt *S, raw_ostream &OS) override {
3962f4a2713aSLionel Sambuc StmtMapTy::iterator I = StmtMap.find(S);
3963f4a2713aSLionel Sambuc
3964f4a2713aSLionel Sambuc if (I == StmtMap.end())
3965f4a2713aSLionel Sambuc return false;
3966f4a2713aSLionel Sambuc
3967f4a2713aSLionel Sambuc if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
3968f4a2713aSLionel Sambuc && I->second.second == currStmt) {
3969f4a2713aSLionel Sambuc return false;
3970f4a2713aSLionel Sambuc }
3971f4a2713aSLionel Sambuc
3972f4a2713aSLionel Sambuc OS << "[B" << I->second.first << "." << I->second.second << "]";
3973f4a2713aSLionel Sambuc return true;
3974f4a2713aSLionel Sambuc }
3975f4a2713aSLionel Sambuc
handleDecl(const Decl * D,raw_ostream & OS)3976f4a2713aSLionel Sambuc bool handleDecl(const Decl *D, raw_ostream &OS) {
3977f4a2713aSLionel Sambuc DeclMapTy::iterator I = DeclMap.find(D);
3978f4a2713aSLionel Sambuc
3979f4a2713aSLionel Sambuc if (I == DeclMap.end())
3980f4a2713aSLionel Sambuc return false;
3981f4a2713aSLionel Sambuc
3982f4a2713aSLionel Sambuc if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
3983f4a2713aSLionel Sambuc && I->second.second == currStmt) {
3984f4a2713aSLionel Sambuc return false;
3985f4a2713aSLionel Sambuc }
3986f4a2713aSLionel Sambuc
3987f4a2713aSLionel Sambuc OS << "[B" << I->second.first << "." << I->second.second << "]";
3988f4a2713aSLionel Sambuc return true;
3989f4a2713aSLionel Sambuc }
3990f4a2713aSLionel Sambuc };
3991f4a2713aSLionel Sambuc } // end anonymous namespace
3992f4a2713aSLionel Sambuc
3993f4a2713aSLionel Sambuc
3994f4a2713aSLionel Sambuc namespace {
3995f4a2713aSLionel Sambuc class CFGBlockTerminatorPrint
3996f4a2713aSLionel Sambuc : public StmtVisitor<CFGBlockTerminatorPrint,void> {
3997f4a2713aSLionel Sambuc
3998f4a2713aSLionel Sambuc raw_ostream &OS;
3999f4a2713aSLionel Sambuc StmtPrinterHelper* Helper;
4000f4a2713aSLionel Sambuc PrintingPolicy Policy;
4001f4a2713aSLionel Sambuc public:
CFGBlockTerminatorPrint(raw_ostream & os,StmtPrinterHelper * helper,const PrintingPolicy & Policy)4002f4a2713aSLionel Sambuc CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
4003f4a2713aSLionel Sambuc const PrintingPolicy &Policy)
4004*0a6a1f1dSLionel Sambuc : OS(os), Helper(helper), Policy(Policy) {
4005*0a6a1f1dSLionel Sambuc this->Policy.IncludeNewlines = false;
4006*0a6a1f1dSLionel Sambuc }
4007f4a2713aSLionel Sambuc
VisitIfStmt(IfStmt * I)4008f4a2713aSLionel Sambuc void VisitIfStmt(IfStmt *I) {
4009f4a2713aSLionel Sambuc OS << "if ";
4010*0a6a1f1dSLionel Sambuc if (Stmt *C = I->getCond())
4011*0a6a1f1dSLionel Sambuc C->printPretty(OS, Helper, Policy);
4012f4a2713aSLionel Sambuc }
4013f4a2713aSLionel Sambuc
4014f4a2713aSLionel Sambuc // Default case.
VisitStmt(Stmt * Terminator)4015f4a2713aSLionel Sambuc void VisitStmt(Stmt *Terminator) {
4016f4a2713aSLionel Sambuc Terminator->printPretty(OS, Helper, Policy);
4017f4a2713aSLionel Sambuc }
4018f4a2713aSLionel Sambuc
VisitDeclStmt(DeclStmt * DS)4019f4a2713aSLionel Sambuc void VisitDeclStmt(DeclStmt *DS) {
4020f4a2713aSLionel Sambuc VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
4021f4a2713aSLionel Sambuc OS << "static init " << VD->getName();
4022f4a2713aSLionel Sambuc }
4023f4a2713aSLionel Sambuc
VisitForStmt(ForStmt * F)4024f4a2713aSLionel Sambuc void VisitForStmt(ForStmt *F) {
4025f4a2713aSLionel Sambuc OS << "for (" ;
4026f4a2713aSLionel Sambuc if (F->getInit())
4027f4a2713aSLionel Sambuc OS << "...";
4028f4a2713aSLionel Sambuc OS << "; ";
4029f4a2713aSLionel Sambuc if (Stmt *C = F->getCond())
4030f4a2713aSLionel Sambuc C->printPretty(OS, Helper, Policy);
4031f4a2713aSLionel Sambuc OS << "; ";
4032f4a2713aSLionel Sambuc if (F->getInc())
4033f4a2713aSLionel Sambuc OS << "...";
4034f4a2713aSLionel Sambuc OS << ")";
4035f4a2713aSLionel Sambuc }
4036f4a2713aSLionel Sambuc
VisitWhileStmt(WhileStmt * W)4037f4a2713aSLionel Sambuc void VisitWhileStmt(WhileStmt *W) {
4038f4a2713aSLionel Sambuc OS << "while " ;
4039f4a2713aSLionel Sambuc if (Stmt *C = W->getCond())
4040f4a2713aSLionel Sambuc C->printPretty(OS, Helper, Policy);
4041f4a2713aSLionel Sambuc }
4042f4a2713aSLionel Sambuc
VisitDoStmt(DoStmt * D)4043f4a2713aSLionel Sambuc void VisitDoStmt(DoStmt *D) {
4044f4a2713aSLionel Sambuc OS << "do ... while ";
4045f4a2713aSLionel Sambuc if (Stmt *C = D->getCond())
4046f4a2713aSLionel Sambuc C->printPretty(OS, Helper, Policy);
4047f4a2713aSLionel Sambuc }
4048f4a2713aSLionel Sambuc
VisitSwitchStmt(SwitchStmt * Terminator)4049f4a2713aSLionel Sambuc void VisitSwitchStmt(SwitchStmt *Terminator) {
4050f4a2713aSLionel Sambuc OS << "switch ";
4051f4a2713aSLionel Sambuc Terminator->getCond()->printPretty(OS, Helper, Policy);
4052f4a2713aSLionel Sambuc }
4053f4a2713aSLionel Sambuc
VisitCXXTryStmt(CXXTryStmt * CS)4054f4a2713aSLionel Sambuc void VisitCXXTryStmt(CXXTryStmt *CS) {
4055f4a2713aSLionel Sambuc OS << "try ...";
4056f4a2713aSLionel Sambuc }
4057f4a2713aSLionel Sambuc
VisitAbstractConditionalOperator(AbstractConditionalOperator * C)4058f4a2713aSLionel Sambuc void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
4059*0a6a1f1dSLionel Sambuc if (Stmt *Cond = C->getCond())
4060*0a6a1f1dSLionel Sambuc Cond->printPretty(OS, Helper, Policy);
4061f4a2713aSLionel Sambuc OS << " ? ... : ...";
4062f4a2713aSLionel Sambuc }
4063f4a2713aSLionel Sambuc
VisitChooseExpr(ChooseExpr * C)4064f4a2713aSLionel Sambuc void VisitChooseExpr(ChooseExpr *C) {
4065f4a2713aSLionel Sambuc OS << "__builtin_choose_expr( ";
4066*0a6a1f1dSLionel Sambuc if (Stmt *Cond = C->getCond())
4067*0a6a1f1dSLionel Sambuc Cond->printPretty(OS, Helper, Policy);
4068f4a2713aSLionel Sambuc OS << " )";
4069f4a2713aSLionel Sambuc }
4070f4a2713aSLionel Sambuc
VisitIndirectGotoStmt(IndirectGotoStmt * I)4071f4a2713aSLionel Sambuc void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
4072f4a2713aSLionel Sambuc OS << "goto *";
4073*0a6a1f1dSLionel Sambuc if (Stmt *T = I->getTarget())
4074*0a6a1f1dSLionel Sambuc T->printPretty(OS, Helper, Policy);
4075f4a2713aSLionel Sambuc }
4076f4a2713aSLionel Sambuc
VisitBinaryOperator(BinaryOperator * B)4077f4a2713aSLionel Sambuc void VisitBinaryOperator(BinaryOperator* B) {
4078f4a2713aSLionel Sambuc if (!B->isLogicalOp()) {
4079f4a2713aSLionel Sambuc VisitExpr(B);
4080f4a2713aSLionel Sambuc return;
4081f4a2713aSLionel Sambuc }
4082f4a2713aSLionel Sambuc
4083*0a6a1f1dSLionel Sambuc if (B->getLHS())
4084f4a2713aSLionel Sambuc B->getLHS()->printPretty(OS, Helper, Policy);
4085f4a2713aSLionel Sambuc
4086f4a2713aSLionel Sambuc switch (B->getOpcode()) {
4087f4a2713aSLionel Sambuc case BO_LOr:
4088f4a2713aSLionel Sambuc OS << " || ...";
4089f4a2713aSLionel Sambuc return;
4090f4a2713aSLionel Sambuc case BO_LAnd:
4091f4a2713aSLionel Sambuc OS << " && ...";
4092f4a2713aSLionel Sambuc return;
4093f4a2713aSLionel Sambuc default:
4094f4a2713aSLionel Sambuc llvm_unreachable("Invalid logical operator.");
4095f4a2713aSLionel Sambuc }
4096f4a2713aSLionel Sambuc }
4097f4a2713aSLionel Sambuc
VisitExpr(Expr * E)4098f4a2713aSLionel Sambuc void VisitExpr(Expr *E) {
4099f4a2713aSLionel Sambuc E->printPretty(OS, Helper, Policy);
4100f4a2713aSLionel Sambuc }
4101*0a6a1f1dSLionel Sambuc
4102*0a6a1f1dSLionel Sambuc public:
print(CFGTerminator T)4103*0a6a1f1dSLionel Sambuc void print(CFGTerminator T) {
4104*0a6a1f1dSLionel Sambuc if (T.isTemporaryDtorsBranch())
4105*0a6a1f1dSLionel Sambuc OS << "(Temp Dtor) ";
4106*0a6a1f1dSLionel Sambuc Visit(T.getStmt());
4107*0a6a1f1dSLionel Sambuc }
4108f4a2713aSLionel Sambuc };
4109f4a2713aSLionel Sambuc } // end anonymous namespace
4110f4a2713aSLionel Sambuc
print_elem(raw_ostream & OS,StmtPrinterHelper & Helper,const CFGElement & E)4111f4a2713aSLionel Sambuc static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
4112f4a2713aSLionel Sambuc const CFGElement &E) {
4113f4a2713aSLionel Sambuc if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
4114f4a2713aSLionel Sambuc const Stmt *S = CS->getStmt();
4115*0a6a1f1dSLionel Sambuc assert(S != nullptr && "Expecting non-null Stmt");
4116f4a2713aSLionel Sambuc
4117f4a2713aSLionel Sambuc // special printing for statement-expressions.
4118f4a2713aSLionel Sambuc if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
4119f4a2713aSLionel Sambuc const CompoundStmt *Sub = SE->getSubStmt();
4120f4a2713aSLionel Sambuc
4121f4a2713aSLionel Sambuc if (Sub->children()) {
4122f4a2713aSLionel Sambuc OS << "({ ... ; ";
4123f4a2713aSLionel Sambuc Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
4124f4a2713aSLionel Sambuc OS << " })\n";
4125f4a2713aSLionel Sambuc return;
4126f4a2713aSLionel Sambuc }
4127f4a2713aSLionel Sambuc }
4128f4a2713aSLionel Sambuc // special printing for comma expressions.
4129f4a2713aSLionel Sambuc if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
4130f4a2713aSLionel Sambuc if (B->getOpcode() == BO_Comma) {
4131f4a2713aSLionel Sambuc OS << "... , ";
4132f4a2713aSLionel Sambuc Helper.handledStmt(B->getRHS(),OS);
4133f4a2713aSLionel Sambuc OS << '\n';
4134f4a2713aSLionel Sambuc return;
4135f4a2713aSLionel Sambuc }
4136f4a2713aSLionel Sambuc }
4137f4a2713aSLionel Sambuc S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
4138f4a2713aSLionel Sambuc
4139f4a2713aSLionel Sambuc if (isa<CXXOperatorCallExpr>(S)) {
4140f4a2713aSLionel Sambuc OS << " (OperatorCall)";
4141f4a2713aSLionel Sambuc }
4142f4a2713aSLionel Sambuc else if (isa<CXXBindTemporaryExpr>(S)) {
4143f4a2713aSLionel Sambuc OS << " (BindTemporary)";
4144f4a2713aSLionel Sambuc }
4145f4a2713aSLionel Sambuc else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
4146f4a2713aSLionel Sambuc OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")";
4147f4a2713aSLionel Sambuc }
4148f4a2713aSLionel Sambuc else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
4149f4a2713aSLionel Sambuc OS << " (" << CE->getStmtClassName() << ", "
4150f4a2713aSLionel Sambuc << CE->getCastKindName()
4151f4a2713aSLionel Sambuc << ", " << CE->getType().getAsString()
4152f4a2713aSLionel Sambuc << ")";
4153f4a2713aSLionel Sambuc }
4154f4a2713aSLionel Sambuc
4155f4a2713aSLionel Sambuc // Expressions need a newline.
4156f4a2713aSLionel Sambuc if (isa<Expr>(S))
4157f4a2713aSLionel Sambuc OS << '\n';
4158f4a2713aSLionel Sambuc
4159f4a2713aSLionel Sambuc } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) {
4160f4a2713aSLionel Sambuc const CXXCtorInitializer *I = IE->getInitializer();
4161f4a2713aSLionel Sambuc if (I->isBaseInitializer())
4162f4a2713aSLionel Sambuc OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
4163f4a2713aSLionel Sambuc else if (I->isDelegatingInitializer())
4164f4a2713aSLionel Sambuc OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();
4165f4a2713aSLionel Sambuc else OS << I->getAnyMember()->getName();
4166f4a2713aSLionel Sambuc
4167f4a2713aSLionel Sambuc OS << "(";
4168f4a2713aSLionel Sambuc if (Expr *IE = I->getInit())
4169f4a2713aSLionel Sambuc IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
4170f4a2713aSLionel Sambuc OS << ")";
4171f4a2713aSLionel Sambuc
4172f4a2713aSLionel Sambuc if (I->isBaseInitializer())
4173f4a2713aSLionel Sambuc OS << " (Base initializer)\n";
4174f4a2713aSLionel Sambuc else if (I->isDelegatingInitializer())
4175f4a2713aSLionel Sambuc OS << " (Delegating initializer)\n";
4176f4a2713aSLionel Sambuc else OS << " (Member initializer)\n";
4177f4a2713aSLionel Sambuc
4178f4a2713aSLionel Sambuc } else if (Optional<CFGAutomaticObjDtor> DE =
4179f4a2713aSLionel Sambuc E.getAs<CFGAutomaticObjDtor>()) {
4180f4a2713aSLionel Sambuc const VarDecl *VD = DE->getVarDecl();
4181f4a2713aSLionel Sambuc Helper.handleDecl(VD, OS);
4182f4a2713aSLionel Sambuc
4183f4a2713aSLionel Sambuc const Type* T = VD->getType().getTypePtr();
4184f4a2713aSLionel Sambuc if (const ReferenceType* RT = T->getAs<ReferenceType>())
4185f4a2713aSLionel Sambuc T = RT->getPointeeType().getTypePtr();
4186f4a2713aSLionel Sambuc T = T->getBaseElementTypeUnsafe();
4187f4a2713aSLionel Sambuc
4188f4a2713aSLionel Sambuc OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()";
4189f4a2713aSLionel Sambuc OS << " (Implicit destructor)\n";
4190f4a2713aSLionel Sambuc
4191*0a6a1f1dSLionel Sambuc } else if (Optional<CFGNewAllocator> NE = E.getAs<CFGNewAllocator>()) {
4192*0a6a1f1dSLionel Sambuc OS << "CFGNewAllocator(";
4193*0a6a1f1dSLionel Sambuc if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
4194*0a6a1f1dSLionel Sambuc AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
4195*0a6a1f1dSLionel Sambuc OS << ")\n";
4196f4a2713aSLionel Sambuc } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
4197f4a2713aSLionel Sambuc const CXXRecordDecl *RD = DE->getCXXRecordDecl();
4198f4a2713aSLionel Sambuc if (!RD)
4199f4a2713aSLionel Sambuc return;
4200f4a2713aSLionel Sambuc CXXDeleteExpr *DelExpr =
4201f4a2713aSLionel Sambuc const_cast<CXXDeleteExpr*>(DE->getDeleteExpr());
4202f4a2713aSLionel Sambuc Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
4203f4a2713aSLionel Sambuc OS << "->~" << RD->getName().str() << "()";
4204f4a2713aSLionel Sambuc OS << " (Implicit destructor)\n";
4205f4a2713aSLionel Sambuc } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) {
4206f4a2713aSLionel Sambuc const CXXBaseSpecifier *BS = BE->getBaseSpecifier();
4207f4a2713aSLionel Sambuc OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
4208f4a2713aSLionel Sambuc OS << " (Base object destructor)\n";
4209f4a2713aSLionel Sambuc
4210f4a2713aSLionel Sambuc } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) {
4211f4a2713aSLionel Sambuc const FieldDecl *FD = ME->getFieldDecl();
4212f4a2713aSLionel Sambuc const Type *T = FD->getType()->getBaseElementTypeUnsafe();
4213f4a2713aSLionel Sambuc OS << "this->" << FD->getName();
4214f4a2713aSLionel Sambuc OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
4215f4a2713aSLionel Sambuc OS << " (Member object destructor)\n";
4216f4a2713aSLionel Sambuc
4217f4a2713aSLionel Sambuc } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) {
4218f4a2713aSLionel Sambuc const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr();
4219f4a2713aSLionel Sambuc OS << "~";
4220f4a2713aSLionel Sambuc BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
4221f4a2713aSLionel Sambuc OS << "() (Temporary object destructor)\n";
4222f4a2713aSLionel Sambuc }
4223f4a2713aSLionel Sambuc }
4224f4a2713aSLionel Sambuc
print_block(raw_ostream & OS,const CFG * cfg,const CFGBlock & B,StmtPrinterHelper & Helper,bool print_edges,bool ShowColors)4225f4a2713aSLionel Sambuc static void print_block(raw_ostream &OS, const CFG* cfg,
4226f4a2713aSLionel Sambuc const CFGBlock &B,
4227f4a2713aSLionel Sambuc StmtPrinterHelper &Helper, bool print_edges,
4228f4a2713aSLionel Sambuc bool ShowColors) {
4229f4a2713aSLionel Sambuc
4230f4a2713aSLionel Sambuc Helper.setBlockID(B.getBlockID());
4231f4a2713aSLionel Sambuc
4232f4a2713aSLionel Sambuc // Print the header.
4233f4a2713aSLionel Sambuc if (ShowColors)
4234f4a2713aSLionel Sambuc OS.changeColor(raw_ostream::YELLOW, true);
4235f4a2713aSLionel Sambuc
4236f4a2713aSLionel Sambuc OS << "\n [B" << B.getBlockID();
4237f4a2713aSLionel Sambuc
4238f4a2713aSLionel Sambuc if (&B == &cfg->getEntry())
4239f4a2713aSLionel Sambuc OS << " (ENTRY)]\n";
4240f4a2713aSLionel Sambuc else if (&B == &cfg->getExit())
4241f4a2713aSLionel Sambuc OS << " (EXIT)]\n";
4242f4a2713aSLionel Sambuc else if (&B == cfg->getIndirectGotoBlock())
4243f4a2713aSLionel Sambuc OS << " (INDIRECT GOTO DISPATCH)]\n";
4244*0a6a1f1dSLionel Sambuc else if (B.hasNoReturnElement())
4245*0a6a1f1dSLionel Sambuc OS << " (NORETURN)]\n";
4246f4a2713aSLionel Sambuc else
4247f4a2713aSLionel Sambuc OS << "]\n";
4248f4a2713aSLionel Sambuc
4249f4a2713aSLionel Sambuc if (ShowColors)
4250f4a2713aSLionel Sambuc OS.resetColor();
4251f4a2713aSLionel Sambuc
4252f4a2713aSLionel Sambuc // Print the label of this block.
4253f4a2713aSLionel Sambuc if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {
4254f4a2713aSLionel Sambuc
4255f4a2713aSLionel Sambuc if (print_edges)
4256f4a2713aSLionel Sambuc OS << " ";
4257f4a2713aSLionel Sambuc
4258f4a2713aSLionel Sambuc if (LabelStmt *L = dyn_cast<LabelStmt>(Label))
4259f4a2713aSLionel Sambuc OS << L->getName();
4260f4a2713aSLionel Sambuc else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
4261f4a2713aSLionel Sambuc OS << "case ";
4262*0a6a1f1dSLionel Sambuc if (C->getLHS())
4263f4a2713aSLionel Sambuc C->getLHS()->printPretty(OS, &Helper,
4264f4a2713aSLionel Sambuc PrintingPolicy(Helper.getLangOpts()));
4265f4a2713aSLionel Sambuc if (C->getRHS()) {
4266f4a2713aSLionel Sambuc OS << " ... ";
4267f4a2713aSLionel Sambuc C->getRHS()->printPretty(OS, &Helper,
4268f4a2713aSLionel Sambuc PrintingPolicy(Helper.getLangOpts()));
4269f4a2713aSLionel Sambuc }
4270f4a2713aSLionel Sambuc } else if (isa<DefaultStmt>(Label))
4271f4a2713aSLionel Sambuc OS << "default";
4272f4a2713aSLionel Sambuc else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
4273f4a2713aSLionel Sambuc OS << "catch (";
4274f4a2713aSLionel Sambuc if (CS->getExceptionDecl())
4275f4a2713aSLionel Sambuc CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper.getLangOpts()),
4276f4a2713aSLionel Sambuc 0);
4277f4a2713aSLionel Sambuc else
4278f4a2713aSLionel Sambuc OS << "...";
4279f4a2713aSLionel Sambuc OS << ")";
4280f4a2713aSLionel Sambuc
4281f4a2713aSLionel Sambuc } else
4282f4a2713aSLionel Sambuc llvm_unreachable("Invalid label statement in CFGBlock.");
4283f4a2713aSLionel Sambuc
4284f4a2713aSLionel Sambuc OS << ":\n";
4285f4a2713aSLionel Sambuc }
4286f4a2713aSLionel Sambuc
4287f4a2713aSLionel Sambuc // Iterate through the statements in the block and print them.
4288f4a2713aSLionel Sambuc unsigned j = 1;
4289f4a2713aSLionel Sambuc
4290f4a2713aSLionel Sambuc for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
4291f4a2713aSLionel Sambuc I != E ; ++I, ++j ) {
4292f4a2713aSLionel Sambuc
4293f4a2713aSLionel Sambuc // Print the statement # in the basic block and the statement itself.
4294f4a2713aSLionel Sambuc if (print_edges)
4295f4a2713aSLionel Sambuc OS << " ";
4296f4a2713aSLionel Sambuc
4297f4a2713aSLionel Sambuc OS << llvm::format("%3d", j) << ": ";
4298f4a2713aSLionel Sambuc
4299f4a2713aSLionel Sambuc Helper.setStmtID(j);
4300f4a2713aSLionel Sambuc
4301f4a2713aSLionel Sambuc print_elem(OS, Helper, *I);
4302f4a2713aSLionel Sambuc }
4303f4a2713aSLionel Sambuc
4304f4a2713aSLionel Sambuc // Print the terminator of this block.
4305f4a2713aSLionel Sambuc if (B.getTerminator()) {
4306f4a2713aSLionel Sambuc if (ShowColors)
4307f4a2713aSLionel Sambuc OS.changeColor(raw_ostream::GREEN);
4308f4a2713aSLionel Sambuc
4309f4a2713aSLionel Sambuc OS << " T: ";
4310f4a2713aSLionel Sambuc
4311f4a2713aSLionel Sambuc Helper.setBlockID(-1);
4312f4a2713aSLionel Sambuc
4313f4a2713aSLionel Sambuc PrintingPolicy PP(Helper.getLangOpts());
4314f4a2713aSLionel Sambuc CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
4315*0a6a1f1dSLionel Sambuc TPrinter.print(B.getTerminator());
4316f4a2713aSLionel Sambuc OS << '\n';
4317f4a2713aSLionel Sambuc
4318f4a2713aSLionel Sambuc if (ShowColors)
4319f4a2713aSLionel Sambuc OS.resetColor();
4320f4a2713aSLionel Sambuc }
4321f4a2713aSLionel Sambuc
4322f4a2713aSLionel Sambuc if (print_edges) {
4323f4a2713aSLionel Sambuc // Print the predecessors of this block.
4324f4a2713aSLionel Sambuc if (!B.pred_empty()) {
4325f4a2713aSLionel Sambuc const raw_ostream::Colors Color = raw_ostream::BLUE;
4326f4a2713aSLionel Sambuc if (ShowColors)
4327f4a2713aSLionel Sambuc OS.changeColor(Color);
4328f4a2713aSLionel Sambuc OS << " Preds " ;
4329f4a2713aSLionel Sambuc if (ShowColors)
4330f4a2713aSLionel Sambuc OS.resetColor();
4331f4a2713aSLionel Sambuc OS << '(' << B.pred_size() << "):";
4332f4a2713aSLionel Sambuc unsigned i = 0;
4333f4a2713aSLionel Sambuc
4334f4a2713aSLionel Sambuc if (ShowColors)
4335f4a2713aSLionel Sambuc OS.changeColor(Color);
4336f4a2713aSLionel Sambuc
4337f4a2713aSLionel Sambuc for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
4338f4a2713aSLionel Sambuc I != E; ++I, ++i) {
4339f4a2713aSLionel Sambuc
4340f4a2713aSLionel Sambuc if (i % 10 == 8)
4341f4a2713aSLionel Sambuc OS << "\n ";
4342f4a2713aSLionel Sambuc
4343*0a6a1f1dSLionel Sambuc CFGBlock *B = *I;
4344*0a6a1f1dSLionel Sambuc bool Reachable = true;
4345*0a6a1f1dSLionel Sambuc if (!B) {
4346*0a6a1f1dSLionel Sambuc Reachable = false;
4347*0a6a1f1dSLionel Sambuc B = I->getPossiblyUnreachableBlock();
4348*0a6a1f1dSLionel Sambuc }
4349*0a6a1f1dSLionel Sambuc
4350*0a6a1f1dSLionel Sambuc OS << " B" << B->getBlockID();
4351*0a6a1f1dSLionel Sambuc if (!Reachable)
4352*0a6a1f1dSLionel Sambuc OS << "(Unreachable)";
4353f4a2713aSLionel Sambuc }
4354f4a2713aSLionel Sambuc
4355f4a2713aSLionel Sambuc if (ShowColors)
4356f4a2713aSLionel Sambuc OS.resetColor();
4357f4a2713aSLionel Sambuc
4358f4a2713aSLionel Sambuc OS << '\n';
4359f4a2713aSLionel Sambuc }
4360f4a2713aSLionel Sambuc
4361f4a2713aSLionel Sambuc // Print the successors of this block.
4362f4a2713aSLionel Sambuc if (!B.succ_empty()) {
4363f4a2713aSLionel Sambuc const raw_ostream::Colors Color = raw_ostream::MAGENTA;
4364f4a2713aSLionel Sambuc if (ShowColors)
4365f4a2713aSLionel Sambuc OS.changeColor(Color);
4366f4a2713aSLionel Sambuc OS << " Succs ";
4367f4a2713aSLionel Sambuc if (ShowColors)
4368f4a2713aSLionel Sambuc OS.resetColor();
4369f4a2713aSLionel Sambuc OS << '(' << B.succ_size() << "):";
4370f4a2713aSLionel Sambuc unsigned i = 0;
4371f4a2713aSLionel Sambuc
4372f4a2713aSLionel Sambuc if (ShowColors)
4373f4a2713aSLionel Sambuc OS.changeColor(Color);
4374f4a2713aSLionel Sambuc
4375f4a2713aSLionel Sambuc for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
4376f4a2713aSLionel Sambuc I != E; ++I, ++i) {
4377f4a2713aSLionel Sambuc
4378f4a2713aSLionel Sambuc if (i % 10 == 8)
4379f4a2713aSLionel Sambuc OS << "\n ";
4380f4a2713aSLionel Sambuc
4381*0a6a1f1dSLionel Sambuc CFGBlock *B = *I;
4382*0a6a1f1dSLionel Sambuc
4383*0a6a1f1dSLionel Sambuc bool Reachable = true;
4384*0a6a1f1dSLionel Sambuc if (!B) {
4385*0a6a1f1dSLionel Sambuc Reachable = false;
4386*0a6a1f1dSLionel Sambuc B = I->getPossiblyUnreachableBlock();
4387*0a6a1f1dSLionel Sambuc }
4388*0a6a1f1dSLionel Sambuc
4389*0a6a1f1dSLionel Sambuc if (B) {
4390*0a6a1f1dSLionel Sambuc OS << " B" << B->getBlockID();
4391*0a6a1f1dSLionel Sambuc if (!Reachable)
4392*0a6a1f1dSLionel Sambuc OS << "(Unreachable)";
4393*0a6a1f1dSLionel Sambuc }
4394*0a6a1f1dSLionel Sambuc else {
4395f4a2713aSLionel Sambuc OS << " NULL";
4396f4a2713aSLionel Sambuc }
4397*0a6a1f1dSLionel Sambuc }
4398f4a2713aSLionel Sambuc
4399f4a2713aSLionel Sambuc if (ShowColors)
4400f4a2713aSLionel Sambuc OS.resetColor();
4401f4a2713aSLionel Sambuc OS << '\n';
4402f4a2713aSLionel Sambuc }
4403f4a2713aSLionel Sambuc }
4404f4a2713aSLionel Sambuc }
4405f4a2713aSLionel Sambuc
4406f4a2713aSLionel Sambuc
4407f4a2713aSLionel Sambuc /// dump - A simple pretty printer of a CFG that outputs to stderr.
dump(const LangOptions & LO,bool ShowColors) const4408f4a2713aSLionel Sambuc void CFG::dump(const LangOptions &LO, bool ShowColors) const {
4409f4a2713aSLionel Sambuc print(llvm::errs(), LO, ShowColors);
4410f4a2713aSLionel Sambuc }
4411f4a2713aSLionel Sambuc
4412f4a2713aSLionel Sambuc /// print - A simple pretty printer of a CFG that outputs to an ostream.
print(raw_ostream & OS,const LangOptions & LO,bool ShowColors) const4413f4a2713aSLionel Sambuc void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const {
4414f4a2713aSLionel Sambuc StmtPrinterHelper Helper(this, LO);
4415f4a2713aSLionel Sambuc
4416f4a2713aSLionel Sambuc // Print the entry block.
4417f4a2713aSLionel Sambuc print_block(OS, this, getEntry(), Helper, true, ShowColors);
4418f4a2713aSLionel Sambuc
4419f4a2713aSLionel Sambuc // Iterate through the CFGBlocks and print them one by one.
4420f4a2713aSLionel Sambuc for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
4421f4a2713aSLionel Sambuc // Skip the entry block, because we already printed it.
4422f4a2713aSLionel Sambuc if (&(**I) == &getEntry() || &(**I) == &getExit())
4423f4a2713aSLionel Sambuc continue;
4424f4a2713aSLionel Sambuc
4425f4a2713aSLionel Sambuc print_block(OS, this, **I, Helper, true, ShowColors);
4426f4a2713aSLionel Sambuc }
4427f4a2713aSLionel Sambuc
4428f4a2713aSLionel Sambuc // Print the exit block.
4429f4a2713aSLionel Sambuc print_block(OS, this, getExit(), Helper, true, ShowColors);
4430f4a2713aSLionel Sambuc OS << '\n';
4431f4a2713aSLionel Sambuc OS.flush();
4432f4a2713aSLionel Sambuc }
4433f4a2713aSLionel Sambuc
4434f4a2713aSLionel Sambuc /// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
dump(const CFG * cfg,const LangOptions & LO,bool ShowColors) const4435f4a2713aSLionel Sambuc void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,
4436f4a2713aSLionel Sambuc bool ShowColors) const {
4437f4a2713aSLionel Sambuc print(llvm::errs(), cfg, LO, ShowColors);
4438f4a2713aSLionel Sambuc }
4439f4a2713aSLionel Sambuc
dump() const4440*0a6a1f1dSLionel Sambuc void CFGBlock::dump() const {
4441*0a6a1f1dSLionel Sambuc dump(getParent(), LangOptions(), false);
4442*0a6a1f1dSLionel Sambuc }
4443*0a6a1f1dSLionel Sambuc
4444f4a2713aSLionel Sambuc /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
4445f4a2713aSLionel Sambuc /// Generally this will only be called from CFG::print.
print(raw_ostream & OS,const CFG * cfg,const LangOptions & LO,bool ShowColors) const4446f4a2713aSLionel Sambuc void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
4447f4a2713aSLionel Sambuc const LangOptions &LO, bool ShowColors) const {
4448f4a2713aSLionel Sambuc StmtPrinterHelper Helper(cfg, LO);
4449f4a2713aSLionel Sambuc print_block(OS, cfg, *this, Helper, true, ShowColors);
4450f4a2713aSLionel Sambuc OS << '\n';
4451f4a2713aSLionel Sambuc }
4452f4a2713aSLionel Sambuc
4453f4a2713aSLionel Sambuc /// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
printTerminator(raw_ostream & OS,const LangOptions & LO) const4454f4a2713aSLionel Sambuc void CFGBlock::printTerminator(raw_ostream &OS,
4455f4a2713aSLionel Sambuc const LangOptions &LO) const {
4456*0a6a1f1dSLionel Sambuc CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));
4457*0a6a1f1dSLionel Sambuc TPrinter.print(getTerminator());
4458f4a2713aSLionel Sambuc }
4459f4a2713aSLionel Sambuc
getTerminatorCondition(bool StripParens)4460*0a6a1f1dSLionel Sambuc Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
4461f4a2713aSLionel Sambuc Stmt *Terminator = this->Terminator;
4462f4a2713aSLionel Sambuc if (!Terminator)
4463*0a6a1f1dSLionel Sambuc return nullptr;
4464f4a2713aSLionel Sambuc
4465*0a6a1f1dSLionel Sambuc Expr *E = nullptr;
4466f4a2713aSLionel Sambuc
4467f4a2713aSLionel Sambuc switch (Terminator->getStmtClass()) {
4468f4a2713aSLionel Sambuc default:
4469f4a2713aSLionel Sambuc break;
4470f4a2713aSLionel Sambuc
4471f4a2713aSLionel Sambuc case Stmt::CXXForRangeStmtClass:
4472f4a2713aSLionel Sambuc E = cast<CXXForRangeStmt>(Terminator)->getCond();
4473f4a2713aSLionel Sambuc break;
4474f4a2713aSLionel Sambuc
4475f4a2713aSLionel Sambuc case Stmt::ForStmtClass:
4476f4a2713aSLionel Sambuc E = cast<ForStmt>(Terminator)->getCond();
4477f4a2713aSLionel Sambuc break;
4478f4a2713aSLionel Sambuc
4479f4a2713aSLionel Sambuc case Stmt::WhileStmtClass:
4480f4a2713aSLionel Sambuc E = cast<WhileStmt>(Terminator)->getCond();
4481f4a2713aSLionel Sambuc break;
4482f4a2713aSLionel Sambuc
4483f4a2713aSLionel Sambuc case Stmt::DoStmtClass:
4484f4a2713aSLionel Sambuc E = cast<DoStmt>(Terminator)->getCond();
4485f4a2713aSLionel Sambuc break;
4486f4a2713aSLionel Sambuc
4487f4a2713aSLionel Sambuc case Stmt::IfStmtClass:
4488f4a2713aSLionel Sambuc E = cast<IfStmt>(Terminator)->getCond();
4489f4a2713aSLionel Sambuc break;
4490f4a2713aSLionel Sambuc
4491f4a2713aSLionel Sambuc case Stmt::ChooseExprClass:
4492f4a2713aSLionel Sambuc E = cast<ChooseExpr>(Terminator)->getCond();
4493f4a2713aSLionel Sambuc break;
4494f4a2713aSLionel Sambuc
4495f4a2713aSLionel Sambuc case Stmt::IndirectGotoStmtClass:
4496f4a2713aSLionel Sambuc E = cast<IndirectGotoStmt>(Terminator)->getTarget();
4497f4a2713aSLionel Sambuc break;
4498f4a2713aSLionel Sambuc
4499f4a2713aSLionel Sambuc case Stmt::SwitchStmtClass:
4500f4a2713aSLionel Sambuc E = cast<SwitchStmt>(Terminator)->getCond();
4501f4a2713aSLionel Sambuc break;
4502f4a2713aSLionel Sambuc
4503f4a2713aSLionel Sambuc case Stmt::BinaryConditionalOperatorClass:
4504f4a2713aSLionel Sambuc E = cast<BinaryConditionalOperator>(Terminator)->getCond();
4505f4a2713aSLionel Sambuc break;
4506f4a2713aSLionel Sambuc
4507f4a2713aSLionel Sambuc case Stmt::ConditionalOperatorClass:
4508f4a2713aSLionel Sambuc E = cast<ConditionalOperator>(Terminator)->getCond();
4509f4a2713aSLionel Sambuc break;
4510f4a2713aSLionel Sambuc
4511f4a2713aSLionel Sambuc case Stmt::BinaryOperatorClass: // '&&' and '||'
4512f4a2713aSLionel Sambuc E = cast<BinaryOperator>(Terminator)->getLHS();
4513f4a2713aSLionel Sambuc break;
4514f4a2713aSLionel Sambuc
4515f4a2713aSLionel Sambuc case Stmt::ObjCForCollectionStmtClass:
4516f4a2713aSLionel Sambuc return Terminator;
4517f4a2713aSLionel Sambuc }
4518f4a2713aSLionel Sambuc
4519*0a6a1f1dSLionel Sambuc if (!StripParens)
4520*0a6a1f1dSLionel Sambuc return E;
4521*0a6a1f1dSLionel Sambuc
4522*0a6a1f1dSLionel Sambuc return E ? E->IgnoreParens() : nullptr;
4523f4a2713aSLionel Sambuc }
4524f4a2713aSLionel Sambuc
4525f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
4526f4a2713aSLionel Sambuc // CFG Graphviz Visualization
4527f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
4528f4a2713aSLionel Sambuc
4529f4a2713aSLionel Sambuc
4530f4a2713aSLionel Sambuc #ifndef NDEBUG
4531f4a2713aSLionel Sambuc static StmtPrinterHelper* GraphHelper;
4532f4a2713aSLionel Sambuc #endif
4533f4a2713aSLionel Sambuc
viewCFG(const LangOptions & LO) const4534f4a2713aSLionel Sambuc void CFG::viewCFG(const LangOptions &LO) const {
4535f4a2713aSLionel Sambuc #ifndef NDEBUG
4536f4a2713aSLionel Sambuc StmtPrinterHelper H(this, LO);
4537f4a2713aSLionel Sambuc GraphHelper = &H;
4538f4a2713aSLionel Sambuc llvm::ViewGraph(this,"CFG");
4539*0a6a1f1dSLionel Sambuc GraphHelper = nullptr;
4540f4a2713aSLionel Sambuc #endif
4541f4a2713aSLionel Sambuc }
4542f4a2713aSLionel Sambuc
4543f4a2713aSLionel Sambuc namespace llvm {
4544f4a2713aSLionel Sambuc template<>
4545f4a2713aSLionel Sambuc struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
4546f4a2713aSLionel Sambuc
DOTGraphTraitsllvm::DOTGraphTraits4547f4a2713aSLionel Sambuc DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
4548f4a2713aSLionel Sambuc
getNodeLabelllvm::DOTGraphTraits4549f4a2713aSLionel Sambuc static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) {
4550f4a2713aSLionel Sambuc
4551f4a2713aSLionel Sambuc #ifndef NDEBUG
4552f4a2713aSLionel Sambuc std::string OutSStr;
4553f4a2713aSLionel Sambuc llvm::raw_string_ostream Out(OutSStr);
4554f4a2713aSLionel Sambuc print_block(Out,Graph, *Node, *GraphHelper, false, false);
4555f4a2713aSLionel Sambuc std::string& OutStr = Out.str();
4556f4a2713aSLionel Sambuc
4557f4a2713aSLionel Sambuc if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
4558f4a2713aSLionel Sambuc
4559f4a2713aSLionel Sambuc // Process string output to make it nicer...
4560f4a2713aSLionel Sambuc for (unsigned i = 0; i != OutStr.length(); ++i)
4561f4a2713aSLionel Sambuc if (OutStr[i] == '\n') { // Left justify
4562f4a2713aSLionel Sambuc OutStr[i] = '\\';
4563f4a2713aSLionel Sambuc OutStr.insert(OutStr.begin()+i+1, 'l');
4564f4a2713aSLionel Sambuc }
4565f4a2713aSLionel Sambuc
4566f4a2713aSLionel Sambuc return OutStr;
4567f4a2713aSLionel Sambuc #else
4568f4a2713aSLionel Sambuc return "";
4569f4a2713aSLionel Sambuc #endif
4570f4a2713aSLionel Sambuc }
4571f4a2713aSLionel Sambuc };
4572f4a2713aSLionel Sambuc } // end namespace llvm
4573