xref: /openbsd-src/gnu/llvm/clang/lib/Analysis/CFG.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- CFG.cpp - Classes for representing and building CFGs ---------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file defines the CFG and CFGBuilder classes for representing and
10e5dd7070Spatrick //  building Control-Flow Graphs (CFGs) from ASTs.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/Analysis/CFG.h"
15e5dd7070Spatrick #include "clang/AST/ASTContext.h"
16e5dd7070Spatrick #include "clang/AST/Attr.h"
17e5dd7070Spatrick #include "clang/AST/Decl.h"
18e5dd7070Spatrick #include "clang/AST/DeclBase.h"
19e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
20e5dd7070Spatrick #include "clang/AST/DeclGroup.h"
21e5dd7070Spatrick #include "clang/AST/Expr.h"
22e5dd7070Spatrick #include "clang/AST/ExprCXX.h"
23e5dd7070Spatrick #include "clang/AST/OperationKinds.h"
24e5dd7070Spatrick #include "clang/AST/PrettyPrinter.h"
25e5dd7070Spatrick #include "clang/AST/Stmt.h"
26e5dd7070Spatrick #include "clang/AST/StmtCXX.h"
27e5dd7070Spatrick #include "clang/AST/StmtObjC.h"
28e5dd7070Spatrick #include "clang/AST/StmtVisitor.h"
29e5dd7070Spatrick #include "clang/AST/Type.h"
30e5dd7070Spatrick #include "clang/Analysis/ConstructionContext.h"
31e5dd7070Spatrick #include "clang/Analysis/Support/BumpVector.h"
32e5dd7070Spatrick #include "clang/Basic/Builtins.h"
33e5dd7070Spatrick #include "clang/Basic/ExceptionSpecificationType.h"
34e5dd7070Spatrick #include "clang/Basic/JsonSupport.h"
35e5dd7070Spatrick #include "clang/Basic/LLVM.h"
36e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
37e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
38e5dd7070Spatrick #include "clang/Basic/Specifiers.h"
39e5dd7070Spatrick #include "llvm/ADT/APInt.h"
40e5dd7070Spatrick #include "llvm/ADT/APSInt.h"
41e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h"
42e5dd7070Spatrick #include "llvm/ADT/DenseMap.h"
43e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
44e5dd7070Spatrick #include "llvm/ADT/SetVector.h"
45e5dd7070Spatrick #include "llvm/ADT/SmallPtrSet.h"
46e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
47e5dd7070Spatrick #include "llvm/Support/Allocator.h"
48e5dd7070Spatrick #include "llvm/Support/Casting.h"
49e5dd7070Spatrick #include "llvm/Support/Compiler.h"
50e5dd7070Spatrick #include "llvm/Support/DOTGraphTraits.h"
51e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
52e5dd7070Spatrick #include "llvm/Support/Format.h"
53e5dd7070Spatrick #include "llvm/Support/GraphWriter.h"
54e5dd7070Spatrick #include "llvm/Support/SaveAndRestore.h"
55e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
56e5dd7070Spatrick #include <cassert>
57e5dd7070Spatrick #include <memory>
58*12c85518Srobert #include <optional>
59e5dd7070Spatrick #include <string>
60e5dd7070Spatrick #include <tuple>
61e5dd7070Spatrick #include <utility>
62e5dd7070Spatrick #include <vector>
63e5dd7070Spatrick 
64e5dd7070Spatrick using namespace clang;
65e5dd7070Spatrick 
GetEndLoc(Decl * D)66e5dd7070Spatrick static SourceLocation GetEndLoc(Decl *D) {
67e5dd7070Spatrick   if (VarDecl *VD = dyn_cast<VarDecl>(D))
68e5dd7070Spatrick     if (Expr *Ex = VD->getInit())
69e5dd7070Spatrick       return Ex->getSourceRange().getEnd();
70e5dd7070Spatrick   return D->getLocation();
71e5dd7070Spatrick }
72e5dd7070Spatrick 
73e5dd7070Spatrick /// Returns true on constant values based around a single IntegerLiteral.
74e5dd7070Spatrick /// Allow for use of parentheses, integer casts, and negative signs.
75*12c85518Srobert /// FIXME: it would be good to unify this function with
76*12c85518Srobert /// getIntegerLiteralSubexpressionValue at some point given the similarity
77*12c85518Srobert /// between the functions.
78*12c85518Srobert 
IsIntegerLiteralConstantExpr(const Expr * E)79e5dd7070Spatrick static bool IsIntegerLiteralConstantExpr(const Expr *E) {
80e5dd7070Spatrick   // Allow parentheses
81e5dd7070Spatrick   E = E->IgnoreParens();
82e5dd7070Spatrick 
83e5dd7070Spatrick   // Allow conversions to different integer kind.
84e5dd7070Spatrick   if (const auto *CE = dyn_cast<CastExpr>(E)) {
85e5dd7070Spatrick     if (CE->getCastKind() != CK_IntegralCast)
86e5dd7070Spatrick       return false;
87e5dd7070Spatrick     E = CE->getSubExpr();
88e5dd7070Spatrick   }
89e5dd7070Spatrick 
90e5dd7070Spatrick   // Allow negative numbers.
91e5dd7070Spatrick   if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
92e5dd7070Spatrick     if (UO->getOpcode() != UO_Minus)
93e5dd7070Spatrick       return false;
94e5dd7070Spatrick     E = UO->getSubExpr();
95e5dd7070Spatrick   }
96e5dd7070Spatrick 
97e5dd7070Spatrick   return isa<IntegerLiteral>(E);
98e5dd7070Spatrick }
99e5dd7070Spatrick 
100e5dd7070Spatrick /// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral
101e5dd7070Spatrick /// constant expression or EnumConstantDecl from the given Expr. If it fails,
102e5dd7070Spatrick /// returns nullptr.
tryTransformToIntOrEnumConstant(const Expr * E)103e5dd7070Spatrick static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {
104e5dd7070Spatrick   E = E->IgnoreParens();
105e5dd7070Spatrick   if (IsIntegerLiteralConstantExpr(E))
106e5dd7070Spatrick     return E;
107e5dd7070Spatrick   if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
108e5dd7070Spatrick     return isa<EnumConstantDecl>(DR->getDecl()) ? DR : nullptr;
109e5dd7070Spatrick   return nullptr;
110e5dd7070Spatrick }
111e5dd7070Spatrick 
112e5dd7070Spatrick /// Tries to interpret a binary operator into `Expr Op NumExpr` form, if
113e5dd7070Spatrick /// NumExpr is an integer literal or an enum constant.
114e5dd7070Spatrick ///
115e5dd7070Spatrick /// If this fails, at least one of the returned DeclRefExpr or Expr will be
116e5dd7070Spatrick /// null.
117e5dd7070Spatrick static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
tryNormalizeBinaryOperator(const BinaryOperator * B)118e5dd7070Spatrick tryNormalizeBinaryOperator(const BinaryOperator *B) {
119e5dd7070Spatrick   BinaryOperatorKind Op = B->getOpcode();
120e5dd7070Spatrick 
121e5dd7070Spatrick   const Expr *MaybeDecl = B->getLHS();
122e5dd7070Spatrick   const Expr *Constant = tryTransformToIntOrEnumConstant(B->getRHS());
123e5dd7070Spatrick   // Expr looked like `0 == Foo` instead of `Foo == 0`
124e5dd7070Spatrick   if (Constant == nullptr) {
125e5dd7070Spatrick     // Flip the operator
126e5dd7070Spatrick     if (Op == BO_GT)
127e5dd7070Spatrick       Op = BO_LT;
128e5dd7070Spatrick     else if (Op == BO_GE)
129e5dd7070Spatrick       Op = BO_LE;
130e5dd7070Spatrick     else if (Op == BO_LT)
131e5dd7070Spatrick       Op = BO_GT;
132e5dd7070Spatrick     else if (Op == BO_LE)
133e5dd7070Spatrick       Op = BO_GE;
134e5dd7070Spatrick 
135e5dd7070Spatrick     MaybeDecl = B->getRHS();
136e5dd7070Spatrick     Constant = tryTransformToIntOrEnumConstant(B->getLHS());
137e5dd7070Spatrick   }
138e5dd7070Spatrick 
139e5dd7070Spatrick   return std::make_tuple(MaybeDecl, Op, Constant);
140e5dd7070Spatrick }
141e5dd7070Spatrick 
142e5dd7070Spatrick /// For an expression `x == Foo && x == Bar`, this determines whether the
143e5dd7070Spatrick /// `Foo` and `Bar` are either of the same enumeration type, or both integer
144e5dd7070Spatrick /// literals.
145e5dd7070Spatrick ///
146e5dd7070Spatrick /// It's an error to pass this arguments that are not either IntegerLiterals
147e5dd7070Spatrick /// or DeclRefExprs (that have decls of type EnumConstantDecl)
areExprTypesCompatible(const Expr * E1,const Expr * E2)148e5dd7070Spatrick static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {
149e5dd7070Spatrick   // User intent isn't clear if they're mixing int literals with enum
150e5dd7070Spatrick   // constants.
151e5dd7070Spatrick   if (isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))
152e5dd7070Spatrick     return false;
153e5dd7070Spatrick 
154e5dd7070Spatrick   // Integer literal comparisons, regardless of literal type, are acceptable.
155e5dd7070Spatrick   if (!isa<DeclRefExpr>(E1))
156e5dd7070Spatrick     return true;
157e5dd7070Spatrick 
158e5dd7070Spatrick   // IntegerLiterals are handled above and only EnumConstantDecls are expected
159e5dd7070Spatrick   // beyond this point
160e5dd7070Spatrick   assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
161e5dd7070Spatrick   auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
162e5dd7070Spatrick   auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
163e5dd7070Spatrick 
164e5dd7070Spatrick   assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
165e5dd7070Spatrick   const DeclContext *DC1 = Decl1->getDeclContext();
166e5dd7070Spatrick   const DeclContext *DC2 = Decl2->getDeclContext();
167e5dd7070Spatrick 
168e5dd7070Spatrick   assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
169e5dd7070Spatrick   return DC1 == DC2;
170e5dd7070Spatrick }
171e5dd7070Spatrick 
172e5dd7070Spatrick namespace {
173e5dd7070Spatrick 
174e5dd7070Spatrick class CFGBuilder;
175e5dd7070Spatrick 
176e5dd7070Spatrick /// The CFG builder uses a recursive algorithm to build the CFG.  When
177e5dd7070Spatrick ///  we process an expression, sometimes we know that we must add the
178e5dd7070Spatrick ///  subexpressions as block-level expressions.  For example:
179e5dd7070Spatrick ///
180e5dd7070Spatrick ///    exp1 || exp2
181e5dd7070Spatrick ///
182e5dd7070Spatrick ///  When processing the '||' expression, we know that exp1 and exp2
183e5dd7070Spatrick ///  need to be added as block-level expressions, even though they
184e5dd7070Spatrick ///  might not normally need to be.  AddStmtChoice records this
185e5dd7070Spatrick ///  contextual information.  If AddStmtChoice is 'NotAlwaysAdd', then
186e5dd7070Spatrick ///  the builder has an option not to add a subexpression as a
187e5dd7070Spatrick ///  block-level expression.
188e5dd7070Spatrick class AddStmtChoice {
189e5dd7070Spatrick public:
190e5dd7070Spatrick   enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
191e5dd7070Spatrick 
AddStmtChoice(Kind a_kind=NotAlwaysAdd)192e5dd7070Spatrick   AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
193e5dd7070Spatrick 
194e5dd7070Spatrick   bool alwaysAdd(CFGBuilder &builder,
195e5dd7070Spatrick                  const Stmt *stmt) const;
196e5dd7070Spatrick 
197e5dd7070Spatrick   /// Return a copy of this object, except with the 'always-add' bit
198e5dd7070Spatrick   ///  set as specified.
withAlwaysAdd(bool alwaysAdd) const199e5dd7070Spatrick   AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {
200e5dd7070Spatrick     return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
201e5dd7070Spatrick   }
202e5dd7070Spatrick 
203e5dd7070Spatrick private:
204e5dd7070Spatrick   Kind kind;
205e5dd7070Spatrick };
206e5dd7070Spatrick 
207e5dd7070Spatrick /// LocalScope - Node in tree of local scopes created for C++ implicit
208e5dd7070Spatrick /// destructor calls generation. It contains list of automatic variables
209e5dd7070Spatrick /// declared in the scope and link to position in previous scope this scope
210e5dd7070Spatrick /// began in.
211e5dd7070Spatrick ///
212e5dd7070Spatrick /// The process of creating local scopes is as follows:
213e5dd7070Spatrick /// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),
214e5dd7070Spatrick /// - Before processing statements in scope (e.g. CompoundStmt) create
215e5dd7070Spatrick ///   LocalScope object using CFGBuilder::ScopePos as link to previous scope
216e5dd7070Spatrick ///   and set CFGBuilder::ScopePos to the end of new scope,
217e5dd7070Spatrick /// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points
218e5dd7070Spatrick ///   at this VarDecl,
219e5dd7070Spatrick /// - For every normal (without jump) end of scope add to CFGBlock destructors
220e5dd7070Spatrick ///   for objects in the current scope,
221e5dd7070Spatrick /// - For every jump add to CFGBlock destructors for objects
222e5dd7070Spatrick ///   between CFGBuilder::ScopePos and local scope position saved for jump
223e5dd7070Spatrick ///   target. Thanks to C++ restrictions on goto jumps we can be sure that
224e5dd7070Spatrick ///   jump target position will be on the path to root from CFGBuilder::ScopePos
225e5dd7070Spatrick ///   (adding any variable that doesn't need constructor to be called to
226e5dd7070Spatrick ///   LocalScope can break this assumption),
227e5dd7070Spatrick ///
228e5dd7070Spatrick class LocalScope {
229e5dd7070Spatrick public:
230e5dd7070Spatrick   using AutomaticVarsTy = BumpVector<VarDecl *>;
231e5dd7070Spatrick 
232e5dd7070Spatrick   /// const_iterator - Iterates local scope backwards and jumps to previous
233e5dd7070Spatrick   /// scope on reaching the beginning of currently iterated scope.
234e5dd7070Spatrick   class const_iterator {
235e5dd7070Spatrick     const LocalScope* Scope = nullptr;
236e5dd7070Spatrick 
237e5dd7070Spatrick     /// VarIter is guaranteed to be greater then 0 for every valid iterator.
238e5dd7070Spatrick     /// Invalid iterator (with null Scope) has VarIter equal to 0.
239e5dd7070Spatrick     unsigned VarIter = 0;
240e5dd7070Spatrick 
241e5dd7070Spatrick   public:
242e5dd7070Spatrick     /// Create invalid iterator. Dereferencing invalid iterator is not allowed.
243e5dd7070Spatrick     /// Incrementing invalid iterator is allowed and will result in invalid
244e5dd7070Spatrick     /// iterator.
245e5dd7070Spatrick     const_iterator() = default;
246e5dd7070Spatrick 
247e5dd7070Spatrick     /// Create valid iterator. In case when S.Prev is an invalid iterator and
248e5dd7070Spatrick     /// I is equal to 0, this will create invalid iterator.
const_iterator(const LocalScope & S,unsigned I)249e5dd7070Spatrick     const_iterator(const LocalScope& S, unsigned I)
250e5dd7070Spatrick         : Scope(&S), VarIter(I) {
251e5dd7070Spatrick       // Iterator to "end" of scope is not allowed. Handle it by going up
252e5dd7070Spatrick       // in scopes tree possibly up to invalid iterator in the root.
253e5dd7070Spatrick       if (VarIter == 0 && Scope)
254e5dd7070Spatrick         *this = Scope->Prev;
255e5dd7070Spatrick     }
256e5dd7070Spatrick 
operator ->() const257e5dd7070Spatrick     VarDecl *const* operator->() const {
258e5dd7070Spatrick       assert(Scope && "Dereferencing invalid iterator is not allowed");
259e5dd7070Spatrick       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
260e5dd7070Spatrick       return &Scope->Vars[VarIter - 1];
261e5dd7070Spatrick     }
262e5dd7070Spatrick 
getFirstVarInScope() const263e5dd7070Spatrick     const VarDecl *getFirstVarInScope() const {
264e5dd7070Spatrick       assert(Scope && "Dereferencing invalid iterator is not allowed");
265e5dd7070Spatrick       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
266e5dd7070Spatrick       return Scope->Vars[0];
267e5dd7070Spatrick     }
268e5dd7070Spatrick 
operator *() const269e5dd7070Spatrick     VarDecl *operator*() const {
270e5dd7070Spatrick       return *this->operator->();
271e5dd7070Spatrick     }
272e5dd7070Spatrick 
operator ++()273e5dd7070Spatrick     const_iterator &operator++() {
274e5dd7070Spatrick       if (!Scope)
275e5dd7070Spatrick         return *this;
276e5dd7070Spatrick 
277e5dd7070Spatrick       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
278e5dd7070Spatrick       --VarIter;
279e5dd7070Spatrick       if (VarIter == 0)
280e5dd7070Spatrick         *this = Scope->Prev;
281e5dd7070Spatrick       return *this;
282e5dd7070Spatrick     }
operator ++(int)283e5dd7070Spatrick     const_iterator operator++(int) {
284e5dd7070Spatrick       const_iterator P = *this;
285e5dd7070Spatrick       ++*this;
286e5dd7070Spatrick       return P;
287e5dd7070Spatrick     }
288e5dd7070Spatrick 
operator ==(const const_iterator & rhs) const289e5dd7070Spatrick     bool operator==(const const_iterator &rhs) const {
290e5dd7070Spatrick       return Scope == rhs.Scope && VarIter == rhs.VarIter;
291e5dd7070Spatrick     }
operator !=(const const_iterator & rhs) const292e5dd7070Spatrick     bool operator!=(const const_iterator &rhs) const {
293e5dd7070Spatrick       return !(*this == rhs);
294e5dd7070Spatrick     }
295e5dd7070Spatrick 
operator bool() const296e5dd7070Spatrick     explicit operator bool() const {
297e5dd7070Spatrick       return *this != const_iterator();
298e5dd7070Spatrick     }
299e5dd7070Spatrick 
300e5dd7070Spatrick     int distance(const_iterator L);
301e5dd7070Spatrick     const_iterator shared_parent(const_iterator L);
pointsToFirstDeclaredVar()302e5dd7070Spatrick     bool pointsToFirstDeclaredVar() { return VarIter == 1; }
303e5dd7070Spatrick   };
304e5dd7070Spatrick 
305e5dd7070Spatrick private:
306e5dd7070Spatrick   BumpVectorContext ctx;
307e5dd7070Spatrick 
308e5dd7070Spatrick   /// Automatic variables in order of declaration.
309e5dd7070Spatrick   AutomaticVarsTy Vars;
310e5dd7070Spatrick 
311e5dd7070Spatrick   /// Iterator to variable in previous scope that was declared just before
312e5dd7070Spatrick   /// begin of this scope.
313e5dd7070Spatrick   const_iterator Prev;
314e5dd7070Spatrick 
315e5dd7070Spatrick public:
316e5dd7070Spatrick   /// Constructs empty scope linked to previous scope in specified place.
LocalScope(BumpVectorContext ctx,const_iterator P)317e5dd7070Spatrick   LocalScope(BumpVectorContext ctx, const_iterator P)
318e5dd7070Spatrick       : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
319e5dd7070Spatrick 
320e5dd7070Spatrick   /// Begin of scope in direction of CFG building (backwards).
begin() const321e5dd7070Spatrick   const_iterator begin() const { return const_iterator(*this, Vars.size()); }
322e5dd7070Spatrick 
addVar(VarDecl * VD)323e5dd7070Spatrick   void addVar(VarDecl *VD) {
324e5dd7070Spatrick     Vars.push_back(VD, ctx);
325e5dd7070Spatrick   }
326e5dd7070Spatrick };
327e5dd7070Spatrick 
328e5dd7070Spatrick } // namespace
329e5dd7070Spatrick 
330e5dd7070Spatrick /// distance - Calculates distance from this to L. L must be reachable from this
331e5dd7070Spatrick /// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.
332e5dd7070Spatrick /// number of scopes between this and L.
distance(LocalScope::const_iterator L)333e5dd7070Spatrick int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
334e5dd7070Spatrick   int D = 0;
335e5dd7070Spatrick   const_iterator F = *this;
336e5dd7070Spatrick   while (F.Scope != L.Scope) {
337e5dd7070Spatrick     assert(F != const_iterator() &&
338e5dd7070Spatrick            "L iterator is not reachable from F iterator.");
339e5dd7070Spatrick     D += F.VarIter;
340e5dd7070Spatrick     F = F.Scope->Prev;
341e5dd7070Spatrick   }
342e5dd7070Spatrick   D += F.VarIter - L.VarIter;
343e5dd7070Spatrick   return D;
344e5dd7070Spatrick }
345e5dd7070Spatrick 
346e5dd7070Spatrick /// Calculates the closest parent of this iterator
347e5dd7070Spatrick /// that is in a scope reachable through the parents of L.
348e5dd7070Spatrick /// I.e. when using 'goto' from this to L, the lifetime of all variables
349e5dd7070Spatrick /// between this and shared_parent(L) end.
350e5dd7070Spatrick LocalScope::const_iterator
shared_parent(LocalScope::const_iterator L)351e5dd7070Spatrick LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
352e5dd7070Spatrick   llvm::SmallPtrSet<const LocalScope *, 4> ScopesOfL;
353e5dd7070Spatrick   while (true) {
354e5dd7070Spatrick     ScopesOfL.insert(L.Scope);
355e5dd7070Spatrick     if (L == const_iterator())
356e5dd7070Spatrick       break;
357e5dd7070Spatrick     L = L.Scope->Prev;
358e5dd7070Spatrick   }
359e5dd7070Spatrick 
360e5dd7070Spatrick   const_iterator F = *this;
361e5dd7070Spatrick   while (true) {
362e5dd7070Spatrick     if (ScopesOfL.count(F.Scope))
363e5dd7070Spatrick       return F;
364e5dd7070Spatrick     assert(F != const_iterator() &&
365e5dd7070Spatrick            "L iterator is not reachable from F iterator.");
366e5dd7070Spatrick     F = F.Scope->Prev;
367e5dd7070Spatrick   }
368e5dd7070Spatrick }
369e5dd7070Spatrick 
370e5dd7070Spatrick namespace {
371e5dd7070Spatrick 
372e5dd7070Spatrick /// Structure for specifying position in CFG during its build process. It
373e5dd7070Spatrick /// consists of CFGBlock that specifies position in CFG and
374e5dd7070Spatrick /// LocalScope::const_iterator that specifies position in LocalScope graph.
375e5dd7070Spatrick struct BlockScopePosPair {
376e5dd7070Spatrick   CFGBlock *block = nullptr;
377e5dd7070Spatrick   LocalScope::const_iterator scopePosition;
378e5dd7070Spatrick 
379e5dd7070Spatrick   BlockScopePosPair() = default;
BlockScopePosPair__anon76ebc3340211::BlockScopePosPair380e5dd7070Spatrick   BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
381e5dd7070Spatrick       : block(b), scopePosition(scopePos) {}
382e5dd7070Spatrick };
383e5dd7070Spatrick 
384e5dd7070Spatrick /// TryResult - a class representing a variant over the values
385e5dd7070Spatrick ///  'true', 'false', or 'unknown'.  This is returned by tryEvaluateBool,
386e5dd7070Spatrick ///  and is used by the CFGBuilder to decide if a branch condition
387e5dd7070Spatrick ///  can be decided up front during CFG construction.
388e5dd7070Spatrick class TryResult {
389e5dd7070Spatrick   int X = -1;
390e5dd7070Spatrick 
391e5dd7070Spatrick public:
392e5dd7070Spatrick   TryResult() = default;
TryResult(bool b)393e5dd7070Spatrick   TryResult(bool b) : X(b ? 1 : 0) {}
394e5dd7070Spatrick 
isTrue() const395e5dd7070Spatrick   bool isTrue() const { return X == 1; }
isFalse() const396e5dd7070Spatrick   bool isFalse() const { return X == 0; }
isKnown() const397e5dd7070Spatrick   bool isKnown() const { return X >= 0; }
398e5dd7070Spatrick 
negate()399e5dd7070Spatrick   void negate() {
400e5dd7070Spatrick     assert(isKnown());
401e5dd7070Spatrick     X ^= 0x1;
402e5dd7070Spatrick   }
403e5dd7070Spatrick };
404e5dd7070Spatrick 
405e5dd7070Spatrick } // namespace
406e5dd7070Spatrick 
bothKnownTrue(TryResult R1,TryResult R2)407e5dd7070Spatrick static TryResult bothKnownTrue(TryResult R1, TryResult R2) {
408e5dd7070Spatrick   if (!R1.isKnown() || !R2.isKnown())
409e5dd7070Spatrick     return TryResult();
410e5dd7070Spatrick   return TryResult(R1.isTrue() && R2.isTrue());
411e5dd7070Spatrick }
412e5dd7070Spatrick 
413e5dd7070Spatrick namespace {
414e5dd7070Spatrick 
415e5dd7070Spatrick class reverse_children {
416e5dd7070Spatrick   llvm::SmallVector<Stmt *, 12> childrenBuf;
417e5dd7070Spatrick   ArrayRef<Stmt *> children;
418e5dd7070Spatrick 
419e5dd7070Spatrick public:
420e5dd7070Spatrick   reverse_children(Stmt *S);
421e5dd7070Spatrick 
422e5dd7070Spatrick   using iterator = ArrayRef<Stmt *>::reverse_iterator;
423e5dd7070Spatrick 
begin() const424e5dd7070Spatrick   iterator begin() const { return children.rbegin(); }
end() const425e5dd7070Spatrick   iterator end() const { return children.rend(); }
426e5dd7070Spatrick };
427e5dd7070Spatrick 
428e5dd7070Spatrick } // namespace
429e5dd7070Spatrick 
reverse_children(Stmt * S)430e5dd7070Spatrick reverse_children::reverse_children(Stmt *S) {
431e5dd7070Spatrick   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
432e5dd7070Spatrick     children = CE->getRawSubExprs();
433e5dd7070Spatrick     return;
434e5dd7070Spatrick   }
435e5dd7070Spatrick   switch (S->getStmtClass()) {
436e5dd7070Spatrick     // Note: Fill in this switch with more cases we want to optimize.
437e5dd7070Spatrick     case Stmt::InitListExprClass: {
438e5dd7070Spatrick       InitListExpr *IE = cast<InitListExpr>(S);
439*12c85518Srobert       children = llvm::ArrayRef(reinterpret_cast<Stmt **>(IE->getInits()),
440e5dd7070Spatrick                                 IE->getNumInits());
441e5dd7070Spatrick       return;
442e5dd7070Spatrick     }
443e5dd7070Spatrick     default:
444e5dd7070Spatrick       break;
445e5dd7070Spatrick   }
446e5dd7070Spatrick 
447e5dd7070Spatrick   // Default case for all other statements.
448*12c85518Srobert   llvm::append_range(childrenBuf, S->children());
449e5dd7070Spatrick 
450e5dd7070Spatrick   // This needs to be done *after* childrenBuf has been populated.
451e5dd7070Spatrick   children = childrenBuf;
452e5dd7070Spatrick }
453e5dd7070Spatrick 
454e5dd7070Spatrick namespace {
455e5dd7070Spatrick 
456e5dd7070Spatrick /// CFGBuilder - This class implements CFG construction from an AST.
457e5dd7070Spatrick ///   The builder is stateful: an instance of the builder should be used to only
458e5dd7070Spatrick ///   construct a single CFG.
459e5dd7070Spatrick ///
460e5dd7070Spatrick ///   Example usage:
461e5dd7070Spatrick ///
462e5dd7070Spatrick ///     CFGBuilder builder;
463e5dd7070Spatrick ///     std::unique_ptr<CFG> cfg = builder.buildCFG(decl, stmt1);
464e5dd7070Spatrick ///
465e5dd7070Spatrick ///  CFG construction is done via a recursive walk of an AST.  We actually parse
466e5dd7070Spatrick ///  the AST in reverse order so that the successor of a basic block is
467e5dd7070Spatrick ///  constructed prior to its predecessor.  This allows us to nicely capture
468e5dd7070Spatrick ///  implicit fall-throughs without extra basic blocks.
469e5dd7070Spatrick class CFGBuilder {
470e5dd7070Spatrick   using JumpTarget = BlockScopePosPair;
471e5dd7070Spatrick   using JumpSource = BlockScopePosPair;
472e5dd7070Spatrick 
473e5dd7070Spatrick   ASTContext *Context;
474e5dd7070Spatrick   std::unique_ptr<CFG> cfg;
475e5dd7070Spatrick 
476e5dd7070Spatrick   // Current block.
477e5dd7070Spatrick   CFGBlock *Block = nullptr;
478e5dd7070Spatrick 
479e5dd7070Spatrick   // Block after the current block.
480e5dd7070Spatrick   CFGBlock *Succ = nullptr;
481e5dd7070Spatrick 
482e5dd7070Spatrick   JumpTarget ContinueJumpTarget;
483e5dd7070Spatrick   JumpTarget BreakJumpTarget;
484e5dd7070Spatrick   JumpTarget SEHLeaveJumpTarget;
485e5dd7070Spatrick   CFGBlock *SwitchTerminatedBlock = nullptr;
486e5dd7070Spatrick   CFGBlock *DefaultCaseBlock = nullptr;
487e5dd7070Spatrick 
488*12c85518Srobert   // This can point to either a C++ try, an Objective-C @try, or an SEH __try.
489*12c85518Srobert   // try and @try can be mixed and generally work the same.
490*12c85518Srobert   // The frontend forbids mixing SEH __try with either try or @try.
491*12c85518Srobert   // So having one for all three is enough.
492e5dd7070Spatrick   CFGBlock *TryTerminatedBlock = nullptr;
493e5dd7070Spatrick 
494e5dd7070Spatrick   // Current position in local scope.
495e5dd7070Spatrick   LocalScope::const_iterator ScopePos;
496e5dd7070Spatrick 
497e5dd7070Spatrick   // LabelMap records the mapping from Label expressions to their jump targets.
498e5dd7070Spatrick   using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
499e5dd7070Spatrick   LabelMapTy LabelMap;
500e5dd7070Spatrick 
501e5dd7070Spatrick   // A list of blocks that end with a "goto" that must be backpatched to their
502e5dd7070Spatrick   // resolved targets upon completion of CFG construction.
503e5dd7070Spatrick   using BackpatchBlocksTy = std::vector<JumpSource>;
504e5dd7070Spatrick   BackpatchBlocksTy BackpatchBlocks;
505e5dd7070Spatrick 
506e5dd7070Spatrick   // A list of labels whose address has been taken (for indirect gotos).
507e5dd7070Spatrick   using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
508e5dd7070Spatrick   LabelSetTy AddressTakenLabels;
509e5dd7070Spatrick 
510e5dd7070Spatrick   // Information about the currently visited C++ object construction site.
511e5dd7070Spatrick   // This is set in the construction trigger and read when the constructor
512e5dd7070Spatrick   // or a function that returns an object by value is being visited.
513e5dd7070Spatrick   llvm::DenseMap<Expr *, const ConstructionContextLayer *>
514e5dd7070Spatrick       ConstructionContextMap;
515e5dd7070Spatrick 
516e5dd7070Spatrick   using DeclsWithEndedScopeSetTy = llvm::SmallSetVector<VarDecl *, 16>;
517e5dd7070Spatrick   DeclsWithEndedScopeSetTy DeclsWithEndedScope;
518e5dd7070Spatrick 
519e5dd7070Spatrick   bool badCFG = false;
520e5dd7070Spatrick   const CFG::BuildOptions &BuildOpts;
521e5dd7070Spatrick 
522e5dd7070Spatrick   // State to track for building switch statements.
523e5dd7070Spatrick   bool switchExclusivelyCovered = false;
524e5dd7070Spatrick   Expr::EvalResult *switchCond = nullptr;
525e5dd7070Spatrick 
526e5dd7070Spatrick   CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;
527e5dd7070Spatrick   const Stmt *lastLookup = nullptr;
528e5dd7070Spatrick 
529e5dd7070Spatrick   // Caches boolean evaluations of expressions to avoid multiple re-evaluations
530e5dd7070Spatrick   // during construction of branches for chained logical operators.
531e5dd7070Spatrick   using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
532e5dd7070Spatrick   CachedBoolEvalsTy CachedBoolEvals;
533e5dd7070Spatrick 
534e5dd7070Spatrick public:
CFGBuilder(ASTContext * astContext,const CFG::BuildOptions & buildOpts)535e5dd7070Spatrick   explicit CFGBuilder(ASTContext *astContext,
536e5dd7070Spatrick                       const CFG::BuildOptions &buildOpts)
537*12c85518Srobert       : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}
538e5dd7070Spatrick 
539e5dd7070Spatrick   // buildCFG - Used by external clients to construct the CFG.
540e5dd7070Spatrick   std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);
541e5dd7070Spatrick 
542e5dd7070Spatrick   bool alwaysAdd(const Stmt *stmt);
543e5dd7070Spatrick 
544e5dd7070Spatrick private:
545e5dd7070Spatrick   // Visitors to walk an AST and construct the CFG.
546e5dd7070Spatrick   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
547e5dd7070Spatrick   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
548*12c85518Srobert   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
549e5dd7070Spatrick   CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
550e5dd7070Spatrick   CFGBlock *VisitBreakStmt(BreakStmt *B);
551e5dd7070Spatrick   CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
552e5dd7070Spatrick   CFGBlock *VisitCaseStmt(CaseStmt *C);
553e5dd7070Spatrick   CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
554e5dd7070Spatrick   CFGBlock *VisitCompoundStmt(CompoundStmt *C, bool ExternallyDestructed);
555e5dd7070Spatrick   CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,
556e5dd7070Spatrick                                      AddStmtChoice asc);
557e5dd7070Spatrick   CFGBlock *VisitContinueStmt(ContinueStmt *C);
558e5dd7070Spatrick   CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
559e5dd7070Spatrick                                       AddStmtChoice asc);
560e5dd7070Spatrick   CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
561e5dd7070Spatrick   CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
562e5dd7070Spatrick   CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
563e5dd7070Spatrick   CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
564e5dd7070Spatrick   CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
565e5dd7070Spatrick   CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
566e5dd7070Spatrick                                        AddStmtChoice asc);
567e5dd7070Spatrick   CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
568e5dd7070Spatrick                                         AddStmtChoice asc);
569e5dd7070Spatrick   CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
570e5dd7070Spatrick   CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
571*12c85518Srobert   CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);
572e5dd7070Spatrick   CFGBlock *VisitDeclStmt(DeclStmt *DS);
573e5dd7070Spatrick   CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
574e5dd7070Spatrick   CFGBlock *VisitDefaultStmt(DefaultStmt *D);
575e5dd7070Spatrick   CFGBlock *VisitDoStmt(DoStmt *D);
576e5dd7070Spatrick   CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
577e5dd7070Spatrick                                   AddStmtChoice asc, bool ExternallyDestructed);
578e5dd7070Spatrick   CFGBlock *VisitForStmt(ForStmt *F);
579e5dd7070Spatrick   CFGBlock *VisitGotoStmt(GotoStmt *G);
580e5dd7070Spatrick   CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);
581e5dd7070Spatrick   CFGBlock *VisitIfStmt(IfStmt *I);
582e5dd7070Spatrick   CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
583e5dd7070Spatrick   CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
584e5dd7070Spatrick   CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
585e5dd7070Spatrick   CFGBlock *VisitLabelStmt(LabelStmt *L);
586e5dd7070Spatrick   CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
587e5dd7070Spatrick   CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
588e5dd7070Spatrick   CFGBlock *VisitLogicalOperator(BinaryOperator *B);
589e5dd7070Spatrick   std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
590e5dd7070Spatrick                                                          Stmt *Term,
591e5dd7070Spatrick                                                          CFGBlock *TrueBlock,
592e5dd7070Spatrick                                                          CFGBlock *FalseBlock);
593e5dd7070Spatrick   CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
594e5dd7070Spatrick                                           AddStmtChoice asc);
595e5dd7070Spatrick   CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
596e5dd7070Spatrick   CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
597e5dd7070Spatrick   CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
598e5dd7070Spatrick   CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
599e5dd7070Spatrick   CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
600e5dd7070Spatrick   CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
601e5dd7070Spatrick   CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
602e5dd7070Spatrick   CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
603e5dd7070Spatrick   CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
604e5dd7070Spatrick   CFGBlock *VisitReturnStmt(Stmt *S);
605*12c85518Srobert   CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
606*12c85518Srobert                                       AddStmtChoice asc);
607e5dd7070Spatrick   CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
608e5dd7070Spatrick   CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
609e5dd7070Spatrick   CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
610e5dd7070Spatrick   CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
611e5dd7070Spatrick   CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
612e5dd7070Spatrick   CFGBlock *VisitSwitchStmt(SwitchStmt *S);
613e5dd7070Spatrick   CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
614e5dd7070Spatrick                                           AddStmtChoice asc);
615e5dd7070Spatrick   CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
616e5dd7070Spatrick   CFGBlock *VisitWhileStmt(WhileStmt *W);
617*12c85518Srobert   CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);
618e5dd7070Spatrick 
619e5dd7070Spatrick   CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
620e5dd7070Spatrick                   bool ExternallyDestructed = false);
621e5dd7070Spatrick   CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
622e5dd7070Spatrick   CFGBlock *VisitChildren(Stmt *S);
623e5dd7070Spatrick   CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
624e5dd7070Spatrick   CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,
625e5dd7070Spatrick                                         AddStmtChoice asc);
626e5dd7070Spatrick 
maybeAddScopeBeginForVarDecl(CFGBlock * B,const VarDecl * VD,const Stmt * S)627e5dd7070Spatrick   void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,
628e5dd7070Spatrick                                     const Stmt *S) {
629e5dd7070Spatrick     if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
630e5dd7070Spatrick       appendScopeBegin(B, VD, S);
631e5dd7070Spatrick   }
632e5dd7070Spatrick 
633e5dd7070Spatrick   /// When creating the CFG for temporary destructors, we want to mirror the
634e5dd7070Spatrick   /// branch structure of the corresponding constructor calls.
635e5dd7070Spatrick   /// Thus, while visiting a statement for temporary destructors, we keep a
636e5dd7070Spatrick   /// context to keep track of the following information:
637e5dd7070Spatrick   /// - whether a subexpression is executed unconditionally
638e5dd7070Spatrick   /// - if a subexpression is executed conditionally, the first
639e5dd7070Spatrick   ///   CXXBindTemporaryExpr we encounter in that subexpression (which
640e5dd7070Spatrick   ///   corresponds to the last temporary destructor we have to call for this
641e5dd7070Spatrick   ///   subexpression) and the CFG block at that point (which will become the
642e5dd7070Spatrick   ///   successor block when inserting the decision point).
643e5dd7070Spatrick   ///
644e5dd7070Spatrick   /// That way, we can build the branch structure for temporary destructors as
645e5dd7070Spatrick   /// follows:
646e5dd7070Spatrick   /// 1. If a subexpression is executed unconditionally, we add the temporary
647e5dd7070Spatrick   ///    destructor calls to the current block.
648e5dd7070Spatrick   /// 2. If a subexpression is executed conditionally, when we encounter a
649e5dd7070Spatrick   ///    CXXBindTemporaryExpr:
650e5dd7070Spatrick   ///    a) If it is the first temporary destructor call in the subexpression,
651e5dd7070Spatrick   ///       we remember the CXXBindTemporaryExpr and the current block in the
652e5dd7070Spatrick   ///       TempDtorContext; we start a new block, and insert the temporary
653e5dd7070Spatrick   ///       destructor call.
654e5dd7070Spatrick   ///    b) Otherwise, add the temporary destructor call to the current block.
655e5dd7070Spatrick   ///  3. When we finished visiting a conditionally executed subexpression,
656e5dd7070Spatrick   ///     and we found at least one temporary constructor during the visitation
657e5dd7070Spatrick   ///     (2.a has executed), we insert a decision block that uses the
658e5dd7070Spatrick   ///     CXXBindTemporaryExpr as terminator, and branches to the current block
659e5dd7070Spatrick   ///     if the CXXBindTemporaryExpr was marked executed, and otherwise
660e5dd7070Spatrick   ///     branches to the stored successor.
661e5dd7070Spatrick   struct TempDtorContext {
662e5dd7070Spatrick     TempDtorContext() = default;
TempDtorContext__anon76ebc3340411::CFGBuilder::TempDtorContext663e5dd7070Spatrick     TempDtorContext(TryResult KnownExecuted)
664e5dd7070Spatrick         : IsConditional(true), KnownExecuted(KnownExecuted) {}
665e5dd7070Spatrick 
666e5dd7070Spatrick     /// Returns whether we need to start a new branch for a temporary destructor
667e5dd7070Spatrick     /// call. This is the case when the temporary destructor is
668e5dd7070Spatrick     /// conditionally executed, and it is the first one we encounter while
669e5dd7070Spatrick     /// visiting a subexpression - other temporary destructors at the same level
670e5dd7070Spatrick     /// will be added to the same block and are executed under the same
671e5dd7070Spatrick     /// condition.
needsTempDtorBranch__anon76ebc3340411::CFGBuilder::TempDtorContext672e5dd7070Spatrick     bool needsTempDtorBranch() const {
673e5dd7070Spatrick       return IsConditional && !TerminatorExpr;
674e5dd7070Spatrick     }
675e5dd7070Spatrick 
676e5dd7070Spatrick     /// Remember the successor S of a temporary destructor decision branch for
677e5dd7070Spatrick     /// the corresponding CXXBindTemporaryExpr E.
setDecisionPoint__anon76ebc3340411::CFGBuilder::TempDtorContext678e5dd7070Spatrick     void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
679e5dd7070Spatrick       Succ = S;
680e5dd7070Spatrick       TerminatorExpr = E;
681e5dd7070Spatrick     }
682e5dd7070Spatrick 
683e5dd7070Spatrick     const bool IsConditional = false;
684e5dd7070Spatrick     const TryResult KnownExecuted = true;
685e5dd7070Spatrick     CFGBlock *Succ = nullptr;
686e5dd7070Spatrick     CXXBindTemporaryExpr *TerminatorExpr = nullptr;
687e5dd7070Spatrick   };
688e5dd7070Spatrick 
689e5dd7070Spatrick   // Visitors to walk an AST and generate destructors of temporaries in
690e5dd7070Spatrick   // full expression.
691e5dd7070Spatrick   CFGBlock *VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
692e5dd7070Spatrick                                    TempDtorContext &Context);
693e5dd7070Spatrick   CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E,  bool ExternallyDestructed,
694e5dd7070Spatrick                                            TempDtorContext &Context);
695e5dd7070Spatrick   CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,
696e5dd7070Spatrick                                                  bool ExternallyDestructed,
697e5dd7070Spatrick                                                  TempDtorContext &Context);
698e5dd7070Spatrick   CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
699e5dd7070Spatrick       CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context);
700e5dd7070Spatrick   CFGBlock *VisitConditionalOperatorForTemporaryDtors(
701e5dd7070Spatrick       AbstractConditionalOperator *E, bool ExternallyDestructed,
702e5dd7070Spatrick       TempDtorContext &Context);
703e5dd7070Spatrick   void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
704e5dd7070Spatrick                                    CFGBlock *FalseSucc = nullptr);
705e5dd7070Spatrick 
706e5dd7070Spatrick   // NYS == Not Yet Supported
NYS()707e5dd7070Spatrick   CFGBlock *NYS() {
708e5dd7070Spatrick     badCFG = true;
709e5dd7070Spatrick     return Block;
710e5dd7070Spatrick   }
711e5dd7070Spatrick 
712e5dd7070Spatrick   // Remember to apply the construction context based on the current \p Layer
713e5dd7070Spatrick   // when constructing the CFG element for \p CE.
714e5dd7070Spatrick   void consumeConstructionContext(const ConstructionContextLayer *Layer,
715e5dd7070Spatrick                                   Expr *E);
716e5dd7070Spatrick 
717e5dd7070Spatrick   // Scan \p Child statement to find constructors in it, while keeping in mind
718e5dd7070Spatrick   // that its parent statement is providing a partial construction context
719e5dd7070Spatrick   // described by \p Layer. If a constructor is found, it would be assigned
720e5dd7070Spatrick   // the context based on the layer. If an additional construction context layer
721e5dd7070Spatrick   // is found, the function recurses into that.
722e5dd7070Spatrick   void findConstructionContexts(const ConstructionContextLayer *Layer,
723e5dd7070Spatrick                                 Stmt *Child);
724e5dd7070Spatrick 
725e5dd7070Spatrick   // Scan all arguments of a call expression for a construction context.
726e5dd7070Spatrick   // These sorts of call expressions don't have a common superclass,
727e5dd7070Spatrick   // hence strict duck-typing.
728e5dd7070Spatrick   template <typename CallLikeExpr,
729ec727ea7Spatrick             typename = std::enable_if_t<
730*12c85518Srobert                 std::is_base_of_v<CallExpr, CallLikeExpr> ||
731*12c85518Srobert                 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
732*12c85518Srobert                 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
findConstructionContextsForArguments(CallLikeExpr * E)733e5dd7070Spatrick   void findConstructionContextsForArguments(CallLikeExpr *E) {
734e5dd7070Spatrick     for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
735e5dd7070Spatrick       Expr *Arg = E->getArg(i);
736e5dd7070Spatrick       if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue())
737e5dd7070Spatrick         findConstructionContexts(
738e5dd7070Spatrick             ConstructionContextLayer::create(cfg->getBumpVectorContext(),
739e5dd7070Spatrick                                              ConstructionContextItem(E, i)),
740e5dd7070Spatrick             Arg);
741e5dd7070Spatrick     }
742e5dd7070Spatrick   }
743e5dd7070Spatrick 
744e5dd7070Spatrick   // Unset the construction context after consuming it. This is done immediately
745e5dd7070Spatrick   // after adding the CFGConstructor or CFGCXXRecordTypedCall element, so
746e5dd7070Spatrick   // there's no need to do this manually in every Visit... function.
747e5dd7070Spatrick   void cleanupConstructionContext(Expr *E);
748e5dd7070Spatrick 
autoCreateBlock()749e5dd7070Spatrick   void autoCreateBlock() { if (!Block) Block = createBlock(); }
750e5dd7070Spatrick   CFGBlock *createBlock(bool add_successor = true);
751e5dd7070Spatrick   CFGBlock *createNoReturnBlock();
752e5dd7070Spatrick 
addStmt(Stmt * S)753e5dd7070Spatrick   CFGBlock *addStmt(Stmt *S) {
754e5dd7070Spatrick     return Visit(S, AddStmtChoice::AlwaysAdd);
755e5dd7070Spatrick   }
756e5dd7070Spatrick 
757e5dd7070Spatrick   CFGBlock *addInitializer(CXXCtorInitializer *I);
758e5dd7070Spatrick   void addLoopExit(const Stmt *LoopStmt);
759e5dd7070Spatrick   void addAutomaticObjDtors(LocalScope::const_iterator B,
760e5dd7070Spatrick                             LocalScope::const_iterator E, Stmt *S);
761e5dd7070Spatrick   void addLifetimeEnds(LocalScope::const_iterator B,
762e5dd7070Spatrick                        LocalScope::const_iterator E, Stmt *S);
763e5dd7070Spatrick   void addAutomaticObjHandling(LocalScope::const_iterator B,
764e5dd7070Spatrick                                LocalScope::const_iterator E, Stmt *S);
765e5dd7070Spatrick   void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
766e5dd7070Spatrick   void addScopesEnd(LocalScope::const_iterator B, LocalScope::const_iterator E,
767e5dd7070Spatrick                     Stmt *S);
768e5dd7070Spatrick 
769e5dd7070Spatrick   void getDeclsWithEndedScope(LocalScope::const_iterator B,
770e5dd7070Spatrick                               LocalScope::const_iterator E, Stmt *S);
771e5dd7070Spatrick 
772e5dd7070Spatrick   // Local scopes creation.
773e5dd7070Spatrick   LocalScope* createOrReuseLocalScope(LocalScope* Scope);
774e5dd7070Spatrick 
775e5dd7070Spatrick   void addLocalScopeForStmt(Stmt *S);
776e5dd7070Spatrick   LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
777e5dd7070Spatrick                                        LocalScope* Scope = nullptr);
778e5dd7070Spatrick   LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
779e5dd7070Spatrick 
780e5dd7070Spatrick   void addLocalScopeAndDtors(Stmt *S);
781e5dd7070Spatrick 
retrieveAndCleanupConstructionContext(Expr * E)782e5dd7070Spatrick   const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
783e5dd7070Spatrick     if (!BuildOpts.AddRichCXXConstructors)
784e5dd7070Spatrick       return nullptr;
785e5dd7070Spatrick 
786e5dd7070Spatrick     const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
787e5dd7070Spatrick     if (!Layer)
788e5dd7070Spatrick       return nullptr;
789e5dd7070Spatrick 
790e5dd7070Spatrick     cleanupConstructionContext(E);
791e5dd7070Spatrick     return ConstructionContext::createFromLayers(cfg->getBumpVectorContext(),
792e5dd7070Spatrick                                                  Layer);
793e5dd7070Spatrick   }
794e5dd7070Spatrick 
795e5dd7070Spatrick   // Interface to CFGBlock - adding CFGElements.
796e5dd7070Spatrick 
appendStmt(CFGBlock * B,const Stmt * S)797e5dd7070Spatrick   void appendStmt(CFGBlock *B, const Stmt *S) {
798e5dd7070Spatrick     if (alwaysAdd(S) && cachedEntry)
799e5dd7070Spatrick       cachedEntry->second = B;
800e5dd7070Spatrick 
801e5dd7070Spatrick     // All block-level expressions should have already been IgnoreParens()ed.
802e5dd7070Spatrick     assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
803e5dd7070Spatrick     B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
804e5dd7070Spatrick   }
805e5dd7070Spatrick 
appendConstructor(CFGBlock * B,CXXConstructExpr * CE)806e5dd7070Spatrick   void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
807e5dd7070Spatrick     if (const ConstructionContext *CC =
808e5dd7070Spatrick             retrieveAndCleanupConstructionContext(CE)) {
809e5dd7070Spatrick       B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
810e5dd7070Spatrick       return;
811e5dd7070Spatrick     }
812e5dd7070Spatrick 
813e5dd7070Spatrick     // No valid construction context found. Fall back to statement.
814e5dd7070Spatrick     B->appendStmt(CE, cfg->getBumpVectorContext());
815e5dd7070Spatrick   }
816e5dd7070Spatrick 
appendCall(CFGBlock * B,CallExpr * CE)817e5dd7070Spatrick   void appendCall(CFGBlock *B, CallExpr *CE) {
818e5dd7070Spatrick     if (alwaysAdd(CE) && cachedEntry)
819e5dd7070Spatrick       cachedEntry->second = B;
820e5dd7070Spatrick 
821e5dd7070Spatrick     if (const ConstructionContext *CC =
822e5dd7070Spatrick             retrieveAndCleanupConstructionContext(CE)) {
823e5dd7070Spatrick       B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext());
824e5dd7070Spatrick       return;
825e5dd7070Spatrick     }
826e5dd7070Spatrick 
827e5dd7070Spatrick     // No valid construction context found. Fall back to statement.
828e5dd7070Spatrick     B->appendStmt(CE, cfg->getBumpVectorContext());
829e5dd7070Spatrick   }
830e5dd7070Spatrick 
appendInitializer(CFGBlock * B,CXXCtorInitializer * I)831e5dd7070Spatrick   void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
832e5dd7070Spatrick     B->appendInitializer(I, cfg->getBumpVectorContext());
833e5dd7070Spatrick   }
834e5dd7070Spatrick 
appendNewAllocator(CFGBlock * B,CXXNewExpr * NE)835e5dd7070Spatrick   void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
836e5dd7070Spatrick     B->appendNewAllocator(NE, cfg->getBumpVectorContext());
837e5dd7070Spatrick   }
838e5dd7070Spatrick 
appendBaseDtor(CFGBlock * B,const CXXBaseSpecifier * BS)839e5dd7070Spatrick   void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
840e5dd7070Spatrick     B->appendBaseDtor(BS, cfg->getBumpVectorContext());
841e5dd7070Spatrick   }
842e5dd7070Spatrick 
appendMemberDtor(CFGBlock * B,FieldDecl * FD)843e5dd7070Spatrick   void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
844e5dd7070Spatrick     B->appendMemberDtor(FD, cfg->getBumpVectorContext());
845e5dd7070Spatrick   }
846e5dd7070Spatrick 
appendObjCMessage(CFGBlock * B,ObjCMessageExpr * ME)847e5dd7070Spatrick   void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
848e5dd7070Spatrick     if (alwaysAdd(ME) && cachedEntry)
849e5dd7070Spatrick       cachedEntry->second = B;
850e5dd7070Spatrick 
851e5dd7070Spatrick     if (const ConstructionContext *CC =
852e5dd7070Spatrick             retrieveAndCleanupConstructionContext(ME)) {
853e5dd7070Spatrick       B->appendCXXRecordTypedCall(ME, CC, cfg->getBumpVectorContext());
854e5dd7070Spatrick       return;
855e5dd7070Spatrick     }
856e5dd7070Spatrick 
857e5dd7070Spatrick     B->appendStmt(const_cast<ObjCMessageExpr *>(ME),
858e5dd7070Spatrick                   cfg->getBumpVectorContext());
859e5dd7070Spatrick   }
860e5dd7070Spatrick 
appendTemporaryDtor(CFGBlock * B,CXXBindTemporaryExpr * E)861e5dd7070Spatrick   void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
862e5dd7070Spatrick     B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
863e5dd7070Spatrick   }
864e5dd7070Spatrick 
appendAutomaticObjDtor(CFGBlock * B,VarDecl * VD,Stmt * S)865e5dd7070Spatrick   void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
866e5dd7070Spatrick     B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
867e5dd7070Spatrick   }
868e5dd7070Spatrick 
appendLifetimeEnds(CFGBlock * B,VarDecl * VD,Stmt * S)869e5dd7070Spatrick   void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
870e5dd7070Spatrick     B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());
871e5dd7070Spatrick   }
872e5dd7070Spatrick 
appendLoopExit(CFGBlock * B,const Stmt * LoopStmt)873e5dd7070Spatrick   void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {
874e5dd7070Spatrick     B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());
875e5dd7070Spatrick   }
876e5dd7070Spatrick 
appendDeleteDtor(CFGBlock * B,CXXRecordDecl * RD,CXXDeleteExpr * DE)877e5dd7070Spatrick   void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
878e5dd7070Spatrick     B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
879e5dd7070Spatrick   }
880e5dd7070Spatrick 
881e5dd7070Spatrick   void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
882e5dd7070Spatrick       LocalScope::const_iterator B, LocalScope::const_iterator E);
883e5dd7070Spatrick 
884e5dd7070Spatrick   void prependAutomaticObjLifetimeWithTerminator(CFGBlock *Blk,
885e5dd7070Spatrick                                                  LocalScope::const_iterator B,
886e5dd7070Spatrick                                                  LocalScope::const_iterator E);
887e5dd7070Spatrick 
888e5dd7070Spatrick   const VarDecl *
889e5dd7070Spatrick   prependAutomaticObjScopeEndWithTerminator(CFGBlock *Blk,
890e5dd7070Spatrick                                             LocalScope::const_iterator B,
891e5dd7070Spatrick                                             LocalScope::const_iterator E);
892e5dd7070Spatrick 
addSuccessor(CFGBlock * B,CFGBlock * S,bool IsReachable=true)893e5dd7070Spatrick   void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
894e5dd7070Spatrick     B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
895e5dd7070Spatrick                     cfg->getBumpVectorContext());
896e5dd7070Spatrick   }
897e5dd7070Spatrick 
898e5dd7070Spatrick   /// Add a reachable successor to a block, with the alternate variant that is
899e5dd7070Spatrick   /// unreachable.
addSuccessor(CFGBlock * B,CFGBlock * ReachableBlock,CFGBlock * AltBlock)900e5dd7070Spatrick   void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
901e5dd7070Spatrick     B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
902e5dd7070Spatrick                     cfg->getBumpVectorContext());
903e5dd7070Spatrick   }
904e5dd7070Spatrick 
appendScopeBegin(CFGBlock * B,const VarDecl * VD,const Stmt * S)905e5dd7070Spatrick   void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
906e5dd7070Spatrick     if (BuildOpts.AddScopes)
907e5dd7070Spatrick       B->appendScopeBegin(VD, S, cfg->getBumpVectorContext());
908e5dd7070Spatrick   }
909e5dd7070Spatrick 
prependScopeBegin(CFGBlock * B,const VarDecl * VD,const Stmt * S)910e5dd7070Spatrick   void prependScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
911e5dd7070Spatrick     if (BuildOpts.AddScopes)
912e5dd7070Spatrick       B->prependScopeBegin(VD, S, cfg->getBumpVectorContext());
913e5dd7070Spatrick   }
914e5dd7070Spatrick 
appendScopeEnd(CFGBlock * B,const VarDecl * VD,const Stmt * S)915e5dd7070Spatrick   void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
916e5dd7070Spatrick     if (BuildOpts.AddScopes)
917e5dd7070Spatrick       B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());
918e5dd7070Spatrick   }
919e5dd7070Spatrick 
prependScopeEnd(CFGBlock * B,const VarDecl * VD,const Stmt * S)920e5dd7070Spatrick   void prependScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
921e5dd7070Spatrick     if (BuildOpts.AddScopes)
922e5dd7070Spatrick       B->prependScopeEnd(VD, S, cfg->getBumpVectorContext());
923e5dd7070Spatrick   }
924e5dd7070Spatrick 
925e5dd7070Spatrick   /// Find a relational comparison with an expression evaluating to a
926e5dd7070Spatrick   /// boolean and a constant other than 0 and 1.
927e5dd7070Spatrick   /// e.g. if ((x < y) == 10)
checkIncorrectRelationalOperator(const BinaryOperator * B)928e5dd7070Spatrick   TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
929e5dd7070Spatrick     const Expr *LHSExpr = B->getLHS()->IgnoreParens();
930e5dd7070Spatrick     const Expr *RHSExpr = B->getRHS()->IgnoreParens();
931e5dd7070Spatrick 
932e5dd7070Spatrick     const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
933e5dd7070Spatrick     const Expr *BoolExpr = RHSExpr;
934e5dd7070Spatrick     bool IntFirst = true;
935e5dd7070Spatrick     if (!IntLiteral) {
936e5dd7070Spatrick       IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
937e5dd7070Spatrick       BoolExpr = LHSExpr;
938e5dd7070Spatrick       IntFirst = false;
939e5dd7070Spatrick     }
940e5dd7070Spatrick 
941e5dd7070Spatrick     if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue())
942e5dd7070Spatrick       return TryResult();
943e5dd7070Spatrick 
944e5dd7070Spatrick     llvm::APInt IntValue = IntLiteral->getValue();
945e5dd7070Spatrick     if ((IntValue == 1) || (IntValue == 0))
946e5dd7070Spatrick       return TryResult();
947e5dd7070Spatrick 
948e5dd7070Spatrick     bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() ||
949e5dd7070Spatrick                      !IntValue.isNegative();
950e5dd7070Spatrick 
951e5dd7070Spatrick     BinaryOperatorKind Bok = B->getOpcode();
952e5dd7070Spatrick     if (Bok == BO_GT || Bok == BO_GE) {
953e5dd7070Spatrick       // Always true for 10 > bool and bool > -1
954e5dd7070Spatrick       // Always false for -1 > bool and bool > 10
955e5dd7070Spatrick       return TryResult(IntFirst == IntLarger);
956e5dd7070Spatrick     } else {
957e5dd7070Spatrick       // Always true for -1 < bool and bool < 10
958e5dd7070Spatrick       // Always false for 10 < bool and bool < -1
959e5dd7070Spatrick       return TryResult(IntFirst != IntLarger);
960e5dd7070Spatrick     }
961e5dd7070Spatrick   }
962e5dd7070Spatrick 
963e5dd7070Spatrick   /// Find an incorrect equality comparison. Either with an expression
964e5dd7070Spatrick   /// evaluating to a boolean and a constant other than 0 and 1.
965e5dd7070Spatrick   /// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to
966e5dd7070Spatrick   /// true/false e.q. (x & 8) == 4.
checkIncorrectEqualityOperator(const BinaryOperator * B)967e5dd7070Spatrick   TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {
968e5dd7070Spatrick     const Expr *LHSExpr = B->getLHS()->IgnoreParens();
969e5dd7070Spatrick     const Expr *RHSExpr = B->getRHS()->IgnoreParens();
970e5dd7070Spatrick 
971*12c85518Srobert     std::optional<llvm::APInt> IntLiteral1 =
972*12c85518Srobert         getIntegerLiteralSubexpressionValue(LHSExpr);
973e5dd7070Spatrick     const Expr *BoolExpr = RHSExpr;
974e5dd7070Spatrick 
975*12c85518Srobert     if (!IntLiteral1) {
976*12c85518Srobert       IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
977e5dd7070Spatrick       BoolExpr = LHSExpr;
978e5dd7070Spatrick     }
979e5dd7070Spatrick 
980*12c85518Srobert     if (!IntLiteral1)
981e5dd7070Spatrick       return TryResult();
982e5dd7070Spatrick 
983e5dd7070Spatrick     const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
984e5dd7070Spatrick     if (BitOp && (BitOp->getOpcode() == BO_And ||
985e5dd7070Spatrick                   BitOp->getOpcode() == BO_Or)) {
986e5dd7070Spatrick       const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens();
987e5dd7070Spatrick       const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens();
988e5dd7070Spatrick 
989*12c85518Srobert       std::optional<llvm::APInt> IntLiteral2 =
990*12c85518Srobert           getIntegerLiteralSubexpressionValue(LHSExpr2);
991e5dd7070Spatrick 
992e5dd7070Spatrick       if (!IntLiteral2)
993*12c85518Srobert         IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
994e5dd7070Spatrick 
995e5dd7070Spatrick       if (!IntLiteral2)
996e5dd7070Spatrick         return TryResult();
997e5dd7070Spatrick 
998*12c85518Srobert       if ((BitOp->getOpcode() == BO_And &&
999*12c85518Srobert            (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
1000*12c85518Srobert           (BitOp->getOpcode() == BO_Or &&
1001*12c85518Srobert            (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
1002e5dd7070Spatrick         if (BuildOpts.Observer)
1003e5dd7070Spatrick           BuildOpts.Observer->compareBitwiseEquality(B,
1004e5dd7070Spatrick                                                      B->getOpcode() != BO_EQ);
1005*12c85518Srobert         return TryResult(B->getOpcode() != BO_EQ);
1006e5dd7070Spatrick       }
1007e5dd7070Spatrick     } else if (BoolExpr->isKnownToHaveBooleanValue()) {
1008*12c85518Srobert       if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
1009e5dd7070Spatrick         return TryResult();
1010e5dd7070Spatrick       }
1011e5dd7070Spatrick       return TryResult(B->getOpcode() != BO_EQ);
1012e5dd7070Spatrick     }
1013e5dd7070Spatrick 
1014e5dd7070Spatrick     return TryResult();
1015e5dd7070Spatrick   }
1016e5dd7070Spatrick 
1017*12c85518Srobert   // Helper function to get an APInt from an expression. Supports expressions
1018*12c85518Srobert   // which are an IntegerLiteral or a UnaryOperator and returns the value with
1019*12c85518Srobert   // all operations performed on it.
1020*12c85518Srobert   // FIXME: it would be good to unify this function with
1021*12c85518Srobert   // IsIntegerLiteralConstantExpr at some point given the similarity between the
1022*12c85518Srobert   // functions.
1023*12c85518Srobert   std::optional<llvm::APInt>
getIntegerLiteralSubexpressionValue(const Expr * E)1024*12c85518Srobert   getIntegerLiteralSubexpressionValue(const Expr *E) {
1025*12c85518Srobert 
1026*12c85518Srobert     // If unary.
1027*12c85518Srobert     if (const auto *UnOp = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
1028*12c85518Srobert       // Get the sub expression of the unary expression and get the Integer
1029*12c85518Srobert       // Literal.
1030*12c85518Srobert       const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();
1031*12c85518Srobert 
1032*12c85518Srobert       if (const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1033*12c85518Srobert 
1034*12c85518Srobert         llvm::APInt Value = IntLiteral->getValue();
1035*12c85518Srobert 
1036*12c85518Srobert         // Perform the operation manually.
1037*12c85518Srobert         switch (UnOp->getOpcode()) {
1038*12c85518Srobert         case UO_Plus:
1039*12c85518Srobert           return Value;
1040*12c85518Srobert         case UO_Minus:
1041*12c85518Srobert           return -Value;
1042*12c85518Srobert         case UO_Not:
1043*12c85518Srobert           return ~Value;
1044*12c85518Srobert         case UO_LNot:
1045*12c85518Srobert           return llvm::APInt(Context->getTypeSize(Context->IntTy), !Value);
1046*12c85518Srobert         default:
1047*12c85518Srobert           assert(false && "Unexpected unary operator!");
1048*12c85518Srobert           return std::nullopt;
1049*12c85518Srobert         }
1050*12c85518Srobert       }
1051*12c85518Srobert     } else if (const auto *IntLiteral =
1052*12c85518Srobert                    dyn_cast<IntegerLiteral>(E->IgnoreParens()))
1053*12c85518Srobert       return IntLiteral->getValue();
1054*12c85518Srobert 
1055*12c85518Srobert     return std::nullopt;
1056*12c85518Srobert   }
1057*12c85518Srobert 
analyzeLogicOperatorCondition(BinaryOperatorKind Relation,const llvm::APSInt & Value1,const llvm::APSInt & Value2)1058e5dd7070Spatrick   TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,
1059e5dd7070Spatrick                                           const llvm::APSInt &Value1,
1060e5dd7070Spatrick                                           const llvm::APSInt &Value2) {
1061e5dd7070Spatrick     assert(Value1.isSigned() == Value2.isSigned());
1062e5dd7070Spatrick     switch (Relation) {
1063e5dd7070Spatrick       default:
1064e5dd7070Spatrick         return TryResult();
1065e5dd7070Spatrick       case BO_EQ:
1066e5dd7070Spatrick         return TryResult(Value1 == Value2);
1067e5dd7070Spatrick       case BO_NE:
1068e5dd7070Spatrick         return TryResult(Value1 != Value2);
1069e5dd7070Spatrick       case BO_LT:
1070e5dd7070Spatrick         return TryResult(Value1 <  Value2);
1071e5dd7070Spatrick       case BO_LE:
1072e5dd7070Spatrick         return TryResult(Value1 <= Value2);
1073e5dd7070Spatrick       case BO_GT:
1074e5dd7070Spatrick         return TryResult(Value1 >  Value2);
1075e5dd7070Spatrick       case BO_GE:
1076e5dd7070Spatrick         return TryResult(Value1 >= Value2);
1077e5dd7070Spatrick     }
1078e5dd7070Spatrick   }
1079e5dd7070Spatrick 
1080e5dd7070Spatrick   /// Find a pair of comparison expressions with or without parentheses
1081e5dd7070Spatrick   /// with a shared variable and constants and a logical operator between them
1082e5dd7070Spatrick   /// that always evaluates to either true or false.
1083e5dd7070Spatrick   /// e.g. if (x != 3 || x != 4)
checkIncorrectLogicOperator(const BinaryOperator * B)1084e5dd7070Spatrick   TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {
1085e5dd7070Spatrick     assert(B->isLogicalOp());
1086e5dd7070Spatrick     const BinaryOperator *LHS =
1087e5dd7070Spatrick         dyn_cast<BinaryOperator>(B->getLHS()->IgnoreParens());
1088e5dd7070Spatrick     const BinaryOperator *RHS =
1089e5dd7070Spatrick         dyn_cast<BinaryOperator>(B->getRHS()->IgnoreParens());
1090e5dd7070Spatrick     if (!LHS || !RHS)
1091e5dd7070Spatrick       return {};
1092e5dd7070Spatrick 
1093e5dd7070Spatrick     if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
1094e5dd7070Spatrick       return {};
1095e5dd7070Spatrick 
1096e5dd7070Spatrick     const Expr *DeclExpr1;
1097e5dd7070Spatrick     const Expr *NumExpr1;
1098e5dd7070Spatrick     BinaryOperatorKind BO1;
1099e5dd7070Spatrick     std::tie(DeclExpr1, BO1, NumExpr1) = tryNormalizeBinaryOperator(LHS);
1100e5dd7070Spatrick 
1101e5dd7070Spatrick     if (!DeclExpr1 || !NumExpr1)
1102e5dd7070Spatrick       return {};
1103e5dd7070Spatrick 
1104e5dd7070Spatrick     const Expr *DeclExpr2;
1105e5dd7070Spatrick     const Expr *NumExpr2;
1106e5dd7070Spatrick     BinaryOperatorKind BO2;
1107e5dd7070Spatrick     std::tie(DeclExpr2, BO2, NumExpr2) = tryNormalizeBinaryOperator(RHS);
1108e5dd7070Spatrick 
1109e5dd7070Spatrick     if (!DeclExpr2 || !NumExpr2)
1110e5dd7070Spatrick       return {};
1111e5dd7070Spatrick 
1112e5dd7070Spatrick     // Check that it is the same variable on both sides.
1113e5dd7070Spatrick     if (!Expr::isSameComparisonOperand(DeclExpr1, DeclExpr2))
1114e5dd7070Spatrick       return {};
1115e5dd7070Spatrick 
1116e5dd7070Spatrick     // Make sure the user's intent is clear (e.g. they're comparing against two
1117e5dd7070Spatrick     // int literals, or two things from the same enum)
1118e5dd7070Spatrick     if (!areExprTypesCompatible(NumExpr1, NumExpr2))
1119e5dd7070Spatrick       return {};
1120e5dd7070Spatrick 
1121e5dd7070Spatrick     Expr::EvalResult L1Result, L2Result;
1122e5dd7070Spatrick     if (!NumExpr1->EvaluateAsInt(L1Result, *Context) ||
1123e5dd7070Spatrick         !NumExpr2->EvaluateAsInt(L2Result, *Context))
1124e5dd7070Spatrick       return {};
1125e5dd7070Spatrick 
1126e5dd7070Spatrick     llvm::APSInt L1 = L1Result.Val.getInt();
1127e5dd7070Spatrick     llvm::APSInt L2 = L2Result.Val.getInt();
1128e5dd7070Spatrick 
1129e5dd7070Spatrick     // Can't compare signed with unsigned or with different bit width.
1130e5dd7070Spatrick     if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
1131e5dd7070Spatrick       return {};
1132e5dd7070Spatrick 
1133e5dd7070Spatrick     // Values that will be used to determine if result of logical
1134e5dd7070Spatrick     // operator is always true/false
1135e5dd7070Spatrick     const llvm::APSInt Values[] = {
1136e5dd7070Spatrick       // Value less than both Value1 and Value2
1137e5dd7070Spatrick       llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
1138e5dd7070Spatrick       // L1
1139e5dd7070Spatrick       L1,
1140e5dd7070Spatrick       // Value between Value1 and Value2
1141e5dd7070Spatrick       ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
1142e5dd7070Spatrick                               L1.isUnsigned()),
1143e5dd7070Spatrick       // L2
1144e5dd7070Spatrick       L2,
1145e5dd7070Spatrick       // Value greater than both Value1 and Value2
1146e5dd7070Spatrick       llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
1147e5dd7070Spatrick     };
1148e5dd7070Spatrick 
1149e5dd7070Spatrick     // Check whether expression is always true/false by evaluating the following
1150e5dd7070Spatrick     // * variable x is less than the smallest literal.
1151e5dd7070Spatrick     // * variable x is equal to the smallest literal.
1152e5dd7070Spatrick     // * Variable x is between smallest and largest literal.
1153e5dd7070Spatrick     // * Variable x is equal to the largest literal.
1154e5dd7070Spatrick     // * Variable x is greater than largest literal.
1155e5dd7070Spatrick     bool AlwaysTrue = true, AlwaysFalse = true;
1156e5dd7070Spatrick     // Track value of both subexpressions.  If either side is always
1157e5dd7070Spatrick     // true/false, another warning should have already been emitted.
1158e5dd7070Spatrick     bool LHSAlwaysTrue = true, LHSAlwaysFalse = true;
1159e5dd7070Spatrick     bool RHSAlwaysTrue = true, RHSAlwaysFalse = true;
1160e5dd7070Spatrick     for (const llvm::APSInt &Value : Values) {
1161e5dd7070Spatrick       TryResult Res1, Res2;
1162e5dd7070Spatrick       Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
1163e5dd7070Spatrick       Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
1164e5dd7070Spatrick 
1165e5dd7070Spatrick       if (!Res1.isKnown() || !Res2.isKnown())
1166e5dd7070Spatrick         return {};
1167e5dd7070Spatrick 
1168e5dd7070Spatrick       if (B->getOpcode() == BO_LAnd) {
1169e5dd7070Spatrick         AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
1170e5dd7070Spatrick         AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
1171e5dd7070Spatrick       } else {
1172e5dd7070Spatrick         AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
1173e5dd7070Spatrick         AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
1174e5dd7070Spatrick       }
1175e5dd7070Spatrick 
1176e5dd7070Spatrick       LHSAlwaysTrue &= Res1.isTrue();
1177e5dd7070Spatrick       LHSAlwaysFalse &= Res1.isFalse();
1178e5dd7070Spatrick       RHSAlwaysTrue &= Res2.isTrue();
1179e5dd7070Spatrick       RHSAlwaysFalse &= Res2.isFalse();
1180e5dd7070Spatrick     }
1181e5dd7070Spatrick 
1182e5dd7070Spatrick     if (AlwaysTrue || AlwaysFalse) {
1183e5dd7070Spatrick       if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1184e5dd7070Spatrick           !RHSAlwaysFalse && BuildOpts.Observer)
1185e5dd7070Spatrick         BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
1186e5dd7070Spatrick       return TryResult(AlwaysTrue);
1187e5dd7070Spatrick     }
1188e5dd7070Spatrick     return {};
1189e5dd7070Spatrick   }
1190e5dd7070Spatrick 
1191e5dd7070Spatrick   /// A bitwise-or with a non-zero constant always evaluates to true.
checkIncorrectBitwiseOrOperator(const BinaryOperator * B)1192e5dd7070Spatrick   TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {
1193e5dd7070Spatrick     const Expr *LHSConstant =
1194e5dd7070Spatrick         tryTransformToIntOrEnumConstant(B->getLHS()->IgnoreParenImpCasts());
1195e5dd7070Spatrick     const Expr *RHSConstant =
1196e5dd7070Spatrick         tryTransformToIntOrEnumConstant(B->getRHS()->IgnoreParenImpCasts());
1197e5dd7070Spatrick 
1198e5dd7070Spatrick     if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1199e5dd7070Spatrick       return {};
1200e5dd7070Spatrick 
1201e5dd7070Spatrick     const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1202e5dd7070Spatrick 
1203e5dd7070Spatrick     Expr::EvalResult Result;
1204e5dd7070Spatrick     if (!Constant->EvaluateAsInt(Result, *Context))
1205e5dd7070Spatrick       return {};
1206e5dd7070Spatrick 
1207e5dd7070Spatrick     if (Result.Val.getInt() == 0)
1208e5dd7070Spatrick       return {};
1209e5dd7070Spatrick 
1210e5dd7070Spatrick     if (BuildOpts.Observer)
1211e5dd7070Spatrick       BuildOpts.Observer->compareBitwiseOr(B);
1212e5dd7070Spatrick 
1213e5dd7070Spatrick     return TryResult(true);
1214e5dd7070Spatrick   }
1215e5dd7070Spatrick 
1216e5dd7070Spatrick   /// Try and evaluate an expression to an integer constant.
tryEvaluate(Expr * S,Expr::EvalResult & outResult)1217e5dd7070Spatrick   bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
1218e5dd7070Spatrick     if (!BuildOpts.PruneTriviallyFalseEdges)
1219e5dd7070Spatrick       return false;
1220e5dd7070Spatrick     return !S->isTypeDependent() &&
1221e5dd7070Spatrick            !S->isValueDependent() &&
1222e5dd7070Spatrick            S->EvaluateAsRValue(outResult, *Context);
1223e5dd7070Spatrick   }
1224e5dd7070Spatrick 
1225e5dd7070Spatrick   /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
1226e5dd7070Spatrick   /// if we can evaluate to a known value, otherwise return -1.
tryEvaluateBool(Expr * S)1227e5dd7070Spatrick   TryResult tryEvaluateBool(Expr *S) {
1228e5dd7070Spatrick     if (!BuildOpts.PruneTriviallyFalseEdges ||
1229e5dd7070Spatrick         S->isTypeDependent() || S->isValueDependent())
1230e5dd7070Spatrick       return {};
1231e5dd7070Spatrick 
1232e5dd7070Spatrick     if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
1233e5dd7070Spatrick       if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
1234e5dd7070Spatrick         // Check the cache first.
1235e5dd7070Spatrick         CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
1236e5dd7070Spatrick         if (I != CachedBoolEvals.end())
1237e5dd7070Spatrick           return I->second; // already in map;
1238e5dd7070Spatrick 
1239e5dd7070Spatrick         // Retrieve result at first, or the map might be updated.
1240e5dd7070Spatrick         TryResult Result = evaluateAsBooleanConditionNoCache(S);
1241e5dd7070Spatrick         CachedBoolEvals[S] = Result; // update or insert
1242e5dd7070Spatrick         return Result;
1243e5dd7070Spatrick       }
1244e5dd7070Spatrick       else {
1245e5dd7070Spatrick         switch (Bop->getOpcode()) {
1246e5dd7070Spatrick           default: break;
1247e5dd7070Spatrick           // For 'x & 0' and 'x * 0', we can determine that
1248e5dd7070Spatrick           // the value is always false.
1249e5dd7070Spatrick           case BO_Mul:
1250e5dd7070Spatrick           case BO_And: {
1251e5dd7070Spatrick             // If either operand is zero, we know the value
1252e5dd7070Spatrick             // must be false.
1253e5dd7070Spatrick             Expr::EvalResult LHSResult;
1254e5dd7070Spatrick             if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
1255e5dd7070Spatrick               llvm::APSInt IntVal = LHSResult.Val.getInt();
1256e5dd7070Spatrick               if (!IntVal.getBoolValue()) {
1257e5dd7070Spatrick                 return TryResult(false);
1258e5dd7070Spatrick               }
1259e5dd7070Spatrick             }
1260e5dd7070Spatrick             Expr::EvalResult RHSResult;
1261e5dd7070Spatrick             if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
1262e5dd7070Spatrick               llvm::APSInt IntVal = RHSResult.Val.getInt();
1263e5dd7070Spatrick               if (!IntVal.getBoolValue()) {
1264e5dd7070Spatrick                 return TryResult(false);
1265e5dd7070Spatrick               }
1266e5dd7070Spatrick             }
1267e5dd7070Spatrick           }
1268e5dd7070Spatrick           break;
1269e5dd7070Spatrick         }
1270e5dd7070Spatrick       }
1271e5dd7070Spatrick     }
1272e5dd7070Spatrick 
1273e5dd7070Spatrick     return evaluateAsBooleanConditionNoCache(S);
1274e5dd7070Spatrick   }
1275e5dd7070Spatrick 
1276e5dd7070Spatrick   /// Evaluate as boolean \param E without using the cache.
evaluateAsBooleanConditionNoCache(Expr * E)1277e5dd7070Spatrick   TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
1278e5dd7070Spatrick     if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
1279e5dd7070Spatrick       if (Bop->isLogicalOp()) {
1280e5dd7070Spatrick         TryResult LHS = tryEvaluateBool(Bop->getLHS());
1281e5dd7070Spatrick         if (LHS.isKnown()) {
1282e5dd7070Spatrick           // We were able to evaluate the LHS, see if we can get away with not
1283e5dd7070Spatrick           // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
1284e5dd7070Spatrick           if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1285e5dd7070Spatrick             return LHS.isTrue();
1286e5dd7070Spatrick 
1287e5dd7070Spatrick           TryResult RHS = tryEvaluateBool(Bop->getRHS());
1288e5dd7070Spatrick           if (RHS.isKnown()) {
1289e5dd7070Spatrick             if (Bop->getOpcode() == BO_LOr)
1290e5dd7070Spatrick               return LHS.isTrue() || RHS.isTrue();
1291e5dd7070Spatrick             else
1292e5dd7070Spatrick               return LHS.isTrue() && RHS.isTrue();
1293e5dd7070Spatrick           }
1294e5dd7070Spatrick         } else {
1295e5dd7070Spatrick           TryResult RHS = tryEvaluateBool(Bop->getRHS());
1296e5dd7070Spatrick           if (RHS.isKnown()) {
1297e5dd7070Spatrick             // We can't evaluate the LHS; however, sometimes the result
1298e5dd7070Spatrick             // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
1299e5dd7070Spatrick             if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
1300e5dd7070Spatrick               return RHS.isTrue();
1301e5dd7070Spatrick           } else {
1302e5dd7070Spatrick             TryResult BopRes = checkIncorrectLogicOperator(Bop);
1303e5dd7070Spatrick             if (BopRes.isKnown())
1304e5dd7070Spatrick               return BopRes.isTrue();
1305e5dd7070Spatrick           }
1306e5dd7070Spatrick         }
1307e5dd7070Spatrick 
1308e5dd7070Spatrick         return {};
1309e5dd7070Spatrick       } else if (Bop->isEqualityOp()) {
1310e5dd7070Spatrick           TryResult BopRes = checkIncorrectEqualityOperator(Bop);
1311e5dd7070Spatrick           if (BopRes.isKnown())
1312e5dd7070Spatrick             return BopRes.isTrue();
1313e5dd7070Spatrick       } else if (Bop->isRelationalOp()) {
1314e5dd7070Spatrick         TryResult BopRes = checkIncorrectRelationalOperator(Bop);
1315e5dd7070Spatrick         if (BopRes.isKnown())
1316e5dd7070Spatrick           return BopRes.isTrue();
1317e5dd7070Spatrick       } else if (Bop->getOpcode() == BO_Or) {
1318e5dd7070Spatrick         TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1319e5dd7070Spatrick         if (BopRes.isKnown())
1320e5dd7070Spatrick           return BopRes.isTrue();
1321e5dd7070Spatrick       }
1322e5dd7070Spatrick     }
1323e5dd7070Spatrick 
1324e5dd7070Spatrick     bool Result;
1325e5dd7070Spatrick     if (E->EvaluateAsBooleanCondition(Result, *Context))
1326e5dd7070Spatrick       return Result;
1327e5dd7070Spatrick 
1328e5dd7070Spatrick     return {};
1329e5dd7070Spatrick   }
1330e5dd7070Spatrick 
1331e5dd7070Spatrick   bool hasTrivialDestructor(VarDecl *VD);
1332e5dd7070Spatrick };
1333e5dd7070Spatrick 
1334e5dd7070Spatrick } // namespace
1335e5dd7070Spatrick 
1336*12c85518Srobert Expr *
extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr * AILE)1337*12c85518Srobert clang::extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE) {
1338*12c85518Srobert   if (!AILE)
1339*12c85518Srobert     return nullptr;
1340*12c85518Srobert 
1341*12c85518Srobert   Expr *AILEInit = AILE->getSubExpr();
1342*12c85518Srobert   while (const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1343*12c85518Srobert     AILEInit = E->getSubExpr();
1344*12c85518Srobert 
1345*12c85518Srobert   return AILEInit;
1346*12c85518Srobert }
1347*12c85518Srobert 
alwaysAdd(CFGBuilder & builder,const Stmt * stmt) const1348e5dd7070Spatrick inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
1349e5dd7070Spatrick                                      const Stmt *stmt) const {
1350e5dd7070Spatrick   return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
1351e5dd7070Spatrick }
1352e5dd7070Spatrick 
alwaysAdd(const Stmt * stmt)1353e5dd7070Spatrick bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
1354e5dd7070Spatrick   bool shouldAdd = BuildOpts.alwaysAdd(stmt);
1355e5dd7070Spatrick 
1356e5dd7070Spatrick   if (!BuildOpts.forcedBlkExprs)
1357e5dd7070Spatrick     return shouldAdd;
1358e5dd7070Spatrick 
1359e5dd7070Spatrick   if (lastLookup == stmt) {
1360e5dd7070Spatrick     if (cachedEntry) {
1361e5dd7070Spatrick       assert(cachedEntry->first == stmt);
1362e5dd7070Spatrick       return true;
1363e5dd7070Spatrick     }
1364e5dd7070Spatrick     return shouldAdd;
1365e5dd7070Spatrick   }
1366e5dd7070Spatrick 
1367e5dd7070Spatrick   lastLookup = stmt;
1368e5dd7070Spatrick 
1369e5dd7070Spatrick   // Perform the lookup!
1370e5dd7070Spatrick   CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;
1371e5dd7070Spatrick 
1372e5dd7070Spatrick   if (!fb) {
1373e5dd7070Spatrick     // No need to update 'cachedEntry', since it will always be null.
1374e5dd7070Spatrick     assert(!cachedEntry);
1375e5dd7070Spatrick     return shouldAdd;
1376e5dd7070Spatrick   }
1377e5dd7070Spatrick 
1378e5dd7070Spatrick   CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
1379e5dd7070Spatrick   if (itr == fb->end()) {
1380e5dd7070Spatrick     cachedEntry = nullptr;
1381e5dd7070Spatrick     return shouldAdd;
1382e5dd7070Spatrick   }
1383e5dd7070Spatrick 
1384e5dd7070Spatrick   cachedEntry = &*itr;
1385e5dd7070Spatrick   return true;
1386e5dd7070Spatrick }
1387e5dd7070Spatrick 
1388e5dd7070Spatrick // FIXME: Add support for dependent-sized array types in C++?
1389e5dd7070Spatrick // Does it even make sense to build a CFG for an uninstantiated template?
FindVA(const Type * t)1390e5dd7070Spatrick static const VariableArrayType *FindVA(const Type *t) {
1391e5dd7070Spatrick   while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
1392e5dd7070Spatrick     if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
1393e5dd7070Spatrick       if (vat->getSizeExpr())
1394e5dd7070Spatrick         return vat;
1395e5dd7070Spatrick 
1396e5dd7070Spatrick     t = vt->getElementType().getTypePtr();
1397e5dd7070Spatrick   }
1398e5dd7070Spatrick 
1399e5dd7070Spatrick   return nullptr;
1400e5dd7070Spatrick }
1401e5dd7070Spatrick 
consumeConstructionContext(const ConstructionContextLayer * Layer,Expr * E)1402e5dd7070Spatrick void CFGBuilder::consumeConstructionContext(
1403e5dd7070Spatrick     const ConstructionContextLayer *Layer, Expr *E) {
1404e5dd7070Spatrick   assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
1405e5dd7070Spatrick           isa<ObjCMessageExpr>(E)) && "Expression cannot construct an object!");
1406e5dd7070Spatrick   if (const ConstructionContextLayer *PreviouslyStoredLayer =
1407e5dd7070Spatrick           ConstructionContextMap.lookup(E)) {
1408e5dd7070Spatrick     (void)PreviouslyStoredLayer;
1409e5dd7070Spatrick     // We might have visited this child when we were finding construction
1410e5dd7070Spatrick     // contexts within its parents.
1411e5dd7070Spatrick     assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
1412e5dd7070Spatrick            "Already within a different construction context!");
1413e5dd7070Spatrick   } else {
1414e5dd7070Spatrick     ConstructionContextMap[E] = Layer;
1415e5dd7070Spatrick   }
1416e5dd7070Spatrick }
1417e5dd7070Spatrick 
findConstructionContexts(const ConstructionContextLayer * Layer,Stmt * Child)1418e5dd7070Spatrick void CFGBuilder::findConstructionContexts(
1419e5dd7070Spatrick     const ConstructionContextLayer *Layer, Stmt *Child) {
1420e5dd7070Spatrick   if (!BuildOpts.AddRichCXXConstructors)
1421e5dd7070Spatrick     return;
1422e5dd7070Spatrick 
1423e5dd7070Spatrick   if (!Child)
1424e5dd7070Spatrick     return;
1425e5dd7070Spatrick 
1426e5dd7070Spatrick   auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {
1427e5dd7070Spatrick     return ConstructionContextLayer::create(cfg->getBumpVectorContext(), Item,
1428e5dd7070Spatrick                                             Layer);
1429e5dd7070Spatrick   };
1430e5dd7070Spatrick 
1431e5dd7070Spatrick   switch(Child->getStmtClass()) {
1432e5dd7070Spatrick   case Stmt::CXXConstructExprClass:
1433e5dd7070Spatrick   case Stmt::CXXTemporaryObjectExprClass: {
1434e5dd7070Spatrick     // Support pre-C++17 copy elision AST.
1435e5dd7070Spatrick     auto *CE = cast<CXXConstructExpr>(Child);
1436e5dd7070Spatrick     if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
1437e5dd7070Spatrick       findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
1438e5dd7070Spatrick     }
1439e5dd7070Spatrick 
1440e5dd7070Spatrick     consumeConstructionContext(Layer, CE);
1441e5dd7070Spatrick     break;
1442e5dd7070Spatrick   }
1443e5dd7070Spatrick   // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr.
1444e5dd7070Spatrick   // FIXME: An isa<> would look much better but this whole switch is a
1445e5dd7070Spatrick   // workaround for an internal compiler error in MSVC 2015 (see r326021).
1446e5dd7070Spatrick   case Stmt::CallExprClass:
1447e5dd7070Spatrick   case Stmt::CXXMemberCallExprClass:
1448e5dd7070Spatrick   case Stmt::CXXOperatorCallExprClass:
1449e5dd7070Spatrick   case Stmt::UserDefinedLiteralClass:
1450e5dd7070Spatrick   case Stmt::ObjCMessageExprClass: {
1451e5dd7070Spatrick     auto *E = cast<Expr>(Child);
1452e5dd7070Spatrick     if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(E))
1453e5dd7070Spatrick       consumeConstructionContext(Layer, E);
1454e5dd7070Spatrick     break;
1455e5dd7070Spatrick   }
1456e5dd7070Spatrick   case Stmt::ExprWithCleanupsClass: {
1457e5dd7070Spatrick     auto *Cleanups = cast<ExprWithCleanups>(Child);
1458e5dd7070Spatrick     findConstructionContexts(Layer, Cleanups->getSubExpr());
1459e5dd7070Spatrick     break;
1460e5dd7070Spatrick   }
1461e5dd7070Spatrick   case Stmt::CXXFunctionalCastExprClass: {
1462e5dd7070Spatrick     auto *Cast = cast<CXXFunctionalCastExpr>(Child);
1463e5dd7070Spatrick     findConstructionContexts(Layer, Cast->getSubExpr());
1464e5dd7070Spatrick     break;
1465e5dd7070Spatrick   }
1466e5dd7070Spatrick   case Stmt::ImplicitCastExprClass: {
1467e5dd7070Spatrick     auto *Cast = cast<ImplicitCastExpr>(Child);
1468e5dd7070Spatrick     // Should we support other implicit cast kinds?
1469e5dd7070Spatrick     switch (Cast->getCastKind()) {
1470e5dd7070Spatrick     case CK_NoOp:
1471e5dd7070Spatrick     case CK_ConstructorConversion:
1472e5dd7070Spatrick       findConstructionContexts(Layer, Cast->getSubExpr());
1473e5dd7070Spatrick       break;
1474e5dd7070Spatrick     default:
1475e5dd7070Spatrick       break;
1476e5dd7070Spatrick     }
1477e5dd7070Spatrick     break;
1478e5dd7070Spatrick   }
1479e5dd7070Spatrick   case Stmt::CXXBindTemporaryExprClass: {
1480e5dd7070Spatrick     auto *BTE = cast<CXXBindTemporaryExpr>(Child);
1481e5dd7070Spatrick     findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
1482e5dd7070Spatrick     break;
1483e5dd7070Spatrick   }
1484e5dd7070Spatrick   case Stmt::MaterializeTemporaryExprClass: {
1485e5dd7070Spatrick     // Normally we don't want to search in MaterializeTemporaryExpr because
1486e5dd7070Spatrick     // it indicates the beginning of a temporary object construction context,
1487e5dd7070Spatrick     // so it shouldn't be found in the middle. However, if it is the beginning
1488e5dd7070Spatrick     // of an elidable copy or move construction context, we need to include it.
1489e5dd7070Spatrick     if (Layer->getItem().getKind() ==
1490e5dd7070Spatrick         ConstructionContextItem::ElidableConstructorKind) {
1491e5dd7070Spatrick       auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1492e5dd7070Spatrick       findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
1493e5dd7070Spatrick     }
1494e5dd7070Spatrick     break;
1495e5dd7070Spatrick   }
1496e5dd7070Spatrick   case Stmt::ConditionalOperatorClass: {
1497e5dd7070Spatrick     auto *CO = cast<ConditionalOperator>(Child);
1498e5dd7070Spatrick     if (Layer->getItem().getKind() !=
1499e5dd7070Spatrick         ConstructionContextItem::MaterializationKind) {
1500e5dd7070Spatrick       // If the object returned by the conditional operator is not going to be a
1501e5dd7070Spatrick       // temporary object that needs to be immediately materialized, then
1502e5dd7070Spatrick       // it must be C++17 with its mandatory copy elision. Do not yet promise
1503e5dd7070Spatrick       // to support this case.
1504e5dd7070Spatrick       assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
1505e5dd7070Spatrick              Context->getLangOpts().CPlusPlus17);
1506e5dd7070Spatrick       break;
1507e5dd7070Spatrick     }
1508e5dd7070Spatrick     findConstructionContexts(Layer, CO->getLHS());
1509e5dd7070Spatrick     findConstructionContexts(Layer, CO->getRHS());
1510e5dd7070Spatrick     break;
1511e5dd7070Spatrick   }
1512e5dd7070Spatrick   case Stmt::InitListExprClass: {
1513e5dd7070Spatrick     auto *ILE = cast<InitListExpr>(Child);
1514e5dd7070Spatrick     if (ILE->isTransparent()) {
1515e5dd7070Spatrick       findConstructionContexts(Layer, ILE->getInit(0));
1516e5dd7070Spatrick       break;
1517e5dd7070Spatrick     }
1518e5dd7070Spatrick     // TODO: Handle other cases. For now, fail to find construction contexts.
1519e5dd7070Spatrick     break;
1520e5dd7070Spatrick   }
1521a9ac8606Spatrick   case Stmt::ParenExprClass: {
1522a9ac8606Spatrick     // If expression is placed into parenthesis we should propagate the parent
1523a9ac8606Spatrick     // construction context to subexpressions.
1524a9ac8606Spatrick     auto *PE = cast<ParenExpr>(Child);
1525a9ac8606Spatrick     findConstructionContexts(Layer, PE->getSubExpr());
1526a9ac8606Spatrick     break;
1527a9ac8606Spatrick   }
1528e5dd7070Spatrick   default:
1529e5dd7070Spatrick     break;
1530e5dd7070Spatrick   }
1531e5dd7070Spatrick }
1532e5dd7070Spatrick 
cleanupConstructionContext(Expr * E)1533e5dd7070Spatrick void CFGBuilder::cleanupConstructionContext(Expr *E) {
1534e5dd7070Spatrick   assert(BuildOpts.AddRichCXXConstructors &&
1535e5dd7070Spatrick          "We should not be managing construction contexts!");
1536e5dd7070Spatrick   assert(ConstructionContextMap.count(E) &&
1537e5dd7070Spatrick          "Cannot exit construction context without the context!");
1538e5dd7070Spatrick   ConstructionContextMap.erase(E);
1539e5dd7070Spatrick }
1540e5dd7070Spatrick 
1541e5dd7070Spatrick 
1542e5dd7070Spatrick /// BuildCFG - Constructs a CFG from an AST (a Stmt*).  The AST can represent an
1543e5dd7070Spatrick ///  arbitrary statement.  Examples include a single expression or a function
1544e5dd7070Spatrick ///  body (compound statement).  The ownership of the returned CFG is
1545e5dd7070Spatrick ///  transferred to the caller.  If CFG construction fails, this method returns
1546e5dd7070Spatrick ///  NULL.
buildCFG(const Decl * D,Stmt * Statement)1547e5dd7070Spatrick std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
1548e5dd7070Spatrick   assert(cfg.get());
1549e5dd7070Spatrick   if (!Statement)
1550e5dd7070Spatrick     return nullptr;
1551e5dd7070Spatrick 
1552e5dd7070Spatrick   // Create an empty block that will serve as the exit block for the CFG.  Since
1553e5dd7070Spatrick   // this is the first block added to the CFG, it will be implicitly registered
1554e5dd7070Spatrick   // as the exit block.
1555e5dd7070Spatrick   Succ = createBlock();
1556e5dd7070Spatrick   assert(Succ == &cfg->getExit());
1557e5dd7070Spatrick   Block = nullptr;  // the EXIT block is empty.  Create all other blocks lazily.
1558e5dd7070Spatrick 
1559e5dd7070Spatrick   assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
1560e5dd7070Spatrick          "AddImplicitDtors and AddLifetime cannot be used at the same time");
1561e5dd7070Spatrick 
1562e5dd7070Spatrick   if (BuildOpts.AddImplicitDtors)
1563e5dd7070Spatrick     if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
1564e5dd7070Spatrick       addImplicitDtorsForDestructor(DD);
1565e5dd7070Spatrick 
1566e5dd7070Spatrick   // Visit the statements and create the CFG.
1567e5dd7070Spatrick   CFGBlock *B = addStmt(Statement);
1568e5dd7070Spatrick 
1569e5dd7070Spatrick   if (badCFG)
1570e5dd7070Spatrick     return nullptr;
1571e5dd7070Spatrick 
1572e5dd7070Spatrick   // For C++ constructor add initializers to CFG. Constructors of virtual bases
1573e5dd7070Spatrick   // are ignored unless the object is of the most derived class.
1574e5dd7070Spatrick   //   class VBase { VBase() = default; VBase(int) {} };
1575e5dd7070Spatrick   //   class A : virtual public VBase { A() : VBase(0) {} };
1576e5dd7070Spatrick   //   class B : public A {};
1577e5dd7070Spatrick   //   B b; // Constructor calls in order: VBase(), A(), B().
1578e5dd7070Spatrick   //        // VBase(0) is ignored because A isn't the most derived class.
1579e5dd7070Spatrick   // This may result in the virtual base(s) being already initialized at this
1580e5dd7070Spatrick   // point, in which case we should jump right onto non-virtual bases and
1581e5dd7070Spatrick   // fields. To handle this, make a CFG branch. We only need to add one such
1582e5dd7070Spatrick   // branch per constructor, since the Standard states that all virtual bases
1583e5dd7070Spatrick   // shall be initialized before non-virtual bases and direct data members.
1584e5dd7070Spatrick   if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
1585e5dd7070Spatrick     CFGBlock *VBaseSucc = nullptr;
1586e5dd7070Spatrick     for (auto *I : llvm::reverse(CD->inits())) {
1587e5dd7070Spatrick       if (BuildOpts.AddVirtualBaseBranches && !VBaseSucc &&
1588e5dd7070Spatrick           I->isBaseInitializer() && I->isBaseVirtual()) {
1589e5dd7070Spatrick         // We've reached the first virtual base init while iterating in reverse
1590e5dd7070Spatrick         // order. Make a new block for virtual base initializers so that we
1591e5dd7070Spatrick         // could skip them.
1592e5dd7070Spatrick         VBaseSucc = Succ = B ? B : &cfg->getExit();
1593e5dd7070Spatrick         Block = createBlock();
1594e5dd7070Spatrick       }
1595e5dd7070Spatrick       B = addInitializer(I);
1596e5dd7070Spatrick       if (badCFG)
1597e5dd7070Spatrick         return nullptr;
1598e5dd7070Spatrick     }
1599e5dd7070Spatrick     if (VBaseSucc) {
1600e5dd7070Spatrick       // Make a branch block for potentially skipping virtual base initializers.
1601e5dd7070Spatrick       Succ = VBaseSucc;
1602e5dd7070Spatrick       B = createBlock();
1603e5dd7070Spatrick       B->setTerminator(
1604e5dd7070Spatrick           CFGTerminator(nullptr, CFGTerminator::VirtualBaseBranch));
1605e5dd7070Spatrick       addSuccessor(B, Block, true);
1606e5dd7070Spatrick     }
1607e5dd7070Spatrick   }
1608e5dd7070Spatrick 
1609e5dd7070Spatrick   if (B)
1610e5dd7070Spatrick     Succ = B;
1611e5dd7070Spatrick 
1612e5dd7070Spatrick   // Backpatch the gotos whose label -> block mappings we didn't know when we
1613e5dd7070Spatrick   // encountered them.
1614e5dd7070Spatrick   for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
1615e5dd7070Spatrick                                    E = BackpatchBlocks.end(); I != E; ++I ) {
1616e5dd7070Spatrick 
1617e5dd7070Spatrick     CFGBlock *B = I->block;
1618e5dd7070Spatrick     if (auto *G = dyn_cast<GotoStmt>(B->getTerminator())) {
1619e5dd7070Spatrick       LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
1620e5dd7070Spatrick       // If there is no target for the goto, then we are looking at an
1621e5dd7070Spatrick       // incomplete AST.  Handle this by not registering a successor.
1622e5dd7070Spatrick       if (LI == LabelMap.end())
1623e5dd7070Spatrick         continue;
1624e5dd7070Spatrick       JumpTarget JT = LI->second;
1625e5dd7070Spatrick       prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition,
1626e5dd7070Spatrick                                                 JT.scopePosition);
1627e5dd7070Spatrick       prependAutomaticObjDtorsWithTerminator(B, I->scopePosition,
1628e5dd7070Spatrick                                              JT.scopePosition);
1629e5dd7070Spatrick       const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator(
1630e5dd7070Spatrick           B, I->scopePosition, JT.scopePosition);
1631e5dd7070Spatrick       appendScopeBegin(JT.block, VD, G);
1632e5dd7070Spatrick       addSuccessor(B, JT.block);
1633e5dd7070Spatrick     };
1634e5dd7070Spatrick     if (auto *G = dyn_cast<GCCAsmStmt>(B->getTerminator())) {
1635e5dd7070Spatrick       CFGBlock *Successor  = (I+1)->block;
1636e5dd7070Spatrick       for (auto *L : G->labels()) {
1637e5dd7070Spatrick         LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
1638e5dd7070Spatrick         // If there is no target for the goto, then we are looking at an
1639e5dd7070Spatrick         // incomplete AST.  Handle this by not registering a successor.
1640e5dd7070Spatrick         if (LI == LabelMap.end())
1641e5dd7070Spatrick           continue;
1642e5dd7070Spatrick         JumpTarget JT = LI->second;
1643e5dd7070Spatrick         // Successor has been added, so skip it.
1644e5dd7070Spatrick         if (JT.block == Successor)
1645e5dd7070Spatrick           continue;
1646e5dd7070Spatrick         addSuccessor(B, JT.block);
1647e5dd7070Spatrick       }
1648e5dd7070Spatrick       I++;
1649e5dd7070Spatrick     }
1650e5dd7070Spatrick   }
1651e5dd7070Spatrick 
1652e5dd7070Spatrick   // Add successors to the Indirect Goto Dispatch block (if we have one).
1653e5dd7070Spatrick   if (CFGBlock *B = cfg->getIndirectGotoBlock())
1654e5dd7070Spatrick     for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
1655e5dd7070Spatrick                               E = AddressTakenLabels.end(); I != E; ++I ) {
1656e5dd7070Spatrick       // Lookup the target block.
1657e5dd7070Spatrick       LabelMapTy::iterator LI = LabelMap.find(*I);
1658e5dd7070Spatrick 
1659e5dd7070Spatrick       // If there is no target block that contains label, then we are looking
1660e5dd7070Spatrick       // at an incomplete AST.  Handle this by not registering a successor.
1661e5dd7070Spatrick       if (LI == LabelMap.end()) continue;
1662e5dd7070Spatrick 
1663e5dd7070Spatrick       addSuccessor(B, LI->second.block);
1664e5dd7070Spatrick     }
1665e5dd7070Spatrick 
1666e5dd7070Spatrick   // Create an empty entry block that has no predecessors.
1667e5dd7070Spatrick   cfg->setEntry(createBlock());
1668e5dd7070Spatrick 
1669e5dd7070Spatrick   if (BuildOpts.AddRichCXXConstructors)
1670e5dd7070Spatrick     assert(ConstructionContextMap.empty() &&
1671e5dd7070Spatrick            "Not all construction contexts were cleaned up!");
1672e5dd7070Spatrick 
1673e5dd7070Spatrick   return std::move(cfg);
1674e5dd7070Spatrick }
1675e5dd7070Spatrick 
1676e5dd7070Spatrick /// createBlock - Used to lazily create blocks that are connected
1677*12c85518Srobert ///  to the current (global) successor.
createBlock(bool add_successor)1678e5dd7070Spatrick CFGBlock *CFGBuilder::createBlock(bool add_successor) {
1679e5dd7070Spatrick   CFGBlock *B = cfg->createBlock();
1680e5dd7070Spatrick   if (add_successor && Succ)
1681e5dd7070Spatrick     addSuccessor(B, Succ);
1682e5dd7070Spatrick   return B;
1683e5dd7070Spatrick }
1684e5dd7070Spatrick 
1685e5dd7070Spatrick /// createNoReturnBlock - Used to create a block is a 'noreturn' point in the
1686e5dd7070Spatrick /// CFG. It is *not* connected to the current (global) successor, and instead
1687e5dd7070Spatrick /// directly tied to the exit block in order to be reachable.
createNoReturnBlock()1688e5dd7070Spatrick CFGBlock *CFGBuilder::createNoReturnBlock() {
1689e5dd7070Spatrick   CFGBlock *B = createBlock(false);
1690e5dd7070Spatrick   B->setHasNoReturnElement();
1691e5dd7070Spatrick   addSuccessor(B, &cfg->getExit(), Succ);
1692e5dd7070Spatrick   return B;
1693e5dd7070Spatrick }
1694e5dd7070Spatrick 
1695e5dd7070Spatrick /// addInitializer - Add C++ base or member initializer element to CFG.
addInitializer(CXXCtorInitializer * I)1696e5dd7070Spatrick CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
1697e5dd7070Spatrick   if (!BuildOpts.AddInitializers)
1698e5dd7070Spatrick     return Block;
1699e5dd7070Spatrick 
1700e5dd7070Spatrick   bool HasTemporaries = false;
1701e5dd7070Spatrick 
1702e5dd7070Spatrick   // Destructors of temporaries in initialization expression should be called
1703e5dd7070Spatrick   // after initialization finishes.
1704e5dd7070Spatrick   Expr *Init = I->getInit();
1705e5dd7070Spatrick   if (Init) {
1706e5dd7070Spatrick     HasTemporaries = isa<ExprWithCleanups>(Init);
1707e5dd7070Spatrick 
1708e5dd7070Spatrick     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
1709e5dd7070Spatrick       // Generate destructors for temporaries in initialization expression.
1710e5dd7070Spatrick       TempDtorContext Context;
1711e5dd7070Spatrick       VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1712e5dd7070Spatrick                              /*ExternallyDestructed=*/false, Context);
1713e5dd7070Spatrick     }
1714e5dd7070Spatrick   }
1715e5dd7070Spatrick 
1716e5dd7070Spatrick   autoCreateBlock();
1717e5dd7070Spatrick   appendInitializer(Block, I);
1718e5dd7070Spatrick 
1719e5dd7070Spatrick   if (Init) {
1720*12c85518Srobert     // If the initializer is an ArrayInitLoopExpr, we want to extract the
1721*12c85518Srobert     // initializer, that's used for each element.
1722*12c85518Srobert     auto *AILEInit = extractElementInitializerFromNestedAILE(
1723*12c85518Srobert         dyn_cast<ArrayInitLoopExpr>(Init));
1724*12c85518Srobert 
1725e5dd7070Spatrick     findConstructionContexts(
1726e5dd7070Spatrick         ConstructionContextLayer::create(cfg->getBumpVectorContext(), I),
1727*12c85518Srobert         AILEInit ? AILEInit : Init);
1728e5dd7070Spatrick 
1729e5dd7070Spatrick     if (HasTemporaries) {
1730e5dd7070Spatrick       // For expression with temporaries go directly to subexpression to omit
1731e5dd7070Spatrick       // generating destructors for the second time.
1732e5dd7070Spatrick       return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
1733e5dd7070Spatrick     }
1734e5dd7070Spatrick     if (BuildOpts.AddCXXDefaultInitExprInCtors) {
1735e5dd7070Spatrick       if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) {
1736e5dd7070Spatrick         // In general, appending the expression wrapped by a CXXDefaultInitExpr
1737e5dd7070Spatrick         // may cause the same Expr to appear more than once in the CFG. Doing it
1738e5dd7070Spatrick         // here is safe because there's only one initializer per field.
1739e5dd7070Spatrick         autoCreateBlock();
1740e5dd7070Spatrick         appendStmt(Block, Default);
1741e5dd7070Spatrick         if (Stmt *Child = Default->getExpr())
1742e5dd7070Spatrick           if (CFGBlock *R = Visit(Child))
1743e5dd7070Spatrick             Block = R;
1744e5dd7070Spatrick         return Block;
1745e5dd7070Spatrick       }
1746e5dd7070Spatrick     }
1747e5dd7070Spatrick     return Visit(Init);
1748e5dd7070Spatrick   }
1749e5dd7070Spatrick 
1750e5dd7070Spatrick   return Block;
1751e5dd7070Spatrick }
1752e5dd7070Spatrick 
1753e5dd7070Spatrick /// Retrieve the type of the temporary object whose lifetime was
1754e5dd7070Spatrick /// extended by a local reference with the given initializer.
getReferenceInitTemporaryType(const Expr * Init,bool * FoundMTE=nullptr)1755e5dd7070Spatrick static QualType getReferenceInitTemporaryType(const Expr *Init,
1756e5dd7070Spatrick                                               bool *FoundMTE = nullptr) {
1757e5dd7070Spatrick   while (true) {
1758e5dd7070Spatrick     // Skip parentheses.
1759e5dd7070Spatrick     Init = Init->IgnoreParens();
1760e5dd7070Spatrick 
1761e5dd7070Spatrick     // Skip through cleanups.
1762e5dd7070Spatrick     if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) {
1763e5dd7070Spatrick       Init = EWC->getSubExpr();
1764e5dd7070Spatrick       continue;
1765e5dd7070Spatrick     }
1766e5dd7070Spatrick 
1767e5dd7070Spatrick     // Skip through the temporary-materialization expression.
1768e5dd7070Spatrick     if (const MaterializeTemporaryExpr *MTE
1769e5dd7070Spatrick           = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1770e5dd7070Spatrick       Init = MTE->getSubExpr();
1771e5dd7070Spatrick       if (FoundMTE)
1772e5dd7070Spatrick         *FoundMTE = true;
1773e5dd7070Spatrick       continue;
1774e5dd7070Spatrick     }
1775e5dd7070Spatrick 
1776e5dd7070Spatrick     // Skip sub-object accesses into rvalues.
1777e5dd7070Spatrick     SmallVector<const Expr *, 2> CommaLHSs;
1778e5dd7070Spatrick     SmallVector<SubobjectAdjustment, 2> Adjustments;
1779e5dd7070Spatrick     const Expr *SkippedInit =
1780e5dd7070Spatrick         Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
1781e5dd7070Spatrick     if (SkippedInit != Init) {
1782e5dd7070Spatrick       Init = SkippedInit;
1783e5dd7070Spatrick       continue;
1784e5dd7070Spatrick     }
1785e5dd7070Spatrick 
1786e5dd7070Spatrick     break;
1787e5dd7070Spatrick   }
1788e5dd7070Spatrick 
1789e5dd7070Spatrick   return Init->getType();
1790e5dd7070Spatrick }
1791e5dd7070Spatrick 
1792e5dd7070Spatrick // TODO: Support adding LoopExit element to the CFG in case where the loop is
1793e5dd7070Spatrick // ended by ReturnStmt, GotoStmt or ThrowExpr.
addLoopExit(const Stmt * LoopStmt)1794e5dd7070Spatrick void CFGBuilder::addLoopExit(const Stmt *LoopStmt){
1795e5dd7070Spatrick   if(!BuildOpts.AddLoopExit)
1796e5dd7070Spatrick     return;
1797e5dd7070Spatrick   autoCreateBlock();
1798e5dd7070Spatrick   appendLoopExit(Block, LoopStmt);
1799e5dd7070Spatrick }
1800e5dd7070Spatrick 
getDeclsWithEndedScope(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1801e5dd7070Spatrick void CFGBuilder::getDeclsWithEndedScope(LocalScope::const_iterator B,
1802e5dd7070Spatrick                                         LocalScope::const_iterator E, Stmt *S) {
1803e5dd7070Spatrick   if (!BuildOpts.AddScopes)
1804e5dd7070Spatrick     return;
1805e5dd7070Spatrick 
1806e5dd7070Spatrick   if (B == E)
1807e5dd7070Spatrick     return;
1808e5dd7070Spatrick 
1809e5dd7070Spatrick   // To go from B to E, one first goes up the scopes from B to P
1810e5dd7070Spatrick   // then sideways in one scope from P to P' and then down
1811e5dd7070Spatrick   // the scopes from P' to E.
1812e5dd7070Spatrick   // The lifetime of all objects between B and P end.
1813e5dd7070Spatrick   LocalScope::const_iterator P = B.shared_parent(E);
1814e5dd7070Spatrick   int Dist = B.distance(P);
1815e5dd7070Spatrick   if (Dist <= 0)
1816e5dd7070Spatrick     return;
1817e5dd7070Spatrick 
1818e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != P; ++I)
1819e5dd7070Spatrick     if (I.pointsToFirstDeclaredVar())
1820e5dd7070Spatrick       DeclsWithEndedScope.insert(*I);
1821e5dd7070Spatrick }
1822e5dd7070Spatrick 
addAutomaticObjHandling(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1823e5dd7070Spatrick void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
1824e5dd7070Spatrick                                          LocalScope::const_iterator E,
1825e5dd7070Spatrick                                          Stmt *S) {
1826e5dd7070Spatrick   getDeclsWithEndedScope(B, E, S);
1827e5dd7070Spatrick   if (BuildOpts.AddScopes)
1828e5dd7070Spatrick     addScopesEnd(B, E, S);
1829e5dd7070Spatrick   if (BuildOpts.AddImplicitDtors)
1830e5dd7070Spatrick     addAutomaticObjDtors(B, E, S);
1831e5dd7070Spatrick   if (BuildOpts.AddLifetime)
1832e5dd7070Spatrick     addLifetimeEnds(B, E, S);
1833e5dd7070Spatrick }
1834e5dd7070Spatrick 
1835e5dd7070Spatrick /// Add to current block automatic objects that leave the scope.
addLifetimeEnds(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1836e5dd7070Spatrick void CFGBuilder::addLifetimeEnds(LocalScope::const_iterator B,
1837e5dd7070Spatrick                                  LocalScope::const_iterator E, Stmt *S) {
1838e5dd7070Spatrick   if (!BuildOpts.AddLifetime)
1839e5dd7070Spatrick     return;
1840e5dd7070Spatrick 
1841e5dd7070Spatrick   if (B == E)
1842e5dd7070Spatrick     return;
1843e5dd7070Spatrick 
1844e5dd7070Spatrick   // To go from B to E, one first goes up the scopes from B to P
1845e5dd7070Spatrick   // then sideways in one scope from P to P' and then down
1846e5dd7070Spatrick   // the scopes from P' to E.
1847e5dd7070Spatrick   // The lifetime of all objects between B and P end.
1848e5dd7070Spatrick   LocalScope::const_iterator P = B.shared_parent(E);
1849e5dd7070Spatrick   int dist = B.distance(P);
1850e5dd7070Spatrick   if (dist <= 0)
1851e5dd7070Spatrick     return;
1852e5dd7070Spatrick 
1853e5dd7070Spatrick   // We need to perform the scope leaving in reverse order
1854e5dd7070Spatrick   SmallVector<VarDecl *, 10> DeclsTrivial;
1855e5dd7070Spatrick   SmallVector<VarDecl *, 10> DeclsNonTrivial;
1856e5dd7070Spatrick   DeclsTrivial.reserve(dist);
1857e5dd7070Spatrick   DeclsNonTrivial.reserve(dist);
1858e5dd7070Spatrick 
1859e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != P; ++I)
1860e5dd7070Spatrick     if (hasTrivialDestructor(*I))
1861e5dd7070Spatrick       DeclsTrivial.push_back(*I);
1862e5dd7070Spatrick     else
1863e5dd7070Spatrick       DeclsNonTrivial.push_back(*I);
1864e5dd7070Spatrick 
1865e5dd7070Spatrick   autoCreateBlock();
1866e5dd7070Spatrick   // object with trivial destructor end their lifetime last (when storage
1867e5dd7070Spatrick   // duration ends)
1868*12c85518Srobert   for (VarDecl *VD : llvm::reverse(DeclsTrivial))
1869*12c85518Srobert     appendLifetimeEnds(Block, VD, S);
1870e5dd7070Spatrick 
1871*12c85518Srobert   for (VarDecl *VD : llvm::reverse(DeclsNonTrivial))
1872*12c85518Srobert     appendLifetimeEnds(Block, VD, S);
1873e5dd7070Spatrick }
1874e5dd7070Spatrick 
1875e5dd7070Spatrick /// Add to current block markers for ending scopes.
addScopesEnd(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1876e5dd7070Spatrick void CFGBuilder::addScopesEnd(LocalScope::const_iterator B,
1877e5dd7070Spatrick                               LocalScope::const_iterator E, Stmt *S) {
1878e5dd7070Spatrick   // If implicit destructors are enabled, we'll add scope ends in
1879e5dd7070Spatrick   // addAutomaticObjDtors.
1880e5dd7070Spatrick   if (BuildOpts.AddImplicitDtors)
1881e5dd7070Spatrick     return;
1882e5dd7070Spatrick 
1883e5dd7070Spatrick   autoCreateBlock();
1884e5dd7070Spatrick 
1885*12c85518Srobert   for (VarDecl *VD : llvm::reverse(DeclsWithEndedScope))
1886*12c85518Srobert     appendScopeEnd(Block, VD, S);
1887e5dd7070Spatrick }
1888e5dd7070Spatrick 
1889e5dd7070Spatrick /// addAutomaticObjDtors - Add to current block automatic objects destructors
1890e5dd7070Spatrick /// for objects in range of local scope positions. Use S as trigger statement
1891e5dd7070Spatrick /// for destructors.
addAutomaticObjDtors(LocalScope::const_iterator B,LocalScope::const_iterator E,Stmt * S)1892e5dd7070Spatrick void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
1893e5dd7070Spatrick                                       LocalScope::const_iterator E, Stmt *S) {
1894e5dd7070Spatrick   if (!BuildOpts.AddImplicitDtors)
1895e5dd7070Spatrick     return;
1896e5dd7070Spatrick 
1897e5dd7070Spatrick   if (B == E)
1898e5dd7070Spatrick     return;
1899e5dd7070Spatrick 
1900e5dd7070Spatrick   // We need to append the destructors in reverse order, but any one of them
1901e5dd7070Spatrick   // may be a no-return destructor which changes the CFG. As a result, buffer
1902e5dd7070Spatrick   // this sequence up and replay them in reverse order when appending onto the
1903e5dd7070Spatrick   // CFGBlock(s).
1904e5dd7070Spatrick   SmallVector<VarDecl*, 10> Decls;
1905e5dd7070Spatrick   Decls.reserve(B.distance(E));
1906e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != E; ++I)
1907e5dd7070Spatrick     Decls.push_back(*I);
1908e5dd7070Spatrick 
1909*12c85518Srobert   for (VarDecl *VD : llvm::reverse(Decls)) {
1910*12c85518Srobert     if (hasTrivialDestructor(VD)) {
1911e5dd7070Spatrick       // If AddScopes is enabled and *I is a first variable in a scope, add a
1912e5dd7070Spatrick       // ScopeEnd marker in a Block.
1913*12c85518Srobert       if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD)) {
1914e5dd7070Spatrick         autoCreateBlock();
1915*12c85518Srobert         appendScopeEnd(Block, VD, S);
1916e5dd7070Spatrick       }
1917e5dd7070Spatrick       continue;
1918e5dd7070Spatrick     }
1919e5dd7070Spatrick     // If this destructor is marked as a no-return destructor, we need to
1920e5dd7070Spatrick     // create a new block for the destructor which does not have as a successor
1921e5dd7070Spatrick     // anything built thus far: control won't flow out of this block.
1922*12c85518Srobert     QualType Ty = VD->getType();
1923e5dd7070Spatrick     if (Ty->isReferenceType()) {
1924*12c85518Srobert       Ty = getReferenceInitTemporaryType(VD->getInit());
1925e5dd7070Spatrick     }
1926e5dd7070Spatrick     Ty = Context->getBaseElementType(Ty);
1927e5dd7070Spatrick 
1928e5dd7070Spatrick     if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
1929e5dd7070Spatrick       Block = createNoReturnBlock();
1930e5dd7070Spatrick     else
1931e5dd7070Spatrick       autoCreateBlock();
1932e5dd7070Spatrick 
1933e5dd7070Spatrick     // Add ScopeEnd just after automatic obj destructor.
1934*12c85518Srobert     if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD))
1935*12c85518Srobert       appendScopeEnd(Block, VD, S);
1936*12c85518Srobert     appendAutomaticObjDtor(Block, VD, S);
1937e5dd7070Spatrick   }
1938e5dd7070Spatrick }
1939e5dd7070Spatrick 
1940e5dd7070Spatrick /// addImplicitDtorsForDestructor - Add implicit destructors generated for
1941e5dd7070Spatrick /// base and member objects in destructor.
addImplicitDtorsForDestructor(const CXXDestructorDecl * DD)1942e5dd7070Spatrick void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
1943e5dd7070Spatrick   assert(BuildOpts.AddImplicitDtors &&
1944e5dd7070Spatrick          "Can be called only when dtors should be added");
1945e5dd7070Spatrick   const CXXRecordDecl *RD = DD->getParent();
1946e5dd7070Spatrick 
1947e5dd7070Spatrick   // At the end destroy virtual base objects.
1948e5dd7070Spatrick   for (const auto &VI : RD->vbases()) {
1949e5dd7070Spatrick     // TODO: Add a VirtualBaseBranch to see if the most derived class
1950e5dd7070Spatrick     // (which is different from the current class) is responsible for
1951e5dd7070Spatrick     // destroying them.
1952e5dd7070Spatrick     const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
1953*12c85518Srobert     if (CD && !CD->hasTrivialDestructor()) {
1954e5dd7070Spatrick       autoCreateBlock();
1955e5dd7070Spatrick       appendBaseDtor(Block, &VI);
1956e5dd7070Spatrick     }
1957e5dd7070Spatrick   }
1958e5dd7070Spatrick 
1959e5dd7070Spatrick   // Before virtual bases destroy direct base objects.
1960e5dd7070Spatrick   for (const auto &BI : RD->bases()) {
1961e5dd7070Spatrick     if (!BI.isVirtual()) {
1962e5dd7070Spatrick       const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
1963*12c85518Srobert       if (CD && !CD->hasTrivialDestructor()) {
1964e5dd7070Spatrick         autoCreateBlock();
1965e5dd7070Spatrick         appendBaseDtor(Block, &BI);
1966e5dd7070Spatrick       }
1967e5dd7070Spatrick     }
1968e5dd7070Spatrick   }
1969e5dd7070Spatrick 
1970e5dd7070Spatrick   // First destroy member objects.
1971e5dd7070Spatrick   for (auto *FI : RD->fields()) {
1972e5dd7070Spatrick     // Check for constant size array. Set type to array element type.
1973e5dd7070Spatrick     QualType QT = FI->getType();
1974*12c85518Srobert     // It may be a multidimensional array.
1975*12c85518Srobert     while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
1976e5dd7070Spatrick       if (AT->getSize() == 0)
1977*12c85518Srobert         break;
1978e5dd7070Spatrick       QT = AT->getElementType();
1979e5dd7070Spatrick     }
1980e5dd7070Spatrick 
1981e5dd7070Spatrick     if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
1982e5dd7070Spatrick       if (!CD->hasTrivialDestructor()) {
1983e5dd7070Spatrick         autoCreateBlock();
1984e5dd7070Spatrick         appendMemberDtor(Block, FI);
1985e5dd7070Spatrick       }
1986e5dd7070Spatrick   }
1987e5dd7070Spatrick }
1988e5dd7070Spatrick 
1989e5dd7070Spatrick /// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
1990e5dd7070Spatrick /// way return valid LocalScope object.
createOrReuseLocalScope(LocalScope * Scope)1991e5dd7070Spatrick LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
1992e5dd7070Spatrick   if (Scope)
1993e5dd7070Spatrick     return Scope;
1994e5dd7070Spatrick   llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
1995e5dd7070Spatrick   return new (alloc.Allocate<LocalScope>())
1996e5dd7070Spatrick       LocalScope(BumpVectorContext(alloc), ScopePos);
1997e5dd7070Spatrick }
1998e5dd7070Spatrick 
1999e5dd7070Spatrick /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
2000e5dd7070Spatrick /// that should create implicit scope (e.g. if/else substatements).
addLocalScopeForStmt(Stmt * S)2001e5dd7070Spatrick void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
2002e5dd7070Spatrick   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
2003e5dd7070Spatrick       !BuildOpts.AddScopes)
2004e5dd7070Spatrick     return;
2005e5dd7070Spatrick 
2006e5dd7070Spatrick   LocalScope *Scope = nullptr;
2007e5dd7070Spatrick 
2008e5dd7070Spatrick   // For compound statement we will be creating explicit scope.
2009e5dd7070Spatrick   if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
2010e5dd7070Spatrick     for (auto *BI : CS->body()) {
2011e5dd7070Spatrick       Stmt *SI = BI->stripLabelLikeStatements();
2012e5dd7070Spatrick       if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
2013e5dd7070Spatrick         Scope = addLocalScopeForDeclStmt(DS, Scope);
2014e5dd7070Spatrick     }
2015e5dd7070Spatrick     return;
2016e5dd7070Spatrick   }
2017e5dd7070Spatrick 
2018e5dd7070Spatrick   // For any other statement scope will be implicit and as such will be
2019e5dd7070Spatrick   // interesting only for DeclStmt.
2020e5dd7070Spatrick   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
2021e5dd7070Spatrick     addLocalScopeForDeclStmt(DS);
2022e5dd7070Spatrick }
2023e5dd7070Spatrick 
2024e5dd7070Spatrick /// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will
2025e5dd7070Spatrick /// reuse Scope if not NULL.
addLocalScopeForDeclStmt(DeclStmt * DS,LocalScope * Scope)2026e5dd7070Spatrick LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
2027e5dd7070Spatrick                                                  LocalScope* Scope) {
2028e5dd7070Spatrick   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
2029e5dd7070Spatrick       !BuildOpts.AddScopes)
2030e5dd7070Spatrick     return Scope;
2031e5dd7070Spatrick 
2032e5dd7070Spatrick   for (auto *DI : DS->decls())
2033e5dd7070Spatrick     if (VarDecl *VD = dyn_cast<VarDecl>(DI))
2034e5dd7070Spatrick       Scope = addLocalScopeForVarDecl(VD, Scope);
2035e5dd7070Spatrick   return Scope;
2036e5dd7070Spatrick }
2037e5dd7070Spatrick 
hasTrivialDestructor(VarDecl * VD)2038e5dd7070Spatrick bool CFGBuilder::hasTrivialDestructor(VarDecl *VD) {
2039e5dd7070Spatrick   // Check for const references bound to temporary. Set type to pointee.
2040e5dd7070Spatrick   QualType QT = VD->getType();
2041e5dd7070Spatrick   if (QT->isReferenceType()) {
2042e5dd7070Spatrick     // Attempt to determine whether this declaration lifetime-extends a
2043e5dd7070Spatrick     // temporary.
2044e5dd7070Spatrick     //
2045e5dd7070Spatrick     // FIXME: This is incorrect. Non-reference declarations can lifetime-extend
2046e5dd7070Spatrick     // temporaries, and a single declaration can extend multiple temporaries.
2047e5dd7070Spatrick     // We should look at the storage duration on each nested
2048e5dd7070Spatrick     // MaterializeTemporaryExpr instead.
2049e5dd7070Spatrick 
2050e5dd7070Spatrick     const Expr *Init = VD->getInit();
2051e5dd7070Spatrick     if (!Init) {
2052e5dd7070Spatrick       // Probably an exception catch-by-reference variable.
2053e5dd7070Spatrick       // FIXME: It doesn't really mean that the object has a trivial destructor.
2054e5dd7070Spatrick       // Also are there other cases?
2055e5dd7070Spatrick       return true;
2056e5dd7070Spatrick     }
2057e5dd7070Spatrick 
2058e5dd7070Spatrick     // Lifetime-extending a temporary?
2059e5dd7070Spatrick     bool FoundMTE = false;
2060e5dd7070Spatrick     QT = getReferenceInitTemporaryType(Init, &FoundMTE);
2061e5dd7070Spatrick     if (!FoundMTE)
2062e5dd7070Spatrick       return true;
2063e5dd7070Spatrick   }
2064e5dd7070Spatrick 
2065e5dd7070Spatrick   // Check for constant size array. Set type to array element type.
2066e5dd7070Spatrick   while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
2067e5dd7070Spatrick     if (AT->getSize() == 0)
2068e5dd7070Spatrick       return true;
2069e5dd7070Spatrick     QT = AT->getElementType();
2070e5dd7070Spatrick   }
2071e5dd7070Spatrick 
2072e5dd7070Spatrick   // Check if type is a C++ class with non-trivial destructor.
2073e5dd7070Spatrick   if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
2074e5dd7070Spatrick     return !CD->hasDefinition() || CD->hasTrivialDestructor();
2075e5dd7070Spatrick   return true;
2076e5dd7070Spatrick }
2077e5dd7070Spatrick 
2078e5dd7070Spatrick /// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will
2079e5dd7070Spatrick /// create add scope for automatic objects and temporary objects bound to
2080e5dd7070Spatrick /// const reference. Will reuse Scope if not NULL.
addLocalScopeForVarDecl(VarDecl * VD,LocalScope * Scope)2081e5dd7070Spatrick LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
2082e5dd7070Spatrick                                                 LocalScope* Scope) {
2083e5dd7070Spatrick   assert(!(BuildOpts.AddImplicitDtors && BuildOpts.AddLifetime) &&
2084e5dd7070Spatrick          "AddImplicitDtors and AddLifetime cannot be used at the same time");
2085e5dd7070Spatrick   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
2086e5dd7070Spatrick       !BuildOpts.AddScopes)
2087e5dd7070Spatrick     return Scope;
2088e5dd7070Spatrick 
2089e5dd7070Spatrick   // Check if variable is local.
2090*12c85518Srobert   if (!VD->hasLocalStorage())
2091*12c85518Srobert     return Scope;
2092e5dd7070Spatrick 
2093e5dd7070Spatrick   if (BuildOpts.AddImplicitDtors) {
2094e5dd7070Spatrick     if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
2095e5dd7070Spatrick       // Add the variable to scope
2096e5dd7070Spatrick       Scope = createOrReuseLocalScope(Scope);
2097e5dd7070Spatrick       Scope->addVar(VD);
2098e5dd7070Spatrick       ScopePos = Scope->begin();
2099e5dd7070Spatrick     }
2100e5dd7070Spatrick     return Scope;
2101e5dd7070Spatrick   }
2102e5dd7070Spatrick 
2103e5dd7070Spatrick   assert(BuildOpts.AddLifetime);
2104e5dd7070Spatrick   // Add the variable to scope
2105e5dd7070Spatrick   Scope = createOrReuseLocalScope(Scope);
2106e5dd7070Spatrick   Scope->addVar(VD);
2107e5dd7070Spatrick   ScopePos = Scope->begin();
2108e5dd7070Spatrick   return Scope;
2109e5dd7070Spatrick }
2110e5dd7070Spatrick 
2111e5dd7070Spatrick /// addLocalScopeAndDtors - For given statement add local scope for it and
2112e5dd7070Spatrick /// add destructors that will cleanup the scope. Will reuse Scope if not NULL.
addLocalScopeAndDtors(Stmt * S)2113e5dd7070Spatrick void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
2114e5dd7070Spatrick   LocalScope::const_iterator scopeBeginPos = ScopePos;
2115e5dd7070Spatrick   addLocalScopeForStmt(S);
2116e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
2117e5dd7070Spatrick }
2118e5dd7070Spatrick 
2119e5dd7070Spatrick /// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for
2120e5dd7070Spatrick /// variables with automatic storage duration to CFGBlock's elements vector.
2121e5dd7070Spatrick /// Elements will be prepended to physical beginning of the vector which
2122e5dd7070Spatrick /// happens to be logical end. Use blocks terminator as statement that specifies
2123e5dd7070Spatrick /// destructors call site.
2124e5dd7070Spatrick /// FIXME: This mechanism for adding automatic destructors doesn't handle
2125e5dd7070Spatrick /// no-return destructors properly.
prependAutomaticObjDtorsWithTerminator(CFGBlock * Blk,LocalScope::const_iterator B,LocalScope::const_iterator E)2126e5dd7070Spatrick void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
2127e5dd7070Spatrick     LocalScope::const_iterator B, LocalScope::const_iterator E) {
2128e5dd7070Spatrick   if (!BuildOpts.AddImplicitDtors)
2129e5dd7070Spatrick     return;
2130e5dd7070Spatrick   BumpVectorContext &C = cfg->getBumpVectorContext();
2131e5dd7070Spatrick   CFGBlock::iterator InsertPos
2132e5dd7070Spatrick     = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C);
2133e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != E; ++I)
2134e5dd7070Spatrick     InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I,
2135e5dd7070Spatrick                                             Blk->getTerminatorStmt());
2136e5dd7070Spatrick }
2137e5dd7070Spatrick 
2138e5dd7070Spatrick /// prependAutomaticObjLifetimeWithTerminator - Prepend lifetime CFGElements for
2139e5dd7070Spatrick /// variables with automatic storage duration to CFGBlock's elements vector.
2140e5dd7070Spatrick /// Elements will be prepended to physical beginning of the vector which
2141e5dd7070Spatrick /// happens to be logical end. Use blocks terminator as statement that specifies
2142e5dd7070Spatrick /// where lifetime ends.
prependAutomaticObjLifetimeWithTerminator(CFGBlock * Blk,LocalScope::const_iterator B,LocalScope::const_iterator E)2143e5dd7070Spatrick void CFGBuilder::prependAutomaticObjLifetimeWithTerminator(
2144e5dd7070Spatrick     CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2145e5dd7070Spatrick   if (!BuildOpts.AddLifetime)
2146e5dd7070Spatrick     return;
2147e5dd7070Spatrick   BumpVectorContext &C = cfg->getBumpVectorContext();
2148e5dd7070Spatrick   CFGBlock::iterator InsertPos =
2149e5dd7070Spatrick       Blk->beginLifetimeEndsInsert(Blk->end(), B.distance(E), C);
2150e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != E; ++I) {
2151e5dd7070Spatrick     InsertPos =
2152e5dd7070Spatrick         Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminatorStmt());
2153e5dd7070Spatrick   }
2154e5dd7070Spatrick }
2155e5dd7070Spatrick 
2156e5dd7070Spatrick /// prependAutomaticObjScopeEndWithTerminator - Prepend scope end CFGElements for
2157e5dd7070Spatrick /// variables with automatic storage duration to CFGBlock's elements vector.
2158e5dd7070Spatrick /// Elements will be prepended to physical beginning of the vector which
2159e5dd7070Spatrick /// happens to be logical end. Use blocks terminator as statement that specifies
2160e5dd7070Spatrick /// where scope ends.
2161e5dd7070Spatrick const VarDecl *
prependAutomaticObjScopeEndWithTerminator(CFGBlock * Blk,LocalScope::const_iterator B,LocalScope::const_iterator E)2162e5dd7070Spatrick CFGBuilder::prependAutomaticObjScopeEndWithTerminator(
2163e5dd7070Spatrick     CFGBlock *Blk, LocalScope::const_iterator B, LocalScope::const_iterator E) {
2164e5dd7070Spatrick   if (!BuildOpts.AddScopes)
2165e5dd7070Spatrick     return nullptr;
2166e5dd7070Spatrick   BumpVectorContext &C = cfg->getBumpVectorContext();
2167e5dd7070Spatrick   CFGBlock::iterator InsertPos =
2168e5dd7070Spatrick       Blk->beginScopeEndInsert(Blk->end(), 1, C);
2169e5dd7070Spatrick   LocalScope::const_iterator PlaceToInsert = B;
2170e5dd7070Spatrick   for (LocalScope::const_iterator I = B; I != E; ++I)
2171e5dd7070Spatrick     PlaceToInsert = I;
2172e5dd7070Spatrick   Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminatorStmt());
2173e5dd7070Spatrick   return *PlaceToInsert;
2174e5dd7070Spatrick }
2175e5dd7070Spatrick 
2176e5dd7070Spatrick /// Visit - Walk the subtree of a statement and add extra
2177e5dd7070Spatrick ///   blocks for ternary operators, &&, and ||.  We also process "," and
2178e5dd7070Spatrick ///   DeclStmts (which may contain nested control-flow).
Visit(Stmt * S,AddStmtChoice asc,bool ExternallyDestructed)2179e5dd7070Spatrick CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2180e5dd7070Spatrick                             bool ExternallyDestructed) {
2181e5dd7070Spatrick   if (!S) {
2182e5dd7070Spatrick     badCFG = true;
2183e5dd7070Spatrick     return nullptr;
2184e5dd7070Spatrick   }
2185e5dd7070Spatrick 
2186e5dd7070Spatrick   if (Expr *E = dyn_cast<Expr>(S))
2187e5dd7070Spatrick     S = E->IgnoreParens();
2188e5dd7070Spatrick 
2189e5dd7070Spatrick   if (Context->getLangOpts().OpenMP)
2190e5dd7070Spatrick     if (auto *D = dyn_cast<OMPExecutableDirective>(S))
2191e5dd7070Spatrick       return VisitOMPExecutableDirective(D, asc);
2192e5dd7070Spatrick 
2193e5dd7070Spatrick   switch (S->getStmtClass()) {
2194e5dd7070Spatrick     default:
2195e5dd7070Spatrick       return VisitStmt(S, asc);
2196e5dd7070Spatrick 
2197e5dd7070Spatrick     case Stmt::ImplicitValueInitExprClass:
2198e5dd7070Spatrick       if (BuildOpts.OmitImplicitValueInitializers)
2199e5dd7070Spatrick         return Block;
2200e5dd7070Spatrick       return VisitStmt(S, asc);
2201e5dd7070Spatrick 
2202e5dd7070Spatrick     case Stmt::InitListExprClass:
2203e5dd7070Spatrick       return VisitInitListExpr(cast<InitListExpr>(S), asc);
2204e5dd7070Spatrick 
2205*12c85518Srobert     case Stmt::AttributedStmtClass:
2206*12c85518Srobert       return VisitAttributedStmt(cast<AttributedStmt>(S), asc);
2207*12c85518Srobert 
2208e5dd7070Spatrick     case Stmt::AddrLabelExprClass:
2209e5dd7070Spatrick       return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
2210e5dd7070Spatrick 
2211e5dd7070Spatrick     case Stmt::BinaryConditionalOperatorClass:
2212e5dd7070Spatrick       return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
2213e5dd7070Spatrick 
2214e5dd7070Spatrick     case Stmt::BinaryOperatorClass:
2215e5dd7070Spatrick       return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
2216e5dd7070Spatrick 
2217e5dd7070Spatrick     case Stmt::BlockExprClass:
2218e5dd7070Spatrick       return VisitBlockExpr(cast<BlockExpr>(S), asc);
2219e5dd7070Spatrick 
2220e5dd7070Spatrick     case Stmt::BreakStmtClass:
2221e5dd7070Spatrick       return VisitBreakStmt(cast<BreakStmt>(S));
2222e5dd7070Spatrick 
2223e5dd7070Spatrick     case Stmt::CallExprClass:
2224e5dd7070Spatrick     case Stmt::CXXOperatorCallExprClass:
2225e5dd7070Spatrick     case Stmt::CXXMemberCallExprClass:
2226e5dd7070Spatrick     case Stmt::UserDefinedLiteralClass:
2227e5dd7070Spatrick       return VisitCallExpr(cast<CallExpr>(S), asc);
2228e5dd7070Spatrick 
2229e5dd7070Spatrick     case Stmt::CaseStmtClass:
2230e5dd7070Spatrick       return VisitCaseStmt(cast<CaseStmt>(S));
2231e5dd7070Spatrick 
2232e5dd7070Spatrick     case Stmt::ChooseExprClass:
2233e5dd7070Spatrick       return VisitChooseExpr(cast<ChooseExpr>(S), asc);
2234e5dd7070Spatrick 
2235e5dd7070Spatrick     case Stmt::CompoundStmtClass:
2236e5dd7070Spatrick       return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
2237e5dd7070Spatrick 
2238e5dd7070Spatrick     case Stmt::ConditionalOperatorClass:
2239e5dd7070Spatrick       return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
2240e5dd7070Spatrick 
2241e5dd7070Spatrick     case Stmt::ContinueStmtClass:
2242e5dd7070Spatrick       return VisitContinueStmt(cast<ContinueStmt>(S));
2243e5dd7070Spatrick 
2244e5dd7070Spatrick     case Stmt::CXXCatchStmtClass:
2245e5dd7070Spatrick       return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
2246e5dd7070Spatrick 
2247e5dd7070Spatrick     case Stmt::ExprWithCleanupsClass:
2248e5dd7070Spatrick       return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2249e5dd7070Spatrick                                    asc, ExternallyDestructed);
2250e5dd7070Spatrick 
2251e5dd7070Spatrick     case Stmt::CXXDefaultArgExprClass:
2252e5dd7070Spatrick     case Stmt::CXXDefaultInitExprClass:
2253e5dd7070Spatrick       // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
2254e5dd7070Spatrick       // called function's declaration, not by the caller. If we simply add
2255e5dd7070Spatrick       // this expression to the CFG, we could end up with the same Expr
2256e5dd7070Spatrick       // appearing multiple times.
2257e5dd7070Spatrick       // PR13385 / <rdar://problem/12156507>
2258e5dd7070Spatrick       //
2259e5dd7070Spatrick       // It's likewise possible for multiple CXXDefaultInitExprs for the same
2260e5dd7070Spatrick       // expression to be used in the same function (through aggregate
2261e5dd7070Spatrick       // initialization).
2262e5dd7070Spatrick       return VisitStmt(S, asc);
2263e5dd7070Spatrick 
2264e5dd7070Spatrick     case Stmt::CXXBindTemporaryExprClass:
2265e5dd7070Spatrick       return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
2266e5dd7070Spatrick 
2267e5dd7070Spatrick     case Stmt::CXXConstructExprClass:
2268e5dd7070Spatrick       return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
2269e5dd7070Spatrick 
2270e5dd7070Spatrick     case Stmt::CXXNewExprClass:
2271e5dd7070Spatrick       return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
2272e5dd7070Spatrick 
2273e5dd7070Spatrick     case Stmt::CXXDeleteExprClass:
2274e5dd7070Spatrick       return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
2275e5dd7070Spatrick 
2276e5dd7070Spatrick     case Stmt::CXXFunctionalCastExprClass:
2277e5dd7070Spatrick       return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
2278e5dd7070Spatrick 
2279e5dd7070Spatrick     case Stmt::CXXTemporaryObjectExprClass:
2280e5dd7070Spatrick       return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
2281e5dd7070Spatrick 
2282e5dd7070Spatrick     case Stmt::CXXThrowExprClass:
2283e5dd7070Spatrick       return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
2284e5dd7070Spatrick 
2285e5dd7070Spatrick     case Stmt::CXXTryStmtClass:
2286e5dd7070Spatrick       return VisitCXXTryStmt(cast<CXXTryStmt>(S));
2287e5dd7070Spatrick 
2288*12c85518Srobert     case Stmt::CXXTypeidExprClass:
2289*12c85518Srobert       return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);
2290*12c85518Srobert 
2291e5dd7070Spatrick     case Stmt::CXXForRangeStmtClass:
2292e5dd7070Spatrick       return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
2293e5dd7070Spatrick 
2294e5dd7070Spatrick     case Stmt::DeclStmtClass:
2295e5dd7070Spatrick       return VisitDeclStmt(cast<DeclStmt>(S));
2296e5dd7070Spatrick 
2297e5dd7070Spatrick     case Stmt::DefaultStmtClass:
2298e5dd7070Spatrick       return VisitDefaultStmt(cast<DefaultStmt>(S));
2299e5dd7070Spatrick 
2300e5dd7070Spatrick     case Stmt::DoStmtClass:
2301e5dd7070Spatrick       return VisitDoStmt(cast<DoStmt>(S));
2302e5dd7070Spatrick 
2303e5dd7070Spatrick     case Stmt::ForStmtClass:
2304e5dd7070Spatrick       return VisitForStmt(cast<ForStmt>(S));
2305e5dd7070Spatrick 
2306e5dd7070Spatrick     case Stmt::GotoStmtClass:
2307e5dd7070Spatrick       return VisitGotoStmt(cast<GotoStmt>(S));
2308e5dd7070Spatrick 
2309e5dd7070Spatrick     case Stmt::GCCAsmStmtClass:
2310e5dd7070Spatrick       return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
2311e5dd7070Spatrick 
2312e5dd7070Spatrick     case Stmt::IfStmtClass:
2313e5dd7070Spatrick       return VisitIfStmt(cast<IfStmt>(S));
2314e5dd7070Spatrick 
2315e5dd7070Spatrick     case Stmt::ImplicitCastExprClass:
2316e5dd7070Spatrick       return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
2317e5dd7070Spatrick 
2318e5dd7070Spatrick     case Stmt::ConstantExprClass:
2319e5dd7070Spatrick       return VisitConstantExpr(cast<ConstantExpr>(S), asc);
2320e5dd7070Spatrick 
2321e5dd7070Spatrick     case Stmt::IndirectGotoStmtClass:
2322e5dd7070Spatrick       return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
2323e5dd7070Spatrick 
2324e5dd7070Spatrick     case Stmt::LabelStmtClass:
2325e5dd7070Spatrick       return VisitLabelStmt(cast<LabelStmt>(S));
2326e5dd7070Spatrick 
2327e5dd7070Spatrick     case Stmt::LambdaExprClass:
2328e5dd7070Spatrick       return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
2329e5dd7070Spatrick 
2330e5dd7070Spatrick     case Stmt::MaterializeTemporaryExprClass:
2331e5dd7070Spatrick       return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
2332e5dd7070Spatrick                                            asc);
2333e5dd7070Spatrick 
2334e5dd7070Spatrick     case Stmt::MemberExprClass:
2335e5dd7070Spatrick       return VisitMemberExpr(cast<MemberExpr>(S), asc);
2336e5dd7070Spatrick 
2337e5dd7070Spatrick     case Stmt::NullStmtClass:
2338e5dd7070Spatrick       return Block;
2339e5dd7070Spatrick 
2340e5dd7070Spatrick     case Stmt::ObjCAtCatchStmtClass:
2341e5dd7070Spatrick       return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
2342e5dd7070Spatrick 
2343e5dd7070Spatrick     case Stmt::ObjCAutoreleasePoolStmtClass:
2344e5dd7070Spatrick       return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
2345e5dd7070Spatrick 
2346e5dd7070Spatrick     case Stmt::ObjCAtSynchronizedStmtClass:
2347e5dd7070Spatrick       return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
2348e5dd7070Spatrick 
2349e5dd7070Spatrick     case Stmt::ObjCAtThrowStmtClass:
2350e5dd7070Spatrick       return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
2351e5dd7070Spatrick 
2352e5dd7070Spatrick     case Stmt::ObjCAtTryStmtClass:
2353e5dd7070Spatrick       return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
2354e5dd7070Spatrick 
2355e5dd7070Spatrick     case Stmt::ObjCForCollectionStmtClass:
2356e5dd7070Spatrick       return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
2357e5dd7070Spatrick 
2358e5dd7070Spatrick     case Stmt::ObjCMessageExprClass:
2359e5dd7070Spatrick       return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
2360e5dd7070Spatrick 
2361e5dd7070Spatrick     case Stmt::OpaqueValueExprClass:
2362e5dd7070Spatrick       return Block;
2363e5dd7070Spatrick 
2364e5dd7070Spatrick     case Stmt::PseudoObjectExprClass:
2365e5dd7070Spatrick       return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
2366e5dd7070Spatrick 
2367e5dd7070Spatrick     case Stmt::ReturnStmtClass:
2368e5dd7070Spatrick     case Stmt::CoreturnStmtClass:
2369e5dd7070Spatrick       return VisitReturnStmt(S);
2370e5dd7070Spatrick 
2371*12c85518Srobert     case Stmt::CoyieldExprClass:
2372*12c85518Srobert     case Stmt::CoawaitExprClass:
2373*12c85518Srobert       return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
2374*12c85518Srobert 
2375e5dd7070Spatrick     case Stmt::SEHExceptStmtClass:
2376e5dd7070Spatrick       return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
2377e5dd7070Spatrick 
2378e5dd7070Spatrick     case Stmt::SEHFinallyStmtClass:
2379e5dd7070Spatrick       return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
2380e5dd7070Spatrick 
2381e5dd7070Spatrick     case Stmt::SEHLeaveStmtClass:
2382e5dd7070Spatrick       return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
2383e5dd7070Spatrick 
2384e5dd7070Spatrick     case Stmt::SEHTryStmtClass:
2385e5dd7070Spatrick       return VisitSEHTryStmt(cast<SEHTryStmt>(S));
2386e5dd7070Spatrick 
2387e5dd7070Spatrick     case Stmt::UnaryExprOrTypeTraitExprClass:
2388e5dd7070Spatrick       return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
2389e5dd7070Spatrick                                            asc);
2390e5dd7070Spatrick 
2391e5dd7070Spatrick     case Stmt::StmtExprClass:
2392e5dd7070Spatrick       return VisitStmtExpr(cast<StmtExpr>(S), asc);
2393e5dd7070Spatrick 
2394e5dd7070Spatrick     case Stmt::SwitchStmtClass:
2395e5dd7070Spatrick       return VisitSwitchStmt(cast<SwitchStmt>(S));
2396e5dd7070Spatrick 
2397e5dd7070Spatrick     case Stmt::UnaryOperatorClass:
2398e5dd7070Spatrick       return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
2399e5dd7070Spatrick 
2400e5dd7070Spatrick     case Stmt::WhileStmtClass:
2401e5dd7070Spatrick       return VisitWhileStmt(cast<WhileStmt>(S));
2402*12c85518Srobert 
2403*12c85518Srobert     case Stmt::ArrayInitLoopExprClass:
2404*12c85518Srobert       return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);
2405e5dd7070Spatrick   }
2406e5dd7070Spatrick }
2407e5dd7070Spatrick 
VisitStmt(Stmt * S,AddStmtChoice asc)2408e5dd7070Spatrick CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
2409e5dd7070Spatrick   if (asc.alwaysAdd(*this, S)) {
2410e5dd7070Spatrick     autoCreateBlock();
2411e5dd7070Spatrick     appendStmt(Block, S);
2412e5dd7070Spatrick   }
2413e5dd7070Spatrick 
2414e5dd7070Spatrick   return VisitChildren(S);
2415e5dd7070Spatrick }
2416e5dd7070Spatrick 
2417e5dd7070Spatrick /// VisitChildren - Visit the children of a Stmt.
VisitChildren(Stmt * S)2418e5dd7070Spatrick CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
2419e5dd7070Spatrick   CFGBlock *B = Block;
2420e5dd7070Spatrick 
2421e5dd7070Spatrick   // Visit the children in their reverse order so that they appear in
2422e5dd7070Spatrick   // left-to-right (natural) order in the CFG.
2423e5dd7070Spatrick   reverse_children RChildren(S);
2424e5dd7070Spatrick   for (Stmt *Child : RChildren) {
2425e5dd7070Spatrick     if (Child)
2426e5dd7070Spatrick       if (CFGBlock *R = Visit(Child))
2427e5dd7070Spatrick         B = R;
2428e5dd7070Spatrick   }
2429e5dd7070Spatrick   return B;
2430e5dd7070Spatrick }
2431e5dd7070Spatrick 
VisitInitListExpr(InitListExpr * ILE,AddStmtChoice asc)2432e5dd7070Spatrick CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2433e5dd7070Spatrick   if (asc.alwaysAdd(*this, ILE)) {
2434e5dd7070Spatrick     autoCreateBlock();
2435e5dd7070Spatrick     appendStmt(Block, ILE);
2436e5dd7070Spatrick   }
2437e5dd7070Spatrick   CFGBlock *B = Block;
2438e5dd7070Spatrick 
2439e5dd7070Spatrick   reverse_children RChildren(ILE);
2440e5dd7070Spatrick   for (Stmt *Child : RChildren) {
2441e5dd7070Spatrick     if (!Child)
2442e5dd7070Spatrick       continue;
2443e5dd7070Spatrick     if (CFGBlock *R = Visit(Child))
2444e5dd7070Spatrick       B = R;
2445e5dd7070Spatrick     if (BuildOpts.AddCXXDefaultInitExprInAggregates) {
2446e5dd7070Spatrick       if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2447e5dd7070Spatrick         if (Stmt *Child = DIE->getExpr())
2448e5dd7070Spatrick           if (CFGBlock *R = Visit(Child))
2449e5dd7070Spatrick             B = R;
2450e5dd7070Spatrick     }
2451e5dd7070Spatrick   }
2452e5dd7070Spatrick   return B;
2453e5dd7070Spatrick }
2454e5dd7070Spatrick 
VisitAddrLabelExpr(AddrLabelExpr * A,AddStmtChoice asc)2455e5dd7070Spatrick CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
2456e5dd7070Spatrick                                          AddStmtChoice asc) {
2457e5dd7070Spatrick   AddressTakenLabels.insert(A->getLabel());
2458e5dd7070Spatrick 
2459e5dd7070Spatrick   if (asc.alwaysAdd(*this, A)) {
2460e5dd7070Spatrick     autoCreateBlock();
2461e5dd7070Spatrick     appendStmt(Block, A);
2462e5dd7070Spatrick   }
2463e5dd7070Spatrick 
2464e5dd7070Spatrick   return Block;
2465e5dd7070Spatrick }
2466e5dd7070Spatrick 
isFallthroughStatement(const AttributedStmt * A)2467*12c85518Srobert static bool isFallthroughStatement(const AttributedStmt *A) {
2468*12c85518Srobert   bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->getAttrs());
2469*12c85518Srobert   assert((!isFallthrough || isa<NullStmt>(A->getSubStmt())) &&
2470*12c85518Srobert          "expected fallthrough not to have children");
2471*12c85518Srobert   return isFallthrough;
2472*12c85518Srobert }
2473*12c85518Srobert 
VisitAttributedStmt(AttributedStmt * A,AddStmtChoice asc)2474*12c85518Srobert CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
2475e5dd7070Spatrick                                           AddStmtChoice asc) {
2476*12c85518Srobert   // AttributedStmts for [[likely]] can have arbitrary statements as children,
2477*12c85518Srobert   // and the current visitation order here would add the AttributedStmts
2478*12c85518Srobert   // for [[likely]] after the child nodes, which is undesirable: For example,
2479*12c85518Srobert   // if the child contains an unconditional return, the [[likely]] would be
2480*12c85518Srobert   // considered unreachable.
2481*12c85518Srobert   // So only add the AttributedStmt for FallThrough, which has CFG effects and
2482*12c85518Srobert   // also no children, and omit the others. None of the other current StmtAttrs
2483*12c85518Srobert   // have semantic meaning for the CFG.
2484*12c85518Srobert   if (isFallthroughStatement(A) && asc.alwaysAdd(*this, A)) {
2485*12c85518Srobert     autoCreateBlock();
2486*12c85518Srobert     appendStmt(Block, A);
2487*12c85518Srobert   }
2488*12c85518Srobert 
2489*12c85518Srobert   return VisitChildren(A);
2490*12c85518Srobert }
2491*12c85518Srobert 
VisitUnaryOperator(UnaryOperator * U,AddStmtChoice asc)2492*12c85518Srobert CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
2493e5dd7070Spatrick   if (asc.alwaysAdd(*this, U)) {
2494e5dd7070Spatrick     autoCreateBlock();
2495e5dd7070Spatrick     appendStmt(Block, U);
2496e5dd7070Spatrick   }
2497e5dd7070Spatrick 
2498e5dd7070Spatrick   if (U->getOpcode() == UO_LNot)
2499e5dd7070Spatrick     tryEvaluateBool(U->getSubExpr()->IgnoreParens());
2500e5dd7070Spatrick 
2501e5dd7070Spatrick   return Visit(U->getSubExpr(), AddStmtChoice());
2502e5dd7070Spatrick }
2503e5dd7070Spatrick 
VisitLogicalOperator(BinaryOperator * B)2504e5dd7070Spatrick CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
2505e5dd7070Spatrick   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2506e5dd7070Spatrick   appendStmt(ConfluenceBlock, B);
2507e5dd7070Spatrick 
2508e5dd7070Spatrick   if (badCFG)
2509e5dd7070Spatrick     return nullptr;
2510e5dd7070Spatrick 
2511e5dd7070Spatrick   return VisitLogicalOperator(B, nullptr, ConfluenceBlock,
2512e5dd7070Spatrick                               ConfluenceBlock).first;
2513e5dd7070Spatrick }
2514e5dd7070Spatrick 
2515e5dd7070Spatrick std::pair<CFGBlock*, CFGBlock*>
VisitLogicalOperator(BinaryOperator * B,Stmt * Term,CFGBlock * TrueBlock,CFGBlock * FalseBlock)2516e5dd7070Spatrick CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
2517e5dd7070Spatrick                                  Stmt *Term,
2518e5dd7070Spatrick                                  CFGBlock *TrueBlock,
2519e5dd7070Spatrick                                  CFGBlock *FalseBlock) {
2520e5dd7070Spatrick   // Introspect the RHS.  If it is a nested logical operation, we recursively
2521e5dd7070Spatrick   // build the CFG using this function.  Otherwise, resort to default
2522e5dd7070Spatrick   // CFG construction behavior.
2523e5dd7070Spatrick   Expr *RHS = B->getRHS()->IgnoreParens();
2524e5dd7070Spatrick   CFGBlock *RHSBlock, *ExitBlock;
2525e5dd7070Spatrick 
2526e5dd7070Spatrick   do {
2527e5dd7070Spatrick     if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
2528e5dd7070Spatrick       if (B_RHS->isLogicalOp()) {
2529e5dd7070Spatrick         std::tie(RHSBlock, ExitBlock) =
2530e5dd7070Spatrick           VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
2531e5dd7070Spatrick         break;
2532e5dd7070Spatrick       }
2533e5dd7070Spatrick 
2534e5dd7070Spatrick     // The RHS is not a nested logical operation.  Don't push the terminator
2535e5dd7070Spatrick     // down further, but instead visit RHS and construct the respective
2536e5dd7070Spatrick     // pieces of the CFG, and link up the RHSBlock with the terminator
2537e5dd7070Spatrick     // we have been provided.
2538e5dd7070Spatrick     ExitBlock = RHSBlock = createBlock(false);
2539e5dd7070Spatrick 
2540e5dd7070Spatrick     // Even though KnownVal is only used in the else branch of the next
2541e5dd7070Spatrick     // conditional, tryEvaluateBool performs additional checking on the
2542e5dd7070Spatrick     // Expr, so it should be called unconditionally.
2543e5dd7070Spatrick     TryResult KnownVal = tryEvaluateBool(RHS);
2544e5dd7070Spatrick     if (!KnownVal.isKnown())
2545e5dd7070Spatrick       KnownVal = tryEvaluateBool(B);
2546e5dd7070Spatrick 
2547e5dd7070Spatrick     if (!Term) {
2548e5dd7070Spatrick       assert(TrueBlock == FalseBlock);
2549e5dd7070Spatrick       addSuccessor(RHSBlock, TrueBlock);
2550e5dd7070Spatrick     }
2551e5dd7070Spatrick     else {
2552e5dd7070Spatrick       RHSBlock->setTerminator(Term);
2553e5dd7070Spatrick       addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
2554e5dd7070Spatrick       addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
2555e5dd7070Spatrick     }
2556e5dd7070Spatrick 
2557e5dd7070Spatrick     Block = RHSBlock;
2558e5dd7070Spatrick     RHSBlock = addStmt(RHS);
2559e5dd7070Spatrick   }
2560e5dd7070Spatrick   while (false);
2561e5dd7070Spatrick 
2562e5dd7070Spatrick   if (badCFG)
2563e5dd7070Spatrick     return std::make_pair(nullptr, nullptr);
2564e5dd7070Spatrick 
2565e5dd7070Spatrick   // Generate the blocks for evaluating the LHS.
2566e5dd7070Spatrick   Expr *LHS = B->getLHS()->IgnoreParens();
2567e5dd7070Spatrick 
2568e5dd7070Spatrick   if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
2569e5dd7070Spatrick     if (B_LHS->isLogicalOp()) {
2570e5dd7070Spatrick       if (B->getOpcode() == BO_LOr)
2571e5dd7070Spatrick         FalseBlock = RHSBlock;
2572e5dd7070Spatrick       else
2573e5dd7070Spatrick         TrueBlock = RHSBlock;
2574e5dd7070Spatrick 
2575e5dd7070Spatrick       // For the LHS, treat 'B' as the terminator that we want to sink
2576e5dd7070Spatrick       // into the nested branch.  The RHS always gets the top-most
2577e5dd7070Spatrick       // terminator.
2578e5dd7070Spatrick       return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
2579e5dd7070Spatrick     }
2580e5dd7070Spatrick 
2581e5dd7070Spatrick   // Create the block evaluating the LHS.
2582e5dd7070Spatrick   // This contains the '&&' or '||' as the terminator.
2583e5dd7070Spatrick   CFGBlock *LHSBlock = createBlock(false);
2584e5dd7070Spatrick   LHSBlock->setTerminator(B);
2585e5dd7070Spatrick 
2586e5dd7070Spatrick   Block = LHSBlock;
2587e5dd7070Spatrick   CFGBlock *EntryLHSBlock = addStmt(LHS);
2588e5dd7070Spatrick 
2589e5dd7070Spatrick   if (badCFG)
2590e5dd7070Spatrick     return std::make_pair(nullptr, nullptr);
2591e5dd7070Spatrick 
2592e5dd7070Spatrick   // See if this is a known constant.
2593e5dd7070Spatrick   TryResult KnownVal = tryEvaluateBool(LHS);
2594e5dd7070Spatrick 
2595e5dd7070Spatrick   // Now link the LHSBlock with RHSBlock.
2596e5dd7070Spatrick   if (B->getOpcode() == BO_LOr) {
2597e5dd7070Spatrick     addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
2598e5dd7070Spatrick     addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
2599e5dd7070Spatrick   } else {
2600e5dd7070Spatrick     assert(B->getOpcode() == BO_LAnd);
2601e5dd7070Spatrick     addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
2602e5dd7070Spatrick     addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
2603e5dd7070Spatrick   }
2604e5dd7070Spatrick 
2605e5dd7070Spatrick   return std::make_pair(EntryLHSBlock, ExitBlock);
2606e5dd7070Spatrick }
2607e5dd7070Spatrick 
VisitBinaryOperator(BinaryOperator * B,AddStmtChoice asc)2608e5dd7070Spatrick CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
2609e5dd7070Spatrick                                           AddStmtChoice asc) {
2610e5dd7070Spatrick    // && or ||
2611e5dd7070Spatrick   if (B->isLogicalOp())
2612e5dd7070Spatrick     return VisitLogicalOperator(B);
2613e5dd7070Spatrick 
2614e5dd7070Spatrick   if (B->getOpcode() == BO_Comma) { // ,
2615e5dd7070Spatrick     autoCreateBlock();
2616e5dd7070Spatrick     appendStmt(Block, B);
2617e5dd7070Spatrick     addStmt(B->getRHS());
2618e5dd7070Spatrick     return addStmt(B->getLHS());
2619e5dd7070Spatrick   }
2620e5dd7070Spatrick 
2621e5dd7070Spatrick   if (B->isAssignmentOp()) {
2622e5dd7070Spatrick     if (asc.alwaysAdd(*this, B)) {
2623e5dd7070Spatrick       autoCreateBlock();
2624e5dd7070Spatrick       appendStmt(Block, B);
2625e5dd7070Spatrick     }
2626e5dd7070Spatrick     Visit(B->getLHS());
2627e5dd7070Spatrick     return Visit(B->getRHS());
2628e5dd7070Spatrick   }
2629e5dd7070Spatrick 
2630e5dd7070Spatrick   if (asc.alwaysAdd(*this, B)) {
2631e5dd7070Spatrick     autoCreateBlock();
2632e5dd7070Spatrick     appendStmt(Block, B);
2633e5dd7070Spatrick   }
2634e5dd7070Spatrick 
2635e5dd7070Spatrick   if (B->isEqualityOp() || B->isRelationalOp())
2636e5dd7070Spatrick     tryEvaluateBool(B);
2637e5dd7070Spatrick 
2638e5dd7070Spatrick   CFGBlock *RBlock = Visit(B->getRHS());
2639e5dd7070Spatrick   CFGBlock *LBlock = Visit(B->getLHS());
2640e5dd7070Spatrick   // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
2641e5dd7070Spatrick   // containing a DoStmt, and the LHS doesn't create a new block, then we should
2642e5dd7070Spatrick   // return RBlock.  Otherwise we'll incorrectly return NULL.
2643e5dd7070Spatrick   return (LBlock ? LBlock : RBlock);
2644e5dd7070Spatrick }
2645e5dd7070Spatrick 
VisitNoRecurse(Expr * E,AddStmtChoice asc)2646e5dd7070Spatrick CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
2647e5dd7070Spatrick   if (asc.alwaysAdd(*this, E)) {
2648e5dd7070Spatrick     autoCreateBlock();
2649e5dd7070Spatrick     appendStmt(Block, E);
2650e5dd7070Spatrick   }
2651e5dd7070Spatrick   return Block;
2652e5dd7070Spatrick }
2653e5dd7070Spatrick 
VisitBreakStmt(BreakStmt * B)2654e5dd7070Spatrick CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
2655e5dd7070Spatrick   // "break" is a control-flow statement.  Thus we stop processing the current
2656e5dd7070Spatrick   // block.
2657e5dd7070Spatrick   if (badCFG)
2658e5dd7070Spatrick     return nullptr;
2659e5dd7070Spatrick 
2660e5dd7070Spatrick   // Now create a new block that ends with the break statement.
2661e5dd7070Spatrick   Block = createBlock(false);
2662e5dd7070Spatrick   Block->setTerminator(B);
2663e5dd7070Spatrick 
2664e5dd7070Spatrick   // If there is no target for the break, then we are looking at an incomplete
2665e5dd7070Spatrick   // AST.  This means that the CFG cannot be constructed.
2666e5dd7070Spatrick   if (BreakJumpTarget.block) {
2667e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
2668e5dd7070Spatrick     addSuccessor(Block, BreakJumpTarget.block);
2669e5dd7070Spatrick   } else
2670e5dd7070Spatrick     badCFG = true;
2671e5dd7070Spatrick 
2672e5dd7070Spatrick   return Block;
2673e5dd7070Spatrick }
2674e5dd7070Spatrick 
CanThrow(Expr * E,ASTContext & Ctx)2675e5dd7070Spatrick static bool CanThrow(Expr *E, ASTContext &Ctx) {
2676e5dd7070Spatrick   QualType Ty = E->getType();
2677e5dd7070Spatrick   if (Ty->isFunctionPointerType() || Ty->isBlockPointerType())
2678e5dd7070Spatrick     Ty = Ty->getPointeeType();
2679e5dd7070Spatrick 
2680e5dd7070Spatrick   const FunctionType *FT = Ty->getAs<FunctionType>();
2681e5dd7070Spatrick   if (FT) {
2682e5dd7070Spatrick     if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
2683e5dd7070Spatrick       if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&
2684e5dd7070Spatrick           Proto->isNothrow())
2685e5dd7070Spatrick         return false;
2686e5dd7070Spatrick   }
2687e5dd7070Spatrick   return true;
2688e5dd7070Spatrick }
2689e5dd7070Spatrick 
VisitCallExpr(CallExpr * C,AddStmtChoice asc)2690e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
2691e5dd7070Spatrick   // Compute the callee type.
2692e5dd7070Spatrick   QualType calleeType = C->getCallee()->getType();
2693e5dd7070Spatrick   if (calleeType == Context->BoundMemberTy) {
2694e5dd7070Spatrick     QualType boundType = Expr::findBoundMemberType(C->getCallee());
2695e5dd7070Spatrick 
2696e5dd7070Spatrick     // We should only get a null bound type if processing a dependent
2697e5dd7070Spatrick     // CFG.  Recover by assuming nothing.
2698e5dd7070Spatrick     if (!boundType.isNull()) calleeType = boundType;
2699e5dd7070Spatrick   }
2700e5dd7070Spatrick 
2701e5dd7070Spatrick   // If this is a call to a no-return function, this stops the block here.
2702e5dd7070Spatrick   bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
2703e5dd7070Spatrick 
2704e5dd7070Spatrick   bool AddEHEdge = false;
2705e5dd7070Spatrick 
2706e5dd7070Spatrick   // Languages without exceptions are assumed to not throw.
2707e5dd7070Spatrick   if (Context->getLangOpts().Exceptions) {
2708e5dd7070Spatrick     if (BuildOpts.AddEHEdges)
2709e5dd7070Spatrick       AddEHEdge = true;
2710e5dd7070Spatrick   }
2711e5dd7070Spatrick 
2712e5dd7070Spatrick   // If this is a call to a builtin function, it might not actually evaluate
2713e5dd7070Spatrick   // its arguments. Don't add them to the CFG if this is the case.
2714e5dd7070Spatrick   bool OmitArguments = false;
2715e5dd7070Spatrick 
2716e5dd7070Spatrick   if (FunctionDecl *FD = C->getDirectCallee()) {
2717e5dd7070Spatrick     // TODO: Support construction contexts for variadic function arguments.
2718e5dd7070Spatrick     // These are a bit problematic and not very useful because passing
2719e5dd7070Spatrick     // C++ objects as C-style variadic arguments doesn't work in general
2720e5dd7070Spatrick     // (see [expr.call]).
2721e5dd7070Spatrick     if (!FD->isVariadic())
2722e5dd7070Spatrick       findConstructionContextsForArguments(C);
2723e5dd7070Spatrick 
2724e5dd7070Spatrick     if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))
2725e5dd7070Spatrick       NoReturn = true;
2726e5dd7070Spatrick     if (FD->hasAttr<NoThrowAttr>())
2727e5dd7070Spatrick       AddEHEdge = false;
2728e5dd7070Spatrick     if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
2729e5dd7070Spatrick         FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
2730e5dd7070Spatrick       OmitArguments = true;
2731e5dd7070Spatrick   }
2732e5dd7070Spatrick 
2733e5dd7070Spatrick   if (!CanThrow(C->getCallee(), *Context))
2734e5dd7070Spatrick     AddEHEdge = false;
2735e5dd7070Spatrick 
2736e5dd7070Spatrick   if (OmitArguments) {
2737e5dd7070Spatrick     assert(!NoReturn && "noreturn calls with unevaluated args not implemented");
2738e5dd7070Spatrick     assert(!AddEHEdge && "EH calls with unevaluated args not implemented");
2739e5dd7070Spatrick     autoCreateBlock();
2740e5dd7070Spatrick     appendStmt(Block, C);
2741e5dd7070Spatrick     return Visit(C->getCallee());
2742e5dd7070Spatrick   }
2743e5dd7070Spatrick 
2744e5dd7070Spatrick   if (!NoReturn && !AddEHEdge) {
2745e5dd7070Spatrick     autoCreateBlock();
2746e5dd7070Spatrick     appendCall(Block, C);
2747e5dd7070Spatrick 
2748e5dd7070Spatrick     return VisitChildren(C);
2749e5dd7070Spatrick   }
2750e5dd7070Spatrick 
2751e5dd7070Spatrick   if (Block) {
2752e5dd7070Spatrick     Succ = Block;
2753e5dd7070Spatrick     if (badCFG)
2754e5dd7070Spatrick       return nullptr;
2755e5dd7070Spatrick   }
2756e5dd7070Spatrick 
2757e5dd7070Spatrick   if (NoReturn)
2758e5dd7070Spatrick     Block = createNoReturnBlock();
2759e5dd7070Spatrick   else
2760e5dd7070Spatrick     Block = createBlock();
2761e5dd7070Spatrick 
2762e5dd7070Spatrick   appendCall(Block, C);
2763e5dd7070Spatrick 
2764e5dd7070Spatrick   if (AddEHEdge) {
2765e5dd7070Spatrick     // Add exceptional edges.
2766e5dd7070Spatrick     if (TryTerminatedBlock)
2767e5dd7070Spatrick       addSuccessor(Block, TryTerminatedBlock);
2768e5dd7070Spatrick     else
2769e5dd7070Spatrick       addSuccessor(Block, &cfg->getExit());
2770e5dd7070Spatrick   }
2771e5dd7070Spatrick 
2772e5dd7070Spatrick   return VisitChildren(C);
2773e5dd7070Spatrick }
2774e5dd7070Spatrick 
VisitChooseExpr(ChooseExpr * C,AddStmtChoice asc)2775e5dd7070Spatrick CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
2776e5dd7070Spatrick                                       AddStmtChoice asc) {
2777e5dd7070Spatrick   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2778e5dd7070Spatrick   appendStmt(ConfluenceBlock, C);
2779e5dd7070Spatrick   if (badCFG)
2780e5dd7070Spatrick     return nullptr;
2781e5dd7070Spatrick 
2782e5dd7070Spatrick   AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
2783e5dd7070Spatrick   Succ = ConfluenceBlock;
2784e5dd7070Spatrick   Block = nullptr;
2785e5dd7070Spatrick   CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);
2786e5dd7070Spatrick   if (badCFG)
2787e5dd7070Spatrick     return nullptr;
2788e5dd7070Spatrick 
2789e5dd7070Spatrick   Succ = ConfluenceBlock;
2790e5dd7070Spatrick   Block = nullptr;
2791e5dd7070Spatrick   CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);
2792e5dd7070Spatrick   if (badCFG)
2793e5dd7070Spatrick     return nullptr;
2794e5dd7070Spatrick 
2795e5dd7070Spatrick   Block = createBlock(false);
2796e5dd7070Spatrick   // See if this is a known constant.
2797e5dd7070Spatrick   const TryResult& KnownVal = tryEvaluateBool(C->getCond());
2798e5dd7070Spatrick   addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
2799e5dd7070Spatrick   addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
2800e5dd7070Spatrick   Block->setTerminator(C);
2801e5dd7070Spatrick   return addStmt(C->getCond());
2802e5dd7070Spatrick }
2803e5dd7070Spatrick 
VisitCompoundStmt(CompoundStmt * C,bool ExternallyDestructed)2804*12c85518Srobert CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,
2805*12c85518Srobert                                         bool ExternallyDestructed) {
2806e5dd7070Spatrick   LocalScope::const_iterator scopeBeginPos = ScopePos;
2807e5dd7070Spatrick   addLocalScopeForStmt(C);
2808e5dd7070Spatrick 
2809e5dd7070Spatrick   if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
2810e5dd7070Spatrick     // If the body ends with a ReturnStmt, the dtors will be added in
2811e5dd7070Spatrick     // VisitReturnStmt.
2812e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
2813e5dd7070Spatrick   }
2814e5dd7070Spatrick 
2815e5dd7070Spatrick   CFGBlock *LastBlock = Block;
2816e5dd7070Spatrick 
2817*12c85518Srobert   for (Stmt *S : llvm::reverse(C->body())) {
2818e5dd7070Spatrick     // If we hit a segment of code just containing ';' (NullStmts), we can
2819e5dd7070Spatrick     // get a null block back.  In such cases, just use the LastBlock
2820*12c85518Srobert     CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2821e5dd7070Spatrick                                ExternallyDestructed);
2822e5dd7070Spatrick 
2823e5dd7070Spatrick     if (newBlock)
2824e5dd7070Spatrick       LastBlock = newBlock;
2825e5dd7070Spatrick 
2826e5dd7070Spatrick     if (badCFG)
2827e5dd7070Spatrick       return nullptr;
2828e5dd7070Spatrick 
2829e5dd7070Spatrick     ExternallyDestructed = false;
2830e5dd7070Spatrick   }
2831e5dd7070Spatrick 
2832e5dd7070Spatrick   return LastBlock;
2833e5dd7070Spatrick }
2834e5dd7070Spatrick 
VisitConditionalOperator(AbstractConditionalOperator * C,AddStmtChoice asc)2835e5dd7070Spatrick CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
2836e5dd7070Spatrick                                                AddStmtChoice asc) {
2837e5dd7070Spatrick   const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);
2838e5dd7070Spatrick   const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);
2839e5dd7070Spatrick 
2840e5dd7070Spatrick   // Create the confluence block that will "merge" the results of the ternary
2841e5dd7070Spatrick   // expression.
2842e5dd7070Spatrick   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
2843e5dd7070Spatrick   appendStmt(ConfluenceBlock, C);
2844e5dd7070Spatrick   if (badCFG)
2845e5dd7070Spatrick     return nullptr;
2846e5dd7070Spatrick 
2847e5dd7070Spatrick   AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
2848e5dd7070Spatrick 
2849e5dd7070Spatrick   // Create a block for the LHS expression if there is an LHS expression.  A
2850e5dd7070Spatrick   // GCC extension allows LHS to be NULL, causing the condition to be the
2851e5dd7070Spatrick   // value that is returned instead.
2852e5dd7070Spatrick   //  e.g: x ?: y is shorthand for: x ? x : y;
2853e5dd7070Spatrick   Succ = ConfluenceBlock;
2854e5dd7070Spatrick   Block = nullptr;
2855e5dd7070Spatrick   CFGBlock *LHSBlock = nullptr;
2856e5dd7070Spatrick   const Expr *trueExpr = C->getTrueExpr();
2857e5dd7070Spatrick   if (trueExpr != opaqueValue) {
2858e5dd7070Spatrick     LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
2859e5dd7070Spatrick     if (badCFG)
2860e5dd7070Spatrick       return nullptr;
2861e5dd7070Spatrick     Block = nullptr;
2862e5dd7070Spatrick   }
2863e5dd7070Spatrick   else
2864e5dd7070Spatrick     LHSBlock = ConfluenceBlock;
2865e5dd7070Spatrick 
2866e5dd7070Spatrick   // Create the block for the RHS expression.
2867e5dd7070Spatrick   Succ = ConfluenceBlock;
2868e5dd7070Spatrick   CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
2869e5dd7070Spatrick   if (badCFG)
2870e5dd7070Spatrick     return nullptr;
2871e5dd7070Spatrick 
2872e5dd7070Spatrick   // If the condition is a logical '&&' or '||', build a more accurate CFG.
2873e5dd7070Spatrick   if (BinaryOperator *Cond =
2874e5dd7070Spatrick         dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens()))
2875e5dd7070Spatrick     if (Cond->isLogicalOp())
2876e5dd7070Spatrick       return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
2877e5dd7070Spatrick 
2878e5dd7070Spatrick   // Create the block that will contain the condition.
2879e5dd7070Spatrick   Block = createBlock(false);
2880e5dd7070Spatrick 
2881e5dd7070Spatrick   // See if this is a known constant.
2882e5dd7070Spatrick   const TryResult& KnownVal = tryEvaluateBool(C->getCond());
2883e5dd7070Spatrick   addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
2884e5dd7070Spatrick   addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
2885e5dd7070Spatrick   Block->setTerminator(C);
2886e5dd7070Spatrick   Expr *condExpr = C->getCond();
2887e5dd7070Spatrick 
2888e5dd7070Spatrick   if (opaqueValue) {
2889e5dd7070Spatrick     // Run the condition expression if it's not trivially expressed in
2890e5dd7070Spatrick     // terms of the opaque value (or if there is no opaque value).
2891e5dd7070Spatrick     if (condExpr != opaqueValue)
2892e5dd7070Spatrick       addStmt(condExpr);
2893e5dd7070Spatrick 
2894e5dd7070Spatrick     // Before that, run the common subexpression if there was one.
2895e5dd7070Spatrick     // At least one of this or the above will be run.
2896e5dd7070Spatrick     return addStmt(BCO->getCommon());
2897e5dd7070Spatrick   }
2898e5dd7070Spatrick 
2899e5dd7070Spatrick   return addStmt(condExpr);
2900e5dd7070Spatrick }
2901e5dd7070Spatrick 
VisitDeclStmt(DeclStmt * DS)2902e5dd7070Spatrick CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
2903e5dd7070Spatrick   // Check if the Decl is for an __label__.  If so, elide it from the
2904e5dd7070Spatrick   // CFG entirely.
2905e5dd7070Spatrick   if (isa<LabelDecl>(*DS->decl_begin()))
2906e5dd7070Spatrick     return Block;
2907e5dd7070Spatrick 
2908e5dd7070Spatrick   // This case also handles static_asserts.
2909e5dd7070Spatrick   if (DS->isSingleDecl())
2910e5dd7070Spatrick     return VisitDeclSubExpr(DS);
2911e5dd7070Spatrick 
2912e5dd7070Spatrick   CFGBlock *B = nullptr;
2913e5dd7070Spatrick 
2914e5dd7070Spatrick   // Build an individual DeclStmt for each decl.
2915e5dd7070Spatrick   for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),
2916e5dd7070Spatrick                                        E = DS->decl_rend();
2917e5dd7070Spatrick        I != E; ++I) {
2918e5dd7070Spatrick 
2919e5dd7070Spatrick     // Allocate the DeclStmt using the BumpPtrAllocator.  It will get
2920e5dd7070Spatrick     // automatically freed with the CFG.
2921e5dd7070Spatrick     DeclGroupRef DG(*I);
2922e5dd7070Spatrick     Decl *D = *I;
2923e5dd7070Spatrick     DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
2924e5dd7070Spatrick     cfg->addSyntheticDeclStmt(DSNew, DS);
2925e5dd7070Spatrick 
2926e5dd7070Spatrick     // Append the fake DeclStmt to block.
2927e5dd7070Spatrick     B = VisitDeclSubExpr(DSNew);
2928e5dd7070Spatrick   }
2929e5dd7070Spatrick 
2930e5dd7070Spatrick   return B;
2931e5dd7070Spatrick }
2932e5dd7070Spatrick 
2933e5dd7070Spatrick /// VisitDeclSubExpr - Utility method to add block-level expressions for
2934e5dd7070Spatrick /// DeclStmts and initializers in them.
VisitDeclSubExpr(DeclStmt * DS)2935e5dd7070Spatrick CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
2936e5dd7070Spatrick   assert(DS->isSingleDecl() && "Can handle single declarations only.");
2937ec727ea7Spatrick 
2938ec727ea7Spatrick   if (const auto *TND = dyn_cast<TypedefNameDecl>(DS->getSingleDecl())) {
2939ec727ea7Spatrick     // If we encounter a VLA, process its size expressions.
2940ec727ea7Spatrick     const Type *T = TND->getUnderlyingType().getTypePtr();
2941ec727ea7Spatrick     if (!T->isVariablyModifiedType())
2942ec727ea7Spatrick       return Block;
2943ec727ea7Spatrick 
2944ec727ea7Spatrick     autoCreateBlock();
2945ec727ea7Spatrick     appendStmt(Block, DS);
2946ec727ea7Spatrick 
2947ec727ea7Spatrick     CFGBlock *LastBlock = Block;
2948ec727ea7Spatrick     for (const VariableArrayType *VA = FindVA(T); VA != nullptr;
2949ec727ea7Spatrick          VA = FindVA(VA->getElementType().getTypePtr())) {
2950ec727ea7Spatrick       if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
2951ec727ea7Spatrick         LastBlock = NewBlock;
2952ec727ea7Spatrick     }
2953ec727ea7Spatrick     return LastBlock;
2954ec727ea7Spatrick   }
2955ec727ea7Spatrick 
2956e5dd7070Spatrick   VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
2957e5dd7070Spatrick 
2958e5dd7070Spatrick   if (!VD) {
2959ec727ea7Spatrick     // Of everything that can be declared in a DeclStmt, only VarDecls and the
2960ec727ea7Spatrick     // exceptions above impact runtime semantics.
2961e5dd7070Spatrick     return Block;
2962e5dd7070Spatrick   }
2963e5dd7070Spatrick 
2964e5dd7070Spatrick   bool HasTemporaries = false;
2965e5dd7070Spatrick 
2966e5dd7070Spatrick   // Guard static initializers under a branch.
2967e5dd7070Spatrick   CFGBlock *blockAfterStaticInit = nullptr;
2968e5dd7070Spatrick 
2969e5dd7070Spatrick   if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
2970e5dd7070Spatrick     // For static variables, we need to create a branch to track
2971e5dd7070Spatrick     // whether or not they are initialized.
2972e5dd7070Spatrick     if (Block) {
2973e5dd7070Spatrick       Succ = Block;
2974e5dd7070Spatrick       Block = nullptr;
2975e5dd7070Spatrick       if (badCFG)
2976e5dd7070Spatrick         return nullptr;
2977e5dd7070Spatrick     }
2978e5dd7070Spatrick     blockAfterStaticInit = Succ;
2979e5dd7070Spatrick   }
2980e5dd7070Spatrick 
2981e5dd7070Spatrick   // Destructors of temporaries in initialization expression should be called
2982e5dd7070Spatrick   // after initialization finishes.
2983e5dd7070Spatrick   Expr *Init = VD->getInit();
2984e5dd7070Spatrick   if (Init) {
2985e5dd7070Spatrick     HasTemporaries = isa<ExprWithCleanups>(Init);
2986e5dd7070Spatrick 
2987e5dd7070Spatrick     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
2988e5dd7070Spatrick       // Generate destructors for temporaries in initialization expression.
2989e5dd7070Spatrick       TempDtorContext Context;
2990e5dd7070Spatrick       VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2991e5dd7070Spatrick                              /*ExternallyDestructed=*/true, Context);
2992e5dd7070Spatrick     }
2993e5dd7070Spatrick   }
2994e5dd7070Spatrick 
2995*12c85518Srobert   // If we bind to a tuple-like type, we iterate over the HoldingVars, and
2996*12c85518Srobert   // create a DeclStmt for each of them.
2997*12c85518Srobert   if (const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
2998*12c85518Srobert     for (auto *BD : llvm::reverse(DD->bindings())) {
2999*12c85518Srobert       if (auto *VD = BD->getHoldingVar()) {
3000*12c85518Srobert         DeclGroupRef DG(VD);
3001*12c85518Srobert         DeclStmt *DSNew =
3002*12c85518Srobert             new (Context) DeclStmt(DG, VD->getLocation(), GetEndLoc(VD));
3003*12c85518Srobert         cfg->addSyntheticDeclStmt(DSNew, DS);
3004*12c85518Srobert         Block = VisitDeclSubExpr(DSNew);
3005*12c85518Srobert       }
3006*12c85518Srobert     }
3007*12c85518Srobert   }
3008*12c85518Srobert 
3009e5dd7070Spatrick   autoCreateBlock();
3010e5dd7070Spatrick   appendStmt(Block, DS);
3011e5dd7070Spatrick 
3012*12c85518Srobert   // If the initializer is an ArrayInitLoopExpr, we want to extract the
3013*12c85518Srobert   // initializer, that's used for each element.
3014*12c85518Srobert   const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init);
3015*12c85518Srobert 
3016e5dd7070Spatrick   findConstructionContexts(
3017e5dd7070Spatrick       ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
3018*12c85518Srobert       AILE ? AILE->getSubExpr() : Init);
3019e5dd7070Spatrick 
3020e5dd7070Spatrick   // Keep track of the last non-null block, as 'Block' can be nulled out
3021e5dd7070Spatrick   // if the initializer expression is something like a 'while' in a
3022e5dd7070Spatrick   // statement-expression.
3023e5dd7070Spatrick   CFGBlock *LastBlock = Block;
3024e5dd7070Spatrick 
3025e5dd7070Spatrick   if (Init) {
3026e5dd7070Spatrick     if (HasTemporaries) {
3027e5dd7070Spatrick       // For expression with temporaries go directly to subexpression to omit
3028e5dd7070Spatrick       // generating destructors for the second time.
3029e5dd7070Spatrick       ExprWithCleanups *EC = cast<ExprWithCleanups>(Init);
3030e5dd7070Spatrick       if (CFGBlock *newBlock = Visit(EC->getSubExpr()))
3031e5dd7070Spatrick         LastBlock = newBlock;
3032e5dd7070Spatrick     }
3033e5dd7070Spatrick     else {
3034e5dd7070Spatrick       if (CFGBlock *newBlock = Visit(Init))
3035e5dd7070Spatrick         LastBlock = newBlock;
3036e5dd7070Spatrick     }
3037e5dd7070Spatrick   }
3038e5dd7070Spatrick 
3039e5dd7070Spatrick   // If the type of VD is a VLA, then we must process its size expressions.
3040ec727ea7Spatrick   // FIXME: This does not find the VLA if it is embedded in other types,
3041ec727ea7Spatrick   // like here: `int (*p_vla)[x];`
3042e5dd7070Spatrick   for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());
3043e5dd7070Spatrick        VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {
3044e5dd7070Spatrick     if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
3045e5dd7070Spatrick       LastBlock = newBlock;
3046e5dd7070Spatrick   }
3047e5dd7070Spatrick 
3048e5dd7070Spatrick   maybeAddScopeBeginForVarDecl(Block, VD, DS);
3049e5dd7070Spatrick 
3050e5dd7070Spatrick   // Remove variable from local scope.
3051e5dd7070Spatrick   if (ScopePos && VD == *ScopePos)
3052e5dd7070Spatrick     ++ScopePos;
3053e5dd7070Spatrick 
3054e5dd7070Spatrick   CFGBlock *B = LastBlock;
3055e5dd7070Spatrick   if (blockAfterStaticInit) {
3056e5dd7070Spatrick     Succ = B;
3057e5dd7070Spatrick     Block = createBlock(false);
3058e5dd7070Spatrick     Block->setTerminator(DS);
3059e5dd7070Spatrick     addSuccessor(Block, blockAfterStaticInit);
3060e5dd7070Spatrick     addSuccessor(Block, B);
3061e5dd7070Spatrick     B = Block;
3062e5dd7070Spatrick   }
3063e5dd7070Spatrick 
3064e5dd7070Spatrick   return B;
3065e5dd7070Spatrick }
3066e5dd7070Spatrick 
VisitIfStmt(IfStmt * I)3067e5dd7070Spatrick CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
3068e5dd7070Spatrick   // We may see an if statement in the middle of a basic block, or it may be the
3069e5dd7070Spatrick   // first statement we are processing.  In either case, we create a new basic
3070e5dd7070Spatrick   // block.  First, we create the blocks for the then...else statements, and
3071e5dd7070Spatrick   // then we create the block containing the if statement.  If we were in the
3072e5dd7070Spatrick   // middle of a block, we stop processing that block.  That block is then the
3073e5dd7070Spatrick   // implicit successor for the "then" and "else" clauses.
3074e5dd7070Spatrick 
3075e5dd7070Spatrick   // Save local scope position because in case of condition variable ScopePos
3076e5dd7070Spatrick   // won't be restored when traversing AST.
3077*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
3078e5dd7070Spatrick 
3079e5dd7070Spatrick   // Create local scope for C++17 if init-stmt if one exists.
3080e5dd7070Spatrick   if (Stmt *Init = I->getInit())
3081e5dd7070Spatrick     addLocalScopeForStmt(Init);
3082e5dd7070Spatrick 
3083e5dd7070Spatrick   // Create local scope for possible condition variable.
3084e5dd7070Spatrick   // Store scope position. Add implicit destructor.
3085e5dd7070Spatrick   if (VarDecl *VD = I->getConditionVariable())
3086e5dd7070Spatrick     addLocalScopeForVarDecl(VD);
3087e5dd7070Spatrick 
3088e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
3089e5dd7070Spatrick 
3090e5dd7070Spatrick   // The block we were processing is now finished.  Make it the successor
3091e5dd7070Spatrick   // block.
3092e5dd7070Spatrick   if (Block) {
3093e5dd7070Spatrick     Succ = Block;
3094e5dd7070Spatrick     if (badCFG)
3095e5dd7070Spatrick       return nullptr;
3096e5dd7070Spatrick   }
3097e5dd7070Spatrick 
3098e5dd7070Spatrick   // Process the false branch.
3099e5dd7070Spatrick   CFGBlock *ElseBlock = Succ;
3100e5dd7070Spatrick 
3101e5dd7070Spatrick   if (Stmt *Else = I->getElse()) {
3102*12c85518Srobert     SaveAndRestore sv(Succ);
3103e5dd7070Spatrick 
3104e5dd7070Spatrick     // NULL out Block so that the recursive call to Visit will
3105e5dd7070Spatrick     // create a new basic block.
3106e5dd7070Spatrick     Block = nullptr;
3107e5dd7070Spatrick 
3108e5dd7070Spatrick     // If branch is not a compound statement create implicit scope
3109e5dd7070Spatrick     // and add destructors.
3110e5dd7070Spatrick     if (!isa<CompoundStmt>(Else))
3111e5dd7070Spatrick       addLocalScopeAndDtors(Else);
3112e5dd7070Spatrick 
3113e5dd7070Spatrick     ElseBlock = addStmt(Else);
3114e5dd7070Spatrick 
3115e5dd7070Spatrick     if (!ElseBlock) // Can occur when the Else body has all NullStmts.
3116e5dd7070Spatrick       ElseBlock = sv.get();
3117e5dd7070Spatrick     else if (Block) {
3118e5dd7070Spatrick       if (badCFG)
3119e5dd7070Spatrick         return nullptr;
3120e5dd7070Spatrick     }
3121e5dd7070Spatrick   }
3122e5dd7070Spatrick 
3123e5dd7070Spatrick   // Process the true branch.
3124e5dd7070Spatrick   CFGBlock *ThenBlock;
3125e5dd7070Spatrick   {
3126e5dd7070Spatrick     Stmt *Then = I->getThen();
3127e5dd7070Spatrick     assert(Then);
3128*12c85518Srobert     SaveAndRestore sv(Succ);
3129e5dd7070Spatrick     Block = nullptr;
3130e5dd7070Spatrick 
3131e5dd7070Spatrick     // If branch is not a compound statement create implicit scope
3132e5dd7070Spatrick     // and add destructors.
3133e5dd7070Spatrick     if (!isa<CompoundStmt>(Then))
3134e5dd7070Spatrick       addLocalScopeAndDtors(Then);
3135e5dd7070Spatrick 
3136e5dd7070Spatrick     ThenBlock = addStmt(Then);
3137e5dd7070Spatrick 
3138e5dd7070Spatrick     if (!ThenBlock) {
3139e5dd7070Spatrick       // We can reach here if the "then" body has all NullStmts.
3140e5dd7070Spatrick       // Create an empty block so we can distinguish between true and false
3141e5dd7070Spatrick       // branches in path-sensitive analyses.
3142e5dd7070Spatrick       ThenBlock = createBlock(false);
3143e5dd7070Spatrick       addSuccessor(ThenBlock, sv.get());
3144e5dd7070Spatrick     } else if (Block) {
3145e5dd7070Spatrick       if (badCFG)
3146e5dd7070Spatrick         return nullptr;
3147e5dd7070Spatrick     }
3148e5dd7070Spatrick   }
3149e5dd7070Spatrick 
3150e5dd7070Spatrick   // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by
3151e5dd7070Spatrick   // having these handle the actual control-flow jump.  Note that
3152e5dd7070Spatrick   // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)"
3153e5dd7070Spatrick   // we resort to the old control-flow behavior.  This special handling
3154e5dd7070Spatrick   // removes infeasible paths from the control-flow graph by having the
3155e5dd7070Spatrick   // control-flow transfer of '&&' or '||' go directly into the then/else
3156e5dd7070Spatrick   // blocks directly.
3157e5dd7070Spatrick   BinaryOperator *Cond =
3158*12c85518Srobert       (I->isConsteval() || I->getConditionVariable())
3159e5dd7070Spatrick           ? nullptr
3160e5dd7070Spatrick           : dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens());
3161e5dd7070Spatrick   CFGBlock *LastBlock;
3162e5dd7070Spatrick   if (Cond && Cond->isLogicalOp())
3163e5dd7070Spatrick     LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
3164e5dd7070Spatrick   else {
3165e5dd7070Spatrick     // Now create a new block containing the if statement.
3166e5dd7070Spatrick     Block = createBlock(false);
3167e5dd7070Spatrick 
3168e5dd7070Spatrick     // Set the terminator of the new block to the If statement.
3169e5dd7070Spatrick     Block->setTerminator(I);
3170e5dd7070Spatrick 
3171e5dd7070Spatrick     // See if this is a known constant.
3172*12c85518Srobert     TryResult KnownVal;
3173*12c85518Srobert     if (!I->isConsteval())
3174*12c85518Srobert       KnownVal = tryEvaluateBool(I->getCond());
3175e5dd7070Spatrick 
3176e5dd7070Spatrick     // Add the successors.  If we know that specific branches are
3177e5dd7070Spatrick     // unreachable, inform addSuccessor() of that knowledge.
3178e5dd7070Spatrick     addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse());
3179e5dd7070Spatrick     addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue());
3180e5dd7070Spatrick 
3181e5dd7070Spatrick     // Add the condition as the last statement in the new block.  This may
3182e5dd7070Spatrick     // create new blocks as the condition may contain control-flow.  Any newly
3183e5dd7070Spatrick     // created blocks will be pointed to be "Block".
3184e5dd7070Spatrick     LastBlock = addStmt(I->getCond());
3185e5dd7070Spatrick 
3186e5dd7070Spatrick     // If the IfStmt contains a condition variable, add it and its
3187e5dd7070Spatrick     // initializer to the CFG.
3188e5dd7070Spatrick     if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {
3189e5dd7070Spatrick       autoCreateBlock();
3190e5dd7070Spatrick       LastBlock = addStmt(const_cast<DeclStmt *>(DS));
3191e5dd7070Spatrick     }
3192e5dd7070Spatrick   }
3193e5dd7070Spatrick 
3194e5dd7070Spatrick   // Finally, if the IfStmt contains a C++17 init-stmt, add it to the CFG.
3195e5dd7070Spatrick   if (Stmt *Init = I->getInit()) {
3196e5dd7070Spatrick     autoCreateBlock();
3197e5dd7070Spatrick     LastBlock = addStmt(Init);
3198e5dd7070Spatrick   }
3199e5dd7070Spatrick 
3200e5dd7070Spatrick   return LastBlock;
3201e5dd7070Spatrick }
3202e5dd7070Spatrick 
VisitReturnStmt(Stmt * S)3203e5dd7070Spatrick CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
3204e5dd7070Spatrick   // If we were in the middle of a block we stop processing that block.
3205e5dd7070Spatrick   //
3206e5dd7070Spatrick   // NOTE: If a "return" or "co_return" appears in the middle of a block, this
3207e5dd7070Spatrick   //       means that the code afterwards is DEAD (unreachable).  We still keep
3208e5dd7070Spatrick   //       a basic block for that code; a simple "mark-and-sweep" from the entry
3209e5dd7070Spatrick   //       block will be able to report such dead blocks.
3210e5dd7070Spatrick   assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
3211e5dd7070Spatrick 
3212e5dd7070Spatrick   // Create the new block.
3213e5dd7070Spatrick   Block = createBlock(false);
3214e5dd7070Spatrick 
3215e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
3216e5dd7070Spatrick 
3217e5dd7070Spatrick   if (auto *R = dyn_cast<ReturnStmt>(S))
3218e5dd7070Spatrick     findConstructionContexts(
3219e5dd7070Spatrick         ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),
3220e5dd7070Spatrick         R->getRetValue());
3221e5dd7070Spatrick 
3222e5dd7070Spatrick   // If the one of the destructors does not return, we already have the Exit
3223e5dd7070Spatrick   // block as a successor.
3224e5dd7070Spatrick   if (!Block->hasNoReturnElement())
3225e5dd7070Spatrick     addSuccessor(Block, &cfg->getExit());
3226e5dd7070Spatrick 
3227e5dd7070Spatrick   // Add the return statement to the block.
3228e5dd7070Spatrick   appendStmt(Block, S);
3229e5dd7070Spatrick 
3230e5dd7070Spatrick   // Visit children
3231e5dd7070Spatrick   if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3232e5dd7070Spatrick     if (Expr *O = RS->getRetValue())
3233e5dd7070Spatrick       return Visit(O, AddStmtChoice::AlwaysAdd, /*ExternallyDestructed=*/true);
3234e5dd7070Spatrick     return Block;
3235e5dd7070Spatrick   }
3236*12c85518Srobert 
3237*12c85518Srobert   CoreturnStmt *CRS = cast<CoreturnStmt>(S);
3238*12c85518Srobert   auto *B = Block;
3239*12c85518Srobert   if (CFGBlock *R = Visit(CRS->getPromiseCall()))
3240*12c85518Srobert     B = R;
3241*12c85518Srobert 
3242*12c85518Srobert   if (Expr *RV = CRS->getOperand())
3243*12c85518Srobert     if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))
3244*12c85518Srobert       // A non-initlist void expression.
3245*12c85518Srobert       if (CFGBlock *R = Visit(RV))
3246*12c85518Srobert         B = R;
3247*12c85518Srobert 
3248*12c85518Srobert   return B;
3249*12c85518Srobert }
3250*12c85518Srobert 
VisitCoroutineSuspendExpr(CoroutineSuspendExpr * E,AddStmtChoice asc)3251*12c85518Srobert CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
3252*12c85518Srobert                                                 AddStmtChoice asc) {
3253*12c85518Srobert   // We're modelling the pre-coro-xform CFG. Thus just evalate the various
3254*12c85518Srobert   // active components of the co_await or co_yield. Note we do not model the
3255*12c85518Srobert   // edge from the builtin_suspend to the exit node.
3256*12c85518Srobert   if (asc.alwaysAdd(*this, E)) {
3257*12c85518Srobert     autoCreateBlock();
3258*12c85518Srobert     appendStmt(Block, E);
3259*12c85518Srobert   }
3260*12c85518Srobert   CFGBlock *B = Block;
3261*12c85518Srobert   if (auto *R = Visit(E->getResumeExpr()))
3262*12c85518Srobert     B = R;
3263*12c85518Srobert   if (auto *R = Visit(E->getSuspendExpr()))
3264*12c85518Srobert     B = R;
3265*12c85518Srobert   if (auto *R = Visit(E->getReadyExpr()))
3266*12c85518Srobert     B = R;
3267*12c85518Srobert   if (auto *R = Visit(E->getCommonExpr()))
3268*12c85518Srobert     B = R;
3269*12c85518Srobert   return B;
3270e5dd7070Spatrick }
3271e5dd7070Spatrick 
VisitSEHExceptStmt(SEHExceptStmt * ES)3272e5dd7070Spatrick CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
3273e5dd7070Spatrick   // SEHExceptStmt are treated like labels, so they are the first statement in a
3274e5dd7070Spatrick   // block.
3275e5dd7070Spatrick 
3276e5dd7070Spatrick   // Save local scope position because in case of exception variable ScopePos
3277e5dd7070Spatrick   // won't be restored when traversing AST.
3278*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
3279e5dd7070Spatrick 
3280e5dd7070Spatrick   addStmt(ES->getBlock());
3281e5dd7070Spatrick   CFGBlock *SEHExceptBlock = Block;
3282e5dd7070Spatrick   if (!SEHExceptBlock)
3283e5dd7070Spatrick     SEHExceptBlock = createBlock();
3284e5dd7070Spatrick 
3285e5dd7070Spatrick   appendStmt(SEHExceptBlock, ES);
3286e5dd7070Spatrick 
3287e5dd7070Spatrick   // Also add the SEHExceptBlock as a label, like with regular labels.
3288e5dd7070Spatrick   SEHExceptBlock->setLabel(ES);
3289e5dd7070Spatrick 
3290e5dd7070Spatrick   // Bail out if the CFG is bad.
3291e5dd7070Spatrick   if (badCFG)
3292e5dd7070Spatrick     return nullptr;
3293e5dd7070Spatrick 
3294e5dd7070Spatrick   // We set Block to NULL to allow lazy creation of a new block (if necessary).
3295e5dd7070Spatrick   Block = nullptr;
3296e5dd7070Spatrick 
3297e5dd7070Spatrick   return SEHExceptBlock;
3298e5dd7070Spatrick }
3299e5dd7070Spatrick 
VisitSEHFinallyStmt(SEHFinallyStmt * FS)3300e5dd7070Spatrick CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3301e5dd7070Spatrick   return VisitCompoundStmt(FS->getBlock(), /*ExternallyDestructed=*/false);
3302e5dd7070Spatrick }
3303e5dd7070Spatrick 
VisitSEHLeaveStmt(SEHLeaveStmt * LS)3304e5dd7070Spatrick CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
3305e5dd7070Spatrick   // "__leave" is a control-flow statement.  Thus we stop processing the current
3306e5dd7070Spatrick   // block.
3307e5dd7070Spatrick   if (badCFG)
3308e5dd7070Spatrick     return nullptr;
3309e5dd7070Spatrick 
3310e5dd7070Spatrick   // Now create a new block that ends with the __leave statement.
3311e5dd7070Spatrick   Block = createBlock(false);
3312e5dd7070Spatrick   Block->setTerminator(LS);
3313e5dd7070Spatrick 
3314e5dd7070Spatrick   // If there is no target for the __leave, then we are looking at an incomplete
3315e5dd7070Spatrick   // AST.  This means that the CFG cannot be constructed.
3316e5dd7070Spatrick   if (SEHLeaveJumpTarget.block) {
3317e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
3318e5dd7070Spatrick     addSuccessor(Block, SEHLeaveJumpTarget.block);
3319e5dd7070Spatrick   } else
3320e5dd7070Spatrick     badCFG = true;
3321e5dd7070Spatrick 
3322e5dd7070Spatrick   return Block;
3323e5dd7070Spatrick }
3324e5dd7070Spatrick 
VisitSEHTryStmt(SEHTryStmt * Terminator)3325e5dd7070Spatrick CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
3326e5dd7070Spatrick   // "__try"/"__except"/"__finally" is a control-flow statement.  Thus we stop
3327e5dd7070Spatrick   // processing the current block.
3328e5dd7070Spatrick   CFGBlock *SEHTrySuccessor = nullptr;
3329e5dd7070Spatrick 
3330e5dd7070Spatrick   if (Block) {
3331e5dd7070Spatrick     if (badCFG)
3332e5dd7070Spatrick       return nullptr;
3333e5dd7070Spatrick     SEHTrySuccessor = Block;
3334e5dd7070Spatrick   } else SEHTrySuccessor = Succ;
3335e5dd7070Spatrick 
3336e5dd7070Spatrick   // FIXME: Implement __finally support.
3337e5dd7070Spatrick   if (Terminator->getFinallyHandler())
3338e5dd7070Spatrick     return NYS();
3339e5dd7070Spatrick 
3340e5dd7070Spatrick   CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
3341e5dd7070Spatrick 
3342e5dd7070Spatrick   // Create a new block that will contain the __try statement.
3343e5dd7070Spatrick   CFGBlock *NewTryTerminatedBlock = createBlock(false);
3344e5dd7070Spatrick 
3345e5dd7070Spatrick   // Add the terminator in the __try block.
3346e5dd7070Spatrick   NewTryTerminatedBlock->setTerminator(Terminator);
3347e5dd7070Spatrick 
3348e5dd7070Spatrick   if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {
3349e5dd7070Spatrick     // The code after the try is the implicit successor if there's an __except.
3350e5dd7070Spatrick     Succ = SEHTrySuccessor;
3351e5dd7070Spatrick     Block = nullptr;
3352e5dd7070Spatrick     CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
3353e5dd7070Spatrick     if (!ExceptBlock)
3354e5dd7070Spatrick       return nullptr;
3355e5dd7070Spatrick     // Add this block to the list of successors for the block with the try
3356e5dd7070Spatrick     // statement.
3357e5dd7070Spatrick     addSuccessor(NewTryTerminatedBlock, ExceptBlock);
3358e5dd7070Spatrick   }
3359e5dd7070Spatrick   if (PrevSEHTryTerminatedBlock)
3360e5dd7070Spatrick     addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
3361e5dd7070Spatrick   else
3362e5dd7070Spatrick     addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
3363e5dd7070Spatrick 
3364e5dd7070Spatrick   // The code after the try is the implicit successor.
3365e5dd7070Spatrick   Succ = SEHTrySuccessor;
3366e5dd7070Spatrick 
3367e5dd7070Spatrick   // Save the current "__try" context.
3368*12c85518Srobert   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
3369e5dd7070Spatrick   cfg->addTryDispatchBlock(TryTerminatedBlock);
3370e5dd7070Spatrick 
3371e5dd7070Spatrick   // Save the current value for the __leave target.
3372e5dd7070Spatrick   // All __leaves should go to the code following the __try
3373e5dd7070Spatrick   // (FIXME: or if the __try has a __finally, to the __finally.)
3374*12c85518Srobert   SaveAndRestore save_break(SEHLeaveJumpTarget);
3375e5dd7070Spatrick   SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
3376e5dd7070Spatrick 
3377e5dd7070Spatrick   assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");
3378e5dd7070Spatrick   Block = nullptr;
3379e5dd7070Spatrick   return addStmt(Terminator->getTryBlock());
3380e5dd7070Spatrick }
3381e5dd7070Spatrick 
VisitLabelStmt(LabelStmt * L)3382e5dd7070Spatrick CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
3383e5dd7070Spatrick   // Get the block of the labeled statement.  Add it to our map.
3384e5dd7070Spatrick   addStmt(L->getSubStmt());
3385e5dd7070Spatrick   CFGBlock *LabelBlock = Block;
3386e5dd7070Spatrick 
3387e5dd7070Spatrick   if (!LabelBlock)              // This can happen when the body is empty, i.e.
3388e5dd7070Spatrick     LabelBlock = createBlock(); // scopes that only contains NullStmts.
3389e5dd7070Spatrick 
3390e5dd7070Spatrick   assert(LabelMap.find(L->getDecl()) == LabelMap.end() &&
3391e5dd7070Spatrick          "label already in map");
3392e5dd7070Spatrick   LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
3393e5dd7070Spatrick 
3394e5dd7070Spatrick   // Labels partition blocks, so this is the end of the basic block we were
3395e5dd7070Spatrick   // processing (L is the block's label).  Because this is label (and we have
3396e5dd7070Spatrick   // already processed the substatement) there is no extra control-flow to worry
3397e5dd7070Spatrick   // about.
3398e5dd7070Spatrick   LabelBlock->setLabel(L);
3399e5dd7070Spatrick   if (badCFG)
3400e5dd7070Spatrick     return nullptr;
3401e5dd7070Spatrick 
3402*12c85518Srobert   // We set Block to NULL to allow lazy creation of a new block (if necessary).
3403e5dd7070Spatrick   Block = nullptr;
3404e5dd7070Spatrick 
3405e5dd7070Spatrick   // This block is now the implicit successor of other blocks.
3406e5dd7070Spatrick   Succ = LabelBlock;
3407e5dd7070Spatrick 
3408e5dd7070Spatrick   return LabelBlock;
3409e5dd7070Spatrick }
3410e5dd7070Spatrick 
VisitBlockExpr(BlockExpr * E,AddStmtChoice asc)3411e5dd7070Spatrick CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
3412e5dd7070Spatrick   CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3413e5dd7070Spatrick   for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) {
3414e5dd7070Spatrick     if (Expr *CopyExpr = CI.getCopyExpr()) {
3415e5dd7070Spatrick       CFGBlock *Tmp = Visit(CopyExpr);
3416e5dd7070Spatrick       if (Tmp)
3417e5dd7070Spatrick         LastBlock = Tmp;
3418e5dd7070Spatrick     }
3419e5dd7070Spatrick   }
3420e5dd7070Spatrick   return LastBlock;
3421e5dd7070Spatrick }
3422e5dd7070Spatrick 
VisitLambdaExpr(LambdaExpr * E,AddStmtChoice asc)3423e5dd7070Spatrick CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
3424e5dd7070Spatrick   CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3425*12c85518Srobert 
3426*12c85518Srobert   unsigned Idx = 0;
3427e5dd7070Spatrick   for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(),
3428*12c85518Srobert                                          et = E->capture_init_end();
3429*12c85518Srobert        it != et; ++it, ++Idx) {
3430e5dd7070Spatrick     if (Expr *Init = *it) {
3431*12c85518Srobert       // If the initializer is an ArrayInitLoopExpr, we want to extract the
3432*12c85518Srobert       // initializer, that's used for each element.
3433*12c85518Srobert       auto *AILEInit = extractElementInitializerFromNestedAILE(
3434*12c85518Srobert           dyn_cast<ArrayInitLoopExpr>(Init));
3435*12c85518Srobert 
3436*12c85518Srobert       findConstructionContexts(ConstructionContextLayer::create(
3437*12c85518Srobert                                    cfg->getBumpVectorContext(), {E, Idx}),
3438*12c85518Srobert                                AILEInit ? AILEInit : Init);
3439*12c85518Srobert 
3440e5dd7070Spatrick       CFGBlock *Tmp = Visit(Init);
3441e5dd7070Spatrick       if (Tmp)
3442e5dd7070Spatrick         LastBlock = Tmp;
3443e5dd7070Spatrick     }
3444e5dd7070Spatrick   }
3445e5dd7070Spatrick   return LastBlock;
3446e5dd7070Spatrick }
3447e5dd7070Spatrick 
VisitGotoStmt(GotoStmt * G)3448e5dd7070Spatrick CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
3449e5dd7070Spatrick   // Goto is a control-flow statement.  Thus we stop processing the current
3450e5dd7070Spatrick   // block and create a new one.
3451e5dd7070Spatrick 
3452e5dd7070Spatrick   Block = createBlock(false);
3453e5dd7070Spatrick   Block->setTerminator(G);
3454e5dd7070Spatrick 
3455e5dd7070Spatrick   // If we already know the mapping to the label block add the successor now.
3456e5dd7070Spatrick   LabelMapTy::iterator I = LabelMap.find(G->getLabel());
3457e5dd7070Spatrick 
3458e5dd7070Spatrick   if (I == LabelMap.end())
3459e5dd7070Spatrick     // We will need to backpatch this block later.
3460e5dd7070Spatrick     BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3461e5dd7070Spatrick   else {
3462e5dd7070Spatrick     JumpTarget JT = I->second;
3463e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, JT.scopePosition, G);
3464e5dd7070Spatrick     addSuccessor(Block, JT.block);
3465e5dd7070Spatrick   }
3466e5dd7070Spatrick 
3467e5dd7070Spatrick   return Block;
3468e5dd7070Spatrick }
3469e5dd7070Spatrick 
VisitGCCAsmStmt(GCCAsmStmt * G,AddStmtChoice asc)3470e5dd7070Spatrick CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
3471e5dd7070Spatrick   // Goto is a control-flow statement.  Thus we stop processing the current
3472e5dd7070Spatrick   // block and create a new one.
3473e5dd7070Spatrick 
3474e5dd7070Spatrick   if (!G->isAsmGoto())
3475e5dd7070Spatrick     return VisitStmt(G, asc);
3476e5dd7070Spatrick 
3477e5dd7070Spatrick   if (Block) {
3478e5dd7070Spatrick     Succ = Block;
3479e5dd7070Spatrick     if (badCFG)
3480e5dd7070Spatrick       return nullptr;
3481e5dd7070Spatrick   }
3482e5dd7070Spatrick   Block = createBlock();
3483e5dd7070Spatrick   Block->setTerminator(G);
3484e5dd7070Spatrick   // We will backpatch this block later for all the labels.
3485e5dd7070Spatrick   BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
3486e5dd7070Spatrick   // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
3487e5dd7070Spatrick   // used to avoid adding "Succ" again.
3488e5dd7070Spatrick   BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3489*12c85518Srobert   return VisitChildren(G);
3490e5dd7070Spatrick }
3491e5dd7070Spatrick 
VisitForStmt(ForStmt * F)3492e5dd7070Spatrick CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
3493e5dd7070Spatrick   CFGBlock *LoopSuccessor = nullptr;
3494e5dd7070Spatrick 
3495e5dd7070Spatrick   // Save local scope position because in case of condition variable ScopePos
3496e5dd7070Spatrick   // won't be restored when traversing AST.
3497*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
3498e5dd7070Spatrick 
3499e5dd7070Spatrick   // Create local scope for init statement and possible condition variable.
3500e5dd7070Spatrick   // Add destructor for init statement and condition variable.
3501e5dd7070Spatrick   // Store scope position for continue statement.
3502e5dd7070Spatrick   if (Stmt *Init = F->getInit())
3503e5dd7070Spatrick     addLocalScopeForStmt(Init);
3504e5dd7070Spatrick   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3505e5dd7070Spatrick 
3506e5dd7070Spatrick   if (VarDecl *VD = F->getConditionVariable())
3507e5dd7070Spatrick     addLocalScopeForVarDecl(VD);
3508e5dd7070Spatrick   LocalScope::const_iterator ContinueScopePos = ScopePos;
3509e5dd7070Spatrick 
3510e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
3511e5dd7070Spatrick 
3512e5dd7070Spatrick   addLoopExit(F);
3513e5dd7070Spatrick 
3514e5dd7070Spatrick   // "for" is a control-flow statement.  Thus we stop processing the current
3515e5dd7070Spatrick   // block.
3516e5dd7070Spatrick   if (Block) {
3517e5dd7070Spatrick     if (badCFG)
3518e5dd7070Spatrick       return nullptr;
3519e5dd7070Spatrick     LoopSuccessor = Block;
3520e5dd7070Spatrick   } else
3521e5dd7070Spatrick     LoopSuccessor = Succ;
3522e5dd7070Spatrick 
3523e5dd7070Spatrick   // Save the current value for the break targets.
3524e5dd7070Spatrick   // All breaks should go to the code following the loop.
3525*12c85518Srobert   SaveAndRestore save_break(BreakJumpTarget);
3526e5dd7070Spatrick   BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3527e5dd7070Spatrick 
3528e5dd7070Spatrick   CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
3529e5dd7070Spatrick 
3530e5dd7070Spatrick   // Now create the loop body.
3531e5dd7070Spatrick   {
3532e5dd7070Spatrick     assert(F->getBody());
3533e5dd7070Spatrick 
3534e5dd7070Spatrick     // Save the current values for Block, Succ, continue and break targets.
3535*12c85518Srobert     SaveAndRestore save_Block(Block), save_Succ(Succ);
3536*12c85518Srobert     SaveAndRestore save_continue(ContinueJumpTarget);
3537e5dd7070Spatrick 
3538e5dd7070Spatrick     // Create an empty block to represent the transition block for looping back
3539e5dd7070Spatrick     // to the head of the loop.  If we have increment code, it will
3540e5dd7070Spatrick     // go in this block as well.
3541e5dd7070Spatrick     Block = Succ = TransitionBlock = createBlock(false);
3542e5dd7070Spatrick     TransitionBlock->setLoopTarget(F);
3543e5dd7070Spatrick 
3544e5dd7070Spatrick     if (Stmt *I = F->getInc()) {
3545e5dd7070Spatrick       // Generate increment code in its own basic block.  This is the target of
3546e5dd7070Spatrick       // continue statements.
3547e5dd7070Spatrick       Succ = addStmt(I);
3548e5dd7070Spatrick     }
3549e5dd7070Spatrick 
3550e5dd7070Spatrick     // Finish up the increment (or empty) block if it hasn't been already.
3551e5dd7070Spatrick     if (Block) {
3552e5dd7070Spatrick       assert(Block == Succ);
3553e5dd7070Spatrick       if (badCFG)
3554e5dd7070Spatrick         return nullptr;
3555e5dd7070Spatrick       Block = nullptr;
3556e5dd7070Spatrick     }
3557e5dd7070Spatrick 
3558e5dd7070Spatrick    // The starting block for the loop increment is the block that should
3559e5dd7070Spatrick    // represent the 'loop target' for looping back to the start of the loop.
3560e5dd7070Spatrick    ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
3561e5dd7070Spatrick    ContinueJumpTarget.block->setLoopTarget(F);
3562e5dd7070Spatrick 
3563e5dd7070Spatrick     // Loop body should end with destructor of Condition variable (if any).
3564e5dd7070Spatrick    addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
3565e5dd7070Spatrick 
3566e5dd7070Spatrick     // If body is not a compound statement create implicit scope
3567e5dd7070Spatrick     // and add destructors.
3568e5dd7070Spatrick     if (!isa<CompoundStmt>(F->getBody()))
3569e5dd7070Spatrick       addLocalScopeAndDtors(F->getBody());
3570e5dd7070Spatrick 
3571e5dd7070Spatrick     // Now populate the body block, and in the process create new blocks as we
3572e5dd7070Spatrick     // walk the body of the loop.
3573e5dd7070Spatrick     BodyBlock = addStmt(F->getBody());
3574e5dd7070Spatrick 
3575e5dd7070Spatrick     if (!BodyBlock) {
3576e5dd7070Spatrick       // In the case of "for (...;...;...);" we can have a null BodyBlock.
3577e5dd7070Spatrick       // Use the continue jump target as the proxy for the body.
3578e5dd7070Spatrick       BodyBlock = ContinueJumpTarget.block;
3579e5dd7070Spatrick     }
3580e5dd7070Spatrick     else if (badCFG)
3581e5dd7070Spatrick       return nullptr;
3582e5dd7070Spatrick   }
3583e5dd7070Spatrick 
3584e5dd7070Spatrick   // Because of short-circuit evaluation, the condition of the loop can span
3585e5dd7070Spatrick   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
3586e5dd7070Spatrick   // evaluate the condition.
3587e5dd7070Spatrick   CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
3588e5dd7070Spatrick 
3589e5dd7070Spatrick   do {
3590e5dd7070Spatrick     Expr *C = F->getCond();
3591*12c85518Srobert     SaveAndRestore save_scope_pos(ScopePos);
3592e5dd7070Spatrick 
3593e5dd7070Spatrick     // Specially handle logical operators, which have a slightly
3594e5dd7070Spatrick     // more optimal CFG representation.
3595e5dd7070Spatrick     if (BinaryOperator *Cond =
3596e5dd7070Spatrick             dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr))
3597e5dd7070Spatrick       if (Cond->isLogicalOp()) {
3598e5dd7070Spatrick         std::tie(EntryConditionBlock, ExitConditionBlock) =
3599e5dd7070Spatrick           VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
3600e5dd7070Spatrick         break;
3601e5dd7070Spatrick       }
3602e5dd7070Spatrick 
3603e5dd7070Spatrick     // The default case when not handling logical operators.
3604e5dd7070Spatrick     EntryConditionBlock = ExitConditionBlock = createBlock(false);
3605e5dd7070Spatrick     ExitConditionBlock->setTerminator(F);
3606e5dd7070Spatrick 
3607e5dd7070Spatrick     // See if this is a known constant.
3608e5dd7070Spatrick     TryResult KnownVal(true);
3609e5dd7070Spatrick 
3610e5dd7070Spatrick     if (C) {
3611e5dd7070Spatrick       // Now add the actual condition to the condition block.
3612e5dd7070Spatrick       // Because the condition itself may contain control-flow, new blocks may
3613e5dd7070Spatrick       // be created.  Thus we update "Succ" after adding the condition.
3614e5dd7070Spatrick       Block = ExitConditionBlock;
3615e5dd7070Spatrick       EntryConditionBlock = addStmt(C);
3616e5dd7070Spatrick 
3617e5dd7070Spatrick       // If this block contains a condition variable, add both the condition
3618e5dd7070Spatrick       // variable and initializer to the CFG.
3619e5dd7070Spatrick       if (VarDecl *VD = F->getConditionVariable()) {
3620e5dd7070Spatrick         if (Expr *Init = VD->getInit()) {
3621e5dd7070Spatrick           autoCreateBlock();
3622e5dd7070Spatrick           const DeclStmt *DS = F->getConditionVariableDeclStmt();
3623e5dd7070Spatrick           assert(DS->isSingleDecl());
3624e5dd7070Spatrick           findConstructionContexts(
3625e5dd7070Spatrick               ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
3626e5dd7070Spatrick               Init);
3627e5dd7070Spatrick           appendStmt(Block, DS);
3628e5dd7070Spatrick           EntryConditionBlock = addStmt(Init);
3629e5dd7070Spatrick           assert(Block == EntryConditionBlock);
3630e5dd7070Spatrick           maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3631e5dd7070Spatrick         }
3632e5dd7070Spatrick       }
3633e5dd7070Spatrick 
3634e5dd7070Spatrick       if (Block && badCFG)
3635e5dd7070Spatrick         return nullptr;
3636e5dd7070Spatrick 
3637e5dd7070Spatrick       KnownVal = tryEvaluateBool(C);
3638e5dd7070Spatrick     }
3639e5dd7070Spatrick 
3640e5dd7070Spatrick     // Add the loop body entry as a successor to the condition.
3641e5dd7070Spatrick     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3642e5dd7070Spatrick     // Link up the condition block with the code that follows the loop.  (the
3643e5dd7070Spatrick     // false branch).
3644e5dd7070Spatrick     addSuccessor(ExitConditionBlock,
3645e5dd7070Spatrick                  KnownVal.isTrue() ? nullptr : LoopSuccessor);
3646e5dd7070Spatrick   } while (false);
3647e5dd7070Spatrick 
3648e5dd7070Spatrick   // Link up the loop-back block to the entry condition block.
3649e5dd7070Spatrick   addSuccessor(TransitionBlock, EntryConditionBlock);
3650e5dd7070Spatrick 
3651e5dd7070Spatrick   // The condition block is the implicit successor for any code above the loop.
3652e5dd7070Spatrick   Succ = EntryConditionBlock;
3653e5dd7070Spatrick 
3654e5dd7070Spatrick   // If the loop contains initialization, create a new block for those
3655e5dd7070Spatrick   // statements.  This block can also contain statements that precede the loop.
3656e5dd7070Spatrick   if (Stmt *I = F->getInit()) {
3657*12c85518Srobert     SaveAndRestore save_scope_pos(ScopePos);
3658e5dd7070Spatrick     ScopePos = LoopBeginScopePos;
3659e5dd7070Spatrick     Block = createBlock();
3660e5dd7070Spatrick     return addStmt(I);
3661e5dd7070Spatrick   }
3662e5dd7070Spatrick 
3663e5dd7070Spatrick   // There is no loop initialization.  We are thus basically a while loop.
3664e5dd7070Spatrick   // NULL out Block to force lazy block construction.
3665e5dd7070Spatrick   Block = nullptr;
3666e5dd7070Spatrick   Succ = EntryConditionBlock;
3667e5dd7070Spatrick   return EntryConditionBlock;
3668e5dd7070Spatrick }
3669e5dd7070Spatrick 
3670e5dd7070Spatrick CFGBlock *
VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr * MTE,AddStmtChoice asc)3671e5dd7070Spatrick CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
3672e5dd7070Spatrick                                           AddStmtChoice asc) {
3673e5dd7070Spatrick   findConstructionContexts(
3674e5dd7070Spatrick       ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
3675e5dd7070Spatrick       MTE->getSubExpr());
3676e5dd7070Spatrick 
3677e5dd7070Spatrick   return VisitStmt(MTE, asc);
3678e5dd7070Spatrick }
3679e5dd7070Spatrick 
VisitMemberExpr(MemberExpr * M,AddStmtChoice asc)3680e5dd7070Spatrick CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
3681e5dd7070Spatrick   if (asc.alwaysAdd(*this, M)) {
3682e5dd7070Spatrick     autoCreateBlock();
3683e5dd7070Spatrick     appendStmt(Block, M);
3684e5dd7070Spatrick   }
3685e5dd7070Spatrick   return Visit(M->getBase());
3686e5dd7070Spatrick }
3687e5dd7070Spatrick 
VisitObjCForCollectionStmt(ObjCForCollectionStmt * S)3688e5dd7070Spatrick CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
3689e5dd7070Spatrick   // Objective-C fast enumeration 'for' statements:
3690e5dd7070Spatrick   //  http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
3691e5dd7070Spatrick   //
3692e5dd7070Spatrick   //  for ( Type newVariable in collection_expression ) { statements }
3693e5dd7070Spatrick   //
3694e5dd7070Spatrick   //  becomes:
3695e5dd7070Spatrick   //
3696e5dd7070Spatrick   //   prologue:
3697e5dd7070Spatrick   //     1. collection_expression
3698e5dd7070Spatrick   //     T. jump to loop_entry
3699e5dd7070Spatrick   //   loop_entry:
3700e5dd7070Spatrick   //     1. side-effects of element expression
3701e5dd7070Spatrick   //     1. ObjCForCollectionStmt [performs binding to newVariable]
3702e5dd7070Spatrick   //     T. ObjCForCollectionStmt  TB, FB  [jumps to TB if newVariable != nil]
3703e5dd7070Spatrick   //   TB:
3704e5dd7070Spatrick   //     statements
3705e5dd7070Spatrick   //     T. jump to loop_entry
3706e5dd7070Spatrick   //   FB:
3707e5dd7070Spatrick   //     what comes after
3708e5dd7070Spatrick   //
3709e5dd7070Spatrick   //  and
3710e5dd7070Spatrick   //
3711e5dd7070Spatrick   //  Type existingItem;
3712e5dd7070Spatrick   //  for ( existingItem in expression ) { statements }
3713e5dd7070Spatrick   //
3714e5dd7070Spatrick   //  becomes:
3715e5dd7070Spatrick   //
3716e5dd7070Spatrick   //   the same with newVariable replaced with existingItem; the binding works
3717e5dd7070Spatrick   //   the same except that for one ObjCForCollectionStmt::getElement() returns
3718e5dd7070Spatrick   //   a DeclStmt and the other returns a DeclRefExpr.
3719e5dd7070Spatrick 
3720e5dd7070Spatrick   CFGBlock *LoopSuccessor = nullptr;
3721e5dd7070Spatrick 
3722e5dd7070Spatrick   if (Block) {
3723e5dd7070Spatrick     if (badCFG)
3724e5dd7070Spatrick       return nullptr;
3725e5dd7070Spatrick     LoopSuccessor = Block;
3726e5dd7070Spatrick     Block = nullptr;
3727e5dd7070Spatrick   } else
3728e5dd7070Spatrick     LoopSuccessor = Succ;
3729e5dd7070Spatrick 
3730e5dd7070Spatrick   // Build the condition blocks.
3731e5dd7070Spatrick   CFGBlock *ExitConditionBlock = createBlock(false);
3732e5dd7070Spatrick 
3733e5dd7070Spatrick   // Set the terminator for the "exit" condition block.
3734e5dd7070Spatrick   ExitConditionBlock->setTerminator(S);
3735e5dd7070Spatrick 
3736e5dd7070Spatrick   // The last statement in the block should be the ObjCForCollectionStmt, which
3737e5dd7070Spatrick   // performs the actual binding to 'element' and determines if there are any
3738e5dd7070Spatrick   // more items in the collection.
3739e5dd7070Spatrick   appendStmt(ExitConditionBlock, S);
3740e5dd7070Spatrick   Block = ExitConditionBlock;
3741e5dd7070Spatrick 
3742e5dd7070Spatrick   // Walk the 'element' expression to see if there are any side-effects.  We
3743e5dd7070Spatrick   // generate new blocks as necessary.  We DON'T add the statement by default to
3744e5dd7070Spatrick   // the CFG unless it contains control-flow.
3745e5dd7070Spatrick   CFGBlock *EntryConditionBlock = Visit(S->getElement(),
3746e5dd7070Spatrick                                         AddStmtChoice::NotAlwaysAdd);
3747e5dd7070Spatrick   if (Block) {
3748e5dd7070Spatrick     if (badCFG)
3749e5dd7070Spatrick       return nullptr;
3750e5dd7070Spatrick     Block = nullptr;
3751e5dd7070Spatrick   }
3752e5dd7070Spatrick 
3753e5dd7070Spatrick   // The condition block is the implicit successor for the loop body as well as
3754e5dd7070Spatrick   // any code above the loop.
3755e5dd7070Spatrick   Succ = EntryConditionBlock;
3756e5dd7070Spatrick 
3757e5dd7070Spatrick   // Now create the true branch.
3758e5dd7070Spatrick   {
3759e5dd7070Spatrick     // Save the current values for Succ, continue and break targets.
3760*12c85518Srobert     SaveAndRestore save_Block(Block), save_Succ(Succ);
3761*12c85518Srobert     SaveAndRestore save_continue(ContinueJumpTarget),
3762e5dd7070Spatrick         save_break(BreakJumpTarget);
3763e5dd7070Spatrick 
3764e5dd7070Spatrick     // Add an intermediate block between the BodyBlock and the
3765e5dd7070Spatrick     // EntryConditionBlock to represent the "loop back" transition, for looping
3766e5dd7070Spatrick     // back to the head of the loop.
3767e5dd7070Spatrick     CFGBlock *LoopBackBlock = nullptr;
3768e5dd7070Spatrick     Succ = LoopBackBlock = createBlock();
3769e5dd7070Spatrick     LoopBackBlock->setLoopTarget(S);
3770e5dd7070Spatrick 
3771e5dd7070Spatrick     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3772e5dd7070Spatrick     ContinueJumpTarget = JumpTarget(Succ, ScopePos);
3773e5dd7070Spatrick 
3774e5dd7070Spatrick     CFGBlock *BodyBlock = addStmt(S->getBody());
3775e5dd7070Spatrick 
3776e5dd7070Spatrick     if (!BodyBlock)
3777e5dd7070Spatrick       BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;"
3778e5dd7070Spatrick     else if (Block) {
3779e5dd7070Spatrick       if (badCFG)
3780e5dd7070Spatrick         return nullptr;
3781e5dd7070Spatrick     }
3782e5dd7070Spatrick 
3783e5dd7070Spatrick     // This new body block is a successor to our "exit" condition block.
3784e5dd7070Spatrick     addSuccessor(ExitConditionBlock, BodyBlock);
3785e5dd7070Spatrick   }
3786e5dd7070Spatrick 
3787e5dd7070Spatrick   // Link up the condition block with the code that follows the loop.
3788e5dd7070Spatrick   // (the false branch).
3789e5dd7070Spatrick   addSuccessor(ExitConditionBlock, LoopSuccessor);
3790e5dd7070Spatrick 
3791e5dd7070Spatrick   // Now create a prologue block to contain the collection expression.
3792e5dd7070Spatrick   Block = createBlock();
3793e5dd7070Spatrick   return addStmt(S->getCollection());
3794e5dd7070Spatrick }
3795e5dd7070Spatrick 
VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt * S)3796e5dd7070Spatrick CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
3797e5dd7070Spatrick   // Inline the body.
3798e5dd7070Spatrick   return addStmt(S->getSubStmt());
3799e5dd7070Spatrick   // TODO: consider adding cleanups for the end of @autoreleasepool scope.
3800e5dd7070Spatrick }
3801e5dd7070Spatrick 
VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt * S)3802e5dd7070Spatrick CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
3803e5dd7070Spatrick   // FIXME: Add locking 'primitives' to CFG for @synchronized.
3804e5dd7070Spatrick 
3805e5dd7070Spatrick   // Inline the body.
3806e5dd7070Spatrick   CFGBlock *SyncBlock = addStmt(S->getSynchBody());
3807e5dd7070Spatrick 
3808e5dd7070Spatrick   // The sync body starts its own basic block.  This makes it a little easier
3809e5dd7070Spatrick   // for diagnostic clients.
3810e5dd7070Spatrick   if (SyncBlock) {
3811e5dd7070Spatrick     if (badCFG)
3812e5dd7070Spatrick       return nullptr;
3813e5dd7070Spatrick 
3814e5dd7070Spatrick     Block = nullptr;
3815e5dd7070Spatrick     Succ = SyncBlock;
3816e5dd7070Spatrick   }
3817e5dd7070Spatrick 
3818e5dd7070Spatrick   // Add the @synchronized to the CFG.
3819e5dd7070Spatrick   autoCreateBlock();
3820e5dd7070Spatrick   appendStmt(Block, S);
3821e5dd7070Spatrick 
3822e5dd7070Spatrick   // Inline the sync expression.
3823e5dd7070Spatrick   return addStmt(S->getSynchExpr());
3824e5dd7070Spatrick }
3825e5dd7070Spatrick 
VisitPseudoObjectExpr(PseudoObjectExpr * E)3826e5dd7070Spatrick CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
3827e5dd7070Spatrick   autoCreateBlock();
3828e5dd7070Spatrick 
3829e5dd7070Spatrick   // Add the PseudoObject as the last thing.
3830e5dd7070Spatrick   appendStmt(Block, E);
3831e5dd7070Spatrick 
3832e5dd7070Spatrick   CFGBlock *lastBlock = Block;
3833e5dd7070Spatrick 
3834e5dd7070Spatrick   // Before that, evaluate all of the semantics in order.  In
3835e5dd7070Spatrick   // CFG-land, that means appending them in reverse order.
3836e5dd7070Spatrick   for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {
3837e5dd7070Spatrick     Expr *Semantic = E->getSemanticExpr(--i);
3838e5dd7070Spatrick 
3839e5dd7070Spatrick     // If the semantic is an opaque value, we're being asked to bind
3840e5dd7070Spatrick     // it to its source expression.
3841e5dd7070Spatrick     if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
3842e5dd7070Spatrick       Semantic = OVE->getSourceExpr();
3843e5dd7070Spatrick 
3844e5dd7070Spatrick     if (CFGBlock *B = Visit(Semantic))
3845e5dd7070Spatrick       lastBlock = B;
3846e5dd7070Spatrick   }
3847e5dd7070Spatrick 
3848e5dd7070Spatrick   return lastBlock;
3849e5dd7070Spatrick }
3850e5dd7070Spatrick 
VisitWhileStmt(WhileStmt * W)3851e5dd7070Spatrick CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
3852e5dd7070Spatrick   CFGBlock *LoopSuccessor = nullptr;
3853e5dd7070Spatrick 
3854e5dd7070Spatrick   // Save local scope position because in case of condition variable ScopePos
3855e5dd7070Spatrick   // won't be restored when traversing AST.
3856*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
3857e5dd7070Spatrick 
3858e5dd7070Spatrick   // Create local scope for possible condition variable.
3859e5dd7070Spatrick   // Store scope position for continue statement.
3860e5dd7070Spatrick   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
3861e5dd7070Spatrick   if (VarDecl *VD = W->getConditionVariable()) {
3862e5dd7070Spatrick     addLocalScopeForVarDecl(VD);
3863e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3864e5dd7070Spatrick   }
3865e5dd7070Spatrick   addLoopExit(W);
3866e5dd7070Spatrick 
3867e5dd7070Spatrick   // "while" is a control-flow statement.  Thus we stop processing the current
3868e5dd7070Spatrick   // block.
3869e5dd7070Spatrick   if (Block) {
3870e5dd7070Spatrick     if (badCFG)
3871e5dd7070Spatrick       return nullptr;
3872e5dd7070Spatrick     LoopSuccessor = Block;
3873e5dd7070Spatrick     Block = nullptr;
3874e5dd7070Spatrick   } else {
3875e5dd7070Spatrick     LoopSuccessor = Succ;
3876e5dd7070Spatrick   }
3877e5dd7070Spatrick 
3878e5dd7070Spatrick   CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
3879e5dd7070Spatrick 
3880e5dd7070Spatrick   // Process the loop body.
3881e5dd7070Spatrick   {
3882e5dd7070Spatrick     assert(W->getBody());
3883e5dd7070Spatrick 
3884e5dd7070Spatrick     // Save the current values for Block, Succ, continue and break targets.
3885*12c85518Srobert     SaveAndRestore save_Block(Block), save_Succ(Succ);
3886*12c85518Srobert     SaveAndRestore save_continue(ContinueJumpTarget),
3887e5dd7070Spatrick         save_break(BreakJumpTarget);
3888e5dd7070Spatrick 
3889e5dd7070Spatrick     // Create an empty block to represent the transition block for looping back
3890e5dd7070Spatrick     // to the head of the loop.
3891e5dd7070Spatrick     Succ = TransitionBlock = createBlock(false);
3892e5dd7070Spatrick     TransitionBlock->setLoopTarget(W);
3893e5dd7070Spatrick     ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
3894e5dd7070Spatrick 
3895e5dd7070Spatrick     // All breaks should go to the code following the loop.
3896e5dd7070Spatrick     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
3897e5dd7070Spatrick 
3898e5dd7070Spatrick     // Loop body should end with destructor of Condition variable (if any).
3899e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
3900e5dd7070Spatrick 
3901e5dd7070Spatrick     // If body is not a compound statement create implicit scope
3902e5dd7070Spatrick     // and add destructors.
3903e5dd7070Spatrick     if (!isa<CompoundStmt>(W->getBody()))
3904e5dd7070Spatrick       addLocalScopeAndDtors(W->getBody());
3905e5dd7070Spatrick 
3906e5dd7070Spatrick     // Create the body.  The returned block is the entry to the loop body.
3907e5dd7070Spatrick     BodyBlock = addStmt(W->getBody());
3908e5dd7070Spatrick 
3909e5dd7070Spatrick     if (!BodyBlock)
3910e5dd7070Spatrick       BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
3911e5dd7070Spatrick     else if (Block && badCFG)
3912e5dd7070Spatrick       return nullptr;
3913e5dd7070Spatrick   }
3914e5dd7070Spatrick 
3915e5dd7070Spatrick   // Because of short-circuit evaluation, the condition of the loop can span
3916e5dd7070Spatrick   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
3917e5dd7070Spatrick   // evaluate the condition.
3918e5dd7070Spatrick   CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
3919e5dd7070Spatrick 
3920e5dd7070Spatrick   do {
3921e5dd7070Spatrick     Expr *C = W->getCond();
3922e5dd7070Spatrick 
3923e5dd7070Spatrick     // Specially handle logical operators, which have a slightly
3924e5dd7070Spatrick     // more optimal CFG representation.
3925e5dd7070Spatrick     if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))
3926e5dd7070Spatrick       if (Cond->isLogicalOp()) {
3927e5dd7070Spatrick         std::tie(EntryConditionBlock, ExitConditionBlock) =
3928e5dd7070Spatrick             VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
3929e5dd7070Spatrick         break;
3930e5dd7070Spatrick       }
3931e5dd7070Spatrick 
3932e5dd7070Spatrick     // The default case when not handling logical operators.
3933e5dd7070Spatrick     ExitConditionBlock = createBlock(false);
3934e5dd7070Spatrick     ExitConditionBlock->setTerminator(W);
3935e5dd7070Spatrick 
3936e5dd7070Spatrick     // Now add the actual condition to the condition block.
3937e5dd7070Spatrick     // Because the condition itself may contain control-flow, new blocks may
3938e5dd7070Spatrick     // be created.  Thus we update "Succ" after adding the condition.
3939e5dd7070Spatrick     Block = ExitConditionBlock;
3940e5dd7070Spatrick     Block = EntryConditionBlock = addStmt(C);
3941e5dd7070Spatrick 
3942e5dd7070Spatrick     // If this block contains a condition variable, add both the condition
3943e5dd7070Spatrick     // variable and initializer to the CFG.
3944e5dd7070Spatrick     if (VarDecl *VD = W->getConditionVariable()) {
3945e5dd7070Spatrick       if (Expr *Init = VD->getInit()) {
3946e5dd7070Spatrick         autoCreateBlock();
3947e5dd7070Spatrick         const DeclStmt *DS = W->getConditionVariableDeclStmt();
3948e5dd7070Spatrick         assert(DS->isSingleDecl());
3949e5dd7070Spatrick         findConstructionContexts(
3950e5dd7070Spatrick             ConstructionContextLayer::create(cfg->getBumpVectorContext(),
3951e5dd7070Spatrick                                              const_cast<DeclStmt *>(DS)),
3952e5dd7070Spatrick             Init);
3953e5dd7070Spatrick         appendStmt(Block, DS);
3954e5dd7070Spatrick         EntryConditionBlock = addStmt(Init);
3955e5dd7070Spatrick         assert(Block == EntryConditionBlock);
3956e5dd7070Spatrick         maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
3957e5dd7070Spatrick       }
3958e5dd7070Spatrick     }
3959e5dd7070Spatrick 
3960e5dd7070Spatrick     if (Block && badCFG)
3961e5dd7070Spatrick       return nullptr;
3962e5dd7070Spatrick 
3963e5dd7070Spatrick     // See if this is a known constant.
3964e5dd7070Spatrick     const TryResult& KnownVal = tryEvaluateBool(C);
3965e5dd7070Spatrick 
3966e5dd7070Spatrick     // Add the loop body entry as a successor to the condition.
3967e5dd7070Spatrick     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
3968e5dd7070Spatrick     // Link up the condition block with the code that follows the loop.  (the
3969e5dd7070Spatrick     // false branch).
3970e5dd7070Spatrick     addSuccessor(ExitConditionBlock,
3971e5dd7070Spatrick                  KnownVal.isTrue() ? nullptr : LoopSuccessor);
3972e5dd7070Spatrick   } while(false);
3973e5dd7070Spatrick 
3974e5dd7070Spatrick   // Link up the loop-back block to the entry condition block.
3975e5dd7070Spatrick   addSuccessor(TransitionBlock, EntryConditionBlock);
3976e5dd7070Spatrick 
3977e5dd7070Spatrick   // There can be no more statements in the condition block since we loop back
3978e5dd7070Spatrick   // to this block.  NULL out Block to force lazy creation of another block.
3979e5dd7070Spatrick   Block = nullptr;
3980e5dd7070Spatrick 
3981e5dd7070Spatrick   // Return the condition block, which is the dominating block for the loop.
3982e5dd7070Spatrick   Succ = EntryConditionBlock;
3983e5dd7070Spatrick   return EntryConditionBlock;
3984e5dd7070Spatrick }
3985e5dd7070Spatrick 
VisitArrayInitLoopExpr(ArrayInitLoopExpr * A,AddStmtChoice asc)3986*12c85518Srobert CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
3987*12c85518Srobert                                              AddStmtChoice asc) {
3988*12c85518Srobert   if (asc.alwaysAdd(*this, A)) {
3989*12c85518Srobert     autoCreateBlock();
3990*12c85518Srobert     appendStmt(Block, A);
3991*12c85518Srobert   }
3992*12c85518Srobert 
3993*12c85518Srobert   CFGBlock *B = Block;
3994*12c85518Srobert 
3995*12c85518Srobert   if (CFGBlock *R = Visit(A->getSubExpr()))
3996*12c85518Srobert     B = R;
3997*12c85518Srobert 
3998*12c85518Srobert   auto *OVE = dyn_cast<OpaqueValueExpr>(A->getCommonExpr());
3999*12c85518Srobert   assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
4000*12c85518Srobert                 "OpaqueValueExpr!");
4001*12c85518Srobert   if (CFGBlock *R = Visit(OVE->getSourceExpr()))
4002*12c85518Srobert     B = R;
4003*12c85518Srobert 
4004*12c85518Srobert   return B;
4005*12c85518Srobert }
4006*12c85518Srobert 
VisitObjCAtCatchStmt(ObjCAtCatchStmt * CS)4007*12c85518Srobert CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4008*12c85518Srobert   // ObjCAtCatchStmt are treated like labels, so they are the first statement
4009*12c85518Srobert   // in a block.
4010*12c85518Srobert 
4011*12c85518Srobert   // Save local scope position because in case of exception variable ScopePos
4012*12c85518Srobert   // won't be restored when traversing AST.
4013*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
4014*12c85518Srobert 
4015*12c85518Srobert   if (CS->getCatchBody())
4016*12c85518Srobert     addStmt(CS->getCatchBody());
4017*12c85518Srobert 
4018*12c85518Srobert   CFGBlock *CatchBlock = Block;
4019*12c85518Srobert   if (!CatchBlock)
4020*12c85518Srobert     CatchBlock = createBlock();
4021*12c85518Srobert 
4022*12c85518Srobert   appendStmt(CatchBlock, CS);
4023*12c85518Srobert 
4024*12c85518Srobert   // Also add the ObjCAtCatchStmt as a label, like with regular labels.
4025*12c85518Srobert   CatchBlock->setLabel(CS);
4026*12c85518Srobert 
4027*12c85518Srobert   // Bail out if the CFG is bad.
4028*12c85518Srobert   if (badCFG)
4029*12c85518Srobert     return nullptr;
4030*12c85518Srobert 
4031*12c85518Srobert   // We set Block to NULL to allow lazy creation of a new block (if necessary).
4032*12c85518Srobert   Block = nullptr;
4033*12c85518Srobert 
4034*12c85518Srobert   return CatchBlock;
4035e5dd7070Spatrick }
4036e5dd7070Spatrick 
VisitObjCAtThrowStmt(ObjCAtThrowStmt * S)4037e5dd7070Spatrick CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
4038e5dd7070Spatrick   // If we were in the middle of a block we stop processing that block.
4039e5dd7070Spatrick   if (badCFG)
4040e5dd7070Spatrick     return nullptr;
4041e5dd7070Spatrick 
4042e5dd7070Spatrick   // Create the new block.
4043e5dd7070Spatrick   Block = createBlock(false);
4044e5dd7070Spatrick 
4045*12c85518Srobert   if (TryTerminatedBlock)
4046*12c85518Srobert     // The current try statement is the only successor.
4047*12c85518Srobert     addSuccessor(Block, TryTerminatedBlock);
4048*12c85518Srobert   else
4049*12c85518Srobert     // otherwise the Exit block is the only successor.
4050e5dd7070Spatrick     addSuccessor(Block, &cfg->getExit());
4051e5dd7070Spatrick 
4052e5dd7070Spatrick   // Add the statement to the block.  This may create new blocks if S contains
4053e5dd7070Spatrick   // control-flow (short-circuit operations).
4054e5dd7070Spatrick   return VisitStmt(S, AddStmtChoice::AlwaysAdd);
4055e5dd7070Spatrick }
4056e5dd7070Spatrick 
VisitObjCAtTryStmt(ObjCAtTryStmt * Terminator)4057*12c85518Srobert CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4058*12c85518Srobert   // "@try"/"@catch" is a control-flow statement.  Thus we stop processing the
4059*12c85518Srobert   // current block.
4060*12c85518Srobert   CFGBlock *TrySuccessor = nullptr;
4061*12c85518Srobert 
4062*12c85518Srobert   if (Block) {
4063*12c85518Srobert     if (badCFG)
4064*12c85518Srobert       return nullptr;
4065*12c85518Srobert     TrySuccessor = Block;
4066*12c85518Srobert   } else
4067*12c85518Srobert     TrySuccessor = Succ;
4068*12c85518Srobert 
4069*12c85518Srobert   // FIXME: Implement @finally support.
4070*12c85518Srobert   if (Terminator->getFinallyStmt())
4071*12c85518Srobert     return NYS();
4072*12c85518Srobert 
4073*12c85518Srobert   CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4074*12c85518Srobert 
4075*12c85518Srobert   // Create a new block that will contain the try statement.
4076*12c85518Srobert   CFGBlock *NewTryTerminatedBlock = createBlock(false);
4077*12c85518Srobert   // Add the terminator in the try block.
4078*12c85518Srobert   NewTryTerminatedBlock->setTerminator(Terminator);
4079*12c85518Srobert 
4080*12c85518Srobert   bool HasCatchAll = false;
4081*12c85518Srobert   for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) {
4082*12c85518Srobert     // The code after the try is the implicit successor.
4083*12c85518Srobert     Succ = TrySuccessor;
4084*12c85518Srobert     if (CS->hasEllipsis()) {
4085*12c85518Srobert       HasCatchAll = true;
4086*12c85518Srobert     }
4087*12c85518Srobert     Block = nullptr;
4088*12c85518Srobert     CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4089*12c85518Srobert     if (!CatchBlock)
4090*12c85518Srobert       return nullptr;
4091*12c85518Srobert     // Add this block to the list of successors for the block with the try
4092*12c85518Srobert     // statement.
4093*12c85518Srobert     addSuccessor(NewTryTerminatedBlock, CatchBlock);
4094*12c85518Srobert   }
4095*12c85518Srobert 
4096*12c85518Srobert   // FIXME: This needs updating when @finally support is added.
4097*12c85518Srobert   if (!HasCatchAll) {
4098*12c85518Srobert     if (PrevTryTerminatedBlock)
4099*12c85518Srobert       addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4100*12c85518Srobert     else
4101*12c85518Srobert       addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4102*12c85518Srobert   }
4103*12c85518Srobert 
4104*12c85518Srobert   // The code after the try is the implicit successor.
4105*12c85518Srobert   Succ = TrySuccessor;
4106*12c85518Srobert 
4107*12c85518Srobert   // Save the current "try" context.
4108*12c85518Srobert   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4109*12c85518Srobert   cfg->addTryDispatchBlock(TryTerminatedBlock);
4110*12c85518Srobert 
4111*12c85518Srobert   assert(Terminator->getTryBody() && "try must contain a non-NULL body");
4112*12c85518Srobert   Block = nullptr;
4113*12c85518Srobert   return addStmt(Terminator->getTryBody());
4114*12c85518Srobert }
4115*12c85518Srobert 
VisitObjCMessageExpr(ObjCMessageExpr * ME,AddStmtChoice asc)4116e5dd7070Spatrick CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
4117e5dd7070Spatrick                                            AddStmtChoice asc) {
4118e5dd7070Spatrick   findConstructionContextsForArguments(ME);
4119e5dd7070Spatrick 
4120e5dd7070Spatrick   autoCreateBlock();
4121e5dd7070Spatrick   appendObjCMessage(Block, ME);
4122e5dd7070Spatrick 
4123e5dd7070Spatrick   return VisitChildren(ME);
4124e5dd7070Spatrick }
4125e5dd7070Spatrick 
VisitCXXThrowExpr(CXXThrowExpr * T)4126e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
4127e5dd7070Spatrick   // If we were in the middle of a block we stop processing that block.
4128e5dd7070Spatrick   if (badCFG)
4129e5dd7070Spatrick     return nullptr;
4130e5dd7070Spatrick 
4131e5dd7070Spatrick   // Create the new block.
4132e5dd7070Spatrick   Block = createBlock(false);
4133e5dd7070Spatrick 
4134e5dd7070Spatrick   if (TryTerminatedBlock)
4135e5dd7070Spatrick     // The current try statement is the only successor.
4136e5dd7070Spatrick     addSuccessor(Block, TryTerminatedBlock);
4137e5dd7070Spatrick   else
4138e5dd7070Spatrick     // otherwise the Exit block is the only successor.
4139e5dd7070Spatrick     addSuccessor(Block, &cfg->getExit());
4140e5dd7070Spatrick 
4141e5dd7070Spatrick   // Add the statement to the block.  This may create new blocks if S contains
4142e5dd7070Spatrick   // control-flow (short-circuit operations).
4143e5dd7070Spatrick   return VisitStmt(T, AddStmtChoice::AlwaysAdd);
4144e5dd7070Spatrick }
4145e5dd7070Spatrick 
VisitCXXTypeidExpr(CXXTypeidExpr * S,AddStmtChoice asc)4146*12c85518Srobert CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
4147*12c85518Srobert   if (asc.alwaysAdd(*this, S)) {
4148*12c85518Srobert     autoCreateBlock();
4149*12c85518Srobert     appendStmt(Block, S);
4150*12c85518Srobert   }
4151*12c85518Srobert 
4152*12c85518Srobert   // C++ [expr.typeid]p3:
4153*12c85518Srobert   //   When typeid is applied to an expression other than an glvalue of a
4154*12c85518Srobert   //   polymorphic class type [...] [the] expression is an unevaluated
4155*12c85518Srobert   //   operand. [...]
4156*12c85518Srobert   // We add only potentially evaluated statements to the block to avoid
4157*12c85518Srobert   // CFG generation for unevaluated operands.
4158*12c85518Srobert   if (S && !S->isTypeDependent() && S->isPotentiallyEvaluated())
4159*12c85518Srobert     return VisitChildren(S);
4160*12c85518Srobert 
4161*12c85518Srobert   // Return block without CFG for unevaluated operands.
4162*12c85518Srobert   return Block;
4163*12c85518Srobert }
4164*12c85518Srobert 
VisitDoStmt(DoStmt * D)4165e5dd7070Spatrick CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
4166e5dd7070Spatrick   CFGBlock *LoopSuccessor = nullptr;
4167e5dd7070Spatrick 
4168e5dd7070Spatrick   addLoopExit(D);
4169e5dd7070Spatrick 
4170e5dd7070Spatrick   // "do...while" is a control-flow statement.  Thus we stop processing the
4171e5dd7070Spatrick   // current block.
4172e5dd7070Spatrick   if (Block) {
4173e5dd7070Spatrick     if (badCFG)
4174e5dd7070Spatrick       return nullptr;
4175e5dd7070Spatrick     LoopSuccessor = Block;
4176e5dd7070Spatrick   } else
4177e5dd7070Spatrick     LoopSuccessor = Succ;
4178e5dd7070Spatrick 
4179e5dd7070Spatrick   // Because of short-circuit evaluation, the condition of the loop can span
4180e5dd7070Spatrick   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
4181e5dd7070Spatrick   // evaluate the condition.
4182e5dd7070Spatrick   CFGBlock *ExitConditionBlock = createBlock(false);
4183e5dd7070Spatrick   CFGBlock *EntryConditionBlock = ExitConditionBlock;
4184e5dd7070Spatrick 
4185e5dd7070Spatrick   // Set the terminator for the "exit" condition block.
4186e5dd7070Spatrick   ExitConditionBlock->setTerminator(D);
4187e5dd7070Spatrick 
4188e5dd7070Spatrick   // Now add the actual condition to the condition block.  Because the condition
4189e5dd7070Spatrick   // itself may contain control-flow, new blocks may be created.
4190e5dd7070Spatrick   if (Stmt *C = D->getCond()) {
4191e5dd7070Spatrick     Block = ExitConditionBlock;
4192e5dd7070Spatrick     EntryConditionBlock = addStmt(C);
4193e5dd7070Spatrick     if (Block) {
4194e5dd7070Spatrick       if (badCFG)
4195e5dd7070Spatrick         return nullptr;
4196e5dd7070Spatrick     }
4197e5dd7070Spatrick   }
4198e5dd7070Spatrick 
4199e5dd7070Spatrick   // The condition block is the implicit successor for the loop body.
4200e5dd7070Spatrick   Succ = EntryConditionBlock;
4201e5dd7070Spatrick 
4202e5dd7070Spatrick   // See if this is a known constant.
4203e5dd7070Spatrick   const TryResult &KnownVal = tryEvaluateBool(D->getCond());
4204e5dd7070Spatrick 
4205e5dd7070Spatrick   // Process the loop body.
4206e5dd7070Spatrick   CFGBlock *BodyBlock = nullptr;
4207e5dd7070Spatrick   {
4208e5dd7070Spatrick     assert(D->getBody());
4209e5dd7070Spatrick 
4210e5dd7070Spatrick     // Save the current values for Block, Succ, and continue and break targets
4211*12c85518Srobert     SaveAndRestore save_Block(Block), save_Succ(Succ);
4212*12c85518Srobert     SaveAndRestore save_continue(ContinueJumpTarget),
4213e5dd7070Spatrick         save_break(BreakJumpTarget);
4214e5dd7070Spatrick 
4215e5dd7070Spatrick     // All continues within this loop should go to the condition block
4216e5dd7070Spatrick     ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
4217e5dd7070Spatrick 
4218e5dd7070Spatrick     // All breaks should go to the code following the loop.
4219e5dd7070Spatrick     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4220e5dd7070Spatrick 
4221e5dd7070Spatrick     // NULL out Block to force lazy instantiation of blocks for the body.
4222e5dd7070Spatrick     Block = nullptr;
4223e5dd7070Spatrick 
4224e5dd7070Spatrick     // If body is not a compound statement create implicit scope
4225e5dd7070Spatrick     // and add destructors.
4226e5dd7070Spatrick     if (!isa<CompoundStmt>(D->getBody()))
4227e5dd7070Spatrick       addLocalScopeAndDtors(D->getBody());
4228e5dd7070Spatrick 
4229e5dd7070Spatrick     // Create the body.  The returned block is the entry to the loop body.
4230e5dd7070Spatrick     BodyBlock = addStmt(D->getBody());
4231e5dd7070Spatrick 
4232e5dd7070Spatrick     if (!BodyBlock)
4233e5dd7070Spatrick       BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
4234e5dd7070Spatrick     else if (Block) {
4235e5dd7070Spatrick       if (badCFG)
4236e5dd7070Spatrick         return nullptr;
4237e5dd7070Spatrick     }
4238e5dd7070Spatrick 
4239e5dd7070Spatrick     // Add an intermediate block between the BodyBlock and the
4240e5dd7070Spatrick     // ExitConditionBlock to represent the "loop back" transition.  Create an
4241e5dd7070Spatrick     // empty block to represent the transition block for looping back to the
4242e5dd7070Spatrick     // head of the loop.
4243e5dd7070Spatrick     // FIXME: Can we do this more efficiently without adding another block?
4244e5dd7070Spatrick     Block = nullptr;
4245e5dd7070Spatrick     Succ = BodyBlock;
4246e5dd7070Spatrick     CFGBlock *LoopBackBlock = createBlock();
4247e5dd7070Spatrick     LoopBackBlock->setLoopTarget(D);
4248e5dd7070Spatrick 
4249e5dd7070Spatrick     if (!KnownVal.isFalse())
4250e5dd7070Spatrick       // Add the loop body entry as a successor to the condition.
4251e5dd7070Spatrick       addSuccessor(ExitConditionBlock, LoopBackBlock);
4252e5dd7070Spatrick     else
4253e5dd7070Spatrick       addSuccessor(ExitConditionBlock, nullptr);
4254e5dd7070Spatrick   }
4255e5dd7070Spatrick 
4256e5dd7070Spatrick   // Link up the condition block with the code that follows the loop.
4257e5dd7070Spatrick   // (the false branch).
4258e5dd7070Spatrick   addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4259e5dd7070Spatrick 
4260e5dd7070Spatrick   // There can be no more statements in the body block(s) since we loop back to
4261e5dd7070Spatrick   // the body.  NULL out Block to force lazy creation of another block.
4262e5dd7070Spatrick   Block = nullptr;
4263e5dd7070Spatrick 
4264e5dd7070Spatrick   // Return the loop body, which is the dominating block for the loop.
4265e5dd7070Spatrick   Succ = BodyBlock;
4266e5dd7070Spatrick   return BodyBlock;
4267e5dd7070Spatrick }
4268e5dd7070Spatrick 
VisitContinueStmt(ContinueStmt * C)4269e5dd7070Spatrick CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
4270e5dd7070Spatrick   // "continue" is a control-flow statement.  Thus we stop processing the
4271e5dd7070Spatrick   // current block.
4272e5dd7070Spatrick   if (badCFG)
4273e5dd7070Spatrick     return nullptr;
4274e5dd7070Spatrick 
4275e5dd7070Spatrick   // Now create a new block that ends with the continue statement.
4276e5dd7070Spatrick   Block = createBlock(false);
4277e5dd7070Spatrick   Block->setTerminator(C);
4278e5dd7070Spatrick 
4279e5dd7070Spatrick   // If there is no target for the continue, then we are looking at an
4280e5dd7070Spatrick   // incomplete AST.  This means the CFG cannot be constructed.
4281e5dd7070Spatrick   if (ContinueJumpTarget.block) {
4282e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
4283e5dd7070Spatrick     addSuccessor(Block, ContinueJumpTarget.block);
4284e5dd7070Spatrick   } else
4285e5dd7070Spatrick     badCFG = true;
4286e5dd7070Spatrick 
4287e5dd7070Spatrick   return Block;
4288e5dd7070Spatrick }
4289e5dd7070Spatrick 
VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr * E,AddStmtChoice asc)4290e5dd7070Spatrick CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
4291e5dd7070Spatrick                                                     AddStmtChoice asc) {
4292e5dd7070Spatrick   if (asc.alwaysAdd(*this, E)) {
4293e5dd7070Spatrick     autoCreateBlock();
4294e5dd7070Spatrick     appendStmt(Block, E);
4295e5dd7070Spatrick   }
4296e5dd7070Spatrick 
4297e5dd7070Spatrick   // VLA types have expressions that must be evaluated.
4298ec727ea7Spatrick   // Evaluation is done only for `sizeof`.
4299ec727ea7Spatrick 
4300ec727ea7Spatrick   if (E->getKind() != UETT_SizeOf)
4301ec727ea7Spatrick     return Block;
4302ec727ea7Spatrick 
4303e5dd7070Spatrick   CFGBlock *lastBlock = Block;
4304e5dd7070Spatrick 
4305e5dd7070Spatrick   if (E->isArgumentType()) {
4306e5dd7070Spatrick     for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
4307e5dd7070Spatrick          VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
4308e5dd7070Spatrick       lastBlock = addStmt(VA->getSizeExpr());
4309e5dd7070Spatrick   }
4310e5dd7070Spatrick   return lastBlock;
4311e5dd7070Spatrick }
4312e5dd7070Spatrick 
4313e5dd7070Spatrick /// VisitStmtExpr - Utility method to handle (nested) statement
4314e5dd7070Spatrick ///  expressions (a GCC extension).
VisitStmtExpr(StmtExpr * SE,AddStmtChoice asc)4315e5dd7070Spatrick CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
4316e5dd7070Spatrick   if (asc.alwaysAdd(*this, SE)) {
4317e5dd7070Spatrick     autoCreateBlock();
4318e5dd7070Spatrick     appendStmt(Block, SE);
4319e5dd7070Spatrick   }
4320e5dd7070Spatrick   return VisitCompoundStmt(SE->getSubStmt(), /*ExternallyDestructed=*/true);
4321e5dd7070Spatrick }
4322e5dd7070Spatrick 
VisitSwitchStmt(SwitchStmt * Terminator)4323e5dd7070Spatrick CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
4324e5dd7070Spatrick   // "switch" is a control-flow statement.  Thus we stop processing the current
4325e5dd7070Spatrick   // block.
4326e5dd7070Spatrick   CFGBlock *SwitchSuccessor = nullptr;
4327e5dd7070Spatrick 
4328e5dd7070Spatrick   // Save local scope position because in case of condition variable ScopePos
4329e5dd7070Spatrick   // won't be restored when traversing AST.
4330*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
4331e5dd7070Spatrick 
4332e5dd7070Spatrick   // Create local scope for C++17 switch init-stmt if one exists.
4333e5dd7070Spatrick   if (Stmt *Init = Terminator->getInit())
4334e5dd7070Spatrick     addLocalScopeForStmt(Init);
4335e5dd7070Spatrick 
4336e5dd7070Spatrick   // Create local scope for possible condition variable.
4337e5dd7070Spatrick   // Store scope position. Add implicit destructor.
4338e5dd7070Spatrick   if (VarDecl *VD = Terminator->getConditionVariable())
4339e5dd7070Spatrick     addLocalScopeForVarDecl(VD);
4340e5dd7070Spatrick 
4341e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
4342e5dd7070Spatrick 
4343e5dd7070Spatrick   if (Block) {
4344e5dd7070Spatrick     if (badCFG)
4345e5dd7070Spatrick       return nullptr;
4346e5dd7070Spatrick     SwitchSuccessor = Block;
4347e5dd7070Spatrick   } else SwitchSuccessor = Succ;
4348e5dd7070Spatrick 
4349e5dd7070Spatrick   // Save the current "switch" context.
4350*12c85518Srobert   SaveAndRestore save_switch(SwitchTerminatedBlock),
4351e5dd7070Spatrick       save_default(DefaultCaseBlock);
4352*12c85518Srobert   SaveAndRestore save_break(BreakJumpTarget);
4353e5dd7070Spatrick 
4354e5dd7070Spatrick   // Set the "default" case to be the block after the switch statement.  If the
4355e5dd7070Spatrick   // switch statement contains a "default:", this value will be overwritten with
4356e5dd7070Spatrick   // the block for that code.
4357e5dd7070Spatrick   DefaultCaseBlock = SwitchSuccessor;
4358e5dd7070Spatrick 
4359e5dd7070Spatrick   // Create a new block that will contain the switch statement.
4360e5dd7070Spatrick   SwitchTerminatedBlock = createBlock(false);
4361e5dd7070Spatrick 
4362e5dd7070Spatrick   // Now process the switch body.  The code after the switch is the implicit
4363e5dd7070Spatrick   // successor.
4364e5dd7070Spatrick   Succ = SwitchSuccessor;
4365e5dd7070Spatrick   BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
4366e5dd7070Spatrick 
4367e5dd7070Spatrick   // When visiting the body, the case statements should automatically get linked
4368e5dd7070Spatrick   // up to the switch.  We also don't keep a pointer to the body, since all
4369e5dd7070Spatrick   // control-flow from the switch goes to case/default statements.
4370e5dd7070Spatrick   assert(Terminator->getBody() && "switch must contain a non-NULL body");
4371e5dd7070Spatrick   Block = nullptr;
4372e5dd7070Spatrick 
4373e5dd7070Spatrick   // For pruning unreachable case statements, save the current state
4374e5dd7070Spatrick   // for tracking the condition value.
4375*12c85518Srobert   SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, false);
4376e5dd7070Spatrick 
4377e5dd7070Spatrick   // Determine if the switch condition can be explicitly evaluated.
4378e5dd7070Spatrick   assert(Terminator->getCond() && "switch condition must be non-NULL");
4379e5dd7070Spatrick   Expr::EvalResult result;
4380e5dd7070Spatrick   bool b = tryEvaluate(Terminator->getCond(), result);
4381*12c85518Srobert   SaveAndRestore save_switchCond(switchCond, b ? &result : nullptr);
4382e5dd7070Spatrick 
4383e5dd7070Spatrick   // If body is not a compound statement create implicit scope
4384e5dd7070Spatrick   // and add destructors.
4385e5dd7070Spatrick   if (!isa<CompoundStmt>(Terminator->getBody()))
4386e5dd7070Spatrick     addLocalScopeAndDtors(Terminator->getBody());
4387e5dd7070Spatrick 
4388e5dd7070Spatrick   addStmt(Terminator->getBody());
4389e5dd7070Spatrick   if (Block) {
4390e5dd7070Spatrick     if (badCFG)
4391e5dd7070Spatrick       return nullptr;
4392e5dd7070Spatrick   }
4393e5dd7070Spatrick 
4394e5dd7070Spatrick   // If we have no "default:" case, the default transition is to the code
4395e5dd7070Spatrick   // following the switch body.  Moreover, take into account if all the
4396e5dd7070Spatrick   // cases of a switch are covered (e.g., switching on an enum value).
4397e5dd7070Spatrick   //
4398e5dd7070Spatrick   // Note: We add a successor to a switch that is considered covered yet has no
4399e5dd7070Spatrick   //       case statements if the enumeration has no enumerators.
4400e5dd7070Spatrick   bool SwitchAlwaysHasSuccessor = false;
4401e5dd7070Spatrick   SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
4402e5dd7070Spatrick   SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() &&
4403e5dd7070Spatrick                               Terminator->getSwitchCaseList();
4404e5dd7070Spatrick   addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
4405e5dd7070Spatrick                !SwitchAlwaysHasSuccessor);
4406e5dd7070Spatrick 
4407e5dd7070Spatrick   // Add the terminator and condition in the switch block.
4408e5dd7070Spatrick   SwitchTerminatedBlock->setTerminator(Terminator);
4409e5dd7070Spatrick   Block = SwitchTerminatedBlock;
4410e5dd7070Spatrick   CFGBlock *LastBlock = addStmt(Terminator->getCond());
4411e5dd7070Spatrick 
4412e5dd7070Spatrick   // If the SwitchStmt contains a condition variable, add both the
4413e5dd7070Spatrick   // SwitchStmt and the condition variable initialization to the CFG.
4414e5dd7070Spatrick   if (VarDecl *VD = Terminator->getConditionVariable()) {
4415e5dd7070Spatrick     if (Expr *Init = VD->getInit()) {
4416e5dd7070Spatrick       autoCreateBlock();
4417e5dd7070Spatrick       appendStmt(Block, Terminator->getConditionVariableDeclStmt());
4418e5dd7070Spatrick       LastBlock = addStmt(Init);
4419e5dd7070Spatrick       maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
4420e5dd7070Spatrick     }
4421e5dd7070Spatrick   }
4422e5dd7070Spatrick 
4423e5dd7070Spatrick   // Finally, if the SwitchStmt contains a C++17 init-stmt, add it to the CFG.
4424e5dd7070Spatrick   if (Stmt *Init = Terminator->getInit()) {
4425e5dd7070Spatrick     autoCreateBlock();
4426e5dd7070Spatrick     LastBlock = addStmt(Init);
4427e5dd7070Spatrick   }
4428e5dd7070Spatrick 
4429e5dd7070Spatrick   return LastBlock;
4430e5dd7070Spatrick }
4431e5dd7070Spatrick 
shouldAddCase(bool & switchExclusivelyCovered,const Expr::EvalResult * switchCond,const CaseStmt * CS,ASTContext & Ctx)4432e5dd7070Spatrick static bool shouldAddCase(bool &switchExclusivelyCovered,
4433e5dd7070Spatrick                           const Expr::EvalResult *switchCond,
4434e5dd7070Spatrick                           const CaseStmt *CS,
4435e5dd7070Spatrick                           ASTContext &Ctx) {
4436e5dd7070Spatrick   if (!switchCond)
4437e5dd7070Spatrick     return true;
4438e5dd7070Spatrick 
4439e5dd7070Spatrick   bool addCase = false;
4440e5dd7070Spatrick 
4441e5dd7070Spatrick   if (!switchExclusivelyCovered) {
4442e5dd7070Spatrick     if (switchCond->Val.isInt()) {
4443e5dd7070Spatrick       // Evaluate the LHS of the case value.
4444e5dd7070Spatrick       const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx);
4445e5dd7070Spatrick       const llvm::APSInt &condInt = switchCond->Val.getInt();
4446e5dd7070Spatrick 
4447e5dd7070Spatrick       if (condInt == lhsInt) {
4448e5dd7070Spatrick         addCase = true;
4449e5dd7070Spatrick         switchExclusivelyCovered = true;
4450e5dd7070Spatrick       }
4451e5dd7070Spatrick       else if (condInt > lhsInt) {
4452e5dd7070Spatrick         if (const Expr *RHS = CS->getRHS()) {
4453e5dd7070Spatrick           // Evaluate the RHS of the case value.
4454e5dd7070Spatrick           const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
4455e5dd7070Spatrick           if (V2 >= condInt) {
4456e5dd7070Spatrick             addCase = true;
4457e5dd7070Spatrick             switchExclusivelyCovered = true;
4458e5dd7070Spatrick           }
4459e5dd7070Spatrick         }
4460e5dd7070Spatrick       }
4461e5dd7070Spatrick     }
4462e5dd7070Spatrick     else
4463e5dd7070Spatrick       addCase = true;
4464e5dd7070Spatrick   }
4465e5dd7070Spatrick   return addCase;
4466e5dd7070Spatrick }
4467e5dd7070Spatrick 
VisitCaseStmt(CaseStmt * CS)4468e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
4469e5dd7070Spatrick   // CaseStmts are essentially labels, so they are the first statement in a
4470e5dd7070Spatrick   // block.
4471e5dd7070Spatrick   CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;
4472e5dd7070Spatrick 
4473e5dd7070Spatrick   if (Stmt *Sub = CS->getSubStmt()) {
4474e5dd7070Spatrick     // For deeply nested chains of CaseStmts, instead of doing a recursion
4475e5dd7070Spatrick     // (which can blow out the stack), manually unroll and create blocks
4476e5dd7070Spatrick     // along the way.
4477e5dd7070Spatrick     while (isa<CaseStmt>(Sub)) {
4478e5dd7070Spatrick       CFGBlock *currentBlock = createBlock(false);
4479e5dd7070Spatrick       currentBlock->setLabel(CS);
4480e5dd7070Spatrick 
4481e5dd7070Spatrick       if (TopBlock)
4482e5dd7070Spatrick         addSuccessor(LastBlock, currentBlock);
4483e5dd7070Spatrick       else
4484e5dd7070Spatrick         TopBlock = currentBlock;
4485e5dd7070Spatrick 
4486e5dd7070Spatrick       addSuccessor(SwitchTerminatedBlock,
4487e5dd7070Spatrick                    shouldAddCase(switchExclusivelyCovered, switchCond,
4488e5dd7070Spatrick                                  CS, *Context)
4489e5dd7070Spatrick                    ? currentBlock : nullptr);
4490e5dd7070Spatrick 
4491e5dd7070Spatrick       LastBlock = currentBlock;
4492e5dd7070Spatrick       CS = cast<CaseStmt>(Sub);
4493e5dd7070Spatrick       Sub = CS->getSubStmt();
4494e5dd7070Spatrick     }
4495e5dd7070Spatrick 
4496e5dd7070Spatrick     addStmt(Sub);
4497e5dd7070Spatrick   }
4498e5dd7070Spatrick 
4499e5dd7070Spatrick   CFGBlock *CaseBlock = Block;
4500e5dd7070Spatrick   if (!CaseBlock)
4501e5dd7070Spatrick     CaseBlock = createBlock();
4502e5dd7070Spatrick 
4503e5dd7070Spatrick   // Cases statements partition blocks, so this is the top of the basic block we
4504e5dd7070Spatrick   // were processing (the "case XXX:" is the label).
4505e5dd7070Spatrick   CaseBlock->setLabel(CS);
4506e5dd7070Spatrick 
4507e5dd7070Spatrick   if (badCFG)
4508e5dd7070Spatrick     return nullptr;
4509e5dd7070Spatrick 
4510e5dd7070Spatrick   // Add this block to the list of successors for the block with the switch
4511e5dd7070Spatrick   // statement.
4512e5dd7070Spatrick   assert(SwitchTerminatedBlock);
4513e5dd7070Spatrick   addSuccessor(SwitchTerminatedBlock, CaseBlock,
4514e5dd7070Spatrick                shouldAddCase(switchExclusivelyCovered, switchCond,
4515e5dd7070Spatrick                              CS, *Context));
4516e5dd7070Spatrick 
4517*12c85518Srobert   // We set Block to NULL to allow lazy creation of a new block (if necessary).
4518e5dd7070Spatrick   Block = nullptr;
4519e5dd7070Spatrick 
4520e5dd7070Spatrick   if (TopBlock) {
4521e5dd7070Spatrick     addSuccessor(LastBlock, CaseBlock);
4522e5dd7070Spatrick     Succ = TopBlock;
4523e5dd7070Spatrick   } else {
4524e5dd7070Spatrick     // This block is now the implicit successor of other blocks.
4525e5dd7070Spatrick     Succ = CaseBlock;
4526e5dd7070Spatrick   }
4527e5dd7070Spatrick 
4528e5dd7070Spatrick   return Succ;
4529e5dd7070Spatrick }
4530e5dd7070Spatrick 
VisitDefaultStmt(DefaultStmt * Terminator)4531e5dd7070Spatrick CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
4532e5dd7070Spatrick   if (Terminator->getSubStmt())
4533e5dd7070Spatrick     addStmt(Terminator->getSubStmt());
4534e5dd7070Spatrick 
4535e5dd7070Spatrick   DefaultCaseBlock = Block;
4536e5dd7070Spatrick 
4537e5dd7070Spatrick   if (!DefaultCaseBlock)
4538e5dd7070Spatrick     DefaultCaseBlock = createBlock();
4539e5dd7070Spatrick 
4540e5dd7070Spatrick   // Default statements partition blocks, so this is the top of the basic block
4541e5dd7070Spatrick   // we were processing (the "default:" is the label).
4542e5dd7070Spatrick   DefaultCaseBlock->setLabel(Terminator);
4543e5dd7070Spatrick 
4544e5dd7070Spatrick   if (badCFG)
4545e5dd7070Spatrick     return nullptr;
4546e5dd7070Spatrick 
4547e5dd7070Spatrick   // Unlike case statements, we don't add the default block to the successors
4548e5dd7070Spatrick   // for the switch statement immediately.  This is done when we finish
4549e5dd7070Spatrick   // processing the switch statement.  This allows for the default case
4550e5dd7070Spatrick   // (including a fall-through to the code after the switch statement) to always
4551e5dd7070Spatrick   // be the last successor of a switch-terminated block.
4552e5dd7070Spatrick 
4553*12c85518Srobert   // We set Block to NULL to allow lazy creation of a new block (if necessary).
4554e5dd7070Spatrick   Block = nullptr;
4555e5dd7070Spatrick 
4556e5dd7070Spatrick   // This block is now the implicit successor of other blocks.
4557e5dd7070Spatrick   Succ = DefaultCaseBlock;
4558e5dd7070Spatrick 
4559e5dd7070Spatrick   return DefaultCaseBlock;
4560e5dd7070Spatrick }
4561e5dd7070Spatrick 
VisitCXXTryStmt(CXXTryStmt * Terminator)4562e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
4563e5dd7070Spatrick   // "try"/"catch" is a control-flow statement.  Thus we stop processing the
4564e5dd7070Spatrick   // current block.
4565e5dd7070Spatrick   CFGBlock *TrySuccessor = nullptr;
4566e5dd7070Spatrick 
4567e5dd7070Spatrick   if (Block) {
4568e5dd7070Spatrick     if (badCFG)
4569e5dd7070Spatrick       return nullptr;
4570e5dd7070Spatrick     TrySuccessor = Block;
4571*12c85518Srobert   } else
4572*12c85518Srobert     TrySuccessor = Succ;
4573e5dd7070Spatrick 
4574e5dd7070Spatrick   CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4575e5dd7070Spatrick 
4576e5dd7070Spatrick   // Create a new block that will contain the try statement.
4577e5dd7070Spatrick   CFGBlock *NewTryTerminatedBlock = createBlock(false);
4578e5dd7070Spatrick   // Add the terminator in the try block.
4579e5dd7070Spatrick   NewTryTerminatedBlock->setTerminator(Terminator);
4580e5dd7070Spatrick 
4581e5dd7070Spatrick   bool HasCatchAll = false;
4582*12c85518Srobert   for (unsigned I = 0, E = Terminator->getNumHandlers(); I != E; ++I) {
4583e5dd7070Spatrick     // The code after the try is the implicit successor.
4584e5dd7070Spatrick     Succ = TrySuccessor;
4585*12c85518Srobert     CXXCatchStmt *CS = Terminator->getHandler(I);
4586e5dd7070Spatrick     if (CS->getExceptionDecl() == nullptr) {
4587e5dd7070Spatrick       HasCatchAll = true;
4588e5dd7070Spatrick     }
4589e5dd7070Spatrick     Block = nullptr;
4590e5dd7070Spatrick     CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
4591e5dd7070Spatrick     if (!CatchBlock)
4592e5dd7070Spatrick       return nullptr;
4593e5dd7070Spatrick     // Add this block to the list of successors for the block with the try
4594e5dd7070Spatrick     // statement.
4595e5dd7070Spatrick     addSuccessor(NewTryTerminatedBlock, CatchBlock);
4596e5dd7070Spatrick   }
4597e5dd7070Spatrick   if (!HasCatchAll) {
4598e5dd7070Spatrick     if (PrevTryTerminatedBlock)
4599e5dd7070Spatrick       addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4600e5dd7070Spatrick     else
4601e5dd7070Spatrick       addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4602e5dd7070Spatrick   }
4603e5dd7070Spatrick 
4604e5dd7070Spatrick   // The code after the try is the implicit successor.
4605e5dd7070Spatrick   Succ = TrySuccessor;
4606e5dd7070Spatrick 
4607e5dd7070Spatrick   // Save the current "try" context.
4608*12c85518Srobert   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4609e5dd7070Spatrick   cfg->addTryDispatchBlock(TryTerminatedBlock);
4610e5dd7070Spatrick 
4611e5dd7070Spatrick   assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
4612e5dd7070Spatrick   Block = nullptr;
4613e5dd7070Spatrick   return addStmt(Terminator->getTryBlock());
4614e5dd7070Spatrick }
4615e5dd7070Spatrick 
VisitCXXCatchStmt(CXXCatchStmt * CS)4616e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
4617e5dd7070Spatrick   // CXXCatchStmt are treated like labels, so they are the first statement in a
4618e5dd7070Spatrick   // block.
4619e5dd7070Spatrick 
4620e5dd7070Spatrick   // Save local scope position because in case of exception variable ScopePos
4621e5dd7070Spatrick   // won't be restored when traversing AST.
4622*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
4623e5dd7070Spatrick 
4624e5dd7070Spatrick   // Create local scope for possible exception variable.
4625e5dd7070Spatrick   // Store scope position. Add implicit destructor.
4626e5dd7070Spatrick   if (VarDecl *VD = CS->getExceptionDecl()) {
4627e5dd7070Spatrick     LocalScope::const_iterator BeginScopePos = ScopePos;
4628e5dd7070Spatrick     addLocalScopeForVarDecl(VD);
4629e5dd7070Spatrick     addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
4630e5dd7070Spatrick   }
4631e5dd7070Spatrick 
4632e5dd7070Spatrick   if (CS->getHandlerBlock())
4633e5dd7070Spatrick     addStmt(CS->getHandlerBlock());
4634e5dd7070Spatrick 
4635e5dd7070Spatrick   CFGBlock *CatchBlock = Block;
4636e5dd7070Spatrick   if (!CatchBlock)
4637e5dd7070Spatrick     CatchBlock = createBlock();
4638e5dd7070Spatrick 
4639e5dd7070Spatrick   // CXXCatchStmt is more than just a label.  They have semantic meaning
4640e5dd7070Spatrick   // as well, as they implicitly "initialize" the catch variable.  Add
4641e5dd7070Spatrick   // it to the CFG as a CFGElement so that the control-flow of these
4642e5dd7070Spatrick   // semantics gets captured.
4643e5dd7070Spatrick   appendStmt(CatchBlock, CS);
4644e5dd7070Spatrick 
4645e5dd7070Spatrick   // Also add the CXXCatchStmt as a label, to mirror handling of regular
4646e5dd7070Spatrick   // labels.
4647e5dd7070Spatrick   CatchBlock->setLabel(CS);
4648e5dd7070Spatrick 
4649e5dd7070Spatrick   // Bail out if the CFG is bad.
4650e5dd7070Spatrick   if (badCFG)
4651e5dd7070Spatrick     return nullptr;
4652e5dd7070Spatrick 
4653*12c85518Srobert   // We set Block to NULL to allow lazy creation of a new block (if necessary).
4654e5dd7070Spatrick   Block = nullptr;
4655e5dd7070Spatrick 
4656e5dd7070Spatrick   return CatchBlock;
4657e5dd7070Spatrick }
4658e5dd7070Spatrick 
VisitCXXForRangeStmt(CXXForRangeStmt * S)4659e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
4660e5dd7070Spatrick   // C++0x for-range statements are specified as [stmt.ranged]:
4661e5dd7070Spatrick   //
4662e5dd7070Spatrick   // {
4663e5dd7070Spatrick   //   auto && __range = range-init;
4664e5dd7070Spatrick   //   for ( auto __begin = begin-expr,
4665e5dd7070Spatrick   //         __end = end-expr;
4666e5dd7070Spatrick   //         __begin != __end;
4667e5dd7070Spatrick   //         ++__begin ) {
4668e5dd7070Spatrick   //     for-range-declaration = *__begin;
4669e5dd7070Spatrick   //     statement
4670e5dd7070Spatrick   //   }
4671e5dd7070Spatrick   // }
4672e5dd7070Spatrick 
4673e5dd7070Spatrick   // Save local scope position before the addition of the implicit variables.
4674*12c85518Srobert   SaveAndRestore save_scope_pos(ScopePos);
4675e5dd7070Spatrick 
4676e5dd7070Spatrick   // Create local scopes and destructors for range, begin and end variables.
4677e5dd7070Spatrick   if (Stmt *Range = S->getRangeStmt())
4678e5dd7070Spatrick     addLocalScopeForStmt(Range);
4679e5dd7070Spatrick   if (Stmt *Begin = S->getBeginStmt())
4680e5dd7070Spatrick     addLocalScopeForStmt(Begin);
4681e5dd7070Spatrick   if (Stmt *End = S->getEndStmt())
4682e5dd7070Spatrick     addLocalScopeForStmt(End);
4683e5dd7070Spatrick   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
4684e5dd7070Spatrick 
4685e5dd7070Spatrick   LocalScope::const_iterator ContinueScopePos = ScopePos;
4686e5dd7070Spatrick 
4687e5dd7070Spatrick   // "for" is a control-flow statement.  Thus we stop processing the current
4688e5dd7070Spatrick   // block.
4689e5dd7070Spatrick   CFGBlock *LoopSuccessor = nullptr;
4690e5dd7070Spatrick   if (Block) {
4691e5dd7070Spatrick     if (badCFG)
4692e5dd7070Spatrick       return nullptr;
4693e5dd7070Spatrick     LoopSuccessor = Block;
4694e5dd7070Spatrick   } else
4695e5dd7070Spatrick     LoopSuccessor = Succ;
4696e5dd7070Spatrick 
4697e5dd7070Spatrick   // Save the current value for the break targets.
4698e5dd7070Spatrick   // All breaks should go to the code following the loop.
4699*12c85518Srobert   SaveAndRestore save_break(BreakJumpTarget);
4700e5dd7070Spatrick   BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
4701e5dd7070Spatrick 
4702e5dd7070Spatrick   // The block for the __begin != __end expression.
4703e5dd7070Spatrick   CFGBlock *ConditionBlock = createBlock(false);
4704e5dd7070Spatrick   ConditionBlock->setTerminator(S);
4705e5dd7070Spatrick 
4706e5dd7070Spatrick   // Now add the actual condition to the condition block.
4707e5dd7070Spatrick   if (Expr *C = S->getCond()) {
4708e5dd7070Spatrick     Block = ConditionBlock;
4709e5dd7070Spatrick     CFGBlock *BeginConditionBlock = addStmt(C);
4710e5dd7070Spatrick     if (badCFG)
4711e5dd7070Spatrick       return nullptr;
4712e5dd7070Spatrick     assert(BeginConditionBlock == ConditionBlock &&
4713e5dd7070Spatrick            "condition block in for-range was unexpectedly complex");
4714e5dd7070Spatrick     (void)BeginConditionBlock;
4715e5dd7070Spatrick   }
4716e5dd7070Spatrick 
4717e5dd7070Spatrick   // The condition block is the implicit successor for the loop body as well as
4718e5dd7070Spatrick   // any code above the loop.
4719e5dd7070Spatrick   Succ = ConditionBlock;
4720e5dd7070Spatrick 
4721e5dd7070Spatrick   // See if this is a known constant.
4722e5dd7070Spatrick   TryResult KnownVal(true);
4723e5dd7070Spatrick 
4724e5dd7070Spatrick   if (S->getCond())
4725e5dd7070Spatrick     KnownVal = tryEvaluateBool(S->getCond());
4726e5dd7070Spatrick 
4727e5dd7070Spatrick   // Now create the loop body.
4728e5dd7070Spatrick   {
4729e5dd7070Spatrick     assert(S->getBody());
4730e5dd7070Spatrick 
4731e5dd7070Spatrick     // Save the current values for Block, Succ, and continue targets.
4732*12c85518Srobert     SaveAndRestore save_Block(Block), save_Succ(Succ);
4733*12c85518Srobert     SaveAndRestore save_continue(ContinueJumpTarget);
4734e5dd7070Spatrick 
4735e5dd7070Spatrick     // Generate increment code in its own basic block.  This is the target of
4736e5dd7070Spatrick     // continue statements.
4737e5dd7070Spatrick     Block = nullptr;
4738e5dd7070Spatrick     Succ = addStmt(S->getInc());
4739e5dd7070Spatrick     if (badCFG)
4740e5dd7070Spatrick       return nullptr;
4741e5dd7070Spatrick     ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
4742e5dd7070Spatrick 
4743e5dd7070Spatrick     // The starting block for the loop increment is the block that should
4744e5dd7070Spatrick     // represent the 'loop target' for looping back to the start of the loop.
4745e5dd7070Spatrick     ContinueJumpTarget.block->setLoopTarget(S);
4746e5dd7070Spatrick 
4747e5dd7070Spatrick     // Finish up the increment block and prepare to start the loop body.
4748e5dd7070Spatrick     assert(Block);
4749e5dd7070Spatrick     if (badCFG)
4750e5dd7070Spatrick       return nullptr;
4751e5dd7070Spatrick     Block = nullptr;
4752e5dd7070Spatrick 
4753e5dd7070Spatrick     // Add implicit scope and dtors for loop variable.
4754e5dd7070Spatrick     addLocalScopeAndDtors(S->getLoopVarStmt());
4755e5dd7070Spatrick 
4756a9ac8606Spatrick     // If body is not a compound statement create implicit scope
4757a9ac8606Spatrick     // and add destructors.
4758a9ac8606Spatrick     if (!isa<CompoundStmt>(S->getBody()))
4759a9ac8606Spatrick       addLocalScopeAndDtors(S->getBody());
4760a9ac8606Spatrick 
4761e5dd7070Spatrick     // Populate a new block to contain the loop body and loop variable.
4762e5dd7070Spatrick     addStmt(S->getBody());
4763a9ac8606Spatrick 
4764e5dd7070Spatrick     if (badCFG)
4765e5dd7070Spatrick       return nullptr;
4766e5dd7070Spatrick     CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
4767e5dd7070Spatrick     if (badCFG)
4768e5dd7070Spatrick       return nullptr;
4769e5dd7070Spatrick 
4770e5dd7070Spatrick     // This new body block is a successor to our condition block.
4771e5dd7070Spatrick     addSuccessor(ConditionBlock,
4772e5dd7070Spatrick                  KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
4773e5dd7070Spatrick   }
4774e5dd7070Spatrick 
4775e5dd7070Spatrick   // Link up the condition block with the code that follows the loop (the
4776e5dd7070Spatrick   // false branch).
4777e5dd7070Spatrick   addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
4778e5dd7070Spatrick 
4779e5dd7070Spatrick   // Add the initialization statements.
4780e5dd7070Spatrick   Block = createBlock();
4781e5dd7070Spatrick   addStmt(S->getBeginStmt());
4782e5dd7070Spatrick   addStmt(S->getEndStmt());
4783e5dd7070Spatrick   CFGBlock *Head = addStmt(S->getRangeStmt());
4784e5dd7070Spatrick   if (S->getInit())
4785e5dd7070Spatrick     Head = addStmt(S->getInit());
4786e5dd7070Spatrick   return Head;
4787e5dd7070Spatrick }
4788e5dd7070Spatrick 
VisitExprWithCleanups(ExprWithCleanups * E,AddStmtChoice asc,bool ExternallyDestructed)4789e5dd7070Spatrick CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4790e5dd7070Spatrick     AddStmtChoice asc, bool ExternallyDestructed) {
4791e5dd7070Spatrick   if (BuildOpts.AddTemporaryDtors) {
4792e5dd7070Spatrick     // If adding implicit destructors visit the full expression for adding
4793e5dd7070Spatrick     // destructors of temporaries.
4794e5dd7070Spatrick     TempDtorContext Context;
4795e5dd7070Spatrick     VisitForTemporaryDtors(E->getSubExpr(), ExternallyDestructed, Context);
4796e5dd7070Spatrick 
4797e5dd7070Spatrick     // Full expression has to be added as CFGStmt so it will be sequenced
4798e5dd7070Spatrick     // before destructors of it's temporaries.
4799e5dd7070Spatrick     asc = asc.withAlwaysAdd(true);
4800e5dd7070Spatrick   }
4801e5dd7070Spatrick   return Visit(E->getSubExpr(), asc);
4802e5dd7070Spatrick }
4803e5dd7070Spatrick 
VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr * E,AddStmtChoice asc)4804e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
4805e5dd7070Spatrick                                                 AddStmtChoice asc) {
4806e5dd7070Spatrick   if (asc.alwaysAdd(*this, E)) {
4807e5dd7070Spatrick     autoCreateBlock();
4808e5dd7070Spatrick     appendStmt(Block, E);
4809e5dd7070Spatrick 
4810e5dd7070Spatrick     findConstructionContexts(
4811e5dd7070Spatrick         ConstructionContextLayer::create(cfg->getBumpVectorContext(), E),
4812e5dd7070Spatrick         E->getSubExpr());
4813e5dd7070Spatrick 
4814e5dd7070Spatrick     // We do not want to propagate the AlwaysAdd property.
4815e5dd7070Spatrick     asc = asc.withAlwaysAdd(false);
4816e5dd7070Spatrick   }
4817e5dd7070Spatrick   return Visit(E->getSubExpr(), asc);
4818e5dd7070Spatrick }
4819e5dd7070Spatrick 
VisitCXXConstructExpr(CXXConstructExpr * C,AddStmtChoice asc)4820e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
4821e5dd7070Spatrick                                             AddStmtChoice asc) {
4822e5dd7070Spatrick   // If the constructor takes objects as arguments by value, we need to properly
4823e5dd7070Spatrick   // construct these objects. Construction contexts we find here aren't for the
4824e5dd7070Spatrick   // constructor C, they're for its arguments only.
4825e5dd7070Spatrick   findConstructionContextsForArguments(C);
4826e5dd7070Spatrick 
4827e5dd7070Spatrick   autoCreateBlock();
4828e5dd7070Spatrick   appendConstructor(Block, C);
4829e5dd7070Spatrick 
4830e5dd7070Spatrick   return VisitChildren(C);
4831e5dd7070Spatrick }
4832e5dd7070Spatrick 
VisitCXXNewExpr(CXXNewExpr * NE,AddStmtChoice asc)4833e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
4834e5dd7070Spatrick                                       AddStmtChoice asc) {
4835e5dd7070Spatrick   autoCreateBlock();
4836e5dd7070Spatrick   appendStmt(Block, NE);
4837e5dd7070Spatrick 
4838e5dd7070Spatrick   findConstructionContexts(
4839e5dd7070Spatrick       ConstructionContextLayer::create(cfg->getBumpVectorContext(), NE),
4840e5dd7070Spatrick       const_cast<CXXConstructExpr *>(NE->getConstructExpr()));
4841e5dd7070Spatrick 
4842e5dd7070Spatrick   if (NE->getInitializer())
4843e5dd7070Spatrick     Block = Visit(NE->getInitializer());
4844e5dd7070Spatrick 
4845e5dd7070Spatrick   if (BuildOpts.AddCXXNewAllocator)
4846e5dd7070Spatrick     appendNewAllocator(Block, NE);
4847e5dd7070Spatrick 
4848e5dd7070Spatrick   if (NE->isArray() && *NE->getArraySize())
4849e5dd7070Spatrick     Block = Visit(*NE->getArraySize());
4850e5dd7070Spatrick 
4851e5dd7070Spatrick   for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),
4852e5dd7070Spatrick        E = NE->placement_arg_end(); I != E; ++I)
4853e5dd7070Spatrick     Block = Visit(*I);
4854e5dd7070Spatrick 
4855e5dd7070Spatrick   return Block;
4856e5dd7070Spatrick }
4857e5dd7070Spatrick 
VisitCXXDeleteExpr(CXXDeleteExpr * DE,AddStmtChoice asc)4858e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
4859e5dd7070Spatrick                                          AddStmtChoice asc) {
4860e5dd7070Spatrick   autoCreateBlock();
4861e5dd7070Spatrick   appendStmt(Block, DE);
4862e5dd7070Spatrick   QualType DTy = DE->getDestroyedType();
4863e5dd7070Spatrick   if (!DTy.isNull()) {
4864e5dd7070Spatrick     DTy = DTy.getNonReferenceType();
4865e5dd7070Spatrick     CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
4866e5dd7070Spatrick     if (RD) {
4867e5dd7070Spatrick       if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
4868e5dd7070Spatrick         appendDeleteDtor(Block, RD, DE);
4869e5dd7070Spatrick     }
4870e5dd7070Spatrick   }
4871e5dd7070Spatrick 
4872e5dd7070Spatrick   return VisitChildren(DE);
4873e5dd7070Spatrick }
4874e5dd7070Spatrick 
VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr * E,AddStmtChoice asc)4875e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
4876e5dd7070Spatrick                                                  AddStmtChoice asc) {
4877e5dd7070Spatrick   if (asc.alwaysAdd(*this, E)) {
4878e5dd7070Spatrick     autoCreateBlock();
4879e5dd7070Spatrick     appendStmt(Block, E);
4880e5dd7070Spatrick     // We do not want to propagate the AlwaysAdd property.
4881e5dd7070Spatrick     asc = asc.withAlwaysAdd(false);
4882e5dd7070Spatrick   }
4883e5dd7070Spatrick   return Visit(E->getSubExpr(), asc);
4884e5dd7070Spatrick }
4885e5dd7070Spatrick 
VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr * C,AddStmtChoice asc)4886e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
4887e5dd7070Spatrick                                                   AddStmtChoice asc) {
4888e5dd7070Spatrick   // If the constructor takes objects as arguments by value, we need to properly
4889e5dd7070Spatrick   // construct these objects. Construction contexts we find here aren't for the
4890e5dd7070Spatrick   // constructor C, they're for its arguments only.
4891e5dd7070Spatrick   findConstructionContextsForArguments(C);
4892e5dd7070Spatrick 
4893e5dd7070Spatrick   autoCreateBlock();
4894e5dd7070Spatrick   appendConstructor(Block, C);
4895e5dd7070Spatrick   return VisitChildren(C);
4896e5dd7070Spatrick }
4897e5dd7070Spatrick 
VisitImplicitCastExpr(ImplicitCastExpr * E,AddStmtChoice asc)4898e5dd7070Spatrick CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
4899e5dd7070Spatrick                                             AddStmtChoice asc) {
4900e5dd7070Spatrick   if (asc.alwaysAdd(*this, E)) {
4901e5dd7070Spatrick     autoCreateBlock();
4902e5dd7070Spatrick     appendStmt(Block, E);
4903e5dd7070Spatrick   }
4904e5dd7070Spatrick 
4905e5dd7070Spatrick   if (E->getCastKind() == CK_IntegralToBoolean)
4906e5dd7070Spatrick     tryEvaluateBool(E->getSubExpr()->IgnoreParens());
4907e5dd7070Spatrick 
4908e5dd7070Spatrick   return Visit(E->getSubExpr(), AddStmtChoice());
4909e5dd7070Spatrick }
4910e5dd7070Spatrick 
VisitConstantExpr(ConstantExpr * E,AddStmtChoice asc)4911e5dd7070Spatrick CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
4912e5dd7070Spatrick   return Visit(E->getSubExpr(), AddStmtChoice());
4913e5dd7070Spatrick }
4914e5dd7070Spatrick 
VisitIndirectGotoStmt(IndirectGotoStmt * I)4915e5dd7070Spatrick CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
4916e5dd7070Spatrick   // Lazily create the indirect-goto dispatch block if there isn't one already.
4917e5dd7070Spatrick   CFGBlock *IBlock = cfg->getIndirectGotoBlock();
4918e5dd7070Spatrick 
4919e5dd7070Spatrick   if (!IBlock) {
4920e5dd7070Spatrick     IBlock = createBlock(false);
4921e5dd7070Spatrick     cfg->setIndirectGotoBlock(IBlock);
4922e5dd7070Spatrick   }
4923e5dd7070Spatrick 
4924e5dd7070Spatrick   // IndirectGoto is a control-flow statement.  Thus we stop processing the
4925e5dd7070Spatrick   // current block and create a new one.
4926e5dd7070Spatrick   if (badCFG)
4927e5dd7070Spatrick     return nullptr;
4928e5dd7070Spatrick 
4929e5dd7070Spatrick   Block = createBlock(false);
4930e5dd7070Spatrick   Block->setTerminator(I);
4931e5dd7070Spatrick   addSuccessor(Block, IBlock);
4932e5dd7070Spatrick   return addStmt(I->getTarget());
4933e5dd7070Spatrick }
4934e5dd7070Spatrick 
VisitForTemporaryDtors(Stmt * E,bool ExternallyDestructed,TempDtorContext & Context)4935e5dd7070Spatrick CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
4936e5dd7070Spatrick                                              TempDtorContext &Context) {
4937e5dd7070Spatrick   assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
4938e5dd7070Spatrick 
4939e5dd7070Spatrick tryAgain:
4940e5dd7070Spatrick   if (!E) {
4941e5dd7070Spatrick     badCFG = true;
4942e5dd7070Spatrick     return nullptr;
4943e5dd7070Spatrick   }
4944e5dd7070Spatrick   switch (E->getStmtClass()) {
4945e5dd7070Spatrick     default:
4946e5dd7070Spatrick       return VisitChildrenForTemporaryDtors(E, false, Context);
4947e5dd7070Spatrick 
4948e5dd7070Spatrick     case Stmt::InitListExprClass:
4949e5dd7070Spatrick       return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
4950e5dd7070Spatrick 
4951e5dd7070Spatrick     case Stmt::BinaryOperatorClass:
4952e5dd7070Spatrick       return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4953e5dd7070Spatrick                                                   ExternallyDestructed,
4954e5dd7070Spatrick                                                   Context);
4955e5dd7070Spatrick 
4956e5dd7070Spatrick     case Stmt::CXXBindTemporaryExprClass:
4957e5dd7070Spatrick       return VisitCXXBindTemporaryExprForTemporaryDtors(
4958e5dd7070Spatrick           cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);
4959e5dd7070Spatrick 
4960e5dd7070Spatrick     case Stmt::BinaryConditionalOperatorClass:
4961e5dd7070Spatrick     case Stmt::ConditionalOperatorClass:
4962e5dd7070Spatrick       return VisitConditionalOperatorForTemporaryDtors(
4963e5dd7070Spatrick           cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);
4964e5dd7070Spatrick 
4965e5dd7070Spatrick     case Stmt::ImplicitCastExprClass:
4966e5dd7070Spatrick       // For implicit cast we want ExternallyDestructed to be passed further.
4967e5dd7070Spatrick       E = cast<CastExpr>(E)->getSubExpr();
4968e5dd7070Spatrick       goto tryAgain;
4969e5dd7070Spatrick 
4970e5dd7070Spatrick     case Stmt::CXXFunctionalCastExprClass:
4971e5dd7070Spatrick       // For functional cast we want ExternallyDestructed to be passed further.
4972e5dd7070Spatrick       E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
4973e5dd7070Spatrick       goto tryAgain;
4974e5dd7070Spatrick 
4975e5dd7070Spatrick     case Stmt::ConstantExprClass:
4976e5dd7070Spatrick       E = cast<ConstantExpr>(E)->getSubExpr();
4977e5dd7070Spatrick       goto tryAgain;
4978e5dd7070Spatrick 
4979e5dd7070Spatrick     case Stmt::ParenExprClass:
4980e5dd7070Spatrick       E = cast<ParenExpr>(E)->getSubExpr();
4981e5dd7070Spatrick       goto tryAgain;
4982e5dd7070Spatrick 
4983e5dd7070Spatrick     case Stmt::MaterializeTemporaryExprClass: {
4984e5dd7070Spatrick       const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E);
4985e5dd7070Spatrick       ExternallyDestructed = (MTE->getStorageDuration() != SD_FullExpression);
4986e5dd7070Spatrick       SmallVector<const Expr *, 2> CommaLHSs;
4987e5dd7070Spatrick       SmallVector<SubobjectAdjustment, 2> Adjustments;
4988e5dd7070Spatrick       // Find the expression whose lifetime needs to be extended.
4989e5dd7070Spatrick       E = const_cast<Expr *>(
4990e5dd7070Spatrick           cast<MaterializeTemporaryExpr>(E)
4991e5dd7070Spatrick               ->getSubExpr()
4992e5dd7070Spatrick               ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
4993e5dd7070Spatrick       // Visit the skipped comma operator left-hand sides for other temporaries.
4994e5dd7070Spatrick       for (const Expr *CommaLHS : CommaLHSs) {
4995e5dd7070Spatrick         VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
4996e5dd7070Spatrick                                /*ExternallyDestructed=*/false, Context);
4997e5dd7070Spatrick       }
4998e5dd7070Spatrick       goto tryAgain;
4999e5dd7070Spatrick     }
5000e5dd7070Spatrick 
5001e5dd7070Spatrick     case Stmt::BlockExprClass:
5002e5dd7070Spatrick       // Don't recurse into blocks; their subexpressions don't get evaluated
5003e5dd7070Spatrick       // here.
5004e5dd7070Spatrick       return Block;
5005e5dd7070Spatrick 
5006e5dd7070Spatrick     case Stmt::LambdaExprClass: {
5007e5dd7070Spatrick       // For lambda expressions, only recurse into the capture initializers,
5008e5dd7070Spatrick       // and not the body.
5009e5dd7070Spatrick       auto *LE = cast<LambdaExpr>(E);
5010e5dd7070Spatrick       CFGBlock *B = Block;
5011e5dd7070Spatrick       for (Expr *Init : LE->capture_inits()) {
5012e5dd7070Spatrick         if (Init) {
5013e5dd7070Spatrick           if (CFGBlock *R = VisitForTemporaryDtors(
5014e5dd7070Spatrick                   Init, /*ExternallyDestructed=*/true, Context))
5015e5dd7070Spatrick             B = R;
5016e5dd7070Spatrick         }
5017e5dd7070Spatrick       }
5018e5dd7070Spatrick       return B;
5019e5dd7070Spatrick     }
5020e5dd7070Spatrick 
5021e5dd7070Spatrick     case Stmt::StmtExprClass:
5022e5dd7070Spatrick       // Don't recurse into statement expressions; any cleanups inside them
5023e5dd7070Spatrick       // will be wrapped in their own ExprWithCleanups.
5024e5dd7070Spatrick       return Block;
5025e5dd7070Spatrick 
5026e5dd7070Spatrick     case Stmt::CXXDefaultArgExprClass:
5027e5dd7070Spatrick       E = cast<CXXDefaultArgExpr>(E)->getExpr();
5028e5dd7070Spatrick       goto tryAgain;
5029e5dd7070Spatrick 
5030e5dd7070Spatrick     case Stmt::CXXDefaultInitExprClass:
5031e5dd7070Spatrick       E = cast<CXXDefaultInitExpr>(E)->getExpr();
5032e5dd7070Spatrick       goto tryAgain;
5033e5dd7070Spatrick   }
5034e5dd7070Spatrick }
5035e5dd7070Spatrick 
VisitChildrenForTemporaryDtors(Stmt * E,bool ExternallyDestructed,TempDtorContext & Context)5036e5dd7070Spatrick CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
5037e5dd7070Spatrick                                                      bool ExternallyDestructed,
5038e5dd7070Spatrick                                                      TempDtorContext &Context) {
5039e5dd7070Spatrick   if (isa<LambdaExpr>(E)) {
5040e5dd7070Spatrick     // Do not visit the children of lambdas; they have their own CFGs.
5041e5dd7070Spatrick     return Block;
5042e5dd7070Spatrick   }
5043e5dd7070Spatrick 
5044e5dd7070Spatrick   // When visiting children for destructors we want to visit them in reverse
5045e5dd7070Spatrick   // order that they will appear in the CFG.  Because the CFG is built
5046e5dd7070Spatrick   // bottom-up, this means we visit them in their natural order, which
5047e5dd7070Spatrick   // reverses them in the CFG.
5048e5dd7070Spatrick   CFGBlock *B = Block;
5049e5dd7070Spatrick   for (Stmt *Child : E->children())
5050e5dd7070Spatrick     if (Child)
5051e5dd7070Spatrick       if (CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
5052e5dd7070Spatrick         B = R;
5053e5dd7070Spatrick 
5054e5dd7070Spatrick   return B;
5055e5dd7070Spatrick }
5056e5dd7070Spatrick 
VisitBinaryOperatorForTemporaryDtors(BinaryOperator * E,bool ExternallyDestructed,TempDtorContext & Context)5057e5dd7070Spatrick CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5058e5dd7070Spatrick     BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) {
5059e5dd7070Spatrick   if (E->isCommaOp()) {
5060a9ac8606Spatrick     // For the comma operator, the LHS expression is evaluated before the RHS
5061a9ac8606Spatrick     // expression, so prepend temporary destructors for the LHS first.
5062e5dd7070Spatrick     CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
5063a9ac8606Spatrick     CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), ExternallyDestructed, Context);
5064a9ac8606Spatrick     return RHSBlock ? RHSBlock : LHSBlock;
5065e5dd7070Spatrick   }
5066e5dd7070Spatrick 
5067e5dd7070Spatrick   if (E->isLogicalOp()) {
5068e5dd7070Spatrick     VisitForTemporaryDtors(E->getLHS(), false, Context);
5069e5dd7070Spatrick     TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
5070e5dd7070Spatrick     if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
5071e5dd7070Spatrick       RHSExecuted.negate();
5072e5dd7070Spatrick 
5073e5dd7070Spatrick     // We do not know at CFG-construction time whether the right-hand-side was
5074e5dd7070Spatrick     // executed, thus we add a branch node that depends on the temporary
5075e5dd7070Spatrick     // constructor call.
5076e5dd7070Spatrick     TempDtorContext RHSContext(
5077e5dd7070Spatrick         bothKnownTrue(Context.KnownExecuted, RHSExecuted));
5078e5dd7070Spatrick     VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
5079e5dd7070Spatrick     InsertTempDtorDecisionBlock(RHSContext);
5080e5dd7070Spatrick 
5081e5dd7070Spatrick     return Block;
5082e5dd7070Spatrick   }
5083e5dd7070Spatrick 
5084e5dd7070Spatrick   if (E->isAssignmentOp()) {
5085a9ac8606Spatrick     // For assignment operators, the RHS expression is evaluated before the LHS
5086a9ac8606Spatrick     // expression, so prepend temporary destructors for the RHS first.
5087e5dd7070Spatrick     CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);
5088e5dd7070Spatrick     CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
5089e5dd7070Spatrick     return LHSBlock ? LHSBlock : RHSBlock;
5090e5dd7070Spatrick   }
5091e5dd7070Spatrick 
5092a9ac8606Spatrick   // Any other operator is visited normally.
5093a9ac8606Spatrick   return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
5094e5dd7070Spatrick }
5095e5dd7070Spatrick 
VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr * E,bool ExternallyDestructed,TempDtorContext & Context)5096e5dd7070Spatrick CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5097e5dd7070Spatrick     CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) {
5098e5dd7070Spatrick   // First add destructors for temporaries in subexpression.
5099e5dd7070Spatrick   // Because VisitCXXBindTemporaryExpr calls setDestructed:
5100e5dd7070Spatrick   CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), true, Context);
5101e5dd7070Spatrick   if (!ExternallyDestructed) {
5102e5dd7070Spatrick     // If lifetime of temporary is not prolonged (by assigning to constant
5103e5dd7070Spatrick     // reference) add destructor for it.
5104e5dd7070Spatrick 
5105e5dd7070Spatrick     const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
5106e5dd7070Spatrick 
5107e5dd7070Spatrick     if (Dtor->getParent()->isAnyDestructorNoReturn()) {
5108e5dd7070Spatrick       // If the destructor is marked as a no-return destructor, we need to
5109e5dd7070Spatrick       // create a new block for the destructor which does not have as a
5110e5dd7070Spatrick       // successor anything built thus far. Control won't flow out of this
5111e5dd7070Spatrick       // block.
5112e5dd7070Spatrick       if (B) Succ = B;
5113e5dd7070Spatrick       Block = createNoReturnBlock();
5114e5dd7070Spatrick     } else if (Context.needsTempDtorBranch()) {
5115e5dd7070Spatrick       // If we need to introduce a branch, we add a new block that we will hook
5116e5dd7070Spatrick       // up to a decision block later.
5117e5dd7070Spatrick       if (B) Succ = B;
5118e5dd7070Spatrick       Block = createBlock();
5119e5dd7070Spatrick     } else {
5120e5dd7070Spatrick       autoCreateBlock();
5121e5dd7070Spatrick     }
5122e5dd7070Spatrick     if (Context.needsTempDtorBranch()) {
5123e5dd7070Spatrick       Context.setDecisionPoint(Succ, E);
5124e5dd7070Spatrick     }
5125e5dd7070Spatrick     appendTemporaryDtor(Block, E);
5126e5dd7070Spatrick 
5127e5dd7070Spatrick     B = Block;
5128e5dd7070Spatrick   }
5129e5dd7070Spatrick   return B;
5130e5dd7070Spatrick }
5131e5dd7070Spatrick 
InsertTempDtorDecisionBlock(const TempDtorContext & Context,CFGBlock * FalseSucc)5132e5dd7070Spatrick void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
5133e5dd7070Spatrick                                              CFGBlock *FalseSucc) {
5134e5dd7070Spatrick   if (!Context.TerminatorExpr) {
5135e5dd7070Spatrick     // If no temporary was found, we do not need to insert a decision point.
5136e5dd7070Spatrick     return;
5137e5dd7070Spatrick   }
5138e5dd7070Spatrick   assert(Context.TerminatorExpr);
5139e5dd7070Spatrick   CFGBlock *Decision = createBlock(false);
5140e5dd7070Spatrick   Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
5141e5dd7070Spatrick                                         CFGTerminator::TemporaryDtorsBranch));
5142e5dd7070Spatrick   addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
5143e5dd7070Spatrick   addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
5144e5dd7070Spatrick                !Context.KnownExecuted.isTrue());
5145e5dd7070Spatrick   Block = Decision;
5146e5dd7070Spatrick }
5147e5dd7070Spatrick 
VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator * E,bool ExternallyDestructed,TempDtorContext & Context)5148e5dd7070Spatrick CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5149e5dd7070Spatrick     AbstractConditionalOperator *E, bool ExternallyDestructed,
5150e5dd7070Spatrick     TempDtorContext &Context) {
5151e5dd7070Spatrick   VisitForTemporaryDtors(E->getCond(), false, Context);
5152e5dd7070Spatrick   CFGBlock *ConditionBlock = Block;
5153e5dd7070Spatrick   CFGBlock *ConditionSucc = Succ;
5154e5dd7070Spatrick   TryResult ConditionVal = tryEvaluateBool(E->getCond());
5155e5dd7070Spatrick   TryResult NegatedVal = ConditionVal;
5156e5dd7070Spatrick   if (NegatedVal.isKnown()) NegatedVal.negate();
5157e5dd7070Spatrick 
5158e5dd7070Spatrick   TempDtorContext TrueContext(
5159e5dd7070Spatrick       bothKnownTrue(Context.KnownExecuted, ConditionVal));
5160e5dd7070Spatrick   VisitForTemporaryDtors(E->getTrueExpr(), ExternallyDestructed, TrueContext);
5161e5dd7070Spatrick   CFGBlock *TrueBlock = Block;
5162e5dd7070Spatrick 
5163e5dd7070Spatrick   Block = ConditionBlock;
5164e5dd7070Spatrick   Succ = ConditionSucc;
5165e5dd7070Spatrick   TempDtorContext FalseContext(
5166e5dd7070Spatrick       bothKnownTrue(Context.KnownExecuted, NegatedVal));
5167e5dd7070Spatrick   VisitForTemporaryDtors(E->getFalseExpr(), ExternallyDestructed, FalseContext);
5168e5dd7070Spatrick 
5169e5dd7070Spatrick   if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
5170e5dd7070Spatrick     InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
5171e5dd7070Spatrick   } else if (TrueContext.TerminatorExpr) {
5172e5dd7070Spatrick     Block = TrueBlock;
5173e5dd7070Spatrick     InsertTempDtorDecisionBlock(TrueContext);
5174e5dd7070Spatrick   } else {
5175e5dd7070Spatrick     InsertTempDtorDecisionBlock(FalseContext);
5176e5dd7070Spatrick   }
5177e5dd7070Spatrick   return Block;
5178e5dd7070Spatrick }
5179e5dd7070Spatrick 
VisitOMPExecutableDirective(OMPExecutableDirective * D,AddStmtChoice asc)5180e5dd7070Spatrick CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
5181e5dd7070Spatrick                                                   AddStmtChoice asc) {
5182e5dd7070Spatrick   if (asc.alwaysAdd(*this, D)) {
5183e5dd7070Spatrick     autoCreateBlock();
5184e5dd7070Spatrick     appendStmt(Block, D);
5185e5dd7070Spatrick   }
5186e5dd7070Spatrick 
5187e5dd7070Spatrick   // Iterate over all used expression in clauses.
5188e5dd7070Spatrick   CFGBlock *B = Block;
5189e5dd7070Spatrick 
5190e5dd7070Spatrick   // Reverse the elements to process them in natural order. Iterators are not
5191e5dd7070Spatrick   // bidirectional, so we need to create temp vector.
5192e5dd7070Spatrick   SmallVector<Stmt *, 8> Used(
5193e5dd7070Spatrick       OMPExecutableDirective::used_clauses_children(D->clauses()));
5194e5dd7070Spatrick   for (Stmt *S : llvm::reverse(Used)) {
5195e5dd7070Spatrick     assert(S && "Expected non-null used-in-clause child.");
5196e5dd7070Spatrick     if (CFGBlock *R = Visit(S))
5197e5dd7070Spatrick       B = R;
5198e5dd7070Spatrick   }
5199e5dd7070Spatrick   // Visit associated structured block if any.
5200a9ac8606Spatrick   if (!D->isStandaloneDirective()) {
5201a9ac8606Spatrick     Stmt *S = D->getRawStmt();
5202e5dd7070Spatrick     if (!isa<CompoundStmt>(S))
5203e5dd7070Spatrick       addLocalScopeAndDtors(S);
5204e5dd7070Spatrick     if (CFGBlock *R = addStmt(S))
5205e5dd7070Spatrick       B = R;
5206e5dd7070Spatrick   }
5207e5dd7070Spatrick 
5208e5dd7070Spatrick   return B;
5209e5dd7070Spatrick }
5210e5dd7070Spatrick 
5211e5dd7070Spatrick /// createBlock - Constructs and adds a new CFGBlock to the CFG.  The block has
5212e5dd7070Spatrick ///  no successors or predecessors.  If this is the first block created in the
5213e5dd7070Spatrick ///  CFG, it is automatically set to be the Entry and Exit of the CFG.
createBlock()5214e5dd7070Spatrick CFGBlock *CFG::createBlock() {
5215e5dd7070Spatrick   bool first_block = begin() == end();
5216e5dd7070Spatrick 
5217e5dd7070Spatrick   // Create the block.
5218e5dd7070Spatrick   CFGBlock *Mem = getAllocator().Allocate<CFGBlock>();
5219e5dd7070Spatrick   new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);
5220e5dd7070Spatrick   Blocks.push_back(Mem, BlkBVC);
5221e5dd7070Spatrick 
5222e5dd7070Spatrick   // If this is the first block, set it as the Entry and Exit.
5223e5dd7070Spatrick   if (first_block)
5224e5dd7070Spatrick     Entry = Exit = &back();
5225e5dd7070Spatrick 
5226e5dd7070Spatrick   // Return the block.
5227e5dd7070Spatrick   return &back();
5228e5dd7070Spatrick }
5229e5dd7070Spatrick 
5230e5dd7070Spatrick /// buildCFG - Constructs a CFG from an AST.
buildCFG(const Decl * D,Stmt * Statement,ASTContext * C,const BuildOptions & BO)5231e5dd7070Spatrick std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,
5232e5dd7070Spatrick                                    ASTContext *C, const BuildOptions &BO) {
5233e5dd7070Spatrick   CFGBuilder Builder(C, BO);
5234e5dd7070Spatrick   return Builder.buildCFG(D, Statement);
5235e5dd7070Spatrick }
5236e5dd7070Spatrick 
isLinear() const5237e5dd7070Spatrick bool CFG::isLinear() const {
5238e5dd7070Spatrick   // Quick path: if we only have the ENTRY block, the EXIT block, and some code
5239e5dd7070Spatrick   // in between, then we have no room for control flow.
5240e5dd7070Spatrick   if (size() <= 3)
5241e5dd7070Spatrick     return true;
5242e5dd7070Spatrick 
5243e5dd7070Spatrick   // Traverse the CFG until we find a branch.
5244e5dd7070Spatrick   // TODO: While this should still be very fast,
5245e5dd7070Spatrick   // maybe we should cache the answer.
5246e5dd7070Spatrick   llvm::SmallPtrSet<const CFGBlock *, 4> Visited;
5247e5dd7070Spatrick   const CFGBlock *B = Entry;
5248e5dd7070Spatrick   while (B != Exit) {
5249e5dd7070Spatrick     auto IteratorAndFlag = Visited.insert(B);
5250e5dd7070Spatrick     if (!IteratorAndFlag.second) {
5251e5dd7070Spatrick       // We looped back to a block that we've already visited. Not linear.
5252e5dd7070Spatrick       return false;
5253e5dd7070Spatrick     }
5254e5dd7070Spatrick 
5255e5dd7070Spatrick     // Iterate over reachable successors.
5256e5dd7070Spatrick     const CFGBlock *FirstReachableB = nullptr;
5257e5dd7070Spatrick     for (const CFGBlock::AdjacentBlock &AB : B->succs()) {
5258e5dd7070Spatrick       if (!AB.isReachable())
5259e5dd7070Spatrick         continue;
5260e5dd7070Spatrick 
5261e5dd7070Spatrick       if (FirstReachableB == nullptr) {
5262e5dd7070Spatrick         FirstReachableB = &*AB;
5263e5dd7070Spatrick       } else {
5264e5dd7070Spatrick         // We've encountered a branch. It's not a linear CFG.
5265e5dd7070Spatrick         return false;
5266e5dd7070Spatrick       }
5267e5dd7070Spatrick     }
5268e5dd7070Spatrick 
5269e5dd7070Spatrick     if (!FirstReachableB) {
5270e5dd7070Spatrick       // We reached a dead end. EXIT is unreachable. This is linear enough.
5271e5dd7070Spatrick       return true;
5272e5dd7070Spatrick     }
5273e5dd7070Spatrick 
5274e5dd7070Spatrick     // There's only one way to move forward. Proceed.
5275e5dd7070Spatrick     B = FirstReachableB;
5276e5dd7070Spatrick   }
5277e5dd7070Spatrick 
5278e5dd7070Spatrick   // We reached EXIT and found no branches.
5279e5dd7070Spatrick   return true;
5280e5dd7070Spatrick }
5281e5dd7070Spatrick 
5282e5dd7070Spatrick const CXXDestructorDecl *
getDestructorDecl(ASTContext & astContext) const5283e5dd7070Spatrick CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
5284e5dd7070Spatrick   switch (getKind()) {
5285e5dd7070Spatrick     case CFGElement::Initializer:
5286e5dd7070Spatrick     case CFGElement::NewAllocator:
5287e5dd7070Spatrick     case CFGElement::LoopExit:
5288e5dd7070Spatrick     case CFGElement::LifetimeEnds:
5289e5dd7070Spatrick     case CFGElement::Statement:
5290e5dd7070Spatrick     case CFGElement::Constructor:
5291e5dd7070Spatrick     case CFGElement::CXXRecordTypedCall:
5292e5dd7070Spatrick     case CFGElement::ScopeBegin:
5293e5dd7070Spatrick     case CFGElement::ScopeEnd:
5294e5dd7070Spatrick       llvm_unreachable("getDestructorDecl should only be used with "
5295e5dd7070Spatrick                        "ImplicitDtors");
5296e5dd7070Spatrick     case CFGElement::AutomaticObjectDtor: {
5297e5dd7070Spatrick       const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
5298e5dd7070Spatrick       QualType ty = var->getType();
5299e5dd7070Spatrick 
5300e5dd7070Spatrick       // FIXME: See CFGBuilder::addLocalScopeForVarDecl.
5301e5dd7070Spatrick       //
5302e5dd7070Spatrick       // Lifetime-extending constructs are handled here. This works for a single
5303e5dd7070Spatrick       // temporary in an initializer expression.
5304e5dd7070Spatrick       if (ty->isReferenceType()) {
5305e5dd7070Spatrick         if (const Expr *Init = var->getInit()) {
5306e5dd7070Spatrick           ty = getReferenceInitTemporaryType(Init);
5307e5dd7070Spatrick         }
5308e5dd7070Spatrick       }
5309e5dd7070Spatrick 
5310e5dd7070Spatrick       while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
5311e5dd7070Spatrick         ty = arrayType->getElementType();
5312e5dd7070Spatrick       }
5313e5dd7070Spatrick 
5314e5dd7070Spatrick       // The situation when the type of the lifetime-extending reference
5315e5dd7070Spatrick       // does not correspond to the type of the object is supposed
5316e5dd7070Spatrick       // to be handled by now. In particular, 'ty' is now the unwrapped
5317e5dd7070Spatrick       // record type.
5318e5dd7070Spatrick       const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();
5319e5dd7070Spatrick       assert(classDecl);
5320e5dd7070Spatrick       return classDecl->getDestructor();
5321e5dd7070Spatrick     }
5322e5dd7070Spatrick     case CFGElement::DeleteDtor: {
5323e5dd7070Spatrick       const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
5324e5dd7070Spatrick       QualType DTy = DE->getDestroyedType();
5325e5dd7070Spatrick       DTy = DTy.getNonReferenceType();
5326e5dd7070Spatrick       const CXXRecordDecl *classDecl =
5327e5dd7070Spatrick           astContext.getBaseElementType(DTy)->getAsCXXRecordDecl();
5328e5dd7070Spatrick       return classDecl->getDestructor();
5329e5dd7070Spatrick     }
5330e5dd7070Spatrick     case CFGElement::TemporaryDtor: {
5331e5dd7070Spatrick       const CXXBindTemporaryExpr *bindExpr =
5332e5dd7070Spatrick         castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5333e5dd7070Spatrick       const CXXTemporary *temp = bindExpr->getTemporary();
5334e5dd7070Spatrick       return temp->getDestructor();
5335e5dd7070Spatrick     }
5336*12c85518Srobert     case CFGElement::MemberDtor: {
5337*12c85518Srobert       const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();
5338*12c85518Srobert       QualType ty = field->getType();
5339*12c85518Srobert 
5340*12c85518Srobert       while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
5341*12c85518Srobert         ty = arrayType->getElementType();
5342*12c85518Srobert       }
5343*12c85518Srobert 
5344*12c85518Srobert       const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();
5345*12c85518Srobert       assert(classDecl);
5346*12c85518Srobert       return classDecl->getDestructor();
5347*12c85518Srobert     }
5348e5dd7070Spatrick     case CFGElement::BaseDtor:
5349e5dd7070Spatrick       // Not yet supported.
5350e5dd7070Spatrick       return nullptr;
5351e5dd7070Spatrick   }
5352e5dd7070Spatrick   llvm_unreachable("getKind() returned bogus value");
5353e5dd7070Spatrick }
5354e5dd7070Spatrick 
5355e5dd7070Spatrick //===----------------------------------------------------------------------===//
5356e5dd7070Spatrick // CFGBlock operations.
5357e5dd7070Spatrick //===----------------------------------------------------------------------===//
5358e5dd7070Spatrick 
AdjacentBlock(CFGBlock * B,bool IsReachable)5359e5dd7070Spatrick CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
5360e5dd7070Spatrick     : ReachableBlock(IsReachable ? B : nullptr),
5361e5dd7070Spatrick       UnreachableBlock(!IsReachable ? B : nullptr,
5362e5dd7070Spatrick                        B && IsReachable ? AB_Normal : AB_Unreachable) {}
5363e5dd7070Spatrick 
AdjacentBlock(CFGBlock * B,CFGBlock * AlternateBlock)5364e5dd7070Spatrick CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
5365e5dd7070Spatrick     : ReachableBlock(B),
5366e5dd7070Spatrick       UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
5367e5dd7070Spatrick                        B == AlternateBlock ? AB_Alternate : AB_Normal) {}
5368e5dd7070Spatrick 
addSuccessor(AdjacentBlock Succ,BumpVectorContext & C)5369e5dd7070Spatrick void CFGBlock::addSuccessor(AdjacentBlock Succ,
5370e5dd7070Spatrick                             BumpVectorContext &C) {
5371e5dd7070Spatrick   if (CFGBlock *B = Succ.getReachableBlock())
5372e5dd7070Spatrick     B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C);
5373e5dd7070Spatrick 
5374e5dd7070Spatrick   if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock())
5375e5dd7070Spatrick     UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);
5376e5dd7070Spatrick 
5377e5dd7070Spatrick   Succs.push_back(Succ, C);
5378e5dd7070Spatrick }
5379e5dd7070Spatrick 
FilterEdge(const CFGBlock::FilterOptions & F,const CFGBlock * From,const CFGBlock * To)5380e5dd7070Spatrick bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
5381e5dd7070Spatrick         const CFGBlock *From, const CFGBlock *To) {
5382e5dd7070Spatrick   if (F.IgnoreNullPredecessors && !From)
5383e5dd7070Spatrick     return true;
5384e5dd7070Spatrick 
5385e5dd7070Spatrick   if (To && From && F.IgnoreDefaultsWithCoveredEnums) {
5386e5dd7070Spatrick     // If the 'To' has no label or is labeled but the label isn't a
5387e5dd7070Spatrick     // CaseStmt then filter this edge.
5388e5dd7070Spatrick     if (const SwitchStmt *S =
5389e5dd7070Spatrick         dyn_cast_or_null<SwitchStmt>(From->getTerminatorStmt())) {
5390e5dd7070Spatrick       if (S->isAllEnumCasesCovered()) {
5391e5dd7070Spatrick         const Stmt *L = To->getLabel();
5392e5dd7070Spatrick         if (!L || !isa<CaseStmt>(L))
5393e5dd7070Spatrick           return true;
5394e5dd7070Spatrick       }
5395e5dd7070Spatrick     }
5396e5dd7070Spatrick   }
5397e5dd7070Spatrick 
5398e5dd7070Spatrick   return false;
5399e5dd7070Spatrick }
5400e5dd7070Spatrick 
5401e5dd7070Spatrick //===----------------------------------------------------------------------===//
5402e5dd7070Spatrick // CFG pretty printing
5403e5dd7070Spatrick //===----------------------------------------------------------------------===//
5404e5dd7070Spatrick 
5405e5dd7070Spatrick namespace {
5406e5dd7070Spatrick 
5407e5dd7070Spatrick class StmtPrinterHelper : public PrinterHelper  {
5408e5dd7070Spatrick   using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
5409e5dd7070Spatrick   using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
5410e5dd7070Spatrick 
5411e5dd7070Spatrick   StmtMapTy StmtMap;
5412e5dd7070Spatrick   DeclMapTy DeclMap;
5413e5dd7070Spatrick   signed currentBlock = 0;
5414e5dd7070Spatrick   unsigned currStmt = 0;
5415e5dd7070Spatrick   const LangOptions &LangOpts;
5416e5dd7070Spatrick 
5417e5dd7070Spatrick public:
StmtPrinterHelper(const CFG * cfg,const LangOptions & LO)5418e5dd7070Spatrick   StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
5419e5dd7070Spatrick       : LangOpts(LO) {
5420e5dd7070Spatrick     if (!cfg)
5421e5dd7070Spatrick       return;
5422e5dd7070Spatrick     for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
5423e5dd7070Spatrick       unsigned j = 1;
5424e5dd7070Spatrick       for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
5425e5dd7070Spatrick            BI != BEnd; ++BI, ++j ) {
5426*12c85518Srobert         if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
5427e5dd7070Spatrick           const Stmt *stmt= SE->getStmt();
5428e5dd7070Spatrick           std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
5429e5dd7070Spatrick           StmtMap[stmt] = P;
5430e5dd7070Spatrick 
5431e5dd7070Spatrick           switch (stmt->getStmtClass()) {
5432e5dd7070Spatrick             case Stmt::DeclStmtClass:
5433e5dd7070Spatrick               DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
5434e5dd7070Spatrick               break;
5435e5dd7070Spatrick             case Stmt::IfStmtClass: {
5436e5dd7070Spatrick               const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
5437e5dd7070Spatrick               if (var)
5438e5dd7070Spatrick                 DeclMap[var] = P;
5439e5dd7070Spatrick               break;
5440e5dd7070Spatrick             }
5441e5dd7070Spatrick             case Stmt::ForStmtClass: {
5442e5dd7070Spatrick               const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
5443e5dd7070Spatrick               if (var)
5444e5dd7070Spatrick                 DeclMap[var] = P;
5445e5dd7070Spatrick               break;
5446e5dd7070Spatrick             }
5447e5dd7070Spatrick             case Stmt::WhileStmtClass: {
5448e5dd7070Spatrick               const VarDecl *var =
5449e5dd7070Spatrick                 cast<WhileStmt>(stmt)->getConditionVariable();
5450e5dd7070Spatrick               if (var)
5451e5dd7070Spatrick                 DeclMap[var] = P;
5452e5dd7070Spatrick               break;
5453e5dd7070Spatrick             }
5454e5dd7070Spatrick             case Stmt::SwitchStmtClass: {
5455e5dd7070Spatrick               const VarDecl *var =
5456e5dd7070Spatrick                 cast<SwitchStmt>(stmt)->getConditionVariable();
5457e5dd7070Spatrick               if (var)
5458e5dd7070Spatrick                 DeclMap[var] = P;
5459e5dd7070Spatrick               break;
5460e5dd7070Spatrick             }
5461e5dd7070Spatrick             case Stmt::CXXCatchStmtClass: {
5462e5dd7070Spatrick               const VarDecl *var =
5463e5dd7070Spatrick                 cast<CXXCatchStmt>(stmt)->getExceptionDecl();
5464e5dd7070Spatrick               if (var)
5465e5dd7070Spatrick                 DeclMap[var] = P;
5466e5dd7070Spatrick               break;
5467e5dd7070Spatrick             }
5468e5dd7070Spatrick             default:
5469e5dd7070Spatrick               break;
5470e5dd7070Spatrick           }
5471e5dd7070Spatrick         }
5472e5dd7070Spatrick       }
5473e5dd7070Spatrick     }
5474e5dd7070Spatrick   }
5475e5dd7070Spatrick 
5476e5dd7070Spatrick   ~StmtPrinterHelper() override = default;
5477e5dd7070Spatrick 
getLangOpts() const5478e5dd7070Spatrick   const LangOptions &getLangOpts() const { return LangOpts; }
setBlockID(signed i)5479e5dd7070Spatrick   void setBlockID(signed i) { currentBlock = i; }
setStmtID(unsigned i)5480e5dd7070Spatrick   void setStmtID(unsigned i) { currStmt = i; }
5481e5dd7070Spatrick 
handledStmt(Stmt * S,raw_ostream & OS)5482e5dd7070Spatrick   bool handledStmt(Stmt *S, raw_ostream &OS) override {
5483e5dd7070Spatrick     StmtMapTy::iterator I = StmtMap.find(S);
5484e5dd7070Spatrick 
5485e5dd7070Spatrick     if (I == StmtMap.end())
5486e5dd7070Spatrick       return false;
5487e5dd7070Spatrick 
5488e5dd7070Spatrick     if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
5489e5dd7070Spatrick                           && I->second.second == currStmt) {
5490e5dd7070Spatrick       return false;
5491e5dd7070Spatrick     }
5492e5dd7070Spatrick 
5493e5dd7070Spatrick     OS << "[B" << I->second.first << "." << I->second.second << "]";
5494e5dd7070Spatrick     return true;
5495e5dd7070Spatrick   }
5496e5dd7070Spatrick 
handleDecl(const Decl * D,raw_ostream & OS)5497e5dd7070Spatrick   bool handleDecl(const Decl *D, raw_ostream &OS) {
5498e5dd7070Spatrick     DeclMapTy::iterator I = DeclMap.find(D);
5499e5dd7070Spatrick 
5500e5dd7070Spatrick     if (I == DeclMap.end())
5501e5dd7070Spatrick       return false;
5502e5dd7070Spatrick 
5503e5dd7070Spatrick     if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
5504e5dd7070Spatrick                           && I->second.second == currStmt) {
5505e5dd7070Spatrick       return false;
5506e5dd7070Spatrick     }
5507e5dd7070Spatrick 
5508e5dd7070Spatrick     OS << "[B" << I->second.first << "." << I->second.second << "]";
5509e5dd7070Spatrick     return true;
5510e5dd7070Spatrick   }
5511e5dd7070Spatrick };
5512e5dd7070Spatrick 
5513e5dd7070Spatrick class CFGBlockTerminatorPrint
5514e5dd7070Spatrick     : public StmtVisitor<CFGBlockTerminatorPrint,void> {
5515e5dd7070Spatrick   raw_ostream &OS;
5516e5dd7070Spatrick   StmtPrinterHelper* Helper;
5517e5dd7070Spatrick   PrintingPolicy Policy;
5518e5dd7070Spatrick 
5519e5dd7070Spatrick public:
CFGBlockTerminatorPrint(raw_ostream & os,StmtPrinterHelper * helper,const PrintingPolicy & Policy)5520e5dd7070Spatrick   CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
5521e5dd7070Spatrick                           const PrintingPolicy &Policy)
5522e5dd7070Spatrick       : OS(os), Helper(helper), Policy(Policy) {
5523e5dd7070Spatrick     this->Policy.IncludeNewlines = false;
5524e5dd7070Spatrick   }
5525e5dd7070Spatrick 
VisitIfStmt(IfStmt * I)5526e5dd7070Spatrick   void VisitIfStmt(IfStmt *I) {
5527e5dd7070Spatrick     OS << "if ";
5528e5dd7070Spatrick     if (Stmt *C = I->getCond())
5529e5dd7070Spatrick       C->printPretty(OS, Helper, Policy);
5530e5dd7070Spatrick   }
5531e5dd7070Spatrick 
5532e5dd7070Spatrick   // Default case.
VisitStmt(Stmt * Terminator)5533e5dd7070Spatrick   void VisitStmt(Stmt *Terminator) {
5534e5dd7070Spatrick     Terminator->printPretty(OS, Helper, Policy);
5535e5dd7070Spatrick   }
5536e5dd7070Spatrick 
VisitDeclStmt(DeclStmt * DS)5537e5dd7070Spatrick   void VisitDeclStmt(DeclStmt *DS) {
5538e5dd7070Spatrick     VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
5539e5dd7070Spatrick     OS << "static init " << VD->getName();
5540e5dd7070Spatrick   }
5541e5dd7070Spatrick 
VisitForStmt(ForStmt * F)5542e5dd7070Spatrick   void VisitForStmt(ForStmt *F) {
5543e5dd7070Spatrick     OS << "for (" ;
5544e5dd7070Spatrick     if (F->getInit())
5545e5dd7070Spatrick       OS << "...";
5546e5dd7070Spatrick     OS << "; ";
5547e5dd7070Spatrick     if (Stmt *C = F->getCond())
5548e5dd7070Spatrick       C->printPretty(OS, Helper, Policy);
5549e5dd7070Spatrick     OS << "; ";
5550e5dd7070Spatrick     if (F->getInc())
5551e5dd7070Spatrick       OS << "...";
5552e5dd7070Spatrick     OS << ")";
5553e5dd7070Spatrick   }
5554e5dd7070Spatrick 
VisitWhileStmt(WhileStmt * W)5555e5dd7070Spatrick   void VisitWhileStmt(WhileStmt *W) {
5556e5dd7070Spatrick     OS << "while " ;
5557e5dd7070Spatrick     if (Stmt *C = W->getCond())
5558e5dd7070Spatrick       C->printPretty(OS, Helper, Policy);
5559e5dd7070Spatrick   }
5560e5dd7070Spatrick 
VisitDoStmt(DoStmt * D)5561e5dd7070Spatrick   void VisitDoStmt(DoStmt *D) {
5562e5dd7070Spatrick     OS << "do ... while ";
5563e5dd7070Spatrick     if (Stmt *C = D->getCond())
5564e5dd7070Spatrick       C->printPretty(OS, Helper, Policy);
5565e5dd7070Spatrick   }
5566e5dd7070Spatrick 
VisitSwitchStmt(SwitchStmt * Terminator)5567e5dd7070Spatrick   void VisitSwitchStmt(SwitchStmt *Terminator) {
5568e5dd7070Spatrick     OS << "switch ";
5569e5dd7070Spatrick     Terminator->getCond()->printPretty(OS, Helper, Policy);
5570e5dd7070Spatrick   }
5571e5dd7070Spatrick 
VisitCXXTryStmt(CXXTryStmt *)5572*12c85518Srobert   void VisitCXXTryStmt(CXXTryStmt *) { OS << "try ..."; }
5573e5dd7070Spatrick 
VisitObjCAtTryStmt(ObjCAtTryStmt *)5574*12c85518Srobert   void VisitObjCAtTryStmt(ObjCAtTryStmt *) { OS << "@try ..."; }
5575*12c85518Srobert 
VisitSEHTryStmt(SEHTryStmt * CS)5576*12c85518Srobert   void VisitSEHTryStmt(SEHTryStmt *CS) { OS << "__try ..."; }
5577e5dd7070Spatrick 
VisitAbstractConditionalOperator(AbstractConditionalOperator * C)5578e5dd7070Spatrick   void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
5579e5dd7070Spatrick     if (Stmt *Cond = C->getCond())
5580e5dd7070Spatrick       Cond->printPretty(OS, Helper, Policy);
5581e5dd7070Spatrick     OS << " ? ... : ...";
5582e5dd7070Spatrick   }
5583e5dd7070Spatrick 
VisitChooseExpr(ChooseExpr * C)5584e5dd7070Spatrick   void VisitChooseExpr(ChooseExpr *C) {
5585e5dd7070Spatrick     OS << "__builtin_choose_expr( ";
5586e5dd7070Spatrick     if (Stmt *Cond = C->getCond())
5587e5dd7070Spatrick       Cond->printPretty(OS, Helper, Policy);
5588e5dd7070Spatrick     OS << " )";
5589e5dd7070Spatrick   }
5590e5dd7070Spatrick 
VisitIndirectGotoStmt(IndirectGotoStmt * I)5591e5dd7070Spatrick   void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
5592e5dd7070Spatrick     OS << "goto *";
5593e5dd7070Spatrick     if (Stmt *T = I->getTarget())
5594e5dd7070Spatrick       T->printPretty(OS, Helper, Policy);
5595e5dd7070Spatrick   }
5596e5dd7070Spatrick 
VisitBinaryOperator(BinaryOperator * B)5597e5dd7070Spatrick   void VisitBinaryOperator(BinaryOperator* B) {
5598e5dd7070Spatrick     if (!B->isLogicalOp()) {
5599e5dd7070Spatrick       VisitExpr(B);
5600e5dd7070Spatrick       return;
5601e5dd7070Spatrick     }
5602e5dd7070Spatrick 
5603e5dd7070Spatrick     if (B->getLHS())
5604e5dd7070Spatrick       B->getLHS()->printPretty(OS, Helper, Policy);
5605e5dd7070Spatrick 
5606e5dd7070Spatrick     switch (B->getOpcode()) {
5607e5dd7070Spatrick       case BO_LOr:
5608e5dd7070Spatrick         OS << " || ...";
5609e5dd7070Spatrick         return;
5610e5dd7070Spatrick       case BO_LAnd:
5611e5dd7070Spatrick         OS << " && ...";
5612e5dd7070Spatrick         return;
5613e5dd7070Spatrick       default:
5614e5dd7070Spatrick         llvm_unreachable("Invalid logical operator.");
5615e5dd7070Spatrick     }
5616e5dd7070Spatrick   }
5617e5dd7070Spatrick 
VisitExpr(Expr * E)5618e5dd7070Spatrick   void VisitExpr(Expr *E) {
5619e5dd7070Spatrick     E->printPretty(OS, Helper, Policy);
5620e5dd7070Spatrick   }
5621e5dd7070Spatrick 
5622e5dd7070Spatrick public:
print(CFGTerminator T)5623e5dd7070Spatrick   void print(CFGTerminator T) {
5624e5dd7070Spatrick     switch (T.getKind()) {
5625e5dd7070Spatrick     case CFGTerminator::StmtBranch:
5626e5dd7070Spatrick       Visit(T.getStmt());
5627e5dd7070Spatrick       break;
5628e5dd7070Spatrick     case CFGTerminator::TemporaryDtorsBranch:
5629e5dd7070Spatrick       OS << "(Temp Dtor) ";
5630e5dd7070Spatrick       Visit(T.getStmt());
5631e5dd7070Spatrick       break;
5632e5dd7070Spatrick     case CFGTerminator::VirtualBaseBranch:
5633e5dd7070Spatrick       OS << "(See if most derived ctor has already initialized vbases)";
5634e5dd7070Spatrick       break;
5635e5dd7070Spatrick     }
5636e5dd7070Spatrick   }
5637e5dd7070Spatrick };
5638e5dd7070Spatrick 
5639e5dd7070Spatrick } // namespace
5640e5dd7070Spatrick 
print_initializer(raw_ostream & OS,StmtPrinterHelper & Helper,const CXXCtorInitializer * I)5641e5dd7070Spatrick static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper,
5642e5dd7070Spatrick                               const CXXCtorInitializer *I) {
5643e5dd7070Spatrick   if (I->isBaseInitializer())
5644e5dd7070Spatrick     OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
5645e5dd7070Spatrick   else if (I->isDelegatingInitializer())
5646e5dd7070Spatrick     OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();
5647e5dd7070Spatrick   else
5648e5dd7070Spatrick     OS << I->getAnyMember()->getName();
5649e5dd7070Spatrick   OS << "(";
5650e5dd7070Spatrick   if (Expr *IE = I->getInit())
5651e5dd7070Spatrick     IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5652e5dd7070Spatrick   OS << ")";
5653e5dd7070Spatrick 
5654e5dd7070Spatrick   if (I->isBaseInitializer())
5655e5dd7070Spatrick     OS << " (Base initializer)";
5656e5dd7070Spatrick   else if (I->isDelegatingInitializer())
5657e5dd7070Spatrick     OS << " (Delegating initializer)";
5658e5dd7070Spatrick   else
5659e5dd7070Spatrick     OS << " (Member initializer)";
5660e5dd7070Spatrick }
5661e5dd7070Spatrick 
print_construction_context(raw_ostream & OS,StmtPrinterHelper & Helper,const ConstructionContext * CC)5662e5dd7070Spatrick static void print_construction_context(raw_ostream &OS,
5663e5dd7070Spatrick                                        StmtPrinterHelper &Helper,
5664e5dd7070Spatrick                                        const ConstructionContext *CC) {
5665e5dd7070Spatrick   SmallVector<const Stmt *, 3> Stmts;
5666e5dd7070Spatrick   switch (CC->getKind()) {
5667e5dd7070Spatrick   case ConstructionContext::SimpleConstructorInitializerKind: {
5668e5dd7070Spatrick     OS << ", ";
5669e5dd7070Spatrick     const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
5670e5dd7070Spatrick     print_initializer(OS, Helper, SICC->getCXXCtorInitializer());
5671e5dd7070Spatrick     return;
5672e5dd7070Spatrick   }
5673e5dd7070Spatrick   case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: {
5674e5dd7070Spatrick     OS << ", ";
5675e5dd7070Spatrick     const auto *CICC =
5676e5dd7070Spatrick         cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
5677e5dd7070Spatrick     print_initializer(OS, Helper, CICC->getCXXCtorInitializer());
5678e5dd7070Spatrick     Stmts.push_back(CICC->getCXXBindTemporaryExpr());
5679e5dd7070Spatrick     break;
5680e5dd7070Spatrick   }
5681e5dd7070Spatrick   case ConstructionContext::SimpleVariableKind: {
5682e5dd7070Spatrick     const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
5683e5dd7070Spatrick     Stmts.push_back(SDSCC->getDeclStmt());
5684e5dd7070Spatrick     break;
5685e5dd7070Spatrick   }
5686e5dd7070Spatrick   case ConstructionContext::CXX17ElidedCopyVariableKind: {
5687e5dd7070Spatrick     const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
5688e5dd7070Spatrick     Stmts.push_back(CDSCC->getDeclStmt());
5689e5dd7070Spatrick     Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
5690e5dd7070Spatrick     break;
5691e5dd7070Spatrick   }
5692e5dd7070Spatrick   case ConstructionContext::NewAllocatedObjectKind: {
5693e5dd7070Spatrick     const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
5694e5dd7070Spatrick     Stmts.push_back(NECC->getCXXNewExpr());
5695e5dd7070Spatrick     break;
5696e5dd7070Spatrick   }
5697e5dd7070Spatrick   case ConstructionContext::SimpleReturnedValueKind: {
5698e5dd7070Spatrick     const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
5699e5dd7070Spatrick     Stmts.push_back(RSCC->getReturnStmt());
5700e5dd7070Spatrick     break;
5701e5dd7070Spatrick   }
5702e5dd7070Spatrick   case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
5703e5dd7070Spatrick     const auto *RSCC =
5704e5dd7070Spatrick         cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
5705e5dd7070Spatrick     Stmts.push_back(RSCC->getReturnStmt());
5706e5dd7070Spatrick     Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
5707e5dd7070Spatrick     break;
5708e5dd7070Spatrick   }
5709e5dd7070Spatrick   case ConstructionContext::SimpleTemporaryObjectKind: {
5710e5dd7070Spatrick     const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
5711e5dd7070Spatrick     Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5712e5dd7070Spatrick     Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5713e5dd7070Spatrick     break;
5714e5dd7070Spatrick   }
5715e5dd7070Spatrick   case ConstructionContext::ElidedTemporaryObjectKind: {
5716e5dd7070Spatrick     const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
5717e5dd7070Spatrick     Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
5718e5dd7070Spatrick     Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
5719e5dd7070Spatrick     Stmts.push_back(TOCC->getConstructorAfterElision());
5720e5dd7070Spatrick     break;
5721e5dd7070Spatrick   }
5722*12c85518Srobert   case ConstructionContext::LambdaCaptureKind: {
5723*12c85518Srobert     const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
5724*12c85518Srobert     Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS);
5725*12c85518Srobert     OS << "+" << LCC->getIndex();
5726*12c85518Srobert     return;
5727*12c85518Srobert   }
5728e5dd7070Spatrick   case ConstructionContext::ArgumentKind: {
5729e5dd7070Spatrick     const auto *ACC = cast<ArgumentConstructionContext>(CC);
5730e5dd7070Spatrick     if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
5731e5dd7070Spatrick       OS << ", ";
5732e5dd7070Spatrick       Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
5733e5dd7070Spatrick     }
5734e5dd7070Spatrick     OS << ", ";
5735e5dd7070Spatrick     Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
5736e5dd7070Spatrick     OS << "+" << ACC->getIndex();
5737e5dd7070Spatrick     return;
5738e5dd7070Spatrick   }
5739e5dd7070Spatrick   }
5740e5dd7070Spatrick   for (auto I: Stmts)
5741e5dd7070Spatrick     if (I) {
5742e5dd7070Spatrick       OS << ", ";
5743e5dd7070Spatrick       Helper.handledStmt(const_cast<Stmt *>(I), OS);
5744e5dd7070Spatrick     }
5745e5dd7070Spatrick }
5746e5dd7070Spatrick 
5747e5dd7070Spatrick static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5748e5dd7070Spatrick                        const CFGElement &E);
5749e5dd7070Spatrick 
dumpToStream(llvm::raw_ostream & OS) const5750e5dd7070Spatrick void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
5751e5dd7070Spatrick   StmtPrinterHelper Helper(nullptr, {});
5752e5dd7070Spatrick   print_elem(OS, Helper, *this);
5753e5dd7070Spatrick }
5754e5dd7070Spatrick 
print_elem(raw_ostream & OS,StmtPrinterHelper & Helper,const CFGElement & E)5755e5dd7070Spatrick static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5756e5dd7070Spatrick                        const CFGElement &E) {
5757e5dd7070Spatrick   switch (E.getKind()) {
5758e5dd7070Spatrick   case CFGElement::Kind::Statement:
5759e5dd7070Spatrick   case CFGElement::Kind::CXXRecordTypedCall:
5760e5dd7070Spatrick   case CFGElement::Kind::Constructor: {
5761e5dd7070Spatrick     CFGStmt CS = E.castAs<CFGStmt>();
5762e5dd7070Spatrick     const Stmt *S = CS.getStmt();
5763e5dd7070Spatrick     assert(S != nullptr && "Expecting non-null Stmt");
5764e5dd7070Spatrick 
5765e5dd7070Spatrick     // special printing for statement-expressions.
5766e5dd7070Spatrick     if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
5767e5dd7070Spatrick       const CompoundStmt *Sub = SE->getSubStmt();
5768e5dd7070Spatrick 
5769e5dd7070Spatrick       auto Children = Sub->children();
5770e5dd7070Spatrick       if (Children.begin() != Children.end()) {
5771e5dd7070Spatrick         OS << "({ ... ; ";
5772e5dd7070Spatrick         Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
5773e5dd7070Spatrick         OS << " })\n";
5774e5dd7070Spatrick         return;
5775e5dd7070Spatrick       }
5776e5dd7070Spatrick     }
5777e5dd7070Spatrick     // special printing for comma expressions.
5778e5dd7070Spatrick     if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
5779e5dd7070Spatrick       if (B->getOpcode() == BO_Comma) {
5780e5dd7070Spatrick         OS << "... , ";
5781e5dd7070Spatrick         Helper.handledStmt(B->getRHS(),OS);
5782e5dd7070Spatrick         OS << '\n';
5783e5dd7070Spatrick         return;
5784e5dd7070Spatrick       }
5785e5dd7070Spatrick     }
5786e5dd7070Spatrick     S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5787e5dd7070Spatrick 
5788e5dd7070Spatrick     if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) {
5789e5dd7070Spatrick       if (isa<CXXOperatorCallExpr>(S))
5790e5dd7070Spatrick         OS << " (OperatorCall)";
5791e5dd7070Spatrick       OS << " (CXXRecordTypedCall";
5792e5dd7070Spatrick       print_construction_context(OS, Helper, VTC->getConstructionContext());
5793e5dd7070Spatrick       OS << ")";
5794e5dd7070Spatrick     } else if (isa<CXXOperatorCallExpr>(S)) {
5795e5dd7070Spatrick       OS << " (OperatorCall)";
5796e5dd7070Spatrick     } else if (isa<CXXBindTemporaryExpr>(S)) {
5797e5dd7070Spatrick       OS << " (BindTemporary)";
5798e5dd7070Spatrick     } else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
5799e5dd7070Spatrick       OS << " (CXXConstructExpr";
5800*12c85518Srobert       if (std::optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) {
5801e5dd7070Spatrick         print_construction_context(OS, Helper, CE->getConstructionContext());
5802e5dd7070Spatrick       }
5803*12c85518Srobert       OS << ", " << CCE->getType() << ")";
5804e5dd7070Spatrick     } else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
5805*12c85518Srobert       OS << " (" << CE->getStmtClassName() << ", " << CE->getCastKindName()
5806*12c85518Srobert          << ", " << CE->getType() << ")";
5807e5dd7070Spatrick     }
5808e5dd7070Spatrick 
5809e5dd7070Spatrick     // Expressions need a newline.
5810e5dd7070Spatrick     if (isa<Expr>(S))
5811e5dd7070Spatrick       OS << '\n';
5812e5dd7070Spatrick 
5813e5dd7070Spatrick     break;
5814e5dd7070Spatrick   }
5815e5dd7070Spatrick 
5816e5dd7070Spatrick   case CFGElement::Kind::Initializer:
5817e5dd7070Spatrick     print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
5818e5dd7070Spatrick     OS << '\n';
5819e5dd7070Spatrick     break;
5820e5dd7070Spatrick 
5821e5dd7070Spatrick   case CFGElement::Kind::AutomaticObjectDtor: {
5822e5dd7070Spatrick     CFGAutomaticObjDtor DE = E.castAs<CFGAutomaticObjDtor>();
5823e5dd7070Spatrick     const VarDecl *VD = DE.getVarDecl();
5824e5dd7070Spatrick     Helper.handleDecl(VD, OS);
5825e5dd7070Spatrick 
5826e5dd7070Spatrick     QualType T = VD->getType();
5827e5dd7070Spatrick     if (T->isReferenceType())
5828e5dd7070Spatrick       T = getReferenceInitTemporaryType(VD->getInit(), nullptr);
5829e5dd7070Spatrick 
5830e5dd7070Spatrick     OS << ".~";
5831e5dd7070Spatrick     T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
5832e5dd7070Spatrick     OS << "() (Implicit destructor)\n";
5833e5dd7070Spatrick     break;
5834e5dd7070Spatrick   }
5835e5dd7070Spatrick 
5836e5dd7070Spatrick   case CFGElement::Kind::LifetimeEnds:
5837e5dd7070Spatrick     Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
5838e5dd7070Spatrick     OS << " (Lifetime ends)\n";
5839e5dd7070Spatrick     break;
5840e5dd7070Spatrick 
5841e5dd7070Spatrick   case CFGElement::Kind::LoopExit:
5842e5dd7070Spatrick     OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
5843e5dd7070Spatrick     break;
5844e5dd7070Spatrick 
5845e5dd7070Spatrick   case CFGElement::Kind::ScopeBegin:
5846e5dd7070Spatrick     OS << "CFGScopeBegin(";
5847e5dd7070Spatrick     if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
5848e5dd7070Spatrick       OS << VD->getQualifiedNameAsString();
5849e5dd7070Spatrick     OS << ")\n";
5850e5dd7070Spatrick     break;
5851e5dd7070Spatrick 
5852e5dd7070Spatrick   case CFGElement::Kind::ScopeEnd:
5853e5dd7070Spatrick     OS << "CFGScopeEnd(";
5854e5dd7070Spatrick     if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
5855e5dd7070Spatrick       OS << VD->getQualifiedNameAsString();
5856e5dd7070Spatrick     OS << ")\n";
5857e5dd7070Spatrick     break;
5858e5dd7070Spatrick 
5859e5dd7070Spatrick   case CFGElement::Kind::NewAllocator:
5860e5dd7070Spatrick     OS << "CFGNewAllocator(";
5861e5dd7070Spatrick     if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
5862e5dd7070Spatrick       AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
5863e5dd7070Spatrick     OS << ")\n";
5864e5dd7070Spatrick     break;
5865e5dd7070Spatrick 
5866e5dd7070Spatrick   case CFGElement::Kind::DeleteDtor: {
5867e5dd7070Spatrick     CFGDeleteDtor DE = E.castAs<CFGDeleteDtor>();
5868e5dd7070Spatrick     const CXXRecordDecl *RD = DE.getCXXRecordDecl();
5869e5dd7070Spatrick     if (!RD)
5870e5dd7070Spatrick       return;
5871e5dd7070Spatrick     CXXDeleteExpr *DelExpr =
5872e5dd7070Spatrick         const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());
5873e5dd7070Spatrick     Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
5874e5dd7070Spatrick     OS << "->~" << RD->getName().str() << "()";
5875e5dd7070Spatrick     OS << " (Implicit destructor)\n";
5876e5dd7070Spatrick     break;
5877e5dd7070Spatrick   }
5878e5dd7070Spatrick 
5879e5dd7070Spatrick   case CFGElement::Kind::BaseDtor: {
5880e5dd7070Spatrick     const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
5881e5dd7070Spatrick     OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
5882e5dd7070Spatrick     OS << " (Base object destructor)\n";
5883e5dd7070Spatrick     break;
5884e5dd7070Spatrick   }
5885e5dd7070Spatrick 
5886e5dd7070Spatrick   case CFGElement::Kind::MemberDtor: {
5887e5dd7070Spatrick     const FieldDecl *FD = E.castAs<CFGMemberDtor>().getFieldDecl();
5888e5dd7070Spatrick     const Type *T = FD->getType()->getBaseElementTypeUnsafe();
5889e5dd7070Spatrick     OS << "this->" << FD->getName();
5890e5dd7070Spatrick     OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
5891e5dd7070Spatrick     OS << " (Member object destructor)\n";
5892e5dd7070Spatrick     break;
5893e5dd7070Spatrick   }
5894e5dd7070Spatrick 
5895e5dd7070Spatrick   case CFGElement::Kind::TemporaryDtor: {
5896*12c85518Srobert     const CXXBindTemporaryExpr *BT =
5897*12c85518Srobert         E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
5898e5dd7070Spatrick     OS << "~";
5899e5dd7070Spatrick     BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
5900e5dd7070Spatrick     OS << "() (Temporary object destructor)\n";
5901e5dd7070Spatrick     break;
5902e5dd7070Spatrick   }
5903e5dd7070Spatrick   }
5904e5dd7070Spatrick }
5905e5dd7070Spatrick 
print_block(raw_ostream & OS,const CFG * cfg,const CFGBlock & B,StmtPrinterHelper & Helper,bool print_edges,bool ShowColors)5906e5dd7070Spatrick static void print_block(raw_ostream &OS, const CFG* cfg,
5907e5dd7070Spatrick                         const CFGBlock &B,
5908e5dd7070Spatrick                         StmtPrinterHelper &Helper, bool print_edges,
5909e5dd7070Spatrick                         bool ShowColors) {
5910e5dd7070Spatrick   Helper.setBlockID(B.getBlockID());
5911e5dd7070Spatrick 
5912e5dd7070Spatrick   // Print the header.
5913e5dd7070Spatrick   if (ShowColors)
5914e5dd7070Spatrick     OS.changeColor(raw_ostream::YELLOW, true);
5915e5dd7070Spatrick 
5916e5dd7070Spatrick   OS << "\n [B" << B.getBlockID();
5917e5dd7070Spatrick 
5918e5dd7070Spatrick   if (&B == &cfg->getEntry())
5919e5dd7070Spatrick     OS << " (ENTRY)]\n";
5920e5dd7070Spatrick   else if (&B == &cfg->getExit())
5921e5dd7070Spatrick     OS << " (EXIT)]\n";
5922e5dd7070Spatrick   else if (&B == cfg->getIndirectGotoBlock())
5923e5dd7070Spatrick     OS << " (INDIRECT GOTO DISPATCH)]\n";
5924e5dd7070Spatrick   else if (B.hasNoReturnElement())
5925e5dd7070Spatrick     OS << " (NORETURN)]\n";
5926e5dd7070Spatrick   else
5927e5dd7070Spatrick     OS << "]\n";
5928e5dd7070Spatrick 
5929e5dd7070Spatrick   if (ShowColors)
5930e5dd7070Spatrick     OS.resetColor();
5931e5dd7070Spatrick 
5932e5dd7070Spatrick   // Print the label of this block.
5933e5dd7070Spatrick   if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {
5934e5dd7070Spatrick     if (print_edges)
5935e5dd7070Spatrick       OS << "  ";
5936e5dd7070Spatrick 
5937e5dd7070Spatrick     if (LabelStmt *L = dyn_cast<LabelStmt>(Label))
5938e5dd7070Spatrick       OS << L->getName();
5939e5dd7070Spatrick     else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
5940e5dd7070Spatrick       OS << "case ";
5941*12c85518Srobert       if (const Expr *LHS = C->getLHS())
5942*12c85518Srobert         LHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5943*12c85518Srobert       if (const Expr *RHS = C->getRHS()) {
5944e5dd7070Spatrick         OS << " ... ";
5945*12c85518Srobert         RHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5946e5dd7070Spatrick       }
5947e5dd7070Spatrick     } else if (isa<DefaultStmt>(Label))
5948e5dd7070Spatrick       OS << "default";
5949e5dd7070Spatrick     else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
5950e5dd7070Spatrick       OS << "catch (";
5951*12c85518Srobert       if (const VarDecl *ED = CS->getExceptionDecl())
5952*12c85518Srobert         ED->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
5953*12c85518Srobert       else
5954*12c85518Srobert         OS << "...";
5955*12c85518Srobert       OS << ")";
5956*12c85518Srobert     } else if (ObjCAtCatchStmt *CS = dyn_cast<ObjCAtCatchStmt>(Label)) {
5957*12c85518Srobert       OS << "@catch (";
5958*12c85518Srobert       if (const VarDecl *PD = CS->getCatchParamDecl())
5959*12c85518Srobert         PD->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
5960e5dd7070Spatrick       else
5961e5dd7070Spatrick         OS << "...";
5962e5dd7070Spatrick       OS << ")";
5963e5dd7070Spatrick     } else if (SEHExceptStmt *ES = dyn_cast<SEHExceptStmt>(Label)) {
5964e5dd7070Spatrick       OS << "__except (";
5965e5dd7070Spatrick       ES->getFilterExpr()->printPretty(OS, &Helper,
5966e5dd7070Spatrick                                        PrintingPolicy(Helper.getLangOpts()), 0);
5967e5dd7070Spatrick       OS << ")";
5968e5dd7070Spatrick     } else
5969e5dd7070Spatrick       llvm_unreachable("Invalid label statement in CFGBlock.");
5970e5dd7070Spatrick 
5971e5dd7070Spatrick     OS << ":\n";
5972e5dd7070Spatrick   }
5973e5dd7070Spatrick 
5974e5dd7070Spatrick   // Iterate through the statements in the block and print them.
5975e5dd7070Spatrick   unsigned j = 1;
5976e5dd7070Spatrick 
5977e5dd7070Spatrick   for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
5978e5dd7070Spatrick        I != E ; ++I, ++j ) {
5979e5dd7070Spatrick     // Print the statement # in the basic block and the statement itself.
5980e5dd7070Spatrick     if (print_edges)
5981e5dd7070Spatrick       OS << " ";
5982e5dd7070Spatrick 
5983e5dd7070Spatrick     OS << llvm::format("%3d", j) << ": ";
5984e5dd7070Spatrick 
5985e5dd7070Spatrick     Helper.setStmtID(j);
5986e5dd7070Spatrick 
5987e5dd7070Spatrick     print_elem(OS, Helper, *I);
5988e5dd7070Spatrick   }
5989e5dd7070Spatrick 
5990e5dd7070Spatrick   // Print the terminator of this block.
5991e5dd7070Spatrick   if (B.getTerminator().isValid()) {
5992e5dd7070Spatrick     if (ShowColors)
5993e5dd7070Spatrick       OS.changeColor(raw_ostream::GREEN);
5994e5dd7070Spatrick 
5995e5dd7070Spatrick     OS << "   T: ";
5996e5dd7070Spatrick 
5997e5dd7070Spatrick     Helper.setBlockID(-1);
5998e5dd7070Spatrick 
5999e5dd7070Spatrick     PrintingPolicy PP(Helper.getLangOpts());
6000e5dd7070Spatrick     CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
6001e5dd7070Spatrick     TPrinter.print(B.getTerminator());
6002e5dd7070Spatrick     OS << '\n';
6003e5dd7070Spatrick 
6004e5dd7070Spatrick     if (ShowColors)
6005e5dd7070Spatrick       OS.resetColor();
6006e5dd7070Spatrick   }
6007e5dd7070Spatrick 
6008e5dd7070Spatrick   if (print_edges) {
6009e5dd7070Spatrick     // Print the predecessors of this block.
6010e5dd7070Spatrick     if (!B.pred_empty()) {
6011e5dd7070Spatrick       const raw_ostream::Colors Color = raw_ostream::BLUE;
6012e5dd7070Spatrick       if (ShowColors)
6013e5dd7070Spatrick         OS.changeColor(Color);
6014e5dd7070Spatrick       OS << "   Preds " ;
6015e5dd7070Spatrick       if (ShowColors)
6016e5dd7070Spatrick         OS.resetColor();
6017e5dd7070Spatrick       OS << '(' << B.pred_size() << "):";
6018e5dd7070Spatrick       unsigned i = 0;
6019e5dd7070Spatrick 
6020e5dd7070Spatrick       if (ShowColors)
6021e5dd7070Spatrick         OS.changeColor(Color);
6022e5dd7070Spatrick 
6023e5dd7070Spatrick       for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
6024e5dd7070Spatrick            I != E; ++I, ++i) {
6025e5dd7070Spatrick         if (i % 10 == 8)
6026e5dd7070Spatrick           OS << "\n     ";
6027e5dd7070Spatrick 
6028e5dd7070Spatrick         CFGBlock *B = *I;
6029e5dd7070Spatrick         bool Reachable = true;
6030e5dd7070Spatrick         if (!B) {
6031e5dd7070Spatrick           Reachable = false;
6032e5dd7070Spatrick           B = I->getPossiblyUnreachableBlock();
6033e5dd7070Spatrick         }
6034e5dd7070Spatrick 
6035e5dd7070Spatrick         OS << " B" << B->getBlockID();
6036e5dd7070Spatrick         if (!Reachable)
6037e5dd7070Spatrick           OS << "(Unreachable)";
6038e5dd7070Spatrick       }
6039e5dd7070Spatrick 
6040e5dd7070Spatrick       if (ShowColors)
6041e5dd7070Spatrick         OS.resetColor();
6042e5dd7070Spatrick 
6043e5dd7070Spatrick       OS << '\n';
6044e5dd7070Spatrick     }
6045e5dd7070Spatrick 
6046e5dd7070Spatrick     // Print the successors of this block.
6047e5dd7070Spatrick     if (!B.succ_empty()) {
6048e5dd7070Spatrick       const raw_ostream::Colors Color = raw_ostream::MAGENTA;
6049e5dd7070Spatrick       if (ShowColors)
6050e5dd7070Spatrick         OS.changeColor(Color);
6051e5dd7070Spatrick       OS << "   Succs ";
6052e5dd7070Spatrick       if (ShowColors)
6053e5dd7070Spatrick         OS.resetColor();
6054e5dd7070Spatrick       OS << '(' << B.succ_size() << "):";
6055e5dd7070Spatrick       unsigned i = 0;
6056e5dd7070Spatrick 
6057e5dd7070Spatrick       if (ShowColors)
6058e5dd7070Spatrick         OS.changeColor(Color);
6059e5dd7070Spatrick 
6060e5dd7070Spatrick       for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
6061e5dd7070Spatrick            I != E; ++I, ++i) {
6062e5dd7070Spatrick         if (i % 10 == 8)
6063e5dd7070Spatrick           OS << "\n    ";
6064e5dd7070Spatrick 
6065e5dd7070Spatrick         CFGBlock *B = *I;
6066e5dd7070Spatrick 
6067e5dd7070Spatrick         bool Reachable = true;
6068e5dd7070Spatrick         if (!B) {
6069e5dd7070Spatrick           Reachable = false;
6070e5dd7070Spatrick           B = I->getPossiblyUnreachableBlock();
6071e5dd7070Spatrick         }
6072e5dd7070Spatrick 
6073e5dd7070Spatrick         if (B) {
6074e5dd7070Spatrick           OS << " B" << B->getBlockID();
6075e5dd7070Spatrick           if (!Reachable)
6076e5dd7070Spatrick             OS << "(Unreachable)";
6077e5dd7070Spatrick         }
6078e5dd7070Spatrick         else {
6079e5dd7070Spatrick           OS << " NULL";
6080e5dd7070Spatrick         }
6081e5dd7070Spatrick       }
6082e5dd7070Spatrick 
6083e5dd7070Spatrick       if (ShowColors)
6084e5dd7070Spatrick         OS.resetColor();
6085e5dd7070Spatrick       OS << '\n';
6086e5dd7070Spatrick     }
6087e5dd7070Spatrick   }
6088e5dd7070Spatrick }
6089e5dd7070Spatrick 
6090e5dd7070Spatrick /// dump - A simple pretty printer of a CFG that outputs to stderr.
dump(const LangOptions & LO,bool ShowColors) const6091e5dd7070Spatrick void CFG::dump(const LangOptions &LO, bool ShowColors) const {
6092e5dd7070Spatrick   print(llvm::errs(), LO, ShowColors);
6093e5dd7070Spatrick }
6094e5dd7070Spatrick 
6095e5dd7070Spatrick /// print - A simple pretty printer of a CFG that outputs to an ostream.
print(raw_ostream & OS,const LangOptions & LO,bool ShowColors) const6096e5dd7070Spatrick void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const {
6097e5dd7070Spatrick   StmtPrinterHelper Helper(this, LO);
6098e5dd7070Spatrick 
6099e5dd7070Spatrick   // Print the entry block.
6100e5dd7070Spatrick   print_block(OS, this, getEntry(), Helper, true, ShowColors);
6101e5dd7070Spatrick 
6102e5dd7070Spatrick   // Iterate through the CFGBlocks and print them one by one.
6103e5dd7070Spatrick   for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
6104e5dd7070Spatrick     // Skip the entry block, because we already printed it.
6105e5dd7070Spatrick     if (&(**I) == &getEntry() || &(**I) == &getExit())
6106e5dd7070Spatrick       continue;
6107e5dd7070Spatrick 
6108e5dd7070Spatrick     print_block(OS, this, **I, Helper, true, ShowColors);
6109e5dd7070Spatrick   }
6110e5dd7070Spatrick 
6111e5dd7070Spatrick   // Print the exit block.
6112e5dd7070Spatrick   print_block(OS, this, getExit(), Helper, true, ShowColors);
6113e5dd7070Spatrick   OS << '\n';
6114e5dd7070Spatrick   OS.flush();
6115e5dd7070Spatrick }
6116e5dd7070Spatrick 
getIndexInCFG() const6117e5dd7070Spatrick size_t CFGBlock::getIndexInCFG() const {
6118e5dd7070Spatrick   return llvm::find(*getParent(), this) - getParent()->begin();
6119e5dd7070Spatrick }
6120e5dd7070Spatrick 
6121e5dd7070Spatrick /// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
dump(const CFG * cfg,const LangOptions & LO,bool ShowColors) const6122e5dd7070Spatrick void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,
6123e5dd7070Spatrick                     bool ShowColors) const {
6124e5dd7070Spatrick   print(llvm::errs(), cfg, LO, ShowColors);
6125e5dd7070Spatrick }
6126e5dd7070Spatrick 
dump() const6127e5dd7070Spatrick LLVM_DUMP_METHOD void CFGBlock::dump() const {
6128e5dd7070Spatrick   dump(getParent(), LangOptions(), false);
6129e5dd7070Spatrick }
6130e5dd7070Spatrick 
6131e5dd7070Spatrick /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
6132e5dd7070Spatrick ///   Generally this will only be called from CFG::print.
print(raw_ostream & OS,const CFG * cfg,const LangOptions & LO,bool ShowColors) const6133e5dd7070Spatrick void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
6134e5dd7070Spatrick                      const LangOptions &LO, bool ShowColors) const {
6135e5dd7070Spatrick   StmtPrinterHelper Helper(cfg, LO);
6136e5dd7070Spatrick   print_block(OS, cfg, *this, Helper, true, ShowColors);
6137e5dd7070Spatrick   OS << '\n';
6138e5dd7070Spatrick }
6139e5dd7070Spatrick 
6140e5dd7070Spatrick /// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
printTerminator(raw_ostream & OS,const LangOptions & LO) const6141e5dd7070Spatrick void CFGBlock::printTerminator(raw_ostream &OS,
6142e5dd7070Spatrick                                const LangOptions &LO) const {
6143e5dd7070Spatrick   CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));
6144e5dd7070Spatrick   TPrinter.print(getTerminator());
6145e5dd7070Spatrick }
6146e5dd7070Spatrick 
6147e5dd7070Spatrick /// printTerminatorJson - Pretty-prints the terminator in JSON format.
printTerminatorJson(raw_ostream & Out,const LangOptions & LO,bool AddQuotes) const6148e5dd7070Spatrick void CFGBlock::printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
6149e5dd7070Spatrick                                    bool AddQuotes) const {
6150e5dd7070Spatrick   std::string Buf;
6151e5dd7070Spatrick   llvm::raw_string_ostream TempOut(Buf);
6152e5dd7070Spatrick 
6153e5dd7070Spatrick   printTerminator(TempOut, LO);
6154e5dd7070Spatrick 
6155e5dd7070Spatrick   Out << JsonFormat(TempOut.str(), AddQuotes);
6156e5dd7070Spatrick }
6157e5dd7070Spatrick 
6158e5dd7070Spatrick // Returns true if by simply looking at the block, we can be sure that it
6159e5dd7070Spatrick // results in a sink during analysis. This is useful to know when the analysis
6160e5dd7070Spatrick // was interrupted, and we try to figure out if it would sink eventually.
6161e5dd7070Spatrick // There may be many more reasons why a sink would appear during analysis
6162e5dd7070Spatrick // (eg. checkers may generate sinks arbitrarily), but here we only consider
6163e5dd7070Spatrick // sinks that would be obvious by looking at the CFG.
isImmediateSinkBlock(const CFGBlock * Blk)6164e5dd7070Spatrick static bool isImmediateSinkBlock(const CFGBlock *Blk) {
6165e5dd7070Spatrick   if (Blk->hasNoReturnElement())
6166e5dd7070Spatrick     return true;
6167e5dd7070Spatrick 
6168e5dd7070Spatrick   // FIXME: Throw-expressions are currently generating sinks during analysis:
6169e5dd7070Spatrick   // they're not supported yet, and also often used for actually terminating
6170e5dd7070Spatrick   // the program. So we should treat them as sinks in this analysis as well,
6171e5dd7070Spatrick   // at least for now, but once we have better support for exceptions,
6172e5dd7070Spatrick   // we'd need to carefully handle the case when the throw is being
6173e5dd7070Spatrick   // immediately caught.
6174*12c85518Srobert   if (llvm::any_of(*Blk, [](const CFGElement &Elm) {
6175*12c85518Srobert         if (std::optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())
6176e5dd7070Spatrick           if (isa<CXXThrowExpr>(StmtElm->getStmt()))
6177e5dd7070Spatrick             return true;
6178e5dd7070Spatrick         return false;
6179e5dd7070Spatrick       }))
6180e5dd7070Spatrick     return true;
6181e5dd7070Spatrick 
6182e5dd7070Spatrick   return false;
6183e5dd7070Spatrick }
6184e5dd7070Spatrick 
isInevitablySinking() const6185e5dd7070Spatrick bool CFGBlock::isInevitablySinking() const {
6186e5dd7070Spatrick   const CFG &Cfg = *getParent();
6187e5dd7070Spatrick 
6188e5dd7070Spatrick   const CFGBlock *StartBlk = this;
6189e5dd7070Spatrick   if (isImmediateSinkBlock(StartBlk))
6190e5dd7070Spatrick     return true;
6191e5dd7070Spatrick 
6192e5dd7070Spatrick   llvm::SmallVector<const CFGBlock *, 32> DFSWorkList;
6193e5dd7070Spatrick   llvm::SmallPtrSet<const CFGBlock *, 32> Visited;
6194e5dd7070Spatrick 
6195e5dd7070Spatrick   DFSWorkList.push_back(StartBlk);
6196e5dd7070Spatrick   while (!DFSWorkList.empty()) {
6197e5dd7070Spatrick     const CFGBlock *Blk = DFSWorkList.back();
6198e5dd7070Spatrick     DFSWorkList.pop_back();
6199e5dd7070Spatrick     Visited.insert(Blk);
6200e5dd7070Spatrick 
6201e5dd7070Spatrick     // If at least one path reaches the CFG exit, it means that control is
6202e5dd7070Spatrick     // returned to the caller. For now, say that we are not sure what
6203e5dd7070Spatrick     // happens next. If necessary, this can be improved to analyze
6204e5dd7070Spatrick     // the parent StackFrameContext's call site in a similar manner.
6205e5dd7070Spatrick     if (Blk == &Cfg.getExit())
6206e5dd7070Spatrick       return false;
6207e5dd7070Spatrick 
6208e5dd7070Spatrick     for (const auto &Succ : Blk->succs()) {
6209e5dd7070Spatrick       if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6210e5dd7070Spatrick         if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {
6211e5dd7070Spatrick           // If the block has reachable child blocks that aren't no-return,
6212e5dd7070Spatrick           // add them to the worklist.
6213e5dd7070Spatrick           DFSWorkList.push_back(SuccBlk);
6214e5dd7070Spatrick         }
6215e5dd7070Spatrick       }
6216e5dd7070Spatrick     }
6217e5dd7070Spatrick   }
6218e5dd7070Spatrick 
6219e5dd7070Spatrick   // Nothing reached the exit. It can only mean one thing: there's no return.
6220e5dd7070Spatrick   return true;
6221e5dd7070Spatrick }
6222e5dd7070Spatrick 
getLastCondition() const6223e5dd7070Spatrick const Expr *CFGBlock::getLastCondition() const {
6224e5dd7070Spatrick   // If the terminator is a temporary dtor or a virtual base, etc, we can't
6225e5dd7070Spatrick   // retrieve a meaningful condition, bail out.
6226e5dd7070Spatrick   if (Terminator.getKind() != CFGTerminator::StmtBranch)
6227e5dd7070Spatrick     return nullptr;
6228e5dd7070Spatrick 
6229e5dd7070Spatrick   // Also, if this method was called on a block that doesn't have 2 successors,
6230e5dd7070Spatrick   // this block doesn't have retrievable condition.
6231e5dd7070Spatrick   if (succ_size() < 2)
6232e5dd7070Spatrick     return nullptr;
6233e5dd7070Spatrick 
6234e5dd7070Spatrick   // FIXME: Is there a better condition expression we can return in this case?
6235e5dd7070Spatrick   if (size() == 0)
6236e5dd7070Spatrick     return nullptr;
6237e5dd7070Spatrick 
6238e5dd7070Spatrick   auto StmtElem = rbegin()->getAs<CFGStmt>();
6239e5dd7070Spatrick   if (!StmtElem)
6240e5dd7070Spatrick     return nullptr;
6241e5dd7070Spatrick 
6242e5dd7070Spatrick   const Stmt *Cond = StmtElem->getStmt();
6243e5dd7070Spatrick   if (isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))
6244e5dd7070Spatrick     return nullptr;
6245e5dd7070Spatrick 
6246e5dd7070Spatrick   // Only ObjCForCollectionStmt is known not to be a non-Expr terminator, hence
6247e5dd7070Spatrick   // the cast<>.
6248e5dd7070Spatrick   return cast<Expr>(Cond)->IgnoreParens();
6249e5dd7070Spatrick }
6250e5dd7070Spatrick 
getTerminatorCondition(bool StripParens)6251e5dd7070Spatrick Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
6252e5dd7070Spatrick   Stmt *Terminator = getTerminatorStmt();
6253e5dd7070Spatrick   if (!Terminator)
6254e5dd7070Spatrick     return nullptr;
6255e5dd7070Spatrick 
6256e5dd7070Spatrick   Expr *E = nullptr;
6257e5dd7070Spatrick 
6258e5dd7070Spatrick   switch (Terminator->getStmtClass()) {
6259e5dd7070Spatrick     default:
6260e5dd7070Spatrick       break;
6261e5dd7070Spatrick 
6262e5dd7070Spatrick     case Stmt::CXXForRangeStmtClass:
6263e5dd7070Spatrick       E = cast<CXXForRangeStmt>(Terminator)->getCond();
6264e5dd7070Spatrick       break;
6265e5dd7070Spatrick 
6266e5dd7070Spatrick     case Stmt::ForStmtClass:
6267e5dd7070Spatrick       E = cast<ForStmt>(Terminator)->getCond();
6268e5dd7070Spatrick       break;
6269e5dd7070Spatrick 
6270e5dd7070Spatrick     case Stmt::WhileStmtClass:
6271e5dd7070Spatrick       E = cast<WhileStmt>(Terminator)->getCond();
6272e5dd7070Spatrick       break;
6273e5dd7070Spatrick 
6274e5dd7070Spatrick     case Stmt::DoStmtClass:
6275e5dd7070Spatrick       E = cast<DoStmt>(Terminator)->getCond();
6276e5dd7070Spatrick       break;
6277e5dd7070Spatrick 
6278e5dd7070Spatrick     case Stmt::IfStmtClass:
6279e5dd7070Spatrick       E = cast<IfStmt>(Terminator)->getCond();
6280e5dd7070Spatrick       break;
6281e5dd7070Spatrick 
6282e5dd7070Spatrick     case Stmt::ChooseExprClass:
6283e5dd7070Spatrick       E = cast<ChooseExpr>(Terminator)->getCond();
6284e5dd7070Spatrick       break;
6285e5dd7070Spatrick 
6286e5dd7070Spatrick     case Stmt::IndirectGotoStmtClass:
6287e5dd7070Spatrick       E = cast<IndirectGotoStmt>(Terminator)->getTarget();
6288e5dd7070Spatrick       break;
6289e5dd7070Spatrick 
6290e5dd7070Spatrick     case Stmt::SwitchStmtClass:
6291e5dd7070Spatrick       E = cast<SwitchStmt>(Terminator)->getCond();
6292e5dd7070Spatrick       break;
6293e5dd7070Spatrick 
6294e5dd7070Spatrick     case Stmt::BinaryConditionalOperatorClass:
6295e5dd7070Spatrick       E = cast<BinaryConditionalOperator>(Terminator)->getCond();
6296e5dd7070Spatrick       break;
6297e5dd7070Spatrick 
6298e5dd7070Spatrick     case Stmt::ConditionalOperatorClass:
6299e5dd7070Spatrick       E = cast<ConditionalOperator>(Terminator)->getCond();
6300e5dd7070Spatrick       break;
6301e5dd7070Spatrick 
6302e5dd7070Spatrick     case Stmt::BinaryOperatorClass: // '&&' and '||'
6303e5dd7070Spatrick       E = cast<BinaryOperator>(Terminator)->getLHS();
6304e5dd7070Spatrick       break;
6305e5dd7070Spatrick 
6306e5dd7070Spatrick     case Stmt::ObjCForCollectionStmtClass:
6307e5dd7070Spatrick       return Terminator;
6308e5dd7070Spatrick   }
6309e5dd7070Spatrick 
6310e5dd7070Spatrick   if (!StripParens)
6311e5dd7070Spatrick     return E;
6312e5dd7070Spatrick 
6313e5dd7070Spatrick   return E ? E->IgnoreParens() : nullptr;
6314e5dd7070Spatrick }
6315e5dd7070Spatrick 
6316e5dd7070Spatrick //===----------------------------------------------------------------------===//
6317e5dd7070Spatrick // CFG Graphviz Visualization
6318e5dd7070Spatrick //===----------------------------------------------------------------------===//
6319e5dd7070Spatrick 
6320e5dd7070Spatrick static StmtPrinterHelper *GraphHelper;
6321e5dd7070Spatrick 
viewCFG(const LangOptions & LO) const6322e5dd7070Spatrick void CFG::viewCFG(const LangOptions &LO) const {
6323e5dd7070Spatrick   StmtPrinterHelper H(this, LO);
6324e5dd7070Spatrick   GraphHelper = &H;
6325e5dd7070Spatrick   llvm::ViewGraph(this,"CFG");
6326e5dd7070Spatrick   GraphHelper = nullptr;
6327e5dd7070Spatrick }
6328e5dd7070Spatrick 
6329e5dd7070Spatrick namespace llvm {
6330e5dd7070Spatrick 
6331e5dd7070Spatrick template<>
6332e5dd7070Spatrick struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits6333e5dd7070Spatrick   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
6334e5dd7070Spatrick 
getNodeLabelllvm::DOTGraphTraits6335e5dd7070Spatrick   static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph) {
6336e5dd7070Spatrick     std::string OutSStr;
6337e5dd7070Spatrick     llvm::raw_string_ostream Out(OutSStr);
6338e5dd7070Spatrick     print_block(Out,Graph, *Node, *GraphHelper, false, false);
6339e5dd7070Spatrick     std::string& OutStr = Out.str();
6340e5dd7070Spatrick 
6341e5dd7070Spatrick     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
6342e5dd7070Spatrick 
6343e5dd7070Spatrick     // Process string output to make it nicer...
6344e5dd7070Spatrick     for (unsigned i = 0; i != OutStr.length(); ++i)
6345e5dd7070Spatrick       if (OutStr[i] == '\n') {                            // Left justify
6346e5dd7070Spatrick         OutStr[i] = '\\';
6347e5dd7070Spatrick         OutStr.insert(OutStr.begin()+i+1, 'l');
6348e5dd7070Spatrick       }
6349e5dd7070Spatrick 
6350e5dd7070Spatrick     return OutStr;
6351e5dd7070Spatrick   }
6352e5dd7070Spatrick };
6353e5dd7070Spatrick 
6354e5dd7070Spatrick } // namespace llvm
6355