xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/CFG.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- CFG.cpp - Classes for representing and building CFGs ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines the CFG and CFGBuilder classes for representing and
100b57cec5SDimitry Andric //  building Control-Flow Graphs (CFGs) from ASTs.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/Attr.h"
170b57cec5SDimitry Andric #include "clang/AST/Decl.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclBase.h"
190b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h"
210b57cec5SDimitry Andric #include "clang/AST/Expr.h"
220b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
230b57cec5SDimitry Andric #include "clang/AST/OperationKinds.h"
240b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h"
250b57cec5SDimitry Andric #include "clang/AST/Stmt.h"
260b57cec5SDimitry Andric #include "clang/AST/StmtCXX.h"
270b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
280b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h"
290b57cec5SDimitry Andric #include "clang/AST/Type.h"
300b57cec5SDimitry Andric #include "clang/Analysis/ConstructionContext.h"
310b57cec5SDimitry Andric #include "clang/Analysis/Support/BumpVector.h"
320b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
330b57cec5SDimitry Andric #include "clang/Basic/ExceptionSpecificationType.h"
340b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h"
350b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
360b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
370b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
380b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h"
390b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
400b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
410b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
420b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
430b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
440b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
450b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
460b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
470b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
480b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
490b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
500b57cec5SDimitry Andric #include "llvm/Support/DOTGraphTraits.h"
510b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
520b57cec5SDimitry Andric #include "llvm/Support/Format.h"
530b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h"
540b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
550b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
560b57cec5SDimitry Andric #include <cassert>
570b57cec5SDimitry Andric #include <memory>
58bdd1243dSDimitry Andric #include <optional>
590b57cec5SDimitry Andric #include <string>
600b57cec5SDimitry Andric #include <tuple>
610b57cec5SDimitry Andric #include <utility>
620b57cec5SDimitry Andric #include <vector>
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric using namespace clang;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric static SourceLocation GetEndLoc(Decl *D) {
670b57cec5SDimitry Andric   if (VarDecl *VD = dyn_cast<VarDecl>(D))
680b57cec5SDimitry Andric     if (Expr *Ex = VD->getInit())
690b57cec5SDimitry Andric       return Ex->getSourceRange().getEnd();
700b57cec5SDimitry Andric   return D->getLocation();
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
73a7dea167SDimitry Andric /// Returns true on constant values based around a single IntegerLiteral.
74a7dea167SDimitry Andric /// Allow for use of parentheses, integer casts, and negative signs.
75bdd1243dSDimitry Andric /// FIXME: it would be good to unify this function with
76bdd1243dSDimitry Andric /// getIntegerLiteralSubexpressionValue at some point given the similarity
77bdd1243dSDimitry Andric /// between the functions.
78bdd1243dSDimitry Andric 
79a7dea167SDimitry Andric static bool IsIntegerLiteralConstantExpr(const Expr *E) {
80a7dea167SDimitry Andric   // Allow parentheses
81a7dea167SDimitry Andric   E = E->IgnoreParens();
82a7dea167SDimitry Andric 
83a7dea167SDimitry Andric   // Allow conversions to different integer kind.
84a7dea167SDimitry Andric   if (const auto *CE = dyn_cast<CastExpr>(E)) {
85a7dea167SDimitry Andric     if (CE->getCastKind() != CK_IntegralCast)
86a7dea167SDimitry Andric       return false;
87a7dea167SDimitry Andric     E = CE->getSubExpr();
88a7dea167SDimitry Andric   }
89a7dea167SDimitry Andric 
90a7dea167SDimitry Andric   // Allow negative numbers.
91a7dea167SDimitry Andric   if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
92a7dea167SDimitry Andric     if (UO->getOpcode() != UO_Minus)
93a7dea167SDimitry Andric       return false;
94a7dea167SDimitry Andric     E = UO->getSubExpr();
95a7dea167SDimitry Andric   }
96a7dea167SDimitry Andric 
97a7dea167SDimitry Andric   return isa<IntegerLiteral>(E);
98a7dea167SDimitry Andric }
99a7dea167SDimitry Andric 
1000b57cec5SDimitry Andric /// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral
101a7dea167SDimitry Andric /// constant expression or EnumConstantDecl from the given Expr. If it fails,
102a7dea167SDimitry Andric /// returns nullptr.
1030b57cec5SDimitry Andric static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {
1040b57cec5SDimitry Andric   E = E->IgnoreParens();
105a7dea167SDimitry Andric   if (IsIntegerLiteralConstantExpr(E))
1060b57cec5SDimitry Andric     return E;
1070b57cec5SDimitry Andric   if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
1080b57cec5SDimitry Andric     return isa<EnumConstantDecl>(DR->getDecl()) ? DR : nullptr;
1090b57cec5SDimitry Andric   return nullptr;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
112a7dea167SDimitry Andric /// Tries to interpret a binary operator into `Expr Op NumExpr` form, if
113a7dea167SDimitry Andric /// NumExpr is an integer literal or an enum constant.
1140b57cec5SDimitry Andric ///
1150b57cec5SDimitry Andric /// If this fails, at least one of the returned DeclRefExpr or Expr will be
1160b57cec5SDimitry Andric /// null.
117a7dea167SDimitry Andric static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
1180b57cec5SDimitry Andric tryNormalizeBinaryOperator(const BinaryOperator *B) {
1190b57cec5SDimitry Andric   BinaryOperatorKind Op = B->getOpcode();
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   const Expr *MaybeDecl = B->getLHS();
1220b57cec5SDimitry Andric   const Expr *Constant = tryTransformToIntOrEnumConstant(B->getRHS());
1230b57cec5SDimitry Andric   // Expr looked like `0 == Foo` instead of `Foo == 0`
1240b57cec5SDimitry Andric   if (Constant == nullptr) {
1250b57cec5SDimitry Andric     // Flip the operator
1260b57cec5SDimitry Andric     if (Op == BO_GT)
1270b57cec5SDimitry Andric       Op = BO_LT;
1280b57cec5SDimitry Andric     else if (Op == BO_GE)
1290b57cec5SDimitry Andric       Op = BO_LE;
1300b57cec5SDimitry Andric     else if (Op == BO_LT)
1310b57cec5SDimitry Andric       Op = BO_GT;
1320b57cec5SDimitry Andric     else if (Op == BO_LE)
1330b57cec5SDimitry Andric       Op = BO_GE;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     MaybeDecl = B->getRHS();
1360b57cec5SDimitry Andric     Constant = tryTransformToIntOrEnumConstant(B->getLHS());
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
139a7dea167SDimitry Andric   return std::make_tuple(MaybeDecl, Op, Constant);
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric /// For an expression `x == Foo && x == Bar`, this determines whether the
1430b57cec5SDimitry Andric /// `Foo` and `Bar` are either of the same enumeration type, or both integer
1440b57cec5SDimitry Andric /// literals.
1450b57cec5SDimitry Andric ///
1460b57cec5SDimitry Andric /// It's an error to pass this arguments that are not either IntegerLiterals
1470b57cec5SDimitry Andric /// or DeclRefExprs (that have decls of type EnumConstantDecl)
1480b57cec5SDimitry Andric static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {
1490b57cec5SDimitry Andric   // User intent isn't clear if they're mixing int literals with enum
1500b57cec5SDimitry Andric   // constants.
151a7dea167SDimitry Andric   if (isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))
1520b57cec5SDimitry Andric     return false;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   // Integer literal comparisons, regardless of literal type, are acceptable.
155a7dea167SDimitry Andric   if (!isa<DeclRefExpr>(E1))
1560b57cec5SDimitry Andric     return true;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   // IntegerLiterals are handled above and only EnumConstantDecls are expected
1590b57cec5SDimitry Andric   // beyond this point
1600b57cec5SDimitry Andric   assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));
1610b57cec5SDimitry Andric   auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();
1620b57cec5SDimitry Andric   auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));
1650b57cec5SDimitry Andric   const DeclContext *DC1 = Decl1->getDeclContext();
1660b57cec5SDimitry Andric   const DeclContext *DC2 = Decl2->getDeclContext();
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));
1690b57cec5SDimitry Andric   return DC1 == DC2;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric namespace {
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric class CFGBuilder;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric /// The CFG builder uses a recursive algorithm to build the CFG.  When
1770b57cec5SDimitry Andric ///  we process an expression, sometimes we know that we must add the
1780b57cec5SDimitry Andric ///  subexpressions as block-level expressions.  For example:
1790b57cec5SDimitry Andric ///
1800b57cec5SDimitry Andric ///    exp1 || exp2
1810b57cec5SDimitry Andric ///
1820b57cec5SDimitry Andric ///  When processing the '||' expression, we know that exp1 and exp2
1830b57cec5SDimitry Andric ///  need to be added as block-level expressions, even though they
1840b57cec5SDimitry Andric ///  might not normally need to be.  AddStmtChoice records this
1850b57cec5SDimitry Andric ///  contextual information.  If AddStmtChoice is 'NotAlwaysAdd', then
1860b57cec5SDimitry Andric ///  the builder has an option not to add a subexpression as a
1870b57cec5SDimitry Andric ///  block-level expression.
1880b57cec5SDimitry Andric class AddStmtChoice {
1890b57cec5SDimitry Andric public:
1900b57cec5SDimitry Andric   enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   bool alwaysAdd(CFGBuilder &builder,
1950b57cec5SDimitry Andric                  const Stmt *stmt) const;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   /// Return a copy of this object, except with the 'always-add' bit
1980b57cec5SDimitry Andric   ///  set as specified.
1990b57cec5SDimitry Andric   AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {
2000b57cec5SDimitry Andric     return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric private:
2040b57cec5SDimitry Andric   Kind kind;
2050b57cec5SDimitry Andric };
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric /// LocalScope - Node in tree of local scopes created for C++ implicit
2080b57cec5SDimitry Andric /// destructor calls generation. It contains list of automatic variables
2090b57cec5SDimitry Andric /// declared in the scope and link to position in previous scope this scope
2100b57cec5SDimitry Andric /// began in.
2110b57cec5SDimitry Andric ///
2120b57cec5SDimitry Andric /// The process of creating local scopes is as follows:
2130b57cec5SDimitry Andric /// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),
2140b57cec5SDimitry Andric /// - Before processing statements in scope (e.g. CompoundStmt) create
2150b57cec5SDimitry Andric ///   LocalScope object using CFGBuilder::ScopePos as link to previous scope
2160b57cec5SDimitry Andric ///   and set CFGBuilder::ScopePos to the end of new scope,
2170b57cec5SDimitry Andric /// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points
2180b57cec5SDimitry Andric ///   at this VarDecl,
2190b57cec5SDimitry Andric /// - For every normal (without jump) end of scope add to CFGBlock destructors
2200b57cec5SDimitry Andric ///   for objects in the current scope,
2210b57cec5SDimitry Andric /// - For every jump add to CFGBlock destructors for objects
2220b57cec5SDimitry Andric ///   between CFGBuilder::ScopePos and local scope position saved for jump
2230b57cec5SDimitry Andric ///   target. Thanks to C++ restrictions on goto jumps we can be sure that
2240b57cec5SDimitry Andric ///   jump target position will be on the path to root from CFGBuilder::ScopePos
2250b57cec5SDimitry Andric ///   (adding any variable that doesn't need constructor to be called to
2260b57cec5SDimitry Andric ///   LocalScope can break this assumption),
2270b57cec5SDimitry Andric ///
2280b57cec5SDimitry Andric class LocalScope {
2290b57cec5SDimitry Andric public:
2300b57cec5SDimitry Andric   using AutomaticVarsTy = BumpVector<VarDecl *>;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// const_iterator - Iterates local scope backwards and jumps to previous
2330b57cec5SDimitry Andric   /// scope on reaching the beginning of currently iterated scope.
2340b57cec5SDimitry Andric   class const_iterator {
2350b57cec5SDimitry Andric     const LocalScope* Scope = nullptr;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric     /// VarIter is guaranteed to be greater then 0 for every valid iterator.
2380b57cec5SDimitry Andric     /// Invalid iterator (with null Scope) has VarIter equal to 0.
2390b57cec5SDimitry Andric     unsigned VarIter = 0;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   public:
2420b57cec5SDimitry Andric     /// Create invalid iterator. Dereferencing invalid iterator is not allowed.
2430b57cec5SDimitry Andric     /// Incrementing invalid iterator is allowed and will result in invalid
2440b57cec5SDimitry Andric     /// iterator.
2450b57cec5SDimitry Andric     const_iterator() = default;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     /// Create valid iterator. In case when S.Prev is an invalid iterator and
2480b57cec5SDimitry Andric     /// I is equal to 0, this will create invalid iterator.
2490b57cec5SDimitry Andric     const_iterator(const LocalScope& S, unsigned I)
2500b57cec5SDimitry Andric         : Scope(&S), VarIter(I) {
2510b57cec5SDimitry Andric       // Iterator to "end" of scope is not allowed. Handle it by going up
2520b57cec5SDimitry Andric       // in scopes tree possibly up to invalid iterator in the root.
2530b57cec5SDimitry Andric       if (VarIter == 0 && Scope)
2540b57cec5SDimitry Andric         *this = Scope->Prev;
2550b57cec5SDimitry Andric     }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric     VarDecl *const* operator->() const {
2580b57cec5SDimitry Andric       assert(Scope && "Dereferencing invalid iterator is not allowed");
2590b57cec5SDimitry Andric       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
2600b57cec5SDimitry Andric       return &Scope->Vars[VarIter - 1];
2610b57cec5SDimitry Andric     }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric     const VarDecl *getFirstVarInScope() const {
2640b57cec5SDimitry Andric       assert(Scope && "Dereferencing invalid iterator is not allowed");
2650b57cec5SDimitry Andric       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
2660b57cec5SDimitry Andric       return Scope->Vars[0];
2670b57cec5SDimitry Andric     }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric     VarDecl *operator*() const {
2700b57cec5SDimitry Andric       return *this->operator->();
2710b57cec5SDimitry Andric     }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric     const_iterator &operator++() {
2740b57cec5SDimitry Andric       if (!Scope)
2750b57cec5SDimitry Andric         return *this;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       assert(VarIter != 0 && "Iterator has invalid value of VarIter member");
2780b57cec5SDimitry Andric       --VarIter;
2790b57cec5SDimitry Andric       if (VarIter == 0)
2800b57cec5SDimitry Andric         *this = Scope->Prev;
2810b57cec5SDimitry Andric       return *this;
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric     const_iterator operator++(int) {
2840b57cec5SDimitry Andric       const_iterator P = *this;
2850b57cec5SDimitry Andric       ++*this;
2860b57cec5SDimitry Andric       return P;
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     bool operator==(const const_iterator &rhs) const {
2900b57cec5SDimitry Andric       return Scope == rhs.Scope && VarIter == rhs.VarIter;
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric     bool operator!=(const const_iterator &rhs) const {
2930b57cec5SDimitry Andric       return !(*this == rhs);
2940b57cec5SDimitry Andric     }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric     explicit operator bool() const {
2970b57cec5SDimitry Andric       return *this != const_iterator();
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     int distance(const_iterator L);
3010b57cec5SDimitry Andric     const_iterator shared_parent(const_iterator L);
3020b57cec5SDimitry Andric     bool pointsToFirstDeclaredVar() { return VarIter == 1; }
30306c3fb27SDimitry Andric     bool inSameLocalScope(const_iterator rhs) { return Scope == rhs.Scope; }
3040b57cec5SDimitry Andric   };
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric private:
3070b57cec5SDimitry Andric   BumpVectorContext ctx;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   /// Automatic variables in order of declaration.
3100b57cec5SDimitry Andric   AutomaticVarsTy Vars;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   /// Iterator to variable in previous scope that was declared just before
3130b57cec5SDimitry Andric   /// begin of this scope.
3140b57cec5SDimitry Andric   const_iterator Prev;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric public:
3170b57cec5SDimitry Andric   /// Constructs empty scope linked to previous scope in specified place.
3180b57cec5SDimitry Andric   LocalScope(BumpVectorContext ctx, const_iterator P)
3190b57cec5SDimitry Andric       : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   /// Begin of scope in direction of CFG building (backwards).
3220b57cec5SDimitry Andric   const_iterator begin() const { return const_iterator(*this, Vars.size()); }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   void addVar(VarDecl *VD) {
3250b57cec5SDimitry Andric     Vars.push_back(VD, ctx);
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric };
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric } // namespace
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric /// distance - Calculates distance from this to L. L must be reachable from this
3320b57cec5SDimitry Andric /// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.
3330b57cec5SDimitry Andric /// number of scopes between this and L.
3340b57cec5SDimitry Andric int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {
3350b57cec5SDimitry Andric   int D = 0;
3360b57cec5SDimitry Andric   const_iterator F = *this;
3370b57cec5SDimitry Andric   while (F.Scope != L.Scope) {
3380b57cec5SDimitry Andric     assert(F != const_iterator() &&
3390b57cec5SDimitry Andric            "L iterator is not reachable from F iterator.");
3400b57cec5SDimitry Andric     D += F.VarIter;
3410b57cec5SDimitry Andric     F = F.Scope->Prev;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric   D += F.VarIter - L.VarIter;
3440b57cec5SDimitry Andric   return D;
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric /// Calculates the closest parent of this iterator
3480b57cec5SDimitry Andric /// that is in a scope reachable through the parents of L.
3490b57cec5SDimitry Andric /// I.e. when using 'goto' from this to L, the lifetime of all variables
3500b57cec5SDimitry Andric /// between this and shared_parent(L) end.
3510b57cec5SDimitry Andric LocalScope::const_iterator
3520b57cec5SDimitry Andric LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {
35306c3fb27SDimitry Andric   // one of iterators is not valid (we are not in scope), so common
35406c3fb27SDimitry Andric   // parent is const_iterator() (i.e. sentinel).
35506c3fb27SDimitry Andric   if ((*this == const_iterator()) || (L == const_iterator())) {
35606c3fb27SDimitry Andric     return const_iterator();
35706c3fb27SDimitry Andric   }
35806c3fb27SDimitry Andric 
35906c3fb27SDimitry Andric   const_iterator F = *this;
36006c3fb27SDimitry Andric   if (F.inSameLocalScope(L)) {
36106c3fb27SDimitry Andric     // Iterators are in the same scope, get common subset of variables.
36206c3fb27SDimitry Andric     F.VarIter = std::min(F.VarIter, L.VarIter);
36306c3fb27SDimitry Andric     return F;
36406c3fb27SDimitry Andric   }
36506c3fb27SDimitry Andric 
36606c3fb27SDimitry Andric   llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;
3670b57cec5SDimitry Andric   while (true) {
36806c3fb27SDimitry Andric     ScopesOfL.try_emplace(L.Scope, L.VarIter);
3690b57cec5SDimitry Andric     if (L == const_iterator())
3700b57cec5SDimitry Andric       break;
3710b57cec5SDimitry Andric     L = L.Scope->Prev;
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   while (true) {
37506c3fb27SDimitry Andric     if (auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {
37606c3fb27SDimitry Andric       // Get common subset of variables in given scope
37706c3fb27SDimitry Andric       F.VarIter = std::min(F.VarIter, LIt->getSecond());
3780b57cec5SDimitry Andric       return F;
37906c3fb27SDimitry Andric     }
3800b57cec5SDimitry Andric     assert(F != const_iterator() &&
3810b57cec5SDimitry Andric            "L iterator is not reachable from F iterator.");
3820b57cec5SDimitry Andric     F = F.Scope->Prev;
3830b57cec5SDimitry Andric   }
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric namespace {
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric /// Structure for specifying position in CFG during its build process. It
3890b57cec5SDimitry Andric /// consists of CFGBlock that specifies position in CFG and
3900b57cec5SDimitry Andric /// LocalScope::const_iterator that specifies position in LocalScope graph.
3910b57cec5SDimitry Andric struct BlockScopePosPair {
3920b57cec5SDimitry Andric   CFGBlock *block = nullptr;
3930b57cec5SDimitry Andric   LocalScope::const_iterator scopePosition;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   BlockScopePosPair() = default;
3960b57cec5SDimitry Andric   BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)
3970b57cec5SDimitry Andric       : block(b), scopePosition(scopePos) {}
3980b57cec5SDimitry Andric };
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric /// TryResult - a class representing a variant over the values
4010b57cec5SDimitry Andric ///  'true', 'false', or 'unknown'.  This is returned by tryEvaluateBool,
4020b57cec5SDimitry Andric ///  and is used by the CFGBuilder to decide if a branch condition
4030b57cec5SDimitry Andric ///  can be decided up front during CFG construction.
4040b57cec5SDimitry Andric class TryResult {
4050b57cec5SDimitry Andric   int X = -1;
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric public:
4080b57cec5SDimitry Andric   TryResult() = default;
4090b57cec5SDimitry Andric   TryResult(bool b) : X(b ? 1 : 0) {}
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   bool isTrue() const { return X == 1; }
4120b57cec5SDimitry Andric   bool isFalse() const { return X == 0; }
4130b57cec5SDimitry Andric   bool isKnown() const { return X >= 0; }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   void negate() {
4160b57cec5SDimitry Andric     assert(isKnown());
4170b57cec5SDimitry Andric     X ^= 0x1;
4180b57cec5SDimitry Andric   }
4190b57cec5SDimitry Andric };
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric } // namespace
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric static TryResult bothKnownTrue(TryResult R1, TryResult R2) {
4240b57cec5SDimitry Andric   if (!R1.isKnown() || !R2.isKnown())
4250b57cec5SDimitry Andric     return TryResult();
4260b57cec5SDimitry Andric   return TryResult(R1.isTrue() && R2.isTrue());
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric namespace {
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric class reverse_children {
4320b57cec5SDimitry Andric   llvm::SmallVector<Stmt *, 12> childrenBuf;
4330b57cec5SDimitry Andric   ArrayRef<Stmt *> children;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric public:
4360b57cec5SDimitry Andric   reverse_children(Stmt *S);
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   using iterator = ArrayRef<Stmt *>::reverse_iterator;
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   iterator begin() const { return children.rbegin(); }
4410b57cec5SDimitry Andric   iterator end() const { return children.rend(); }
4420b57cec5SDimitry Andric };
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric } // namespace
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric reverse_children::reverse_children(Stmt *S) {
4470b57cec5SDimitry Andric   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
4480b57cec5SDimitry Andric     children = CE->getRawSubExprs();
4490b57cec5SDimitry Andric     return;
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric   switch (S->getStmtClass()) {
4520b57cec5SDimitry Andric     // Note: Fill in this switch with more cases we want to optimize.
4530b57cec5SDimitry Andric     case Stmt::InitListExprClass: {
4540b57cec5SDimitry Andric       InitListExpr *IE = cast<InitListExpr>(S);
455bdd1243dSDimitry Andric       children = llvm::ArrayRef(reinterpret_cast<Stmt **>(IE->getInits()),
4560b57cec5SDimitry Andric                                 IE->getNumInits());
4570b57cec5SDimitry Andric       return;
4580b57cec5SDimitry Andric     }
4590b57cec5SDimitry Andric     default:
4600b57cec5SDimitry Andric       break;
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   // Default case for all other statements.
46481ad6265SDimitry Andric   llvm::append_range(childrenBuf, S->children());
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   // This needs to be done *after* childrenBuf has been populated.
4670b57cec5SDimitry Andric   children = childrenBuf;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric namespace {
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric /// CFGBuilder - This class implements CFG construction from an AST.
4730b57cec5SDimitry Andric ///   The builder is stateful: an instance of the builder should be used to only
4740b57cec5SDimitry Andric ///   construct a single CFG.
4750b57cec5SDimitry Andric ///
4760b57cec5SDimitry Andric ///   Example usage:
4770b57cec5SDimitry Andric ///
4780b57cec5SDimitry Andric ///     CFGBuilder builder;
4790b57cec5SDimitry Andric ///     std::unique_ptr<CFG> cfg = builder.buildCFG(decl, stmt1);
4800b57cec5SDimitry Andric ///
4810b57cec5SDimitry Andric ///  CFG construction is done via a recursive walk of an AST.  We actually parse
4820b57cec5SDimitry Andric ///  the AST in reverse order so that the successor of a basic block is
4830b57cec5SDimitry Andric ///  constructed prior to its predecessor.  This allows us to nicely capture
4840b57cec5SDimitry Andric ///  implicit fall-throughs without extra basic blocks.
4850b57cec5SDimitry Andric class CFGBuilder {
4860b57cec5SDimitry Andric   using JumpTarget = BlockScopePosPair;
4870b57cec5SDimitry Andric   using JumpSource = BlockScopePosPair;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   ASTContext *Context;
4900b57cec5SDimitry Andric   std::unique_ptr<CFG> cfg;
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   // Current block.
4930b57cec5SDimitry Andric   CFGBlock *Block = nullptr;
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   // Block after the current block.
4960b57cec5SDimitry Andric   CFGBlock *Succ = nullptr;
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   JumpTarget ContinueJumpTarget;
4990b57cec5SDimitry Andric   JumpTarget BreakJumpTarget;
5000b57cec5SDimitry Andric   JumpTarget SEHLeaveJumpTarget;
5010b57cec5SDimitry Andric   CFGBlock *SwitchTerminatedBlock = nullptr;
5020b57cec5SDimitry Andric   CFGBlock *DefaultCaseBlock = nullptr;
5030b57cec5SDimitry Andric 
504349cc55cSDimitry Andric   // This can point to either a C++ try, an Objective-C @try, or an SEH __try.
505349cc55cSDimitry Andric   // try and @try can be mixed and generally work the same.
506349cc55cSDimitry Andric   // The frontend forbids mixing SEH __try with either try or @try.
507349cc55cSDimitry Andric   // So having one for all three is enough.
5080b57cec5SDimitry Andric   CFGBlock *TryTerminatedBlock = nullptr;
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   // Current position in local scope.
5110b57cec5SDimitry Andric   LocalScope::const_iterator ScopePos;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   // LabelMap records the mapping from Label expressions to their jump targets.
5140b57cec5SDimitry Andric   using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;
5150b57cec5SDimitry Andric   LabelMapTy LabelMap;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   // A list of blocks that end with a "goto" that must be backpatched to their
5180b57cec5SDimitry Andric   // resolved targets upon completion of CFG construction.
5190b57cec5SDimitry Andric   using BackpatchBlocksTy = std::vector<JumpSource>;
5200b57cec5SDimitry Andric   BackpatchBlocksTy BackpatchBlocks;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   // A list of labels whose address has been taken (for indirect gotos).
5230b57cec5SDimitry Andric   using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;
5240b57cec5SDimitry Andric   LabelSetTy AddressTakenLabels;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   // Information about the currently visited C++ object construction site.
5270b57cec5SDimitry Andric   // This is set in the construction trigger and read when the constructor
5280b57cec5SDimitry Andric   // or a function that returns an object by value is being visited.
5290b57cec5SDimitry Andric   llvm::DenseMap<Expr *, const ConstructionContextLayer *>
5300b57cec5SDimitry Andric       ConstructionContextMap;
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   bool badCFG = false;
5330b57cec5SDimitry Andric   const CFG::BuildOptions &BuildOpts;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   // State to track for building switch statements.
5360b57cec5SDimitry Andric   bool switchExclusivelyCovered = false;
5370b57cec5SDimitry Andric   Expr::EvalResult *switchCond = nullptr;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;
5400b57cec5SDimitry Andric   const Stmt *lastLookup = nullptr;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   // Caches boolean evaluations of expressions to avoid multiple re-evaluations
5430b57cec5SDimitry Andric   // during construction of branches for chained logical operators.
5440b57cec5SDimitry Andric   using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;
5450b57cec5SDimitry Andric   CachedBoolEvalsTy CachedBoolEvals;
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric public:
5480b57cec5SDimitry Andric   explicit CFGBuilder(ASTContext *astContext,
5490b57cec5SDimitry Andric                       const CFG::BuildOptions &buildOpts)
55004eeddc0SDimitry Andric       : Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   // buildCFG - Used by external clients to construct the CFG.
5530b57cec5SDimitry Andric   std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   bool alwaysAdd(const Stmt *stmt);
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric private:
5580b57cec5SDimitry Andric   // Visitors to walk an AST and construct the CFG.
559480093f4SDimitry Andric   CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
5600b57cec5SDimitry Andric   CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
561349cc55cSDimitry Andric   CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);
5620b57cec5SDimitry Andric   CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
5630b57cec5SDimitry Andric   CFGBlock *VisitBreakStmt(BreakStmt *B);
5640b57cec5SDimitry Andric   CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
5650b57cec5SDimitry Andric   CFGBlock *VisitCaseStmt(CaseStmt *C);
5660b57cec5SDimitry Andric   CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
567a7dea167SDimitry Andric   CFGBlock *VisitCompoundStmt(CompoundStmt *C, bool ExternallyDestructed);
5680b57cec5SDimitry Andric   CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,
5690b57cec5SDimitry Andric                                      AddStmtChoice asc);
5700b57cec5SDimitry Andric   CFGBlock *VisitContinueStmt(ContinueStmt *C);
5710b57cec5SDimitry Andric   CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
5720b57cec5SDimitry Andric                                       AddStmtChoice asc);
5730b57cec5SDimitry Andric   CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
5740b57cec5SDimitry Andric   CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);
5750b57cec5SDimitry Andric   CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);
5760b57cec5SDimitry Andric   CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);
5770b57cec5SDimitry Andric   CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);
5780b57cec5SDimitry Andric   CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
5790b57cec5SDimitry Andric                                        AddStmtChoice asc);
5800b57cec5SDimitry Andric   CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
5810b57cec5SDimitry Andric                                         AddStmtChoice asc);
5820b57cec5SDimitry Andric   CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
5830b57cec5SDimitry Andric   CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
58481ad6265SDimitry Andric   CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);
5850b57cec5SDimitry Andric   CFGBlock *VisitDeclStmt(DeclStmt *DS);
5860b57cec5SDimitry Andric   CFGBlock *VisitDeclSubExpr(DeclStmt *DS);
5870b57cec5SDimitry Andric   CFGBlock *VisitDefaultStmt(DefaultStmt *D);
5880b57cec5SDimitry Andric   CFGBlock *VisitDoStmt(DoStmt *D);
589a7dea167SDimitry Andric   CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,
590a7dea167SDimitry Andric                                   AddStmtChoice asc, bool ExternallyDestructed);
5910b57cec5SDimitry Andric   CFGBlock *VisitForStmt(ForStmt *F);
5920b57cec5SDimitry Andric   CFGBlock *VisitGotoStmt(GotoStmt *G);
5930b57cec5SDimitry Andric   CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);
5940b57cec5SDimitry Andric   CFGBlock *VisitIfStmt(IfStmt *I);
5950b57cec5SDimitry Andric   CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);
5960b57cec5SDimitry Andric   CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);
5970b57cec5SDimitry Andric   CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
5980b57cec5SDimitry Andric   CFGBlock *VisitLabelStmt(LabelStmt *L);
5990b57cec5SDimitry Andric   CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);
6000b57cec5SDimitry Andric   CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);
6010b57cec5SDimitry Andric   CFGBlock *VisitLogicalOperator(BinaryOperator *B);
6020b57cec5SDimitry Andric   std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,
6030b57cec5SDimitry Andric                                                          Stmt *Term,
6040b57cec5SDimitry Andric                                                          CFGBlock *TrueBlock,
6050b57cec5SDimitry Andric                                                          CFGBlock *FalseBlock);
6060b57cec5SDimitry Andric   CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
6070b57cec5SDimitry Andric                                           AddStmtChoice asc);
6080b57cec5SDimitry Andric   CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
6090b57cec5SDimitry Andric   CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
6100b57cec5SDimitry Andric   CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
6110b57cec5SDimitry Andric   CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
6120b57cec5SDimitry Andric   CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
6130b57cec5SDimitry Andric   CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
6140b57cec5SDimitry Andric   CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
6150b57cec5SDimitry Andric   CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);
6160b57cec5SDimitry Andric   CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);
6170b57cec5SDimitry Andric   CFGBlock *VisitReturnStmt(Stmt *S);
61881ad6265SDimitry Andric   CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,
61981ad6265SDimitry Andric                                       AddStmtChoice asc);
6200b57cec5SDimitry Andric   CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);
6210b57cec5SDimitry Andric   CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);
6220b57cec5SDimitry Andric   CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);
6230b57cec5SDimitry Andric   CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);
6240b57cec5SDimitry Andric   CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
6250b57cec5SDimitry Andric   CFGBlock *VisitSwitchStmt(SwitchStmt *S);
6260b57cec5SDimitry Andric   CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
6270b57cec5SDimitry Andric                                           AddStmtChoice asc);
6280b57cec5SDimitry Andric   CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);
6290b57cec5SDimitry Andric   CFGBlock *VisitWhileStmt(WhileStmt *W);
63081ad6265SDimitry Andric   CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);
6310b57cec5SDimitry Andric 
632a7dea167SDimitry Andric   CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,
633a7dea167SDimitry Andric                   bool ExternallyDestructed = false);
6340b57cec5SDimitry Andric   CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
6350b57cec5SDimitry Andric   CFGBlock *VisitChildren(Stmt *S);
6360b57cec5SDimitry Andric   CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);
6370b57cec5SDimitry Andric   CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,
6380b57cec5SDimitry Andric                                         AddStmtChoice asc);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,
6410b57cec5SDimitry Andric                                     const Stmt *S) {
6420b57cec5SDimitry Andric     if (ScopePos && (VD == ScopePos.getFirstVarInScope()))
6430b57cec5SDimitry Andric       appendScopeBegin(B, VD, S);
6440b57cec5SDimitry Andric   }
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   /// When creating the CFG for temporary destructors, we want to mirror the
6470b57cec5SDimitry Andric   /// branch structure of the corresponding constructor calls.
6480b57cec5SDimitry Andric   /// Thus, while visiting a statement for temporary destructors, we keep a
6490b57cec5SDimitry Andric   /// context to keep track of the following information:
6500b57cec5SDimitry Andric   /// - whether a subexpression is executed unconditionally
6510b57cec5SDimitry Andric   /// - if a subexpression is executed conditionally, the first
6520b57cec5SDimitry Andric   ///   CXXBindTemporaryExpr we encounter in that subexpression (which
6530b57cec5SDimitry Andric   ///   corresponds to the last temporary destructor we have to call for this
6540b57cec5SDimitry Andric   ///   subexpression) and the CFG block at that point (which will become the
6550b57cec5SDimitry Andric   ///   successor block when inserting the decision point).
6560b57cec5SDimitry Andric   ///
6570b57cec5SDimitry Andric   /// That way, we can build the branch structure for temporary destructors as
6580b57cec5SDimitry Andric   /// follows:
6590b57cec5SDimitry Andric   /// 1. If a subexpression is executed unconditionally, we add the temporary
6600b57cec5SDimitry Andric   ///    destructor calls to the current block.
6610b57cec5SDimitry Andric   /// 2. If a subexpression is executed conditionally, when we encounter a
6620b57cec5SDimitry Andric   ///    CXXBindTemporaryExpr:
6630b57cec5SDimitry Andric   ///    a) If it is the first temporary destructor call in the subexpression,
6640b57cec5SDimitry Andric   ///       we remember the CXXBindTemporaryExpr and the current block in the
6650b57cec5SDimitry Andric   ///       TempDtorContext; we start a new block, and insert the temporary
6660b57cec5SDimitry Andric   ///       destructor call.
6670b57cec5SDimitry Andric   ///    b) Otherwise, add the temporary destructor call to the current block.
6680b57cec5SDimitry Andric   ///  3. When we finished visiting a conditionally executed subexpression,
6690b57cec5SDimitry Andric   ///     and we found at least one temporary constructor during the visitation
6700b57cec5SDimitry Andric   ///     (2.a has executed), we insert a decision block that uses the
6710b57cec5SDimitry Andric   ///     CXXBindTemporaryExpr as terminator, and branches to the current block
6720b57cec5SDimitry Andric   ///     if the CXXBindTemporaryExpr was marked executed, and otherwise
6730b57cec5SDimitry Andric   ///     branches to the stored successor.
6740b57cec5SDimitry Andric   struct TempDtorContext {
6750b57cec5SDimitry Andric     TempDtorContext() = default;
6760b57cec5SDimitry Andric     TempDtorContext(TryResult KnownExecuted)
6770b57cec5SDimitry Andric         : IsConditional(true), KnownExecuted(KnownExecuted) {}
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric     /// Returns whether we need to start a new branch for a temporary destructor
6800b57cec5SDimitry Andric     /// call. This is the case when the temporary destructor is
6810b57cec5SDimitry Andric     /// conditionally executed, and it is the first one we encounter while
6820b57cec5SDimitry Andric     /// visiting a subexpression - other temporary destructors at the same level
6830b57cec5SDimitry Andric     /// will be added to the same block and are executed under the same
6840b57cec5SDimitry Andric     /// condition.
6850b57cec5SDimitry Andric     bool needsTempDtorBranch() const {
6860b57cec5SDimitry Andric       return IsConditional && !TerminatorExpr;
6870b57cec5SDimitry Andric     }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     /// Remember the successor S of a temporary destructor decision branch for
6900b57cec5SDimitry Andric     /// the corresponding CXXBindTemporaryExpr E.
6910b57cec5SDimitry Andric     void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {
6920b57cec5SDimitry Andric       Succ = S;
6930b57cec5SDimitry Andric       TerminatorExpr = E;
6940b57cec5SDimitry Andric     }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric     const bool IsConditional = false;
6970b57cec5SDimitry Andric     const TryResult KnownExecuted = true;
6980b57cec5SDimitry Andric     CFGBlock *Succ = nullptr;
6990b57cec5SDimitry Andric     CXXBindTemporaryExpr *TerminatorExpr = nullptr;
7000b57cec5SDimitry Andric   };
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   // Visitors to walk an AST and generate destructors of temporaries in
7030b57cec5SDimitry Andric   // full expression.
704a7dea167SDimitry Andric   CFGBlock *VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
7050b57cec5SDimitry Andric                                    TempDtorContext &Context);
706a7dea167SDimitry Andric   CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E,  bool ExternallyDestructed,
707a7dea167SDimitry Andric                                            TempDtorContext &Context);
7080b57cec5SDimitry Andric   CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,
709a7dea167SDimitry Andric                                                  bool ExternallyDestructed,
7100b57cec5SDimitry Andric                                                  TempDtorContext &Context);
7110b57cec5SDimitry Andric   CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(
712a7dea167SDimitry Andric       CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context);
7130b57cec5SDimitry Andric   CFGBlock *VisitConditionalOperatorForTemporaryDtors(
714a7dea167SDimitry Andric       AbstractConditionalOperator *E, bool ExternallyDestructed,
7150b57cec5SDimitry Andric       TempDtorContext &Context);
7160b57cec5SDimitry Andric   void InsertTempDtorDecisionBlock(const TempDtorContext &Context,
7170b57cec5SDimitry Andric                                    CFGBlock *FalseSucc = nullptr);
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   // NYS == Not Yet Supported
7200b57cec5SDimitry Andric   CFGBlock *NYS() {
7210b57cec5SDimitry Andric     badCFG = true;
7220b57cec5SDimitry Andric     return Block;
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric   // Remember to apply the construction context based on the current \p Layer
7260b57cec5SDimitry Andric   // when constructing the CFG element for \p CE.
7270b57cec5SDimitry Andric   void consumeConstructionContext(const ConstructionContextLayer *Layer,
7280b57cec5SDimitry Andric                                   Expr *E);
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   // Scan \p Child statement to find constructors in it, while keeping in mind
7310b57cec5SDimitry Andric   // that its parent statement is providing a partial construction context
7320b57cec5SDimitry Andric   // described by \p Layer. If a constructor is found, it would be assigned
7330b57cec5SDimitry Andric   // the context based on the layer. If an additional construction context layer
7340b57cec5SDimitry Andric   // is found, the function recurses into that.
7350b57cec5SDimitry Andric   void findConstructionContexts(const ConstructionContextLayer *Layer,
7360b57cec5SDimitry Andric                                 Stmt *Child);
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   // Scan all arguments of a call expression for a construction context.
7390b57cec5SDimitry Andric   // These sorts of call expressions don't have a common superclass,
7400b57cec5SDimitry Andric   // hence strict duck-typing.
7410b57cec5SDimitry Andric   template <typename CallLikeExpr,
7425ffd83dbSDimitry Andric             typename = std::enable_if_t<
743bdd1243dSDimitry Andric                 std::is_base_of_v<CallExpr, CallLikeExpr> ||
744bdd1243dSDimitry Andric                 std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||
745bdd1243dSDimitry Andric                 std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>
7460b57cec5SDimitry Andric   void findConstructionContextsForArguments(CallLikeExpr *E) {
7470b57cec5SDimitry Andric     for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
7480b57cec5SDimitry Andric       Expr *Arg = E->getArg(i);
7490b57cec5SDimitry Andric       if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue())
7500b57cec5SDimitry Andric         findConstructionContexts(
7510b57cec5SDimitry Andric             ConstructionContextLayer::create(cfg->getBumpVectorContext(),
7520b57cec5SDimitry Andric                                              ConstructionContextItem(E, i)),
7530b57cec5SDimitry Andric             Arg);
7540b57cec5SDimitry Andric     }
7550b57cec5SDimitry Andric   }
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   // Unset the construction context after consuming it. This is done immediately
7580b57cec5SDimitry Andric   // after adding the CFGConstructor or CFGCXXRecordTypedCall element, so
7590b57cec5SDimitry Andric   // there's no need to do this manually in every Visit... function.
7600b57cec5SDimitry Andric   void cleanupConstructionContext(Expr *E);
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   void autoCreateBlock() { if (!Block) Block = createBlock(); }
7630b57cec5SDimitry Andric   CFGBlock *createBlock(bool add_successor = true);
7640b57cec5SDimitry Andric   CFGBlock *createNoReturnBlock();
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   CFGBlock *addStmt(Stmt *S) {
7670b57cec5SDimitry Andric     return Visit(S, AddStmtChoice::AlwaysAdd);
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   CFGBlock *addInitializer(CXXCtorInitializer *I);
7710b57cec5SDimitry Andric   void addLoopExit(const Stmt *LoopStmt);
7720b57cec5SDimitry Andric   void addAutomaticObjHandling(LocalScope::const_iterator B,
7730b57cec5SDimitry Andric                                LocalScope::const_iterator E, Stmt *S);
77406c3fb27SDimitry Andric   void addAutomaticObjDestruction(LocalScope::const_iterator B,
7750b57cec5SDimitry Andric                                   LocalScope::const_iterator E, Stmt *S);
77606c3fb27SDimitry Andric   void addScopeExitHandling(LocalScope::const_iterator B,
77706c3fb27SDimitry Andric                             LocalScope::const_iterator E, Stmt *S);
77806c3fb27SDimitry Andric   void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
77906c3fb27SDimitry Andric   void addScopeChangesHandling(LocalScope::const_iterator SrcPos,
78006c3fb27SDimitry Andric                                LocalScope::const_iterator DstPos,
78106c3fb27SDimitry Andric                                Stmt *S);
78206c3fb27SDimitry Andric   CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,
78306c3fb27SDimitry Andric                                             CFGBlock *SrcBlk,
78406c3fb27SDimitry Andric                                             LocalScope::const_iterator DstPost,
78506c3fb27SDimitry Andric                                             CFGBlock *DstBlk);
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric   // Local scopes creation.
7880b57cec5SDimitry Andric   LocalScope* createOrReuseLocalScope(LocalScope* Scope);
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric   void addLocalScopeForStmt(Stmt *S);
7910b57cec5SDimitry Andric   LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
7920b57cec5SDimitry Andric                                        LocalScope* Scope = nullptr);
7930b57cec5SDimitry Andric   LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   void addLocalScopeAndDtors(Stmt *S);
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {
7980b57cec5SDimitry Andric     if (!BuildOpts.AddRichCXXConstructors)
7990b57cec5SDimitry Andric       return nullptr;
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric     const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);
8020b57cec5SDimitry Andric     if (!Layer)
8030b57cec5SDimitry Andric       return nullptr;
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric     cleanupConstructionContext(E);
8060b57cec5SDimitry Andric     return ConstructionContext::createFromLayers(cfg->getBumpVectorContext(),
8070b57cec5SDimitry Andric                                                  Layer);
8080b57cec5SDimitry Andric   }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   // Interface to CFGBlock - adding CFGElements.
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric   void appendStmt(CFGBlock *B, const Stmt *S) {
8130b57cec5SDimitry Andric     if (alwaysAdd(S) && cachedEntry)
8140b57cec5SDimitry Andric       cachedEntry->second = B;
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric     // All block-level expressions should have already been IgnoreParens()ed.
8170b57cec5SDimitry Andric     assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);
8180b57cec5SDimitry Andric     B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
8190b57cec5SDimitry Andric   }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
8220b57cec5SDimitry Andric     if (const ConstructionContext *CC =
8230b57cec5SDimitry Andric             retrieveAndCleanupConstructionContext(CE)) {
8240b57cec5SDimitry Andric       B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
8250b57cec5SDimitry Andric       return;
8260b57cec5SDimitry Andric     }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric     // No valid construction context found. Fall back to statement.
8290b57cec5SDimitry Andric     B->appendStmt(CE, cfg->getBumpVectorContext());
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   void appendCall(CFGBlock *B, CallExpr *CE) {
8330b57cec5SDimitry Andric     if (alwaysAdd(CE) && cachedEntry)
8340b57cec5SDimitry Andric       cachedEntry->second = B;
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric     if (const ConstructionContext *CC =
8370b57cec5SDimitry Andric             retrieveAndCleanupConstructionContext(CE)) {
8380b57cec5SDimitry Andric       B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext());
8390b57cec5SDimitry Andric       return;
8400b57cec5SDimitry Andric     }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     // No valid construction context found. Fall back to statement.
8430b57cec5SDimitry Andric     B->appendStmt(CE, cfg->getBumpVectorContext());
8440b57cec5SDimitry Andric   }
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {
8470b57cec5SDimitry Andric     B->appendInitializer(I, cfg->getBumpVectorContext());
8480b57cec5SDimitry Andric   }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric   void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
8510b57cec5SDimitry Andric     B->appendNewAllocator(NE, cfg->getBumpVectorContext());
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric   void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
8550b57cec5SDimitry Andric     B->appendBaseDtor(BS, cfg->getBumpVectorContext());
8560b57cec5SDimitry Andric   }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric   void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
8590b57cec5SDimitry Andric     B->appendMemberDtor(FD, cfg->getBumpVectorContext());
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {
8630b57cec5SDimitry Andric     if (alwaysAdd(ME) && cachedEntry)
8640b57cec5SDimitry Andric       cachedEntry->second = B;
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric     if (const ConstructionContext *CC =
8670b57cec5SDimitry Andric             retrieveAndCleanupConstructionContext(ME)) {
8680b57cec5SDimitry Andric       B->appendCXXRecordTypedCall(ME, CC, cfg->getBumpVectorContext());
8690b57cec5SDimitry Andric       return;
8700b57cec5SDimitry Andric     }
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     B->appendStmt(const_cast<ObjCMessageExpr *>(ME),
8730b57cec5SDimitry Andric                   cfg->getBumpVectorContext());
8740b57cec5SDimitry Andric   }
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric   void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
8770b57cec5SDimitry Andric     B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
8780b57cec5SDimitry Andric   }
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric   void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
8810b57cec5SDimitry Andric     B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
8820b57cec5SDimitry Andric   }
8830b57cec5SDimitry Andric 
8845f757f3fSDimitry Andric   void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
8855f757f3fSDimitry Andric     B->appendCleanupFunction(VD, cfg->getBumpVectorContext());
8865f757f3fSDimitry Andric   }
8875f757f3fSDimitry Andric 
8880b57cec5SDimitry Andric   void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
8890b57cec5SDimitry Andric     B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {
8930b57cec5SDimitry Andric     B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());
8940b57cec5SDimitry Andric   }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {
8970b57cec5SDimitry Andric     B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());
8980b57cec5SDimitry Andric   }
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {
9010b57cec5SDimitry Andric     B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),
9020b57cec5SDimitry Andric                     cfg->getBumpVectorContext());
9030b57cec5SDimitry Andric   }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric   /// Add a reachable successor to a block, with the alternate variant that is
9060b57cec5SDimitry Andric   /// unreachable.
9070b57cec5SDimitry Andric   void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {
9080b57cec5SDimitry Andric     B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),
9090b57cec5SDimitry Andric                     cfg->getBumpVectorContext());
9100b57cec5SDimitry Andric   }
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
9130b57cec5SDimitry Andric     if (BuildOpts.AddScopes)
9140b57cec5SDimitry Andric       B->appendScopeBegin(VD, S, cfg->getBumpVectorContext());
9150b57cec5SDimitry Andric   }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric   void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {
9180b57cec5SDimitry Andric     if (BuildOpts.AddScopes)
9190b57cec5SDimitry Andric       B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());
9200b57cec5SDimitry Andric   }
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric   /// Find a relational comparison with an expression evaluating to a
9230b57cec5SDimitry Andric   /// boolean and a constant other than 0 and 1.
9240b57cec5SDimitry Andric   /// e.g. if ((x < y) == 10)
9250b57cec5SDimitry Andric   TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {
9260b57cec5SDimitry Andric     const Expr *LHSExpr = B->getLHS()->IgnoreParens();
9270b57cec5SDimitry Andric     const Expr *RHSExpr = B->getRHS()->IgnoreParens();
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric     const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);
9300b57cec5SDimitry Andric     const Expr *BoolExpr = RHSExpr;
9310b57cec5SDimitry Andric     bool IntFirst = true;
9320b57cec5SDimitry Andric     if (!IntLiteral) {
9330b57cec5SDimitry Andric       IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);
9340b57cec5SDimitry Andric       BoolExpr = LHSExpr;
9350b57cec5SDimitry Andric       IntFirst = false;
9360b57cec5SDimitry Andric     }
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric     if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue())
9390b57cec5SDimitry Andric       return TryResult();
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric     llvm::APInt IntValue = IntLiteral->getValue();
9420b57cec5SDimitry Andric     if ((IntValue == 1) || (IntValue == 0))
9430b57cec5SDimitry Andric       return TryResult();
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric     bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() ||
9460b57cec5SDimitry Andric                      !IntValue.isNegative();
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric     BinaryOperatorKind Bok = B->getOpcode();
9490b57cec5SDimitry Andric     if (Bok == BO_GT || Bok == BO_GE) {
9500b57cec5SDimitry Andric       // Always true for 10 > bool and bool > -1
9510b57cec5SDimitry Andric       // Always false for -1 > bool and bool > 10
9520b57cec5SDimitry Andric       return TryResult(IntFirst == IntLarger);
9530b57cec5SDimitry Andric     } else {
9540b57cec5SDimitry Andric       // Always true for -1 < bool and bool < 10
9550b57cec5SDimitry Andric       // Always false for 10 < bool and bool < -1
9560b57cec5SDimitry Andric       return TryResult(IntFirst != IntLarger);
9570b57cec5SDimitry Andric     }
9580b57cec5SDimitry Andric   }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   /// Find an incorrect equality comparison. Either with an expression
9610b57cec5SDimitry Andric   /// evaluating to a boolean and a constant other than 0 and 1.
9620b57cec5SDimitry Andric   /// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to
9630b57cec5SDimitry Andric   /// true/false e.q. (x & 8) == 4.
9640b57cec5SDimitry Andric   TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {
9650b57cec5SDimitry Andric     const Expr *LHSExpr = B->getLHS()->IgnoreParens();
9660b57cec5SDimitry Andric     const Expr *RHSExpr = B->getRHS()->IgnoreParens();
9670b57cec5SDimitry Andric 
968bdd1243dSDimitry Andric     std::optional<llvm::APInt> IntLiteral1 =
969bdd1243dSDimitry Andric         getIntegerLiteralSubexpressionValue(LHSExpr);
9700b57cec5SDimitry Andric     const Expr *BoolExpr = RHSExpr;
9710b57cec5SDimitry Andric 
972bdd1243dSDimitry Andric     if (!IntLiteral1) {
973bdd1243dSDimitry Andric       IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);
9740b57cec5SDimitry Andric       BoolExpr = LHSExpr;
9750b57cec5SDimitry Andric     }
9760b57cec5SDimitry Andric 
977bdd1243dSDimitry Andric     if (!IntLiteral1)
9780b57cec5SDimitry Andric       return TryResult();
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric     const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);
9810b57cec5SDimitry Andric     if (BitOp && (BitOp->getOpcode() == BO_And ||
9820b57cec5SDimitry Andric                   BitOp->getOpcode() == BO_Or)) {
9830b57cec5SDimitry Andric       const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens();
9840b57cec5SDimitry Andric       const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens();
9850b57cec5SDimitry Andric 
986bdd1243dSDimitry Andric       std::optional<llvm::APInt> IntLiteral2 =
987bdd1243dSDimitry Andric           getIntegerLiteralSubexpressionValue(LHSExpr2);
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric       if (!IntLiteral2)
990bdd1243dSDimitry Andric         IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric       if (!IntLiteral2)
9930b57cec5SDimitry Andric         return TryResult();
9940b57cec5SDimitry Andric 
995bdd1243dSDimitry Andric       if ((BitOp->getOpcode() == BO_And &&
996bdd1243dSDimitry Andric            (*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||
997bdd1243dSDimitry Andric           (BitOp->getOpcode() == BO_Or &&
998bdd1243dSDimitry Andric            (*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {
9990b57cec5SDimitry Andric         if (BuildOpts.Observer)
10000b57cec5SDimitry Andric           BuildOpts.Observer->compareBitwiseEquality(B,
10010b57cec5SDimitry Andric                                                      B->getOpcode() != BO_EQ);
1002bdd1243dSDimitry Andric         return TryResult(B->getOpcode() != BO_EQ);
10030b57cec5SDimitry Andric       }
10040b57cec5SDimitry Andric     } else if (BoolExpr->isKnownToHaveBooleanValue()) {
1005bdd1243dSDimitry Andric       if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {
10060b57cec5SDimitry Andric         return TryResult();
10070b57cec5SDimitry Andric       }
10080b57cec5SDimitry Andric       return TryResult(B->getOpcode() != BO_EQ);
10090b57cec5SDimitry Andric     }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric     return TryResult();
10120b57cec5SDimitry Andric   }
10130b57cec5SDimitry Andric 
1014bdd1243dSDimitry Andric   // Helper function to get an APInt from an expression. Supports expressions
1015bdd1243dSDimitry Andric   // which are an IntegerLiteral or a UnaryOperator and returns the value with
1016bdd1243dSDimitry Andric   // all operations performed on it.
1017bdd1243dSDimitry Andric   // FIXME: it would be good to unify this function with
1018bdd1243dSDimitry Andric   // IsIntegerLiteralConstantExpr at some point given the similarity between the
1019bdd1243dSDimitry Andric   // functions.
1020bdd1243dSDimitry Andric   std::optional<llvm::APInt>
1021bdd1243dSDimitry Andric   getIntegerLiteralSubexpressionValue(const Expr *E) {
1022bdd1243dSDimitry Andric 
1023bdd1243dSDimitry Andric     // If unary.
1024bdd1243dSDimitry Andric     if (const auto *UnOp = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
1025bdd1243dSDimitry Andric       // Get the sub expression of the unary expression and get the Integer
1026bdd1243dSDimitry Andric       // Literal.
1027bdd1243dSDimitry Andric       const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();
1028bdd1243dSDimitry Andric 
1029bdd1243dSDimitry Andric       if (const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {
1030bdd1243dSDimitry Andric 
1031bdd1243dSDimitry Andric         llvm::APInt Value = IntLiteral->getValue();
1032bdd1243dSDimitry Andric 
1033bdd1243dSDimitry Andric         // Perform the operation manually.
1034bdd1243dSDimitry Andric         switch (UnOp->getOpcode()) {
1035bdd1243dSDimitry Andric         case UO_Plus:
1036bdd1243dSDimitry Andric           return Value;
1037bdd1243dSDimitry Andric         case UO_Minus:
1038bdd1243dSDimitry Andric           return -Value;
1039bdd1243dSDimitry Andric         case UO_Not:
1040bdd1243dSDimitry Andric           return ~Value;
1041bdd1243dSDimitry Andric         case UO_LNot:
1042bdd1243dSDimitry Andric           return llvm::APInt(Context->getTypeSize(Context->IntTy), !Value);
1043bdd1243dSDimitry Andric         default:
1044bdd1243dSDimitry Andric           assert(false && "Unexpected unary operator!");
1045bdd1243dSDimitry Andric           return std::nullopt;
1046bdd1243dSDimitry Andric         }
1047bdd1243dSDimitry Andric       }
1048bdd1243dSDimitry Andric     } else if (const auto *IntLiteral =
1049bdd1243dSDimitry Andric                    dyn_cast<IntegerLiteral>(E->IgnoreParens()))
1050bdd1243dSDimitry Andric       return IntLiteral->getValue();
1051bdd1243dSDimitry Andric 
1052bdd1243dSDimitry Andric     return std::nullopt;
1053bdd1243dSDimitry Andric   }
1054bdd1243dSDimitry Andric 
10550b57cec5SDimitry Andric   TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,
10560b57cec5SDimitry Andric                                           const llvm::APSInt &Value1,
10570b57cec5SDimitry Andric                                           const llvm::APSInt &Value2) {
10580b57cec5SDimitry Andric     assert(Value1.isSigned() == Value2.isSigned());
10590b57cec5SDimitry Andric     switch (Relation) {
10600b57cec5SDimitry Andric       default:
10610b57cec5SDimitry Andric         return TryResult();
10620b57cec5SDimitry Andric       case BO_EQ:
10630b57cec5SDimitry Andric         return TryResult(Value1 == Value2);
10640b57cec5SDimitry Andric       case BO_NE:
10650b57cec5SDimitry Andric         return TryResult(Value1 != Value2);
10660b57cec5SDimitry Andric       case BO_LT:
10670b57cec5SDimitry Andric         return TryResult(Value1 <  Value2);
10680b57cec5SDimitry Andric       case BO_LE:
10690b57cec5SDimitry Andric         return TryResult(Value1 <= Value2);
10700b57cec5SDimitry Andric       case BO_GT:
10710b57cec5SDimitry Andric         return TryResult(Value1 >  Value2);
10720b57cec5SDimitry Andric       case BO_GE:
10730b57cec5SDimitry Andric         return TryResult(Value1 >= Value2);
10740b57cec5SDimitry Andric     }
10750b57cec5SDimitry Andric   }
10760b57cec5SDimitry Andric 
10775f757f3fSDimitry Andric   /// There are two checks handled by this function:
10785f757f3fSDimitry Andric   /// 1. Find a law-of-excluded-middle or law-of-noncontradiction expression
10795f757f3fSDimitry Andric   /// e.g. if (x || !x), if (x && !x)
10805f757f3fSDimitry Andric   /// 2. Find a pair of comparison expressions with or without parentheses
10810b57cec5SDimitry Andric   /// with a shared variable and constants and a logical operator between them
10820b57cec5SDimitry Andric   /// that always evaluates to either true or false.
10830b57cec5SDimitry Andric   /// e.g. if (x != 3 || x != 4)
10840b57cec5SDimitry Andric   TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {
10850b57cec5SDimitry Andric     assert(B->isLogicalOp());
10865f757f3fSDimitry Andric     const Expr *LHSExpr = B->getLHS()->IgnoreParens();
10875f757f3fSDimitry Andric     const Expr *RHSExpr = B->getRHS()->IgnoreParens();
10885f757f3fSDimitry Andric 
10895f757f3fSDimitry Andric     auto CheckLogicalOpWithNegatedVariable = [this, B](const Expr *E1,
10905f757f3fSDimitry Andric                                                        const Expr *E2) {
10915f757f3fSDimitry Andric       if (const auto *Negate = dyn_cast<UnaryOperator>(E1)) {
10925f757f3fSDimitry Andric         if (Negate->getOpcode() == UO_LNot &&
10935f757f3fSDimitry Andric             Expr::isSameComparisonOperand(Negate->getSubExpr(), E2)) {
10945f757f3fSDimitry Andric           bool AlwaysTrue = B->getOpcode() == BO_LOr;
10955f757f3fSDimitry Andric           if (BuildOpts.Observer)
10965f757f3fSDimitry Andric             BuildOpts.Observer->logicAlwaysTrue(B, AlwaysTrue);
10975f757f3fSDimitry Andric           return TryResult(AlwaysTrue);
10985f757f3fSDimitry Andric         }
10995f757f3fSDimitry Andric       }
11005f757f3fSDimitry Andric       return TryResult();
11015f757f3fSDimitry Andric     };
11025f757f3fSDimitry Andric 
11035f757f3fSDimitry Andric     TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);
11045f757f3fSDimitry Andric     if (Result.isKnown())
11055f757f3fSDimitry Andric         return Result;
11065f757f3fSDimitry Andric     Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);
11075f757f3fSDimitry Andric     if (Result.isKnown())
11085f757f3fSDimitry Andric         return Result;
11095f757f3fSDimitry Andric 
11105f757f3fSDimitry Andric     const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);
11115f757f3fSDimitry Andric     const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);
11120b57cec5SDimitry Andric     if (!LHS || !RHS)
11130b57cec5SDimitry Andric       return {};
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric     if (!LHS->isComparisonOp() || !RHS->isComparisonOp())
11160b57cec5SDimitry Andric       return {};
11170b57cec5SDimitry Andric 
1118a7dea167SDimitry Andric     const Expr *DeclExpr1;
1119a7dea167SDimitry Andric     const Expr *NumExpr1;
11200b57cec5SDimitry Andric     BinaryOperatorKind BO1;
1121a7dea167SDimitry Andric     std::tie(DeclExpr1, BO1, NumExpr1) = tryNormalizeBinaryOperator(LHS);
11220b57cec5SDimitry Andric 
1123a7dea167SDimitry Andric     if (!DeclExpr1 || !NumExpr1)
11240b57cec5SDimitry Andric       return {};
11250b57cec5SDimitry Andric 
1126a7dea167SDimitry Andric     const Expr *DeclExpr2;
1127a7dea167SDimitry Andric     const Expr *NumExpr2;
11280b57cec5SDimitry Andric     BinaryOperatorKind BO2;
1129a7dea167SDimitry Andric     std::tie(DeclExpr2, BO2, NumExpr2) = tryNormalizeBinaryOperator(RHS);
11300b57cec5SDimitry Andric 
1131a7dea167SDimitry Andric     if (!DeclExpr2 || !NumExpr2)
11320b57cec5SDimitry Andric       return {};
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric     // Check that it is the same variable on both sides.
1135a7dea167SDimitry Andric     if (!Expr::isSameComparisonOperand(DeclExpr1, DeclExpr2))
11360b57cec5SDimitry Andric       return {};
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric     // Make sure the user's intent is clear (e.g. they're comparing against two
11390b57cec5SDimitry Andric     // int literals, or two things from the same enum)
1140a7dea167SDimitry Andric     if (!areExprTypesCompatible(NumExpr1, NumExpr2))
11410b57cec5SDimitry Andric       return {};
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric     Expr::EvalResult L1Result, L2Result;
1144a7dea167SDimitry Andric     if (!NumExpr1->EvaluateAsInt(L1Result, *Context) ||
1145a7dea167SDimitry Andric         !NumExpr2->EvaluateAsInt(L2Result, *Context))
11460b57cec5SDimitry Andric       return {};
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric     llvm::APSInt L1 = L1Result.Val.getInt();
11490b57cec5SDimitry Andric     llvm::APSInt L2 = L2Result.Val.getInt();
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric     // Can't compare signed with unsigned or with different bit width.
11520b57cec5SDimitry Andric     if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
11530b57cec5SDimitry Andric       return {};
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric     // Values that will be used to determine if result of logical
11560b57cec5SDimitry Andric     // operator is always true/false
11570b57cec5SDimitry Andric     const llvm::APSInt Values[] = {
11580b57cec5SDimitry Andric       // Value less than both Value1 and Value2
11590b57cec5SDimitry Andric       llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),
11600b57cec5SDimitry Andric       // L1
11610b57cec5SDimitry Andric       L1,
11620b57cec5SDimitry Andric       // Value between Value1 and Value2
11630b57cec5SDimitry Andric       ((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),
11640b57cec5SDimitry Andric                               L1.isUnsigned()),
11650b57cec5SDimitry Andric       // L2
11660b57cec5SDimitry Andric       L2,
11670b57cec5SDimitry Andric       // Value greater than both Value1 and Value2
11680b57cec5SDimitry Andric       llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),
11690b57cec5SDimitry Andric     };
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric     // Check whether expression is always true/false by evaluating the following
11720b57cec5SDimitry Andric     // * variable x is less than the smallest literal.
11730b57cec5SDimitry Andric     // * variable x is equal to the smallest literal.
11740b57cec5SDimitry Andric     // * Variable x is between smallest and largest literal.
11750b57cec5SDimitry Andric     // * Variable x is equal to the largest literal.
11760b57cec5SDimitry Andric     // * Variable x is greater than largest literal.
11770b57cec5SDimitry Andric     bool AlwaysTrue = true, AlwaysFalse = true;
1178a7dea167SDimitry Andric     // Track value of both subexpressions.  If either side is always
1179a7dea167SDimitry Andric     // true/false, another warning should have already been emitted.
1180a7dea167SDimitry Andric     bool LHSAlwaysTrue = true, LHSAlwaysFalse = true;
1181a7dea167SDimitry Andric     bool RHSAlwaysTrue = true, RHSAlwaysFalse = true;
11820b57cec5SDimitry Andric     for (const llvm::APSInt &Value : Values) {
11830b57cec5SDimitry Andric       TryResult Res1, Res2;
11840b57cec5SDimitry Andric       Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);
11850b57cec5SDimitry Andric       Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);
11860b57cec5SDimitry Andric 
11870b57cec5SDimitry Andric       if (!Res1.isKnown() || !Res2.isKnown())
11880b57cec5SDimitry Andric         return {};
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric       if (B->getOpcode() == BO_LAnd) {
11910b57cec5SDimitry Andric         AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());
11920b57cec5SDimitry Andric         AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());
11930b57cec5SDimitry Andric       } else {
11940b57cec5SDimitry Andric         AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());
11950b57cec5SDimitry Andric         AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());
11960b57cec5SDimitry Andric       }
1197a7dea167SDimitry Andric 
1198a7dea167SDimitry Andric       LHSAlwaysTrue &= Res1.isTrue();
1199a7dea167SDimitry Andric       LHSAlwaysFalse &= Res1.isFalse();
1200a7dea167SDimitry Andric       RHSAlwaysTrue &= Res2.isTrue();
1201a7dea167SDimitry Andric       RHSAlwaysFalse &= Res2.isFalse();
12020b57cec5SDimitry Andric     }
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric     if (AlwaysTrue || AlwaysFalse) {
1205a7dea167SDimitry Andric       if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&
1206a7dea167SDimitry Andric           !RHSAlwaysFalse && BuildOpts.Observer)
12070b57cec5SDimitry Andric         BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);
12080b57cec5SDimitry Andric       return TryResult(AlwaysTrue);
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric     return {};
12110b57cec5SDimitry Andric   }
12120b57cec5SDimitry Andric 
1213a7dea167SDimitry Andric   /// A bitwise-or with a non-zero constant always evaluates to true.
1214a7dea167SDimitry Andric   TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {
1215a7dea167SDimitry Andric     const Expr *LHSConstant =
1216a7dea167SDimitry Andric         tryTransformToIntOrEnumConstant(B->getLHS()->IgnoreParenImpCasts());
1217a7dea167SDimitry Andric     const Expr *RHSConstant =
1218a7dea167SDimitry Andric         tryTransformToIntOrEnumConstant(B->getRHS()->IgnoreParenImpCasts());
1219a7dea167SDimitry Andric 
1220a7dea167SDimitry Andric     if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))
1221a7dea167SDimitry Andric       return {};
1222a7dea167SDimitry Andric 
1223a7dea167SDimitry Andric     const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;
1224a7dea167SDimitry Andric 
1225a7dea167SDimitry Andric     Expr::EvalResult Result;
1226a7dea167SDimitry Andric     if (!Constant->EvaluateAsInt(Result, *Context))
1227a7dea167SDimitry Andric       return {};
1228a7dea167SDimitry Andric 
1229a7dea167SDimitry Andric     if (Result.Val.getInt() == 0)
1230a7dea167SDimitry Andric       return {};
1231a7dea167SDimitry Andric 
1232a7dea167SDimitry Andric     if (BuildOpts.Observer)
1233a7dea167SDimitry Andric       BuildOpts.Observer->compareBitwiseOr(B);
1234a7dea167SDimitry Andric 
1235a7dea167SDimitry Andric     return TryResult(true);
1236a7dea167SDimitry Andric   }
1237a7dea167SDimitry Andric 
12380b57cec5SDimitry Andric   /// Try and evaluate an expression to an integer constant.
12390b57cec5SDimitry Andric   bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {
12400b57cec5SDimitry Andric     if (!BuildOpts.PruneTriviallyFalseEdges)
12410b57cec5SDimitry Andric       return false;
12420b57cec5SDimitry Andric     return !S->isTypeDependent() &&
12430b57cec5SDimitry Andric            !S->isValueDependent() &&
12440b57cec5SDimitry Andric            S->EvaluateAsRValue(outResult, *Context);
12450b57cec5SDimitry Andric   }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
12480b57cec5SDimitry Andric   /// if we can evaluate to a known value, otherwise return -1.
12490b57cec5SDimitry Andric   TryResult tryEvaluateBool(Expr *S) {
12500b57cec5SDimitry Andric     if (!BuildOpts.PruneTriviallyFalseEdges ||
12510b57cec5SDimitry Andric         S->isTypeDependent() || S->isValueDependent())
12520b57cec5SDimitry Andric       return {};
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric     if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
1255a7dea167SDimitry Andric       if (Bop->isLogicalOp() || Bop->isEqualityOp()) {
12560b57cec5SDimitry Andric         // Check the cache first.
12570b57cec5SDimitry Andric         CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);
12580b57cec5SDimitry Andric         if (I != CachedBoolEvals.end())
12590b57cec5SDimitry Andric           return I->second; // already in map;
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric         // Retrieve result at first, or the map might be updated.
12620b57cec5SDimitry Andric         TryResult Result = evaluateAsBooleanConditionNoCache(S);
12630b57cec5SDimitry Andric         CachedBoolEvals[S] = Result; // update or insert
12640b57cec5SDimitry Andric         return Result;
12650b57cec5SDimitry Andric       }
12660b57cec5SDimitry Andric       else {
12670b57cec5SDimitry Andric         switch (Bop->getOpcode()) {
12680b57cec5SDimitry Andric           default: break;
12690b57cec5SDimitry Andric           // For 'x & 0' and 'x * 0', we can determine that
12700b57cec5SDimitry Andric           // the value is always false.
12710b57cec5SDimitry Andric           case BO_Mul:
12720b57cec5SDimitry Andric           case BO_And: {
12730b57cec5SDimitry Andric             // If either operand is zero, we know the value
12740b57cec5SDimitry Andric             // must be false.
12750b57cec5SDimitry Andric             Expr::EvalResult LHSResult;
12760b57cec5SDimitry Andric             if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
12770b57cec5SDimitry Andric               llvm::APSInt IntVal = LHSResult.Val.getInt();
12780b57cec5SDimitry Andric               if (!IntVal.getBoolValue()) {
12790b57cec5SDimitry Andric                 return TryResult(false);
12800b57cec5SDimitry Andric               }
12810b57cec5SDimitry Andric             }
12820b57cec5SDimitry Andric             Expr::EvalResult RHSResult;
12830b57cec5SDimitry Andric             if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
12840b57cec5SDimitry Andric               llvm::APSInt IntVal = RHSResult.Val.getInt();
12850b57cec5SDimitry Andric               if (!IntVal.getBoolValue()) {
12860b57cec5SDimitry Andric                 return TryResult(false);
12870b57cec5SDimitry Andric               }
12880b57cec5SDimitry Andric             }
12890b57cec5SDimitry Andric           }
12900b57cec5SDimitry Andric           break;
12910b57cec5SDimitry Andric         }
12920b57cec5SDimitry Andric       }
12930b57cec5SDimitry Andric     }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric     return evaluateAsBooleanConditionNoCache(S);
12960b57cec5SDimitry Andric   }
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric   /// Evaluate as boolean \param E without using the cache.
12990b57cec5SDimitry Andric   TryResult evaluateAsBooleanConditionNoCache(Expr *E) {
13000b57cec5SDimitry Andric     if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
13010b57cec5SDimitry Andric       if (Bop->isLogicalOp()) {
13020b57cec5SDimitry Andric         TryResult LHS = tryEvaluateBool(Bop->getLHS());
13030b57cec5SDimitry Andric         if (LHS.isKnown()) {
13040b57cec5SDimitry Andric           // We were able to evaluate the LHS, see if we can get away with not
13050b57cec5SDimitry Andric           // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
13060b57cec5SDimitry Andric           if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))
13070b57cec5SDimitry Andric             return LHS.isTrue();
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric           TryResult RHS = tryEvaluateBool(Bop->getRHS());
13100b57cec5SDimitry Andric           if (RHS.isKnown()) {
13110b57cec5SDimitry Andric             if (Bop->getOpcode() == BO_LOr)
13120b57cec5SDimitry Andric               return LHS.isTrue() || RHS.isTrue();
13130b57cec5SDimitry Andric             else
13140b57cec5SDimitry Andric               return LHS.isTrue() && RHS.isTrue();
13150b57cec5SDimitry Andric           }
13160b57cec5SDimitry Andric         } else {
13170b57cec5SDimitry Andric           TryResult RHS = tryEvaluateBool(Bop->getRHS());
13180b57cec5SDimitry Andric           if (RHS.isKnown()) {
13190b57cec5SDimitry Andric             // We can't evaluate the LHS; however, sometimes the result
13200b57cec5SDimitry Andric             // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
13210b57cec5SDimitry Andric             if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))
13220b57cec5SDimitry Andric               return RHS.isTrue();
13230b57cec5SDimitry Andric           } else {
13240b57cec5SDimitry Andric             TryResult BopRes = checkIncorrectLogicOperator(Bop);
13250b57cec5SDimitry Andric             if (BopRes.isKnown())
13260b57cec5SDimitry Andric               return BopRes.isTrue();
13270b57cec5SDimitry Andric           }
13280b57cec5SDimitry Andric         }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric         return {};
13310b57cec5SDimitry Andric       } else if (Bop->isEqualityOp()) {
13320b57cec5SDimitry Andric           TryResult BopRes = checkIncorrectEqualityOperator(Bop);
13330b57cec5SDimitry Andric           if (BopRes.isKnown())
13340b57cec5SDimitry Andric             return BopRes.isTrue();
13350b57cec5SDimitry Andric       } else if (Bop->isRelationalOp()) {
13360b57cec5SDimitry Andric         TryResult BopRes = checkIncorrectRelationalOperator(Bop);
13370b57cec5SDimitry Andric         if (BopRes.isKnown())
13380b57cec5SDimitry Andric           return BopRes.isTrue();
1339a7dea167SDimitry Andric       } else if (Bop->getOpcode() == BO_Or) {
1340a7dea167SDimitry Andric         TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);
1341a7dea167SDimitry Andric         if (BopRes.isKnown())
1342a7dea167SDimitry Andric           return BopRes.isTrue();
13430b57cec5SDimitry Andric       }
13440b57cec5SDimitry Andric     }
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric     bool Result;
13470b57cec5SDimitry Andric     if (E->EvaluateAsBooleanCondition(Result, *Context))
13480b57cec5SDimitry Andric       return Result;
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric     return {};
13510b57cec5SDimitry Andric   }
13520b57cec5SDimitry Andric 
13535f757f3fSDimitry Andric   bool hasTrivialDestructor(const VarDecl *VD) const;
13545f757f3fSDimitry Andric   bool needsAutomaticDestruction(const VarDecl *VD) const;
13550b57cec5SDimitry Andric };
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric } // namespace
13580b57cec5SDimitry Andric 
1359bdd1243dSDimitry Andric Expr *
1360bdd1243dSDimitry Andric clang::extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE) {
1361bdd1243dSDimitry Andric   if (!AILE)
1362bdd1243dSDimitry Andric     return nullptr;
1363bdd1243dSDimitry Andric 
1364bdd1243dSDimitry Andric   Expr *AILEInit = AILE->getSubExpr();
1365bdd1243dSDimitry Andric   while (const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))
1366bdd1243dSDimitry Andric     AILEInit = E->getSubExpr();
1367bdd1243dSDimitry Andric 
1368bdd1243dSDimitry Andric   return AILEInit;
1369bdd1243dSDimitry Andric }
1370bdd1243dSDimitry Andric 
13710b57cec5SDimitry Andric inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
13720b57cec5SDimitry Andric                                      const Stmt *stmt) const {
13730b57cec5SDimitry Andric   return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
13770b57cec5SDimitry Andric   bool shouldAdd = BuildOpts.alwaysAdd(stmt);
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric   if (!BuildOpts.forcedBlkExprs)
13800b57cec5SDimitry Andric     return shouldAdd;
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   if (lastLookup == stmt) {
13830b57cec5SDimitry Andric     if (cachedEntry) {
13840b57cec5SDimitry Andric       assert(cachedEntry->first == stmt);
13850b57cec5SDimitry Andric       return true;
13860b57cec5SDimitry Andric     }
13870b57cec5SDimitry Andric     return shouldAdd;
13880b57cec5SDimitry Andric   }
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric   lastLookup = stmt;
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric   // Perform the lookup!
13930b57cec5SDimitry Andric   CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric   if (!fb) {
13960b57cec5SDimitry Andric     // No need to update 'cachedEntry', since it will always be null.
13970b57cec5SDimitry Andric     assert(!cachedEntry);
13980b57cec5SDimitry Andric     return shouldAdd;
13990b57cec5SDimitry Andric   }
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric   CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
14020b57cec5SDimitry Andric   if (itr == fb->end()) {
14030b57cec5SDimitry Andric     cachedEntry = nullptr;
14040b57cec5SDimitry Andric     return shouldAdd;
14050b57cec5SDimitry Andric   }
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric   cachedEntry = &*itr;
14080b57cec5SDimitry Andric   return true;
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric // FIXME: Add support for dependent-sized array types in C++?
14120b57cec5SDimitry Andric // Does it even make sense to build a CFG for an uninstantiated template?
14130b57cec5SDimitry Andric static const VariableArrayType *FindVA(const Type *t) {
14140b57cec5SDimitry Andric   while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {
14150b57cec5SDimitry Andric     if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))
14160b57cec5SDimitry Andric       if (vat->getSizeExpr())
14170b57cec5SDimitry Andric         return vat;
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric     t = vt->getElementType().getTypePtr();
14200b57cec5SDimitry Andric   }
14210b57cec5SDimitry Andric 
14220b57cec5SDimitry Andric   return nullptr;
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric void CFGBuilder::consumeConstructionContext(
14260b57cec5SDimitry Andric     const ConstructionContextLayer *Layer, Expr *E) {
14270b57cec5SDimitry Andric   assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||
14280b57cec5SDimitry Andric           isa<ObjCMessageExpr>(E)) && "Expression cannot construct an object!");
14290b57cec5SDimitry Andric   if (const ConstructionContextLayer *PreviouslyStoredLayer =
14300b57cec5SDimitry Andric           ConstructionContextMap.lookup(E)) {
14310b57cec5SDimitry Andric     (void)PreviouslyStoredLayer;
14320b57cec5SDimitry Andric     // We might have visited this child when we were finding construction
14330b57cec5SDimitry Andric     // contexts within its parents.
14340b57cec5SDimitry Andric     assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&
14350b57cec5SDimitry Andric            "Already within a different construction context!");
14360b57cec5SDimitry Andric   } else {
14370b57cec5SDimitry Andric     ConstructionContextMap[E] = Layer;
14380b57cec5SDimitry Andric   }
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric void CFGBuilder::findConstructionContexts(
14420b57cec5SDimitry Andric     const ConstructionContextLayer *Layer, Stmt *Child) {
14430b57cec5SDimitry Andric   if (!BuildOpts.AddRichCXXConstructors)
14440b57cec5SDimitry Andric     return;
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric   if (!Child)
14470b57cec5SDimitry Andric     return;
14480b57cec5SDimitry Andric 
14490b57cec5SDimitry Andric   auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {
14500b57cec5SDimitry Andric     return ConstructionContextLayer::create(cfg->getBumpVectorContext(), Item,
14510b57cec5SDimitry Andric                                             Layer);
14520b57cec5SDimitry Andric   };
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric   switch(Child->getStmtClass()) {
14550b57cec5SDimitry Andric   case Stmt::CXXConstructExprClass:
14560b57cec5SDimitry Andric   case Stmt::CXXTemporaryObjectExprClass: {
14570b57cec5SDimitry Andric     // Support pre-C++17 copy elision AST.
14580b57cec5SDimitry Andric     auto *CE = cast<CXXConstructExpr>(Child);
14590b57cec5SDimitry Andric     if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {
14600b57cec5SDimitry Andric       findConstructionContexts(withExtraLayer(CE), CE->getArg(0));
14610b57cec5SDimitry Andric     }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric     consumeConstructionContext(Layer, CE);
14640b57cec5SDimitry Andric     break;
14650b57cec5SDimitry Andric   }
14660b57cec5SDimitry Andric   // FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr.
14670b57cec5SDimitry Andric   // FIXME: An isa<> would look much better but this whole switch is a
14680b57cec5SDimitry Andric   // workaround for an internal compiler error in MSVC 2015 (see r326021).
14690b57cec5SDimitry Andric   case Stmt::CallExprClass:
14700b57cec5SDimitry Andric   case Stmt::CXXMemberCallExprClass:
14710b57cec5SDimitry Andric   case Stmt::CXXOperatorCallExprClass:
14720b57cec5SDimitry Andric   case Stmt::UserDefinedLiteralClass:
14730b57cec5SDimitry Andric   case Stmt::ObjCMessageExprClass: {
14740b57cec5SDimitry Andric     auto *E = cast<Expr>(Child);
14750b57cec5SDimitry Andric     if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(E))
14760b57cec5SDimitry Andric       consumeConstructionContext(Layer, E);
14770b57cec5SDimitry Andric     break;
14780b57cec5SDimitry Andric   }
14790b57cec5SDimitry Andric   case Stmt::ExprWithCleanupsClass: {
14800b57cec5SDimitry Andric     auto *Cleanups = cast<ExprWithCleanups>(Child);
14810b57cec5SDimitry Andric     findConstructionContexts(Layer, Cleanups->getSubExpr());
14820b57cec5SDimitry Andric     break;
14830b57cec5SDimitry Andric   }
14840b57cec5SDimitry Andric   case Stmt::CXXFunctionalCastExprClass: {
14850b57cec5SDimitry Andric     auto *Cast = cast<CXXFunctionalCastExpr>(Child);
14860b57cec5SDimitry Andric     findConstructionContexts(Layer, Cast->getSubExpr());
14870b57cec5SDimitry Andric     break;
14880b57cec5SDimitry Andric   }
14890b57cec5SDimitry Andric   case Stmt::ImplicitCastExprClass: {
14900b57cec5SDimitry Andric     auto *Cast = cast<ImplicitCastExpr>(Child);
14910b57cec5SDimitry Andric     // Should we support other implicit cast kinds?
14920b57cec5SDimitry Andric     switch (Cast->getCastKind()) {
14930b57cec5SDimitry Andric     case CK_NoOp:
14940b57cec5SDimitry Andric     case CK_ConstructorConversion:
14950b57cec5SDimitry Andric       findConstructionContexts(Layer, Cast->getSubExpr());
14960b57cec5SDimitry Andric       break;
14970b57cec5SDimitry Andric     default:
14980b57cec5SDimitry Andric       break;
14990b57cec5SDimitry Andric     }
15000b57cec5SDimitry Andric     break;
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric   case Stmt::CXXBindTemporaryExprClass: {
15030b57cec5SDimitry Andric     auto *BTE = cast<CXXBindTemporaryExpr>(Child);
15040b57cec5SDimitry Andric     findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());
15050b57cec5SDimitry Andric     break;
15060b57cec5SDimitry Andric   }
15070b57cec5SDimitry Andric   case Stmt::MaterializeTemporaryExprClass: {
15080b57cec5SDimitry Andric     // Normally we don't want to search in MaterializeTemporaryExpr because
15090b57cec5SDimitry Andric     // it indicates the beginning of a temporary object construction context,
15100b57cec5SDimitry Andric     // so it shouldn't be found in the middle. However, if it is the beginning
15110b57cec5SDimitry Andric     // of an elidable copy or move construction context, we need to include it.
15120b57cec5SDimitry Andric     if (Layer->getItem().getKind() ==
15130b57cec5SDimitry Andric         ConstructionContextItem::ElidableConstructorKind) {
15140b57cec5SDimitry Andric       auto *MTE = cast<MaterializeTemporaryExpr>(Child);
1515480093f4SDimitry Andric       findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
15160b57cec5SDimitry Andric     }
15170b57cec5SDimitry Andric     break;
15180b57cec5SDimitry Andric   }
15190b57cec5SDimitry Andric   case Stmt::ConditionalOperatorClass: {
15200b57cec5SDimitry Andric     auto *CO = cast<ConditionalOperator>(Child);
15210b57cec5SDimitry Andric     if (Layer->getItem().getKind() !=
15220b57cec5SDimitry Andric         ConstructionContextItem::MaterializationKind) {
15230b57cec5SDimitry Andric       // If the object returned by the conditional operator is not going to be a
15240b57cec5SDimitry Andric       // temporary object that needs to be immediately materialized, then
15250b57cec5SDimitry Andric       // it must be C++17 with its mandatory copy elision. Do not yet promise
15260b57cec5SDimitry Andric       // to support this case.
15270b57cec5SDimitry Andric       assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||
15280b57cec5SDimitry Andric              Context->getLangOpts().CPlusPlus17);
15290b57cec5SDimitry Andric       break;
15300b57cec5SDimitry Andric     }
15310b57cec5SDimitry Andric     findConstructionContexts(Layer, CO->getLHS());
15320b57cec5SDimitry Andric     findConstructionContexts(Layer, CO->getRHS());
15330b57cec5SDimitry Andric     break;
15340b57cec5SDimitry Andric   }
15350b57cec5SDimitry Andric   case Stmt::InitListExprClass: {
15360b57cec5SDimitry Andric     auto *ILE = cast<InitListExpr>(Child);
15370b57cec5SDimitry Andric     if (ILE->isTransparent()) {
15380b57cec5SDimitry Andric       findConstructionContexts(Layer, ILE->getInit(0));
15390b57cec5SDimitry Andric       break;
15400b57cec5SDimitry Andric     }
15410b57cec5SDimitry Andric     // TODO: Handle other cases. For now, fail to find construction contexts.
15420b57cec5SDimitry Andric     break;
15430b57cec5SDimitry Andric   }
1544fe6060f1SDimitry Andric   case Stmt::ParenExprClass: {
1545fe6060f1SDimitry Andric     // If expression is placed into parenthesis we should propagate the parent
1546fe6060f1SDimitry Andric     // construction context to subexpressions.
1547fe6060f1SDimitry Andric     auto *PE = cast<ParenExpr>(Child);
1548fe6060f1SDimitry Andric     findConstructionContexts(Layer, PE->getSubExpr());
1549fe6060f1SDimitry Andric     break;
1550fe6060f1SDimitry Andric   }
15510b57cec5SDimitry Andric   default:
15520b57cec5SDimitry Andric     break;
15530b57cec5SDimitry Andric   }
15540b57cec5SDimitry Andric }
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric void CFGBuilder::cleanupConstructionContext(Expr *E) {
15570b57cec5SDimitry Andric   assert(BuildOpts.AddRichCXXConstructors &&
15580b57cec5SDimitry Andric          "We should not be managing construction contexts!");
15590b57cec5SDimitry Andric   assert(ConstructionContextMap.count(E) &&
15600b57cec5SDimitry Andric          "Cannot exit construction context without the context!");
15610b57cec5SDimitry Andric   ConstructionContextMap.erase(E);
15620b57cec5SDimitry Andric }
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric /// BuildCFG - Constructs a CFG from an AST (a Stmt*).  The AST can represent an
15650b57cec5SDimitry Andric ///  arbitrary statement.  Examples include a single expression or a function
15660b57cec5SDimitry Andric ///  body (compound statement).  The ownership of the returned CFG is
15670b57cec5SDimitry Andric ///  transferred to the caller.  If CFG construction fails, this method returns
15680b57cec5SDimitry Andric ///  NULL.
15690b57cec5SDimitry Andric std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {
15700b57cec5SDimitry Andric   assert(cfg.get());
15710b57cec5SDimitry Andric   if (!Statement)
15720b57cec5SDimitry Andric     return nullptr;
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric   // Create an empty block that will serve as the exit block for the CFG.  Since
15750b57cec5SDimitry Andric   // this is the first block added to the CFG, it will be implicitly registered
15760b57cec5SDimitry Andric   // as the exit block.
15770b57cec5SDimitry Andric   Succ = createBlock();
15780b57cec5SDimitry Andric   assert(Succ == &cfg->getExit());
15790b57cec5SDimitry Andric   Block = nullptr;  // the EXIT block is empty.  Create all other blocks lazily.
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric   if (BuildOpts.AddImplicitDtors)
15820b57cec5SDimitry Andric     if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))
15830b57cec5SDimitry Andric       addImplicitDtorsForDestructor(DD);
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric   // Visit the statements and create the CFG.
15860b57cec5SDimitry Andric   CFGBlock *B = addStmt(Statement);
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric   if (badCFG)
15890b57cec5SDimitry Andric     return nullptr;
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric   // For C++ constructor add initializers to CFG. Constructors of virtual bases
15920b57cec5SDimitry Andric   // are ignored unless the object is of the most derived class.
15930b57cec5SDimitry Andric   //   class VBase { VBase() = default; VBase(int) {} };
15940b57cec5SDimitry Andric   //   class A : virtual public VBase { A() : VBase(0) {} };
15950b57cec5SDimitry Andric   //   class B : public A {};
15960b57cec5SDimitry Andric   //   B b; // Constructor calls in order: VBase(), A(), B().
15970b57cec5SDimitry Andric   //        // VBase(0) is ignored because A isn't the most derived class.
15980b57cec5SDimitry Andric   // This may result in the virtual base(s) being already initialized at this
15990b57cec5SDimitry Andric   // point, in which case we should jump right onto non-virtual bases and
16000b57cec5SDimitry Andric   // fields. To handle this, make a CFG branch. We only need to add one such
16010b57cec5SDimitry Andric   // branch per constructor, since the Standard states that all virtual bases
16020b57cec5SDimitry Andric   // shall be initialized before non-virtual bases and direct data members.
16030b57cec5SDimitry Andric   if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
16040b57cec5SDimitry Andric     CFGBlock *VBaseSucc = nullptr;
16050b57cec5SDimitry Andric     for (auto *I : llvm::reverse(CD->inits())) {
16060b57cec5SDimitry Andric       if (BuildOpts.AddVirtualBaseBranches && !VBaseSucc &&
16070b57cec5SDimitry Andric           I->isBaseInitializer() && I->isBaseVirtual()) {
16080b57cec5SDimitry Andric         // We've reached the first virtual base init while iterating in reverse
16090b57cec5SDimitry Andric         // order. Make a new block for virtual base initializers so that we
16100b57cec5SDimitry Andric         // could skip them.
16110b57cec5SDimitry Andric         VBaseSucc = Succ = B ? B : &cfg->getExit();
16120b57cec5SDimitry Andric         Block = createBlock();
16130b57cec5SDimitry Andric       }
16140b57cec5SDimitry Andric       B = addInitializer(I);
16150b57cec5SDimitry Andric       if (badCFG)
16160b57cec5SDimitry Andric         return nullptr;
16170b57cec5SDimitry Andric     }
16180b57cec5SDimitry Andric     if (VBaseSucc) {
16190b57cec5SDimitry Andric       // Make a branch block for potentially skipping virtual base initializers.
16200b57cec5SDimitry Andric       Succ = VBaseSucc;
16210b57cec5SDimitry Andric       B = createBlock();
16220b57cec5SDimitry Andric       B->setTerminator(
16230b57cec5SDimitry Andric           CFGTerminator(nullptr, CFGTerminator::VirtualBaseBranch));
16240b57cec5SDimitry Andric       addSuccessor(B, Block, true);
16250b57cec5SDimitry Andric     }
16260b57cec5SDimitry Andric   }
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric   if (B)
16290b57cec5SDimitry Andric     Succ = B;
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric   // Backpatch the gotos whose label -> block mappings we didn't know when we
16320b57cec5SDimitry Andric   // encountered them.
16330b57cec5SDimitry Andric   for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
16340b57cec5SDimitry Andric                                    E = BackpatchBlocks.end(); I != E; ++I ) {
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric     CFGBlock *B = I->block;
16370b57cec5SDimitry Andric     if (auto *G = dyn_cast<GotoStmt>(B->getTerminator())) {
16380b57cec5SDimitry Andric       LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
16390b57cec5SDimitry Andric       // If there is no target for the goto, then we are looking at an
16400b57cec5SDimitry Andric       // incomplete AST.  Handle this by not registering a successor.
16410b57cec5SDimitry Andric       if (LI == LabelMap.end())
16420b57cec5SDimitry Andric         continue;
16430b57cec5SDimitry Andric       JumpTarget JT = LI->second;
164406c3fb27SDimitry Andric 
164506c3fb27SDimitry Andric       CFGBlock *SuccBlk = createScopeChangesHandlingBlock(
164606c3fb27SDimitry Andric           I->scopePosition, B, JT.scopePosition, JT.block);
164706c3fb27SDimitry Andric       addSuccessor(B, SuccBlk);
164806c3fb27SDimitry Andric     } else if (auto *G = dyn_cast<GCCAsmStmt>(B->getTerminator())) {
16490b57cec5SDimitry Andric       CFGBlock *Successor  = (I+1)->block;
16500b57cec5SDimitry Andric       for (auto *L : G->labels()) {
16510b57cec5SDimitry Andric         LabelMapTy::iterator LI = LabelMap.find(L->getLabel());
16520b57cec5SDimitry Andric         // If there is no target for the goto, then we are looking at an
16530b57cec5SDimitry Andric         // incomplete AST.  Handle this by not registering a successor.
16540b57cec5SDimitry Andric         if (LI == LabelMap.end())
16550b57cec5SDimitry Andric           continue;
16560b57cec5SDimitry Andric         JumpTarget JT = LI->second;
16570b57cec5SDimitry Andric         // Successor has been added, so skip it.
16580b57cec5SDimitry Andric         if (JT.block == Successor)
16590b57cec5SDimitry Andric           continue;
16600b57cec5SDimitry Andric         addSuccessor(B, JT.block);
16610b57cec5SDimitry Andric       }
16620b57cec5SDimitry Andric       I++;
16630b57cec5SDimitry Andric     }
16640b57cec5SDimitry Andric   }
16650b57cec5SDimitry Andric 
16660b57cec5SDimitry Andric   // Add successors to the Indirect Goto Dispatch block (if we have one).
16670b57cec5SDimitry Andric   if (CFGBlock *B = cfg->getIndirectGotoBlock())
16680b57cec5SDimitry Andric     for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
16690b57cec5SDimitry Andric                               E = AddressTakenLabels.end(); I != E; ++I ) {
16700b57cec5SDimitry Andric       // Lookup the target block.
16710b57cec5SDimitry Andric       LabelMapTy::iterator LI = LabelMap.find(*I);
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric       // If there is no target block that contains label, then we are looking
16740b57cec5SDimitry Andric       // at an incomplete AST.  Handle this by not registering a successor.
16750b57cec5SDimitry Andric       if (LI == LabelMap.end()) continue;
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric       addSuccessor(B, LI->second.block);
16780b57cec5SDimitry Andric     }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric   // Create an empty entry block that has no predecessors.
16810b57cec5SDimitry Andric   cfg->setEntry(createBlock());
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   if (BuildOpts.AddRichCXXConstructors)
16840b57cec5SDimitry Andric     assert(ConstructionContextMap.empty() &&
16850b57cec5SDimitry Andric            "Not all construction contexts were cleaned up!");
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   return std::move(cfg);
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric /// createBlock - Used to lazily create blocks that are connected
1691bdd1243dSDimitry Andric ///  to the current (global) successor.
16920b57cec5SDimitry Andric CFGBlock *CFGBuilder::createBlock(bool add_successor) {
16930b57cec5SDimitry Andric   CFGBlock *B = cfg->createBlock();
16940b57cec5SDimitry Andric   if (add_successor && Succ)
16950b57cec5SDimitry Andric     addSuccessor(B, Succ);
16960b57cec5SDimitry Andric   return B;
16970b57cec5SDimitry Andric }
16980b57cec5SDimitry Andric 
16990b57cec5SDimitry Andric /// createNoReturnBlock - Used to create a block is a 'noreturn' point in the
17000b57cec5SDimitry Andric /// CFG. It is *not* connected to the current (global) successor, and instead
17010b57cec5SDimitry Andric /// directly tied to the exit block in order to be reachable.
17020b57cec5SDimitry Andric CFGBlock *CFGBuilder::createNoReturnBlock() {
17030b57cec5SDimitry Andric   CFGBlock *B = createBlock(false);
17040b57cec5SDimitry Andric   B->setHasNoReturnElement();
17050b57cec5SDimitry Andric   addSuccessor(B, &cfg->getExit(), Succ);
17060b57cec5SDimitry Andric   return B;
17070b57cec5SDimitry Andric }
17080b57cec5SDimitry Andric 
17090b57cec5SDimitry Andric /// addInitializer - Add C++ base or member initializer element to CFG.
17100b57cec5SDimitry Andric CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
17110b57cec5SDimitry Andric   if (!BuildOpts.AddInitializers)
17120b57cec5SDimitry Andric     return Block;
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric   bool HasTemporaries = false;
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric   // Destructors of temporaries in initialization expression should be called
17170b57cec5SDimitry Andric   // after initialization finishes.
17180b57cec5SDimitry Andric   Expr *Init = I->getInit();
17190b57cec5SDimitry Andric   if (Init) {
17200b57cec5SDimitry Andric     HasTemporaries = isa<ExprWithCleanups>(Init);
17210b57cec5SDimitry Andric 
17220b57cec5SDimitry Andric     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
17230b57cec5SDimitry Andric       // Generate destructors for temporaries in initialization expression.
17240b57cec5SDimitry Andric       TempDtorContext Context;
17250b57cec5SDimitry Andric       VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
1726a7dea167SDimitry Andric                              /*ExternallyDestructed=*/false, Context);
17270b57cec5SDimitry Andric     }
17280b57cec5SDimitry Andric   }
17290b57cec5SDimitry Andric 
17300b57cec5SDimitry Andric   autoCreateBlock();
17310b57cec5SDimitry Andric   appendInitializer(Block, I);
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   if (Init) {
1734972a253aSDimitry Andric     // If the initializer is an ArrayInitLoopExpr, we want to extract the
1735972a253aSDimitry Andric     // initializer, that's used for each element.
1736bdd1243dSDimitry Andric     auto *AILEInit = extractElementInitializerFromNestedAILE(
1737bdd1243dSDimitry Andric         dyn_cast<ArrayInitLoopExpr>(Init));
1738972a253aSDimitry Andric 
17390b57cec5SDimitry Andric     findConstructionContexts(
17400b57cec5SDimitry Andric         ConstructionContextLayer::create(cfg->getBumpVectorContext(), I),
1741bdd1243dSDimitry Andric         AILEInit ? AILEInit : Init);
17420b57cec5SDimitry Andric 
17430b57cec5SDimitry Andric     if (HasTemporaries) {
17440b57cec5SDimitry Andric       // For expression with temporaries go directly to subexpression to omit
17450b57cec5SDimitry Andric       // generating destructors for the second time.
17460b57cec5SDimitry Andric       return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
17470b57cec5SDimitry Andric     }
17480b57cec5SDimitry Andric     if (BuildOpts.AddCXXDefaultInitExprInCtors) {
17490b57cec5SDimitry Andric       if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) {
17500b57cec5SDimitry Andric         // In general, appending the expression wrapped by a CXXDefaultInitExpr
17510b57cec5SDimitry Andric         // may cause the same Expr to appear more than once in the CFG. Doing it
17520b57cec5SDimitry Andric         // here is safe because there's only one initializer per field.
17530b57cec5SDimitry Andric         autoCreateBlock();
17540b57cec5SDimitry Andric         appendStmt(Block, Default);
17550b57cec5SDimitry Andric         if (Stmt *Child = Default->getExpr())
17560b57cec5SDimitry Andric           if (CFGBlock *R = Visit(Child))
17570b57cec5SDimitry Andric             Block = R;
17580b57cec5SDimitry Andric         return Block;
17590b57cec5SDimitry Andric       }
17600b57cec5SDimitry Andric     }
17610b57cec5SDimitry Andric     return Visit(Init);
17620b57cec5SDimitry Andric   }
17630b57cec5SDimitry Andric 
17640b57cec5SDimitry Andric   return Block;
17650b57cec5SDimitry Andric }
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric /// Retrieve the type of the temporary object whose lifetime was
17680b57cec5SDimitry Andric /// extended by a local reference with the given initializer.
17690b57cec5SDimitry Andric static QualType getReferenceInitTemporaryType(const Expr *Init,
17700b57cec5SDimitry Andric                                               bool *FoundMTE = nullptr) {
17710b57cec5SDimitry Andric   while (true) {
17720b57cec5SDimitry Andric     // Skip parentheses.
17730b57cec5SDimitry Andric     Init = Init->IgnoreParens();
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric     // Skip through cleanups.
17760b57cec5SDimitry Andric     if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) {
17770b57cec5SDimitry Andric       Init = EWC->getSubExpr();
17780b57cec5SDimitry Andric       continue;
17790b57cec5SDimitry Andric     }
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric     // Skip through the temporary-materialization expression.
17820b57cec5SDimitry Andric     if (const MaterializeTemporaryExpr *MTE
17830b57cec5SDimitry Andric           = dyn_cast<MaterializeTemporaryExpr>(Init)) {
1784480093f4SDimitry Andric       Init = MTE->getSubExpr();
17850b57cec5SDimitry Andric       if (FoundMTE)
17860b57cec5SDimitry Andric         *FoundMTE = true;
17870b57cec5SDimitry Andric       continue;
17880b57cec5SDimitry Andric     }
17890b57cec5SDimitry Andric 
17900b57cec5SDimitry Andric     // Skip sub-object accesses into rvalues.
1791*0fca6ea1SDimitry Andric     const Expr *SkippedInit = Init->skipRValueSubobjectAdjustments();
17920b57cec5SDimitry Andric     if (SkippedInit != Init) {
17930b57cec5SDimitry Andric       Init = SkippedInit;
17940b57cec5SDimitry Andric       continue;
17950b57cec5SDimitry Andric     }
17960b57cec5SDimitry Andric 
17970b57cec5SDimitry Andric     break;
17980b57cec5SDimitry Andric   }
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric   return Init->getType();
18010b57cec5SDimitry Andric }
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric // TODO: Support adding LoopExit element to the CFG in case where the loop is
18040b57cec5SDimitry Andric // ended by ReturnStmt, GotoStmt or ThrowExpr.
18050b57cec5SDimitry Andric void CFGBuilder::addLoopExit(const Stmt *LoopStmt){
18060b57cec5SDimitry Andric   if(!BuildOpts.AddLoopExit)
18070b57cec5SDimitry Andric     return;
18080b57cec5SDimitry Andric   autoCreateBlock();
18090b57cec5SDimitry Andric   appendLoopExit(Block, LoopStmt);
18100b57cec5SDimitry Andric }
18110b57cec5SDimitry Andric 
181206c3fb27SDimitry Andric /// Adds the CFG elements for leaving the scope of automatic objects in
181306c3fb27SDimitry Andric /// range [B, E). This include following:
181406c3fb27SDimitry Andric ///   * AutomaticObjectDtor for variables with non-trivial destructor
181506c3fb27SDimitry Andric ///   * LifetimeEnds for all variables
181606c3fb27SDimitry Andric ///   * ScopeEnd for each scope left
18170b57cec5SDimitry Andric void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
18180b57cec5SDimitry Andric                                          LocalScope::const_iterator E,
18190b57cec5SDimitry Andric                                          Stmt *S) {
182006c3fb27SDimitry Andric   if (!BuildOpts.AddScopes && !BuildOpts.AddImplicitDtors &&
182106c3fb27SDimitry Andric       !BuildOpts.AddLifetime)
18220b57cec5SDimitry Andric     return;
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   if (B == E)
18250b57cec5SDimitry Andric     return;
18260b57cec5SDimitry Andric 
182706c3fb27SDimitry Andric   // Not leaving the scope, only need to handle destruction and lifetime
182806c3fb27SDimitry Andric   if (B.inSameLocalScope(E)) {
182906c3fb27SDimitry Andric     addAutomaticObjDestruction(B, E, S);
183006c3fb27SDimitry Andric     return;
183106c3fb27SDimitry Andric   }
183206c3fb27SDimitry Andric 
183306c3fb27SDimitry Andric   // Extract information about all local scopes that are left
183406c3fb27SDimitry Andric   SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;
183506c3fb27SDimitry Andric   LocalScopeEndMarkers.push_back(B);
183606c3fb27SDimitry Andric   for (LocalScope::const_iterator I = B; I != E; ++I) {
183706c3fb27SDimitry Andric     if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))
183806c3fb27SDimitry Andric       LocalScopeEndMarkers.push_back(I);
183906c3fb27SDimitry Andric   }
184006c3fb27SDimitry Andric   LocalScopeEndMarkers.push_back(E);
184106c3fb27SDimitry Andric 
184206c3fb27SDimitry Andric   // We need to leave the scope in reverse order, so we reverse the end
184306c3fb27SDimitry Andric   // markers
184406c3fb27SDimitry Andric   std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());
184506c3fb27SDimitry Andric   auto Pairwise =
184606c3fb27SDimitry Andric       llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));
184706c3fb27SDimitry Andric   for (auto [E, B] : Pairwise) {
184806c3fb27SDimitry Andric     if (!B.inSameLocalScope(E))
184906c3fb27SDimitry Andric       addScopeExitHandling(B, E, S);
185006c3fb27SDimitry Andric     addAutomaticObjDestruction(B, E, S);
185106c3fb27SDimitry Andric   }
185206c3fb27SDimitry Andric }
185306c3fb27SDimitry Andric 
185406c3fb27SDimitry Andric /// Add CFG elements corresponding to call destructor and end of lifetime
185506c3fb27SDimitry Andric /// of all automatic variables with non-trivial destructor in range [B, E).
185606c3fb27SDimitry Andric /// This include AutomaticObjectDtor and LifetimeEnds elements.
185706c3fb27SDimitry Andric void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
185806c3fb27SDimitry Andric                                             LocalScope::const_iterator E,
185906c3fb27SDimitry Andric                                             Stmt *S) {
186006c3fb27SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)
18610b57cec5SDimitry Andric     return;
18620b57cec5SDimitry Andric 
186306c3fb27SDimitry Andric   if (B == E)
186406c3fb27SDimitry Andric     return;
186506c3fb27SDimitry Andric 
18665f757f3fSDimitry Andric   SmallVector<VarDecl *, 10> DeclsNeedDestruction;
18675f757f3fSDimitry Andric   DeclsNeedDestruction.reserve(B.distance(E));
18680b57cec5SDimitry Andric 
186906c3fb27SDimitry Andric   for (VarDecl* D : llvm::make_range(B, E))
18705f757f3fSDimitry Andric     if (needsAutomaticDestruction(D))
18715f757f3fSDimitry Andric       DeclsNeedDestruction.push_back(D);
18720b57cec5SDimitry Andric 
18735f757f3fSDimitry Andric   for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
187406c3fb27SDimitry Andric     if (BuildOpts.AddImplicitDtors) {
18750b57cec5SDimitry Andric       // If this destructor is marked as a no-return destructor, we need to
187606c3fb27SDimitry Andric       // create a new block for the destructor which does not have as a
187706c3fb27SDimitry Andric       // successor anything built thus far: control won't flow out of this
187806c3fb27SDimitry Andric       // block.
1879349cc55cSDimitry Andric       QualType Ty = VD->getType();
188006c3fb27SDimitry Andric       if (Ty->isReferenceType())
1881349cc55cSDimitry Andric         Ty = getReferenceInitTemporaryType(VD->getInit());
18820b57cec5SDimitry Andric       Ty = Context->getBaseElementType(Ty);
18830b57cec5SDimitry Andric 
18845f757f3fSDimitry Andric       const CXXRecordDecl *CRD = Ty->getAsCXXRecordDecl();
18855f757f3fSDimitry Andric       if (CRD && CRD->isAnyDestructorNoReturn())
18860b57cec5SDimitry Andric         Block = createNoReturnBlock();
188706c3fb27SDimitry Andric     }
188806c3fb27SDimitry Andric 
18890b57cec5SDimitry Andric     autoCreateBlock();
18900b57cec5SDimitry Andric 
189106c3fb27SDimitry Andric     // Add LifetimeEnd after automatic obj with non-trivial destructors,
189206c3fb27SDimitry Andric     // as they end their lifetime when the destructor returns. For trivial
189306c3fb27SDimitry Andric     // objects, we end lifetime with scope end.
189406c3fb27SDimitry Andric     if (BuildOpts.AddLifetime)
189506c3fb27SDimitry Andric       appendLifetimeEnds(Block, VD, S);
18965f757f3fSDimitry Andric     if (BuildOpts.AddImplicitDtors && !hasTrivialDestructor(VD))
1897349cc55cSDimitry Andric       appendAutomaticObjDtor(Block, VD, S);
18985f757f3fSDimitry Andric     if (VD->hasAttr<CleanupAttr>())
18995f757f3fSDimitry Andric       appendCleanupFunction(Block, VD);
19000b57cec5SDimitry Andric   }
19010b57cec5SDimitry Andric }
19020b57cec5SDimitry Andric 
190306c3fb27SDimitry Andric /// Add CFG elements corresponding to leaving a scope.
190406c3fb27SDimitry Andric /// Assumes that range [B, E) corresponds to single scope.
190506c3fb27SDimitry Andric /// This add following elements:
190606c3fb27SDimitry Andric ///   * LifetimeEnds for all variables with non-trivial destructor
190706c3fb27SDimitry Andric ///   * ScopeEnd for each scope left
190806c3fb27SDimitry Andric void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
190906c3fb27SDimitry Andric                                       LocalScope::const_iterator E, Stmt *S) {
191006c3fb27SDimitry Andric   assert(!B.inSameLocalScope(E));
191106c3fb27SDimitry Andric   if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes)
191206c3fb27SDimitry Andric     return;
191306c3fb27SDimitry Andric 
191406c3fb27SDimitry Andric   if (BuildOpts.AddScopes) {
191506c3fb27SDimitry Andric     autoCreateBlock();
191606c3fb27SDimitry Andric     appendScopeEnd(Block, B.getFirstVarInScope(), S);
191706c3fb27SDimitry Andric   }
191806c3fb27SDimitry Andric 
191906c3fb27SDimitry Andric   if (!BuildOpts.AddLifetime)
192006c3fb27SDimitry Andric     return;
192106c3fb27SDimitry Andric 
192206c3fb27SDimitry Andric   // We need to perform the scope leaving in reverse order
192306c3fb27SDimitry Andric   SmallVector<VarDecl *, 10> DeclsTrivial;
192406c3fb27SDimitry Andric   DeclsTrivial.reserve(B.distance(E));
192506c3fb27SDimitry Andric 
192606c3fb27SDimitry Andric   // Objects with trivial destructor ends their lifetime when their storage
192706c3fb27SDimitry Andric   // is destroyed, for automatic variables, this happens when the end of the
192806c3fb27SDimitry Andric   // scope is added.
192906c3fb27SDimitry Andric   for (VarDecl* D : llvm::make_range(B, E))
19305f757f3fSDimitry Andric     if (!needsAutomaticDestruction(D))
193106c3fb27SDimitry Andric       DeclsTrivial.push_back(D);
193206c3fb27SDimitry Andric 
193306c3fb27SDimitry Andric   if (DeclsTrivial.empty())
193406c3fb27SDimitry Andric     return;
193506c3fb27SDimitry Andric 
193606c3fb27SDimitry Andric   autoCreateBlock();
193706c3fb27SDimitry Andric   for (VarDecl *VD : llvm::reverse(DeclsTrivial))
193806c3fb27SDimitry Andric     appendLifetimeEnds(Block, VD, S);
193906c3fb27SDimitry Andric }
194006c3fb27SDimitry Andric 
194106c3fb27SDimitry Andric /// addScopeChangesHandling - appends information about destruction, lifetime
194206c3fb27SDimitry Andric /// and cfgScopeEnd for variables in the scope that was left by the jump, and
194306c3fb27SDimitry Andric /// appends cfgScopeBegin for all scopes that where entered.
194406c3fb27SDimitry Andric /// We insert the cfgScopeBegin at the end of the jump node, as depending on
194506c3fb27SDimitry Andric /// the sourceBlock, each goto, may enter different amount of scopes.
194606c3fb27SDimitry Andric void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
194706c3fb27SDimitry Andric                                          LocalScope::const_iterator DstPos,
194806c3fb27SDimitry Andric                                          Stmt *S) {
194906c3fb27SDimitry Andric   assert(Block && "Source block should be always crated");
195006c3fb27SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
195106c3fb27SDimitry Andric       !BuildOpts.AddScopes) {
195206c3fb27SDimitry Andric     return;
195306c3fb27SDimitry Andric   }
195406c3fb27SDimitry Andric 
195506c3fb27SDimitry Andric   if (SrcPos == DstPos)
195606c3fb27SDimitry Andric     return;
195706c3fb27SDimitry Andric 
195806c3fb27SDimitry Andric   // Get common scope, the jump leaves all scopes [SrcPos, BasePos), and
195906c3fb27SDimitry Andric   // enter all scopes between [DstPos, BasePos)
196006c3fb27SDimitry Andric   LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);
196106c3fb27SDimitry Andric 
196206c3fb27SDimitry Andric   // Append scope begins for scopes entered by goto
196306c3fb27SDimitry Andric   if (BuildOpts.AddScopes && !DstPos.inSameLocalScope(BasePos)) {
196406c3fb27SDimitry Andric     for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)
196506c3fb27SDimitry Andric       if (I.pointsToFirstDeclaredVar())
196606c3fb27SDimitry Andric         appendScopeBegin(Block, *I, S);
196706c3fb27SDimitry Andric   }
196806c3fb27SDimitry Andric 
196906c3fb27SDimitry Andric   // Append scopeEnds, destructor and lifetime with the terminator for
197006c3fb27SDimitry Andric   // block left by goto.
197106c3fb27SDimitry Andric   addAutomaticObjHandling(SrcPos, BasePos, S);
197206c3fb27SDimitry Andric }
197306c3fb27SDimitry Andric 
197406c3fb27SDimitry Andric /// createScopeChangesHandlingBlock - Creates a block with cfgElements
197506c3fb27SDimitry Andric /// corresponding to changing the scope from the source scope of the GotoStmt,
197606c3fb27SDimitry Andric /// to destination scope. Add destructor, lifetime and cfgScopeEnd
197706c3fb27SDimitry Andric /// CFGElements to newly created CFGBlock, that will have the CFG terminator
197806c3fb27SDimitry Andric /// transferred.
197906c3fb27SDimitry Andric CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
198006c3fb27SDimitry Andric     LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
198106c3fb27SDimitry Andric     LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {
198206c3fb27SDimitry Andric   if (SrcPos == DstPos)
198306c3fb27SDimitry Andric     return DstBlk;
198406c3fb27SDimitry Andric 
198506c3fb27SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
198606c3fb27SDimitry Andric       (!BuildOpts.AddScopes || SrcPos.inSameLocalScope(DstPos)))
198706c3fb27SDimitry Andric     return DstBlk;
198806c3fb27SDimitry Andric 
198906c3fb27SDimitry Andric   // We will update CFBBuilder when creating new block, restore the
199006c3fb27SDimitry Andric   // previous state at exit.
199106c3fb27SDimitry Andric   SaveAndRestore save_Block(Block), save_Succ(Succ);
199206c3fb27SDimitry Andric 
199306c3fb27SDimitry Andric   // Create a new block, and transfer terminator
199406c3fb27SDimitry Andric   Block = createBlock(false);
199506c3fb27SDimitry Andric   Block->setTerminator(SrcBlk->getTerminator());
199606c3fb27SDimitry Andric   SrcBlk->setTerminator(CFGTerminator());
199706c3fb27SDimitry Andric   addSuccessor(Block, DstBlk);
199806c3fb27SDimitry Andric 
199906c3fb27SDimitry Andric   // Fill the created Block with the required elements.
200006c3fb27SDimitry Andric   addScopeChangesHandling(SrcPos, DstPos, Block->getTerminatorStmt());
200106c3fb27SDimitry Andric 
200206c3fb27SDimitry Andric   assert(Block && "There should be at least one scope changing Block");
200306c3fb27SDimitry Andric   return Block;
200406c3fb27SDimitry Andric }
200506c3fb27SDimitry Andric 
20060b57cec5SDimitry Andric /// addImplicitDtorsForDestructor - Add implicit destructors generated for
20070b57cec5SDimitry Andric /// base and member objects in destructor.
20080b57cec5SDimitry Andric void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
20090b57cec5SDimitry Andric   assert(BuildOpts.AddImplicitDtors &&
20100b57cec5SDimitry Andric          "Can be called only when dtors should be added");
20110b57cec5SDimitry Andric   const CXXRecordDecl *RD = DD->getParent();
20120b57cec5SDimitry Andric 
20130b57cec5SDimitry Andric   // At the end destroy virtual base objects.
20140b57cec5SDimitry Andric   for (const auto &VI : RD->vbases()) {
20150b57cec5SDimitry Andric     // TODO: Add a VirtualBaseBranch to see if the most derived class
20160b57cec5SDimitry Andric     // (which is different from the current class) is responsible for
20170b57cec5SDimitry Andric     // destroying them.
20180b57cec5SDimitry Andric     const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();
2019bdd1243dSDimitry Andric     if (CD && !CD->hasTrivialDestructor()) {
20200b57cec5SDimitry Andric       autoCreateBlock();
20210b57cec5SDimitry Andric       appendBaseDtor(Block, &VI);
20220b57cec5SDimitry Andric     }
20230b57cec5SDimitry Andric   }
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric   // Before virtual bases destroy direct base objects.
20260b57cec5SDimitry Andric   for (const auto &BI : RD->bases()) {
20270b57cec5SDimitry Andric     if (!BI.isVirtual()) {
20280b57cec5SDimitry Andric       const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();
2029bdd1243dSDimitry Andric       if (CD && !CD->hasTrivialDestructor()) {
20300b57cec5SDimitry Andric         autoCreateBlock();
20310b57cec5SDimitry Andric         appendBaseDtor(Block, &BI);
20320b57cec5SDimitry Andric       }
20330b57cec5SDimitry Andric     }
20340b57cec5SDimitry Andric   }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric   // First destroy member objects.
20370b57cec5SDimitry Andric   for (auto *FI : RD->fields()) {
20380b57cec5SDimitry Andric     // Check for constant size array. Set type to array element type.
20390b57cec5SDimitry Andric     QualType QT = FI->getType();
2040bdd1243dSDimitry Andric     // It may be a multidimensional array.
2041bdd1243dSDimitry Andric     while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
2042*0fca6ea1SDimitry Andric       if (AT->isZeroSize())
2043bdd1243dSDimitry Andric         break;
20440b57cec5SDimitry Andric       QT = AT->getElementType();
20450b57cec5SDimitry Andric     }
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric     if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
20480b57cec5SDimitry Andric       if (!CD->hasTrivialDestructor()) {
20490b57cec5SDimitry Andric         autoCreateBlock();
20500b57cec5SDimitry Andric         appendMemberDtor(Block, FI);
20510b57cec5SDimitry Andric       }
20520b57cec5SDimitry Andric   }
20530b57cec5SDimitry Andric }
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric /// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
20560b57cec5SDimitry Andric /// way return valid LocalScope object.
20570b57cec5SDimitry Andric LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
20580b57cec5SDimitry Andric   if (Scope)
20590b57cec5SDimitry Andric     return Scope;
20600b57cec5SDimitry Andric   llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
206106c3fb27SDimitry Andric   return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);
20620b57cec5SDimitry Andric }
20630b57cec5SDimitry Andric 
20640b57cec5SDimitry Andric /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
20650b57cec5SDimitry Andric /// that should create implicit scope (e.g. if/else substatements).
20660b57cec5SDimitry Andric void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
20670b57cec5SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
20680b57cec5SDimitry Andric       !BuildOpts.AddScopes)
20690b57cec5SDimitry Andric     return;
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric   LocalScope *Scope = nullptr;
20720b57cec5SDimitry Andric 
20730b57cec5SDimitry Andric   // For compound statement we will be creating explicit scope.
20740b57cec5SDimitry Andric   if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
20750b57cec5SDimitry Andric     for (auto *BI : CS->body()) {
20760b57cec5SDimitry Andric       Stmt *SI = BI->stripLabelLikeStatements();
20770b57cec5SDimitry Andric       if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
20780b57cec5SDimitry Andric         Scope = addLocalScopeForDeclStmt(DS, Scope);
20790b57cec5SDimitry Andric     }
20800b57cec5SDimitry Andric     return;
20810b57cec5SDimitry Andric   }
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric   // For any other statement scope will be implicit and as such will be
20840b57cec5SDimitry Andric   // interesting only for DeclStmt.
20850b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
20860b57cec5SDimitry Andric     addLocalScopeForDeclStmt(DS);
20870b57cec5SDimitry Andric }
20880b57cec5SDimitry Andric 
20890b57cec5SDimitry Andric /// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will
20900b57cec5SDimitry Andric /// reuse Scope if not NULL.
20910b57cec5SDimitry Andric LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
20920b57cec5SDimitry Andric                                                  LocalScope* Scope) {
20930b57cec5SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
20940b57cec5SDimitry Andric       !BuildOpts.AddScopes)
20950b57cec5SDimitry Andric     return Scope;
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   for (auto *DI : DS->decls())
20980b57cec5SDimitry Andric     if (VarDecl *VD = dyn_cast<VarDecl>(DI))
20990b57cec5SDimitry Andric       Scope = addLocalScopeForVarDecl(VD, Scope);
21000b57cec5SDimitry Andric   return Scope;
21010b57cec5SDimitry Andric }
21020b57cec5SDimitry Andric 
21035f757f3fSDimitry Andric bool CFGBuilder::needsAutomaticDestruction(const VarDecl *VD) const {
21045f757f3fSDimitry Andric   return !hasTrivialDestructor(VD) || VD->hasAttr<CleanupAttr>();
21055f757f3fSDimitry Andric }
21065f757f3fSDimitry Andric 
21075f757f3fSDimitry Andric bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const {
21080b57cec5SDimitry Andric   // Check for const references bound to temporary. Set type to pointee.
21090b57cec5SDimitry Andric   QualType QT = VD->getType();
21100b57cec5SDimitry Andric   if (QT->isReferenceType()) {
21110b57cec5SDimitry Andric     // Attempt to determine whether this declaration lifetime-extends a
21120b57cec5SDimitry Andric     // temporary.
21130b57cec5SDimitry Andric     //
21140b57cec5SDimitry Andric     // FIXME: This is incorrect. Non-reference declarations can lifetime-extend
21150b57cec5SDimitry Andric     // temporaries, and a single declaration can extend multiple temporaries.
21160b57cec5SDimitry Andric     // We should look at the storage duration on each nested
21170b57cec5SDimitry Andric     // MaterializeTemporaryExpr instead.
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric     const Expr *Init = VD->getInit();
21200b57cec5SDimitry Andric     if (!Init) {
21210b57cec5SDimitry Andric       // Probably an exception catch-by-reference variable.
21220b57cec5SDimitry Andric       // FIXME: It doesn't really mean that the object has a trivial destructor.
21230b57cec5SDimitry Andric       // Also are there other cases?
21240b57cec5SDimitry Andric       return true;
21250b57cec5SDimitry Andric     }
21260b57cec5SDimitry Andric 
21270b57cec5SDimitry Andric     // Lifetime-extending a temporary?
21280b57cec5SDimitry Andric     bool FoundMTE = false;
21290b57cec5SDimitry Andric     QT = getReferenceInitTemporaryType(Init, &FoundMTE);
21300b57cec5SDimitry Andric     if (!FoundMTE)
21310b57cec5SDimitry Andric       return true;
21320b57cec5SDimitry Andric   }
21330b57cec5SDimitry Andric 
21340b57cec5SDimitry Andric   // Check for constant size array. Set type to array element type.
21350b57cec5SDimitry Andric   while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
2136*0fca6ea1SDimitry Andric     if (AT->isZeroSize())
21370b57cec5SDimitry Andric       return true;
21380b57cec5SDimitry Andric     QT = AT->getElementType();
21390b57cec5SDimitry Andric   }
21400b57cec5SDimitry Andric 
21410b57cec5SDimitry Andric   // Check if type is a C++ class with non-trivial destructor.
21420b57cec5SDimitry Andric   if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
21430b57cec5SDimitry Andric     return !CD->hasDefinition() || CD->hasTrivialDestructor();
21440b57cec5SDimitry Andric   return true;
21450b57cec5SDimitry Andric }
21460b57cec5SDimitry Andric 
21470b57cec5SDimitry Andric /// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will
21480b57cec5SDimitry Andric /// create add scope for automatic objects and temporary objects bound to
21490b57cec5SDimitry Andric /// const reference. Will reuse Scope if not NULL.
21500b57cec5SDimitry Andric LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
21510b57cec5SDimitry Andric                                                 LocalScope* Scope) {
21520b57cec5SDimitry Andric   if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&
21530b57cec5SDimitry Andric       !BuildOpts.AddScopes)
21540b57cec5SDimitry Andric     return Scope;
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric   // Check if variable is local.
215781ad6265SDimitry Andric   if (!VD->hasLocalStorage())
215881ad6265SDimitry Andric     return Scope;
21590b57cec5SDimitry Andric 
216006c3fb27SDimitry Andric   if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes &&
21615f757f3fSDimitry Andric       !needsAutomaticDestruction(VD)) {
216206c3fb27SDimitry Andric     assert(BuildOpts.AddImplicitDtors);
21630b57cec5SDimitry Andric     return Scope;
21640b57cec5SDimitry Andric   }
21650b57cec5SDimitry Andric 
21660b57cec5SDimitry Andric   // Add the variable to scope
21670b57cec5SDimitry Andric   Scope = createOrReuseLocalScope(Scope);
21680b57cec5SDimitry Andric   Scope->addVar(VD);
21690b57cec5SDimitry Andric   ScopePos = Scope->begin();
21700b57cec5SDimitry Andric   return Scope;
21710b57cec5SDimitry Andric }
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric /// addLocalScopeAndDtors - For given statement add local scope for it and
21740b57cec5SDimitry Andric /// add destructors that will cleanup the scope. Will reuse Scope if not NULL.
21750b57cec5SDimitry Andric void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
21760b57cec5SDimitry Andric   LocalScope::const_iterator scopeBeginPos = ScopePos;
21770b57cec5SDimitry Andric   addLocalScopeForStmt(S);
21780b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, scopeBeginPos, S);
21790b57cec5SDimitry Andric }
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric /// Visit - Walk the subtree of a statement and add extra
21820b57cec5SDimitry Andric ///   blocks for ternary operators, &&, and ||.  We also process "," and
21830b57cec5SDimitry Andric ///   DeclStmts (which may contain nested control-flow).
2184a7dea167SDimitry Andric CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
2185a7dea167SDimitry Andric                             bool ExternallyDestructed) {
21860b57cec5SDimitry Andric   if (!S) {
21870b57cec5SDimitry Andric     badCFG = true;
21880b57cec5SDimitry Andric     return nullptr;
21890b57cec5SDimitry Andric   }
21900b57cec5SDimitry Andric 
21910b57cec5SDimitry Andric   if (Expr *E = dyn_cast<Expr>(S))
21920b57cec5SDimitry Andric     S = E->IgnoreParens();
21930b57cec5SDimitry Andric 
21940b57cec5SDimitry Andric   if (Context->getLangOpts().OpenMP)
21950b57cec5SDimitry Andric     if (auto *D = dyn_cast<OMPExecutableDirective>(S))
21960b57cec5SDimitry Andric       return VisitOMPExecutableDirective(D, asc);
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric   switch (S->getStmtClass()) {
21990b57cec5SDimitry Andric     default:
22000b57cec5SDimitry Andric       return VisitStmt(S, asc);
22010b57cec5SDimitry Andric 
2202480093f4SDimitry Andric     case Stmt::ImplicitValueInitExprClass:
2203480093f4SDimitry Andric       if (BuildOpts.OmitImplicitValueInitializers)
2204480093f4SDimitry Andric         return Block;
2205480093f4SDimitry Andric       return VisitStmt(S, asc);
2206480093f4SDimitry Andric 
2207480093f4SDimitry Andric     case Stmt::InitListExprClass:
2208480093f4SDimitry Andric       return VisitInitListExpr(cast<InitListExpr>(S), asc);
2209480093f4SDimitry Andric 
2210349cc55cSDimitry Andric     case Stmt::AttributedStmtClass:
2211349cc55cSDimitry Andric       return VisitAttributedStmt(cast<AttributedStmt>(S), asc);
2212349cc55cSDimitry Andric 
22130b57cec5SDimitry Andric     case Stmt::AddrLabelExprClass:
22140b57cec5SDimitry Andric       return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric     case Stmt::BinaryConditionalOperatorClass:
22170b57cec5SDimitry Andric       return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);
22180b57cec5SDimitry Andric 
22190b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass:
22200b57cec5SDimitry Andric       return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric     case Stmt::BlockExprClass:
22230b57cec5SDimitry Andric       return VisitBlockExpr(cast<BlockExpr>(S), asc);
22240b57cec5SDimitry Andric 
22250b57cec5SDimitry Andric     case Stmt::BreakStmtClass:
22260b57cec5SDimitry Andric       return VisitBreakStmt(cast<BreakStmt>(S));
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric     case Stmt::CallExprClass:
22290b57cec5SDimitry Andric     case Stmt::CXXOperatorCallExprClass:
22300b57cec5SDimitry Andric     case Stmt::CXXMemberCallExprClass:
22310b57cec5SDimitry Andric     case Stmt::UserDefinedLiteralClass:
22320b57cec5SDimitry Andric       return VisitCallExpr(cast<CallExpr>(S), asc);
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric     case Stmt::CaseStmtClass:
22350b57cec5SDimitry Andric       return VisitCaseStmt(cast<CaseStmt>(S));
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric     case Stmt::ChooseExprClass:
22380b57cec5SDimitry Andric       return VisitChooseExpr(cast<ChooseExpr>(S), asc);
22390b57cec5SDimitry Andric 
22400b57cec5SDimitry Andric     case Stmt::CompoundStmtClass:
2241a7dea167SDimitry Andric       return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric     case Stmt::ConditionalOperatorClass:
22440b57cec5SDimitry Andric       return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric     case Stmt::ContinueStmtClass:
22470b57cec5SDimitry Andric       return VisitContinueStmt(cast<ContinueStmt>(S));
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric     case Stmt::CXXCatchStmtClass:
22500b57cec5SDimitry Andric       return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric     case Stmt::ExprWithCleanupsClass:
2253a7dea167SDimitry Andric       return VisitExprWithCleanups(cast<ExprWithCleanups>(S),
2254a7dea167SDimitry Andric                                    asc, ExternallyDestructed);
22550b57cec5SDimitry Andric 
22560b57cec5SDimitry Andric     case Stmt::CXXDefaultArgExprClass:
22570b57cec5SDimitry Andric     case Stmt::CXXDefaultInitExprClass:
22580b57cec5SDimitry Andric       // FIXME: The expression inside a CXXDefaultArgExpr is owned by the
22590b57cec5SDimitry Andric       // called function's declaration, not by the caller. If we simply add
22600b57cec5SDimitry Andric       // this expression to the CFG, we could end up with the same Expr
22615f757f3fSDimitry Andric       // appearing multiple times (PR13385).
22620b57cec5SDimitry Andric       //
22630b57cec5SDimitry Andric       // It's likewise possible for multiple CXXDefaultInitExprs for the same
22640b57cec5SDimitry Andric       // expression to be used in the same function (through aggregate
22650b57cec5SDimitry Andric       // initialization).
22660b57cec5SDimitry Andric       return VisitStmt(S, asc);
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric     case Stmt::CXXBindTemporaryExprClass:
22690b57cec5SDimitry Andric       return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
22700b57cec5SDimitry Andric 
22710b57cec5SDimitry Andric     case Stmt::CXXConstructExprClass:
22720b57cec5SDimitry Andric       return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric     case Stmt::CXXNewExprClass:
22750b57cec5SDimitry Andric       return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);
22760b57cec5SDimitry Andric 
22770b57cec5SDimitry Andric     case Stmt::CXXDeleteExprClass:
22780b57cec5SDimitry Andric       return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric     case Stmt::CXXFunctionalCastExprClass:
22810b57cec5SDimitry Andric       return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);
22820b57cec5SDimitry Andric 
22830b57cec5SDimitry Andric     case Stmt::CXXTemporaryObjectExprClass:
22840b57cec5SDimitry Andric       return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric     case Stmt::CXXThrowExprClass:
22870b57cec5SDimitry Andric       return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric     case Stmt::CXXTryStmtClass:
22900b57cec5SDimitry Andric       return VisitCXXTryStmt(cast<CXXTryStmt>(S));
22910b57cec5SDimitry Andric 
229281ad6265SDimitry Andric     case Stmt::CXXTypeidExprClass:
229381ad6265SDimitry Andric       return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);
229481ad6265SDimitry Andric 
22950b57cec5SDimitry Andric     case Stmt::CXXForRangeStmtClass:
22960b57cec5SDimitry Andric       return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric     case Stmt::DeclStmtClass:
22990b57cec5SDimitry Andric       return VisitDeclStmt(cast<DeclStmt>(S));
23000b57cec5SDimitry Andric 
23010b57cec5SDimitry Andric     case Stmt::DefaultStmtClass:
23020b57cec5SDimitry Andric       return VisitDefaultStmt(cast<DefaultStmt>(S));
23030b57cec5SDimitry Andric 
23040b57cec5SDimitry Andric     case Stmt::DoStmtClass:
23050b57cec5SDimitry Andric       return VisitDoStmt(cast<DoStmt>(S));
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric     case Stmt::ForStmtClass:
23080b57cec5SDimitry Andric       return VisitForStmt(cast<ForStmt>(S));
23090b57cec5SDimitry Andric 
23100b57cec5SDimitry Andric     case Stmt::GotoStmtClass:
23110b57cec5SDimitry Andric       return VisitGotoStmt(cast<GotoStmt>(S));
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric     case Stmt::GCCAsmStmtClass:
23140b57cec5SDimitry Andric       return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);
23150b57cec5SDimitry Andric 
23160b57cec5SDimitry Andric     case Stmt::IfStmtClass:
23170b57cec5SDimitry Andric       return VisitIfStmt(cast<IfStmt>(S));
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric     case Stmt::ImplicitCastExprClass:
23200b57cec5SDimitry Andric       return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric     case Stmt::ConstantExprClass:
23230b57cec5SDimitry Andric       return VisitConstantExpr(cast<ConstantExpr>(S), asc);
23240b57cec5SDimitry Andric 
23250b57cec5SDimitry Andric     case Stmt::IndirectGotoStmtClass:
23260b57cec5SDimitry Andric       return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
23270b57cec5SDimitry Andric 
23280b57cec5SDimitry Andric     case Stmt::LabelStmtClass:
23290b57cec5SDimitry Andric       return VisitLabelStmt(cast<LabelStmt>(S));
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric     case Stmt::LambdaExprClass:
23320b57cec5SDimitry Andric       return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric     case Stmt::MaterializeTemporaryExprClass:
23350b57cec5SDimitry Andric       return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),
23360b57cec5SDimitry Andric                                            asc);
23370b57cec5SDimitry Andric 
23380b57cec5SDimitry Andric     case Stmt::MemberExprClass:
23390b57cec5SDimitry Andric       return VisitMemberExpr(cast<MemberExpr>(S), asc);
23400b57cec5SDimitry Andric 
23410b57cec5SDimitry Andric     case Stmt::NullStmtClass:
23420b57cec5SDimitry Andric       return Block;
23430b57cec5SDimitry Andric 
23440b57cec5SDimitry Andric     case Stmt::ObjCAtCatchStmtClass:
23450b57cec5SDimitry Andric       return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric     case Stmt::ObjCAutoreleasePoolStmtClass:
23480b57cec5SDimitry Andric       return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric     case Stmt::ObjCAtSynchronizedStmtClass:
23510b57cec5SDimitry Andric       return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric     case Stmt::ObjCAtThrowStmtClass:
23540b57cec5SDimitry Andric       return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
23550b57cec5SDimitry Andric 
23560b57cec5SDimitry Andric     case Stmt::ObjCAtTryStmtClass:
23570b57cec5SDimitry Andric       return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric     case Stmt::ObjCForCollectionStmtClass:
23600b57cec5SDimitry Andric       return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
23610b57cec5SDimitry Andric 
23620b57cec5SDimitry Andric     case Stmt::ObjCMessageExprClass:
23630b57cec5SDimitry Andric       return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric     case Stmt::OpaqueValueExprClass:
23660b57cec5SDimitry Andric       return Block;
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric     case Stmt::PseudoObjectExprClass:
23690b57cec5SDimitry Andric       return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));
23700b57cec5SDimitry Andric 
23710b57cec5SDimitry Andric     case Stmt::ReturnStmtClass:
23720b57cec5SDimitry Andric     case Stmt::CoreturnStmtClass:
23730b57cec5SDimitry Andric       return VisitReturnStmt(S);
23740b57cec5SDimitry Andric 
237581ad6265SDimitry Andric     case Stmt::CoyieldExprClass:
237681ad6265SDimitry Andric     case Stmt::CoawaitExprClass:
237781ad6265SDimitry Andric       return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);
237881ad6265SDimitry Andric 
23790b57cec5SDimitry Andric     case Stmt::SEHExceptStmtClass:
23800b57cec5SDimitry Andric       return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));
23810b57cec5SDimitry Andric 
23820b57cec5SDimitry Andric     case Stmt::SEHFinallyStmtClass:
23830b57cec5SDimitry Andric       return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));
23840b57cec5SDimitry Andric 
23850b57cec5SDimitry Andric     case Stmt::SEHLeaveStmtClass:
23860b57cec5SDimitry Andric       return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));
23870b57cec5SDimitry Andric 
23880b57cec5SDimitry Andric     case Stmt::SEHTryStmtClass:
23890b57cec5SDimitry Andric       return VisitSEHTryStmt(cast<SEHTryStmt>(S));
23900b57cec5SDimitry Andric 
23910b57cec5SDimitry Andric     case Stmt::UnaryExprOrTypeTraitExprClass:
23920b57cec5SDimitry Andric       return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
23930b57cec5SDimitry Andric                                            asc);
23940b57cec5SDimitry Andric 
23950b57cec5SDimitry Andric     case Stmt::StmtExprClass:
23960b57cec5SDimitry Andric       return VisitStmtExpr(cast<StmtExpr>(S), asc);
23970b57cec5SDimitry Andric 
23980b57cec5SDimitry Andric     case Stmt::SwitchStmtClass:
23990b57cec5SDimitry Andric       return VisitSwitchStmt(cast<SwitchStmt>(S));
24000b57cec5SDimitry Andric 
24010b57cec5SDimitry Andric     case Stmt::UnaryOperatorClass:
24020b57cec5SDimitry Andric       return VisitUnaryOperator(cast<UnaryOperator>(S), asc);
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
24050b57cec5SDimitry Andric       return VisitWhileStmt(cast<WhileStmt>(S));
240681ad6265SDimitry Andric 
240781ad6265SDimitry Andric     case Stmt::ArrayInitLoopExprClass:
240881ad6265SDimitry Andric       return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);
24090b57cec5SDimitry Andric   }
24100b57cec5SDimitry Andric }
24110b57cec5SDimitry Andric 
24120b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
24130b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, S)) {
24140b57cec5SDimitry Andric     autoCreateBlock();
24150b57cec5SDimitry Andric     appendStmt(Block, S);
24160b57cec5SDimitry Andric   }
24170b57cec5SDimitry Andric 
24180b57cec5SDimitry Andric   return VisitChildren(S);
24190b57cec5SDimitry Andric }
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric /// VisitChildren - Visit the children of a Stmt.
24220b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
24230b57cec5SDimitry Andric   CFGBlock *B = Block;
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   // Visit the children in their reverse order so that they appear in
24260b57cec5SDimitry Andric   // left-to-right (natural) order in the CFG.
24270b57cec5SDimitry Andric   reverse_children RChildren(S);
2428480093f4SDimitry Andric   for (Stmt *Child : RChildren) {
2429480093f4SDimitry Andric     if (Child)
24300b57cec5SDimitry Andric       if (CFGBlock *R = Visit(Child))
24310b57cec5SDimitry Andric         B = R;
24320b57cec5SDimitry Andric   }
24330b57cec5SDimitry Andric   return B;
24340b57cec5SDimitry Andric }
24350b57cec5SDimitry Andric 
2436480093f4SDimitry Andric CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
2437480093f4SDimitry Andric   if (asc.alwaysAdd(*this, ILE)) {
2438480093f4SDimitry Andric     autoCreateBlock();
2439480093f4SDimitry Andric     appendStmt(Block, ILE);
2440480093f4SDimitry Andric   }
2441480093f4SDimitry Andric   CFGBlock *B = Block;
2442480093f4SDimitry Andric 
2443480093f4SDimitry Andric   reverse_children RChildren(ILE);
2444480093f4SDimitry Andric   for (Stmt *Child : RChildren) {
2445480093f4SDimitry Andric     if (!Child)
2446480093f4SDimitry Andric       continue;
2447480093f4SDimitry Andric     if (CFGBlock *R = Visit(Child))
2448480093f4SDimitry Andric       B = R;
2449480093f4SDimitry Andric     if (BuildOpts.AddCXXDefaultInitExprInAggregates) {
2450480093f4SDimitry Andric       if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
2451480093f4SDimitry Andric         if (Stmt *Child = DIE->getExpr())
2452480093f4SDimitry Andric           if (CFGBlock *R = Visit(Child))
2453480093f4SDimitry Andric             B = R;
2454480093f4SDimitry Andric     }
2455480093f4SDimitry Andric   }
2456480093f4SDimitry Andric   return B;
2457480093f4SDimitry Andric }
2458480093f4SDimitry Andric 
24590b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
24600b57cec5SDimitry Andric                                          AddStmtChoice asc) {
24610b57cec5SDimitry Andric   AddressTakenLabels.insert(A->getLabel());
24620b57cec5SDimitry Andric 
24630b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, A)) {
24640b57cec5SDimitry Andric     autoCreateBlock();
24650b57cec5SDimitry Andric     appendStmt(Block, A);
24660b57cec5SDimitry Andric   }
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric   return Block;
24690b57cec5SDimitry Andric }
24700b57cec5SDimitry Andric 
2471349cc55cSDimitry Andric static bool isFallthroughStatement(const AttributedStmt *A) {
2472349cc55cSDimitry Andric   bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->getAttrs());
2473349cc55cSDimitry Andric   assert((!isFallthrough || isa<NullStmt>(A->getSubStmt())) &&
2474349cc55cSDimitry Andric          "expected fallthrough not to have children");
2475349cc55cSDimitry Andric   return isFallthrough;
2476349cc55cSDimitry Andric }
2477349cc55cSDimitry Andric 
2478349cc55cSDimitry Andric CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
24790b57cec5SDimitry Andric                                           AddStmtChoice asc) {
2480349cc55cSDimitry Andric   // AttributedStmts for [[likely]] can have arbitrary statements as children,
2481349cc55cSDimitry Andric   // and the current visitation order here would add the AttributedStmts
2482349cc55cSDimitry Andric   // for [[likely]] after the child nodes, which is undesirable: For example,
2483349cc55cSDimitry Andric   // if the child contains an unconditional return, the [[likely]] would be
2484349cc55cSDimitry Andric   // considered unreachable.
2485349cc55cSDimitry Andric   // So only add the AttributedStmt for FallThrough, which has CFG effects and
2486349cc55cSDimitry Andric   // also no children, and omit the others. None of the other current StmtAttrs
2487349cc55cSDimitry Andric   // have semantic meaning for the CFG.
2488349cc55cSDimitry Andric   if (isFallthroughStatement(A) && asc.alwaysAdd(*this, A)) {
2489349cc55cSDimitry Andric     autoCreateBlock();
2490349cc55cSDimitry Andric     appendStmt(Block, A);
2491349cc55cSDimitry Andric   }
2492349cc55cSDimitry Andric 
2493349cc55cSDimitry Andric   return VisitChildren(A);
2494349cc55cSDimitry Andric }
2495349cc55cSDimitry Andric 
2496349cc55cSDimitry Andric CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {
24970b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, U)) {
24980b57cec5SDimitry Andric     autoCreateBlock();
24990b57cec5SDimitry Andric     appendStmt(Block, U);
25000b57cec5SDimitry Andric   }
25010b57cec5SDimitry Andric 
2502a7dea167SDimitry Andric   if (U->getOpcode() == UO_LNot)
2503a7dea167SDimitry Andric     tryEvaluateBool(U->getSubExpr()->IgnoreParens());
2504a7dea167SDimitry Andric 
25050b57cec5SDimitry Andric   return Visit(U->getSubExpr(), AddStmtChoice());
25060b57cec5SDimitry Andric }
25070b57cec5SDimitry Andric 
25080b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {
25090b57cec5SDimitry Andric   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
25100b57cec5SDimitry Andric   appendStmt(ConfluenceBlock, B);
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric   if (badCFG)
25130b57cec5SDimitry Andric     return nullptr;
25140b57cec5SDimitry Andric 
25150b57cec5SDimitry Andric   return VisitLogicalOperator(B, nullptr, ConfluenceBlock,
25160b57cec5SDimitry Andric                               ConfluenceBlock).first;
25170b57cec5SDimitry Andric }
25180b57cec5SDimitry Andric 
25190b57cec5SDimitry Andric std::pair<CFGBlock*, CFGBlock*>
25200b57cec5SDimitry Andric CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
25210b57cec5SDimitry Andric                                  Stmt *Term,
25220b57cec5SDimitry Andric                                  CFGBlock *TrueBlock,
25230b57cec5SDimitry Andric                                  CFGBlock *FalseBlock) {
25240b57cec5SDimitry Andric   // Introspect the RHS.  If it is a nested logical operation, we recursively
25250b57cec5SDimitry Andric   // build the CFG using this function.  Otherwise, resort to default
25260b57cec5SDimitry Andric   // CFG construction behavior.
25270b57cec5SDimitry Andric   Expr *RHS = B->getRHS()->IgnoreParens();
25280b57cec5SDimitry Andric   CFGBlock *RHSBlock, *ExitBlock;
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric   do {
25310b57cec5SDimitry Andric     if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))
25320b57cec5SDimitry Andric       if (B_RHS->isLogicalOp()) {
25330b57cec5SDimitry Andric         std::tie(RHSBlock, ExitBlock) =
25340b57cec5SDimitry Andric           VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);
25350b57cec5SDimitry Andric         break;
25360b57cec5SDimitry Andric       }
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric     // The RHS is not a nested logical operation.  Don't push the terminator
25390b57cec5SDimitry Andric     // down further, but instead visit RHS and construct the respective
25400b57cec5SDimitry Andric     // pieces of the CFG, and link up the RHSBlock with the terminator
25410b57cec5SDimitry Andric     // we have been provided.
25420b57cec5SDimitry Andric     ExitBlock = RHSBlock = createBlock(false);
25430b57cec5SDimitry Andric 
25440b57cec5SDimitry Andric     // Even though KnownVal is only used in the else branch of the next
25450b57cec5SDimitry Andric     // conditional, tryEvaluateBool performs additional checking on the
25460b57cec5SDimitry Andric     // Expr, so it should be called unconditionally.
25470b57cec5SDimitry Andric     TryResult KnownVal = tryEvaluateBool(RHS);
25480b57cec5SDimitry Andric     if (!KnownVal.isKnown())
25490b57cec5SDimitry Andric       KnownVal = tryEvaluateBool(B);
25500b57cec5SDimitry Andric 
25510b57cec5SDimitry Andric     if (!Term) {
25520b57cec5SDimitry Andric       assert(TrueBlock == FalseBlock);
25530b57cec5SDimitry Andric       addSuccessor(RHSBlock, TrueBlock);
25540b57cec5SDimitry Andric     }
25550b57cec5SDimitry Andric     else {
25560b57cec5SDimitry Andric       RHSBlock->setTerminator(Term);
25570b57cec5SDimitry Andric       addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());
25580b57cec5SDimitry Andric       addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());
25590b57cec5SDimitry Andric     }
25600b57cec5SDimitry Andric 
25610b57cec5SDimitry Andric     Block = RHSBlock;
25620b57cec5SDimitry Andric     RHSBlock = addStmt(RHS);
25630b57cec5SDimitry Andric   }
25640b57cec5SDimitry Andric   while (false);
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric   if (badCFG)
25670b57cec5SDimitry Andric     return std::make_pair(nullptr, nullptr);
25680b57cec5SDimitry Andric 
25690b57cec5SDimitry Andric   // Generate the blocks for evaluating the LHS.
25700b57cec5SDimitry Andric   Expr *LHS = B->getLHS()->IgnoreParens();
25710b57cec5SDimitry Andric 
25720b57cec5SDimitry Andric   if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))
25730b57cec5SDimitry Andric     if (B_LHS->isLogicalOp()) {
25740b57cec5SDimitry Andric       if (B->getOpcode() == BO_LOr)
25750b57cec5SDimitry Andric         FalseBlock = RHSBlock;
25760b57cec5SDimitry Andric       else
25770b57cec5SDimitry Andric         TrueBlock = RHSBlock;
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric       // For the LHS, treat 'B' as the terminator that we want to sink
25800b57cec5SDimitry Andric       // into the nested branch.  The RHS always gets the top-most
25810b57cec5SDimitry Andric       // terminator.
25820b57cec5SDimitry Andric       return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);
25830b57cec5SDimitry Andric     }
25840b57cec5SDimitry Andric 
25850b57cec5SDimitry Andric   // Create the block evaluating the LHS.
25860b57cec5SDimitry Andric   // This contains the '&&' or '||' as the terminator.
25870b57cec5SDimitry Andric   CFGBlock *LHSBlock = createBlock(false);
25880b57cec5SDimitry Andric   LHSBlock->setTerminator(B);
25890b57cec5SDimitry Andric 
25900b57cec5SDimitry Andric   Block = LHSBlock;
25910b57cec5SDimitry Andric   CFGBlock *EntryLHSBlock = addStmt(LHS);
25920b57cec5SDimitry Andric 
25930b57cec5SDimitry Andric   if (badCFG)
25940b57cec5SDimitry Andric     return std::make_pair(nullptr, nullptr);
25950b57cec5SDimitry Andric 
25960b57cec5SDimitry Andric   // See if this is a known constant.
25970b57cec5SDimitry Andric   TryResult KnownVal = tryEvaluateBool(LHS);
25980b57cec5SDimitry Andric 
25990b57cec5SDimitry Andric   // Now link the LHSBlock with RHSBlock.
26000b57cec5SDimitry Andric   if (B->getOpcode() == BO_LOr) {
26010b57cec5SDimitry Andric     addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());
26020b57cec5SDimitry Andric     addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());
26030b57cec5SDimitry Andric   } else {
26040b57cec5SDimitry Andric     assert(B->getOpcode() == BO_LAnd);
26050b57cec5SDimitry Andric     addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());
26060b57cec5SDimitry Andric     addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());
26070b57cec5SDimitry Andric   }
26080b57cec5SDimitry Andric 
26090b57cec5SDimitry Andric   return std::make_pair(EntryLHSBlock, ExitBlock);
26100b57cec5SDimitry Andric }
26110b57cec5SDimitry Andric 
26120b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
26130b57cec5SDimitry Andric                                           AddStmtChoice asc) {
26140b57cec5SDimitry Andric    // && or ||
26150b57cec5SDimitry Andric   if (B->isLogicalOp())
26160b57cec5SDimitry Andric     return VisitLogicalOperator(B);
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric   if (B->getOpcode() == BO_Comma) { // ,
26190b57cec5SDimitry Andric     autoCreateBlock();
26200b57cec5SDimitry Andric     appendStmt(Block, B);
26210b57cec5SDimitry Andric     addStmt(B->getRHS());
26220b57cec5SDimitry Andric     return addStmt(B->getLHS());
26230b57cec5SDimitry Andric   }
26240b57cec5SDimitry Andric 
26250b57cec5SDimitry Andric   if (B->isAssignmentOp()) {
26260b57cec5SDimitry Andric     if (asc.alwaysAdd(*this, B)) {
26270b57cec5SDimitry Andric       autoCreateBlock();
26280b57cec5SDimitry Andric       appendStmt(Block, B);
26290b57cec5SDimitry Andric     }
26300b57cec5SDimitry Andric     Visit(B->getLHS());
26310b57cec5SDimitry Andric     return Visit(B->getRHS());
26320b57cec5SDimitry Andric   }
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, B)) {
26350b57cec5SDimitry Andric     autoCreateBlock();
26360b57cec5SDimitry Andric     appendStmt(Block, B);
26370b57cec5SDimitry Andric   }
26380b57cec5SDimitry Andric 
2639a7dea167SDimitry Andric   if (B->isEqualityOp() || B->isRelationalOp())
2640a7dea167SDimitry Andric     tryEvaluateBool(B);
2641a7dea167SDimitry Andric 
26420b57cec5SDimitry Andric   CFGBlock *RBlock = Visit(B->getRHS());
26430b57cec5SDimitry Andric   CFGBlock *LBlock = Visit(B->getLHS());
26440b57cec5SDimitry Andric   // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr
26450b57cec5SDimitry Andric   // containing a DoStmt, and the LHS doesn't create a new block, then we should
26460b57cec5SDimitry Andric   // return RBlock.  Otherwise we'll incorrectly return NULL.
26470b57cec5SDimitry Andric   return (LBlock ? LBlock : RBlock);
26480b57cec5SDimitry Andric }
26490b57cec5SDimitry Andric 
26500b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {
26510b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
26520b57cec5SDimitry Andric     autoCreateBlock();
26530b57cec5SDimitry Andric     appendStmt(Block, E);
26540b57cec5SDimitry Andric   }
26550b57cec5SDimitry Andric   return Block;
26560b57cec5SDimitry Andric }
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
26590b57cec5SDimitry Andric   // "break" is a control-flow statement.  Thus we stop processing the current
26600b57cec5SDimitry Andric   // block.
26610b57cec5SDimitry Andric   if (badCFG)
26620b57cec5SDimitry Andric     return nullptr;
26630b57cec5SDimitry Andric 
26640b57cec5SDimitry Andric   // Now create a new block that ends with the break statement.
26650b57cec5SDimitry Andric   Block = createBlock(false);
26660b57cec5SDimitry Andric   Block->setTerminator(B);
26670b57cec5SDimitry Andric 
26680b57cec5SDimitry Andric   // If there is no target for the break, then we are looking at an incomplete
26690b57cec5SDimitry Andric   // AST.  This means that the CFG cannot be constructed.
26700b57cec5SDimitry Andric   if (BreakJumpTarget.block) {
26710b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);
26720b57cec5SDimitry Andric     addSuccessor(Block, BreakJumpTarget.block);
26730b57cec5SDimitry Andric   } else
26740b57cec5SDimitry Andric     badCFG = true;
26750b57cec5SDimitry Andric 
26760b57cec5SDimitry Andric   return Block;
26770b57cec5SDimitry Andric }
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric static bool CanThrow(Expr *E, ASTContext &Ctx) {
26800b57cec5SDimitry Andric   QualType Ty = E->getType();
2681a7dea167SDimitry Andric   if (Ty->isFunctionPointerType() || Ty->isBlockPointerType())
2682a7dea167SDimitry Andric     Ty = Ty->getPointeeType();
26830b57cec5SDimitry Andric 
26840b57cec5SDimitry Andric   const FunctionType *FT = Ty->getAs<FunctionType>();
26850b57cec5SDimitry Andric   if (FT) {
26860b57cec5SDimitry Andric     if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
26870b57cec5SDimitry Andric       if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&
26880b57cec5SDimitry Andric           Proto->isNothrow())
26890b57cec5SDimitry Andric         return false;
26900b57cec5SDimitry Andric   }
26910b57cec5SDimitry Andric   return true;
26920b57cec5SDimitry Andric }
26930b57cec5SDimitry Andric 
26940b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
26950b57cec5SDimitry Andric   // Compute the callee type.
26960b57cec5SDimitry Andric   QualType calleeType = C->getCallee()->getType();
26970b57cec5SDimitry Andric   if (calleeType == Context->BoundMemberTy) {
26980b57cec5SDimitry Andric     QualType boundType = Expr::findBoundMemberType(C->getCallee());
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric     // We should only get a null bound type if processing a dependent
27010b57cec5SDimitry Andric     // CFG.  Recover by assuming nothing.
27020b57cec5SDimitry Andric     if (!boundType.isNull()) calleeType = boundType;
27030b57cec5SDimitry Andric   }
27040b57cec5SDimitry Andric 
27050b57cec5SDimitry Andric   // If this is a call to a no-return function, this stops the block here.
27060b57cec5SDimitry Andric   bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
27070b57cec5SDimitry Andric 
27080b57cec5SDimitry Andric   bool AddEHEdge = false;
27090b57cec5SDimitry Andric 
27100b57cec5SDimitry Andric   // Languages without exceptions are assumed to not throw.
27110b57cec5SDimitry Andric   if (Context->getLangOpts().Exceptions) {
27120b57cec5SDimitry Andric     if (BuildOpts.AddEHEdges)
27130b57cec5SDimitry Andric       AddEHEdge = true;
27140b57cec5SDimitry Andric   }
27150b57cec5SDimitry Andric 
27160b57cec5SDimitry Andric   // If this is a call to a builtin function, it might not actually evaluate
27170b57cec5SDimitry Andric   // its arguments. Don't add them to the CFG if this is the case.
27180b57cec5SDimitry Andric   bool OmitArguments = false;
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric   if (FunctionDecl *FD = C->getDirectCallee()) {
27210b57cec5SDimitry Andric     // TODO: Support construction contexts for variadic function arguments.
27220b57cec5SDimitry Andric     // These are a bit problematic and not very useful because passing
27230b57cec5SDimitry Andric     // C++ objects as C-style variadic arguments doesn't work in general
27240b57cec5SDimitry Andric     // (see [expr.call]).
27250b57cec5SDimitry Andric     if (!FD->isVariadic())
27260b57cec5SDimitry Andric       findConstructionContextsForArguments(C);
27270b57cec5SDimitry Andric 
27280b57cec5SDimitry Andric     if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))
27290b57cec5SDimitry Andric       NoReturn = true;
27300b57cec5SDimitry Andric     if (FD->hasAttr<NoThrowAttr>())
27310b57cec5SDimitry Andric       AddEHEdge = false;
27320b57cec5SDimitry Andric     if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||
27330b57cec5SDimitry Andric         FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)
27340b57cec5SDimitry Andric       OmitArguments = true;
27350b57cec5SDimitry Andric   }
27360b57cec5SDimitry Andric 
27370b57cec5SDimitry Andric   if (!CanThrow(C->getCallee(), *Context))
27380b57cec5SDimitry Andric     AddEHEdge = false;
27390b57cec5SDimitry Andric 
27400b57cec5SDimitry Andric   if (OmitArguments) {
27410b57cec5SDimitry Andric     assert(!NoReturn && "noreturn calls with unevaluated args not implemented");
27420b57cec5SDimitry Andric     assert(!AddEHEdge && "EH calls with unevaluated args not implemented");
27430b57cec5SDimitry Andric     autoCreateBlock();
27440b57cec5SDimitry Andric     appendStmt(Block, C);
27450b57cec5SDimitry Andric     return Visit(C->getCallee());
27460b57cec5SDimitry Andric   }
27470b57cec5SDimitry Andric 
27480b57cec5SDimitry Andric   if (!NoReturn && !AddEHEdge) {
27490b57cec5SDimitry Andric     autoCreateBlock();
27500b57cec5SDimitry Andric     appendCall(Block, C);
27510b57cec5SDimitry Andric 
27520b57cec5SDimitry Andric     return VisitChildren(C);
27530b57cec5SDimitry Andric   }
27540b57cec5SDimitry Andric 
27550b57cec5SDimitry Andric   if (Block) {
27560b57cec5SDimitry Andric     Succ = Block;
27570b57cec5SDimitry Andric     if (badCFG)
27580b57cec5SDimitry Andric       return nullptr;
27590b57cec5SDimitry Andric   }
27600b57cec5SDimitry Andric 
27610b57cec5SDimitry Andric   if (NoReturn)
27620b57cec5SDimitry Andric     Block = createNoReturnBlock();
27630b57cec5SDimitry Andric   else
27640b57cec5SDimitry Andric     Block = createBlock();
27650b57cec5SDimitry Andric 
27660b57cec5SDimitry Andric   appendCall(Block, C);
27670b57cec5SDimitry Andric 
27680b57cec5SDimitry Andric   if (AddEHEdge) {
27690b57cec5SDimitry Andric     // Add exceptional edges.
27700b57cec5SDimitry Andric     if (TryTerminatedBlock)
27710b57cec5SDimitry Andric       addSuccessor(Block, TryTerminatedBlock);
27720b57cec5SDimitry Andric     else
27730b57cec5SDimitry Andric       addSuccessor(Block, &cfg->getExit());
27740b57cec5SDimitry Andric   }
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric   return VisitChildren(C);
27770b57cec5SDimitry Andric }
27780b57cec5SDimitry Andric 
27790b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
27800b57cec5SDimitry Andric                                       AddStmtChoice asc) {
27810b57cec5SDimitry Andric   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
27820b57cec5SDimitry Andric   appendStmt(ConfluenceBlock, C);
27830b57cec5SDimitry Andric   if (badCFG)
27840b57cec5SDimitry Andric     return nullptr;
27850b57cec5SDimitry Andric 
27860b57cec5SDimitry Andric   AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
27870b57cec5SDimitry Andric   Succ = ConfluenceBlock;
27880b57cec5SDimitry Andric   Block = nullptr;
27890b57cec5SDimitry Andric   CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);
27900b57cec5SDimitry Andric   if (badCFG)
27910b57cec5SDimitry Andric     return nullptr;
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric   Succ = ConfluenceBlock;
27940b57cec5SDimitry Andric   Block = nullptr;
27950b57cec5SDimitry Andric   CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);
27960b57cec5SDimitry Andric   if (badCFG)
27970b57cec5SDimitry Andric     return nullptr;
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   Block = createBlock(false);
28000b57cec5SDimitry Andric   // See if this is a known constant.
28010b57cec5SDimitry Andric   const TryResult& KnownVal = tryEvaluateBool(C->getCond());
28020b57cec5SDimitry Andric   addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);
28030b57cec5SDimitry Andric   addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);
28040b57cec5SDimitry Andric   Block->setTerminator(C);
28050b57cec5SDimitry Andric   return addStmt(C->getCond());
28060b57cec5SDimitry Andric }
28070b57cec5SDimitry Andric 
2808349cc55cSDimitry Andric CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,
2809349cc55cSDimitry Andric                                         bool ExternallyDestructed) {
28100b57cec5SDimitry Andric   LocalScope::const_iterator scopeBeginPos = ScopePos;
28110b57cec5SDimitry Andric   addLocalScopeForStmt(C);
28120b57cec5SDimitry Andric 
28130b57cec5SDimitry Andric   if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
28140b57cec5SDimitry Andric     // If the body ends with a ReturnStmt, the dtors will be added in
28150b57cec5SDimitry Andric     // VisitReturnStmt.
28160b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, scopeBeginPos, C);
28170b57cec5SDimitry Andric   }
28180b57cec5SDimitry Andric 
28190b57cec5SDimitry Andric   CFGBlock *LastBlock = Block;
28200b57cec5SDimitry Andric 
2821349cc55cSDimitry Andric   for (Stmt *S : llvm::reverse(C->body())) {
28220b57cec5SDimitry Andric     // If we hit a segment of code just containing ';' (NullStmts), we can
28230b57cec5SDimitry Andric     // get a null block back.  In such cases, just use the LastBlock
2824349cc55cSDimitry Andric     CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,
2825a7dea167SDimitry Andric                                ExternallyDestructed);
2826a7dea167SDimitry Andric 
2827a7dea167SDimitry Andric     if (newBlock)
28280b57cec5SDimitry Andric       LastBlock = newBlock;
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric     if (badCFG)
28310b57cec5SDimitry Andric       return nullptr;
2832a7dea167SDimitry Andric 
2833a7dea167SDimitry Andric     ExternallyDestructed = false;
28340b57cec5SDimitry Andric   }
28350b57cec5SDimitry Andric 
28360b57cec5SDimitry Andric   return LastBlock;
28370b57cec5SDimitry Andric }
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
28400b57cec5SDimitry Andric                                                AddStmtChoice asc) {
28410b57cec5SDimitry Andric   const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);
28420b57cec5SDimitry Andric   const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);
28430b57cec5SDimitry Andric 
28440b57cec5SDimitry Andric   // Create the confluence block that will "merge" the results of the ternary
28450b57cec5SDimitry Andric   // expression.
28460b57cec5SDimitry Andric   CFGBlock *ConfluenceBlock = Block ? Block : createBlock();
28470b57cec5SDimitry Andric   appendStmt(ConfluenceBlock, C);
28480b57cec5SDimitry Andric   if (badCFG)
28490b57cec5SDimitry Andric     return nullptr;
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric   AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);
28520b57cec5SDimitry Andric 
28530b57cec5SDimitry Andric   // Create a block for the LHS expression if there is an LHS expression.  A
28540b57cec5SDimitry Andric   // GCC extension allows LHS to be NULL, causing the condition to be the
28550b57cec5SDimitry Andric   // value that is returned instead.
28560b57cec5SDimitry Andric   //  e.g: x ?: y is shorthand for: x ? x : y;
28570b57cec5SDimitry Andric   Succ = ConfluenceBlock;
28580b57cec5SDimitry Andric   Block = nullptr;
28590b57cec5SDimitry Andric   CFGBlock *LHSBlock = nullptr;
28600b57cec5SDimitry Andric   const Expr *trueExpr = C->getTrueExpr();
28610b57cec5SDimitry Andric   if (trueExpr != opaqueValue) {
28620b57cec5SDimitry Andric     LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);
28630b57cec5SDimitry Andric     if (badCFG)
28640b57cec5SDimitry Andric       return nullptr;
28650b57cec5SDimitry Andric     Block = nullptr;
28660b57cec5SDimitry Andric   }
28670b57cec5SDimitry Andric   else
28680b57cec5SDimitry Andric     LHSBlock = ConfluenceBlock;
28690b57cec5SDimitry Andric 
28700b57cec5SDimitry Andric   // Create the block for the RHS expression.
28710b57cec5SDimitry Andric   Succ = ConfluenceBlock;
28720b57cec5SDimitry Andric   CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);
28730b57cec5SDimitry Andric   if (badCFG)
28740b57cec5SDimitry Andric     return nullptr;
28750b57cec5SDimitry Andric 
28760b57cec5SDimitry Andric   // If the condition is a logical '&&' or '||', build a more accurate CFG.
28770b57cec5SDimitry Andric   if (BinaryOperator *Cond =
28780b57cec5SDimitry Andric         dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens()))
28790b57cec5SDimitry Andric     if (Cond->isLogicalOp())
28800b57cec5SDimitry Andric       return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric   // Create the block that will contain the condition.
28830b57cec5SDimitry Andric   Block = createBlock(false);
28840b57cec5SDimitry Andric 
28850b57cec5SDimitry Andric   // See if this is a known constant.
28860b57cec5SDimitry Andric   const TryResult& KnownVal = tryEvaluateBool(C->getCond());
28870b57cec5SDimitry Andric   addSuccessor(Block, LHSBlock, !KnownVal.isFalse());
28880b57cec5SDimitry Andric   addSuccessor(Block, RHSBlock, !KnownVal.isTrue());
28890b57cec5SDimitry Andric   Block->setTerminator(C);
28900b57cec5SDimitry Andric   Expr *condExpr = C->getCond();
28910b57cec5SDimitry Andric 
28920b57cec5SDimitry Andric   if (opaqueValue) {
28930b57cec5SDimitry Andric     // Run the condition expression if it's not trivially expressed in
28940b57cec5SDimitry Andric     // terms of the opaque value (or if there is no opaque value).
28950b57cec5SDimitry Andric     if (condExpr != opaqueValue)
28960b57cec5SDimitry Andric       addStmt(condExpr);
28970b57cec5SDimitry Andric 
28980b57cec5SDimitry Andric     // Before that, run the common subexpression if there was one.
28990b57cec5SDimitry Andric     // At least one of this or the above will be run.
29000b57cec5SDimitry Andric     return addStmt(BCO->getCommon());
29010b57cec5SDimitry Andric   }
29020b57cec5SDimitry Andric 
29030b57cec5SDimitry Andric   return addStmt(condExpr);
29040b57cec5SDimitry Andric }
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
29070b57cec5SDimitry Andric   // Check if the Decl is for an __label__.  If so, elide it from the
29080b57cec5SDimitry Andric   // CFG entirely.
29090b57cec5SDimitry Andric   if (isa<LabelDecl>(*DS->decl_begin()))
29100b57cec5SDimitry Andric     return Block;
29110b57cec5SDimitry Andric 
29120b57cec5SDimitry Andric   // This case also handles static_asserts.
29130b57cec5SDimitry Andric   if (DS->isSingleDecl())
29140b57cec5SDimitry Andric     return VisitDeclSubExpr(DS);
29150b57cec5SDimitry Andric 
29160b57cec5SDimitry Andric   CFGBlock *B = nullptr;
29170b57cec5SDimitry Andric 
29180b57cec5SDimitry Andric   // Build an individual DeclStmt for each decl.
29190b57cec5SDimitry Andric   for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),
29200b57cec5SDimitry Andric                                        E = DS->decl_rend();
29210b57cec5SDimitry Andric        I != E; ++I) {
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric     // Allocate the DeclStmt using the BumpPtrAllocator.  It will get
29240b57cec5SDimitry Andric     // automatically freed with the CFG.
29250b57cec5SDimitry Andric     DeclGroupRef DG(*I);
29260b57cec5SDimitry Andric     Decl *D = *I;
29270b57cec5SDimitry Andric     DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
29280b57cec5SDimitry Andric     cfg->addSyntheticDeclStmt(DSNew, DS);
29290b57cec5SDimitry Andric 
29300b57cec5SDimitry Andric     // Append the fake DeclStmt to block.
29310b57cec5SDimitry Andric     B = VisitDeclSubExpr(DSNew);
29320b57cec5SDimitry Andric   }
29330b57cec5SDimitry Andric 
29340b57cec5SDimitry Andric   return B;
29350b57cec5SDimitry Andric }
29360b57cec5SDimitry Andric 
29370b57cec5SDimitry Andric /// VisitDeclSubExpr - Utility method to add block-level expressions for
29380b57cec5SDimitry Andric /// DeclStmts and initializers in them.
29390b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {
29400b57cec5SDimitry Andric   assert(DS->isSingleDecl() && "Can handle single declarations only.");
29415ffd83dbSDimitry Andric 
29425ffd83dbSDimitry Andric   if (const auto *TND = dyn_cast<TypedefNameDecl>(DS->getSingleDecl())) {
29435ffd83dbSDimitry Andric     // If we encounter a VLA, process its size expressions.
29445ffd83dbSDimitry Andric     const Type *T = TND->getUnderlyingType().getTypePtr();
29455ffd83dbSDimitry Andric     if (!T->isVariablyModifiedType())
29465ffd83dbSDimitry Andric       return Block;
29475ffd83dbSDimitry Andric 
29485ffd83dbSDimitry Andric     autoCreateBlock();
29495ffd83dbSDimitry Andric     appendStmt(Block, DS);
29505ffd83dbSDimitry Andric 
29515ffd83dbSDimitry Andric     CFGBlock *LastBlock = Block;
29525ffd83dbSDimitry Andric     for (const VariableArrayType *VA = FindVA(T); VA != nullptr;
29535ffd83dbSDimitry Andric          VA = FindVA(VA->getElementType().getTypePtr())) {
29545ffd83dbSDimitry Andric       if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))
29555ffd83dbSDimitry Andric         LastBlock = NewBlock;
29565ffd83dbSDimitry Andric     }
29575ffd83dbSDimitry Andric     return LastBlock;
29585ffd83dbSDimitry Andric   }
29595ffd83dbSDimitry Andric 
29600b57cec5SDimitry Andric   VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
29610b57cec5SDimitry Andric 
29620b57cec5SDimitry Andric   if (!VD) {
29635ffd83dbSDimitry Andric     // Of everything that can be declared in a DeclStmt, only VarDecls and the
29645ffd83dbSDimitry Andric     // exceptions above impact runtime semantics.
29650b57cec5SDimitry Andric     return Block;
29660b57cec5SDimitry Andric   }
29670b57cec5SDimitry Andric 
29680b57cec5SDimitry Andric   bool HasTemporaries = false;
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric   // Guard static initializers under a branch.
29710b57cec5SDimitry Andric   CFGBlock *blockAfterStaticInit = nullptr;
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric   if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {
29740b57cec5SDimitry Andric     // For static variables, we need to create a branch to track
29750b57cec5SDimitry Andric     // whether or not they are initialized.
29760b57cec5SDimitry Andric     if (Block) {
29770b57cec5SDimitry Andric       Succ = Block;
29780b57cec5SDimitry Andric       Block = nullptr;
29790b57cec5SDimitry Andric       if (badCFG)
29800b57cec5SDimitry Andric         return nullptr;
29810b57cec5SDimitry Andric     }
29820b57cec5SDimitry Andric     blockAfterStaticInit = Succ;
29830b57cec5SDimitry Andric   }
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric   // Destructors of temporaries in initialization expression should be called
29860b57cec5SDimitry Andric   // after initialization finishes.
29870b57cec5SDimitry Andric   Expr *Init = VD->getInit();
29880b57cec5SDimitry Andric   if (Init) {
29890b57cec5SDimitry Andric     HasTemporaries = isa<ExprWithCleanups>(Init);
29900b57cec5SDimitry Andric 
29910b57cec5SDimitry Andric     if (BuildOpts.AddTemporaryDtors && HasTemporaries) {
29920b57cec5SDimitry Andric       // Generate destructors for temporaries in initialization expression.
29930b57cec5SDimitry Andric       TempDtorContext Context;
29940b57cec5SDimitry Andric       VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),
2995a7dea167SDimitry Andric                              /*ExternallyDestructed=*/true, Context);
29960b57cec5SDimitry Andric     }
29970b57cec5SDimitry Andric   }
29980b57cec5SDimitry Andric 
2999972a253aSDimitry Andric   // If we bind to a tuple-like type, we iterate over the HoldingVars, and
3000972a253aSDimitry Andric   // create a DeclStmt for each of them.
3001972a253aSDimitry Andric   if (const auto *DD = dyn_cast<DecompositionDecl>(VD)) {
3002bdd1243dSDimitry Andric     for (auto *BD : llvm::reverse(DD->bindings())) {
3003972a253aSDimitry Andric       if (auto *VD = BD->getHoldingVar()) {
3004972a253aSDimitry Andric         DeclGroupRef DG(VD);
3005972a253aSDimitry Andric         DeclStmt *DSNew =
3006972a253aSDimitry Andric             new (Context) DeclStmt(DG, VD->getLocation(), GetEndLoc(VD));
3007972a253aSDimitry Andric         cfg->addSyntheticDeclStmt(DSNew, DS);
3008972a253aSDimitry Andric         Block = VisitDeclSubExpr(DSNew);
3009972a253aSDimitry Andric       }
3010972a253aSDimitry Andric     }
3011972a253aSDimitry Andric   }
3012972a253aSDimitry Andric 
30130b57cec5SDimitry Andric   autoCreateBlock();
30140b57cec5SDimitry Andric   appendStmt(Block, DS);
30150b57cec5SDimitry Andric 
3016972a253aSDimitry Andric   // If the initializer is an ArrayInitLoopExpr, we want to extract the
3017972a253aSDimitry Andric   // initializer, that's used for each element.
3018972a253aSDimitry Andric   const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init);
3019972a253aSDimitry Andric 
30200b57cec5SDimitry Andric   findConstructionContexts(
30210b57cec5SDimitry Andric       ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
3022972a253aSDimitry Andric       AILE ? AILE->getSubExpr() : Init);
30230b57cec5SDimitry Andric 
30240b57cec5SDimitry Andric   // Keep track of the last non-null block, as 'Block' can be nulled out
30250b57cec5SDimitry Andric   // if the initializer expression is something like a 'while' in a
30260b57cec5SDimitry Andric   // statement-expression.
30270b57cec5SDimitry Andric   CFGBlock *LastBlock = Block;
30280b57cec5SDimitry Andric 
30290b57cec5SDimitry Andric   if (Init) {
30300b57cec5SDimitry Andric     if (HasTemporaries) {
30310b57cec5SDimitry Andric       // For expression with temporaries go directly to subexpression to omit
30320b57cec5SDimitry Andric       // generating destructors for the second time.
30330b57cec5SDimitry Andric       ExprWithCleanups *EC = cast<ExprWithCleanups>(Init);
30340b57cec5SDimitry Andric       if (CFGBlock *newBlock = Visit(EC->getSubExpr()))
30350b57cec5SDimitry Andric         LastBlock = newBlock;
30360b57cec5SDimitry Andric     }
30370b57cec5SDimitry Andric     else {
30380b57cec5SDimitry Andric       if (CFGBlock *newBlock = Visit(Init))
30390b57cec5SDimitry Andric         LastBlock = newBlock;
30400b57cec5SDimitry Andric     }
30410b57cec5SDimitry Andric   }
30420b57cec5SDimitry Andric 
30430b57cec5SDimitry Andric   // If the type of VD is a VLA, then we must process its size expressions.
30445ffd83dbSDimitry Andric   // FIXME: This does not find the VLA if it is embedded in other types,
30455ffd83dbSDimitry Andric   // like here: `int (*p_vla)[x];`
30460b57cec5SDimitry Andric   for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());
30470b57cec5SDimitry Andric        VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {
30480b57cec5SDimitry Andric     if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))
30490b57cec5SDimitry Andric       LastBlock = newBlock;
30500b57cec5SDimitry Andric   }
30510b57cec5SDimitry Andric 
30520b57cec5SDimitry Andric   maybeAddScopeBeginForVarDecl(Block, VD, DS);
30530b57cec5SDimitry Andric 
30540b57cec5SDimitry Andric   // Remove variable from local scope.
30550b57cec5SDimitry Andric   if (ScopePos && VD == *ScopePos)
30560b57cec5SDimitry Andric     ++ScopePos;
30570b57cec5SDimitry Andric 
30580b57cec5SDimitry Andric   CFGBlock *B = LastBlock;
30590b57cec5SDimitry Andric   if (blockAfterStaticInit) {
30600b57cec5SDimitry Andric     Succ = B;
30610b57cec5SDimitry Andric     Block = createBlock(false);
30620b57cec5SDimitry Andric     Block->setTerminator(DS);
30630b57cec5SDimitry Andric     addSuccessor(Block, blockAfterStaticInit);
30640b57cec5SDimitry Andric     addSuccessor(Block, B);
30650b57cec5SDimitry Andric     B = Block;
30660b57cec5SDimitry Andric   }
30670b57cec5SDimitry Andric 
30680b57cec5SDimitry Andric   return B;
30690b57cec5SDimitry Andric }
30700b57cec5SDimitry Andric 
30710b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
30720b57cec5SDimitry Andric   // We may see an if statement in the middle of a basic block, or it may be the
30730b57cec5SDimitry Andric   // first statement we are processing.  In either case, we create a new basic
30740b57cec5SDimitry Andric   // block.  First, we create the blocks for the then...else statements, and
30750b57cec5SDimitry Andric   // then we create the block containing the if statement.  If we were in the
30760b57cec5SDimitry Andric   // middle of a block, we stop processing that block.  That block is then the
30770b57cec5SDimitry Andric   // implicit successor for the "then" and "else" clauses.
30780b57cec5SDimitry Andric 
30790b57cec5SDimitry Andric   // Save local scope position because in case of condition variable ScopePos
30800b57cec5SDimitry Andric   // won't be restored when traversing AST.
3081bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
30820b57cec5SDimitry Andric 
30830b57cec5SDimitry Andric   // Create local scope for C++17 if init-stmt if one exists.
30840b57cec5SDimitry Andric   if (Stmt *Init = I->getInit())
30850b57cec5SDimitry Andric     addLocalScopeForStmt(Init);
30860b57cec5SDimitry Andric 
30870b57cec5SDimitry Andric   // Create local scope for possible condition variable.
30880b57cec5SDimitry Andric   // Store scope position. Add implicit destructor.
30890b57cec5SDimitry Andric   if (VarDecl *VD = I->getConditionVariable())
30900b57cec5SDimitry Andric     addLocalScopeForVarDecl(VD);
30910b57cec5SDimitry Andric 
30920b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);
30930b57cec5SDimitry Andric 
30940b57cec5SDimitry Andric   // The block we were processing is now finished.  Make it the successor
30950b57cec5SDimitry Andric   // block.
30960b57cec5SDimitry Andric   if (Block) {
30970b57cec5SDimitry Andric     Succ = Block;
30980b57cec5SDimitry Andric     if (badCFG)
30990b57cec5SDimitry Andric       return nullptr;
31000b57cec5SDimitry Andric   }
31010b57cec5SDimitry Andric 
31020b57cec5SDimitry Andric   // Process the false branch.
31030b57cec5SDimitry Andric   CFGBlock *ElseBlock = Succ;
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric   if (Stmt *Else = I->getElse()) {
3106bdd1243dSDimitry Andric     SaveAndRestore sv(Succ);
31070b57cec5SDimitry Andric 
31080b57cec5SDimitry Andric     // NULL out Block so that the recursive call to Visit will
31090b57cec5SDimitry Andric     // create a new basic block.
31100b57cec5SDimitry Andric     Block = nullptr;
31110b57cec5SDimitry Andric 
31120b57cec5SDimitry Andric     // If branch is not a compound statement create implicit scope
31130b57cec5SDimitry Andric     // and add destructors.
31140b57cec5SDimitry Andric     if (!isa<CompoundStmt>(Else))
31150b57cec5SDimitry Andric       addLocalScopeAndDtors(Else);
31160b57cec5SDimitry Andric 
31170b57cec5SDimitry Andric     ElseBlock = addStmt(Else);
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric     if (!ElseBlock) // Can occur when the Else body has all NullStmts.
31200b57cec5SDimitry Andric       ElseBlock = sv.get();
31210b57cec5SDimitry Andric     else if (Block) {
31220b57cec5SDimitry Andric       if (badCFG)
31230b57cec5SDimitry Andric         return nullptr;
31240b57cec5SDimitry Andric     }
31250b57cec5SDimitry Andric   }
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric   // Process the true branch.
31280b57cec5SDimitry Andric   CFGBlock *ThenBlock;
31290b57cec5SDimitry Andric   {
31300b57cec5SDimitry Andric     Stmt *Then = I->getThen();
31310b57cec5SDimitry Andric     assert(Then);
3132bdd1243dSDimitry Andric     SaveAndRestore sv(Succ);
31330b57cec5SDimitry Andric     Block = nullptr;
31340b57cec5SDimitry Andric 
31350b57cec5SDimitry Andric     // If branch is not a compound statement create implicit scope
31360b57cec5SDimitry Andric     // and add destructors.
31370b57cec5SDimitry Andric     if (!isa<CompoundStmt>(Then))
31380b57cec5SDimitry Andric       addLocalScopeAndDtors(Then);
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric     ThenBlock = addStmt(Then);
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric     if (!ThenBlock) {
31430b57cec5SDimitry Andric       // We can reach here if the "then" body has all NullStmts.
31440b57cec5SDimitry Andric       // Create an empty block so we can distinguish between true and false
31450b57cec5SDimitry Andric       // branches in path-sensitive analyses.
31460b57cec5SDimitry Andric       ThenBlock = createBlock(false);
31470b57cec5SDimitry Andric       addSuccessor(ThenBlock, sv.get());
31480b57cec5SDimitry Andric     } else if (Block) {
31490b57cec5SDimitry Andric       if (badCFG)
31500b57cec5SDimitry Andric         return nullptr;
31510b57cec5SDimitry Andric     }
31520b57cec5SDimitry Andric   }
31530b57cec5SDimitry Andric 
31540b57cec5SDimitry Andric   // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by
31550b57cec5SDimitry Andric   // having these handle the actual control-flow jump.  Note that
31560b57cec5SDimitry Andric   // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)"
31570b57cec5SDimitry Andric   // we resort to the old control-flow behavior.  This special handling
31580b57cec5SDimitry Andric   // removes infeasible paths from the control-flow graph by having the
31590b57cec5SDimitry Andric   // control-flow transfer of '&&' or '||' go directly into the then/else
31600b57cec5SDimitry Andric   // blocks directly.
31610b57cec5SDimitry Andric   BinaryOperator *Cond =
3162349cc55cSDimitry Andric       (I->isConsteval() || I->getConditionVariable())
31630b57cec5SDimitry Andric           ? nullptr
31640b57cec5SDimitry Andric           : dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens());
31650b57cec5SDimitry Andric   CFGBlock *LastBlock;
31660b57cec5SDimitry Andric   if (Cond && Cond->isLogicalOp())
31670b57cec5SDimitry Andric     LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;
31680b57cec5SDimitry Andric   else {
31690b57cec5SDimitry Andric     // Now create a new block containing the if statement.
31700b57cec5SDimitry Andric     Block = createBlock(false);
31710b57cec5SDimitry Andric 
31720b57cec5SDimitry Andric     // Set the terminator of the new block to the If statement.
31730b57cec5SDimitry Andric     Block->setTerminator(I);
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric     // See if this is a known constant.
3176349cc55cSDimitry Andric     TryResult KnownVal;
3177349cc55cSDimitry Andric     if (!I->isConsteval())
3178349cc55cSDimitry Andric       KnownVal = tryEvaluateBool(I->getCond());
31790b57cec5SDimitry Andric 
31800b57cec5SDimitry Andric     // Add the successors.  If we know that specific branches are
31810b57cec5SDimitry Andric     // unreachable, inform addSuccessor() of that knowledge.
31820b57cec5SDimitry Andric     addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse());
31830b57cec5SDimitry Andric     addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue());
31840b57cec5SDimitry Andric 
31850b57cec5SDimitry Andric     // Add the condition as the last statement in the new block.  This may
31860b57cec5SDimitry Andric     // create new blocks as the condition may contain control-flow.  Any newly
31870b57cec5SDimitry Andric     // created blocks will be pointed to be "Block".
31880b57cec5SDimitry Andric     LastBlock = addStmt(I->getCond());
31890b57cec5SDimitry Andric 
31900b57cec5SDimitry Andric     // If the IfStmt contains a condition variable, add it and its
31910b57cec5SDimitry Andric     // initializer to the CFG.
31920b57cec5SDimitry Andric     if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {
31930b57cec5SDimitry Andric       autoCreateBlock();
31940b57cec5SDimitry Andric       LastBlock = addStmt(const_cast<DeclStmt *>(DS));
31950b57cec5SDimitry Andric     }
31960b57cec5SDimitry Andric   }
31970b57cec5SDimitry Andric 
31980b57cec5SDimitry Andric   // Finally, if the IfStmt contains a C++17 init-stmt, add it to the CFG.
31990b57cec5SDimitry Andric   if (Stmt *Init = I->getInit()) {
32000b57cec5SDimitry Andric     autoCreateBlock();
32010b57cec5SDimitry Andric     LastBlock = addStmt(Init);
32020b57cec5SDimitry Andric   }
32030b57cec5SDimitry Andric 
32040b57cec5SDimitry Andric   return LastBlock;
32050b57cec5SDimitry Andric }
32060b57cec5SDimitry Andric 
32070b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {
32080b57cec5SDimitry Andric   // If we were in the middle of a block we stop processing that block.
32090b57cec5SDimitry Andric   //
32100b57cec5SDimitry Andric   // NOTE: If a "return" or "co_return" appears in the middle of a block, this
32110b57cec5SDimitry Andric   //       means that the code afterwards is DEAD (unreachable).  We still keep
32120b57cec5SDimitry Andric   //       a basic block for that code; a simple "mark-and-sweep" from the entry
32130b57cec5SDimitry Andric   //       block will be able to report such dead blocks.
32140b57cec5SDimitry Andric   assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));
32150b57cec5SDimitry Andric 
32160b57cec5SDimitry Andric   // Create the new block.
32170b57cec5SDimitry Andric   Block = createBlock(false);
32180b57cec5SDimitry Andric 
32190b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);
32200b57cec5SDimitry Andric 
32210b57cec5SDimitry Andric   if (auto *R = dyn_cast<ReturnStmt>(S))
32220b57cec5SDimitry Andric     findConstructionContexts(
32230b57cec5SDimitry Andric         ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),
32240b57cec5SDimitry Andric         R->getRetValue());
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric   // If the one of the destructors does not return, we already have the Exit
32270b57cec5SDimitry Andric   // block as a successor.
32280b57cec5SDimitry Andric   if (!Block->hasNoReturnElement())
32290b57cec5SDimitry Andric     addSuccessor(Block, &cfg->getExit());
32300b57cec5SDimitry Andric 
3231a7dea167SDimitry Andric   // Add the return statement to the block.
3232a7dea167SDimitry Andric   appendStmt(Block, S);
3233a7dea167SDimitry Andric 
3234a7dea167SDimitry Andric   // Visit children
3235a7dea167SDimitry Andric   if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {
3236a7dea167SDimitry Andric     if (Expr *O = RS->getRetValue())
3237a7dea167SDimitry Andric       return Visit(O, AddStmtChoice::AlwaysAdd, /*ExternallyDestructed=*/true);
3238a7dea167SDimitry Andric     return Block;
3239a7dea167SDimitry Andric   }
324081ad6265SDimitry Andric 
324181ad6265SDimitry Andric   CoreturnStmt *CRS = cast<CoreturnStmt>(S);
324281ad6265SDimitry Andric   auto *B = Block;
324381ad6265SDimitry Andric   if (CFGBlock *R = Visit(CRS->getPromiseCall()))
324481ad6265SDimitry Andric     B = R;
324581ad6265SDimitry Andric 
324681ad6265SDimitry Andric   if (Expr *RV = CRS->getOperand())
324781ad6265SDimitry Andric     if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))
324881ad6265SDimitry Andric       // A non-initlist void expression.
324981ad6265SDimitry Andric       if (CFGBlock *R = Visit(RV))
325081ad6265SDimitry Andric         B = R;
325181ad6265SDimitry Andric 
325281ad6265SDimitry Andric   return B;
325381ad6265SDimitry Andric }
325481ad6265SDimitry Andric 
325581ad6265SDimitry Andric CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
325681ad6265SDimitry Andric                                                 AddStmtChoice asc) {
325781ad6265SDimitry Andric   // We're modelling the pre-coro-xform CFG. Thus just evalate the various
325881ad6265SDimitry Andric   // active components of the co_await or co_yield. Note we do not model the
325981ad6265SDimitry Andric   // edge from the builtin_suspend to the exit node.
326081ad6265SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
326181ad6265SDimitry Andric     autoCreateBlock();
326281ad6265SDimitry Andric     appendStmt(Block, E);
326381ad6265SDimitry Andric   }
326481ad6265SDimitry Andric   CFGBlock *B = Block;
326581ad6265SDimitry Andric   if (auto *R = Visit(E->getResumeExpr()))
326681ad6265SDimitry Andric     B = R;
326781ad6265SDimitry Andric   if (auto *R = Visit(E->getSuspendExpr()))
326881ad6265SDimitry Andric     B = R;
326981ad6265SDimitry Andric   if (auto *R = Visit(E->getReadyExpr()))
327081ad6265SDimitry Andric     B = R;
327181ad6265SDimitry Andric   if (auto *R = Visit(E->getCommonExpr()))
327281ad6265SDimitry Andric     B = R;
327381ad6265SDimitry Andric   return B;
32740b57cec5SDimitry Andric }
32750b57cec5SDimitry Andric 
32760b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {
32770b57cec5SDimitry Andric   // SEHExceptStmt are treated like labels, so they are the first statement in a
32780b57cec5SDimitry Andric   // block.
32790b57cec5SDimitry Andric 
32800b57cec5SDimitry Andric   // Save local scope position because in case of exception variable ScopePos
32810b57cec5SDimitry Andric   // won't be restored when traversing AST.
3282bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
32830b57cec5SDimitry Andric 
32840b57cec5SDimitry Andric   addStmt(ES->getBlock());
32850b57cec5SDimitry Andric   CFGBlock *SEHExceptBlock = Block;
32860b57cec5SDimitry Andric   if (!SEHExceptBlock)
32870b57cec5SDimitry Andric     SEHExceptBlock = createBlock();
32880b57cec5SDimitry Andric 
32890b57cec5SDimitry Andric   appendStmt(SEHExceptBlock, ES);
32900b57cec5SDimitry Andric 
32910b57cec5SDimitry Andric   // Also add the SEHExceptBlock as a label, like with regular labels.
32920b57cec5SDimitry Andric   SEHExceptBlock->setLabel(ES);
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric   // Bail out if the CFG is bad.
32950b57cec5SDimitry Andric   if (badCFG)
32960b57cec5SDimitry Andric     return nullptr;
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
32990b57cec5SDimitry Andric   Block = nullptr;
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric   return SEHExceptBlock;
33020b57cec5SDimitry Andric }
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {
3305a7dea167SDimitry Andric   return VisitCompoundStmt(FS->getBlock(), /*ExternallyDestructed=*/false);
33060b57cec5SDimitry Andric }
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {
33090b57cec5SDimitry Andric   // "__leave" is a control-flow statement.  Thus we stop processing the current
33100b57cec5SDimitry Andric   // block.
33110b57cec5SDimitry Andric   if (badCFG)
33120b57cec5SDimitry Andric     return nullptr;
33130b57cec5SDimitry Andric 
33140b57cec5SDimitry Andric   // Now create a new block that ends with the __leave statement.
33150b57cec5SDimitry Andric   Block = createBlock(false);
33160b57cec5SDimitry Andric   Block->setTerminator(LS);
33170b57cec5SDimitry Andric 
33180b57cec5SDimitry Andric   // If there is no target for the __leave, then we are looking at an incomplete
33190b57cec5SDimitry Andric   // AST.  This means that the CFG cannot be constructed.
33200b57cec5SDimitry Andric   if (SEHLeaveJumpTarget.block) {
33210b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);
33220b57cec5SDimitry Andric     addSuccessor(Block, SEHLeaveJumpTarget.block);
33230b57cec5SDimitry Andric   } else
33240b57cec5SDimitry Andric     badCFG = true;
33250b57cec5SDimitry Andric 
33260b57cec5SDimitry Andric   return Block;
33270b57cec5SDimitry Andric }
33280b57cec5SDimitry Andric 
33290b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {
33300b57cec5SDimitry Andric   // "__try"/"__except"/"__finally" is a control-flow statement.  Thus we stop
33310b57cec5SDimitry Andric   // processing the current block.
33320b57cec5SDimitry Andric   CFGBlock *SEHTrySuccessor = nullptr;
33330b57cec5SDimitry Andric 
33340b57cec5SDimitry Andric   if (Block) {
33350b57cec5SDimitry Andric     if (badCFG)
33360b57cec5SDimitry Andric       return nullptr;
33370b57cec5SDimitry Andric     SEHTrySuccessor = Block;
33380b57cec5SDimitry Andric   } else SEHTrySuccessor = Succ;
33390b57cec5SDimitry Andric 
33400b57cec5SDimitry Andric   // FIXME: Implement __finally support.
33410b57cec5SDimitry Andric   if (Terminator->getFinallyHandler())
33420b57cec5SDimitry Andric     return NYS();
33430b57cec5SDimitry Andric 
33440b57cec5SDimitry Andric   CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;
33450b57cec5SDimitry Andric 
33460b57cec5SDimitry Andric   // Create a new block that will contain the __try statement.
33470b57cec5SDimitry Andric   CFGBlock *NewTryTerminatedBlock = createBlock(false);
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric   // Add the terminator in the __try block.
33500b57cec5SDimitry Andric   NewTryTerminatedBlock->setTerminator(Terminator);
33510b57cec5SDimitry Andric 
33520b57cec5SDimitry Andric   if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {
33530b57cec5SDimitry Andric     // The code after the try is the implicit successor if there's an __except.
33540b57cec5SDimitry Andric     Succ = SEHTrySuccessor;
33550b57cec5SDimitry Andric     Block = nullptr;
33560b57cec5SDimitry Andric     CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);
33570b57cec5SDimitry Andric     if (!ExceptBlock)
33580b57cec5SDimitry Andric       return nullptr;
33590b57cec5SDimitry Andric     // Add this block to the list of successors for the block with the try
33600b57cec5SDimitry Andric     // statement.
33610b57cec5SDimitry Andric     addSuccessor(NewTryTerminatedBlock, ExceptBlock);
33620b57cec5SDimitry Andric   }
33630b57cec5SDimitry Andric   if (PrevSEHTryTerminatedBlock)
33640b57cec5SDimitry Andric     addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);
33650b57cec5SDimitry Andric   else
33660b57cec5SDimitry Andric     addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
33670b57cec5SDimitry Andric 
33680b57cec5SDimitry Andric   // The code after the try is the implicit successor.
33690b57cec5SDimitry Andric   Succ = SEHTrySuccessor;
33700b57cec5SDimitry Andric 
33710b57cec5SDimitry Andric   // Save the current "__try" context.
3372bdd1243dSDimitry Andric   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
33730b57cec5SDimitry Andric   cfg->addTryDispatchBlock(TryTerminatedBlock);
33740b57cec5SDimitry Andric 
33750b57cec5SDimitry Andric   // Save the current value for the __leave target.
33760b57cec5SDimitry Andric   // All __leaves should go to the code following the __try
33770b57cec5SDimitry Andric   // (FIXME: or if the __try has a __finally, to the __finally.)
3378bdd1243dSDimitry Andric   SaveAndRestore save_break(SEHLeaveJumpTarget);
33790b57cec5SDimitry Andric   SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric   assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");
33820b57cec5SDimitry Andric   Block = nullptr;
33830b57cec5SDimitry Andric   return addStmt(Terminator->getTryBlock());
33840b57cec5SDimitry Andric }
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {
33870b57cec5SDimitry Andric   // Get the block of the labeled statement.  Add it to our map.
33880b57cec5SDimitry Andric   addStmt(L->getSubStmt());
33890b57cec5SDimitry Andric   CFGBlock *LabelBlock = Block;
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric   if (!LabelBlock)              // This can happen when the body is empty, i.e.
33920b57cec5SDimitry Andric     LabelBlock = createBlock(); // scopes that only contains NullStmts.
33930b57cec5SDimitry Andric 
339406c3fb27SDimitry Andric   assert(!LabelMap.contains(L->getDecl()) && "label already in map");
33950b57cec5SDimitry Andric   LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric   // Labels partition blocks, so this is the end of the basic block we were
33980b57cec5SDimitry Andric   // processing (L is the block's label).  Because this is label (and we have
33990b57cec5SDimitry Andric   // already processed the substatement) there is no extra control-flow to worry
34000b57cec5SDimitry Andric   // about.
34010b57cec5SDimitry Andric   LabelBlock->setLabel(L);
34020b57cec5SDimitry Andric   if (badCFG)
34030b57cec5SDimitry Andric     return nullptr;
34040b57cec5SDimitry Andric 
3405349cc55cSDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
34060b57cec5SDimitry Andric   Block = nullptr;
34070b57cec5SDimitry Andric 
34080b57cec5SDimitry Andric   // This block is now the implicit successor of other blocks.
34090b57cec5SDimitry Andric   Succ = LabelBlock;
34100b57cec5SDimitry Andric 
34110b57cec5SDimitry Andric   return LabelBlock;
34120b57cec5SDimitry Andric }
34130b57cec5SDimitry Andric 
34140b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
34150b57cec5SDimitry Andric   CFGBlock *LastBlock = VisitNoRecurse(E, asc);
34160b57cec5SDimitry Andric   for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) {
34170b57cec5SDimitry Andric     if (Expr *CopyExpr = CI.getCopyExpr()) {
34180b57cec5SDimitry Andric       CFGBlock *Tmp = Visit(CopyExpr);
34190b57cec5SDimitry Andric       if (Tmp)
34200b57cec5SDimitry Andric         LastBlock = Tmp;
34210b57cec5SDimitry Andric     }
34220b57cec5SDimitry Andric   }
34230b57cec5SDimitry Andric   return LastBlock;
34240b57cec5SDimitry Andric }
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {
34270b57cec5SDimitry Andric   CFGBlock *LastBlock = VisitNoRecurse(E, asc);
3428972a253aSDimitry Andric 
3429972a253aSDimitry Andric   unsigned Idx = 0;
34300b57cec5SDimitry Andric   for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(),
3431972a253aSDimitry Andric                                          et = E->capture_init_end();
3432972a253aSDimitry Andric        it != et; ++it, ++Idx) {
34330b57cec5SDimitry Andric     if (Expr *Init = *it) {
3434972a253aSDimitry Andric       // If the initializer is an ArrayInitLoopExpr, we want to extract the
3435972a253aSDimitry Andric       // initializer, that's used for each element.
3436bdd1243dSDimitry Andric       auto *AILEInit = extractElementInitializerFromNestedAILE(
3437bdd1243dSDimitry Andric           dyn_cast<ArrayInitLoopExpr>(Init));
3438972a253aSDimitry Andric 
3439972a253aSDimitry Andric       findConstructionContexts(ConstructionContextLayer::create(
3440972a253aSDimitry Andric                                    cfg->getBumpVectorContext(), {E, Idx}),
3441bdd1243dSDimitry Andric                                AILEInit ? AILEInit : Init);
3442972a253aSDimitry Andric 
34430b57cec5SDimitry Andric       CFGBlock *Tmp = Visit(Init);
34440b57cec5SDimitry Andric       if (Tmp)
34450b57cec5SDimitry Andric         LastBlock = Tmp;
34460b57cec5SDimitry Andric     }
34470b57cec5SDimitry Andric   }
34480b57cec5SDimitry Andric   return LastBlock;
34490b57cec5SDimitry Andric }
34500b57cec5SDimitry Andric 
34510b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {
34520b57cec5SDimitry Andric   // Goto is a control-flow statement.  Thus we stop processing the current
34530b57cec5SDimitry Andric   // block and create a new one.
34540b57cec5SDimitry Andric 
34550b57cec5SDimitry Andric   Block = createBlock(false);
34560b57cec5SDimitry Andric   Block->setTerminator(G);
34570b57cec5SDimitry Andric 
34580b57cec5SDimitry Andric   // If we already know the mapping to the label block add the successor now.
34590b57cec5SDimitry Andric   LabelMapTy::iterator I = LabelMap.find(G->getLabel());
34600b57cec5SDimitry Andric 
34610b57cec5SDimitry Andric   if (I == LabelMap.end())
34620b57cec5SDimitry Andric     // We will need to backpatch this block later.
34630b57cec5SDimitry Andric     BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
34640b57cec5SDimitry Andric   else {
34650b57cec5SDimitry Andric     JumpTarget JT = I->second;
34660b57cec5SDimitry Andric     addSuccessor(Block, JT.block);
346706c3fb27SDimitry Andric     addScopeChangesHandling(ScopePos, JT.scopePosition, G);
34680b57cec5SDimitry Andric   }
34690b57cec5SDimitry Andric 
34700b57cec5SDimitry Andric   return Block;
34710b57cec5SDimitry Andric }
34720b57cec5SDimitry Andric 
34730b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
34740b57cec5SDimitry Andric   // Goto is a control-flow statement.  Thus we stop processing the current
34750b57cec5SDimitry Andric   // block and create a new one.
34760b57cec5SDimitry Andric 
34770b57cec5SDimitry Andric   if (!G->isAsmGoto())
34780b57cec5SDimitry Andric     return VisitStmt(G, asc);
34790b57cec5SDimitry Andric 
34800b57cec5SDimitry Andric   if (Block) {
34810b57cec5SDimitry Andric     Succ = Block;
34820b57cec5SDimitry Andric     if (badCFG)
34830b57cec5SDimitry Andric       return nullptr;
34840b57cec5SDimitry Andric   }
34850b57cec5SDimitry Andric   Block = createBlock();
34860b57cec5SDimitry Andric   Block->setTerminator(G);
34870b57cec5SDimitry Andric   // We will backpatch this block later for all the labels.
34880b57cec5SDimitry Andric   BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
34890b57cec5SDimitry Andric   // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
34900b57cec5SDimitry Andric   // used to avoid adding "Succ" again.
34910b57cec5SDimitry Andric   BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
349204eeddc0SDimitry Andric   return VisitChildren(G);
34930b57cec5SDimitry Andric }
34940b57cec5SDimitry Andric 
34950b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {
34960b57cec5SDimitry Andric   CFGBlock *LoopSuccessor = nullptr;
34970b57cec5SDimitry Andric 
34980b57cec5SDimitry Andric   // Save local scope position because in case of condition variable ScopePos
34990b57cec5SDimitry Andric   // won't be restored when traversing AST.
3500bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
35010b57cec5SDimitry Andric 
35020b57cec5SDimitry Andric   // Create local scope for init statement and possible condition variable.
35030b57cec5SDimitry Andric   // Add destructor for init statement and condition variable.
35040b57cec5SDimitry Andric   // Store scope position for continue statement.
35050b57cec5SDimitry Andric   if (Stmt *Init = F->getInit())
35060b57cec5SDimitry Andric     addLocalScopeForStmt(Init);
35070b57cec5SDimitry Andric   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
35080b57cec5SDimitry Andric 
35090b57cec5SDimitry Andric   if (VarDecl *VD = F->getConditionVariable())
35100b57cec5SDimitry Andric     addLocalScopeForVarDecl(VD);
35110b57cec5SDimitry Andric   LocalScope::const_iterator ContinueScopePos = ScopePos;
35120b57cec5SDimitry Andric 
35130b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);
35140b57cec5SDimitry Andric 
35150b57cec5SDimitry Andric   addLoopExit(F);
35160b57cec5SDimitry Andric 
35170b57cec5SDimitry Andric   // "for" is a control-flow statement.  Thus we stop processing the current
35180b57cec5SDimitry Andric   // block.
35190b57cec5SDimitry Andric   if (Block) {
35200b57cec5SDimitry Andric     if (badCFG)
35210b57cec5SDimitry Andric       return nullptr;
35220b57cec5SDimitry Andric     LoopSuccessor = Block;
35230b57cec5SDimitry Andric   } else
35240b57cec5SDimitry Andric     LoopSuccessor = Succ;
35250b57cec5SDimitry Andric 
35260b57cec5SDimitry Andric   // Save the current value for the break targets.
35270b57cec5SDimitry Andric   // All breaks should go to the code following the loop.
3528bdd1243dSDimitry Andric   SaveAndRestore save_break(BreakJumpTarget);
35290b57cec5SDimitry Andric   BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric   CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
35320b57cec5SDimitry Andric 
35330b57cec5SDimitry Andric   // Now create the loop body.
35340b57cec5SDimitry Andric   {
35350b57cec5SDimitry Andric     assert(F->getBody());
35360b57cec5SDimitry Andric 
35370b57cec5SDimitry Andric     // Save the current values for Block, Succ, continue and break targets.
3538bdd1243dSDimitry Andric     SaveAndRestore save_Block(Block), save_Succ(Succ);
3539bdd1243dSDimitry Andric     SaveAndRestore save_continue(ContinueJumpTarget);
35400b57cec5SDimitry Andric 
35410b57cec5SDimitry Andric     // Create an empty block to represent the transition block for looping back
35420b57cec5SDimitry Andric     // to the head of the loop.  If we have increment code, it will
35430b57cec5SDimitry Andric     // go in this block as well.
35440b57cec5SDimitry Andric     Block = Succ = TransitionBlock = createBlock(false);
35450b57cec5SDimitry Andric     TransitionBlock->setLoopTarget(F);
35460b57cec5SDimitry Andric 
354706c3fb27SDimitry Andric 
354806c3fb27SDimitry Andric     // Loop iteration (after increment) should end with destructor of Condition
354906c3fb27SDimitry Andric     // variable (if any).
355006c3fb27SDimitry Andric     addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
355106c3fb27SDimitry Andric 
35520b57cec5SDimitry Andric     if (Stmt *I = F->getInc()) {
35530b57cec5SDimitry Andric       // Generate increment code in its own basic block.  This is the target of
35540b57cec5SDimitry Andric       // continue statements.
35550b57cec5SDimitry Andric       Succ = addStmt(I);
35560b57cec5SDimitry Andric     }
35570b57cec5SDimitry Andric 
35580b57cec5SDimitry Andric     // Finish up the increment (or empty) block if it hasn't been already.
35590b57cec5SDimitry Andric     if (Block) {
35600b57cec5SDimitry Andric       assert(Block == Succ);
35610b57cec5SDimitry Andric       if (badCFG)
35620b57cec5SDimitry Andric         return nullptr;
35630b57cec5SDimitry Andric       Block = nullptr;
35640b57cec5SDimitry Andric     }
35650b57cec5SDimitry Andric 
35660b57cec5SDimitry Andric    // The starting block for the loop increment is the block that should
35670b57cec5SDimitry Andric    // represent the 'loop target' for looping back to the start of the loop.
35680b57cec5SDimitry Andric    ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
35690b57cec5SDimitry Andric    ContinueJumpTarget.block->setLoopTarget(F);
35700b57cec5SDimitry Andric 
35710b57cec5SDimitry Andric 
35720b57cec5SDimitry Andric     // If body is not a compound statement create implicit scope
35730b57cec5SDimitry Andric     // and add destructors.
35740b57cec5SDimitry Andric     if (!isa<CompoundStmt>(F->getBody()))
35750b57cec5SDimitry Andric       addLocalScopeAndDtors(F->getBody());
35760b57cec5SDimitry Andric 
35770b57cec5SDimitry Andric     // Now populate the body block, and in the process create new blocks as we
35780b57cec5SDimitry Andric     // walk the body of the loop.
35790b57cec5SDimitry Andric     BodyBlock = addStmt(F->getBody());
35800b57cec5SDimitry Andric 
35810b57cec5SDimitry Andric     if (!BodyBlock) {
35820b57cec5SDimitry Andric       // In the case of "for (...;...;...);" we can have a null BodyBlock.
35830b57cec5SDimitry Andric       // Use the continue jump target as the proxy for the body.
35840b57cec5SDimitry Andric       BodyBlock = ContinueJumpTarget.block;
35850b57cec5SDimitry Andric     }
35860b57cec5SDimitry Andric     else if (badCFG)
35870b57cec5SDimitry Andric       return nullptr;
35880b57cec5SDimitry Andric   }
35890b57cec5SDimitry Andric 
35900b57cec5SDimitry Andric   // Because of short-circuit evaluation, the condition of the loop can span
35910b57cec5SDimitry Andric   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
35920b57cec5SDimitry Andric   // evaluate the condition.
35930b57cec5SDimitry Andric   CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
35940b57cec5SDimitry Andric 
35950b57cec5SDimitry Andric   do {
35960b57cec5SDimitry Andric     Expr *C = F->getCond();
3597bdd1243dSDimitry Andric     SaveAndRestore save_scope_pos(ScopePos);
35980b57cec5SDimitry Andric 
35990b57cec5SDimitry Andric     // Specially handle logical operators, which have a slightly
36000b57cec5SDimitry Andric     // more optimal CFG representation.
36010b57cec5SDimitry Andric     if (BinaryOperator *Cond =
36020b57cec5SDimitry Andric             dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr))
36030b57cec5SDimitry Andric       if (Cond->isLogicalOp()) {
36040b57cec5SDimitry Andric         std::tie(EntryConditionBlock, ExitConditionBlock) =
36050b57cec5SDimitry Andric           VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);
36060b57cec5SDimitry Andric         break;
36070b57cec5SDimitry Andric       }
36080b57cec5SDimitry Andric 
36090b57cec5SDimitry Andric     // The default case when not handling logical operators.
36100b57cec5SDimitry Andric     EntryConditionBlock = ExitConditionBlock = createBlock(false);
36110b57cec5SDimitry Andric     ExitConditionBlock->setTerminator(F);
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric     // See if this is a known constant.
36140b57cec5SDimitry Andric     TryResult KnownVal(true);
36150b57cec5SDimitry Andric 
36160b57cec5SDimitry Andric     if (C) {
36170b57cec5SDimitry Andric       // Now add the actual condition to the condition block.
36180b57cec5SDimitry Andric       // Because the condition itself may contain control-flow, new blocks may
36190b57cec5SDimitry Andric       // be created.  Thus we update "Succ" after adding the condition.
36200b57cec5SDimitry Andric       Block = ExitConditionBlock;
36210b57cec5SDimitry Andric       EntryConditionBlock = addStmt(C);
36220b57cec5SDimitry Andric 
36230b57cec5SDimitry Andric       // If this block contains a condition variable, add both the condition
36240b57cec5SDimitry Andric       // variable and initializer to the CFG.
36250b57cec5SDimitry Andric       if (VarDecl *VD = F->getConditionVariable()) {
36260b57cec5SDimitry Andric         if (Expr *Init = VD->getInit()) {
36270b57cec5SDimitry Andric           autoCreateBlock();
36280b57cec5SDimitry Andric           const DeclStmt *DS = F->getConditionVariableDeclStmt();
36290b57cec5SDimitry Andric           assert(DS->isSingleDecl());
36300b57cec5SDimitry Andric           findConstructionContexts(
36310b57cec5SDimitry Andric               ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),
36320b57cec5SDimitry Andric               Init);
36330b57cec5SDimitry Andric           appendStmt(Block, DS);
36340b57cec5SDimitry Andric           EntryConditionBlock = addStmt(Init);
36350b57cec5SDimitry Andric           assert(Block == EntryConditionBlock);
36360b57cec5SDimitry Andric           maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
36370b57cec5SDimitry Andric         }
36380b57cec5SDimitry Andric       }
36390b57cec5SDimitry Andric 
36400b57cec5SDimitry Andric       if (Block && badCFG)
36410b57cec5SDimitry Andric         return nullptr;
36420b57cec5SDimitry Andric 
36430b57cec5SDimitry Andric       KnownVal = tryEvaluateBool(C);
36440b57cec5SDimitry Andric     }
36450b57cec5SDimitry Andric 
36460b57cec5SDimitry Andric     // Add the loop body entry as a successor to the condition.
36470b57cec5SDimitry Andric     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
36480b57cec5SDimitry Andric     // Link up the condition block with the code that follows the loop.  (the
36490b57cec5SDimitry Andric     // false branch).
36500b57cec5SDimitry Andric     addSuccessor(ExitConditionBlock,
36510b57cec5SDimitry Andric                  KnownVal.isTrue() ? nullptr : LoopSuccessor);
36520b57cec5SDimitry Andric   } while (false);
36530b57cec5SDimitry Andric 
36540b57cec5SDimitry Andric   // Link up the loop-back block to the entry condition block.
36550b57cec5SDimitry Andric   addSuccessor(TransitionBlock, EntryConditionBlock);
36560b57cec5SDimitry Andric 
36570b57cec5SDimitry Andric   // The condition block is the implicit successor for any code above the loop.
36580b57cec5SDimitry Andric   Succ = EntryConditionBlock;
36590b57cec5SDimitry Andric 
36600b57cec5SDimitry Andric   // If the loop contains initialization, create a new block for those
36610b57cec5SDimitry Andric   // statements.  This block can also contain statements that precede the loop.
36620b57cec5SDimitry Andric   if (Stmt *I = F->getInit()) {
3663bdd1243dSDimitry Andric     SaveAndRestore save_scope_pos(ScopePos);
36640b57cec5SDimitry Andric     ScopePos = LoopBeginScopePos;
36650b57cec5SDimitry Andric     Block = createBlock();
36660b57cec5SDimitry Andric     return addStmt(I);
36670b57cec5SDimitry Andric   }
36680b57cec5SDimitry Andric 
36690b57cec5SDimitry Andric   // There is no loop initialization.  We are thus basically a while loop.
36700b57cec5SDimitry Andric   // NULL out Block to force lazy block construction.
36710b57cec5SDimitry Andric   Block = nullptr;
36720b57cec5SDimitry Andric   Succ = EntryConditionBlock;
36730b57cec5SDimitry Andric   return EntryConditionBlock;
36740b57cec5SDimitry Andric }
36750b57cec5SDimitry Andric 
36760b57cec5SDimitry Andric CFGBlock *
36770b57cec5SDimitry Andric CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
36780b57cec5SDimitry Andric                                           AddStmtChoice asc) {
36790b57cec5SDimitry Andric   findConstructionContexts(
36800b57cec5SDimitry Andric       ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
3681480093f4SDimitry Andric       MTE->getSubExpr());
36820b57cec5SDimitry Andric 
36830b57cec5SDimitry Andric   return VisitStmt(MTE, asc);
36840b57cec5SDimitry Andric }
36850b57cec5SDimitry Andric 
36860b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
36870b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, M)) {
36880b57cec5SDimitry Andric     autoCreateBlock();
36890b57cec5SDimitry Andric     appendStmt(Block, M);
36900b57cec5SDimitry Andric   }
36910b57cec5SDimitry Andric   return Visit(M->getBase());
36920b57cec5SDimitry Andric }
36930b57cec5SDimitry Andric 
36940b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
36950b57cec5SDimitry Andric   // Objective-C fast enumeration 'for' statements:
36960b57cec5SDimitry Andric   //  http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
36970b57cec5SDimitry Andric   //
36980b57cec5SDimitry Andric   //  for ( Type newVariable in collection_expression ) { statements }
36990b57cec5SDimitry Andric   //
37000b57cec5SDimitry Andric   //  becomes:
37010b57cec5SDimitry Andric   //
37020b57cec5SDimitry Andric   //   prologue:
37030b57cec5SDimitry Andric   //     1. collection_expression
37040b57cec5SDimitry Andric   //     T. jump to loop_entry
37050b57cec5SDimitry Andric   //   loop_entry:
37060b57cec5SDimitry Andric   //     1. side-effects of element expression
37070b57cec5SDimitry Andric   //     1. ObjCForCollectionStmt [performs binding to newVariable]
37080b57cec5SDimitry Andric   //     T. ObjCForCollectionStmt  TB, FB  [jumps to TB if newVariable != nil]
37090b57cec5SDimitry Andric   //   TB:
37100b57cec5SDimitry Andric   //     statements
37110b57cec5SDimitry Andric   //     T. jump to loop_entry
37120b57cec5SDimitry Andric   //   FB:
37130b57cec5SDimitry Andric   //     what comes after
37140b57cec5SDimitry Andric   //
37150b57cec5SDimitry Andric   //  and
37160b57cec5SDimitry Andric   //
37170b57cec5SDimitry Andric   //  Type existingItem;
37180b57cec5SDimitry Andric   //  for ( existingItem in expression ) { statements }
37190b57cec5SDimitry Andric   //
37200b57cec5SDimitry Andric   //  becomes:
37210b57cec5SDimitry Andric   //
37220b57cec5SDimitry Andric   //   the same with newVariable replaced with existingItem; the binding works
37230b57cec5SDimitry Andric   //   the same except that for one ObjCForCollectionStmt::getElement() returns
37240b57cec5SDimitry Andric   //   a DeclStmt and the other returns a DeclRefExpr.
37250b57cec5SDimitry Andric 
37260b57cec5SDimitry Andric   CFGBlock *LoopSuccessor = nullptr;
37270b57cec5SDimitry Andric 
37280b57cec5SDimitry Andric   if (Block) {
37290b57cec5SDimitry Andric     if (badCFG)
37300b57cec5SDimitry Andric       return nullptr;
37310b57cec5SDimitry Andric     LoopSuccessor = Block;
37320b57cec5SDimitry Andric     Block = nullptr;
37330b57cec5SDimitry Andric   } else
37340b57cec5SDimitry Andric     LoopSuccessor = Succ;
37350b57cec5SDimitry Andric 
37360b57cec5SDimitry Andric   // Build the condition blocks.
37370b57cec5SDimitry Andric   CFGBlock *ExitConditionBlock = createBlock(false);
37380b57cec5SDimitry Andric 
37390b57cec5SDimitry Andric   // Set the terminator for the "exit" condition block.
37400b57cec5SDimitry Andric   ExitConditionBlock->setTerminator(S);
37410b57cec5SDimitry Andric 
37420b57cec5SDimitry Andric   // The last statement in the block should be the ObjCForCollectionStmt, which
37430b57cec5SDimitry Andric   // performs the actual binding to 'element' and determines if there are any
37440b57cec5SDimitry Andric   // more items in the collection.
37450b57cec5SDimitry Andric   appendStmt(ExitConditionBlock, S);
37460b57cec5SDimitry Andric   Block = ExitConditionBlock;
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric   // Walk the 'element' expression to see if there are any side-effects.  We
37490b57cec5SDimitry Andric   // generate new blocks as necessary.  We DON'T add the statement by default to
37500b57cec5SDimitry Andric   // the CFG unless it contains control-flow.
37510b57cec5SDimitry Andric   CFGBlock *EntryConditionBlock = Visit(S->getElement(),
37520b57cec5SDimitry Andric                                         AddStmtChoice::NotAlwaysAdd);
37530b57cec5SDimitry Andric   if (Block) {
37540b57cec5SDimitry Andric     if (badCFG)
37550b57cec5SDimitry Andric       return nullptr;
37560b57cec5SDimitry Andric     Block = nullptr;
37570b57cec5SDimitry Andric   }
37580b57cec5SDimitry Andric 
37590b57cec5SDimitry Andric   // The condition block is the implicit successor for the loop body as well as
37600b57cec5SDimitry Andric   // any code above the loop.
37610b57cec5SDimitry Andric   Succ = EntryConditionBlock;
37620b57cec5SDimitry Andric 
37630b57cec5SDimitry Andric   // Now create the true branch.
37640b57cec5SDimitry Andric   {
37650b57cec5SDimitry Andric     // Save the current values for Succ, continue and break targets.
3766bdd1243dSDimitry Andric     SaveAndRestore save_Block(Block), save_Succ(Succ);
3767bdd1243dSDimitry Andric     SaveAndRestore save_continue(ContinueJumpTarget),
37680b57cec5SDimitry Andric         save_break(BreakJumpTarget);
37690b57cec5SDimitry Andric 
37700b57cec5SDimitry Andric     // Add an intermediate block between the BodyBlock and the
37710b57cec5SDimitry Andric     // EntryConditionBlock to represent the "loop back" transition, for looping
37720b57cec5SDimitry Andric     // back to the head of the loop.
37730b57cec5SDimitry Andric     CFGBlock *LoopBackBlock = nullptr;
37740b57cec5SDimitry Andric     Succ = LoopBackBlock = createBlock();
37750b57cec5SDimitry Andric     LoopBackBlock->setLoopTarget(S);
37760b57cec5SDimitry Andric 
37770b57cec5SDimitry Andric     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
37780b57cec5SDimitry Andric     ContinueJumpTarget = JumpTarget(Succ, ScopePos);
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric     CFGBlock *BodyBlock = addStmt(S->getBody());
37810b57cec5SDimitry Andric 
37820b57cec5SDimitry Andric     if (!BodyBlock)
37830b57cec5SDimitry Andric       BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;"
37840b57cec5SDimitry Andric     else if (Block) {
37850b57cec5SDimitry Andric       if (badCFG)
37860b57cec5SDimitry Andric         return nullptr;
37870b57cec5SDimitry Andric     }
37880b57cec5SDimitry Andric 
37890b57cec5SDimitry Andric     // This new body block is a successor to our "exit" condition block.
37900b57cec5SDimitry Andric     addSuccessor(ExitConditionBlock, BodyBlock);
37910b57cec5SDimitry Andric   }
37920b57cec5SDimitry Andric 
37930b57cec5SDimitry Andric   // Link up the condition block with the code that follows the loop.
37940b57cec5SDimitry Andric   // (the false branch).
37950b57cec5SDimitry Andric   addSuccessor(ExitConditionBlock, LoopSuccessor);
37960b57cec5SDimitry Andric 
37970b57cec5SDimitry Andric   // Now create a prologue block to contain the collection expression.
37980b57cec5SDimitry Andric   Block = createBlock();
37990b57cec5SDimitry Andric   return addStmt(S->getCollection());
38000b57cec5SDimitry Andric }
38010b57cec5SDimitry Andric 
38020b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
38030b57cec5SDimitry Andric   // Inline the body.
38040b57cec5SDimitry Andric   return addStmt(S->getSubStmt());
38050b57cec5SDimitry Andric   // TODO: consider adding cleanups for the end of @autoreleasepool scope.
38060b57cec5SDimitry Andric }
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
38090b57cec5SDimitry Andric   // FIXME: Add locking 'primitives' to CFG for @synchronized.
38100b57cec5SDimitry Andric 
38110b57cec5SDimitry Andric   // Inline the body.
38120b57cec5SDimitry Andric   CFGBlock *SyncBlock = addStmt(S->getSynchBody());
38130b57cec5SDimitry Andric 
38140b57cec5SDimitry Andric   // The sync body starts its own basic block.  This makes it a little easier
38150b57cec5SDimitry Andric   // for diagnostic clients.
38160b57cec5SDimitry Andric   if (SyncBlock) {
38170b57cec5SDimitry Andric     if (badCFG)
38180b57cec5SDimitry Andric       return nullptr;
38190b57cec5SDimitry Andric 
38200b57cec5SDimitry Andric     Block = nullptr;
38210b57cec5SDimitry Andric     Succ = SyncBlock;
38220b57cec5SDimitry Andric   }
38230b57cec5SDimitry Andric 
38240b57cec5SDimitry Andric   // Add the @synchronized to the CFG.
38250b57cec5SDimitry Andric   autoCreateBlock();
38260b57cec5SDimitry Andric   appendStmt(Block, S);
38270b57cec5SDimitry Andric 
38280b57cec5SDimitry Andric   // Inline the sync expression.
38290b57cec5SDimitry Andric   return addStmt(S->getSynchExpr());
38300b57cec5SDimitry Andric }
38310b57cec5SDimitry Andric 
38320b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
38330b57cec5SDimitry Andric   autoCreateBlock();
38340b57cec5SDimitry Andric 
38350b57cec5SDimitry Andric   // Add the PseudoObject as the last thing.
38360b57cec5SDimitry Andric   appendStmt(Block, E);
38370b57cec5SDimitry Andric 
38380b57cec5SDimitry Andric   CFGBlock *lastBlock = Block;
38390b57cec5SDimitry Andric 
38400b57cec5SDimitry Andric   // Before that, evaluate all of the semantics in order.  In
38410b57cec5SDimitry Andric   // CFG-land, that means appending them in reverse order.
38420b57cec5SDimitry Andric   for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {
38430b57cec5SDimitry Andric     Expr *Semantic = E->getSemanticExpr(--i);
38440b57cec5SDimitry Andric 
38450b57cec5SDimitry Andric     // If the semantic is an opaque value, we're being asked to bind
38460b57cec5SDimitry Andric     // it to its source expression.
38470b57cec5SDimitry Andric     if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
38480b57cec5SDimitry Andric       Semantic = OVE->getSourceExpr();
38490b57cec5SDimitry Andric 
38500b57cec5SDimitry Andric     if (CFGBlock *B = Visit(Semantic))
38510b57cec5SDimitry Andric       lastBlock = B;
38520b57cec5SDimitry Andric   }
38530b57cec5SDimitry Andric 
38540b57cec5SDimitry Andric   return lastBlock;
38550b57cec5SDimitry Andric }
38560b57cec5SDimitry Andric 
38570b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {
38580b57cec5SDimitry Andric   CFGBlock *LoopSuccessor = nullptr;
38590b57cec5SDimitry Andric 
38600b57cec5SDimitry Andric   // Save local scope position because in case of condition variable ScopePos
38610b57cec5SDimitry Andric   // won't be restored when traversing AST.
3862bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
38630b57cec5SDimitry Andric 
38640b57cec5SDimitry Andric   // Create local scope for possible condition variable.
38650b57cec5SDimitry Andric   // Store scope position for continue statement.
38660b57cec5SDimitry Andric   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
38670b57cec5SDimitry Andric   if (VarDecl *VD = W->getConditionVariable()) {
38680b57cec5SDimitry Andric     addLocalScopeForVarDecl(VD);
38690b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
38700b57cec5SDimitry Andric   }
38710b57cec5SDimitry Andric   addLoopExit(W);
38720b57cec5SDimitry Andric 
38730b57cec5SDimitry Andric   // "while" is a control-flow statement.  Thus we stop processing the current
38740b57cec5SDimitry Andric   // block.
38750b57cec5SDimitry Andric   if (Block) {
38760b57cec5SDimitry Andric     if (badCFG)
38770b57cec5SDimitry Andric       return nullptr;
38780b57cec5SDimitry Andric     LoopSuccessor = Block;
38790b57cec5SDimitry Andric     Block = nullptr;
38800b57cec5SDimitry Andric   } else {
38810b57cec5SDimitry Andric     LoopSuccessor = Succ;
38820b57cec5SDimitry Andric   }
38830b57cec5SDimitry Andric 
38840b57cec5SDimitry Andric   CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;
38850b57cec5SDimitry Andric 
38860b57cec5SDimitry Andric   // Process the loop body.
38870b57cec5SDimitry Andric   {
38880b57cec5SDimitry Andric     assert(W->getBody());
38890b57cec5SDimitry Andric 
38900b57cec5SDimitry Andric     // Save the current values for Block, Succ, continue and break targets.
3891bdd1243dSDimitry Andric     SaveAndRestore save_Block(Block), save_Succ(Succ);
3892bdd1243dSDimitry Andric     SaveAndRestore save_continue(ContinueJumpTarget),
38930b57cec5SDimitry Andric         save_break(BreakJumpTarget);
38940b57cec5SDimitry Andric 
38950b57cec5SDimitry Andric     // Create an empty block to represent the transition block for looping back
38960b57cec5SDimitry Andric     // to the head of the loop.
38970b57cec5SDimitry Andric     Succ = TransitionBlock = createBlock(false);
38980b57cec5SDimitry Andric     TransitionBlock->setLoopTarget(W);
38990b57cec5SDimitry Andric     ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
39000b57cec5SDimitry Andric 
39010b57cec5SDimitry Andric     // All breaks should go to the code following the loop.
39020b57cec5SDimitry Andric     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
39030b57cec5SDimitry Andric 
39040b57cec5SDimitry Andric     // Loop body should end with destructor of Condition variable (if any).
39050b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);
39060b57cec5SDimitry Andric 
39070b57cec5SDimitry Andric     // If body is not a compound statement create implicit scope
39080b57cec5SDimitry Andric     // and add destructors.
39090b57cec5SDimitry Andric     if (!isa<CompoundStmt>(W->getBody()))
39100b57cec5SDimitry Andric       addLocalScopeAndDtors(W->getBody());
39110b57cec5SDimitry Andric 
39120b57cec5SDimitry Andric     // Create the body.  The returned block is the entry to the loop body.
39130b57cec5SDimitry Andric     BodyBlock = addStmt(W->getBody());
39140b57cec5SDimitry Andric 
39150b57cec5SDimitry Andric     if (!BodyBlock)
39160b57cec5SDimitry Andric       BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
39170b57cec5SDimitry Andric     else if (Block && badCFG)
39180b57cec5SDimitry Andric       return nullptr;
39190b57cec5SDimitry Andric   }
39200b57cec5SDimitry Andric 
39210b57cec5SDimitry Andric   // Because of short-circuit evaluation, the condition of the loop can span
39220b57cec5SDimitry Andric   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
39230b57cec5SDimitry Andric   // evaluate the condition.
39240b57cec5SDimitry Andric   CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;
39250b57cec5SDimitry Andric 
39260b57cec5SDimitry Andric   do {
39270b57cec5SDimitry Andric     Expr *C = W->getCond();
39280b57cec5SDimitry Andric 
39290b57cec5SDimitry Andric     // Specially handle logical operators, which have a slightly
39300b57cec5SDimitry Andric     // more optimal CFG representation.
39310b57cec5SDimitry Andric     if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))
39320b57cec5SDimitry Andric       if (Cond->isLogicalOp()) {
39330b57cec5SDimitry Andric         std::tie(EntryConditionBlock, ExitConditionBlock) =
39340b57cec5SDimitry Andric             VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);
39350b57cec5SDimitry Andric         break;
39360b57cec5SDimitry Andric       }
39370b57cec5SDimitry Andric 
39380b57cec5SDimitry Andric     // The default case when not handling logical operators.
39390b57cec5SDimitry Andric     ExitConditionBlock = createBlock(false);
39400b57cec5SDimitry Andric     ExitConditionBlock->setTerminator(W);
39410b57cec5SDimitry Andric 
39420b57cec5SDimitry Andric     // Now add the actual condition to the condition block.
39430b57cec5SDimitry Andric     // Because the condition itself may contain control-flow, new blocks may
39440b57cec5SDimitry Andric     // be created.  Thus we update "Succ" after adding the condition.
39450b57cec5SDimitry Andric     Block = ExitConditionBlock;
39460b57cec5SDimitry Andric     Block = EntryConditionBlock = addStmt(C);
39470b57cec5SDimitry Andric 
39480b57cec5SDimitry Andric     // If this block contains a condition variable, add both the condition
39490b57cec5SDimitry Andric     // variable and initializer to the CFG.
39500b57cec5SDimitry Andric     if (VarDecl *VD = W->getConditionVariable()) {
39510b57cec5SDimitry Andric       if (Expr *Init = VD->getInit()) {
39520b57cec5SDimitry Andric         autoCreateBlock();
39530b57cec5SDimitry Andric         const DeclStmt *DS = W->getConditionVariableDeclStmt();
39540b57cec5SDimitry Andric         assert(DS->isSingleDecl());
39550b57cec5SDimitry Andric         findConstructionContexts(
39560b57cec5SDimitry Andric             ConstructionContextLayer::create(cfg->getBumpVectorContext(),
39570b57cec5SDimitry Andric                                              const_cast<DeclStmt *>(DS)),
39580b57cec5SDimitry Andric             Init);
39590b57cec5SDimitry Andric         appendStmt(Block, DS);
39600b57cec5SDimitry Andric         EntryConditionBlock = addStmt(Init);
39610b57cec5SDimitry Andric         assert(Block == EntryConditionBlock);
39620b57cec5SDimitry Andric         maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);
39630b57cec5SDimitry Andric       }
39640b57cec5SDimitry Andric     }
39650b57cec5SDimitry Andric 
39660b57cec5SDimitry Andric     if (Block && badCFG)
39670b57cec5SDimitry Andric       return nullptr;
39680b57cec5SDimitry Andric 
39690b57cec5SDimitry Andric     // See if this is a known constant.
39700b57cec5SDimitry Andric     const TryResult& KnownVal = tryEvaluateBool(C);
39710b57cec5SDimitry Andric 
39720b57cec5SDimitry Andric     // Add the loop body entry as a successor to the condition.
39730b57cec5SDimitry Andric     addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);
39740b57cec5SDimitry Andric     // Link up the condition block with the code that follows the loop.  (the
39750b57cec5SDimitry Andric     // false branch).
39760b57cec5SDimitry Andric     addSuccessor(ExitConditionBlock,
39770b57cec5SDimitry Andric                  KnownVal.isTrue() ? nullptr : LoopSuccessor);
39780b57cec5SDimitry Andric   } while(false);
39790b57cec5SDimitry Andric 
39800b57cec5SDimitry Andric   // Link up the loop-back block to the entry condition block.
39810b57cec5SDimitry Andric   addSuccessor(TransitionBlock, EntryConditionBlock);
39820b57cec5SDimitry Andric 
39830b57cec5SDimitry Andric   // There can be no more statements in the condition block since we loop back
39840b57cec5SDimitry Andric   // to this block.  NULL out Block to force lazy creation of another block.
39850b57cec5SDimitry Andric   Block = nullptr;
39860b57cec5SDimitry Andric 
39870b57cec5SDimitry Andric   // Return the condition block, which is the dominating block for the loop.
39880b57cec5SDimitry Andric   Succ = EntryConditionBlock;
39890b57cec5SDimitry Andric   return EntryConditionBlock;
39900b57cec5SDimitry Andric }
39910b57cec5SDimitry Andric 
399281ad6265SDimitry Andric CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
399381ad6265SDimitry Andric                                              AddStmtChoice asc) {
399481ad6265SDimitry Andric   if (asc.alwaysAdd(*this, A)) {
399581ad6265SDimitry Andric     autoCreateBlock();
399681ad6265SDimitry Andric     appendStmt(Block, A);
399781ad6265SDimitry Andric   }
399881ad6265SDimitry Andric 
399981ad6265SDimitry Andric   CFGBlock *B = Block;
400081ad6265SDimitry Andric 
400181ad6265SDimitry Andric   if (CFGBlock *R = Visit(A->getSubExpr()))
400281ad6265SDimitry Andric     B = R;
400381ad6265SDimitry Andric 
400481ad6265SDimitry Andric   auto *OVE = dyn_cast<OpaqueValueExpr>(A->getCommonExpr());
400581ad6265SDimitry Andric   assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "
400681ad6265SDimitry Andric                 "OpaqueValueExpr!");
400781ad6265SDimitry Andric   if (CFGBlock *R = Visit(OVE->getSourceExpr()))
400881ad6265SDimitry Andric     B = R;
400981ad6265SDimitry Andric 
401081ad6265SDimitry Andric   return B;
401181ad6265SDimitry Andric }
401281ad6265SDimitry Andric 
4013349cc55cSDimitry Andric CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {
4014349cc55cSDimitry Andric   // ObjCAtCatchStmt are treated like labels, so they are the first statement
4015349cc55cSDimitry Andric   // in a block.
4016349cc55cSDimitry Andric 
4017349cc55cSDimitry Andric   // Save local scope position because in case of exception variable ScopePos
4018349cc55cSDimitry Andric   // won't be restored when traversing AST.
4019bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
4020349cc55cSDimitry Andric 
4021349cc55cSDimitry Andric   if (CS->getCatchBody())
4022349cc55cSDimitry Andric     addStmt(CS->getCatchBody());
4023349cc55cSDimitry Andric 
4024349cc55cSDimitry Andric   CFGBlock *CatchBlock = Block;
4025349cc55cSDimitry Andric   if (!CatchBlock)
4026349cc55cSDimitry Andric     CatchBlock = createBlock();
4027349cc55cSDimitry Andric 
4028349cc55cSDimitry Andric   appendStmt(CatchBlock, CS);
4029349cc55cSDimitry Andric 
4030349cc55cSDimitry Andric   // Also add the ObjCAtCatchStmt as a label, like with regular labels.
4031349cc55cSDimitry Andric   CatchBlock->setLabel(CS);
4032349cc55cSDimitry Andric 
4033349cc55cSDimitry Andric   // Bail out if the CFG is bad.
4034349cc55cSDimitry Andric   if (badCFG)
4035349cc55cSDimitry Andric     return nullptr;
4036349cc55cSDimitry Andric 
4037349cc55cSDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
4038349cc55cSDimitry Andric   Block = nullptr;
4039349cc55cSDimitry Andric 
4040349cc55cSDimitry Andric   return CatchBlock;
40410b57cec5SDimitry Andric }
40420b57cec5SDimitry Andric 
40430b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
40440b57cec5SDimitry Andric   // If we were in the middle of a block we stop processing that block.
40450b57cec5SDimitry Andric   if (badCFG)
40460b57cec5SDimitry Andric     return nullptr;
40470b57cec5SDimitry Andric 
40480b57cec5SDimitry Andric   // Create the new block.
40490b57cec5SDimitry Andric   Block = createBlock(false);
40500b57cec5SDimitry Andric 
4051349cc55cSDimitry Andric   if (TryTerminatedBlock)
4052349cc55cSDimitry Andric     // The current try statement is the only successor.
4053349cc55cSDimitry Andric     addSuccessor(Block, TryTerminatedBlock);
4054349cc55cSDimitry Andric   else
4055349cc55cSDimitry Andric     // otherwise the Exit block is the only successor.
40560b57cec5SDimitry Andric     addSuccessor(Block, &cfg->getExit());
40570b57cec5SDimitry Andric 
40580b57cec5SDimitry Andric   // Add the statement to the block.  This may create new blocks if S contains
40590b57cec5SDimitry Andric   // control-flow (short-circuit operations).
40600b57cec5SDimitry Andric   return VisitStmt(S, AddStmtChoice::AlwaysAdd);
40610b57cec5SDimitry Andric }
40620b57cec5SDimitry Andric 
4063349cc55cSDimitry Andric CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {
4064349cc55cSDimitry Andric   // "@try"/"@catch" is a control-flow statement.  Thus we stop processing the
4065349cc55cSDimitry Andric   // current block.
4066349cc55cSDimitry Andric   CFGBlock *TrySuccessor = nullptr;
4067349cc55cSDimitry Andric 
4068349cc55cSDimitry Andric   if (Block) {
4069349cc55cSDimitry Andric     if (badCFG)
4070349cc55cSDimitry Andric       return nullptr;
4071349cc55cSDimitry Andric     TrySuccessor = Block;
4072349cc55cSDimitry Andric   } else
4073349cc55cSDimitry Andric     TrySuccessor = Succ;
4074349cc55cSDimitry Andric 
4075349cc55cSDimitry Andric   // FIXME: Implement @finally support.
4076349cc55cSDimitry Andric   if (Terminator->getFinallyStmt())
4077349cc55cSDimitry Andric     return NYS();
4078349cc55cSDimitry Andric 
4079349cc55cSDimitry Andric   CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
4080349cc55cSDimitry Andric 
4081349cc55cSDimitry Andric   // Create a new block that will contain the try statement.
4082349cc55cSDimitry Andric   CFGBlock *NewTryTerminatedBlock = createBlock(false);
4083349cc55cSDimitry Andric   // Add the terminator in the try block.
4084349cc55cSDimitry Andric   NewTryTerminatedBlock->setTerminator(Terminator);
4085349cc55cSDimitry Andric 
4086349cc55cSDimitry Andric   bool HasCatchAll = false;
4087349cc55cSDimitry Andric   for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) {
4088349cc55cSDimitry Andric     // The code after the try is the implicit successor.
4089349cc55cSDimitry Andric     Succ = TrySuccessor;
4090349cc55cSDimitry Andric     if (CS->hasEllipsis()) {
4091349cc55cSDimitry Andric       HasCatchAll = true;
4092349cc55cSDimitry Andric     }
4093349cc55cSDimitry Andric     Block = nullptr;
4094349cc55cSDimitry Andric     CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);
4095349cc55cSDimitry Andric     if (!CatchBlock)
4096349cc55cSDimitry Andric       return nullptr;
4097349cc55cSDimitry Andric     // Add this block to the list of successors for the block with the try
4098349cc55cSDimitry Andric     // statement.
4099349cc55cSDimitry Andric     addSuccessor(NewTryTerminatedBlock, CatchBlock);
4100349cc55cSDimitry Andric   }
4101349cc55cSDimitry Andric 
4102349cc55cSDimitry Andric   // FIXME: This needs updating when @finally support is added.
4103349cc55cSDimitry Andric   if (!HasCatchAll) {
4104349cc55cSDimitry Andric     if (PrevTryTerminatedBlock)
4105349cc55cSDimitry Andric       addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
4106349cc55cSDimitry Andric     else
4107349cc55cSDimitry Andric       addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
4108349cc55cSDimitry Andric   }
4109349cc55cSDimitry Andric 
4110349cc55cSDimitry Andric   // The code after the try is the implicit successor.
4111349cc55cSDimitry Andric   Succ = TrySuccessor;
4112349cc55cSDimitry Andric 
4113349cc55cSDimitry Andric   // Save the current "try" context.
4114bdd1243dSDimitry Andric   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
4115349cc55cSDimitry Andric   cfg->addTryDispatchBlock(TryTerminatedBlock);
4116349cc55cSDimitry Andric 
4117349cc55cSDimitry Andric   assert(Terminator->getTryBody() && "try must contain a non-NULL body");
4118349cc55cSDimitry Andric   Block = nullptr;
4119349cc55cSDimitry Andric   return addStmt(Terminator->getTryBody());
4120349cc55cSDimitry Andric }
4121349cc55cSDimitry Andric 
41220b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
41230b57cec5SDimitry Andric                                            AddStmtChoice asc) {
41240b57cec5SDimitry Andric   findConstructionContextsForArguments(ME);
41250b57cec5SDimitry Andric 
41260b57cec5SDimitry Andric   autoCreateBlock();
41270b57cec5SDimitry Andric   appendObjCMessage(Block, ME);
41280b57cec5SDimitry Andric 
41290b57cec5SDimitry Andric   return VisitChildren(ME);
41300b57cec5SDimitry Andric }
41310b57cec5SDimitry Andric 
41320b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {
41330b57cec5SDimitry Andric   // If we were in the middle of a block we stop processing that block.
41340b57cec5SDimitry Andric   if (badCFG)
41350b57cec5SDimitry Andric     return nullptr;
41360b57cec5SDimitry Andric 
41370b57cec5SDimitry Andric   // Create the new block.
41380b57cec5SDimitry Andric   Block = createBlock(false);
41390b57cec5SDimitry Andric 
41400b57cec5SDimitry Andric   if (TryTerminatedBlock)
41410b57cec5SDimitry Andric     // The current try statement is the only successor.
41420b57cec5SDimitry Andric     addSuccessor(Block, TryTerminatedBlock);
41430b57cec5SDimitry Andric   else
41440b57cec5SDimitry Andric     // otherwise the Exit block is the only successor.
41450b57cec5SDimitry Andric     addSuccessor(Block, &cfg->getExit());
41460b57cec5SDimitry Andric 
41470b57cec5SDimitry Andric   // Add the statement to the block.  This may create new blocks if S contains
41480b57cec5SDimitry Andric   // control-flow (short-circuit operations).
41490b57cec5SDimitry Andric   return VisitStmt(T, AddStmtChoice::AlwaysAdd);
41500b57cec5SDimitry Andric }
41510b57cec5SDimitry Andric 
415281ad6265SDimitry Andric CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {
415381ad6265SDimitry Andric   if (asc.alwaysAdd(*this, S)) {
415481ad6265SDimitry Andric     autoCreateBlock();
415581ad6265SDimitry Andric     appendStmt(Block, S);
415681ad6265SDimitry Andric   }
415781ad6265SDimitry Andric 
415881ad6265SDimitry Andric   // C++ [expr.typeid]p3:
415981ad6265SDimitry Andric   //   When typeid is applied to an expression other than an glvalue of a
416081ad6265SDimitry Andric   //   polymorphic class type [...] [the] expression is an unevaluated
416181ad6265SDimitry Andric   //   operand. [...]
416281ad6265SDimitry Andric   // We add only potentially evaluated statements to the block to avoid
416381ad6265SDimitry Andric   // CFG generation for unevaluated operands.
416406c3fb27SDimitry Andric   if (!S->isTypeDependent() && S->isPotentiallyEvaluated())
416581ad6265SDimitry Andric     return VisitChildren(S);
416681ad6265SDimitry Andric 
416781ad6265SDimitry Andric   // Return block without CFG for unevaluated operands.
416881ad6265SDimitry Andric   return Block;
416981ad6265SDimitry Andric }
417081ad6265SDimitry Andric 
41710b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
41720b57cec5SDimitry Andric   CFGBlock *LoopSuccessor = nullptr;
41730b57cec5SDimitry Andric 
41740b57cec5SDimitry Andric   addLoopExit(D);
41750b57cec5SDimitry Andric 
41760b57cec5SDimitry Andric   // "do...while" is a control-flow statement.  Thus we stop processing the
41770b57cec5SDimitry Andric   // current block.
41780b57cec5SDimitry Andric   if (Block) {
41790b57cec5SDimitry Andric     if (badCFG)
41800b57cec5SDimitry Andric       return nullptr;
41810b57cec5SDimitry Andric     LoopSuccessor = Block;
41820b57cec5SDimitry Andric   } else
41830b57cec5SDimitry Andric     LoopSuccessor = Succ;
41840b57cec5SDimitry Andric 
41850b57cec5SDimitry Andric   // Because of short-circuit evaluation, the condition of the loop can span
41860b57cec5SDimitry Andric   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
41870b57cec5SDimitry Andric   // evaluate the condition.
41880b57cec5SDimitry Andric   CFGBlock *ExitConditionBlock = createBlock(false);
41890b57cec5SDimitry Andric   CFGBlock *EntryConditionBlock = ExitConditionBlock;
41900b57cec5SDimitry Andric 
41910b57cec5SDimitry Andric   // Set the terminator for the "exit" condition block.
41920b57cec5SDimitry Andric   ExitConditionBlock->setTerminator(D);
41930b57cec5SDimitry Andric 
41940b57cec5SDimitry Andric   // Now add the actual condition to the condition block.  Because the condition
41950b57cec5SDimitry Andric   // itself may contain control-flow, new blocks may be created.
41960b57cec5SDimitry Andric   if (Stmt *C = D->getCond()) {
41970b57cec5SDimitry Andric     Block = ExitConditionBlock;
41980b57cec5SDimitry Andric     EntryConditionBlock = addStmt(C);
41990b57cec5SDimitry Andric     if (Block) {
42000b57cec5SDimitry Andric       if (badCFG)
42010b57cec5SDimitry Andric         return nullptr;
42020b57cec5SDimitry Andric     }
42030b57cec5SDimitry Andric   }
42040b57cec5SDimitry Andric 
42050b57cec5SDimitry Andric   // The condition block is the implicit successor for the loop body.
42060b57cec5SDimitry Andric   Succ = EntryConditionBlock;
42070b57cec5SDimitry Andric 
42080b57cec5SDimitry Andric   // See if this is a known constant.
42090b57cec5SDimitry Andric   const TryResult &KnownVal = tryEvaluateBool(D->getCond());
42100b57cec5SDimitry Andric 
42110b57cec5SDimitry Andric   // Process the loop body.
42120b57cec5SDimitry Andric   CFGBlock *BodyBlock = nullptr;
42130b57cec5SDimitry Andric   {
42140b57cec5SDimitry Andric     assert(D->getBody());
42150b57cec5SDimitry Andric 
42160b57cec5SDimitry Andric     // Save the current values for Block, Succ, and continue and break targets
4217bdd1243dSDimitry Andric     SaveAndRestore save_Block(Block), save_Succ(Succ);
4218bdd1243dSDimitry Andric     SaveAndRestore save_continue(ContinueJumpTarget),
42190b57cec5SDimitry Andric         save_break(BreakJumpTarget);
42200b57cec5SDimitry Andric 
42210b57cec5SDimitry Andric     // All continues within this loop should go to the condition block
42220b57cec5SDimitry Andric     ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
42230b57cec5SDimitry Andric 
42240b57cec5SDimitry Andric     // All breaks should go to the code following the loop.
42250b57cec5SDimitry Andric     BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
42260b57cec5SDimitry Andric 
42270b57cec5SDimitry Andric     // NULL out Block to force lazy instantiation of blocks for the body.
42280b57cec5SDimitry Andric     Block = nullptr;
42290b57cec5SDimitry Andric 
42300b57cec5SDimitry Andric     // If body is not a compound statement create implicit scope
42310b57cec5SDimitry Andric     // and add destructors.
42320b57cec5SDimitry Andric     if (!isa<CompoundStmt>(D->getBody()))
42330b57cec5SDimitry Andric       addLocalScopeAndDtors(D->getBody());
42340b57cec5SDimitry Andric 
42350b57cec5SDimitry Andric     // Create the body.  The returned block is the entry to the loop body.
42360b57cec5SDimitry Andric     BodyBlock = addStmt(D->getBody());
42370b57cec5SDimitry Andric 
42380b57cec5SDimitry Andric     if (!BodyBlock)
42390b57cec5SDimitry Andric       BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
42400b57cec5SDimitry Andric     else if (Block) {
42410b57cec5SDimitry Andric       if (badCFG)
42420b57cec5SDimitry Andric         return nullptr;
42430b57cec5SDimitry Andric     }
42440b57cec5SDimitry Andric 
42450b57cec5SDimitry Andric     // Add an intermediate block between the BodyBlock and the
42460b57cec5SDimitry Andric     // ExitConditionBlock to represent the "loop back" transition.  Create an
42470b57cec5SDimitry Andric     // empty block to represent the transition block for looping back to the
42480b57cec5SDimitry Andric     // head of the loop.
42490b57cec5SDimitry Andric     // FIXME: Can we do this more efficiently without adding another block?
42500b57cec5SDimitry Andric     Block = nullptr;
42510b57cec5SDimitry Andric     Succ = BodyBlock;
42520b57cec5SDimitry Andric     CFGBlock *LoopBackBlock = createBlock();
42530b57cec5SDimitry Andric     LoopBackBlock->setLoopTarget(D);
42540b57cec5SDimitry Andric 
42550b57cec5SDimitry Andric     if (!KnownVal.isFalse())
42560b57cec5SDimitry Andric       // Add the loop body entry as a successor to the condition.
42570b57cec5SDimitry Andric       addSuccessor(ExitConditionBlock, LoopBackBlock);
42580b57cec5SDimitry Andric     else
42590b57cec5SDimitry Andric       addSuccessor(ExitConditionBlock, nullptr);
42600b57cec5SDimitry Andric   }
42610b57cec5SDimitry Andric 
42620b57cec5SDimitry Andric   // Link up the condition block with the code that follows the loop.
42630b57cec5SDimitry Andric   // (the false branch).
42640b57cec5SDimitry Andric   addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
42650b57cec5SDimitry Andric 
42660b57cec5SDimitry Andric   // There can be no more statements in the body block(s) since we loop back to
42670b57cec5SDimitry Andric   // the body.  NULL out Block to force lazy creation of another block.
42680b57cec5SDimitry Andric   Block = nullptr;
42690b57cec5SDimitry Andric 
42700b57cec5SDimitry Andric   // Return the loop body, which is the dominating block for the loop.
42710b57cec5SDimitry Andric   Succ = BodyBlock;
42720b57cec5SDimitry Andric   return BodyBlock;
42730b57cec5SDimitry Andric }
42740b57cec5SDimitry Andric 
42750b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {
42760b57cec5SDimitry Andric   // "continue" is a control-flow statement.  Thus we stop processing the
42770b57cec5SDimitry Andric   // current block.
42780b57cec5SDimitry Andric   if (badCFG)
42790b57cec5SDimitry Andric     return nullptr;
42800b57cec5SDimitry Andric 
42810b57cec5SDimitry Andric   // Now create a new block that ends with the continue statement.
42820b57cec5SDimitry Andric   Block = createBlock(false);
42830b57cec5SDimitry Andric   Block->setTerminator(C);
42840b57cec5SDimitry Andric 
42850b57cec5SDimitry Andric   // If there is no target for the continue, then we are looking at an
42860b57cec5SDimitry Andric   // incomplete AST.  This means the CFG cannot be constructed.
42870b57cec5SDimitry Andric   if (ContinueJumpTarget.block) {
42880b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);
42890b57cec5SDimitry Andric     addSuccessor(Block, ContinueJumpTarget.block);
42900b57cec5SDimitry Andric   } else
42910b57cec5SDimitry Andric     badCFG = true;
42920b57cec5SDimitry Andric 
42930b57cec5SDimitry Andric   return Block;
42940b57cec5SDimitry Andric }
42950b57cec5SDimitry Andric 
42960b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
42970b57cec5SDimitry Andric                                                     AddStmtChoice asc) {
42980b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
42990b57cec5SDimitry Andric     autoCreateBlock();
43000b57cec5SDimitry Andric     appendStmt(Block, E);
43010b57cec5SDimitry Andric   }
43020b57cec5SDimitry Andric 
43030b57cec5SDimitry Andric   // VLA types have expressions that must be evaluated.
43045ffd83dbSDimitry Andric   // Evaluation is done only for `sizeof`.
43055ffd83dbSDimitry Andric 
43065ffd83dbSDimitry Andric   if (E->getKind() != UETT_SizeOf)
43075ffd83dbSDimitry Andric     return Block;
43085ffd83dbSDimitry Andric 
43090b57cec5SDimitry Andric   CFGBlock *lastBlock = Block;
43100b57cec5SDimitry Andric 
43110b57cec5SDimitry Andric   if (E->isArgumentType()) {
43120b57cec5SDimitry Andric     for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());
43130b57cec5SDimitry Andric          VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))
43140b57cec5SDimitry Andric       lastBlock = addStmt(VA->getSizeExpr());
43150b57cec5SDimitry Andric   }
43160b57cec5SDimitry Andric   return lastBlock;
43170b57cec5SDimitry Andric }
43180b57cec5SDimitry Andric 
43190b57cec5SDimitry Andric /// VisitStmtExpr - Utility method to handle (nested) statement
43200b57cec5SDimitry Andric ///  expressions (a GCC extension).
43210b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
43220b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, SE)) {
43230b57cec5SDimitry Andric     autoCreateBlock();
43240b57cec5SDimitry Andric     appendStmt(Block, SE);
43250b57cec5SDimitry Andric   }
4326a7dea167SDimitry Andric   return VisitCompoundStmt(SE->getSubStmt(), /*ExternallyDestructed=*/true);
43270b57cec5SDimitry Andric }
43280b57cec5SDimitry Andric 
43290b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {
43300b57cec5SDimitry Andric   // "switch" is a control-flow statement.  Thus we stop processing the current
43310b57cec5SDimitry Andric   // block.
43320b57cec5SDimitry Andric   CFGBlock *SwitchSuccessor = nullptr;
43330b57cec5SDimitry Andric 
43340b57cec5SDimitry Andric   // Save local scope position because in case of condition variable ScopePos
43350b57cec5SDimitry Andric   // won't be restored when traversing AST.
4336bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
43370b57cec5SDimitry Andric 
43380b57cec5SDimitry Andric   // Create local scope for C++17 switch init-stmt if one exists.
43390b57cec5SDimitry Andric   if (Stmt *Init = Terminator->getInit())
43400b57cec5SDimitry Andric     addLocalScopeForStmt(Init);
43410b57cec5SDimitry Andric 
43420b57cec5SDimitry Andric   // Create local scope for possible condition variable.
43430b57cec5SDimitry Andric   // Store scope position. Add implicit destructor.
43440b57cec5SDimitry Andric   if (VarDecl *VD = Terminator->getConditionVariable())
43450b57cec5SDimitry Andric     addLocalScopeForVarDecl(VD);
43460b57cec5SDimitry Andric 
43470b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);
43480b57cec5SDimitry Andric 
43490b57cec5SDimitry Andric   if (Block) {
43500b57cec5SDimitry Andric     if (badCFG)
43510b57cec5SDimitry Andric       return nullptr;
43520b57cec5SDimitry Andric     SwitchSuccessor = Block;
43530b57cec5SDimitry Andric   } else SwitchSuccessor = Succ;
43540b57cec5SDimitry Andric 
43550b57cec5SDimitry Andric   // Save the current "switch" context.
4356bdd1243dSDimitry Andric   SaveAndRestore save_switch(SwitchTerminatedBlock),
43570b57cec5SDimitry Andric       save_default(DefaultCaseBlock);
4358bdd1243dSDimitry Andric   SaveAndRestore save_break(BreakJumpTarget);
43590b57cec5SDimitry Andric 
43600b57cec5SDimitry Andric   // Set the "default" case to be the block after the switch statement.  If the
43610b57cec5SDimitry Andric   // switch statement contains a "default:", this value will be overwritten with
43620b57cec5SDimitry Andric   // the block for that code.
43630b57cec5SDimitry Andric   DefaultCaseBlock = SwitchSuccessor;
43640b57cec5SDimitry Andric 
43650b57cec5SDimitry Andric   // Create a new block that will contain the switch statement.
43660b57cec5SDimitry Andric   SwitchTerminatedBlock = createBlock(false);
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric   // Now process the switch body.  The code after the switch is the implicit
43690b57cec5SDimitry Andric   // successor.
43700b57cec5SDimitry Andric   Succ = SwitchSuccessor;
43710b57cec5SDimitry Andric   BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
43720b57cec5SDimitry Andric 
43730b57cec5SDimitry Andric   // When visiting the body, the case statements should automatically get linked
43740b57cec5SDimitry Andric   // up to the switch.  We also don't keep a pointer to the body, since all
43750b57cec5SDimitry Andric   // control-flow from the switch goes to case/default statements.
43760b57cec5SDimitry Andric   assert(Terminator->getBody() && "switch must contain a non-NULL body");
43770b57cec5SDimitry Andric   Block = nullptr;
43780b57cec5SDimitry Andric 
43790b57cec5SDimitry Andric   // For pruning unreachable case statements, save the current state
43800b57cec5SDimitry Andric   // for tracking the condition value.
4381bdd1243dSDimitry Andric   SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, false);
43820b57cec5SDimitry Andric 
43830b57cec5SDimitry Andric   // Determine if the switch condition can be explicitly evaluated.
43840b57cec5SDimitry Andric   assert(Terminator->getCond() && "switch condition must be non-NULL");
43850b57cec5SDimitry Andric   Expr::EvalResult result;
43860b57cec5SDimitry Andric   bool b = tryEvaluate(Terminator->getCond(), result);
4387bdd1243dSDimitry Andric   SaveAndRestore save_switchCond(switchCond, b ? &result : nullptr);
43880b57cec5SDimitry Andric 
43890b57cec5SDimitry Andric   // If body is not a compound statement create implicit scope
43900b57cec5SDimitry Andric   // and add destructors.
43910b57cec5SDimitry Andric   if (!isa<CompoundStmt>(Terminator->getBody()))
43920b57cec5SDimitry Andric     addLocalScopeAndDtors(Terminator->getBody());
43930b57cec5SDimitry Andric 
43940b57cec5SDimitry Andric   addStmt(Terminator->getBody());
43950b57cec5SDimitry Andric   if (Block) {
43960b57cec5SDimitry Andric     if (badCFG)
43970b57cec5SDimitry Andric       return nullptr;
43980b57cec5SDimitry Andric   }
43990b57cec5SDimitry Andric 
44000b57cec5SDimitry Andric   // If we have no "default:" case, the default transition is to the code
44010b57cec5SDimitry Andric   // following the switch body.  Moreover, take into account if all the
44020b57cec5SDimitry Andric   // cases of a switch are covered (e.g., switching on an enum value).
44030b57cec5SDimitry Andric   //
44040b57cec5SDimitry Andric   // Note: We add a successor to a switch that is considered covered yet has no
44050b57cec5SDimitry Andric   //       case statements if the enumeration has no enumerators.
44060b57cec5SDimitry Andric   bool SwitchAlwaysHasSuccessor = false;
44070b57cec5SDimitry Andric   SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;
44080b57cec5SDimitry Andric   SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() &&
44090b57cec5SDimitry Andric                               Terminator->getSwitchCaseList();
44100b57cec5SDimitry Andric   addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,
44110b57cec5SDimitry Andric                !SwitchAlwaysHasSuccessor);
44120b57cec5SDimitry Andric 
44130b57cec5SDimitry Andric   // Add the terminator and condition in the switch block.
44140b57cec5SDimitry Andric   SwitchTerminatedBlock->setTerminator(Terminator);
44150b57cec5SDimitry Andric   Block = SwitchTerminatedBlock;
44160b57cec5SDimitry Andric   CFGBlock *LastBlock = addStmt(Terminator->getCond());
44170b57cec5SDimitry Andric 
44180b57cec5SDimitry Andric   // If the SwitchStmt contains a condition variable, add both the
44190b57cec5SDimitry Andric   // SwitchStmt and the condition variable initialization to the CFG.
44200b57cec5SDimitry Andric   if (VarDecl *VD = Terminator->getConditionVariable()) {
44210b57cec5SDimitry Andric     if (Expr *Init = VD->getInit()) {
44220b57cec5SDimitry Andric       autoCreateBlock();
44230b57cec5SDimitry Andric       appendStmt(Block, Terminator->getConditionVariableDeclStmt());
44240b57cec5SDimitry Andric       LastBlock = addStmt(Init);
44250b57cec5SDimitry Andric       maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);
44260b57cec5SDimitry Andric     }
44270b57cec5SDimitry Andric   }
44280b57cec5SDimitry Andric 
44290b57cec5SDimitry Andric   // Finally, if the SwitchStmt contains a C++17 init-stmt, add it to the CFG.
44300b57cec5SDimitry Andric   if (Stmt *Init = Terminator->getInit()) {
44310b57cec5SDimitry Andric     autoCreateBlock();
44320b57cec5SDimitry Andric     LastBlock = addStmt(Init);
44330b57cec5SDimitry Andric   }
44340b57cec5SDimitry Andric 
44350b57cec5SDimitry Andric   return LastBlock;
44360b57cec5SDimitry Andric }
44370b57cec5SDimitry Andric 
44380b57cec5SDimitry Andric static bool shouldAddCase(bool &switchExclusivelyCovered,
44390b57cec5SDimitry Andric                           const Expr::EvalResult *switchCond,
44400b57cec5SDimitry Andric                           const CaseStmt *CS,
44410b57cec5SDimitry Andric                           ASTContext &Ctx) {
44420b57cec5SDimitry Andric   if (!switchCond)
44430b57cec5SDimitry Andric     return true;
44440b57cec5SDimitry Andric 
44450b57cec5SDimitry Andric   bool addCase = false;
44460b57cec5SDimitry Andric 
44470b57cec5SDimitry Andric   if (!switchExclusivelyCovered) {
44480b57cec5SDimitry Andric     if (switchCond->Val.isInt()) {
44490b57cec5SDimitry Andric       // Evaluate the LHS of the case value.
44500b57cec5SDimitry Andric       const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx);
44510b57cec5SDimitry Andric       const llvm::APSInt &condInt = switchCond->Val.getInt();
44520b57cec5SDimitry Andric 
44530b57cec5SDimitry Andric       if (condInt == lhsInt) {
44540b57cec5SDimitry Andric         addCase = true;
44550b57cec5SDimitry Andric         switchExclusivelyCovered = true;
44560b57cec5SDimitry Andric       }
44570b57cec5SDimitry Andric       else if (condInt > lhsInt) {
44580b57cec5SDimitry Andric         if (const Expr *RHS = CS->getRHS()) {
44590b57cec5SDimitry Andric           // Evaluate the RHS of the case value.
44600b57cec5SDimitry Andric           const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);
44610b57cec5SDimitry Andric           if (V2 >= condInt) {
44620b57cec5SDimitry Andric             addCase = true;
44630b57cec5SDimitry Andric             switchExclusivelyCovered = true;
44640b57cec5SDimitry Andric           }
44650b57cec5SDimitry Andric         }
44660b57cec5SDimitry Andric       }
44670b57cec5SDimitry Andric     }
44680b57cec5SDimitry Andric     else
44690b57cec5SDimitry Andric       addCase = true;
44700b57cec5SDimitry Andric   }
44710b57cec5SDimitry Andric   return addCase;
44720b57cec5SDimitry Andric }
44730b57cec5SDimitry Andric 
44740b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {
44750b57cec5SDimitry Andric   // CaseStmts are essentially labels, so they are the first statement in a
44760b57cec5SDimitry Andric   // block.
44770b57cec5SDimitry Andric   CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;
44780b57cec5SDimitry Andric 
44790b57cec5SDimitry Andric   if (Stmt *Sub = CS->getSubStmt()) {
44800b57cec5SDimitry Andric     // For deeply nested chains of CaseStmts, instead of doing a recursion
44810b57cec5SDimitry Andric     // (which can blow out the stack), manually unroll and create blocks
44820b57cec5SDimitry Andric     // along the way.
44830b57cec5SDimitry Andric     while (isa<CaseStmt>(Sub)) {
44840b57cec5SDimitry Andric       CFGBlock *currentBlock = createBlock(false);
44850b57cec5SDimitry Andric       currentBlock->setLabel(CS);
44860b57cec5SDimitry Andric 
44870b57cec5SDimitry Andric       if (TopBlock)
44880b57cec5SDimitry Andric         addSuccessor(LastBlock, currentBlock);
44890b57cec5SDimitry Andric       else
44900b57cec5SDimitry Andric         TopBlock = currentBlock;
44910b57cec5SDimitry Andric 
44920b57cec5SDimitry Andric       addSuccessor(SwitchTerminatedBlock,
44930b57cec5SDimitry Andric                    shouldAddCase(switchExclusivelyCovered, switchCond,
44940b57cec5SDimitry Andric                                  CS, *Context)
44950b57cec5SDimitry Andric                    ? currentBlock : nullptr);
44960b57cec5SDimitry Andric 
44970b57cec5SDimitry Andric       LastBlock = currentBlock;
44980b57cec5SDimitry Andric       CS = cast<CaseStmt>(Sub);
44990b57cec5SDimitry Andric       Sub = CS->getSubStmt();
45000b57cec5SDimitry Andric     }
45010b57cec5SDimitry Andric 
45020b57cec5SDimitry Andric     addStmt(Sub);
45030b57cec5SDimitry Andric   }
45040b57cec5SDimitry Andric 
45050b57cec5SDimitry Andric   CFGBlock *CaseBlock = Block;
45060b57cec5SDimitry Andric   if (!CaseBlock)
45070b57cec5SDimitry Andric     CaseBlock = createBlock();
45080b57cec5SDimitry Andric 
45090b57cec5SDimitry Andric   // Cases statements partition blocks, so this is the top of the basic block we
45100b57cec5SDimitry Andric   // were processing (the "case XXX:" is the label).
45110b57cec5SDimitry Andric   CaseBlock->setLabel(CS);
45120b57cec5SDimitry Andric 
45130b57cec5SDimitry Andric   if (badCFG)
45140b57cec5SDimitry Andric     return nullptr;
45150b57cec5SDimitry Andric 
45160b57cec5SDimitry Andric   // Add this block to the list of successors for the block with the switch
45170b57cec5SDimitry Andric   // statement.
45180b57cec5SDimitry Andric   assert(SwitchTerminatedBlock);
45190b57cec5SDimitry Andric   addSuccessor(SwitchTerminatedBlock, CaseBlock,
45200b57cec5SDimitry Andric                shouldAddCase(switchExclusivelyCovered, switchCond,
45210b57cec5SDimitry Andric                              CS, *Context));
45220b57cec5SDimitry Andric 
4523349cc55cSDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
45240b57cec5SDimitry Andric   Block = nullptr;
45250b57cec5SDimitry Andric 
45260b57cec5SDimitry Andric   if (TopBlock) {
45270b57cec5SDimitry Andric     addSuccessor(LastBlock, CaseBlock);
45280b57cec5SDimitry Andric     Succ = TopBlock;
45290b57cec5SDimitry Andric   } else {
45300b57cec5SDimitry Andric     // This block is now the implicit successor of other blocks.
45310b57cec5SDimitry Andric     Succ = CaseBlock;
45320b57cec5SDimitry Andric   }
45330b57cec5SDimitry Andric 
45340b57cec5SDimitry Andric   return Succ;
45350b57cec5SDimitry Andric }
45360b57cec5SDimitry Andric 
45370b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {
45380b57cec5SDimitry Andric   if (Terminator->getSubStmt())
45390b57cec5SDimitry Andric     addStmt(Terminator->getSubStmt());
45400b57cec5SDimitry Andric 
45410b57cec5SDimitry Andric   DefaultCaseBlock = Block;
45420b57cec5SDimitry Andric 
45430b57cec5SDimitry Andric   if (!DefaultCaseBlock)
45440b57cec5SDimitry Andric     DefaultCaseBlock = createBlock();
45450b57cec5SDimitry Andric 
45460b57cec5SDimitry Andric   // Default statements partition blocks, so this is the top of the basic block
45470b57cec5SDimitry Andric   // we were processing (the "default:" is the label).
45480b57cec5SDimitry Andric   DefaultCaseBlock->setLabel(Terminator);
45490b57cec5SDimitry Andric 
45500b57cec5SDimitry Andric   if (badCFG)
45510b57cec5SDimitry Andric     return nullptr;
45520b57cec5SDimitry Andric 
45530b57cec5SDimitry Andric   // Unlike case statements, we don't add the default block to the successors
45540b57cec5SDimitry Andric   // for the switch statement immediately.  This is done when we finish
45550b57cec5SDimitry Andric   // processing the switch statement.  This allows for the default case
45560b57cec5SDimitry Andric   // (including a fall-through to the code after the switch statement) to always
45570b57cec5SDimitry Andric   // be the last successor of a switch-terminated block.
45580b57cec5SDimitry Andric 
4559349cc55cSDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
45600b57cec5SDimitry Andric   Block = nullptr;
45610b57cec5SDimitry Andric 
45620b57cec5SDimitry Andric   // This block is now the implicit successor of other blocks.
45630b57cec5SDimitry Andric   Succ = DefaultCaseBlock;
45640b57cec5SDimitry Andric 
45650b57cec5SDimitry Andric   return DefaultCaseBlock;
45660b57cec5SDimitry Andric }
45670b57cec5SDimitry Andric 
45680b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
45690b57cec5SDimitry Andric   // "try"/"catch" is a control-flow statement.  Thus we stop processing the
45700b57cec5SDimitry Andric   // current block.
45710b57cec5SDimitry Andric   CFGBlock *TrySuccessor = nullptr;
45720b57cec5SDimitry Andric 
45730b57cec5SDimitry Andric   if (Block) {
45740b57cec5SDimitry Andric     if (badCFG)
45750b57cec5SDimitry Andric       return nullptr;
45760b57cec5SDimitry Andric     TrySuccessor = Block;
4577349cc55cSDimitry Andric   } else
4578349cc55cSDimitry Andric     TrySuccessor = Succ;
45790b57cec5SDimitry Andric 
45800b57cec5SDimitry Andric   CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
45810b57cec5SDimitry Andric 
45820b57cec5SDimitry Andric   // Create a new block that will contain the try statement.
45830b57cec5SDimitry Andric   CFGBlock *NewTryTerminatedBlock = createBlock(false);
45840b57cec5SDimitry Andric   // Add the terminator in the try block.
45850b57cec5SDimitry Andric   NewTryTerminatedBlock->setTerminator(Terminator);
45860b57cec5SDimitry Andric 
45870b57cec5SDimitry Andric   bool HasCatchAll = false;
4588349cc55cSDimitry Andric   for (unsigned I = 0, E = Terminator->getNumHandlers(); I != E; ++I) {
45890b57cec5SDimitry Andric     // The code after the try is the implicit successor.
45900b57cec5SDimitry Andric     Succ = TrySuccessor;
4591349cc55cSDimitry Andric     CXXCatchStmt *CS = Terminator->getHandler(I);
45920b57cec5SDimitry Andric     if (CS->getExceptionDecl() == nullptr) {
45930b57cec5SDimitry Andric       HasCatchAll = true;
45940b57cec5SDimitry Andric     }
45950b57cec5SDimitry Andric     Block = nullptr;
45960b57cec5SDimitry Andric     CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
45970b57cec5SDimitry Andric     if (!CatchBlock)
45980b57cec5SDimitry Andric       return nullptr;
45990b57cec5SDimitry Andric     // Add this block to the list of successors for the block with the try
46000b57cec5SDimitry Andric     // statement.
46010b57cec5SDimitry Andric     addSuccessor(NewTryTerminatedBlock, CatchBlock);
46020b57cec5SDimitry Andric   }
46030b57cec5SDimitry Andric   if (!HasCatchAll) {
46040b57cec5SDimitry Andric     if (PrevTryTerminatedBlock)
46050b57cec5SDimitry Andric       addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
46060b57cec5SDimitry Andric     else
46070b57cec5SDimitry Andric       addSuccessor(NewTryTerminatedBlock, &cfg->getExit());
46080b57cec5SDimitry Andric   }
46090b57cec5SDimitry Andric 
46100b57cec5SDimitry Andric   // The code after the try is the implicit successor.
46110b57cec5SDimitry Andric   Succ = TrySuccessor;
46120b57cec5SDimitry Andric 
46130b57cec5SDimitry Andric   // Save the current "try" context.
4614bdd1243dSDimitry Andric   SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);
46150b57cec5SDimitry Andric   cfg->addTryDispatchBlock(TryTerminatedBlock);
46160b57cec5SDimitry Andric 
46170b57cec5SDimitry Andric   assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
46180b57cec5SDimitry Andric   Block = nullptr;
46190b57cec5SDimitry Andric   return addStmt(Terminator->getTryBlock());
46200b57cec5SDimitry Andric }
46210b57cec5SDimitry Andric 
46220b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {
46230b57cec5SDimitry Andric   // CXXCatchStmt are treated like labels, so they are the first statement in a
46240b57cec5SDimitry Andric   // block.
46250b57cec5SDimitry Andric 
46260b57cec5SDimitry Andric   // Save local scope position because in case of exception variable ScopePos
46270b57cec5SDimitry Andric   // won't be restored when traversing AST.
4628bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
46290b57cec5SDimitry Andric 
46300b57cec5SDimitry Andric   // Create local scope for possible exception variable.
46310b57cec5SDimitry Andric   // Store scope position. Add implicit destructor.
46320b57cec5SDimitry Andric   if (VarDecl *VD = CS->getExceptionDecl()) {
46330b57cec5SDimitry Andric     LocalScope::const_iterator BeginScopePos = ScopePos;
46340b57cec5SDimitry Andric     addLocalScopeForVarDecl(VD);
46350b57cec5SDimitry Andric     addAutomaticObjHandling(ScopePos, BeginScopePos, CS);
46360b57cec5SDimitry Andric   }
46370b57cec5SDimitry Andric 
46380b57cec5SDimitry Andric   if (CS->getHandlerBlock())
46390b57cec5SDimitry Andric     addStmt(CS->getHandlerBlock());
46400b57cec5SDimitry Andric 
46410b57cec5SDimitry Andric   CFGBlock *CatchBlock = Block;
46420b57cec5SDimitry Andric   if (!CatchBlock)
46430b57cec5SDimitry Andric     CatchBlock = createBlock();
46440b57cec5SDimitry Andric 
46450b57cec5SDimitry Andric   // CXXCatchStmt is more than just a label.  They have semantic meaning
46460b57cec5SDimitry Andric   // as well, as they implicitly "initialize" the catch variable.  Add
46470b57cec5SDimitry Andric   // it to the CFG as a CFGElement so that the control-flow of these
46480b57cec5SDimitry Andric   // semantics gets captured.
46490b57cec5SDimitry Andric   appendStmt(CatchBlock, CS);
46500b57cec5SDimitry Andric 
46510b57cec5SDimitry Andric   // Also add the CXXCatchStmt as a label, to mirror handling of regular
46520b57cec5SDimitry Andric   // labels.
46530b57cec5SDimitry Andric   CatchBlock->setLabel(CS);
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric   // Bail out if the CFG is bad.
46560b57cec5SDimitry Andric   if (badCFG)
46570b57cec5SDimitry Andric     return nullptr;
46580b57cec5SDimitry Andric 
4659349cc55cSDimitry Andric   // We set Block to NULL to allow lazy creation of a new block (if necessary).
46600b57cec5SDimitry Andric   Block = nullptr;
46610b57cec5SDimitry Andric 
46620b57cec5SDimitry Andric   return CatchBlock;
46630b57cec5SDimitry Andric }
46640b57cec5SDimitry Andric 
46650b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
46660b57cec5SDimitry Andric   // C++0x for-range statements are specified as [stmt.ranged]:
46670b57cec5SDimitry Andric   //
46680b57cec5SDimitry Andric   // {
46690b57cec5SDimitry Andric   //   auto && __range = range-init;
46700b57cec5SDimitry Andric   //   for ( auto __begin = begin-expr,
46710b57cec5SDimitry Andric   //         __end = end-expr;
46720b57cec5SDimitry Andric   //         __begin != __end;
46730b57cec5SDimitry Andric   //         ++__begin ) {
46740b57cec5SDimitry Andric   //     for-range-declaration = *__begin;
46750b57cec5SDimitry Andric   //     statement
46760b57cec5SDimitry Andric   //   }
46770b57cec5SDimitry Andric   // }
46780b57cec5SDimitry Andric 
46790b57cec5SDimitry Andric   // Save local scope position before the addition of the implicit variables.
4680bdd1243dSDimitry Andric   SaveAndRestore save_scope_pos(ScopePos);
46810b57cec5SDimitry Andric 
46820b57cec5SDimitry Andric   // Create local scopes and destructors for range, begin and end variables.
46830b57cec5SDimitry Andric   if (Stmt *Range = S->getRangeStmt())
46840b57cec5SDimitry Andric     addLocalScopeForStmt(Range);
46850b57cec5SDimitry Andric   if (Stmt *Begin = S->getBeginStmt())
46860b57cec5SDimitry Andric     addLocalScopeForStmt(Begin);
46870b57cec5SDimitry Andric   if (Stmt *End = S->getEndStmt())
46880b57cec5SDimitry Andric     addLocalScopeForStmt(End);
46890b57cec5SDimitry Andric   addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);
46900b57cec5SDimitry Andric 
46910b57cec5SDimitry Andric   LocalScope::const_iterator ContinueScopePos = ScopePos;
46920b57cec5SDimitry Andric 
46930b57cec5SDimitry Andric   // "for" is a control-flow statement.  Thus we stop processing the current
46940b57cec5SDimitry Andric   // block.
46950b57cec5SDimitry Andric   CFGBlock *LoopSuccessor = nullptr;
46960b57cec5SDimitry Andric   if (Block) {
46970b57cec5SDimitry Andric     if (badCFG)
46980b57cec5SDimitry Andric       return nullptr;
46990b57cec5SDimitry Andric     LoopSuccessor = Block;
47000b57cec5SDimitry Andric   } else
47010b57cec5SDimitry Andric     LoopSuccessor = Succ;
47020b57cec5SDimitry Andric 
47030b57cec5SDimitry Andric   // Save the current value for the break targets.
47040b57cec5SDimitry Andric   // All breaks should go to the code following the loop.
4705bdd1243dSDimitry Andric   SaveAndRestore save_break(BreakJumpTarget);
47060b57cec5SDimitry Andric   BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
47070b57cec5SDimitry Andric 
47080b57cec5SDimitry Andric   // The block for the __begin != __end expression.
47090b57cec5SDimitry Andric   CFGBlock *ConditionBlock = createBlock(false);
47100b57cec5SDimitry Andric   ConditionBlock->setTerminator(S);
47110b57cec5SDimitry Andric 
47120b57cec5SDimitry Andric   // Now add the actual condition to the condition block.
47130b57cec5SDimitry Andric   if (Expr *C = S->getCond()) {
47140b57cec5SDimitry Andric     Block = ConditionBlock;
47150b57cec5SDimitry Andric     CFGBlock *BeginConditionBlock = addStmt(C);
47160b57cec5SDimitry Andric     if (badCFG)
47170b57cec5SDimitry Andric       return nullptr;
47180b57cec5SDimitry Andric     assert(BeginConditionBlock == ConditionBlock &&
47190b57cec5SDimitry Andric            "condition block in for-range was unexpectedly complex");
47200b57cec5SDimitry Andric     (void)BeginConditionBlock;
47210b57cec5SDimitry Andric   }
47220b57cec5SDimitry Andric 
47230b57cec5SDimitry Andric   // The condition block is the implicit successor for the loop body as well as
47240b57cec5SDimitry Andric   // any code above the loop.
47250b57cec5SDimitry Andric   Succ = ConditionBlock;
47260b57cec5SDimitry Andric 
47270b57cec5SDimitry Andric   // See if this is a known constant.
47280b57cec5SDimitry Andric   TryResult KnownVal(true);
47290b57cec5SDimitry Andric 
47300b57cec5SDimitry Andric   if (S->getCond())
47310b57cec5SDimitry Andric     KnownVal = tryEvaluateBool(S->getCond());
47320b57cec5SDimitry Andric 
47330b57cec5SDimitry Andric   // Now create the loop body.
47340b57cec5SDimitry Andric   {
47350b57cec5SDimitry Andric     assert(S->getBody());
47360b57cec5SDimitry Andric 
47370b57cec5SDimitry Andric     // Save the current values for Block, Succ, and continue targets.
4738bdd1243dSDimitry Andric     SaveAndRestore save_Block(Block), save_Succ(Succ);
4739bdd1243dSDimitry Andric     SaveAndRestore save_continue(ContinueJumpTarget);
47400b57cec5SDimitry Andric 
47410b57cec5SDimitry Andric     // Generate increment code in its own basic block.  This is the target of
47420b57cec5SDimitry Andric     // continue statements.
47430b57cec5SDimitry Andric     Block = nullptr;
47440b57cec5SDimitry Andric     Succ = addStmt(S->getInc());
47450b57cec5SDimitry Andric     if (badCFG)
47460b57cec5SDimitry Andric       return nullptr;
47470b57cec5SDimitry Andric     ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
47480b57cec5SDimitry Andric 
47490b57cec5SDimitry Andric     // The starting block for the loop increment is the block that should
47500b57cec5SDimitry Andric     // represent the 'loop target' for looping back to the start of the loop.
47510b57cec5SDimitry Andric     ContinueJumpTarget.block->setLoopTarget(S);
47520b57cec5SDimitry Andric 
47530b57cec5SDimitry Andric     // Finish up the increment block and prepare to start the loop body.
47540b57cec5SDimitry Andric     assert(Block);
47550b57cec5SDimitry Andric     if (badCFG)
47560b57cec5SDimitry Andric       return nullptr;
47570b57cec5SDimitry Andric     Block = nullptr;
47580b57cec5SDimitry Andric 
47590b57cec5SDimitry Andric     // Add implicit scope and dtors for loop variable.
47600b57cec5SDimitry Andric     addLocalScopeAndDtors(S->getLoopVarStmt());
47610b57cec5SDimitry Andric 
4762fe6060f1SDimitry Andric     // If body is not a compound statement create implicit scope
4763fe6060f1SDimitry Andric     // and add destructors.
4764fe6060f1SDimitry Andric     if (!isa<CompoundStmt>(S->getBody()))
4765fe6060f1SDimitry Andric       addLocalScopeAndDtors(S->getBody());
4766fe6060f1SDimitry Andric 
47670b57cec5SDimitry Andric     // Populate a new block to contain the loop body and loop variable.
47680b57cec5SDimitry Andric     addStmt(S->getBody());
4769fe6060f1SDimitry Andric 
47700b57cec5SDimitry Andric     if (badCFG)
47710b57cec5SDimitry Andric       return nullptr;
47720b57cec5SDimitry Andric     CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
47730b57cec5SDimitry Andric     if (badCFG)
47740b57cec5SDimitry Andric       return nullptr;
47750b57cec5SDimitry Andric 
47760b57cec5SDimitry Andric     // This new body block is a successor to our condition block.
47770b57cec5SDimitry Andric     addSuccessor(ConditionBlock,
47780b57cec5SDimitry Andric                  KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);
47790b57cec5SDimitry Andric   }
47800b57cec5SDimitry Andric 
47810b57cec5SDimitry Andric   // Link up the condition block with the code that follows the loop (the
47820b57cec5SDimitry Andric   // false branch).
47830b57cec5SDimitry Andric   addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);
47840b57cec5SDimitry Andric 
47850b57cec5SDimitry Andric   // Add the initialization statements.
47860b57cec5SDimitry Andric   Block = createBlock();
47870b57cec5SDimitry Andric   addStmt(S->getBeginStmt());
47880b57cec5SDimitry Andric   addStmt(S->getEndStmt());
47890b57cec5SDimitry Andric   CFGBlock *Head = addStmt(S->getRangeStmt());
47900b57cec5SDimitry Andric   if (S->getInit())
47910b57cec5SDimitry Andric     Head = addStmt(S->getInit());
47920b57cec5SDimitry Andric   return Head;
47930b57cec5SDimitry Andric }
47940b57cec5SDimitry Andric 
47950b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
4796a7dea167SDimitry Andric     AddStmtChoice asc, bool ExternallyDestructed) {
47970b57cec5SDimitry Andric   if (BuildOpts.AddTemporaryDtors) {
47980b57cec5SDimitry Andric     // If adding implicit destructors visit the full expression for adding
47990b57cec5SDimitry Andric     // destructors of temporaries.
48000b57cec5SDimitry Andric     TempDtorContext Context;
4801a7dea167SDimitry Andric     VisitForTemporaryDtors(E->getSubExpr(), ExternallyDestructed, Context);
48020b57cec5SDimitry Andric 
48030b57cec5SDimitry Andric     // Full expression has to be added as CFGStmt so it will be sequenced
48040b57cec5SDimitry Andric     // before destructors of it's temporaries.
48050b57cec5SDimitry Andric     asc = asc.withAlwaysAdd(true);
48060b57cec5SDimitry Andric   }
48070b57cec5SDimitry Andric   return Visit(E->getSubExpr(), asc);
48080b57cec5SDimitry Andric }
48090b57cec5SDimitry Andric 
48100b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
48110b57cec5SDimitry Andric                                                 AddStmtChoice asc) {
48120b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
48130b57cec5SDimitry Andric     autoCreateBlock();
48140b57cec5SDimitry Andric     appendStmt(Block, E);
48150b57cec5SDimitry Andric 
48160b57cec5SDimitry Andric     findConstructionContexts(
48170b57cec5SDimitry Andric         ConstructionContextLayer::create(cfg->getBumpVectorContext(), E),
48180b57cec5SDimitry Andric         E->getSubExpr());
48190b57cec5SDimitry Andric 
48200b57cec5SDimitry Andric     // We do not want to propagate the AlwaysAdd property.
48210b57cec5SDimitry Andric     asc = asc.withAlwaysAdd(false);
48220b57cec5SDimitry Andric   }
48230b57cec5SDimitry Andric   return Visit(E->getSubExpr(), asc);
48240b57cec5SDimitry Andric }
48250b57cec5SDimitry Andric 
48260b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
48270b57cec5SDimitry Andric                                             AddStmtChoice asc) {
48280b57cec5SDimitry Andric   // If the constructor takes objects as arguments by value, we need to properly
48290b57cec5SDimitry Andric   // construct these objects. Construction contexts we find here aren't for the
48300b57cec5SDimitry Andric   // constructor C, they're for its arguments only.
48310b57cec5SDimitry Andric   findConstructionContextsForArguments(C);
48320b57cec5SDimitry Andric 
48330b57cec5SDimitry Andric   autoCreateBlock();
48340b57cec5SDimitry Andric   appendConstructor(Block, C);
48350b57cec5SDimitry Andric 
48360b57cec5SDimitry Andric   return VisitChildren(C);
48370b57cec5SDimitry Andric }
48380b57cec5SDimitry Andric 
48390b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
48400b57cec5SDimitry Andric                                       AddStmtChoice asc) {
48410b57cec5SDimitry Andric   autoCreateBlock();
48420b57cec5SDimitry Andric   appendStmt(Block, NE);
48430b57cec5SDimitry Andric 
48440b57cec5SDimitry Andric   findConstructionContexts(
48450b57cec5SDimitry Andric       ConstructionContextLayer::create(cfg->getBumpVectorContext(), NE),
48460b57cec5SDimitry Andric       const_cast<CXXConstructExpr *>(NE->getConstructExpr()));
48470b57cec5SDimitry Andric 
48480b57cec5SDimitry Andric   if (NE->getInitializer())
48490b57cec5SDimitry Andric     Block = Visit(NE->getInitializer());
48500b57cec5SDimitry Andric 
48510b57cec5SDimitry Andric   if (BuildOpts.AddCXXNewAllocator)
48520b57cec5SDimitry Andric     appendNewAllocator(Block, NE);
48530b57cec5SDimitry Andric 
48540b57cec5SDimitry Andric   if (NE->isArray() && *NE->getArraySize())
48550b57cec5SDimitry Andric     Block = Visit(*NE->getArraySize());
48560b57cec5SDimitry Andric 
48570b57cec5SDimitry Andric   for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),
48580b57cec5SDimitry Andric        E = NE->placement_arg_end(); I != E; ++I)
48590b57cec5SDimitry Andric     Block = Visit(*I);
48600b57cec5SDimitry Andric 
48610b57cec5SDimitry Andric   return Block;
48620b57cec5SDimitry Andric }
48630b57cec5SDimitry Andric 
48640b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
48650b57cec5SDimitry Andric                                          AddStmtChoice asc) {
48660b57cec5SDimitry Andric   autoCreateBlock();
48670b57cec5SDimitry Andric   appendStmt(Block, DE);
48680b57cec5SDimitry Andric   QualType DTy = DE->getDestroyedType();
48690b57cec5SDimitry Andric   if (!DTy.isNull()) {
48700b57cec5SDimitry Andric     DTy = DTy.getNonReferenceType();
48710b57cec5SDimitry Andric     CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
48720b57cec5SDimitry Andric     if (RD) {
48730b57cec5SDimitry Andric       if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
48740b57cec5SDimitry Andric         appendDeleteDtor(Block, RD, DE);
48750b57cec5SDimitry Andric     }
48760b57cec5SDimitry Andric   }
48770b57cec5SDimitry Andric 
48780b57cec5SDimitry Andric   return VisitChildren(DE);
48790b57cec5SDimitry Andric }
48800b57cec5SDimitry Andric 
48810b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
48820b57cec5SDimitry Andric                                                  AddStmtChoice asc) {
48830b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
48840b57cec5SDimitry Andric     autoCreateBlock();
48850b57cec5SDimitry Andric     appendStmt(Block, E);
48860b57cec5SDimitry Andric     // We do not want to propagate the AlwaysAdd property.
48870b57cec5SDimitry Andric     asc = asc.withAlwaysAdd(false);
48880b57cec5SDimitry Andric   }
48890b57cec5SDimitry Andric   return Visit(E->getSubExpr(), asc);
48900b57cec5SDimitry Andric }
48910b57cec5SDimitry Andric 
48920b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
48930b57cec5SDimitry Andric                                                   AddStmtChoice asc) {
48940b57cec5SDimitry Andric   // If the constructor takes objects as arguments by value, we need to properly
48950b57cec5SDimitry Andric   // construct these objects. Construction contexts we find here aren't for the
48960b57cec5SDimitry Andric   // constructor C, they're for its arguments only.
48970b57cec5SDimitry Andric   findConstructionContextsForArguments(C);
48980b57cec5SDimitry Andric 
48990b57cec5SDimitry Andric   autoCreateBlock();
49000b57cec5SDimitry Andric   appendConstructor(Block, C);
49010b57cec5SDimitry Andric   return VisitChildren(C);
49020b57cec5SDimitry Andric }
49030b57cec5SDimitry Andric 
49040b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
49050b57cec5SDimitry Andric                                             AddStmtChoice asc) {
49060b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, E)) {
49070b57cec5SDimitry Andric     autoCreateBlock();
49080b57cec5SDimitry Andric     appendStmt(Block, E);
49090b57cec5SDimitry Andric   }
4910a7dea167SDimitry Andric 
4911a7dea167SDimitry Andric   if (E->getCastKind() == CK_IntegralToBoolean)
4912a7dea167SDimitry Andric     tryEvaluateBool(E->getSubExpr()->IgnoreParens());
4913a7dea167SDimitry Andric 
49140b57cec5SDimitry Andric   return Visit(E->getSubExpr(), AddStmtChoice());
49150b57cec5SDimitry Andric }
49160b57cec5SDimitry Andric 
49170b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {
49180b57cec5SDimitry Andric   return Visit(E->getSubExpr(), AddStmtChoice());
49190b57cec5SDimitry Andric }
49200b57cec5SDimitry Andric 
49210b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {
49220b57cec5SDimitry Andric   // Lazily create the indirect-goto dispatch block if there isn't one already.
49230b57cec5SDimitry Andric   CFGBlock *IBlock = cfg->getIndirectGotoBlock();
49240b57cec5SDimitry Andric 
49250b57cec5SDimitry Andric   if (!IBlock) {
49260b57cec5SDimitry Andric     IBlock = createBlock(false);
49270b57cec5SDimitry Andric     cfg->setIndirectGotoBlock(IBlock);
49280b57cec5SDimitry Andric   }
49290b57cec5SDimitry Andric 
49300b57cec5SDimitry Andric   // IndirectGoto is a control-flow statement.  Thus we stop processing the
49310b57cec5SDimitry Andric   // current block and create a new one.
49320b57cec5SDimitry Andric   if (badCFG)
49330b57cec5SDimitry Andric     return nullptr;
49340b57cec5SDimitry Andric 
49350b57cec5SDimitry Andric   Block = createBlock(false);
49360b57cec5SDimitry Andric   Block->setTerminator(I);
49370b57cec5SDimitry Andric   addSuccessor(Block, IBlock);
49380b57cec5SDimitry Andric   return addStmt(I->getTarget());
49390b57cec5SDimitry Andric }
49400b57cec5SDimitry Andric 
4941a7dea167SDimitry Andric CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
49420b57cec5SDimitry Andric                                              TempDtorContext &Context) {
49430b57cec5SDimitry Andric   assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);
49440b57cec5SDimitry Andric 
49450b57cec5SDimitry Andric tryAgain:
49460b57cec5SDimitry Andric   if (!E) {
49470b57cec5SDimitry Andric     badCFG = true;
49480b57cec5SDimitry Andric     return nullptr;
49490b57cec5SDimitry Andric   }
49500b57cec5SDimitry Andric   switch (E->getStmtClass()) {
49510b57cec5SDimitry Andric     default:
4952a7dea167SDimitry Andric       return VisitChildrenForTemporaryDtors(E, false, Context);
4953a7dea167SDimitry Andric 
4954a7dea167SDimitry Andric     case Stmt::InitListExprClass:
4955a7dea167SDimitry Andric       return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
49560b57cec5SDimitry Andric 
49570b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass:
49580b57cec5SDimitry Andric       return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),
4959a7dea167SDimitry Andric                                                   ExternallyDestructed,
49600b57cec5SDimitry Andric                                                   Context);
49610b57cec5SDimitry Andric 
49620b57cec5SDimitry Andric     case Stmt::CXXBindTemporaryExprClass:
49630b57cec5SDimitry Andric       return VisitCXXBindTemporaryExprForTemporaryDtors(
4964a7dea167SDimitry Andric           cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);
49650b57cec5SDimitry Andric 
49660b57cec5SDimitry Andric     case Stmt::BinaryConditionalOperatorClass:
49670b57cec5SDimitry Andric     case Stmt::ConditionalOperatorClass:
49680b57cec5SDimitry Andric       return VisitConditionalOperatorForTemporaryDtors(
4969a7dea167SDimitry Andric           cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);
49700b57cec5SDimitry Andric 
49710b57cec5SDimitry Andric     case Stmt::ImplicitCastExprClass:
4972a7dea167SDimitry Andric       // For implicit cast we want ExternallyDestructed to be passed further.
49730b57cec5SDimitry Andric       E = cast<CastExpr>(E)->getSubExpr();
49740b57cec5SDimitry Andric       goto tryAgain;
49750b57cec5SDimitry Andric 
49760b57cec5SDimitry Andric     case Stmt::CXXFunctionalCastExprClass:
4977a7dea167SDimitry Andric       // For functional cast we want ExternallyDestructed to be passed further.
49780b57cec5SDimitry Andric       E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();
49790b57cec5SDimitry Andric       goto tryAgain;
49800b57cec5SDimitry Andric 
49810b57cec5SDimitry Andric     case Stmt::ConstantExprClass:
49820b57cec5SDimitry Andric       E = cast<ConstantExpr>(E)->getSubExpr();
49830b57cec5SDimitry Andric       goto tryAgain;
49840b57cec5SDimitry Andric 
49850b57cec5SDimitry Andric     case Stmt::ParenExprClass:
49860b57cec5SDimitry Andric       E = cast<ParenExpr>(E)->getSubExpr();
49870b57cec5SDimitry Andric       goto tryAgain;
49880b57cec5SDimitry Andric 
49890b57cec5SDimitry Andric     case Stmt::MaterializeTemporaryExprClass: {
49900b57cec5SDimitry Andric       const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E);
4991a7dea167SDimitry Andric       ExternallyDestructed = (MTE->getStorageDuration() != SD_FullExpression);
49920b57cec5SDimitry Andric       SmallVector<const Expr *, 2> CommaLHSs;
49930b57cec5SDimitry Andric       SmallVector<SubobjectAdjustment, 2> Adjustments;
49940b57cec5SDimitry Andric       // Find the expression whose lifetime needs to be extended.
49950b57cec5SDimitry Andric       E = const_cast<Expr *>(
49960b57cec5SDimitry Andric           cast<MaterializeTemporaryExpr>(E)
4997480093f4SDimitry Andric               ->getSubExpr()
49980b57cec5SDimitry Andric               ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
49990b57cec5SDimitry Andric       // Visit the skipped comma operator left-hand sides for other temporaries.
50000b57cec5SDimitry Andric       for (const Expr *CommaLHS : CommaLHSs) {
50010b57cec5SDimitry Andric         VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),
5002a7dea167SDimitry Andric                                /*ExternallyDestructed=*/false, Context);
50030b57cec5SDimitry Andric       }
50040b57cec5SDimitry Andric       goto tryAgain;
50050b57cec5SDimitry Andric     }
50060b57cec5SDimitry Andric 
50070b57cec5SDimitry Andric     case Stmt::BlockExprClass:
50080b57cec5SDimitry Andric       // Don't recurse into blocks; their subexpressions don't get evaluated
50090b57cec5SDimitry Andric       // here.
50100b57cec5SDimitry Andric       return Block;
50110b57cec5SDimitry Andric 
50120b57cec5SDimitry Andric     case Stmt::LambdaExprClass: {
50130b57cec5SDimitry Andric       // For lambda expressions, only recurse into the capture initializers,
50140b57cec5SDimitry Andric       // and not the body.
50150b57cec5SDimitry Andric       auto *LE = cast<LambdaExpr>(E);
50160b57cec5SDimitry Andric       CFGBlock *B = Block;
50170b57cec5SDimitry Andric       for (Expr *Init : LE->capture_inits()) {
50180b57cec5SDimitry Andric         if (Init) {
50190b57cec5SDimitry Andric           if (CFGBlock *R = VisitForTemporaryDtors(
5020a7dea167SDimitry Andric                   Init, /*ExternallyDestructed=*/true, Context))
50210b57cec5SDimitry Andric             B = R;
50220b57cec5SDimitry Andric         }
50230b57cec5SDimitry Andric       }
50240b57cec5SDimitry Andric       return B;
50250b57cec5SDimitry Andric     }
50260b57cec5SDimitry Andric 
5027a7dea167SDimitry Andric     case Stmt::StmtExprClass:
5028a7dea167SDimitry Andric       // Don't recurse into statement expressions; any cleanups inside them
5029a7dea167SDimitry Andric       // will be wrapped in their own ExprWithCleanups.
5030a7dea167SDimitry Andric       return Block;
5031a7dea167SDimitry Andric 
50320b57cec5SDimitry Andric     case Stmt::CXXDefaultArgExprClass:
50330b57cec5SDimitry Andric       E = cast<CXXDefaultArgExpr>(E)->getExpr();
50340b57cec5SDimitry Andric       goto tryAgain;
50350b57cec5SDimitry Andric 
50360b57cec5SDimitry Andric     case Stmt::CXXDefaultInitExprClass:
50370b57cec5SDimitry Andric       E = cast<CXXDefaultInitExpr>(E)->getExpr();
50380b57cec5SDimitry Andric       goto tryAgain;
50390b57cec5SDimitry Andric   }
50400b57cec5SDimitry Andric }
50410b57cec5SDimitry Andric 
50420b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
5043a7dea167SDimitry Andric                                                      bool ExternallyDestructed,
50440b57cec5SDimitry Andric                                                      TempDtorContext &Context) {
50450b57cec5SDimitry Andric   if (isa<LambdaExpr>(E)) {
50460b57cec5SDimitry Andric     // Do not visit the children of lambdas; they have their own CFGs.
50470b57cec5SDimitry Andric     return Block;
50480b57cec5SDimitry Andric   }
50490b57cec5SDimitry Andric 
50500b57cec5SDimitry Andric   // When visiting children for destructors we want to visit them in reverse
50510b57cec5SDimitry Andric   // order that they will appear in the CFG.  Because the CFG is built
50520b57cec5SDimitry Andric   // bottom-up, this means we visit them in their natural order, which
50530b57cec5SDimitry Andric   // reverses them in the CFG.
50540b57cec5SDimitry Andric   CFGBlock *B = Block;
50550b57cec5SDimitry Andric   for (Stmt *Child : E->children())
50560b57cec5SDimitry Andric     if (Child)
5057a7dea167SDimitry Andric       if (CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))
50580b57cec5SDimitry Andric         B = R;
50590b57cec5SDimitry Andric 
50600b57cec5SDimitry Andric   return B;
50610b57cec5SDimitry Andric }
50620b57cec5SDimitry Andric 
50630b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
5064a7dea167SDimitry Andric     BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) {
5065a7dea167SDimitry Andric   if (E->isCommaOp()) {
5066e8d8bef9SDimitry Andric     // For the comma operator, the LHS expression is evaluated before the RHS
5067e8d8bef9SDimitry Andric     // expression, so prepend temporary destructors for the LHS first.
5068a7dea167SDimitry Andric     CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
5069e8d8bef9SDimitry Andric     CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), ExternallyDestructed, Context);
5070e8d8bef9SDimitry Andric     return RHSBlock ? RHSBlock : LHSBlock;
5071a7dea167SDimitry Andric   }
5072a7dea167SDimitry Andric 
50730b57cec5SDimitry Andric   if (E->isLogicalOp()) {
50740b57cec5SDimitry Andric     VisitForTemporaryDtors(E->getLHS(), false, Context);
50750b57cec5SDimitry Andric     TryResult RHSExecuted = tryEvaluateBool(E->getLHS());
50760b57cec5SDimitry Andric     if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)
50770b57cec5SDimitry Andric       RHSExecuted.negate();
50780b57cec5SDimitry Andric 
50790b57cec5SDimitry Andric     // We do not know at CFG-construction time whether the right-hand-side was
50800b57cec5SDimitry Andric     // executed, thus we add a branch node that depends on the temporary
50810b57cec5SDimitry Andric     // constructor call.
50820b57cec5SDimitry Andric     TempDtorContext RHSContext(
50830b57cec5SDimitry Andric         bothKnownTrue(Context.KnownExecuted, RHSExecuted));
50840b57cec5SDimitry Andric     VisitForTemporaryDtors(E->getRHS(), false, RHSContext);
50850b57cec5SDimitry Andric     InsertTempDtorDecisionBlock(RHSContext);
50860b57cec5SDimitry Andric 
50870b57cec5SDimitry Andric     return Block;
50880b57cec5SDimitry Andric   }
50890b57cec5SDimitry Andric 
50900b57cec5SDimitry Andric   if (E->isAssignmentOp()) {
5091e8d8bef9SDimitry Andric     // For assignment operators, the RHS expression is evaluated before the LHS
5092e8d8bef9SDimitry Andric     // expression, so prepend temporary destructors for the RHS first.
50930b57cec5SDimitry Andric     CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);
50940b57cec5SDimitry Andric     CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);
50950b57cec5SDimitry Andric     return LHSBlock ? LHSBlock : RHSBlock;
50960b57cec5SDimitry Andric   }
50970b57cec5SDimitry Andric 
5098e8d8bef9SDimitry Andric   // Any other operator is visited normally.
5099e8d8bef9SDimitry Andric   return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);
51000b57cec5SDimitry Andric }
51010b57cec5SDimitry Andric 
51020b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
5103a7dea167SDimitry Andric     CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) {
51040b57cec5SDimitry Andric   // First add destructors for temporaries in subexpression.
5105a7dea167SDimitry Andric   // Because VisitCXXBindTemporaryExpr calls setDestructed:
5106a7dea167SDimitry Andric   CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), true, Context);
5107a7dea167SDimitry Andric   if (!ExternallyDestructed) {
51080b57cec5SDimitry Andric     // If lifetime of temporary is not prolonged (by assigning to constant
51090b57cec5SDimitry Andric     // reference) add destructor for it.
51100b57cec5SDimitry Andric 
51110b57cec5SDimitry Andric     const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
51120b57cec5SDimitry Andric 
51130b57cec5SDimitry Andric     if (Dtor->getParent()->isAnyDestructorNoReturn()) {
51140b57cec5SDimitry Andric       // If the destructor is marked as a no-return destructor, we need to
51150b57cec5SDimitry Andric       // create a new block for the destructor which does not have as a
51160b57cec5SDimitry Andric       // successor anything built thus far. Control won't flow out of this
51170b57cec5SDimitry Andric       // block.
51180b57cec5SDimitry Andric       if (B) Succ = B;
51190b57cec5SDimitry Andric       Block = createNoReturnBlock();
51200b57cec5SDimitry Andric     } else if (Context.needsTempDtorBranch()) {
51210b57cec5SDimitry Andric       // If we need to introduce a branch, we add a new block that we will hook
51220b57cec5SDimitry Andric       // up to a decision block later.
51230b57cec5SDimitry Andric       if (B) Succ = B;
51240b57cec5SDimitry Andric       Block = createBlock();
51250b57cec5SDimitry Andric     } else {
51260b57cec5SDimitry Andric       autoCreateBlock();
51270b57cec5SDimitry Andric     }
51280b57cec5SDimitry Andric     if (Context.needsTempDtorBranch()) {
51290b57cec5SDimitry Andric       Context.setDecisionPoint(Succ, E);
51300b57cec5SDimitry Andric     }
51310b57cec5SDimitry Andric     appendTemporaryDtor(Block, E);
51320b57cec5SDimitry Andric 
51330b57cec5SDimitry Andric     B = Block;
51340b57cec5SDimitry Andric   }
51350b57cec5SDimitry Andric   return B;
51360b57cec5SDimitry Andric }
51370b57cec5SDimitry Andric 
51380b57cec5SDimitry Andric void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
51390b57cec5SDimitry Andric                                              CFGBlock *FalseSucc) {
51400b57cec5SDimitry Andric   if (!Context.TerminatorExpr) {
51410b57cec5SDimitry Andric     // If no temporary was found, we do not need to insert a decision point.
51420b57cec5SDimitry Andric     return;
51430b57cec5SDimitry Andric   }
51440b57cec5SDimitry Andric   assert(Context.TerminatorExpr);
51450b57cec5SDimitry Andric   CFGBlock *Decision = createBlock(false);
51460b57cec5SDimitry Andric   Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,
51470b57cec5SDimitry Andric                                         CFGTerminator::TemporaryDtorsBranch));
51480b57cec5SDimitry Andric   addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());
51490b57cec5SDimitry Andric   addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,
51500b57cec5SDimitry Andric                !Context.KnownExecuted.isTrue());
51510b57cec5SDimitry Andric   Block = Decision;
51520b57cec5SDimitry Andric }
51530b57cec5SDimitry Andric 
51540b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
5155a7dea167SDimitry Andric     AbstractConditionalOperator *E, bool ExternallyDestructed,
51560b57cec5SDimitry Andric     TempDtorContext &Context) {
51570b57cec5SDimitry Andric   VisitForTemporaryDtors(E->getCond(), false, Context);
51580b57cec5SDimitry Andric   CFGBlock *ConditionBlock = Block;
51590b57cec5SDimitry Andric   CFGBlock *ConditionSucc = Succ;
51600b57cec5SDimitry Andric   TryResult ConditionVal = tryEvaluateBool(E->getCond());
51610b57cec5SDimitry Andric   TryResult NegatedVal = ConditionVal;
51620b57cec5SDimitry Andric   if (NegatedVal.isKnown()) NegatedVal.negate();
51630b57cec5SDimitry Andric 
51640b57cec5SDimitry Andric   TempDtorContext TrueContext(
51650b57cec5SDimitry Andric       bothKnownTrue(Context.KnownExecuted, ConditionVal));
5166a7dea167SDimitry Andric   VisitForTemporaryDtors(E->getTrueExpr(), ExternallyDestructed, TrueContext);
51670b57cec5SDimitry Andric   CFGBlock *TrueBlock = Block;
51680b57cec5SDimitry Andric 
51690b57cec5SDimitry Andric   Block = ConditionBlock;
51700b57cec5SDimitry Andric   Succ = ConditionSucc;
51710b57cec5SDimitry Andric   TempDtorContext FalseContext(
51720b57cec5SDimitry Andric       bothKnownTrue(Context.KnownExecuted, NegatedVal));
5173a7dea167SDimitry Andric   VisitForTemporaryDtors(E->getFalseExpr(), ExternallyDestructed, FalseContext);
51740b57cec5SDimitry Andric 
51750b57cec5SDimitry Andric   if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {
51760b57cec5SDimitry Andric     InsertTempDtorDecisionBlock(FalseContext, TrueBlock);
51770b57cec5SDimitry Andric   } else if (TrueContext.TerminatorExpr) {
51780b57cec5SDimitry Andric     Block = TrueBlock;
51790b57cec5SDimitry Andric     InsertTempDtorDecisionBlock(TrueContext);
51800b57cec5SDimitry Andric   } else {
51810b57cec5SDimitry Andric     InsertTempDtorDecisionBlock(FalseContext);
51820b57cec5SDimitry Andric   }
51830b57cec5SDimitry Andric   return Block;
51840b57cec5SDimitry Andric }
51850b57cec5SDimitry Andric 
51860b57cec5SDimitry Andric CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
51870b57cec5SDimitry Andric                                                   AddStmtChoice asc) {
51880b57cec5SDimitry Andric   if (asc.alwaysAdd(*this, D)) {
51890b57cec5SDimitry Andric     autoCreateBlock();
51900b57cec5SDimitry Andric     appendStmt(Block, D);
51910b57cec5SDimitry Andric   }
51920b57cec5SDimitry Andric 
51930b57cec5SDimitry Andric   // Iterate over all used expression in clauses.
51940b57cec5SDimitry Andric   CFGBlock *B = Block;
51950b57cec5SDimitry Andric 
51960b57cec5SDimitry Andric   // Reverse the elements to process them in natural order. Iterators are not
51970b57cec5SDimitry Andric   // bidirectional, so we need to create temp vector.
51980b57cec5SDimitry Andric   SmallVector<Stmt *, 8> Used(
51990b57cec5SDimitry Andric       OMPExecutableDirective::used_clauses_children(D->clauses()));
52000b57cec5SDimitry Andric   for (Stmt *S : llvm::reverse(Used)) {
52010b57cec5SDimitry Andric     assert(S && "Expected non-null used-in-clause child.");
52020b57cec5SDimitry Andric     if (CFGBlock *R = Visit(S))
52030b57cec5SDimitry Andric       B = R;
52040b57cec5SDimitry Andric   }
52050b57cec5SDimitry Andric   // Visit associated structured block if any.
5206e8d8bef9SDimitry Andric   if (!D->isStandaloneDirective()) {
5207e8d8bef9SDimitry Andric     Stmt *S = D->getRawStmt();
52080b57cec5SDimitry Andric     if (!isa<CompoundStmt>(S))
52090b57cec5SDimitry Andric       addLocalScopeAndDtors(S);
52100b57cec5SDimitry Andric     if (CFGBlock *R = addStmt(S))
52110b57cec5SDimitry Andric       B = R;
52120b57cec5SDimitry Andric   }
52130b57cec5SDimitry Andric 
52140b57cec5SDimitry Andric   return B;
52150b57cec5SDimitry Andric }
52160b57cec5SDimitry Andric 
52170b57cec5SDimitry Andric /// createBlock - Constructs and adds a new CFGBlock to the CFG.  The block has
52180b57cec5SDimitry Andric ///  no successors or predecessors.  If this is the first block created in the
52190b57cec5SDimitry Andric ///  CFG, it is automatically set to be the Entry and Exit of the CFG.
52200b57cec5SDimitry Andric CFGBlock *CFG::createBlock() {
52210b57cec5SDimitry Andric   bool first_block = begin() == end();
52220b57cec5SDimitry Andric 
52230b57cec5SDimitry Andric   // Create the block.
522406c3fb27SDimitry Andric   CFGBlock *Mem = new (getAllocator()) CFGBlock(NumBlockIDs++, BlkBVC, this);
52250b57cec5SDimitry Andric   Blocks.push_back(Mem, BlkBVC);
52260b57cec5SDimitry Andric 
52270b57cec5SDimitry Andric   // If this is the first block, set it as the Entry and Exit.
52280b57cec5SDimitry Andric   if (first_block)
52290b57cec5SDimitry Andric     Entry = Exit = &back();
52300b57cec5SDimitry Andric 
52310b57cec5SDimitry Andric   // Return the block.
52320b57cec5SDimitry Andric   return &back();
52330b57cec5SDimitry Andric }
52340b57cec5SDimitry Andric 
52350b57cec5SDimitry Andric /// buildCFG - Constructs a CFG from an AST.
52360b57cec5SDimitry Andric std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,
52370b57cec5SDimitry Andric                                    ASTContext *C, const BuildOptions &BO) {
52380b57cec5SDimitry Andric   CFGBuilder Builder(C, BO);
52390b57cec5SDimitry Andric   return Builder.buildCFG(D, Statement);
52400b57cec5SDimitry Andric }
52410b57cec5SDimitry Andric 
52420b57cec5SDimitry Andric bool CFG::isLinear() const {
52430b57cec5SDimitry Andric   // Quick path: if we only have the ENTRY block, the EXIT block, and some code
52440b57cec5SDimitry Andric   // in between, then we have no room for control flow.
52450b57cec5SDimitry Andric   if (size() <= 3)
52460b57cec5SDimitry Andric     return true;
52470b57cec5SDimitry Andric 
52480b57cec5SDimitry Andric   // Traverse the CFG until we find a branch.
52490b57cec5SDimitry Andric   // TODO: While this should still be very fast,
52500b57cec5SDimitry Andric   // maybe we should cache the answer.
52510b57cec5SDimitry Andric   llvm::SmallPtrSet<const CFGBlock *, 4> Visited;
52520b57cec5SDimitry Andric   const CFGBlock *B = Entry;
52530b57cec5SDimitry Andric   while (B != Exit) {
52540b57cec5SDimitry Andric     auto IteratorAndFlag = Visited.insert(B);
52550b57cec5SDimitry Andric     if (!IteratorAndFlag.second) {
52560b57cec5SDimitry Andric       // We looped back to a block that we've already visited. Not linear.
52570b57cec5SDimitry Andric       return false;
52580b57cec5SDimitry Andric     }
52590b57cec5SDimitry Andric 
52600b57cec5SDimitry Andric     // Iterate over reachable successors.
52610b57cec5SDimitry Andric     const CFGBlock *FirstReachableB = nullptr;
52620b57cec5SDimitry Andric     for (const CFGBlock::AdjacentBlock &AB : B->succs()) {
52630b57cec5SDimitry Andric       if (!AB.isReachable())
52640b57cec5SDimitry Andric         continue;
52650b57cec5SDimitry Andric 
52660b57cec5SDimitry Andric       if (FirstReachableB == nullptr) {
52670b57cec5SDimitry Andric         FirstReachableB = &*AB;
52680b57cec5SDimitry Andric       } else {
52690b57cec5SDimitry Andric         // We've encountered a branch. It's not a linear CFG.
52700b57cec5SDimitry Andric         return false;
52710b57cec5SDimitry Andric       }
52720b57cec5SDimitry Andric     }
52730b57cec5SDimitry Andric 
52740b57cec5SDimitry Andric     if (!FirstReachableB) {
52750b57cec5SDimitry Andric       // We reached a dead end. EXIT is unreachable. This is linear enough.
52760b57cec5SDimitry Andric       return true;
52770b57cec5SDimitry Andric     }
52780b57cec5SDimitry Andric 
52790b57cec5SDimitry Andric     // There's only one way to move forward. Proceed.
52800b57cec5SDimitry Andric     B = FirstReachableB;
52810b57cec5SDimitry Andric   }
52820b57cec5SDimitry Andric 
52830b57cec5SDimitry Andric   // We reached EXIT and found no branches.
52840b57cec5SDimitry Andric   return true;
52850b57cec5SDimitry Andric }
52860b57cec5SDimitry Andric 
52870b57cec5SDimitry Andric const CXXDestructorDecl *
52880b57cec5SDimitry Andric CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {
52890b57cec5SDimitry Andric   switch (getKind()) {
52900b57cec5SDimitry Andric     case CFGElement::Initializer:
52910b57cec5SDimitry Andric     case CFGElement::NewAllocator:
52920b57cec5SDimitry Andric     case CFGElement::LoopExit:
52930b57cec5SDimitry Andric     case CFGElement::LifetimeEnds:
52940b57cec5SDimitry Andric     case CFGElement::Statement:
52950b57cec5SDimitry Andric     case CFGElement::Constructor:
52960b57cec5SDimitry Andric     case CFGElement::CXXRecordTypedCall:
52970b57cec5SDimitry Andric     case CFGElement::ScopeBegin:
52980b57cec5SDimitry Andric     case CFGElement::ScopeEnd:
52995f757f3fSDimitry Andric     case CFGElement::CleanupFunction:
53000b57cec5SDimitry Andric       llvm_unreachable("getDestructorDecl should only be used with "
53010b57cec5SDimitry Andric                        "ImplicitDtors");
53020b57cec5SDimitry Andric     case CFGElement::AutomaticObjectDtor: {
53030b57cec5SDimitry Andric       const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();
53040b57cec5SDimitry Andric       QualType ty = var->getType();
53050b57cec5SDimitry Andric 
53060b57cec5SDimitry Andric       // FIXME: See CFGBuilder::addLocalScopeForVarDecl.
53070b57cec5SDimitry Andric       //
53080b57cec5SDimitry Andric       // Lifetime-extending constructs are handled here. This works for a single
53090b57cec5SDimitry Andric       // temporary in an initializer expression.
53100b57cec5SDimitry Andric       if (ty->isReferenceType()) {
53110b57cec5SDimitry Andric         if (const Expr *Init = var->getInit()) {
53120b57cec5SDimitry Andric           ty = getReferenceInitTemporaryType(Init);
53130b57cec5SDimitry Andric         }
53140b57cec5SDimitry Andric       }
53150b57cec5SDimitry Andric 
53160b57cec5SDimitry Andric       while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
53170b57cec5SDimitry Andric         ty = arrayType->getElementType();
53180b57cec5SDimitry Andric       }
5319a7dea167SDimitry Andric 
5320a7dea167SDimitry Andric       // The situation when the type of the lifetime-extending reference
5321a7dea167SDimitry Andric       // does not correspond to the type of the object is supposed
5322a7dea167SDimitry Andric       // to be handled by now. In particular, 'ty' is now the unwrapped
5323a7dea167SDimitry Andric       // record type.
5324a7dea167SDimitry Andric       const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();
5325a7dea167SDimitry Andric       assert(classDecl);
53260b57cec5SDimitry Andric       return classDecl->getDestructor();
53270b57cec5SDimitry Andric     }
53280b57cec5SDimitry Andric     case CFGElement::DeleteDtor: {
53290b57cec5SDimitry Andric       const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();
53300b57cec5SDimitry Andric       QualType DTy = DE->getDestroyedType();
53310b57cec5SDimitry Andric       DTy = DTy.getNonReferenceType();
53320b57cec5SDimitry Andric       const CXXRecordDecl *classDecl =
53330b57cec5SDimitry Andric           astContext.getBaseElementType(DTy)->getAsCXXRecordDecl();
53340b57cec5SDimitry Andric       return classDecl->getDestructor();
53350b57cec5SDimitry Andric     }
53360b57cec5SDimitry Andric     case CFGElement::TemporaryDtor: {
53370b57cec5SDimitry Andric       const CXXBindTemporaryExpr *bindExpr =
53380b57cec5SDimitry Andric         castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
53390b57cec5SDimitry Andric       const CXXTemporary *temp = bindExpr->getTemporary();
53400b57cec5SDimitry Andric       return temp->getDestructor();
53410b57cec5SDimitry Andric     }
5342bdd1243dSDimitry Andric     case CFGElement::MemberDtor: {
5343bdd1243dSDimitry Andric       const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();
5344bdd1243dSDimitry Andric       QualType ty = field->getType();
5345bdd1243dSDimitry Andric 
5346bdd1243dSDimitry Andric       while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {
5347bdd1243dSDimitry Andric         ty = arrayType->getElementType();
5348bdd1243dSDimitry Andric       }
5349bdd1243dSDimitry Andric 
5350bdd1243dSDimitry Andric       const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();
5351bdd1243dSDimitry Andric       assert(classDecl);
5352bdd1243dSDimitry Andric       return classDecl->getDestructor();
5353bdd1243dSDimitry Andric     }
53540b57cec5SDimitry Andric     case CFGElement::BaseDtor:
53550b57cec5SDimitry Andric       // Not yet supported.
53560b57cec5SDimitry Andric       return nullptr;
53570b57cec5SDimitry Andric   }
53580b57cec5SDimitry Andric   llvm_unreachable("getKind() returned bogus value");
53590b57cec5SDimitry Andric }
53600b57cec5SDimitry Andric 
53610b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
53620b57cec5SDimitry Andric // CFGBlock operations.
53630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
53640b57cec5SDimitry Andric 
53650b57cec5SDimitry Andric CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
53660b57cec5SDimitry Andric     : ReachableBlock(IsReachable ? B : nullptr),
53670b57cec5SDimitry Andric       UnreachableBlock(!IsReachable ? B : nullptr,
53680b57cec5SDimitry Andric                        B && IsReachable ? AB_Normal : AB_Unreachable) {}
53690b57cec5SDimitry Andric 
53700b57cec5SDimitry Andric CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
53710b57cec5SDimitry Andric     : ReachableBlock(B),
53720b57cec5SDimitry Andric       UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,
53730b57cec5SDimitry Andric                        B == AlternateBlock ? AB_Alternate : AB_Normal) {}
53740b57cec5SDimitry Andric 
53750b57cec5SDimitry Andric void CFGBlock::addSuccessor(AdjacentBlock Succ,
53760b57cec5SDimitry Andric                             BumpVectorContext &C) {
53770b57cec5SDimitry Andric   if (CFGBlock *B = Succ.getReachableBlock())
53780b57cec5SDimitry Andric     B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C);
53790b57cec5SDimitry Andric 
53800b57cec5SDimitry Andric   if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock())
53810b57cec5SDimitry Andric     UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);
53820b57cec5SDimitry Andric 
53830b57cec5SDimitry Andric   Succs.push_back(Succ, C);
53840b57cec5SDimitry Andric }
53850b57cec5SDimitry Andric 
53860b57cec5SDimitry Andric bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
53870b57cec5SDimitry Andric         const CFGBlock *From, const CFGBlock *To) {
53880b57cec5SDimitry Andric   if (F.IgnoreNullPredecessors && !From)
53890b57cec5SDimitry Andric     return true;
53900b57cec5SDimitry Andric 
53910b57cec5SDimitry Andric   if (To && From && F.IgnoreDefaultsWithCoveredEnums) {
53920b57cec5SDimitry Andric     // If the 'To' has no label or is labeled but the label isn't a
53930b57cec5SDimitry Andric     // CaseStmt then filter this edge.
53940b57cec5SDimitry Andric     if (const SwitchStmt *S =
53950b57cec5SDimitry Andric         dyn_cast_or_null<SwitchStmt>(From->getTerminatorStmt())) {
53960b57cec5SDimitry Andric       if (S->isAllEnumCasesCovered()) {
53970b57cec5SDimitry Andric         const Stmt *L = To->getLabel();
53980b57cec5SDimitry Andric         if (!L || !isa<CaseStmt>(L))
53990b57cec5SDimitry Andric           return true;
54000b57cec5SDimitry Andric       }
54010b57cec5SDimitry Andric     }
54020b57cec5SDimitry Andric   }
54030b57cec5SDimitry Andric 
54040b57cec5SDimitry Andric   return false;
54050b57cec5SDimitry Andric }
54060b57cec5SDimitry Andric 
54070b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
54080b57cec5SDimitry Andric // CFG pretty printing
54090b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
54100b57cec5SDimitry Andric 
54110b57cec5SDimitry Andric namespace {
54120b57cec5SDimitry Andric 
54130b57cec5SDimitry Andric class StmtPrinterHelper : public PrinterHelper  {
54140b57cec5SDimitry Andric   using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;
54150b57cec5SDimitry Andric   using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;
54160b57cec5SDimitry Andric 
54170b57cec5SDimitry Andric   StmtMapTy StmtMap;
54180b57cec5SDimitry Andric   DeclMapTy DeclMap;
54190b57cec5SDimitry Andric   signed currentBlock = 0;
54200b57cec5SDimitry Andric   unsigned currStmt = 0;
54210b57cec5SDimitry Andric   const LangOptions &LangOpts;
54220b57cec5SDimitry Andric 
54230b57cec5SDimitry Andric public:
54240b57cec5SDimitry Andric   StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
54250b57cec5SDimitry Andric       : LangOpts(LO) {
5426a7dea167SDimitry Andric     if (!cfg)
5427a7dea167SDimitry Andric       return;
54280b57cec5SDimitry Andric     for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
54290b57cec5SDimitry Andric       unsigned j = 1;
54300b57cec5SDimitry Andric       for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
54310b57cec5SDimitry Andric            BI != BEnd; ++BI, ++j ) {
5432bdd1243dSDimitry Andric         if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {
54330b57cec5SDimitry Andric           const Stmt *stmt= SE->getStmt();
54340b57cec5SDimitry Andric           std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);
54350b57cec5SDimitry Andric           StmtMap[stmt] = P;
54360b57cec5SDimitry Andric 
54370b57cec5SDimitry Andric           switch (stmt->getStmtClass()) {
54380b57cec5SDimitry Andric             case Stmt::DeclStmtClass:
54390b57cec5SDimitry Andric               DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;
54400b57cec5SDimitry Andric               break;
54410b57cec5SDimitry Andric             case Stmt::IfStmtClass: {
54420b57cec5SDimitry Andric               const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();
54430b57cec5SDimitry Andric               if (var)
54440b57cec5SDimitry Andric                 DeclMap[var] = P;
54450b57cec5SDimitry Andric               break;
54460b57cec5SDimitry Andric             }
54470b57cec5SDimitry Andric             case Stmt::ForStmtClass: {
54480b57cec5SDimitry Andric               const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();
54490b57cec5SDimitry Andric               if (var)
54500b57cec5SDimitry Andric                 DeclMap[var] = P;
54510b57cec5SDimitry Andric               break;
54520b57cec5SDimitry Andric             }
54530b57cec5SDimitry Andric             case Stmt::WhileStmtClass: {
54540b57cec5SDimitry Andric               const VarDecl *var =
54550b57cec5SDimitry Andric                 cast<WhileStmt>(stmt)->getConditionVariable();
54560b57cec5SDimitry Andric               if (var)
54570b57cec5SDimitry Andric                 DeclMap[var] = P;
54580b57cec5SDimitry Andric               break;
54590b57cec5SDimitry Andric             }
54600b57cec5SDimitry Andric             case Stmt::SwitchStmtClass: {
54610b57cec5SDimitry Andric               const VarDecl *var =
54620b57cec5SDimitry Andric                 cast<SwitchStmt>(stmt)->getConditionVariable();
54630b57cec5SDimitry Andric               if (var)
54640b57cec5SDimitry Andric                 DeclMap[var] = P;
54650b57cec5SDimitry Andric               break;
54660b57cec5SDimitry Andric             }
54670b57cec5SDimitry Andric             case Stmt::CXXCatchStmtClass: {
54680b57cec5SDimitry Andric               const VarDecl *var =
54690b57cec5SDimitry Andric                 cast<CXXCatchStmt>(stmt)->getExceptionDecl();
54700b57cec5SDimitry Andric               if (var)
54710b57cec5SDimitry Andric                 DeclMap[var] = P;
54720b57cec5SDimitry Andric               break;
54730b57cec5SDimitry Andric             }
54740b57cec5SDimitry Andric             default:
54750b57cec5SDimitry Andric               break;
54760b57cec5SDimitry Andric           }
54770b57cec5SDimitry Andric         }
54780b57cec5SDimitry Andric       }
54790b57cec5SDimitry Andric     }
54800b57cec5SDimitry Andric   }
54810b57cec5SDimitry Andric 
54820b57cec5SDimitry Andric   ~StmtPrinterHelper() override = default;
54830b57cec5SDimitry Andric 
54840b57cec5SDimitry Andric   const LangOptions &getLangOpts() const { return LangOpts; }
54850b57cec5SDimitry Andric   void setBlockID(signed i) { currentBlock = i; }
54860b57cec5SDimitry Andric   void setStmtID(unsigned i) { currStmt = i; }
54870b57cec5SDimitry Andric 
54880b57cec5SDimitry Andric   bool handledStmt(Stmt *S, raw_ostream &OS) override {
54890b57cec5SDimitry Andric     StmtMapTy::iterator I = StmtMap.find(S);
54900b57cec5SDimitry Andric 
54910b57cec5SDimitry Andric     if (I == StmtMap.end())
54920b57cec5SDimitry Andric       return false;
54930b57cec5SDimitry Andric 
54940b57cec5SDimitry Andric     if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
54950b57cec5SDimitry Andric                           && I->second.second == currStmt) {
54960b57cec5SDimitry Andric       return false;
54970b57cec5SDimitry Andric     }
54980b57cec5SDimitry Andric 
54990b57cec5SDimitry Andric     OS << "[B" << I->second.first << "." << I->second.second << "]";
55000b57cec5SDimitry Andric     return true;
55010b57cec5SDimitry Andric   }
55020b57cec5SDimitry Andric 
55030b57cec5SDimitry Andric   bool handleDecl(const Decl *D, raw_ostream &OS) {
55040b57cec5SDimitry Andric     DeclMapTy::iterator I = DeclMap.find(D);
55050b57cec5SDimitry Andric 
55060b57cec5SDimitry Andric     if (I == DeclMap.end())
55070b57cec5SDimitry Andric       return false;
55080b57cec5SDimitry Andric 
55090b57cec5SDimitry Andric     if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock
55100b57cec5SDimitry Andric                           && I->second.second == currStmt) {
55110b57cec5SDimitry Andric       return false;
55120b57cec5SDimitry Andric     }
55130b57cec5SDimitry Andric 
55140b57cec5SDimitry Andric     OS << "[B" << I->second.first << "." << I->second.second << "]";
55150b57cec5SDimitry Andric     return true;
55160b57cec5SDimitry Andric   }
55170b57cec5SDimitry Andric };
55180b57cec5SDimitry Andric 
55190b57cec5SDimitry Andric class CFGBlockTerminatorPrint
55200b57cec5SDimitry Andric     : public StmtVisitor<CFGBlockTerminatorPrint,void> {
55210b57cec5SDimitry Andric   raw_ostream &OS;
55220b57cec5SDimitry Andric   StmtPrinterHelper* Helper;
55230b57cec5SDimitry Andric   PrintingPolicy Policy;
55240b57cec5SDimitry Andric 
55250b57cec5SDimitry Andric public:
55260b57cec5SDimitry Andric   CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,
55270b57cec5SDimitry Andric                           const PrintingPolicy &Policy)
55280b57cec5SDimitry Andric       : OS(os), Helper(helper), Policy(Policy) {
55290b57cec5SDimitry Andric     this->Policy.IncludeNewlines = false;
55300b57cec5SDimitry Andric   }
55310b57cec5SDimitry Andric 
55320b57cec5SDimitry Andric   void VisitIfStmt(IfStmt *I) {
55330b57cec5SDimitry Andric     OS << "if ";
55340b57cec5SDimitry Andric     if (Stmt *C = I->getCond())
55350b57cec5SDimitry Andric       C->printPretty(OS, Helper, Policy);
55360b57cec5SDimitry Andric   }
55370b57cec5SDimitry Andric 
55380b57cec5SDimitry Andric   // Default case.
55390b57cec5SDimitry Andric   void VisitStmt(Stmt *Terminator) {
55400b57cec5SDimitry Andric     Terminator->printPretty(OS, Helper, Policy);
55410b57cec5SDimitry Andric   }
55420b57cec5SDimitry Andric 
55430b57cec5SDimitry Andric   void VisitDeclStmt(DeclStmt *DS) {
55440b57cec5SDimitry Andric     VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
55450b57cec5SDimitry Andric     OS << "static init " << VD->getName();
55460b57cec5SDimitry Andric   }
55470b57cec5SDimitry Andric 
55480b57cec5SDimitry Andric   void VisitForStmt(ForStmt *F) {
55490b57cec5SDimitry Andric     OS << "for (" ;
55500b57cec5SDimitry Andric     if (F->getInit())
55510b57cec5SDimitry Andric       OS << "...";
55520b57cec5SDimitry Andric     OS << "; ";
55530b57cec5SDimitry Andric     if (Stmt *C = F->getCond())
55540b57cec5SDimitry Andric       C->printPretty(OS, Helper, Policy);
55550b57cec5SDimitry Andric     OS << "; ";
55560b57cec5SDimitry Andric     if (F->getInc())
55570b57cec5SDimitry Andric       OS << "...";
55580b57cec5SDimitry Andric     OS << ")";
55590b57cec5SDimitry Andric   }
55600b57cec5SDimitry Andric 
55610b57cec5SDimitry Andric   void VisitWhileStmt(WhileStmt *W) {
55620b57cec5SDimitry Andric     OS << "while " ;
55630b57cec5SDimitry Andric     if (Stmt *C = W->getCond())
55640b57cec5SDimitry Andric       C->printPretty(OS, Helper, Policy);
55650b57cec5SDimitry Andric   }
55660b57cec5SDimitry Andric 
55670b57cec5SDimitry Andric   void VisitDoStmt(DoStmt *D) {
55680b57cec5SDimitry Andric     OS << "do ... while ";
55690b57cec5SDimitry Andric     if (Stmt *C = D->getCond())
55700b57cec5SDimitry Andric       C->printPretty(OS, Helper, Policy);
55710b57cec5SDimitry Andric   }
55720b57cec5SDimitry Andric 
55730b57cec5SDimitry Andric   void VisitSwitchStmt(SwitchStmt *Terminator) {
55740b57cec5SDimitry Andric     OS << "switch ";
55750b57cec5SDimitry Andric     Terminator->getCond()->printPretty(OS, Helper, Policy);
55760b57cec5SDimitry Andric   }
55770b57cec5SDimitry Andric 
5578349cc55cSDimitry Andric   void VisitCXXTryStmt(CXXTryStmt *) { OS << "try ..."; }
55790b57cec5SDimitry Andric 
5580349cc55cSDimitry Andric   void VisitObjCAtTryStmt(ObjCAtTryStmt *) { OS << "@try ..."; }
5581349cc55cSDimitry Andric 
5582349cc55cSDimitry Andric   void VisitSEHTryStmt(SEHTryStmt *CS) { OS << "__try ..."; }
55830b57cec5SDimitry Andric 
55840b57cec5SDimitry Andric   void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
55850b57cec5SDimitry Andric     if (Stmt *Cond = C->getCond())
55860b57cec5SDimitry Andric       Cond->printPretty(OS, Helper, Policy);
55870b57cec5SDimitry Andric     OS << " ? ... : ...";
55880b57cec5SDimitry Andric   }
55890b57cec5SDimitry Andric 
55900b57cec5SDimitry Andric   void VisitChooseExpr(ChooseExpr *C) {
55910b57cec5SDimitry Andric     OS << "__builtin_choose_expr( ";
55920b57cec5SDimitry Andric     if (Stmt *Cond = C->getCond())
55930b57cec5SDimitry Andric       Cond->printPretty(OS, Helper, Policy);
55940b57cec5SDimitry Andric     OS << " )";
55950b57cec5SDimitry Andric   }
55960b57cec5SDimitry Andric 
55970b57cec5SDimitry Andric   void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
55980b57cec5SDimitry Andric     OS << "goto *";
55990b57cec5SDimitry Andric     if (Stmt *T = I->getTarget())
56000b57cec5SDimitry Andric       T->printPretty(OS, Helper, Policy);
56010b57cec5SDimitry Andric   }
56020b57cec5SDimitry Andric 
56030b57cec5SDimitry Andric   void VisitBinaryOperator(BinaryOperator* B) {
56040b57cec5SDimitry Andric     if (!B->isLogicalOp()) {
56050b57cec5SDimitry Andric       VisitExpr(B);
56060b57cec5SDimitry Andric       return;
56070b57cec5SDimitry Andric     }
56080b57cec5SDimitry Andric 
56090b57cec5SDimitry Andric     if (B->getLHS())
56100b57cec5SDimitry Andric       B->getLHS()->printPretty(OS, Helper, Policy);
56110b57cec5SDimitry Andric 
56120b57cec5SDimitry Andric     switch (B->getOpcode()) {
56130b57cec5SDimitry Andric       case BO_LOr:
56140b57cec5SDimitry Andric         OS << " || ...";
56150b57cec5SDimitry Andric         return;
56160b57cec5SDimitry Andric       case BO_LAnd:
56170b57cec5SDimitry Andric         OS << " && ...";
56180b57cec5SDimitry Andric         return;
56190b57cec5SDimitry Andric       default:
56200b57cec5SDimitry Andric         llvm_unreachable("Invalid logical operator.");
56210b57cec5SDimitry Andric     }
56220b57cec5SDimitry Andric   }
56230b57cec5SDimitry Andric 
56240b57cec5SDimitry Andric   void VisitExpr(Expr *E) {
56250b57cec5SDimitry Andric     E->printPretty(OS, Helper, Policy);
56260b57cec5SDimitry Andric   }
56270b57cec5SDimitry Andric 
56280b57cec5SDimitry Andric public:
56290b57cec5SDimitry Andric   void print(CFGTerminator T) {
56300b57cec5SDimitry Andric     switch (T.getKind()) {
56310b57cec5SDimitry Andric     case CFGTerminator::StmtBranch:
56320b57cec5SDimitry Andric       Visit(T.getStmt());
56330b57cec5SDimitry Andric       break;
56340b57cec5SDimitry Andric     case CFGTerminator::TemporaryDtorsBranch:
56350b57cec5SDimitry Andric       OS << "(Temp Dtor) ";
56360b57cec5SDimitry Andric       Visit(T.getStmt());
56370b57cec5SDimitry Andric       break;
56380b57cec5SDimitry Andric     case CFGTerminator::VirtualBaseBranch:
56390b57cec5SDimitry Andric       OS << "(See if most derived ctor has already initialized vbases)";
56400b57cec5SDimitry Andric       break;
56410b57cec5SDimitry Andric     }
56420b57cec5SDimitry Andric   }
56430b57cec5SDimitry Andric };
56440b57cec5SDimitry Andric 
56450b57cec5SDimitry Andric } // namespace
56460b57cec5SDimitry Andric 
56470b57cec5SDimitry Andric static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper,
56480b57cec5SDimitry Andric                               const CXXCtorInitializer *I) {
56490b57cec5SDimitry Andric   if (I->isBaseInitializer())
56500b57cec5SDimitry Andric     OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();
56510b57cec5SDimitry Andric   else if (I->isDelegatingInitializer())
56520b57cec5SDimitry Andric     OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();
56530b57cec5SDimitry Andric   else
56540b57cec5SDimitry Andric     OS << I->getAnyMember()->getName();
56550b57cec5SDimitry Andric   OS << "(";
56560b57cec5SDimitry Andric   if (Expr *IE = I->getInit())
56570b57cec5SDimitry Andric     IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
56580b57cec5SDimitry Andric   OS << ")";
56590b57cec5SDimitry Andric 
56600b57cec5SDimitry Andric   if (I->isBaseInitializer())
56610b57cec5SDimitry Andric     OS << " (Base initializer)";
56620b57cec5SDimitry Andric   else if (I->isDelegatingInitializer())
56630b57cec5SDimitry Andric     OS << " (Delegating initializer)";
56640b57cec5SDimitry Andric   else
56650b57cec5SDimitry Andric     OS << " (Member initializer)";
56660b57cec5SDimitry Andric }
56670b57cec5SDimitry Andric 
56680b57cec5SDimitry Andric static void print_construction_context(raw_ostream &OS,
56690b57cec5SDimitry Andric                                        StmtPrinterHelper &Helper,
56700b57cec5SDimitry Andric                                        const ConstructionContext *CC) {
56710b57cec5SDimitry Andric   SmallVector<const Stmt *, 3> Stmts;
56720b57cec5SDimitry Andric   switch (CC->getKind()) {
56730b57cec5SDimitry Andric   case ConstructionContext::SimpleConstructorInitializerKind: {
56740b57cec5SDimitry Andric     OS << ", ";
56750b57cec5SDimitry Andric     const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);
56760b57cec5SDimitry Andric     print_initializer(OS, Helper, SICC->getCXXCtorInitializer());
56770b57cec5SDimitry Andric     return;
56780b57cec5SDimitry Andric   }
56790b57cec5SDimitry Andric   case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: {
56800b57cec5SDimitry Andric     OS << ", ";
56810b57cec5SDimitry Andric     const auto *CICC =
56820b57cec5SDimitry Andric         cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);
56830b57cec5SDimitry Andric     print_initializer(OS, Helper, CICC->getCXXCtorInitializer());
56840b57cec5SDimitry Andric     Stmts.push_back(CICC->getCXXBindTemporaryExpr());
56850b57cec5SDimitry Andric     break;
56860b57cec5SDimitry Andric   }
56870b57cec5SDimitry Andric   case ConstructionContext::SimpleVariableKind: {
56880b57cec5SDimitry Andric     const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);
56890b57cec5SDimitry Andric     Stmts.push_back(SDSCC->getDeclStmt());
56900b57cec5SDimitry Andric     break;
56910b57cec5SDimitry Andric   }
56920b57cec5SDimitry Andric   case ConstructionContext::CXX17ElidedCopyVariableKind: {
56930b57cec5SDimitry Andric     const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);
56940b57cec5SDimitry Andric     Stmts.push_back(CDSCC->getDeclStmt());
56950b57cec5SDimitry Andric     Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());
56960b57cec5SDimitry Andric     break;
56970b57cec5SDimitry Andric   }
56980b57cec5SDimitry Andric   case ConstructionContext::NewAllocatedObjectKind: {
56990b57cec5SDimitry Andric     const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
57000b57cec5SDimitry Andric     Stmts.push_back(NECC->getCXXNewExpr());
57010b57cec5SDimitry Andric     break;
57020b57cec5SDimitry Andric   }
57030b57cec5SDimitry Andric   case ConstructionContext::SimpleReturnedValueKind: {
57040b57cec5SDimitry Andric     const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);
57050b57cec5SDimitry Andric     Stmts.push_back(RSCC->getReturnStmt());
57060b57cec5SDimitry Andric     break;
57070b57cec5SDimitry Andric   }
57080b57cec5SDimitry Andric   case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {
57090b57cec5SDimitry Andric     const auto *RSCC =
57100b57cec5SDimitry Andric         cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);
57110b57cec5SDimitry Andric     Stmts.push_back(RSCC->getReturnStmt());
57120b57cec5SDimitry Andric     Stmts.push_back(RSCC->getCXXBindTemporaryExpr());
57130b57cec5SDimitry Andric     break;
57140b57cec5SDimitry Andric   }
57150b57cec5SDimitry Andric   case ConstructionContext::SimpleTemporaryObjectKind: {
57160b57cec5SDimitry Andric     const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);
57170b57cec5SDimitry Andric     Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
57180b57cec5SDimitry Andric     Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
57190b57cec5SDimitry Andric     break;
57200b57cec5SDimitry Andric   }
57210b57cec5SDimitry Andric   case ConstructionContext::ElidedTemporaryObjectKind: {
57220b57cec5SDimitry Andric     const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
57230b57cec5SDimitry Andric     Stmts.push_back(TOCC->getCXXBindTemporaryExpr());
57240b57cec5SDimitry Andric     Stmts.push_back(TOCC->getMaterializedTemporaryExpr());
57250b57cec5SDimitry Andric     Stmts.push_back(TOCC->getConstructorAfterElision());
57260b57cec5SDimitry Andric     break;
57270b57cec5SDimitry Andric   }
5728972a253aSDimitry Andric   case ConstructionContext::LambdaCaptureKind: {
5729972a253aSDimitry Andric     const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);
5730972a253aSDimitry Andric     Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS);
5731972a253aSDimitry Andric     OS << "+" << LCC->getIndex();
5732972a253aSDimitry Andric     return;
5733972a253aSDimitry Andric   }
57340b57cec5SDimitry Andric   case ConstructionContext::ArgumentKind: {
57350b57cec5SDimitry Andric     const auto *ACC = cast<ArgumentConstructionContext>(CC);
57360b57cec5SDimitry Andric     if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {
57370b57cec5SDimitry Andric       OS << ", ";
57380b57cec5SDimitry Andric       Helper.handledStmt(const_cast<Stmt *>(BTE), OS);
57390b57cec5SDimitry Andric     }
57400b57cec5SDimitry Andric     OS << ", ";
57410b57cec5SDimitry Andric     Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);
57420b57cec5SDimitry Andric     OS << "+" << ACC->getIndex();
57430b57cec5SDimitry Andric     return;
57440b57cec5SDimitry Andric   }
57450b57cec5SDimitry Andric   }
57460b57cec5SDimitry Andric   for (auto I: Stmts)
57470b57cec5SDimitry Andric     if (I) {
57480b57cec5SDimitry Andric       OS << ", ";
57490b57cec5SDimitry Andric       Helper.handledStmt(const_cast<Stmt *>(I), OS);
57500b57cec5SDimitry Andric     }
57510b57cec5SDimitry Andric }
57520b57cec5SDimitry Andric 
57530b57cec5SDimitry Andric static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
5754a7dea167SDimitry Andric                        const CFGElement &E);
5755a7dea167SDimitry Andric 
5756a7dea167SDimitry Andric void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
575706c3fb27SDimitry Andric   LangOptions LangOpts;
575806c3fb27SDimitry Andric   StmtPrinterHelper Helper(nullptr, LangOpts);
5759a7dea167SDimitry Andric   print_elem(OS, Helper, *this);
5760a7dea167SDimitry Andric }
5761a7dea167SDimitry Andric 
5762a7dea167SDimitry Andric static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
57630b57cec5SDimitry Andric                        const CFGElement &E) {
5764a7dea167SDimitry Andric   switch (E.getKind()) {
5765a7dea167SDimitry Andric   case CFGElement::Kind::Statement:
5766a7dea167SDimitry Andric   case CFGElement::Kind::CXXRecordTypedCall:
5767a7dea167SDimitry Andric   case CFGElement::Kind::Constructor: {
5768a7dea167SDimitry Andric     CFGStmt CS = E.castAs<CFGStmt>();
5769a7dea167SDimitry Andric     const Stmt *S = CS.getStmt();
57700b57cec5SDimitry Andric     assert(S != nullptr && "Expecting non-null Stmt");
57710b57cec5SDimitry Andric 
57720b57cec5SDimitry Andric     // special printing for statement-expressions.
57730b57cec5SDimitry Andric     if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
57740b57cec5SDimitry Andric       const CompoundStmt *Sub = SE->getSubStmt();
57750b57cec5SDimitry Andric 
57760b57cec5SDimitry Andric       auto Children = Sub->children();
57770b57cec5SDimitry Andric       if (Children.begin() != Children.end()) {
57780b57cec5SDimitry Andric         OS << "({ ... ; ";
57790b57cec5SDimitry Andric         Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
57800b57cec5SDimitry Andric         OS << " })\n";
57810b57cec5SDimitry Andric         return;
57820b57cec5SDimitry Andric       }
57830b57cec5SDimitry Andric     }
57840b57cec5SDimitry Andric     // special printing for comma expressions.
57850b57cec5SDimitry Andric     if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
57860b57cec5SDimitry Andric       if (B->getOpcode() == BO_Comma) {
57870b57cec5SDimitry Andric         OS << "... , ";
57880b57cec5SDimitry Andric         Helper.handledStmt(B->getRHS(),OS);
57890b57cec5SDimitry Andric         OS << '\n';
57900b57cec5SDimitry Andric         return;
57910b57cec5SDimitry Andric       }
57920b57cec5SDimitry Andric     }
57930b57cec5SDimitry Andric     S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
57940b57cec5SDimitry Andric 
57950b57cec5SDimitry Andric     if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) {
57960b57cec5SDimitry Andric       if (isa<CXXOperatorCallExpr>(S))
57970b57cec5SDimitry Andric         OS << " (OperatorCall)";
57980b57cec5SDimitry Andric       OS << " (CXXRecordTypedCall";
57990b57cec5SDimitry Andric       print_construction_context(OS, Helper, VTC->getConstructionContext());
58000b57cec5SDimitry Andric       OS << ")";
58010b57cec5SDimitry Andric     } else if (isa<CXXOperatorCallExpr>(S)) {
58020b57cec5SDimitry Andric       OS << " (OperatorCall)";
58030b57cec5SDimitry Andric     } else if (isa<CXXBindTemporaryExpr>(S)) {
58040b57cec5SDimitry Andric       OS << " (BindTemporary)";
58050b57cec5SDimitry Andric     } else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {
58060b57cec5SDimitry Andric       OS << " (CXXConstructExpr";
5807bdd1243dSDimitry Andric       if (std::optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) {
58080b57cec5SDimitry Andric         print_construction_context(OS, Helper, CE->getConstructionContext());
58090b57cec5SDimitry Andric       }
581081ad6265SDimitry Andric       OS << ", " << CCE->getType() << ")";
58110b57cec5SDimitry Andric     } else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {
581281ad6265SDimitry Andric       OS << " (" << CE->getStmtClassName() << ", " << CE->getCastKindName()
581381ad6265SDimitry Andric          << ", " << CE->getType() << ")";
58140b57cec5SDimitry Andric     }
58150b57cec5SDimitry Andric 
58160b57cec5SDimitry Andric     // Expressions need a newline.
58170b57cec5SDimitry Andric     if (isa<Expr>(S))
58180b57cec5SDimitry Andric       OS << '\n';
5819a7dea167SDimitry Andric 
5820a7dea167SDimitry Andric     break;
5821a7dea167SDimitry Andric   }
5822a7dea167SDimitry Andric 
5823a7dea167SDimitry Andric   case CFGElement::Kind::Initializer:
5824a7dea167SDimitry Andric     print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());
58250b57cec5SDimitry Andric     OS << '\n';
5826a7dea167SDimitry Andric     break;
5827a7dea167SDimitry Andric 
5828a7dea167SDimitry Andric   case CFGElement::Kind::AutomaticObjectDtor: {
5829a7dea167SDimitry Andric     CFGAutomaticObjDtor DE = E.castAs<CFGAutomaticObjDtor>();
5830a7dea167SDimitry Andric     const VarDecl *VD = DE.getVarDecl();
58310b57cec5SDimitry Andric     Helper.handleDecl(VD, OS);
58320b57cec5SDimitry Andric 
58330b57cec5SDimitry Andric     QualType T = VD->getType();
58340b57cec5SDimitry Andric     if (T->isReferenceType())
58350b57cec5SDimitry Andric       T = getReferenceInitTemporaryType(VD->getInit(), nullptr);
58360b57cec5SDimitry Andric 
5837a7dea167SDimitry Andric     OS << ".~";
5838a7dea167SDimitry Andric     T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));
5839a7dea167SDimitry Andric     OS << "() (Implicit destructor)\n";
5840a7dea167SDimitry Andric     break;
5841a7dea167SDimitry Andric   }
58420b57cec5SDimitry Andric 
58435f757f3fSDimitry Andric   case CFGElement::Kind::CleanupFunction:
58445f757f3fSDimitry Andric     OS << "CleanupFunction ("
58455f757f3fSDimitry Andric        << E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")\n";
58465f757f3fSDimitry Andric     break;
58475f757f3fSDimitry Andric 
5848a7dea167SDimitry Andric   case CFGElement::Kind::LifetimeEnds:
5849a7dea167SDimitry Andric     Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);
58500b57cec5SDimitry Andric     OS << " (Lifetime ends)\n";
5851a7dea167SDimitry Andric     break;
5852a7dea167SDimitry Andric 
5853a7dea167SDimitry Andric   case CFGElement::Kind::LoopExit:
5854a7dea167SDimitry Andric     OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";
5855a7dea167SDimitry Andric     break;
5856a7dea167SDimitry Andric 
5857a7dea167SDimitry Andric   case CFGElement::Kind::ScopeBegin:
58580b57cec5SDimitry Andric     OS << "CFGScopeBegin(";
5859a7dea167SDimitry Andric     if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())
58600b57cec5SDimitry Andric       OS << VD->getQualifiedNameAsString();
58610b57cec5SDimitry Andric     OS << ")\n";
5862a7dea167SDimitry Andric     break;
5863a7dea167SDimitry Andric 
5864a7dea167SDimitry Andric   case CFGElement::Kind::ScopeEnd:
58650b57cec5SDimitry Andric     OS << "CFGScopeEnd(";
5866a7dea167SDimitry Andric     if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())
58670b57cec5SDimitry Andric       OS << VD->getQualifiedNameAsString();
58680b57cec5SDimitry Andric     OS << ")\n";
5869a7dea167SDimitry Andric     break;
5870a7dea167SDimitry Andric 
5871a7dea167SDimitry Andric   case CFGElement::Kind::NewAllocator:
58720b57cec5SDimitry Andric     OS << "CFGNewAllocator(";
5873a7dea167SDimitry Andric     if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())
58740b57cec5SDimitry Andric       AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
58750b57cec5SDimitry Andric     OS << ")\n";
5876a7dea167SDimitry Andric     break;
5877a7dea167SDimitry Andric 
5878a7dea167SDimitry Andric   case CFGElement::Kind::DeleteDtor: {
5879a7dea167SDimitry Andric     CFGDeleteDtor DE = E.castAs<CFGDeleteDtor>();
5880a7dea167SDimitry Andric     const CXXRecordDecl *RD = DE.getCXXRecordDecl();
58810b57cec5SDimitry Andric     if (!RD)
58820b57cec5SDimitry Andric       return;
58830b57cec5SDimitry Andric     CXXDeleteExpr *DelExpr =
5884a7dea167SDimitry Andric         const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());
58850b57cec5SDimitry Andric     Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);
58860b57cec5SDimitry Andric     OS << "->~" << RD->getName().str() << "()";
58870b57cec5SDimitry Andric     OS << " (Implicit destructor)\n";
5888a7dea167SDimitry Andric     break;
5889a7dea167SDimitry Andric   }
5890a7dea167SDimitry Andric 
5891a7dea167SDimitry Andric   case CFGElement::Kind::BaseDtor: {
5892a7dea167SDimitry Andric     const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();
58930b57cec5SDimitry Andric     OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";
58940b57cec5SDimitry Andric     OS << " (Base object destructor)\n";
5895a7dea167SDimitry Andric     break;
5896a7dea167SDimitry Andric   }
5897a7dea167SDimitry Andric 
5898a7dea167SDimitry Andric   case CFGElement::Kind::MemberDtor: {
5899a7dea167SDimitry Andric     const FieldDecl *FD = E.castAs<CFGMemberDtor>().getFieldDecl();
59000b57cec5SDimitry Andric     const Type *T = FD->getType()->getBaseElementTypeUnsafe();
59010b57cec5SDimitry Andric     OS << "this->" << FD->getName();
59020b57cec5SDimitry Andric     OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
59030b57cec5SDimitry Andric     OS << " (Member object destructor)\n";
5904a7dea167SDimitry Andric     break;
5905a7dea167SDimitry Andric   }
5906a7dea167SDimitry Andric 
5907a7dea167SDimitry Andric   case CFGElement::Kind::TemporaryDtor: {
5908349cc55cSDimitry Andric     const CXXBindTemporaryExpr *BT =
5909349cc55cSDimitry Andric         E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
59100b57cec5SDimitry Andric     OS << "~";
59110b57cec5SDimitry Andric     BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
59120b57cec5SDimitry Andric     OS << "() (Temporary object destructor)\n";
5913a7dea167SDimitry Andric     break;
5914a7dea167SDimitry Andric   }
59150b57cec5SDimitry Andric   }
59160b57cec5SDimitry Andric }
59170b57cec5SDimitry Andric 
59180b57cec5SDimitry Andric static void print_block(raw_ostream &OS, const CFG* cfg,
59190b57cec5SDimitry Andric                         const CFGBlock &B,
59200b57cec5SDimitry Andric                         StmtPrinterHelper &Helper, bool print_edges,
59210b57cec5SDimitry Andric                         bool ShowColors) {
59220b57cec5SDimitry Andric   Helper.setBlockID(B.getBlockID());
59230b57cec5SDimitry Andric 
59240b57cec5SDimitry Andric   // Print the header.
59250b57cec5SDimitry Andric   if (ShowColors)
59260b57cec5SDimitry Andric     OS.changeColor(raw_ostream::YELLOW, true);
59270b57cec5SDimitry Andric 
59280b57cec5SDimitry Andric   OS << "\n [B" << B.getBlockID();
59290b57cec5SDimitry Andric 
59300b57cec5SDimitry Andric   if (&B == &cfg->getEntry())
59310b57cec5SDimitry Andric     OS << " (ENTRY)]\n";
59320b57cec5SDimitry Andric   else if (&B == &cfg->getExit())
59330b57cec5SDimitry Andric     OS << " (EXIT)]\n";
59340b57cec5SDimitry Andric   else if (&B == cfg->getIndirectGotoBlock())
59350b57cec5SDimitry Andric     OS << " (INDIRECT GOTO DISPATCH)]\n";
59360b57cec5SDimitry Andric   else if (B.hasNoReturnElement())
59370b57cec5SDimitry Andric     OS << " (NORETURN)]\n";
59380b57cec5SDimitry Andric   else
59390b57cec5SDimitry Andric     OS << "]\n";
59400b57cec5SDimitry Andric 
59410b57cec5SDimitry Andric   if (ShowColors)
59420b57cec5SDimitry Andric     OS.resetColor();
59430b57cec5SDimitry Andric 
59440b57cec5SDimitry Andric   // Print the label of this block.
59450b57cec5SDimitry Andric   if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {
59460b57cec5SDimitry Andric     if (print_edges)
59470b57cec5SDimitry Andric       OS << "  ";
59480b57cec5SDimitry Andric 
59490b57cec5SDimitry Andric     if (LabelStmt *L = dyn_cast<LabelStmt>(Label))
59500b57cec5SDimitry Andric       OS << L->getName();
59510b57cec5SDimitry Andric     else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
59520b57cec5SDimitry Andric       OS << "case ";
5953349cc55cSDimitry Andric       if (const Expr *LHS = C->getLHS())
5954349cc55cSDimitry Andric         LHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
5955349cc55cSDimitry Andric       if (const Expr *RHS = C->getRHS()) {
59560b57cec5SDimitry Andric         OS << " ... ";
5957349cc55cSDimitry Andric         RHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));
59580b57cec5SDimitry Andric       }
59590b57cec5SDimitry Andric     } else if (isa<DefaultStmt>(Label))
59600b57cec5SDimitry Andric       OS << "default";
59610b57cec5SDimitry Andric     else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
59620b57cec5SDimitry Andric       OS << "catch (";
5963349cc55cSDimitry Andric       if (const VarDecl *ED = CS->getExceptionDecl())
5964349cc55cSDimitry Andric         ED->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
5965349cc55cSDimitry Andric       else
5966349cc55cSDimitry Andric         OS << "...";
5967349cc55cSDimitry Andric       OS << ")";
5968349cc55cSDimitry Andric     } else if (ObjCAtCatchStmt *CS = dyn_cast<ObjCAtCatchStmt>(Label)) {
5969349cc55cSDimitry Andric       OS << "@catch (";
5970349cc55cSDimitry Andric       if (const VarDecl *PD = CS->getCatchParamDecl())
5971349cc55cSDimitry Andric         PD->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);
59720b57cec5SDimitry Andric       else
59730b57cec5SDimitry Andric         OS << "...";
59740b57cec5SDimitry Andric       OS << ")";
59750b57cec5SDimitry Andric     } else if (SEHExceptStmt *ES = dyn_cast<SEHExceptStmt>(Label)) {
59760b57cec5SDimitry Andric       OS << "__except (";
59770b57cec5SDimitry Andric       ES->getFilterExpr()->printPretty(OS, &Helper,
59780b57cec5SDimitry Andric                                        PrintingPolicy(Helper.getLangOpts()), 0);
59790b57cec5SDimitry Andric       OS << ")";
59800b57cec5SDimitry Andric     } else
59810b57cec5SDimitry Andric       llvm_unreachable("Invalid label statement in CFGBlock.");
59820b57cec5SDimitry Andric 
59830b57cec5SDimitry Andric     OS << ":\n";
59840b57cec5SDimitry Andric   }
59850b57cec5SDimitry Andric 
59860b57cec5SDimitry Andric   // Iterate through the statements in the block and print them.
59870b57cec5SDimitry Andric   unsigned j = 1;
59880b57cec5SDimitry Andric 
59890b57cec5SDimitry Andric   for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
59900b57cec5SDimitry Andric        I != E ; ++I, ++j ) {
59910b57cec5SDimitry Andric     // Print the statement # in the basic block and the statement itself.
59920b57cec5SDimitry Andric     if (print_edges)
59930b57cec5SDimitry Andric       OS << " ";
59940b57cec5SDimitry Andric 
59950b57cec5SDimitry Andric     OS << llvm::format("%3d", j) << ": ";
59960b57cec5SDimitry Andric 
59970b57cec5SDimitry Andric     Helper.setStmtID(j);
59980b57cec5SDimitry Andric 
59990b57cec5SDimitry Andric     print_elem(OS, Helper, *I);
60000b57cec5SDimitry Andric   }
60010b57cec5SDimitry Andric 
60020b57cec5SDimitry Andric   // Print the terminator of this block.
60030b57cec5SDimitry Andric   if (B.getTerminator().isValid()) {
60040b57cec5SDimitry Andric     if (ShowColors)
60050b57cec5SDimitry Andric       OS.changeColor(raw_ostream::GREEN);
60060b57cec5SDimitry Andric 
60070b57cec5SDimitry Andric     OS << "   T: ";
60080b57cec5SDimitry Andric 
60090b57cec5SDimitry Andric     Helper.setBlockID(-1);
60100b57cec5SDimitry Andric 
60110b57cec5SDimitry Andric     PrintingPolicy PP(Helper.getLangOpts());
60120b57cec5SDimitry Andric     CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);
60130b57cec5SDimitry Andric     TPrinter.print(B.getTerminator());
60140b57cec5SDimitry Andric     OS << '\n';
60150b57cec5SDimitry Andric 
60160b57cec5SDimitry Andric     if (ShowColors)
60170b57cec5SDimitry Andric       OS.resetColor();
60180b57cec5SDimitry Andric   }
60190b57cec5SDimitry Andric 
60200b57cec5SDimitry Andric   if (print_edges) {
60210b57cec5SDimitry Andric     // Print the predecessors of this block.
60220b57cec5SDimitry Andric     if (!B.pred_empty()) {
60230b57cec5SDimitry Andric       const raw_ostream::Colors Color = raw_ostream::BLUE;
60240b57cec5SDimitry Andric       if (ShowColors)
60250b57cec5SDimitry Andric         OS.changeColor(Color);
60260b57cec5SDimitry Andric       OS << "   Preds " ;
60270b57cec5SDimitry Andric       if (ShowColors)
60280b57cec5SDimitry Andric         OS.resetColor();
60290b57cec5SDimitry Andric       OS << '(' << B.pred_size() << "):";
60300b57cec5SDimitry Andric       unsigned i = 0;
60310b57cec5SDimitry Andric 
60320b57cec5SDimitry Andric       if (ShowColors)
60330b57cec5SDimitry Andric         OS.changeColor(Color);
60340b57cec5SDimitry Andric 
60350b57cec5SDimitry Andric       for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
60360b57cec5SDimitry Andric            I != E; ++I, ++i) {
60370b57cec5SDimitry Andric         if (i % 10 == 8)
60380b57cec5SDimitry Andric           OS << "\n     ";
60390b57cec5SDimitry Andric 
60400b57cec5SDimitry Andric         CFGBlock *B = *I;
60410b57cec5SDimitry Andric         bool Reachable = true;
60420b57cec5SDimitry Andric         if (!B) {
60430b57cec5SDimitry Andric           Reachable = false;
60440b57cec5SDimitry Andric           B = I->getPossiblyUnreachableBlock();
60450b57cec5SDimitry Andric         }
60460b57cec5SDimitry Andric 
60470b57cec5SDimitry Andric         OS << " B" << B->getBlockID();
60480b57cec5SDimitry Andric         if (!Reachable)
60490b57cec5SDimitry Andric           OS << "(Unreachable)";
60500b57cec5SDimitry Andric       }
60510b57cec5SDimitry Andric 
60520b57cec5SDimitry Andric       if (ShowColors)
60530b57cec5SDimitry Andric         OS.resetColor();
60540b57cec5SDimitry Andric 
60550b57cec5SDimitry Andric       OS << '\n';
60560b57cec5SDimitry Andric     }
60570b57cec5SDimitry Andric 
60580b57cec5SDimitry Andric     // Print the successors of this block.
60590b57cec5SDimitry Andric     if (!B.succ_empty()) {
60600b57cec5SDimitry Andric       const raw_ostream::Colors Color = raw_ostream::MAGENTA;
60610b57cec5SDimitry Andric       if (ShowColors)
60620b57cec5SDimitry Andric         OS.changeColor(Color);
60630b57cec5SDimitry Andric       OS << "   Succs ";
60640b57cec5SDimitry Andric       if (ShowColors)
60650b57cec5SDimitry Andric         OS.resetColor();
60660b57cec5SDimitry Andric       OS << '(' << B.succ_size() << "):";
60670b57cec5SDimitry Andric       unsigned i = 0;
60680b57cec5SDimitry Andric 
60690b57cec5SDimitry Andric       if (ShowColors)
60700b57cec5SDimitry Andric         OS.changeColor(Color);
60710b57cec5SDimitry Andric 
60720b57cec5SDimitry Andric       for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
60730b57cec5SDimitry Andric            I != E; ++I, ++i) {
60740b57cec5SDimitry Andric         if (i % 10 == 8)
60750b57cec5SDimitry Andric           OS << "\n    ";
60760b57cec5SDimitry Andric 
60770b57cec5SDimitry Andric         CFGBlock *B = *I;
60780b57cec5SDimitry Andric 
60790b57cec5SDimitry Andric         bool Reachable = true;
60800b57cec5SDimitry Andric         if (!B) {
60810b57cec5SDimitry Andric           Reachable = false;
60820b57cec5SDimitry Andric           B = I->getPossiblyUnreachableBlock();
60830b57cec5SDimitry Andric         }
60840b57cec5SDimitry Andric 
60850b57cec5SDimitry Andric         if (B) {
60860b57cec5SDimitry Andric           OS << " B" << B->getBlockID();
60870b57cec5SDimitry Andric           if (!Reachable)
60880b57cec5SDimitry Andric             OS << "(Unreachable)";
60890b57cec5SDimitry Andric         }
60900b57cec5SDimitry Andric         else {
60910b57cec5SDimitry Andric           OS << " NULL";
60920b57cec5SDimitry Andric         }
60930b57cec5SDimitry Andric       }
60940b57cec5SDimitry Andric 
60950b57cec5SDimitry Andric       if (ShowColors)
60960b57cec5SDimitry Andric         OS.resetColor();
60970b57cec5SDimitry Andric       OS << '\n';
60980b57cec5SDimitry Andric     }
60990b57cec5SDimitry Andric   }
61000b57cec5SDimitry Andric }
61010b57cec5SDimitry Andric 
61020b57cec5SDimitry Andric /// dump - A simple pretty printer of a CFG that outputs to stderr.
61030b57cec5SDimitry Andric void CFG::dump(const LangOptions &LO, bool ShowColors) const {
61040b57cec5SDimitry Andric   print(llvm::errs(), LO, ShowColors);
61050b57cec5SDimitry Andric }
61060b57cec5SDimitry Andric 
61070b57cec5SDimitry Andric /// print - A simple pretty printer of a CFG that outputs to an ostream.
61080b57cec5SDimitry Andric void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const {
61090b57cec5SDimitry Andric   StmtPrinterHelper Helper(this, LO);
61100b57cec5SDimitry Andric 
61110b57cec5SDimitry Andric   // Print the entry block.
61120b57cec5SDimitry Andric   print_block(OS, this, getEntry(), Helper, true, ShowColors);
61130b57cec5SDimitry Andric 
61140b57cec5SDimitry Andric   // Iterate through the CFGBlocks and print them one by one.
61150b57cec5SDimitry Andric   for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
61160b57cec5SDimitry Andric     // Skip the entry block, because we already printed it.
61170b57cec5SDimitry Andric     if (&(**I) == &getEntry() || &(**I) == &getExit())
61180b57cec5SDimitry Andric       continue;
61190b57cec5SDimitry Andric 
61200b57cec5SDimitry Andric     print_block(OS, this, **I, Helper, true, ShowColors);
61210b57cec5SDimitry Andric   }
61220b57cec5SDimitry Andric 
61230b57cec5SDimitry Andric   // Print the exit block.
61240b57cec5SDimitry Andric   print_block(OS, this, getExit(), Helper, true, ShowColors);
61250b57cec5SDimitry Andric   OS << '\n';
61260b57cec5SDimitry Andric   OS.flush();
61270b57cec5SDimitry Andric }
61280b57cec5SDimitry Andric 
6129a7dea167SDimitry Andric size_t CFGBlock::getIndexInCFG() const {
6130a7dea167SDimitry Andric   return llvm::find(*getParent(), this) - getParent()->begin();
6131a7dea167SDimitry Andric }
6132a7dea167SDimitry Andric 
61330b57cec5SDimitry Andric /// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
61340b57cec5SDimitry Andric void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,
61350b57cec5SDimitry Andric                     bool ShowColors) const {
61360b57cec5SDimitry Andric   print(llvm::errs(), cfg, LO, ShowColors);
61370b57cec5SDimitry Andric }
61380b57cec5SDimitry Andric 
61390b57cec5SDimitry Andric LLVM_DUMP_METHOD void CFGBlock::dump() const {
61400b57cec5SDimitry Andric   dump(getParent(), LangOptions(), false);
61410b57cec5SDimitry Andric }
61420b57cec5SDimitry Andric 
61430b57cec5SDimitry Andric /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
61440b57cec5SDimitry Andric ///   Generally this will only be called from CFG::print.
61450b57cec5SDimitry Andric void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
61460b57cec5SDimitry Andric                      const LangOptions &LO, bool ShowColors) const {
61470b57cec5SDimitry Andric   StmtPrinterHelper Helper(cfg, LO);
61480b57cec5SDimitry Andric   print_block(OS, cfg, *this, Helper, true, ShowColors);
61490b57cec5SDimitry Andric   OS << '\n';
61500b57cec5SDimitry Andric }
61510b57cec5SDimitry Andric 
61520b57cec5SDimitry Andric /// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
61530b57cec5SDimitry Andric void CFGBlock::printTerminator(raw_ostream &OS,
61540b57cec5SDimitry Andric                                const LangOptions &LO) const {
61550b57cec5SDimitry Andric   CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));
61560b57cec5SDimitry Andric   TPrinter.print(getTerminator());
61570b57cec5SDimitry Andric }
61580b57cec5SDimitry Andric 
61590b57cec5SDimitry Andric /// printTerminatorJson - Pretty-prints the terminator in JSON format.
61600b57cec5SDimitry Andric void CFGBlock::printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
61610b57cec5SDimitry Andric                                    bool AddQuotes) const {
61620b57cec5SDimitry Andric   std::string Buf;
61630b57cec5SDimitry Andric   llvm::raw_string_ostream TempOut(Buf);
61640b57cec5SDimitry Andric 
61650b57cec5SDimitry Andric   printTerminator(TempOut, LO);
61660b57cec5SDimitry Andric 
61670b57cec5SDimitry Andric   Out << JsonFormat(TempOut.str(), AddQuotes);
61680b57cec5SDimitry Andric }
61690b57cec5SDimitry Andric 
6170a7dea167SDimitry Andric // Returns true if by simply looking at the block, we can be sure that it
6171a7dea167SDimitry Andric // results in a sink during analysis. This is useful to know when the analysis
6172a7dea167SDimitry Andric // was interrupted, and we try to figure out if it would sink eventually.
6173a7dea167SDimitry Andric // There may be many more reasons why a sink would appear during analysis
6174a7dea167SDimitry Andric // (eg. checkers may generate sinks arbitrarily), but here we only consider
6175a7dea167SDimitry Andric // sinks that would be obvious by looking at the CFG.
6176a7dea167SDimitry Andric static bool isImmediateSinkBlock(const CFGBlock *Blk) {
6177a7dea167SDimitry Andric   if (Blk->hasNoReturnElement())
6178a7dea167SDimitry Andric     return true;
6179a7dea167SDimitry Andric 
6180a7dea167SDimitry Andric   // FIXME: Throw-expressions are currently generating sinks during analysis:
6181a7dea167SDimitry Andric   // they're not supported yet, and also often used for actually terminating
6182a7dea167SDimitry Andric   // the program. So we should treat them as sinks in this analysis as well,
6183a7dea167SDimitry Andric   // at least for now, but once we have better support for exceptions,
6184a7dea167SDimitry Andric   // we'd need to carefully handle the case when the throw is being
6185a7dea167SDimitry Andric   // immediately caught.
6186349cc55cSDimitry Andric   if (llvm::any_of(*Blk, [](const CFGElement &Elm) {
6187bdd1243dSDimitry Andric         if (std::optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())
6188a7dea167SDimitry Andric           if (isa<CXXThrowExpr>(StmtElm->getStmt()))
6189a7dea167SDimitry Andric             return true;
6190a7dea167SDimitry Andric         return false;
6191a7dea167SDimitry Andric       }))
6192a7dea167SDimitry Andric     return true;
6193a7dea167SDimitry Andric 
6194a7dea167SDimitry Andric   return false;
6195a7dea167SDimitry Andric }
6196a7dea167SDimitry Andric 
6197a7dea167SDimitry Andric bool CFGBlock::isInevitablySinking() const {
6198a7dea167SDimitry Andric   const CFG &Cfg = *getParent();
6199a7dea167SDimitry Andric 
6200a7dea167SDimitry Andric   const CFGBlock *StartBlk = this;
6201a7dea167SDimitry Andric   if (isImmediateSinkBlock(StartBlk))
6202a7dea167SDimitry Andric     return true;
6203a7dea167SDimitry Andric 
6204a7dea167SDimitry Andric   llvm::SmallVector<const CFGBlock *, 32> DFSWorkList;
6205a7dea167SDimitry Andric   llvm::SmallPtrSet<const CFGBlock *, 32> Visited;
6206a7dea167SDimitry Andric 
6207a7dea167SDimitry Andric   DFSWorkList.push_back(StartBlk);
6208a7dea167SDimitry Andric   while (!DFSWorkList.empty()) {
6209a7dea167SDimitry Andric     const CFGBlock *Blk = DFSWorkList.back();
6210a7dea167SDimitry Andric     DFSWorkList.pop_back();
6211a7dea167SDimitry Andric     Visited.insert(Blk);
6212a7dea167SDimitry Andric 
6213a7dea167SDimitry Andric     // If at least one path reaches the CFG exit, it means that control is
6214a7dea167SDimitry Andric     // returned to the caller. For now, say that we are not sure what
6215a7dea167SDimitry Andric     // happens next. If necessary, this can be improved to analyze
6216a7dea167SDimitry Andric     // the parent StackFrameContext's call site in a similar manner.
6217a7dea167SDimitry Andric     if (Blk == &Cfg.getExit())
6218a7dea167SDimitry Andric       return false;
6219a7dea167SDimitry Andric 
6220a7dea167SDimitry Andric     for (const auto &Succ : Blk->succs()) {
6221a7dea167SDimitry Andric       if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
6222a7dea167SDimitry Andric         if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {
6223a7dea167SDimitry Andric           // If the block has reachable child blocks that aren't no-return,
6224a7dea167SDimitry Andric           // add them to the worklist.
6225a7dea167SDimitry Andric           DFSWorkList.push_back(SuccBlk);
6226a7dea167SDimitry Andric         }
6227a7dea167SDimitry Andric       }
6228a7dea167SDimitry Andric     }
6229a7dea167SDimitry Andric   }
6230a7dea167SDimitry Andric 
6231a7dea167SDimitry Andric   // Nothing reached the exit. It can only mean one thing: there's no return.
6232a7dea167SDimitry Andric   return true;
6233a7dea167SDimitry Andric }
6234a7dea167SDimitry Andric 
62350b57cec5SDimitry Andric const Expr *CFGBlock::getLastCondition() const {
62360b57cec5SDimitry Andric   // If the terminator is a temporary dtor or a virtual base, etc, we can't
62370b57cec5SDimitry Andric   // retrieve a meaningful condition, bail out.
62380b57cec5SDimitry Andric   if (Terminator.getKind() != CFGTerminator::StmtBranch)
62390b57cec5SDimitry Andric     return nullptr;
62400b57cec5SDimitry Andric 
62410b57cec5SDimitry Andric   // Also, if this method was called on a block that doesn't have 2 successors,
62420b57cec5SDimitry Andric   // this block doesn't have retrievable condition.
62430b57cec5SDimitry Andric   if (succ_size() < 2)
62440b57cec5SDimitry Andric     return nullptr;
62450b57cec5SDimitry Andric 
6246480093f4SDimitry Andric   // FIXME: Is there a better condition expression we can return in this case?
6247480093f4SDimitry Andric   if (size() == 0)
6248480093f4SDimitry Andric     return nullptr;
6249480093f4SDimitry Andric 
62500b57cec5SDimitry Andric   auto StmtElem = rbegin()->getAs<CFGStmt>();
62510b57cec5SDimitry Andric   if (!StmtElem)
62520b57cec5SDimitry Andric     return nullptr;
62530b57cec5SDimitry Andric 
62540b57cec5SDimitry Andric   const Stmt *Cond = StmtElem->getStmt();
6255480093f4SDimitry Andric   if (isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))
62560b57cec5SDimitry Andric     return nullptr;
62570b57cec5SDimitry Andric 
62580b57cec5SDimitry Andric   // Only ObjCForCollectionStmt is known not to be a non-Expr terminator, hence
62590b57cec5SDimitry Andric   // the cast<>.
62600b57cec5SDimitry Andric   return cast<Expr>(Cond)->IgnoreParens();
62610b57cec5SDimitry Andric }
62620b57cec5SDimitry Andric 
62630b57cec5SDimitry Andric Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {
62640b57cec5SDimitry Andric   Stmt *Terminator = getTerminatorStmt();
62650b57cec5SDimitry Andric   if (!Terminator)
62660b57cec5SDimitry Andric     return nullptr;
62670b57cec5SDimitry Andric 
62680b57cec5SDimitry Andric   Expr *E = nullptr;
62690b57cec5SDimitry Andric 
62700b57cec5SDimitry Andric   switch (Terminator->getStmtClass()) {
62710b57cec5SDimitry Andric     default:
62720b57cec5SDimitry Andric       break;
62730b57cec5SDimitry Andric 
62740b57cec5SDimitry Andric     case Stmt::CXXForRangeStmtClass:
62750b57cec5SDimitry Andric       E = cast<CXXForRangeStmt>(Terminator)->getCond();
62760b57cec5SDimitry Andric       break;
62770b57cec5SDimitry Andric 
62780b57cec5SDimitry Andric     case Stmt::ForStmtClass:
62790b57cec5SDimitry Andric       E = cast<ForStmt>(Terminator)->getCond();
62800b57cec5SDimitry Andric       break;
62810b57cec5SDimitry Andric 
62820b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
62830b57cec5SDimitry Andric       E = cast<WhileStmt>(Terminator)->getCond();
62840b57cec5SDimitry Andric       break;
62850b57cec5SDimitry Andric 
62860b57cec5SDimitry Andric     case Stmt::DoStmtClass:
62870b57cec5SDimitry Andric       E = cast<DoStmt>(Terminator)->getCond();
62880b57cec5SDimitry Andric       break;
62890b57cec5SDimitry Andric 
62900b57cec5SDimitry Andric     case Stmt::IfStmtClass:
62910b57cec5SDimitry Andric       E = cast<IfStmt>(Terminator)->getCond();
62920b57cec5SDimitry Andric       break;
62930b57cec5SDimitry Andric 
62940b57cec5SDimitry Andric     case Stmt::ChooseExprClass:
62950b57cec5SDimitry Andric       E = cast<ChooseExpr>(Terminator)->getCond();
62960b57cec5SDimitry Andric       break;
62970b57cec5SDimitry Andric 
62980b57cec5SDimitry Andric     case Stmt::IndirectGotoStmtClass:
62990b57cec5SDimitry Andric       E = cast<IndirectGotoStmt>(Terminator)->getTarget();
63000b57cec5SDimitry Andric       break;
63010b57cec5SDimitry Andric 
63020b57cec5SDimitry Andric     case Stmt::SwitchStmtClass:
63030b57cec5SDimitry Andric       E = cast<SwitchStmt>(Terminator)->getCond();
63040b57cec5SDimitry Andric       break;
63050b57cec5SDimitry Andric 
63060b57cec5SDimitry Andric     case Stmt::BinaryConditionalOperatorClass:
63070b57cec5SDimitry Andric       E = cast<BinaryConditionalOperator>(Terminator)->getCond();
63080b57cec5SDimitry Andric       break;
63090b57cec5SDimitry Andric 
63100b57cec5SDimitry Andric     case Stmt::ConditionalOperatorClass:
63110b57cec5SDimitry Andric       E = cast<ConditionalOperator>(Terminator)->getCond();
63120b57cec5SDimitry Andric       break;
63130b57cec5SDimitry Andric 
63140b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass: // '&&' and '||'
63150b57cec5SDimitry Andric       E = cast<BinaryOperator>(Terminator)->getLHS();
63160b57cec5SDimitry Andric       break;
63170b57cec5SDimitry Andric 
63180b57cec5SDimitry Andric     case Stmt::ObjCForCollectionStmtClass:
63190b57cec5SDimitry Andric       return Terminator;
63200b57cec5SDimitry Andric   }
63210b57cec5SDimitry Andric 
63220b57cec5SDimitry Andric   if (!StripParens)
63230b57cec5SDimitry Andric     return E;
63240b57cec5SDimitry Andric 
63250b57cec5SDimitry Andric   return E ? E->IgnoreParens() : nullptr;
63260b57cec5SDimitry Andric }
63270b57cec5SDimitry Andric 
63280b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
63290b57cec5SDimitry Andric // CFG Graphviz Visualization
63300b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
63310b57cec5SDimitry Andric 
63320b57cec5SDimitry Andric static StmtPrinterHelper *GraphHelper;
63330b57cec5SDimitry Andric 
63340b57cec5SDimitry Andric void CFG::viewCFG(const LangOptions &LO) const {
63350b57cec5SDimitry Andric   StmtPrinterHelper H(this, LO);
63360b57cec5SDimitry Andric   GraphHelper = &H;
63370b57cec5SDimitry Andric   llvm::ViewGraph(this,"CFG");
63380b57cec5SDimitry Andric   GraphHelper = nullptr;
63390b57cec5SDimitry Andric }
63400b57cec5SDimitry Andric 
63410b57cec5SDimitry Andric namespace llvm {
63420b57cec5SDimitry Andric 
63430b57cec5SDimitry Andric template<>
63440b57cec5SDimitry Andric struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
63450b57cec5SDimitry Andric   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
63460b57cec5SDimitry Andric 
63470b57cec5SDimitry Andric   static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph) {
63480b57cec5SDimitry Andric     std::string OutSStr;
63490b57cec5SDimitry Andric     llvm::raw_string_ostream Out(OutSStr);
63500b57cec5SDimitry Andric     print_block(Out,Graph, *Node, *GraphHelper, false, false);
63510b57cec5SDimitry Andric     std::string& OutStr = Out.str();
63520b57cec5SDimitry Andric 
63530b57cec5SDimitry Andric     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
63540b57cec5SDimitry Andric 
63550b57cec5SDimitry Andric     // Process string output to make it nicer...
63560b57cec5SDimitry Andric     for (unsigned i = 0; i != OutStr.length(); ++i)
63570b57cec5SDimitry Andric       if (OutStr[i] == '\n') {                            // Left justify
63580b57cec5SDimitry Andric         OutStr[i] = '\\';
63590b57cec5SDimitry Andric         OutStr.insert(OutStr.begin()+i+1, 'l');
63600b57cec5SDimitry Andric       }
63610b57cec5SDimitry Andric 
63620b57cec5SDimitry Andric     return OutStr;
63630b57cec5SDimitry Andric   }
63640b57cec5SDimitry Andric };
63650b57cec5SDimitry Andric 
63660b57cec5SDimitry Andric } // namespace llvm
6367