Path: blob/main/contrib/llvm-project/clang/lib/Analysis/CFG.cpp
35233 views
//===- CFG.cpp - Classes for representing and building CFGs ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the CFG and CFGBuilder classes for representing and9// building Control-Flow Graphs (CFGs) from ASTs.10//11//===----------------------------------------------------------------------===//1213#include "clang/Analysis/CFG.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/Attr.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclBase.h"18#include "clang/AST/DeclCXX.h"19#include "clang/AST/DeclGroup.h"20#include "clang/AST/Expr.h"21#include "clang/AST/ExprCXX.h"22#include "clang/AST/OperationKinds.h"23#include "clang/AST/PrettyPrinter.h"24#include "clang/AST/Stmt.h"25#include "clang/AST/StmtCXX.h"26#include "clang/AST/StmtObjC.h"27#include "clang/AST/StmtVisitor.h"28#include "clang/AST/Type.h"29#include "clang/Analysis/ConstructionContext.h"30#include "clang/Analysis/Support/BumpVector.h"31#include "clang/Basic/Builtins.h"32#include "clang/Basic/ExceptionSpecificationType.h"33#include "clang/Basic/JsonSupport.h"34#include "clang/Basic/LLVM.h"35#include "clang/Basic/LangOptions.h"36#include "clang/Basic/SourceLocation.h"37#include "clang/Basic/Specifiers.h"38#include "llvm/ADT/APInt.h"39#include "llvm/ADT/APSInt.h"40#include "llvm/ADT/ArrayRef.h"41#include "llvm/ADT/DenseMap.h"42#include "llvm/ADT/STLExtras.h"43#include "llvm/ADT/SetVector.h"44#include "llvm/ADT/SmallPtrSet.h"45#include "llvm/ADT/SmallVector.h"46#include "llvm/Support/Allocator.h"47#include "llvm/Support/Casting.h"48#include "llvm/Support/Compiler.h"49#include "llvm/Support/DOTGraphTraits.h"50#include "llvm/Support/ErrorHandling.h"51#include "llvm/Support/Format.h"52#include "llvm/Support/GraphWriter.h"53#include "llvm/Support/SaveAndRestore.h"54#include "llvm/Support/raw_ostream.h"55#include <cassert>56#include <memory>57#include <optional>58#include <string>59#include <tuple>60#include <utility>61#include <vector>6263using namespace clang;6465static SourceLocation GetEndLoc(Decl *D) {66if (VarDecl *VD = dyn_cast<VarDecl>(D))67if (Expr *Ex = VD->getInit())68return Ex->getSourceRange().getEnd();69return D->getLocation();70}7172/// Returns true on constant values based around a single IntegerLiteral.73/// Allow for use of parentheses, integer casts, and negative signs.74/// FIXME: it would be good to unify this function with75/// getIntegerLiteralSubexpressionValue at some point given the similarity76/// between the functions.7778static bool IsIntegerLiteralConstantExpr(const Expr *E) {79// Allow parentheses80E = E->IgnoreParens();8182// Allow conversions to different integer kind.83if (const auto *CE = dyn_cast<CastExpr>(E)) {84if (CE->getCastKind() != CK_IntegralCast)85return false;86E = CE->getSubExpr();87}8889// Allow negative numbers.90if (const auto *UO = dyn_cast<UnaryOperator>(E)) {91if (UO->getOpcode() != UO_Minus)92return false;93E = UO->getSubExpr();94}9596return isa<IntegerLiteral>(E);97}9899/// Helper for tryNormalizeBinaryOperator. Attempts to extract an IntegerLiteral100/// constant expression or EnumConstantDecl from the given Expr. If it fails,101/// returns nullptr.102static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) {103E = E->IgnoreParens();104if (IsIntegerLiteralConstantExpr(E))105return E;106if (auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))107return isa<EnumConstantDecl>(DR->getDecl()) ? DR : nullptr;108return nullptr;109}110111/// Tries to interpret a binary operator into `Expr Op NumExpr` form, if112/// NumExpr is an integer literal or an enum constant.113///114/// If this fails, at least one of the returned DeclRefExpr or Expr will be115/// null.116static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>117tryNormalizeBinaryOperator(const BinaryOperator *B) {118BinaryOperatorKind Op = B->getOpcode();119120const Expr *MaybeDecl = B->getLHS();121const Expr *Constant = tryTransformToIntOrEnumConstant(B->getRHS());122// Expr looked like `0 == Foo` instead of `Foo == 0`123if (Constant == nullptr) {124// Flip the operator125if (Op == BO_GT)126Op = BO_LT;127else if (Op == BO_GE)128Op = BO_LE;129else if (Op == BO_LT)130Op = BO_GT;131else if (Op == BO_LE)132Op = BO_GE;133134MaybeDecl = B->getRHS();135Constant = tryTransformToIntOrEnumConstant(B->getLHS());136}137138return std::make_tuple(MaybeDecl, Op, Constant);139}140141/// For an expression `x == Foo && x == Bar`, this determines whether the142/// `Foo` and `Bar` are either of the same enumeration type, or both integer143/// literals.144///145/// It's an error to pass this arguments that are not either IntegerLiterals146/// or DeclRefExprs (that have decls of type EnumConstantDecl)147static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) {148// User intent isn't clear if they're mixing int literals with enum149// constants.150if (isa<DeclRefExpr>(E1) != isa<DeclRefExpr>(E2))151return false;152153// Integer literal comparisons, regardless of literal type, are acceptable.154if (!isa<DeclRefExpr>(E1))155return true;156157// IntegerLiterals are handled above and only EnumConstantDecls are expected158// beyond this point159assert(isa<DeclRefExpr>(E1) && isa<DeclRefExpr>(E2));160auto *Decl1 = cast<DeclRefExpr>(E1)->getDecl();161auto *Decl2 = cast<DeclRefExpr>(E2)->getDecl();162163assert(isa<EnumConstantDecl>(Decl1) && isa<EnumConstantDecl>(Decl2));164const DeclContext *DC1 = Decl1->getDeclContext();165const DeclContext *DC2 = Decl2->getDeclContext();166167assert(isa<EnumDecl>(DC1) && isa<EnumDecl>(DC2));168return DC1 == DC2;169}170171namespace {172173class CFGBuilder;174175/// The CFG builder uses a recursive algorithm to build the CFG. When176/// we process an expression, sometimes we know that we must add the177/// subexpressions as block-level expressions. For example:178///179/// exp1 || exp2180///181/// When processing the '||' expression, we know that exp1 and exp2182/// need to be added as block-level expressions, even though they183/// might not normally need to be. AddStmtChoice records this184/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then185/// the builder has an option not to add a subexpression as a186/// block-level expression.187class AddStmtChoice {188public:189enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };190191AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}192193bool alwaysAdd(CFGBuilder &builder,194const Stmt *stmt) const;195196/// Return a copy of this object, except with the 'always-add' bit197/// set as specified.198AddStmtChoice withAlwaysAdd(bool alwaysAdd) const {199return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd);200}201202private:203Kind kind;204};205206/// LocalScope - Node in tree of local scopes created for C++ implicit207/// destructor calls generation. It contains list of automatic variables208/// declared in the scope and link to position in previous scope this scope209/// began in.210///211/// The process of creating local scopes is as follows:212/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),213/// - Before processing statements in scope (e.g. CompoundStmt) create214/// LocalScope object using CFGBuilder::ScopePos as link to previous scope215/// and set CFGBuilder::ScopePos to the end of new scope,216/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points217/// at this VarDecl,218/// - For every normal (without jump) end of scope add to CFGBlock destructors219/// for objects in the current scope,220/// - For every jump add to CFGBlock destructors for objects221/// between CFGBuilder::ScopePos and local scope position saved for jump222/// target. Thanks to C++ restrictions on goto jumps we can be sure that223/// jump target position will be on the path to root from CFGBuilder::ScopePos224/// (adding any variable that doesn't need constructor to be called to225/// LocalScope can break this assumption),226///227class LocalScope {228public:229using AutomaticVarsTy = BumpVector<VarDecl *>;230231/// const_iterator - Iterates local scope backwards and jumps to previous232/// scope on reaching the beginning of currently iterated scope.233class const_iterator {234const LocalScope* Scope = nullptr;235236/// VarIter is guaranteed to be greater then 0 for every valid iterator.237/// Invalid iterator (with null Scope) has VarIter equal to 0.238unsigned VarIter = 0;239240public:241/// Create invalid iterator. Dereferencing invalid iterator is not allowed.242/// Incrementing invalid iterator is allowed and will result in invalid243/// iterator.244const_iterator() = default;245246/// Create valid iterator. In case when S.Prev is an invalid iterator and247/// I is equal to 0, this will create invalid iterator.248const_iterator(const LocalScope& S, unsigned I)249: Scope(&S), VarIter(I) {250// Iterator to "end" of scope is not allowed. Handle it by going up251// in scopes tree possibly up to invalid iterator in the root.252if (VarIter == 0 && Scope)253*this = Scope->Prev;254}255256VarDecl *const* operator->() const {257assert(Scope && "Dereferencing invalid iterator is not allowed");258assert(VarIter != 0 && "Iterator has invalid value of VarIter member");259return &Scope->Vars[VarIter - 1];260}261262const VarDecl *getFirstVarInScope() const {263assert(Scope && "Dereferencing invalid iterator is not allowed");264assert(VarIter != 0 && "Iterator has invalid value of VarIter member");265return Scope->Vars[0];266}267268VarDecl *operator*() const {269return *this->operator->();270}271272const_iterator &operator++() {273if (!Scope)274return *this;275276assert(VarIter != 0 && "Iterator has invalid value of VarIter member");277--VarIter;278if (VarIter == 0)279*this = Scope->Prev;280return *this;281}282const_iterator operator++(int) {283const_iterator P = *this;284++*this;285return P;286}287288bool operator==(const const_iterator &rhs) const {289return Scope == rhs.Scope && VarIter == rhs.VarIter;290}291bool operator!=(const const_iterator &rhs) const {292return !(*this == rhs);293}294295explicit operator bool() const {296return *this != const_iterator();297}298299int distance(const_iterator L);300const_iterator shared_parent(const_iterator L);301bool pointsToFirstDeclaredVar() { return VarIter == 1; }302bool inSameLocalScope(const_iterator rhs) { return Scope == rhs.Scope; }303};304305private:306BumpVectorContext ctx;307308/// Automatic variables in order of declaration.309AutomaticVarsTy Vars;310311/// Iterator to variable in previous scope that was declared just before312/// begin of this scope.313const_iterator Prev;314315public:316/// Constructs empty scope linked to previous scope in specified place.317LocalScope(BumpVectorContext ctx, const_iterator P)318: ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}319320/// Begin of scope in direction of CFG building (backwards).321const_iterator begin() const { return const_iterator(*this, Vars.size()); }322323void addVar(VarDecl *VD) {324Vars.push_back(VD, ctx);325}326};327328} // namespace329330/// distance - Calculates distance from this to L. L must be reachable from this331/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t.332/// number of scopes between this and L.333int LocalScope::const_iterator::distance(LocalScope::const_iterator L) {334int D = 0;335const_iterator F = *this;336while (F.Scope != L.Scope) {337assert(F != const_iterator() &&338"L iterator is not reachable from F iterator.");339D += F.VarIter;340F = F.Scope->Prev;341}342D += F.VarIter - L.VarIter;343return D;344}345346/// Calculates the closest parent of this iterator347/// that is in a scope reachable through the parents of L.348/// I.e. when using 'goto' from this to L, the lifetime of all variables349/// between this and shared_parent(L) end.350LocalScope::const_iterator351LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) {352// one of iterators is not valid (we are not in scope), so common353// parent is const_iterator() (i.e. sentinel).354if ((*this == const_iterator()) || (L == const_iterator())) {355return const_iterator();356}357358const_iterator F = *this;359if (F.inSameLocalScope(L)) {360// Iterators are in the same scope, get common subset of variables.361F.VarIter = std::min(F.VarIter, L.VarIter);362return F;363}364365llvm::SmallDenseMap<const LocalScope *, unsigned, 4> ScopesOfL;366while (true) {367ScopesOfL.try_emplace(L.Scope, L.VarIter);368if (L == const_iterator())369break;370L = L.Scope->Prev;371}372373while (true) {374if (auto LIt = ScopesOfL.find(F.Scope); LIt != ScopesOfL.end()) {375// Get common subset of variables in given scope376F.VarIter = std::min(F.VarIter, LIt->getSecond());377return F;378}379assert(F != const_iterator() &&380"L iterator is not reachable from F iterator.");381F = F.Scope->Prev;382}383}384385namespace {386387/// Structure for specifying position in CFG during its build process. It388/// consists of CFGBlock that specifies position in CFG and389/// LocalScope::const_iterator that specifies position in LocalScope graph.390struct BlockScopePosPair {391CFGBlock *block = nullptr;392LocalScope::const_iterator scopePosition;393394BlockScopePosPair() = default;395BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos)396: block(b), scopePosition(scopePos) {}397};398399/// TryResult - a class representing a variant over the values400/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool,401/// and is used by the CFGBuilder to decide if a branch condition402/// can be decided up front during CFG construction.403class TryResult {404int X = -1;405406public:407TryResult() = default;408TryResult(bool b) : X(b ? 1 : 0) {}409410bool isTrue() const { return X == 1; }411bool isFalse() const { return X == 0; }412bool isKnown() const { return X >= 0; }413414void negate() {415assert(isKnown());416X ^= 0x1;417}418};419420} // namespace421422static TryResult bothKnownTrue(TryResult R1, TryResult R2) {423if (!R1.isKnown() || !R2.isKnown())424return TryResult();425return TryResult(R1.isTrue() && R2.isTrue());426}427428namespace {429430class reverse_children {431llvm::SmallVector<Stmt *, 12> childrenBuf;432ArrayRef<Stmt *> children;433434public:435reverse_children(Stmt *S);436437using iterator = ArrayRef<Stmt *>::reverse_iterator;438439iterator begin() const { return children.rbegin(); }440iterator end() const { return children.rend(); }441};442443} // namespace444445reverse_children::reverse_children(Stmt *S) {446if (CallExpr *CE = dyn_cast<CallExpr>(S)) {447children = CE->getRawSubExprs();448return;449}450switch (S->getStmtClass()) {451// Note: Fill in this switch with more cases we want to optimize.452case Stmt::InitListExprClass: {453InitListExpr *IE = cast<InitListExpr>(S);454children = llvm::ArrayRef(reinterpret_cast<Stmt **>(IE->getInits()),455IE->getNumInits());456return;457}458default:459break;460}461462// Default case for all other statements.463llvm::append_range(childrenBuf, S->children());464465// This needs to be done *after* childrenBuf has been populated.466children = childrenBuf;467}468469namespace {470471/// CFGBuilder - This class implements CFG construction from an AST.472/// The builder is stateful: an instance of the builder should be used to only473/// construct a single CFG.474///475/// Example usage:476///477/// CFGBuilder builder;478/// std::unique_ptr<CFG> cfg = builder.buildCFG(decl, stmt1);479///480/// CFG construction is done via a recursive walk of an AST. We actually parse481/// the AST in reverse order so that the successor of a basic block is482/// constructed prior to its predecessor. This allows us to nicely capture483/// implicit fall-throughs without extra basic blocks.484class CFGBuilder {485using JumpTarget = BlockScopePosPair;486using JumpSource = BlockScopePosPair;487488ASTContext *Context;489std::unique_ptr<CFG> cfg;490491// Current block.492CFGBlock *Block = nullptr;493494// Block after the current block.495CFGBlock *Succ = nullptr;496497JumpTarget ContinueJumpTarget;498JumpTarget BreakJumpTarget;499JumpTarget SEHLeaveJumpTarget;500CFGBlock *SwitchTerminatedBlock = nullptr;501CFGBlock *DefaultCaseBlock = nullptr;502503// This can point to either a C++ try, an Objective-C @try, or an SEH __try.504// try and @try can be mixed and generally work the same.505// The frontend forbids mixing SEH __try with either try or @try.506// So having one for all three is enough.507CFGBlock *TryTerminatedBlock = nullptr;508509// Current position in local scope.510LocalScope::const_iterator ScopePos;511512// LabelMap records the mapping from Label expressions to their jump targets.513using LabelMapTy = llvm::DenseMap<LabelDecl *, JumpTarget>;514LabelMapTy LabelMap;515516// A list of blocks that end with a "goto" that must be backpatched to their517// resolved targets upon completion of CFG construction.518using BackpatchBlocksTy = std::vector<JumpSource>;519BackpatchBlocksTy BackpatchBlocks;520521// A list of labels whose address has been taken (for indirect gotos).522using LabelSetTy = llvm::SmallSetVector<LabelDecl *, 8>;523LabelSetTy AddressTakenLabels;524525// Information about the currently visited C++ object construction site.526// This is set in the construction trigger and read when the constructor527// or a function that returns an object by value is being visited.528llvm::DenseMap<Expr *, const ConstructionContextLayer *>529ConstructionContextMap;530531bool badCFG = false;532const CFG::BuildOptions &BuildOpts;533534// State to track for building switch statements.535bool switchExclusivelyCovered = false;536Expr::EvalResult *switchCond = nullptr;537538CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry = nullptr;539const Stmt *lastLookup = nullptr;540541// Caches boolean evaluations of expressions to avoid multiple re-evaluations542// during construction of branches for chained logical operators.543using CachedBoolEvalsTy = llvm::DenseMap<Expr *, TryResult>;544CachedBoolEvalsTy CachedBoolEvals;545546public:547explicit CFGBuilder(ASTContext *astContext,548const CFG::BuildOptions &buildOpts)549: Context(astContext), cfg(new CFG()), BuildOpts(buildOpts) {}550551// buildCFG - Used by external clients to construct the CFG.552std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *Statement);553554bool alwaysAdd(const Stmt *stmt);555556private:557// Visitors to walk an AST and construct the CFG.558CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);559CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);560CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc);561CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);562CFGBlock *VisitBreakStmt(BreakStmt *B);563CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);564CFGBlock *VisitCaseStmt(CaseStmt *C);565CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);566CFGBlock *VisitCompoundStmt(CompoundStmt *C, bool ExternallyDestructed);567CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C,568AddStmtChoice asc);569CFGBlock *VisitContinueStmt(ContinueStmt *C);570CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,571AddStmtChoice asc);572CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);573CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc);574CFGBlock *VisitCXXNewExpr(CXXNewExpr *DE, AddStmtChoice asc);575CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc);576CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S);577CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,578AddStmtChoice asc);579CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,580AddStmtChoice asc);581CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);582CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);583CFGBlock *VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc);584CFGBlock *VisitDeclStmt(DeclStmt *DS);585CFGBlock *VisitDeclSubExpr(DeclStmt *DS);586CFGBlock *VisitDefaultStmt(DefaultStmt *D);587CFGBlock *VisitDoStmt(DoStmt *D);588CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E,589AddStmtChoice asc, bool ExternallyDestructed);590CFGBlock *VisitForStmt(ForStmt *F);591CFGBlock *VisitGotoStmt(GotoStmt *G);592CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc);593CFGBlock *VisitIfStmt(IfStmt *I);594CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc);595CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc);596CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);597CFGBlock *VisitLabelStmt(LabelStmt *L);598CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc);599CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc);600CFGBlock *VisitLogicalOperator(BinaryOperator *B);601std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B,602Stmt *Term,603CFGBlock *TrueBlock,604CFGBlock *FalseBlock);605CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,606AddStmtChoice asc);607CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);608CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);609CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);610CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);611CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);612CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);613CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);614CFGBlock *VisitObjCMessageExpr(ObjCMessageExpr *E, AddStmtChoice asc);615CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E);616CFGBlock *VisitReturnStmt(Stmt *S);617CFGBlock *VisitCoroutineSuspendExpr(CoroutineSuspendExpr *S,618AddStmtChoice asc);619CFGBlock *VisitSEHExceptStmt(SEHExceptStmt *S);620CFGBlock *VisitSEHFinallyStmt(SEHFinallyStmt *S);621CFGBlock *VisitSEHLeaveStmt(SEHLeaveStmt *S);622CFGBlock *VisitSEHTryStmt(SEHTryStmt *S);623CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);624CFGBlock *VisitSwitchStmt(SwitchStmt *S);625CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,626AddStmtChoice asc);627CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc);628CFGBlock *VisitWhileStmt(WhileStmt *W);629CFGBlock *VisitArrayInitLoopExpr(ArrayInitLoopExpr *A, AddStmtChoice asc);630631CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd,632bool ExternallyDestructed = false);633CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);634CFGBlock *VisitChildren(Stmt *S);635CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc);636CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D,637AddStmtChoice asc);638639void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD,640const Stmt *S) {641if (ScopePos && (VD == ScopePos.getFirstVarInScope()))642appendScopeBegin(B, VD, S);643}644645/// When creating the CFG for temporary destructors, we want to mirror the646/// branch structure of the corresponding constructor calls.647/// Thus, while visiting a statement for temporary destructors, we keep a648/// context to keep track of the following information:649/// - whether a subexpression is executed unconditionally650/// - if a subexpression is executed conditionally, the first651/// CXXBindTemporaryExpr we encounter in that subexpression (which652/// corresponds to the last temporary destructor we have to call for this653/// subexpression) and the CFG block at that point (which will become the654/// successor block when inserting the decision point).655///656/// That way, we can build the branch structure for temporary destructors as657/// follows:658/// 1. If a subexpression is executed unconditionally, we add the temporary659/// destructor calls to the current block.660/// 2. If a subexpression is executed conditionally, when we encounter a661/// CXXBindTemporaryExpr:662/// a) If it is the first temporary destructor call in the subexpression,663/// we remember the CXXBindTemporaryExpr and the current block in the664/// TempDtorContext; we start a new block, and insert the temporary665/// destructor call.666/// b) Otherwise, add the temporary destructor call to the current block.667/// 3. When we finished visiting a conditionally executed subexpression,668/// and we found at least one temporary constructor during the visitation669/// (2.a has executed), we insert a decision block that uses the670/// CXXBindTemporaryExpr as terminator, and branches to the current block671/// if the CXXBindTemporaryExpr was marked executed, and otherwise672/// branches to the stored successor.673struct TempDtorContext {674TempDtorContext() = default;675TempDtorContext(TryResult KnownExecuted)676: IsConditional(true), KnownExecuted(KnownExecuted) {}677678/// Returns whether we need to start a new branch for a temporary destructor679/// call. This is the case when the temporary destructor is680/// conditionally executed, and it is the first one we encounter while681/// visiting a subexpression - other temporary destructors at the same level682/// will be added to the same block and are executed under the same683/// condition.684bool needsTempDtorBranch() const {685return IsConditional && !TerminatorExpr;686}687688/// Remember the successor S of a temporary destructor decision branch for689/// the corresponding CXXBindTemporaryExpr E.690void setDecisionPoint(CFGBlock *S, CXXBindTemporaryExpr *E) {691Succ = S;692TerminatorExpr = E;693}694695const bool IsConditional = false;696const TryResult KnownExecuted = true;697CFGBlock *Succ = nullptr;698CXXBindTemporaryExpr *TerminatorExpr = nullptr;699};700701// Visitors to walk an AST and generate destructors of temporaries in702// full expression.703CFGBlock *VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,704TempDtorContext &Context);705CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E, bool ExternallyDestructed,706TempDtorContext &Context);707CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E,708bool ExternallyDestructed,709TempDtorContext &Context);710CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(711CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context);712CFGBlock *VisitConditionalOperatorForTemporaryDtors(713AbstractConditionalOperator *E, bool ExternallyDestructed,714TempDtorContext &Context);715void InsertTempDtorDecisionBlock(const TempDtorContext &Context,716CFGBlock *FalseSucc = nullptr);717718// NYS == Not Yet Supported719CFGBlock *NYS() {720badCFG = true;721return Block;722}723724// Remember to apply the construction context based on the current \p Layer725// when constructing the CFG element for \p CE.726void consumeConstructionContext(const ConstructionContextLayer *Layer,727Expr *E);728729// Scan \p Child statement to find constructors in it, while keeping in mind730// that its parent statement is providing a partial construction context731// described by \p Layer. If a constructor is found, it would be assigned732// the context based on the layer. If an additional construction context layer733// is found, the function recurses into that.734void findConstructionContexts(const ConstructionContextLayer *Layer,735Stmt *Child);736737// Scan all arguments of a call expression for a construction context.738// These sorts of call expressions don't have a common superclass,739// hence strict duck-typing.740template <typename CallLikeExpr,741typename = std::enable_if_t<742std::is_base_of_v<CallExpr, CallLikeExpr> ||743std::is_base_of_v<CXXConstructExpr, CallLikeExpr> ||744std::is_base_of_v<ObjCMessageExpr, CallLikeExpr>>>745void findConstructionContextsForArguments(CallLikeExpr *E) {746for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {747Expr *Arg = E->getArg(i);748if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue())749findConstructionContexts(750ConstructionContextLayer::create(cfg->getBumpVectorContext(),751ConstructionContextItem(E, i)),752Arg);753}754}755756// Unset the construction context after consuming it. This is done immediately757// after adding the CFGConstructor or CFGCXXRecordTypedCall element, so758// there's no need to do this manually in every Visit... function.759void cleanupConstructionContext(Expr *E);760761void autoCreateBlock() { if (!Block) Block = createBlock(); }762CFGBlock *createBlock(bool add_successor = true);763CFGBlock *createNoReturnBlock();764765CFGBlock *addStmt(Stmt *S) {766return Visit(S, AddStmtChoice::AlwaysAdd);767}768769CFGBlock *addInitializer(CXXCtorInitializer *I);770void addLoopExit(const Stmt *LoopStmt);771void addAutomaticObjHandling(LocalScope::const_iterator B,772LocalScope::const_iterator E, Stmt *S);773void addAutomaticObjDestruction(LocalScope::const_iterator B,774LocalScope::const_iterator E, Stmt *S);775void addScopeExitHandling(LocalScope::const_iterator B,776LocalScope::const_iterator E, Stmt *S);777void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);778void addScopeChangesHandling(LocalScope::const_iterator SrcPos,779LocalScope::const_iterator DstPos,780Stmt *S);781CFGBlock *createScopeChangesHandlingBlock(LocalScope::const_iterator SrcPos,782CFGBlock *SrcBlk,783LocalScope::const_iterator DstPost,784CFGBlock *DstBlk);785786// Local scopes creation.787LocalScope* createOrReuseLocalScope(LocalScope* Scope);788789void addLocalScopeForStmt(Stmt *S);790LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,791LocalScope* Scope = nullptr);792LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);793794void addLocalScopeAndDtors(Stmt *S);795796const ConstructionContext *retrieveAndCleanupConstructionContext(Expr *E) {797if (!BuildOpts.AddRichCXXConstructors)798return nullptr;799800const ConstructionContextLayer *Layer = ConstructionContextMap.lookup(E);801if (!Layer)802return nullptr;803804cleanupConstructionContext(E);805return ConstructionContext::createFromLayers(cfg->getBumpVectorContext(),806Layer);807}808809// Interface to CFGBlock - adding CFGElements.810811void appendStmt(CFGBlock *B, const Stmt *S) {812if (alwaysAdd(S) && cachedEntry)813cachedEntry->second = B;814815// All block-level expressions should have already been IgnoreParens()ed.816assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S);817B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());818}819820void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {821if (const ConstructionContext *CC =822retrieveAndCleanupConstructionContext(CE)) {823B->appendConstructor(CE, CC, cfg->getBumpVectorContext());824return;825}826827// No valid construction context found. Fall back to statement.828B->appendStmt(CE, cfg->getBumpVectorContext());829}830831void appendCall(CFGBlock *B, CallExpr *CE) {832if (alwaysAdd(CE) && cachedEntry)833cachedEntry->second = B;834835if (const ConstructionContext *CC =836retrieveAndCleanupConstructionContext(CE)) {837B->appendCXXRecordTypedCall(CE, CC, cfg->getBumpVectorContext());838return;839}840841// No valid construction context found. Fall back to statement.842B->appendStmt(CE, cfg->getBumpVectorContext());843}844845void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) {846B->appendInitializer(I, cfg->getBumpVectorContext());847}848849void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {850B->appendNewAllocator(NE, cfg->getBumpVectorContext());851}852853void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {854B->appendBaseDtor(BS, cfg->getBumpVectorContext());855}856857void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {858B->appendMemberDtor(FD, cfg->getBumpVectorContext());859}860861void appendObjCMessage(CFGBlock *B, ObjCMessageExpr *ME) {862if (alwaysAdd(ME) && cachedEntry)863cachedEntry->second = B;864865if (const ConstructionContext *CC =866retrieveAndCleanupConstructionContext(ME)) {867B->appendCXXRecordTypedCall(ME, CC, cfg->getBumpVectorContext());868return;869}870871B->appendStmt(const_cast<ObjCMessageExpr *>(ME),872cfg->getBumpVectorContext());873}874875void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {876B->appendTemporaryDtor(E, cfg->getBumpVectorContext());877}878879void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {880B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());881}882883void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {884B->appendCleanupFunction(VD, cfg->getBumpVectorContext());885}886887void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {888B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());889}890891void appendLoopExit(CFGBlock *B, const Stmt *LoopStmt) {892B->appendLoopExit(LoopStmt, cfg->getBumpVectorContext());893}894895void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) {896B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext());897}898899void addSuccessor(CFGBlock *B, CFGBlock *S, bool IsReachable = true) {900B->addSuccessor(CFGBlock::AdjacentBlock(S, IsReachable),901cfg->getBumpVectorContext());902}903904/// Add a reachable successor to a block, with the alternate variant that is905/// unreachable.906void addSuccessor(CFGBlock *B, CFGBlock *ReachableBlock, CFGBlock *AltBlock) {907B->addSuccessor(CFGBlock::AdjacentBlock(ReachableBlock, AltBlock),908cfg->getBumpVectorContext());909}910911void appendScopeBegin(CFGBlock *B, const VarDecl *VD, const Stmt *S) {912if (BuildOpts.AddScopes)913B->appendScopeBegin(VD, S, cfg->getBumpVectorContext());914}915916void appendScopeEnd(CFGBlock *B, const VarDecl *VD, const Stmt *S) {917if (BuildOpts.AddScopes)918B->appendScopeEnd(VD, S, cfg->getBumpVectorContext());919}920921/// Find a relational comparison with an expression evaluating to a922/// boolean and a constant other than 0 and 1.923/// e.g. if ((x < y) == 10)924TryResult checkIncorrectRelationalOperator(const BinaryOperator *B) {925const Expr *LHSExpr = B->getLHS()->IgnoreParens();926const Expr *RHSExpr = B->getRHS()->IgnoreParens();927928const IntegerLiteral *IntLiteral = dyn_cast<IntegerLiteral>(LHSExpr);929const Expr *BoolExpr = RHSExpr;930bool IntFirst = true;931if (!IntLiteral) {932IntLiteral = dyn_cast<IntegerLiteral>(RHSExpr);933BoolExpr = LHSExpr;934IntFirst = false;935}936937if (!IntLiteral || !BoolExpr->isKnownToHaveBooleanValue())938return TryResult();939940llvm::APInt IntValue = IntLiteral->getValue();941if ((IntValue == 1) || (IntValue == 0))942return TryResult();943944bool IntLarger = IntLiteral->getType()->isUnsignedIntegerType() ||945!IntValue.isNegative();946947BinaryOperatorKind Bok = B->getOpcode();948if (Bok == BO_GT || Bok == BO_GE) {949// Always true for 10 > bool and bool > -1950// Always false for -1 > bool and bool > 10951return TryResult(IntFirst == IntLarger);952} else {953// Always true for -1 < bool and bool < 10954// Always false for 10 < bool and bool < -1955return TryResult(IntFirst != IntLarger);956}957}958959/// Find an incorrect equality comparison. Either with an expression960/// evaluating to a boolean and a constant other than 0 and 1.961/// e.g. if (!x == 10) or a bitwise and/or operation that always evaluates to962/// true/false e.q. (x & 8) == 4.963TryResult checkIncorrectEqualityOperator(const BinaryOperator *B) {964const Expr *LHSExpr = B->getLHS()->IgnoreParens();965const Expr *RHSExpr = B->getRHS()->IgnoreParens();966967std::optional<llvm::APInt> IntLiteral1 =968getIntegerLiteralSubexpressionValue(LHSExpr);969const Expr *BoolExpr = RHSExpr;970971if (!IntLiteral1) {972IntLiteral1 = getIntegerLiteralSubexpressionValue(RHSExpr);973BoolExpr = LHSExpr;974}975976if (!IntLiteral1)977return TryResult();978979const BinaryOperator *BitOp = dyn_cast<BinaryOperator>(BoolExpr);980if (BitOp && (BitOp->getOpcode() == BO_And ||981BitOp->getOpcode() == BO_Or)) {982const Expr *LHSExpr2 = BitOp->getLHS()->IgnoreParens();983const Expr *RHSExpr2 = BitOp->getRHS()->IgnoreParens();984985std::optional<llvm::APInt> IntLiteral2 =986getIntegerLiteralSubexpressionValue(LHSExpr2);987988if (!IntLiteral2)989IntLiteral2 = getIntegerLiteralSubexpressionValue(RHSExpr2);990991if (!IntLiteral2)992return TryResult();993994if ((BitOp->getOpcode() == BO_And &&995(*IntLiteral2 & *IntLiteral1) != *IntLiteral1) ||996(BitOp->getOpcode() == BO_Or &&997(*IntLiteral2 | *IntLiteral1) != *IntLiteral1)) {998if (BuildOpts.Observer)999BuildOpts.Observer->compareBitwiseEquality(B,1000B->getOpcode() != BO_EQ);1001return TryResult(B->getOpcode() != BO_EQ);1002}1003} else if (BoolExpr->isKnownToHaveBooleanValue()) {1004if ((*IntLiteral1 == 1) || (*IntLiteral1 == 0)) {1005return TryResult();1006}1007return TryResult(B->getOpcode() != BO_EQ);1008}10091010return TryResult();1011}10121013// Helper function to get an APInt from an expression. Supports expressions1014// which are an IntegerLiteral or a UnaryOperator and returns the value with1015// all operations performed on it.1016// FIXME: it would be good to unify this function with1017// IsIntegerLiteralConstantExpr at some point given the similarity between the1018// functions.1019std::optional<llvm::APInt>1020getIntegerLiteralSubexpressionValue(const Expr *E) {10211022// If unary.1023if (const auto *UnOp = dyn_cast<UnaryOperator>(E->IgnoreParens())) {1024// Get the sub expression of the unary expression and get the Integer1025// Literal.1026const Expr *SubExpr = UnOp->getSubExpr()->IgnoreParens();10271028if (const auto *IntLiteral = dyn_cast<IntegerLiteral>(SubExpr)) {10291030llvm::APInt Value = IntLiteral->getValue();10311032// Perform the operation manually.1033switch (UnOp->getOpcode()) {1034case UO_Plus:1035return Value;1036case UO_Minus:1037return -Value;1038case UO_Not:1039return ~Value;1040case UO_LNot:1041return llvm::APInt(Context->getTypeSize(Context->IntTy), !Value);1042default:1043assert(false && "Unexpected unary operator!");1044return std::nullopt;1045}1046}1047} else if (const auto *IntLiteral =1048dyn_cast<IntegerLiteral>(E->IgnoreParens()))1049return IntLiteral->getValue();10501051return std::nullopt;1052}10531054TryResult analyzeLogicOperatorCondition(BinaryOperatorKind Relation,1055const llvm::APSInt &Value1,1056const llvm::APSInt &Value2) {1057assert(Value1.isSigned() == Value2.isSigned());1058switch (Relation) {1059default:1060return TryResult();1061case BO_EQ:1062return TryResult(Value1 == Value2);1063case BO_NE:1064return TryResult(Value1 != Value2);1065case BO_LT:1066return TryResult(Value1 < Value2);1067case BO_LE:1068return TryResult(Value1 <= Value2);1069case BO_GT:1070return TryResult(Value1 > Value2);1071case BO_GE:1072return TryResult(Value1 >= Value2);1073}1074}10751076/// There are two checks handled by this function:1077/// 1. Find a law-of-excluded-middle or law-of-noncontradiction expression1078/// e.g. if (x || !x), if (x && !x)1079/// 2. Find a pair of comparison expressions with or without parentheses1080/// with a shared variable and constants and a logical operator between them1081/// that always evaluates to either true or false.1082/// e.g. if (x != 3 || x != 4)1083TryResult checkIncorrectLogicOperator(const BinaryOperator *B) {1084assert(B->isLogicalOp());1085const Expr *LHSExpr = B->getLHS()->IgnoreParens();1086const Expr *RHSExpr = B->getRHS()->IgnoreParens();10871088auto CheckLogicalOpWithNegatedVariable = [this, B](const Expr *E1,1089const Expr *E2) {1090if (const auto *Negate = dyn_cast<UnaryOperator>(E1)) {1091if (Negate->getOpcode() == UO_LNot &&1092Expr::isSameComparisonOperand(Negate->getSubExpr(), E2)) {1093bool AlwaysTrue = B->getOpcode() == BO_LOr;1094if (BuildOpts.Observer)1095BuildOpts.Observer->logicAlwaysTrue(B, AlwaysTrue);1096return TryResult(AlwaysTrue);1097}1098}1099return TryResult();1100};11011102TryResult Result = CheckLogicalOpWithNegatedVariable(LHSExpr, RHSExpr);1103if (Result.isKnown())1104return Result;1105Result = CheckLogicalOpWithNegatedVariable(RHSExpr, LHSExpr);1106if (Result.isKnown())1107return Result;11081109const auto *LHS = dyn_cast<BinaryOperator>(LHSExpr);1110const auto *RHS = dyn_cast<BinaryOperator>(RHSExpr);1111if (!LHS || !RHS)1112return {};11131114if (!LHS->isComparisonOp() || !RHS->isComparisonOp())1115return {};11161117const Expr *DeclExpr1;1118const Expr *NumExpr1;1119BinaryOperatorKind BO1;1120std::tie(DeclExpr1, BO1, NumExpr1) = tryNormalizeBinaryOperator(LHS);11211122if (!DeclExpr1 || !NumExpr1)1123return {};11241125const Expr *DeclExpr2;1126const Expr *NumExpr2;1127BinaryOperatorKind BO2;1128std::tie(DeclExpr2, BO2, NumExpr2) = tryNormalizeBinaryOperator(RHS);11291130if (!DeclExpr2 || !NumExpr2)1131return {};11321133// Check that it is the same variable on both sides.1134if (!Expr::isSameComparisonOperand(DeclExpr1, DeclExpr2))1135return {};11361137// Make sure the user's intent is clear (e.g. they're comparing against two1138// int literals, or two things from the same enum)1139if (!areExprTypesCompatible(NumExpr1, NumExpr2))1140return {};11411142Expr::EvalResult L1Result, L2Result;1143if (!NumExpr1->EvaluateAsInt(L1Result, *Context) ||1144!NumExpr2->EvaluateAsInt(L2Result, *Context))1145return {};11461147llvm::APSInt L1 = L1Result.Val.getInt();1148llvm::APSInt L2 = L2Result.Val.getInt();11491150// Can't compare signed with unsigned or with different bit width.1151if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())1152return {};11531154// Values that will be used to determine if result of logical1155// operator is always true/false1156const llvm::APSInt Values[] = {1157// Value less than both Value1 and Value21158llvm::APSInt::getMinValue(L1.getBitWidth(), L1.isUnsigned()),1159// L11160L1,1161// Value between Value1 and Value21162((L1 < L2) ? L1 : L2) + llvm::APSInt(llvm::APInt(L1.getBitWidth(), 1),1163L1.isUnsigned()),1164// L21165L2,1166// Value greater than both Value1 and Value21167llvm::APSInt::getMaxValue(L1.getBitWidth(), L1.isUnsigned()),1168};11691170// Check whether expression is always true/false by evaluating the following1171// * variable x is less than the smallest literal.1172// * variable x is equal to the smallest literal.1173// * Variable x is between smallest and largest literal.1174// * Variable x is equal to the largest literal.1175// * Variable x is greater than largest literal.1176bool AlwaysTrue = true, AlwaysFalse = true;1177// Track value of both subexpressions. If either side is always1178// true/false, another warning should have already been emitted.1179bool LHSAlwaysTrue = true, LHSAlwaysFalse = true;1180bool RHSAlwaysTrue = true, RHSAlwaysFalse = true;1181for (const llvm::APSInt &Value : Values) {1182TryResult Res1, Res2;1183Res1 = analyzeLogicOperatorCondition(BO1, Value, L1);1184Res2 = analyzeLogicOperatorCondition(BO2, Value, L2);11851186if (!Res1.isKnown() || !Res2.isKnown())1187return {};11881189if (B->getOpcode() == BO_LAnd) {1190AlwaysTrue &= (Res1.isTrue() && Res2.isTrue());1191AlwaysFalse &= !(Res1.isTrue() && Res2.isTrue());1192} else {1193AlwaysTrue &= (Res1.isTrue() || Res2.isTrue());1194AlwaysFalse &= !(Res1.isTrue() || Res2.isTrue());1195}11961197LHSAlwaysTrue &= Res1.isTrue();1198LHSAlwaysFalse &= Res1.isFalse();1199RHSAlwaysTrue &= Res2.isTrue();1200RHSAlwaysFalse &= Res2.isFalse();1201}12021203if (AlwaysTrue || AlwaysFalse) {1204if (!LHSAlwaysTrue && !LHSAlwaysFalse && !RHSAlwaysTrue &&1205!RHSAlwaysFalse && BuildOpts.Observer)1206BuildOpts.Observer->compareAlwaysTrue(B, AlwaysTrue);1207return TryResult(AlwaysTrue);1208}1209return {};1210}12111212/// A bitwise-or with a non-zero constant always evaluates to true.1213TryResult checkIncorrectBitwiseOrOperator(const BinaryOperator *B) {1214const Expr *LHSConstant =1215tryTransformToIntOrEnumConstant(B->getLHS()->IgnoreParenImpCasts());1216const Expr *RHSConstant =1217tryTransformToIntOrEnumConstant(B->getRHS()->IgnoreParenImpCasts());12181219if ((LHSConstant && RHSConstant) || (!LHSConstant && !RHSConstant))1220return {};12211222const Expr *Constant = LHSConstant ? LHSConstant : RHSConstant;12231224Expr::EvalResult Result;1225if (!Constant->EvaluateAsInt(Result, *Context))1226return {};12271228if (Result.Val.getInt() == 0)1229return {};12301231if (BuildOpts.Observer)1232BuildOpts.Observer->compareBitwiseOr(B);12331234return TryResult(true);1235}12361237/// Try and evaluate an expression to an integer constant.1238bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) {1239if (!BuildOpts.PruneTriviallyFalseEdges)1240return false;1241return !S->isTypeDependent() &&1242!S->isValueDependent() &&1243S->EvaluateAsRValue(outResult, *Context);1244}12451246/// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 11247/// if we can evaluate to a known value, otherwise return -1.1248TryResult tryEvaluateBool(Expr *S) {1249if (!BuildOpts.PruneTriviallyFalseEdges ||1250S->isTypeDependent() || S->isValueDependent())1251return {};12521253if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {1254if (Bop->isLogicalOp() || Bop->isEqualityOp()) {1255// Check the cache first.1256CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S);1257if (I != CachedBoolEvals.end())1258return I->second; // already in map;12591260// Retrieve result at first, or the map might be updated.1261TryResult Result = evaluateAsBooleanConditionNoCache(S);1262CachedBoolEvals[S] = Result; // update or insert1263return Result;1264}1265else {1266switch (Bop->getOpcode()) {1267default: break;1268// For 'x & 0' and 'x * 0', we can determine that1269// the value is always false.1270case BO_Mul:1271case BO_And: {1272// If either operand is zero, we know the value1273// must be false.1274Expr::EvalResult LHSResult;1275if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {1276llvm::APSInt IntVal = LHSResult.Val.getInt();1277if (!IntVal.getBoolValue()) {1278return TryResult(false);1279}1280}1281Expr::EvalResult RHSResult;1282if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {1283llvm::APSInt IntVal = RHSResult.Val.getInt();1284if (!IntVal.getBoolValue()) {1285return TryResult(false);1286}1287}1288}1289break;1290}1291}1292}12931294return evaluateAsBooleanConditionNoCache(S);1295}12961297/// Evaluate as boolean \param E without using the cache.1298TryResult evaluateAsBooleanConditionNoCache(Expr *E) {1299if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {1300if (Bop->isLogicalOp()) {1301TryResult LHS = tryEvaluateBool(Bop->getLHS());1302if (LHS.isKnown()) {1303// We were able to evaluate the LHS, see if we can get away with not1304// evaluating the RHS: 0 && X -> 0, 1 || X -> 11305if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr))1306return LHS.isTrue();13071308TryResult RHS = tryEvaluateBool(Bop->getRHS());1309if (RHS.isKnown()) {1310if (Bop->getOpcode() == BO_LOr)1311return LHS.isTrue() || RHS.isTrue();1312else1313return LHS.isTrue() && RHS.isTrue();1314}1315} else {1316TryResult RHS = tryEvaluateBool(Bop->getRHS());1317if (RHS.isKnown()) {1318// We can't evaluate the LHS; however, sometimes the result1319// is determined by the RHS: X && 0 -> 0, X || 1 -> 1.1320if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr))1321return RHS.isTrue();1322} else {1323TryResult BopRes = checkIncorrectLogicOperator(Bop);1324if (BopRes.isKnown())1325return BopRes.isTrue();1326}1327}13281329return {};1330} else if (Bop->isEqualityOp()) {1331TryResult BopRes = checkIncorrectEqualityOperator(Bop);1332if (BopRes.isKnown())1333return BopRes.isTrue();1334} else if (Bop->isRelationalOp()) {1335TryResult BopRes = checkIncorrectRelationalOperator(Bop);1336if (BopRes.isKnown())1337return BopRes.isTrue();1338} else if (Bop->getOpcode() == BO_Or) {1339TryResult BopRes = checkIncorrectBitwiseOrOperator(Bop);1340if (BopRes.isKnown())1341return BopRes.isTrue();1342}1343}13441345bool Result;1346if (E->EvaluateAsBooleanCondition(Result, *Context))1347return Result;13481349return {};1350}13511352bool hasTrivialDestructor(const VarDecl *VD) const;1353bool needsAutomaticDestruction(const VarDecl *VD) const;1354};13551356} // namespace13571358Expr *1359clang::extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE) {1360if (!AILE)1361return nullptr;13621363Expr *AILEInit = AILE->getSubExpr();1364while (const auto *E = dyn_cast<ArrayInitLoopExpr>(AILEInit))1365AILEInit = E->getSubExpr();13661367return AILEInit;1368}13691370inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,1371const Stmt *stmt) const {1372return builder.alwaysAdd(stmt) || kind == AlwaysAdd;1373}13741375bool CFGBuilder::alwaysAdd(const Stmt *stmt) {1376bool shouldAdd = BuildOpts.alwaysAdd(stmt);13771378if (!BuildOpts.forcedBlkExprs)1379return shouldAdd;13801381if (lastLookup == stmt) {1382if (cachedEntry) {1383assert(cachedEntry->first == stmt);1384return true;1385}1386return shouldAdd;1387}13881389lastLookup = stmt;13901391// Perform the lookup!1392CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;13931394if (!fb) {1395// No need to update 'cachedEntry', since it will always be null.1396assert(!cachedEntry);1397return shouldAdd;1398}13991400CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);1401if (itr == fb->end()) {1402cachedEntry = nullptr;1403return shouldAdd;1404}14051406cachedEntry = &*itr;1407return true;1408}14091410// FIXME: Add support for dependent-sized array types in C++?1411// Does it even make sense to build a CFG for an uninstantiated template?1412static const VariableArrayType *FindVA(const Type *t) {1413while (const ArrayType *vt = dyn_cast<ArrayType>(t)) {1414if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt))1415if (vat->getSizeExpr())1416return vat;14171418t = vt->getElementType().getTypePtr();1419}14201421return nullptr;1422}14231424void CFGBuilder::consumeConstructionContext(1425const ConstructionContextLayer *Layer, Expr *E) {1426assert((isa<CXXConstructExpr>(E) || isa<CallExpr>(E) ||1427isa<ObjCMessageExpr>(E)) && "Expression cannot construct an object!");1428if (const ConstructionContextLayer *PreviouslyStoredLayer =1429ConstructionContextMap.lookup(E)) {1430(void)PreviouslyStoredLayer;1431// We might have visited this child when we were finding construction1432// contexts within its parents.1433assert(PreviouslyStoredLayer->isStrictlyMoreSpecificThan(Layer) &&1434"Already within a different construction context!");1435} else {1436ConstructionContextMap[E] = Layer;1437}1438}14391440void CFGBuilder::findConstructionContexts(1441const ConstructionContextLayer *Layer, Stmt *Child) {1442if (!BuildOpts.AddRichCXXConstructors)1443return;14441445if (!Child)1446return;14471448auto withExtraLayer = [this, Layer](const ConstructionContextItem &Item) {1449return ConstructionContextLayer::create(cfg->getBumpVectorContext(), Item,1450Layer);1451};14521453switch(Child->getStmtClass()) {1454case Stmt::CXXConstructExprClass:1455case Stmt::CXXTemporaryObjectExprClass: {1456// Support pre-C++17 copy elision AST.1457auto *CE = cast<CXXConstructExpr>(Child);1458if (BuildOpts.MarkElidedCXXConstructors && CE->isElidable()) {1459findConstructionContexts(withExtraLayer(CE), CE->getArg(0));1460}14611462consumeConstructionContext(Layer, CE);1463break;1464}1465// FIXME: This, like the main visit, doesn't support CUDAKernelCallExpr.1466// FIXME: An isa<> would look much better but this whole switch is a1467// workaround for an internal compiler error in MSVC 2015 (see r326021).1468case Stmt::CallExprClass:1469case Stmt::CXXMemberCallExprClass:1470case Stmt::CXXOperatorCallExprClass:1471case Stmt::UserDefinedLiteralClass:1472case Stmt::ObjCMessageExprClass: {1473auto *E = cast<Expr>(Child);1474if (CFGCXXRecordTypedCall::isCXXRecordTypedCall(E))1475consumeConstructionContext(Layer, E);1476break;1477}1478case Stmt::ExprWithCleanupsClass: {1479auto *Cleanups = cast<ExprWithCleanups>(Child);1480findConstructionContexts(Layer, Cleanups->getSubExpr());1481break;1482}1483case Stmt::CXXFunctionalCastExprClass: {1484auto *Cast = cast<CXXFunctionalCastExpr>(Child);1485findConstructionContexts(Layer, Cast->getSubExpr());1486break;1487}1488case Stmt::ImplicitCastExprClass: {1489auto *Cast = cast<ImplicitCastExpr>(Child);1490// Should we support other implicit cast kinds?1491switch (Cast->getCastKind()) {1492case CK_NoOp:1493case CK_ConstructorConversion:1494findConstructionContexts(Layer, Cast->getSubExpr());1495break;1496default:1497break;1498}1499break;1500}1501case Stmt::CXXBindTemporaryExprClass: {1502auto *BTE = cast<CXXBindTemporaryExpr>(Child);1503findConstructionContexts(withExtraLayer(BTE), BTE->getSubExpr());1504break;1505}1506case Stmt::MaterializeTemporaryExprClass: {1507// Normally we don't want to search in MaterializeTemporaryExpr because1508// it indicates the beginning of a temporary object construction context,1509// so it shouldn't be found in the middle. However, if it is the beginning1510// of an elidable copy or move construction context, we need to include it.1511if (Layer->getItem().getKind() ==1512ConstructionContextItem::ElidableConstructorKind) {1513auto *MTE = cast<MaterializeTemporaryExpr>(Child);1514findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());1515}1516break;1517}1518case Stmt::ConditionalOperatorClass: {1519auto *CO = cast<ConditionalOperator>(Child);1520if (Layer->getItem().getKind() !=1521ConstructionContextItem::MaterializationKind) {1522// If the object returned by the conditional operator is not going to be a1523// temporary object that needs to be immediately materialized, then1524// it must be C++17 with its mandatory copy elision. Do not yet promise1525// to support this case.1526assert(!CO->getType()->getAsCXXRecordDecl() || CO->isGLValue() ||1527Context->getLangOpts().CPlusPlus17);1528break;1529}1530findConstructionContexts(Layer, CO->getLHS());1531findConstructionContexts(Layer, CO->getRHS());1532break;1533}1534case Stmt::InitListExprClass: {1535auto *ILE = cast<InitListExpr>(Child);1536if (ILE->isTransparent()) {1537findConstructionContexts(Layer, ILE->getInit(0));1538break;1539}1540// TODO: Handle other cases. For now, fail to find construction contexts.1541break;1542}1543case Stmt::ParenExprClass: {1544// If expression is placed into parenthesis we should propagate the parent1545// construction context to subexpressions.1546auto *PE = cast<ParenExpr>(Child);1547findConstructionContexts(Layer, PE->getSubExpr());1548break;1549}1550default:1551break;1552}1553}15541555void CFGBuilder::cleanupConstructionContext(Expr *E) {1556assert(BuildOpts.AddRichCXXConstructors &&1557"We should not be managing construction contexts!");1558assert(ConstructionContextMap.count(E) &&1559"Cannot exit construction context without the context!");1560ConstructionContextMap.erase(E);1561}15621563/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an1564/// arbitrary statement. Examples include a single expression or a function1565/// body (compound statement). The ownership of the returned CFG is1566/// transferred to the caller. If CFG construction fails, this method returns1567/// NULL.1568std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) {1569assert(cfg.get());1570if (!Statement)1571return nullptr;15721573// Create an empty block that will serve as the exit block for the CFG. Since1574// this is the first block added to the CFG, it will be implicitly registered1575// as the exit block.1576Succ = createBlock();1577assert(Succ == &cfg->getExit());1578Block = nullptr; // the EXIT block is empty. Create all other blocks lazily.15791580if (BuildOpts.AddImplicitDtors)1581if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D))1582addImplicitDtorsForDestructor(DD);15831584// Visit the statements and create the CFG.1585CFGBlock *B = addStmt(Statement);15861587if (badCFG)1588return nullptr;15891590// For C++ constructor add initializers to CFG. Constructors of virtual bases1591// are ignored unless the object is of the most derived class.1592// class VBase { VBase() = default; VBase(int) {} };1593// class A : virtual public VBase { A() : VBase(0) {} };1594// class B : public A {};1595// B b; // Constructor calls in order: VBase(), A(), B().1596// // VBase(0) is ignored because A isn't the most derived class.1597// This may result in the virtual base(s) being already initialized at this1598// point, in which case we should jump right onto non-virtual bases and1599// fields. To handle this, make a CFG branch. We only need to add one such1600// branch per constructor, since the Standard states that all virtual bases1601// shall be initialized before non-virtual bases and direct data members.1602if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {1603CFGBlock *VBaseSucc = nullptr;1604for (auto *I : llvm::reverse(CD->inits())) {1605if (BuildOpts.AddVirtualBaseBranches && !VBaseSucc &&1606I->isBaseInitializer() && I->isBaseVirtual()) {1607// We've reached the first virtual base init while iterating in reverse1608// order. Make a new block for virtual base initializers so that we1609// could skip them.1610VBaseSucc = Succ = B ? B : &cfg->getExit();1611Block = createBlock();1612}1613B = addInitializer(I);1614if (badCFG)1615return nullptr;1616}1617if (VBaseSucc) {1618// Make a branch block for potentially skipping virtual base initializers.1619Succ = VBaseSucc;1620B = createBlock();1621B->setTerminator(1622CFGTerminator(nullptr, CFGTerminator::VirtualBaseBranch));1623addSuccessor(B, Block, true);1624}1625}16261627if (B)1628Succ = B;16291630// Backpatch the gotos whose label -> block mappings we didn't know when we1631// encountered them.1632for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),1633E = BackpatchBlocks.end(); I != E; ++I ) {16341635CFGBlock *B = I->block;1636if (auto *G = dyn_cast<GotoStmt>(B->getTerminator())) {1637LabelMapTy::iterator LI = LabelMap.find(G->getLabel());1638// If there is no target for the goto, then we are looking at an1639// incomplete AST. Handle this by not registering a successor.1640if (LI == LabelMap.end())1641continue;1642JumpTarget JT = LI->second;16431644CFGBlock *SuccBlk = createScopeChangesHandlingBlock(1645I->scopePosition, B, JT.scopePosition, JT.block);1646addSuccessor(B, SuccBlk);1647} else if (auto *G = dyn_cast<GCCAsmStmt>(B->getTerminator())) {1648CFGBlock *Successor = (I+1)->block;1649for (auto *L : G->labels()) {1650LabelMapTy::iterator LI = LabelMap.find(L->getLabel());1651// If there is no target for the goto, then we are looking at an1652// incomplete AST. Handle this by not registering a successor.1653if (LI == LabelMap.end())1654continue;1655JumpTarget JT = LI->second;1656// Successor has been added, so skip it.1657if (JT.block == Successor)1658continue;1659addSuccessor(B, JT.block);1660}1661I++;1662}1663}16641665// Add successors to the Indirect Goto Dispatch block (if we have one).1666if (CFGBlock *B = cfg->getIndirectGotoBlock())1667for (LabelSetTy::iterator I = AddressTakenLabels.begin(),1668E = AddressTakenLabels.end(); I != E; ++I ) {1669// Lookup the target block.1670LabelMapTy::iterator LI = LabelMap.find(*I);16711672// If there is no target block that contains label, then we are looking1673// at an incomplete AST. Handle this by not registering a successor.1674if (LI == LabelMap.end()) continue;16751676addSuccessor(B, LI->second.block);1677}16781679// Create an empty entry block that has no predecessors.1680cfg->setEntry(createBlock());16811682if (BuildOpts.AddRichCXXConstructors)1683assert(ConstructionContextMap.empty() &&1684"Not all construction contexts were cleaned up!");16851686return std::move(cfg);1687}16881689/// createBlock - Used to lazily create blocks that are connected1690/// to the current (global) successor.1691CFGBlock *CFGBuilder::createBlock(bool add_successor) {1692CFGBlock *B = cfg->createBlock();1693if (add_successor && Succ)1694addSuccessor(B, Succ);1695return B;1696}16971698/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the1699/// CFG. It is *not* connected to the current (global) successor, and instead1700/// directly tied to the exit block in order to be reachable.1701CFGBlock *CFGBuilder::createNoReturnBlock() {1702CFGBlock *B = createBlock(false);1703B->setHasNoReturnElement();1704addSuccessor(B, &cfg->getExit(), Succ);1705return B;1706}17071708/// addInitializer - Add C++ base or member initializer element to CFG.1709CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {1710if (!BuildOpts.AddInitializers)1711return Block;17121713bool HasTemporaries = false;17141715// Destructors of temporaries in initialization expression should be called1716// after initialization finishes.1717Expr *Init = I->getInit();1718if (Init) {1719HasTemporaries = isa<ExprWithCleanups>(Init);17201721if (BuildOpts.AddTemporaryDtors && HasTemporaries) {1722// Generate destructors for temporaries in initialization expression.1723TempDtorContext Context;1724VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),1725/*ExternallyDestructed=*/false, Context);1726}1727}17281729autoCreateBlock();1730appendInitializer(Block, I);17311732if (Init) {1733// If the initializer is an ArrayInitLoopExpr, we want to extract the1734// initializer, that's used for each element.1735auto *AILEInit = extractElementInitializerFromNestedAILE(1736dyn_cast<ArrayInitLoopExpr>(Init));17371738findConstructionContexts(1739ConstructionContextLayer::create(cfg->getBumpVectorContext(), I),1740AILEInit ? AILEInit : Init);17411742if (HasTemporaries) {1743// For expression with temporaries go directly to subexpression to omit1744// generating destructors for the second time.1745return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());1746}1747if (BuildOpts.AddCXXDefaultInitExprInCtors) {1748if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(Init)) {1749// In general, appending the expression wrapped by a CXXDefaultInitExpr1750// may cause the same Expr to appear more than once in the CFG. Doing it1751// here is safe because there's only one initializer per field.1752autoCreateBlock();1753appendStmt(Block, Default);1754if (Stmt *Child = Default->getExpr())1755if (CFGBlock *R = Visit(Child))1756Block = R;1757return Block;1758}1759}1760return Visit(Init);1761}17621763return Block;1764}17651766/// Retrieve the type of the temporary object whose lifetime was1767/// extended by a local reference with the given initializer.1768static QualType getReferenceInitTemporaryType(const Expr *Init,1769bool *FoundMTE = nullptr) {1770while (true) {1771// Skip parentheses.1772Init = Init->IgnoreParens();17731774// Skip through cleanups.1775if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) {1776Init = EWC->getSubExpr();1777continue;1778}17791780// Skip through the temporary-materialization expression.1781if (const MaterializeTemporaryExpr *MTE1782= dyn_cast<MaterializeTemporaryExpr>(Init)) {1783Init = MTE->getSubExpr();1784if (FoundMTE)1785*FoundMTE = true;1786continue;1787}17881789// Skip sub-object accesses into rvalues.1790const Expr *SkippedInit = Init->skipRValueSubobjectAdjustments();1791if (SkippedInit != Init) {1792Init = SkippedInit;1793continue;1794}17951796break;1797}17981799return Init->getType();1800}18011802// TODO: Support adding LoopExit element to the CFG in case where the loop is1803// ended by ReturnStmt, GotoStmt or ThrowExpr.1804void CFGBuilder::addLoopExit(const Stmt *LoopStmt){1805if(!BuildOpts.AddLoopExit)1806return;1807autoCreateBlock();1808appendLoopExit(Block, LoopStmt);1809}18101811/// Adds the CFG elements for leaving the scope of automatic objects in1812/// range [B, E). This include following:1813/// * AutomaticObjectDtor for variables with non-trivial destructor1814/// * LifetimeEnds for all variables1815/// * ScopeEnd for each scope left1816void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,1817LocalScope::const_iterator E,1818Stmt *S) {1819if (!BuildOpts.AddScopes && !BuildOpts.AddImplicitDtors &&1820!BuildOpts.AddLifetime)1821return;18221823if (B == E)1824return;18251826// Not leaving the scope, only need to handle destruction and lifetime1827if (B.inSameLocalScope(E)) {1828addAutomaticObjDestruction(B, E, S);1829return;1830}18311832// Extract information about all local scopes that are left1833SmallVector<LocalScope::const_iterator, 10> LocalScopeEndMarkers;1834LocalScopeEndMarkers.push_back(B);1835for (LocalScope::const_iterator I = B; I != E; ++I) {1836if (!I.inSameLocalScope(LocalScopeEndMarkers.back()))1837LocalScopeEndMarkers.push_back(I);1838}1839LocalScopeEndMarkers.push_back(E);18401841// We need to leave the scope in reverse order, so we reverse the end1842// markers1843std::reverse(LocalScopeEndMarkers.begin(), LocalScopeEndMarkers.end());1844auto Pairwise =1845llvm::zip(LocalScopeEndMarkers, llvm::drop_begin(LocalScopeEndMarkers));1846for (auto [E, B] : Pairwise) {1847if (!B.inSameLocalScope(E))1848addScopeExitHandling(B, E, S);1849addAutomaticObjDestruction(B, E, S);1850}1851}18521853/// Add CFG elements corresponding to call destructor and end of lifetime1854/// of all automatic variables with non-trivial destructor in range [B, E).1855/// This include AutomaticObjectDtor and LifetimeEnds elements.1856void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,1857LocalScope::const_iterator E,1858Stmt *S) {1859if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime)1860return;18611862if (B == E)1863return;18641865SmallVector<VarDecl *, 10> DeclsNeedDestruction;1866DeclsNeedDestruction.reserve(B.distance(E));18671868for (VarDecl* D : llvm::make_range(B, E))1869if (needsAutomaticDestruction(D))1870DeclsNeedDestruction.push_back(D);18711872for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {1873if (BuildOpts.AddImplicitDtors) {1874// If this destructor is marked as a no-return destructor, we need to1875// create a new block for the destructor which does not have as a1876// successor anything built thus far: control won't flow out of this1877// block.1878QualType Ty = VD->getType();1879if (Ty->isReferenceType())1880Ty = getReferenceInitTemporaryType(VD->getInit());1881Ty = Context->getBaseElementType(Ty);18821883const CXXRecordDecl *CRD = Ty->getAsCXXRecordDecl();1884if (CRD && CRD->isAnyDestructorNoReturn())1885Block = createNoReturnBlock();1886}18871888autoCreateBlock();18891890// Add LifetimeEnd after automatic obj with non-trivial destructors,1891// as they end their lifetime when the destructor returns. For trivial1892// objects, we end lifetime with scope end.1893if (BuildOpts.AddLifetime)1894appendLifetimeEnds(Block, VD, S);1895if (BuildOpts.AddImplicitDtors && !hasTrivialDestructor(VD))1896appendAutomaticObjDtor(Block, VD, S);1897if (VD->hasAttr<CleanupAttr>())1898appendCleanupFunction(Block, VD);1899}1900}19011902/// Add CFG elements corresponding to leaving a scope.1903/// Assumes that range [B, E) corresponds to single scope.1904/// This add following elements:1905/// * LifetimeEnds for all variables with non-trivial destructor1906/// * ScopeEnd for each scope left1907void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,1908LocalScope::const_iterator E, Stmt *S) {1909assert(!B.inSameLocalScope(E));1910if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes)1911return;19121913if (BuildOpts.AddScopes) {1914autoCreateBlock();1915appendScopeEnd(Block, B.getFirstVarInScope(), S);1916}19171918if (!BuildOpts.AddLifetime)1919return;19201921// We need to perform the scope leaving in reverse order1922SmallVector<VarDecl *, 10> DeclsTrivial;1923DeclsTrivial.reserve(B.distance(E));19241925// Objects with trivial destructor ends their lifetime when their storage1926// is destroyed, for automatic variables, this happens when the end of the1927// scope is added.1928for (VarDecl* D : llvm::make_range(B, E))1929if (!needsAutomaticDestruction(D))1930DeclsTrivial.push_back(D);19311932if (DeclsTrivial.empty())1933return;19341935autoCreateBlock();1936for (VarDecl *VD : llvm::reverse(DeclsTrivial))1937appendLifetimeEnds(Block, VD, S);1938}19391940/// addScopeChangesHandling - appends information about destruction, lifetime1941/// and cfgScopeEnd for variables in the scope that was left by the jump, and1942/// appends cfgScopeBegin for all scopes that where entered.1943/// We insert the cfgScopeBegin at the end of the jump node, as depending on1944/// the sourceBlock, each goto, may enter different amount of scopes.1945void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,1946LocalScope::const_iterator DstPos,1947Stmt *S) {1948assert(Block && "Source block should be always crated");1949if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&1950!BuildOpts.AddScopes) {1951return;1952}19531954if (SrcPos == DstPos)1955return;19561957// Get common scope, the jump leaves all scopes [SrcPos, BasePos), and1958// enter all scopes between [DstPos, BasePos)1959LocalScope::const_iterator BasePos = SrcPos.shared_parent(DstPos);19601961// Append scope begins for scopes entered by goto1962if (BuildOpts.AddScopes && !DstPos.inSameLocalScope(BasePos)) {1963for (LocalScope::const_iterator I = DstPos; I != BasePos; ++I)1964if (I.pointsToFirstDeclaredVar())1965appendScopeBegin(Block, *I, S);1966}19671968// Append scopeEnds, destructor and lifetime with the terminator for1969// block left by goto.1970addAutomaticObjHandling(SrcPos, BasePos, S);1971}19721973/// createScopeChangesHandlingBlock - Creates a block with cfgElements1974/// corresponding to changing the scope from the source scope of the GotoStmt,1975/// to destination scope. Add destructor, lifetime and cfgScopeEnd1976/// CFGElements to newly created CFGBlock, that will have the CFG terminator1977/// transferred.1978CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(1979LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,1980LocalScope::const_iterator DstPos, CFGBlock *DstBlk) {1981if (SrcPos == DstPos)1982return DstBlk;19831984if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&1985(!BuildOpts.AddScopes || SrcPos.inSameLocalScope(DstPos)))1986return DstBlk;19871988// We will update CFBBuilder when creating new block, restore the1989// previous state at exit.1990SaveAndRestore save_Block(Block), save_Succ(Succ);19911992// Create a new block, and transfer terminator1993Block = createBlock(false);1994Block->setTerminator(SrcBlk->getTerminator());1995SrcBlk->setTerminator(CFGTerminator());1996addSuccessor(Block, DstBlk);19971998// Fill the created Block with the required elements.1999addScopeChangesHandling(SrcPos, DstPos, Block->getTerminatorStmt());20002001assert(Block && "There should be at least one scope changing Block");2002return Block;2003}20042005/// addImplicitDtorsForDestructor - Add implicit destructors generated for2006/// base and member objects in destructor.2007void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {2008assert(BuildOpts.AddImplicitDtors &&2009"Can be called only when dtors should be added");2010const CXXRecordDecl *RD = DD->getParent();20112012// At the end destroy virtual base objects.2013for (const auto &VI : RD->vbases()) {2014// TODO: Add a VirtualBaseBranch to see if the most derived class2015// (which is different from the current class) is responsible for2016// destroying them.2017const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl();2018if (CD && !CD->hasTrivialDestructor()) {2019autoCreateBlock();2020appendBaseDtor(Block, &VI);2021}2022}20232024// Before virtual bases destroy direct base objects.2025for (const auto &BI : RD->bases()) {2026if (!BI.isVirtual()) {2027const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl();2028if (CD && !CD->hasTrivialDestructor()) {2029autoCreateBlock();2030appendBaseDtor(Block, &BI);2031}2032}2033}20342035// First destroy member objects.2036for (auto *FI : RD->fields()) {2037// Check for constant size array. Set type to array element type.2038QualType QT = FI->getType();2039// It may be a multidimensional array.2040while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {2041if (AT->isZeroSize())2042break;2043QT = AT->getElementType();2044}20452046if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())2047if (!CD->hasTrivialDestructor()) {2048autoCreateBlock();2049appendMemberDtor(Block, FI);2050}2051}2052}20532054/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either2055/// way return valid LocalScope object.2056LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {2057if (Scope)2058return Scope;2059llvm::BumpPtrAllocator &alloc = cfg->getAllocator();2060return new (alloc) LocalScope(BumpVectorContext(alloc), ScopePos);2061}20622063/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement2064/// that should create implicit scope (e.g. if/else substatements).2065void CFGBuilder::addLocalScopeForStmt(Stmt *S) {2066if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&2067!BuildOpts.AddScopes)2068return;20692070LocalScope *Scope = nullptr;20712072// For compound statement we will be creating explicit scope.2073if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {2074for (auto *BI : CS->body()) {2075Stmt *SI = BI->stripLabelLikeStatements();2076if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))2077Scope = addLocalScopeForDeclStmt(DS, Scope);2078}2079return;2080}20812082// For any other statement scope will be implicit and as such will be2083// interesting only for DeclStmt.2084if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))2085addLocalScopeForDeclStmt(DS);2086}20872088/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will2089/// reuse Scope if not NULL.2090LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,2091LocalScope* Scope) {2092if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&2093!BuildOpts.AddScopes)2094return Scope;20952096for (auto *DI : DS->decls())2097if (VarDecl *VD = dyn_cast<VarDecl>(DI))2098Scope = addLocalScopeForVarDecl(VD, Scope);2099return Scope;2100}21012102bool CFGBuilder::needsAutomaticDestruction(const VarDecl *VD) const {2103return !hasTrivialDestructor(VD) || VD->hasAttr<CleanupAttr>();2104}21052106bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const {2107// Check for const references bound to temporary. Set type to pointee.2108QualType QT = VD->getType();2109if (QT->isReferenceType()) {2110// Attempt to determine whether this declaration lifetime-extends a2111// temporary.2112//2113// FIXME: This is incorrect. Non-reference declarations can lifetime-extend2114// temporaries, and a single declaration can extend multiple temporaries.2115// We should look at the storage duration on each nested2116// MaterializeTemporaryExpr instead.21172118const Expr *Init = VD->getInit();2119if (!Init) {2120// Probably an exception catch-by-reference variable.2121// FIXME: It doesn't really mean that the object has a trivial destructor.2122// Also are there other cases?2123return true;2124}21252126// Lifetime-extending a temporary?2127bool FoundMTE = false;2128QT = getReferenceInitTemporaryType(Init, &FoundMTE);2129if (!FoundMTE)2130return true;2131}21322133// Check for constant size array. Set type to array element type.2134while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {2135if (AT->isZeroSize())2136return true;2137QT = AT->getElementType();2138}21392140// Check if type is a C++ class with non-trivial destructor.2141if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())2142return !CD->hasDefinition() || CD->hasTrivialDestructor();2143return true;2144}21452146/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will2147/// create add scope for automatic objects and temporary objects bound to2148/// const reference. Will reuse Scope if not NULL.2149LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,2150LocalScope* Scope) {2151if (!BuildOpts.AddImplicitDtors && !BuildOpts.AddLifetime &&2152!BuildOpts.AddScopes)2153return Scope;21542155// Check if variable is local.2156if (!VD->hasLocalStorage())2157return Scope;21582159if (!BuildOpts.AddLifetime && !BuildOpts.AddScopes &&2160!needsAutomaticDestruction(VD)) {2161assert(BuildOpts.AddImplicitDtors);2162return Scope;2163}21642165// Add the variable to scope2166Scope = createOrReuseLocalScope(Scope);2167Scope->addVar(VD);2168ScopePos = Scope->begin();2169return Scope;2170}21712172/// addLocalScopeAndDtors - For given statement add local scope for it and2173/// add destructors that will cleanup the scope. Will reuse Scope if not NULL.2174void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {2175LocalScope::const_iterator scopeBeginPos = ScopePos;2176addLocalScopeForStmt(S);2177addAutomaticObjHandling(ScopePos, scopeBeginPos, S);2178}21792180/// Visit - Walk the subtree of a statement and add extra2181/// blocks for ternary operators, &&, and ||. We also process "," and2182/// DeclStmts (which may contain nested control-flow).2183CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,2184bool ExternallyDestructed) {2185if (!S) {2186badCFG = true;2187return nullptr;2188}21892190if (Expr *E = dyn_cast<Expr>(S))2191S = E->IgnoreParens();21922193if (Context->getLangOpts().OpenMP)2194if (auto *D = dyn_cast<OMPExecutableDirective>(S))2195return VisitOMPExecutableDirective(D, asc);21962197switch (S->getStmtClass()) {2198default:2199return VisitStmt(S, asc);22002201case Stmt::ImplicitValueInitExprClass:2202if (BuildOpts.OmitImplicitValueInitializers)2203return Block;2204return VisitStmt(S, asc);22052206case Stmt::InitListExprClass:2207return VisitInitListExpr(cast<InitListExpr>(S), asc);22082209case Stmt::AttributedStmtClass:2210return VisitAttributedStmt(cast<AttributedStmt>(S), asc);22112212case Stmt::AddrLabelExprClass:2213return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);22142215case Stmt::BinaryConditionalOperatorClass:2216return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc);22172218case Stmt::BinaryOperatorClass:2219return VisitBinaryOperator(cast<BinaryOperator>(S), asc);22202221case Stmt::BlockExprClass:2222return VisitBlockExpr(cast<BlockExpr>(S), asc);22232224case Stmt::BreakStmtClass:2225return VisitBreakStmt(cast<BreakStmt>(S));22262227case Stmt::CallExprClass:2228case Stmt::CXXOperatorCallExprClass:2229case Stmt::CXXMemberCallExprClass:2230case Stmt::UserDefinedLiteralClass:2231return VisitCallExpr(cast<CallExpr>(S), asc);22322233case Stmt::CaseStmtClass:2234return VisitCaseStmt(cast<CaseStmt>(S));22352236case Stmt::ChooseExprClass:2237return VisitChooseExpr(cast<ChooseExpr>(S), asc);22382239case Stmt::CompoundStmtClass:2240return VisitCompoundStmt(cast<CompoundStmt>(S), ExternallyDestructed);22412242case Stmt::ConditionalOperatorClass:2243return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);22442245case Stmt::ContinueStmtClass:2246return VisitContinueStmt(cast<ContinueStmt>(S));22472248case Stmt::CXXCatchStmtClass:2249return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));22502251case Stmt::ExprWithCleanupsClass:2252return VisitExprWithCleanups(cast<ExprWithCleanups>(S),2253asc, ExternallyDestructed);22542255case Stmt::CXXDefaultArgExprClass:2256case Stmt::CXXDefaultInitExprClass:2257// FIXME: The expression inside a CXXDefaultArgExpr is owned by the2258// called function's declaration, not by the caller. If we simply add2259// this expression to the CFG, we could end up with the same Expr2260// appearing multiple times (PR13385).2261//2262// It's likewise possible for multiple CXXDefaultInitExprs for the same2263// expression to be used in the same function (through aggregate2264// initialization).2265return VisitStmt(S, asc);22662267case Stmt::CXXBindTemporaryExprClass:2268return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);22692270case Stmt::CXXConstructExprClass:2271return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc);22722273case Stmt::CXXNewExprClass:2274return VisitCXXNewExpr(cast<CXXNewExpr>(S), asc);22752276case Stmt::CXXDeleteExprClass:2277return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc);22782279case Stmt::CXXFunctionalCastExprClass:2280return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc);22812282case Stmt::CXXTemporaryObjectExprClass:2283return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc);22842285case Stmt::CXXThrowExprClass:2286return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));22872288case Stmt::CXXTryStmtClass:2289return VisitCXXTryStmt(cast<CXXTryStmt>(S));22902291case Stmt::CXXTypeidExprClass:2292return VisitCXXTypeidExpr(cast<CXXTypeidExpr>(S), asc);22932294case Stmt::CXXForRangeStmtClass:2295return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S));22962297case Stmt::DeclStmtClass:2298return VisitDeclStmt(cast<DeclStmt>(S));22992300case Stmt::DefaultStmtClass:2301return VisitDefaultStmt(cast<DefaultStmt>(S));23022303case Stmt::DoStmtClass:2304return VisitDoStmt(cast<DoStmt>(S));23052306case Stmt::ForStmtClass:2307return VisitForStmt(cast<ForStmt>(S));23082309case Stmt::GotoStmtClass:2310return VisitGotoStmt(cast<GotoStmt>(S));23112312case Stmt::GCCAsmStmtClass:2313return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc);23142315case Stmt::IfStmtClass:2316return VisitIfStmt(cast<IfStmt>(S));23172318case Stmt::ImplicitCastExprClass:2319return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);23202321case Stmt::ConstantExprClass:2322return VisitConstantExpr(cast<ConstantExpr>(S), asc);23232324case Stmt::IndirectGotoStmtClass:2325return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));23262327case Stmt::LabelStmtClass:2328return VisitLabelStmt(cast<LabelStmt>(S));23292330case Stmt::LambdaExprClass:2331return VisitLambdaExpr(cast<LambdaExpr>(S), asc);23322333case Stmt::MaterializeTemporaryExprClass:2334return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S),2335asc);23362337case Stmt::MemberExprClass:2338return VisitMemberExpr(cast<MemberExpr>(S), asc);23392340case Stmt::NullStmtClass:2341return Block;23422343case Stmt::ObjCAtCatchStmtClass:2344return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));23452346case Stmt::ObjCAutoreleasePoolStmtClass:2347return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S));23482349case Stmt::ObjCAtSynchronizedStmtClass:2350return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));23512352case Stmt::ObjCAtThrowStmtClass:2353return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));23542355case Stmt::ObjCAtTryStmtClass:2356return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));23572358case Stmt::ObjCForCollectionStmtClass:2359return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));23602361case Stmt::ObjCMessageExprClass:2362return VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), asc);23632364case Stmt::OpaqueValueExprClass:2365return Block;23662367case Stmt::PseudoObjectExprClass:2368return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S));23692370case Stmt::ReturnStmtClass:2371case Stmt::CoreturnStmtClass:2372return VisitReturnStmt(S);23732374case Stmt::CoyieldExprClass:2375case Stmt::CoawaitExprClass:2376return VisitCoroutineSuspendExpr(cast<CoroutineSuspendExpr>(S), asc);23772378case Stmt::SEHExceptStmtClass:2379return VisitSEHExceptStmt(cast<SEHExceptStmt>(S));23802381case Stmt::SEHFinallyStmtClass:2382return VisitSEHFinallyStmt(cast<SEHFinallyStmt>(S));23832384case Stmt::SEHLeaveStmtClass:2385return VisitSEHLeaveStmt(cast<SEHLeaveStmt>(S));23862387case Stmt::SEHTryStmtClass:2388return VisitSEHTryStmt(cast<SEHTryStmt>(S));23892390case Stmt::UnaryExprOrTypeTraitExprClass:2391return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),2392asc);23932394case Stmt::StmtExprClass:2395return VisitStmtExpr(cast<StmtExpr>(S), asc);23962397case Stmt::SwitchStmtClass:2398return VisitSwitchStmt(cast<SwitchStmt>(S));23992400case Stmt::UnaryOperatorClass:2401return VisitUnaryOperator(cast<UnaryOperator>(S), asc);24022403case Stmt::WhileStmtClass:2404return VisitWhileStmt(cast<WhileStmt>(S));24052406case Stmt::ArrayInitLoopExprClass:2407return VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), asc);2408}2409}24102411CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {2412if (asc.alwaysAdd(*this, S)) {2413autoCreateBlock();2414appendStmt(Block, S);2415}24162417return VisitChildren(S);2418}24192420/// VisitChildren - Visit the children of a Stmt.2421CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {2422CFGBlock *B = Block;24232424// Visit the children in their reverse order so that they appear in2425// left-to-right (natural) order in the CFG.2426reverse_children RChildren(S);2427for (Stmt *Child : RChildren) {2428if (Child)2429if (CFGBlock *R = Visit(Child))2430B = R;2431}2432return B;2433}24342435CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {2436if (asc.alwaysAdd(*this, ILE)) {2437autoCreateBlock();2438appendStmt(Block, ILE);2439}2440CFGBlock *B = Block;24412442reverse_children RChildren(ILE);2443for (Stmt *Child : RChildren) {2444if (!Child)2445continue;2446if (CFGBlock *R = Visit(Child))2447B = R;2448if (BuildOpts.AddCXXDefaultInitExprInAggregates) {2449if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))2450if (Stmt *Child = DIE->getExpr())2451if (CFGBlock *R = Visit(Child))2452B = R;2453}2454}2455return B;2456}24572458CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,2459AddStmtChoice asc) {2460AddressTakenLabels.insert(A->getLabel());24612462if (asc.alwaysAdd(*this, A)) {2463autoCreateBlock();2464appendStmt(Block, A);2465}24662467return Block;2468}24692470static bool isFallthroughStatement(const AttributedStmt *A) {2471bool isFallthrough = hasSpecificAttr<FallThroughAttr>(A->getAttrs());2472assert((!isFallthrough || isa<NullStmt>(A->getSubStmt())) &&2473"expected fallthrough not to have children");2474return isFallthrough;2475}24762477CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,2478AddStmtChoice asc) {2479// AttributedStmts for [[likely]] can have arbitrary statements as children,2480// and the current visitation order here would add the AttributedStmts2481// for [[likely]] after the child nodes, which is undesirable: For example,2482// if the child contains an unconditional return, the [[likely]] would be2483// considered unreachable.2484// So only add the AttributedStmt for FallThrough, which has CFG effects and2485// also no children, and omit the others. None of the other current StmtAttrs2486// have semantic meaning for the CFG.2487if (isFallthroughStatement(A) && asc.alwaysAdd(*this, A)) {2488autoCreateBlock();2489appendStmt(Block, A);2490}24912492return VisitChildren(A);2493}24942495CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) {2496if (asc.alwaysAdd(*this, U)) {2497autoCreateBlock();2498appendStmt(Block, U);2499}25002501if (U->getOpcode() == UO_LNot)2502tryEvaluateBool(U->getSubExpr()->IgnoreParens());25032504return Visit(U->getSubExpr(), AddStmtChoice());2505}25062507CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) {2508CFGBlock *ConfluenceBlock = Block ? Block : createBlock();2509appendStmt(ConfluenceBlock, B);25102511if (badCFG)2512return nullptr;25132514return VisitLogicalOperator(B, nullptr, ConfluenceBlock,2515ConfluenceBlock).first;2516}25172518std::pair<CFGBlock*, CFGBlock*>2519CFGBuilder::VisitLogicalOperator(BinaryOperator *B,2520Stmt *Term,2521CFGBlock *TrueBlock,2522CFGBlock *FalseBlock) {2523// Introspect the RHS. If it is a nested logical operation, we recursively2524// build the CFG using this function. Otherwise, resort to default2525// CFG construction behavior.2526Expr *RHS = B->getRHS()->IgnoreParens();2527CFGBlock *RHSBlock, *ExitBlock;25282529do {2530if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS))2531if (B_RHS->isLogicalOp()) {2532std::tie(RHSBlock, ExitBlock) =2533VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock);2534break;2535}25362537// The RHS is not a nested logical operation. Don't push the terminator2538// down further, but instead visit RHS and construct the respective2539// pieces of the CFG, and link up the RHSBlock with the terminator2540// we have been provided.2541ExitBlock = RHSBlock = createBlock(false);25422543// Even though KnownVal is only used in the else branch of the next2544// conditional, tryEvaluateBool performs additional checking on the2545// Expr, so it should be called unconditionally.2546TryResult KnownVal = tryEvaluateBool(RHS);2547if (!KnownVal.isKnown())2548KnownVal = tryEvaluateBool(B);25492550if (!Term) {2551assert(TrueBlock == FalseBlock);2552addSuccessor(RHSBlock, TrueBlock);2553}2554else {2555RHSBlock->setTerminator(Term);2556addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse());2557addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue());2558}25592560Block = RHSBlock;2561RHSBlock = addStmt(RHS);2562}2563while (false);25642565if (badCFG)2566return std::make_pair(nullptr, nullptr);25672568// Generate the blocks for evaluating the LHS.2569Expr *LHS = B->getLHS()->IgnoreParens();25702571if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS))2572if (B_LHS->isLogicalOp()) {2573if (B->getOpcode() == BO_LOr)2574FalseBlock = RHSBlock;2575else2576TrueBlock = RHSBlock;25772578// For the LHS, treat 'B' as the terminator that we want to sink2579// into the nested branch. The RHS always gets the top-most2580// terminator.2581return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock);2582}25832584// Create the block evaluating the LHS.2585// This contains the '&&' or '||' as the terminator.2586CFGBlock *LHSBlock = createBlock(false);2587LHSBlock->setTerminator(B);25882589Block = LHSBlock;2590CFGBlock *EntryLHSBlock = addStmt(LHS);25912592if (badCFG)2593return std::make_pair(nullptr, nullptr);25942595// See if this is a known constant.2596TryResult KnownVal = tryEvaluateBool(LHS);25972598// Now link the LHSBlock with RHSBlock.2599if (B->getOpcode() == BO_LOr) {2600addSuccessor(LHSBlock, TrueBlock, !KnownVal.isFalse());2601addSuccessor(LHSBlock, RHSBlock, !KnownVal.isTrue());2602} else {2603assert(B->getOpcode() == BO_LAnd);2604addSuccessor(LHSBlock, RHSBlock, !KnownVal.isFalse());2605addSuccessor(LHSBlock, FalseBlock, !KnownVal.isTrue());2606}26072608return std::make_pair(EntryLHSBlock, ExitBlock);2609}26102611CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,2612AddStmtChoice asc) {2613// && or ||2614if (B->isLogicalOp())2615return VisitLogicalOperator(B);26162617if (B->getOpcode() == BO_Comma) { // ,2618autoCreateBlock();2619appendStmt(Block, B);2620addStmt(B->getRHS());2621return addStmt(B->getLHS());2622}26232624if (B->isAssignmentOp()) {2625if (asc.alwaysAdd(*this, B)) {2626autoCreateBlock();2627appendStmt(Block, B);2628}2629Visit(B->getLHS());2630return Visit(B->getRHS());2631}26322633if (asc.alwaysAdd(*this, B)) {2634autoCreateBlock();2635appendStmt(Block, B);2636}26372638if (B->isEqualityOp() || B->isRelationalOp())2639tryEvaluateBool(B);26402641CFGBlock *RBlock = Visit(B->getRHS());2642CFGBlock *LBlock = Visit(B->getLHS());2643// If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr2644// containing a DoStmt, and the LHS doesn't create a new block, then we should2645// return RBlock. Otherwise we'll incorrectly return NULL.2646return (LBlock ? LBlock : RBlock);2647}26482649CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) {2650if (asc.alwaysAdd(*this, E)) {2651autoCreateBlock();2652appendStmt(Block, E);2653}2654return Block;2655}26562657CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {2658// "break" is a control-flow statement. Thus we stop processing the current2659// block.2660if (badCFG)2661return nullptr;26622663// Now create a new block that ends with the break statement.2664Block = createBlock(false);2665Block->setTerminator(B);26662667// If there is no target for the break, then we are looking at an incomplete2668// AST. This means that the CFG cannot be constructed.2669if (BreakJumpTarget.block) {2670addAutomaticObjHandling(ScopePos, BreakJumpTarget.scopePosition, B);2671addSuccessor(Block, BreakJumpTarget.block);2672} else2673badCFG = true;26742675return Block;2676}26772678static bool CanThrow(Expr *E, ASTContext &Ctx) {2679QualType Ty = E->getType();2680if (Ty->isFunctionPointerType() || Ty->isBlockPointerType())2681Ty = Ty->getPointeeType();26822683const FunctionType *FT = Ty->getAs<FunctionType>();2684if (FT) {2685if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))2686if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&2687Proto->isNothrow())2688return false;2689}2690return true;2691}26922693CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {2694// Compute the callee type.2695QualType calleeType = C->getCallee()->getType();2696if (calleeType == Context->BoundMemberTy) {2697QualType boundType = Expr::findBoundMemberType(C->getCallee());26982699// We should only get a null bound type if processing a dependent2700// CFG. Recover by assuming nothing.2701if (!boundType.isNull()) calleeType = boundType;2702}27032704// If this is a call to a no-return function, this stops the block here.2705bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();27062707bool AddEHEdge = false;27082709// Languages without exceptions are assumed to not throw.2710if (Context->getLangOpts().Exceptions) {2711if (BuildOpts.AddEHEdges)2712AddEHEdge = true;2713}27142715// If this is a call to a builtin function, it might not actually evaluate2716// its arguments. Don't add them to the CFG if this is the case.2717bool OmitArguments = false;27182719if (FunctionDecl *FD = C->getDirectCallee()) {2720// TODO: Support construction contexts for variadic function arguments.2721// These are a bit problematic and not very useful because passing2722// C++ objects as C-style variadic arguments doesn't work in general2723// (see [expr.call]).2724if (!FD->isVariadic())2725findConstructionContextsForArguments(C);27262727if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))2728NoReturn = true;2729if (FD->hasAttr<NoThrowAttr>())2730AddEHEdge = false;2731if (FD->getBuiltinID() == Builtin::BI__builtin_object_size ||2732FD->getBuiltinID() == Builtin::BI__builtin_dynamic_object_size)2733OmitArguments = true;2734}27352736if (!CanThrow(C->getCallee(), *Context))2737AddEHEdge = false;27382739if (OmitArguments) {2740assert(!NoReturn && "noreturn calls with unevaluated args not implemented");2741assert(!AddEHEdge && "EH calls with unevaluated args not implemented");2742autoCreateBlock();2743appendStmt(Block, C);2744return Visit(C->getCallee());2745}27462747if (!NoReturn && !AddEHEdge) {2748autoCreateBlock();2749appendCall(Block, C);27502751return VisitChildren(C);2752}27532754if (Block) {2755Succ = Block;2756if (badCFG)2757return nullptr;2758}27592760if (NoReturn)2761Block = createNoReturnBlock();2762else2763Block = createBlock();27642765appendCall(Block, C);27662767if (AddEHEdge) {2768// Add exceptional edges.2769if (TryTerminatedBlock)2770addSuccessor(Block, TryTerminatedBlock);2771else2772addSuccessor(Block, &cfg->getExit());2773}27742775return VisitChildren(C);2776}27772778CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,2779AddStmtChoice asc) {2780CFGBlock *ConfluenceBlock = Block ? Block : createBlock();2781appendStmt(ConfluenceBlock, C);2782if (badCFG)2783return nullptr;27842785AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);2786Succ = ConfluenceBlock;2787Block = nullptr;2788CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd);2789if (badCFG)2790return nullptr;27912792Succ = ConfluenceBlock;2793Block = nullptr;2794CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd);2795if (badCFG)2796return nullptr;27972798Block = createBlock(false);2799// See if this is a known constant.2800const TryResult& KnownVal = tryEvaluateBool(C->getCond());2801addSuccessor(Block, KnownVal.isFalse() ? nullptr : LHSBlock);2802addSuccessor(Block, KnownVal.isTrue() ? nullptr : RHSBlock);2803Block->setTerminator(C);2804return addStmt(C->getCond());2805}28062807CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,2808bool ExternallyDestructed) {2809LocalScope::const_iterator scopeBeginPos = ScopePos;2810addLocalScopeForStmt(C);28112812if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {2813// If the body ends with a ReturnStmt, the dtors will be added in2814// VisitReturnStmt.2815addAutomaticObjHandling(ScopePos, scopeBeginPos, C);2816}28172818CFGBlock *LastBlock = Block;28192820for (Stmt *S : llvm::reverse(C->body())) {2821// If we hit a segment of code just containing ';' (NullStmts), we can2822// get a null block back. In such cases, just use the LastBlock2823CFGBlock *newBlock = Visit(S, AddStmtChoice::AlwaysAdd,2824ExternallyDestructed);28252826if (newBlock)2827LastBlock = newBlock;28282829if (badCFG)2830return nullptr;28312832ExternallyDestructed = false;2833}28342835return LastBlock;2836}28372838CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,2839AddStmtChoice asc) {2840const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C);2841const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : nullptr);28422843// Create the confluence block that will "merge" the results of the ternary2844// expression.2845CFGBlock *ConfluenceBlock = Block ? Block : createBlock();2846appendStmt(ConfluenceBlock, C);2847if (badCFG)2848return nullptr;28492850AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true);28512852// Create a block for the LHS expression if there is an LHS expression. A2853// GCC extension allows LHS to be NULL, causing the condition to be the2854// value that is returned instead.2855// e.g: x ?: y is shorthand for: x ? x : y;2856Succ = ConfluenceBlock;2857Block = nullptr;2858CFGBlock *LHSBlock = nullptr;2859const Expr *trueExpr = C->getTrueExpr();2860if (trueExpr != opaqueValue) {2861LHSBlock = Visit(C->getTrueExpr(), alwaysAdd);2862if (badCFG)2863return nullptr;2864Block = nullptr;2865}2866else2867LHSBlock = ConfluenceBlock;28682869// Create the block for the RHS expression.2870Succ = ConfluenceBlock;2871CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd);2872if (badCFG)2873return nullptr;28742875// If the condition is a logical '&&' or '||', build a more accurate CFG.2876if (BinaryOperator *Cond =2877dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens()))2878if (Cond->isLogicalOp())2879return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first;28802881// Create the block that will contain the condition.2882Block = createBlock(false);28832884// See if this is a known constant.2885const TryResult& KnownVal = tryEvaluateBool(C->getCond());2886addSuccessor(Block, LHSBlock, !KnownVal.isFalse());2887addSuccessor(Block, RHSBlock, !KnownVal.isTrue());2888Block->setTerminator(C);2889Expr *condExpr = C->getCond();28902891if (opaqueValue) {2892// Run the condition expression if it's not trivially expressed in2893// terms of the opaque value (or if there is no opaque value).2894if (condExpr != opaqueValue)2895addStmt(condExpr);28962897// Before that, run the common subexpression if there was one.2898// At least one of this or the above will be run.2899return addStmt(BCO->getCommon());2900}29012902return addStmt(condExpr);2903}29042905CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {2906// Check if the Decl is for an __label__. If so, elide it from the2907// CFG entirely.2908if (isa<LabelDecl>(*DS->decl_begin()))2909return Block;29102911// This case also handles static_asserts.2912if (DS->isSingleDecl())2913return VisitDeclSubExpr(DS);29142915CFGBlock *B = nullptr;29162917// Build an individual DeclStmt for each decl.2918for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(),2919E = DS->decl_rend();2920I != E; ++I) {29212922// Allocate the DeclStmt using the BumpPtrAllocator. It will get2923// automatically freed with the CFG.2924DeclGroupRef DG(*I);2925Decl *D = *I;2926DeclStmt *DSNew = new (Context) DeclStmt(DG, D->getLocation(), GetEndLoc(D));2927cfg->addSyntheticDeclStmt(DSNew, DS);29282929// Append the fake DeclStmt to block.2930B = VisitDeclSubExpr(DSNew);2931}29322933return B;2934}29352936/// VisitDeclSubExpr - Utility method to add block-level expressions for2937/// DeclStmts and initializers in them.2938CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) {2939assert(DS->isSingleDecl() && "Can handle single declarations only.");29402941if (const auto *TND = dyn_cast<TypedefNameDecl>(DS->getSingleDecl())) {2942// If we encounter a VLA, process its size expressions.2943const Type *T = TND->getUnderlyingType().getTypePtr();2944if (!T->isVariablyModifiedType())2945return Block;29462947autoCreateBlock();2948appendStmt(Block, DS);29492950CFGBlock *LastBlock = Block;2951for (const VariableArrayType *VA = FindVA(T); VA != nullptr;2952VA = FindVA(VA->getElementType().getTypePtr())) {2953if (CFGBlock *NewBlock = addStmt(VA->getSizeExpr()))2954LastBlock = NewBlock;2955}2956return LastBlock;2957}29582959VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());29602961if (!VD) {2962// Of everything that can be declared in a DeclStmt, only VarDecls and the2963// exceptions above impact runtime semantics.2964return Block;2965}29662967bool HasTemporaries = false;29682969// Guard static initializers under a branch.2970CFGBlock *blockAfterStaticInit = nullptr;29712972if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) {2973// For static variables, we need to create a branch to track2974// whether or not they are initialized.2975if (Block) {2976Succ = Block;2977Block = nullptr;2978if (badCFG)2979return nullptr;2980}2981blockAfterStaticInit = Succ;2982}29832984// Destructors of temporaries in initialization expression should be called2985// after initialization finishes.2986Expr *Init = VD->getInit();2987if (Init) {2988HasTemporaries = isa<ExprWithCleanups>(Init);29892990if (BuildOpts.AddTemporaryDtors && HasTemporaries) {2991// Generate destructors for temporaries in initialization expression.2992TempDtorContext Context;2993VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(),2994/*ExternallyDestructed=*/true, Context);2995}2996}29972998// If we bind to a tuple-like type, we iterate over the HoldingVars, and2999// create a DeclStmt for each of them.3000if (const auto *DD = dyn_cast<DecompositionDecl>(VD)) {3001for (auto *BD : llvm::reverse(DD->bindings())) {3002if (auto *VD = BD->getHoldingVar()) {3003DeclGroupRef DG(VD);3004DeclStmt *DSNew =3005new (Context) DeclStmt(DG, VD->getLocation(), GetEndLoc(VD));3006cfg->addSyntheticDeclStmt(DSNew, DS);3007Block = VisitDeclSubExpr(DSNew);3008}3009}3010}30113012autoCreateBlock();3013appendStmt(Block, DS);30143015// If the initializer is an ArrayInitLoopExpr, we want to extract the3016// initializer, that's used for each element.3017const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init);30183019findConstructionContexts(3020ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),3021AILE ? AILE->getSubExpr() : Init);30223023// Keep track of the last non-null block, as 'Block' can be nulled out3024// if the initializer expression is something like a 'while' in a3025// statement-expression.3026CFGBlock *LastBlock = Block;30273028if (Init) {3029if (HasTemporaries) {3030// For expression with temporaries go directly to subexpression to omit3031// generating destructors for the second time.3032ExprWithCleanups *EC = cast<ExprWithCleanups>(Init);3033if (CFGBlock *newBlock = Visit(EC->getSubExpr()))3034LastBlock = newBlock;3035}3036else {3037if (CFGBlock *newBlock = Visit(Init))3038LastBlock = newBlock;3039}3040}30413042// If the type of VD is a VLA, then we must process its size expressions.3043// FIXME: This does not find the VLA if it is embedded in other types,3044// like here: `int (*p_vla)[x];`3045for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr());3046VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr())) {3047if (CFGBlock *newBlock = addStmt(VA->getSizeExpr()))3048LastBlock = newBlock;3049}30503051maybeAddScopeBeginForVarDecl(Block, VD, DS);30523053// Remove variable from local scope.3054if (ScopePos && VD == *ScopePos)3055++ScopePos;30563057CFGBlock *B = LastBlock;3058if (blockAfterStaticInit) {3059Succ = B;3060Block = createBlock(false);3061Block->setTerminator(DS);3062addSuccessor(Block, blockAfterStaticInit);3063addSuccessor(Block, B);3064B = Block;3065}30663067return B;3068}30693070CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {3071// We may see an if statement in the middle of a basic block, or it may be the3072// first statement we are processing. In either case, we create a new basic3073// block. First, we create the blocks for the then...else statements, and3074// then we create the block containing the if statement. If we were in the3075// middle of a block, we stop processing that block. That block is then the3076// implicit successor for the "then" and "else" clauses.30773078// Save local scope position because in case of condition variable ScopePos3079// won't be restored when traversing AST.3080SaveAndRestore save_scope_pos(ScopePos);30813082// Create local scope for C++17 if init-stmt if one exists.3083if (Stmt *Init = I->getInit())3084addLocalScopeForStmt(Init);30853086// Create local scope for possible condition variable.3087// Store scope position. Add implicit destructor.3088if (VarDecl *VD = I->getConditionVariable())3089addLocalScopeForVarDecl(VD);30903091addAutomaticObjHandling(ScopePos, save_scope_pos.get(), I);30923093// The block we were processing is now finished. Make it the successor3094// block.3095if (Block) {3096Succ = Block;3097if (badCFG)3098return nullptr;3099}31003101// Process the false branch.3102CFGBlock *ElseBlock = Succ;31033104if (Stmt *Else = I->getElse()) {3105SaveAndRestore sv(Succ);31063107// NULL out Block so that the recursive call to Visit will3108// create a new basic block.3109Block = nullptr;31103111// If branch is not a compound statement create implicit scope3112// and add destructors.3113if (!isa<CompoundStmt>(Else))3114addLocalScopeAndDtors(Else);31153116ElseBlock = addStmt(Else);31173118if (!ElseBlock) // Can occur when the Else body has all NullStmts.3119ElseBlock = sv.get();3120else if (Block) {3121if (badCFG)3122return nullptr;3123}3124}31253126// Process the true branch.3127CFGBlock *ThenBlock;3128{3129Stmt *Then = I->getThen();3130assert(Then);3131SaveAndRestore sv(Succ);3132Block = nullptr;31333134// If branch is not a compound statement create implicit scope3135// and add destructors.3136if (!isa<CompoundStmt>(Then))3137addLocalScopeAndDtors(Then);31383139ThenBlock = addStmt(Then);31403141if (!ThenBlock) {3142// We can reach here if the "then" body has all NullStmts.3143// Create an empty block so we can distinguish between true and false3144// branches in path-sensitive analyses.3145ThenBlock = createBlock(false);3146addSuccessor(ThenBlock, sv.get());3147} else if (Block) {3148if (badCFG)3149return nullptr;3150}3151}31523153// Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by3154// having these handle the actual control-flow jump. Note that3155// if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)"3156// we resort to the old control-flow behavior. This special handling3157// removes infeasible paths from the control-flow graph by having the3158// control-flow transfer of '&&' or '||' go directly into the then/else3159// blocks directly.3160BinaryOperator *Cond =3161(I->isConsteval() || I->getConditionVariable())3162? nullptr3163: dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens());3164CFGBlock *LastBlock;3165if (Cond && Cond->isLogicalOp())3166LastBlock = VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first;3167else {3168// Now create a new block containing the if statement.3169Block = createBlock(false);31703171// Set the terminator of the new block to the If statement.3172Block->setTerminator(I);31733174// See if this is a known constant.3175TryResult KnownVal;3176if (!I->isConsteval())3177KnownVal = tryEvaluateBool(I->getCond());31783179// Add the successors. If we know that specific branches are3180// unreachable, inform addSuccessor() of that knowledge.3181addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse());3182addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue());31833184// Add the condition as the last statement in the new block. This may3185// create new blocks as the condition may contain control-flow. Any newly3186// created blocks will be pointed to be "Block".3187LastBlock = addStmt(I->getCond());31883189// If the IfStmt contains a condition variable, add it and its3190// initializer to the CFG.3191if (const DeclStmt* DS = I->getConditionVariableDeclStmt()) {3192autoCreateBlock();3193LastBlock = addStmt(const_cast<DeclStmt *>(DS));3194}3195}31963197// Finally, if the IfStmt contains a C++17 init-stmt, add it to the CFG.3198if (Stmt *Init = I->getInit()) {3199autoCreateBlock();3200LastBlock = addStmt(Init);3201}32023203return LastBlock;3204}32053206CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) {3207// If we were in the middle of a block we stop processing that block.3208//3209// NOTE: If a "return" or "co_return" appears in the middle of a block, this3210// means that the code afterwards is DEAD (unreachable). We still keep3211// a basic block for that code; a simple "mark-and-sweep" from the entry3212// block will be able to report such dead blocks.3213assert(isa<ReturnStmt>(S) || isa<CoreturnStmt>(S));32143215// Create the new block.3216Block = createBlock(false);32173218addAutomaticObjHandling(ScopePos, LocalScope::const_iterator(), S);32193220if (auto *R = dyn_cast<ReturnStmt>(S))3221findConstructionContexts(3222ConstructionContextLayer::create(cfg->getBumpVectorContext(), R),3223R->getRetValue());32243225// If the one of the destructors does not return, we already have the Exit3226// block as a successor.3227if (!Block->hasNoReturnElement())3228addSuccessor(Block, &cfg->getExit());32293230// Add the return statement to the block.3231appendStmt(Block, S);32323233// Visit children3234if (ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) {3235if (Expr *O = RS->getRetValue())3236return Visit(O, AddStmtChoice::AlwaysAdd, /*ExternallyDestructed=*/true);3237return Block;3238}32393240CoreturnStmt *CRS = cast<CoreturnStmt>(S);3241auto *B = Block;3242if (CFGBlock *R = Visit(CRS->getPromiseCall()))3243B = R;32443245if (Expr *RV = CRS->getOperand())3246if (RV->getType()->isVoidType() && !isa<InitListExpr>(RV))3247// A non-initlist void expression.3248if (CFGBlock *R = Visit(RV))3249B = R;32503251return B;3252}32533254CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,3255AddStmtChoice asc) {3256// We're modelling the pre-coro-xform CFG. Thus just evalate the various3257// active components of the co_await or co_yield. Note we do not model the3258// edge from the builtin_suspend to the exit node.3259if (asc.alwaysAdd(*this, E)) {3260autoCreateBlock();3261appendStmt(Block, E);3262}3263CFGBlock *B = Block;3264if (auto *R = Visit(E->getResumeExpr()))3265B = R;3266if (auto *R = Visit(E->getSuspendExpr()))3267B = R;3268if (auto *R = Visit(E->getReadyExpr()))3269B = R;3270if (auto *R = Visit(E->getCommonExpr()))3271B = R;3272return B;3273}32743275CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) {3276// SEHExceptStmt are treated like labels, so they are the first statement in a3277// block.32783279// Save local scope position because in case of exception variable ScopePos3280// won't be restored when traversing AST.3281SaveAndRestore save_scope_pos(ScopePos);32823283addStmt(ES->getBlock());3284CFGBlock *SEHExceptBlock = Block;3285if (!SEHExceptBlock)3286SEHExceptBlock = createBlock();32873288appendStmt(SEHExceptBlock, ES);32893290// Also add the SEHExceptBlock as a label, like with regular labels.3291SEHExceptBlock->setLabel(ES);32923293// Bail out if the CFG is bad.3294if (badCFG)3295return nullptr;32963297// We set Block to NULL to allow lazy creation of a new block (if necessary).3298Block = nullptr;32993300return SEHExceptBlock;3301}33023303CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) {3304return VisitCompoundStmt(FS->getBlock(), /*ExternallyDestructed=*/false);3305}33063307CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) {3308// "__leave" is a control-flow statement. Thus we stop processing the current3309// block.3310if (badCFG)3311return nullptr;33123313// Now create a new block that ends with the __leave statement.3314Block = createBlock(false);3315Block->setTerminator(LS);33163317// If there is no target for the __leave, then we are looking at an incomplete3318// AST. This means that the CFG cannot be constructed.3319if (SEHLeaveJumpTarget.block) {3320addAutomaticObjHandling(ScopePos, SEHLeaveJumpTarget.scopePosition, LS);3321addSuccessor(Block, SEHLeaveJumpTarget.block);3322} else3323badCFG = true;33243325return Block;3326}33273328CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) {3329// "__try"/"__except"/"__finally" is a control-flow statement. Thus we stop3330// processing the current block.3331CFGBlock *SEHTrySuccessor = nullptr;33323333if (Block) {3334if (badCFG)3335return nullptr;3336SEHTrySuccessor = Block;3337} else SEHTrySuccessor = Succ;33383339// FIXME: Implement __finally support.3340if (Terminator->getFinallyHandler())3341return NYS();33423343CFGBlock *PrevSEHTryTerminatedBlock = TryTerminatedBlock;33443345// Create a new block that will contain the __try statement.3346CFGBlock *NewTryTerminatedBlock = createBlock(false);33473348// Add the terminator in the __try block.3349NewTryTerminatedBlock->setTerminator(Terminator);33503351if (SEHExceptStmt *Except = Terminator->getExceptHandler()) {3352// The code after the try is the implicit successor if there's an __except.3353Succ = SEHTrySuccessor;3354Block = nullptr;3355CFGBlock *ExceptBlock = VisitSEHExceptStmt(Except);3356if (!ExceptBlock)3357return nullptr;3358// Add this block to the list of successors for the block with the try3359// statement.3360addSuccessor(NewTryTerminatedBlock, ExceptBlock);3361}3362if (PrevSEHTryTerminatedBlock)3363addSuccessor(NewTryTerminatedBlock, PrevSEHTryTerminatedBlock);3364else3365addSuccessor(NewTryTerminatedBlock, &cfg->getExit());33663367// The code after the try is the implicit successor.3368Succ = SEHTrySuccessor;33693370// Save the current "__try" context.3371SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);3372cfg->addTryDispatchBlock(TryTerminatedBlock);33733374// Save the current value for the __leave target.3375// All __leaves should go to the code following the __try3376// (FIXME: or if the __try has a __finally, to the __finally.)3377SaveAndRestore save_break(SEHLeaveJumpTarget);3378SEHLeaveJumpTarget = JumpTarget(SEHTrySuccessor, ScopePos);33793380assert(Terminator->getTryBlock() && "__try must contain a non-NULL body");3381Block = nullptr;3382return addStmt(Terminator->getTryBlock());3383}33843385CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) {3386// Get the block of the labeled statement. Add it to our map.3387addStmt(L->getSubStmt());3388CFGBlock *LabelBlock = Block;33893390if (!LabelBlock) // This can happen when the body is empty, i.e.3391LabelBlock = createBlock(); // scopes that only contains NullStmts.33923393assert(!LabelMap.contains(L->getDecl()) && "label already in map");3394LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);33953396// Labels partition blocks, so this is the end of the basic block we were3397// processing (L is the block's label). Because this is label (and we have3398// already processed the substatement) there is no extra control-flow to worry3399// about.3400LabelBlock->setLabel(L);3401if (badCFG)3402return nullptr;34033404// We set Block to NULL to allow lazy creation of a new block (if necessary).3405Block = nullptr;34063407// This block is now the implicit successor of other blocks.3408Succ = LabelBlock;34093410return LabelBlock;3411}34123413CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {3414CFGBlock *LastBlock = VisitNoRecurse(E, asc);3415for (const BlockDecl::Capture &CI : E->getBlockDecl()->captures()) {3416if (Expr *CopyExpr = CI.getCopyExpr()) {3417CFGBlock *Tmp = Visit(CopyExpr);3418if (Tmp)3419LastBlock = Tmp;3420}3421}3422return LastBlock;3423}34243425CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) {3426CFGBlock *LastBlock = VisitNoRecurse(E, asc);34273428unsigned Idx = 0;3429for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(),3430et = E->capture_init_end();3431it != et; ++it, ++Idx) {3432if (Expr *Init = *it) {3433// If the initializer is an ArrayInitLoopExpr, we want to extract the3434// initializer, that's used for each element.3435auto *AILEInit = extractElementInitializerFromNestedAILE(3436dyn_cast<ArrayInitLoopExpr>(Init));34373438findConstructionContexts(ConstructionContextLayer::create(3439cfg->getBumpVectorContext(), {E, Idx}),3440AILEInit ? AILEInit : Init);34413442CFGBlock *Tmp = Visit(Init);3443if (Tmp)3444LastBlock = Tmp;3445}3446}3447return LastBlock;3448}34493450CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) {3451// Goto is a control-flow statement. Thus we stop processing the current3452// block and create a new one.34533454Block = createBlock(false);3455Block->setTerminator(G);34563457// If we already know the mapping to the label block add the successor now.3458LabelMapTy::iterator I = LabelMap.find(G->getLabel());34593460if (I == LabelMap.end())3461// We will need to backpatch this block later.3462BackpatchBlocks.push_back(JumpSource(Block, ScopePos));3463else {3464JumpTarget JT = I->second;3465addSuccessor(Block, JT.block);3466addScopeChangesHandling(ScopePos, JT.scopePosition, G);3467}34683469return Block;3470}34713472CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {3473// Goto is a control-flow statement. Thus we stop processing the current3474// block and create a new one.34753476if (!G->isAsmGoto())3477return VisitStmt(G, asc);34783479if (Block) {3480Succ = Block;3481if (badCFG)3482return nullptr;3483}3484Block = createBlock();3485Block->setTerminator(G);3486// We will backpatch this block later for all the labels.3487BackpatchBlocks.push_back(JumpSource(Block, ScopePos));3488// Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is3489// used to avoid adding "Succ" again.3490BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));3491return VisitChildren(G);3492}34933494CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {3495CFGBlock *LoopSuccessor = nullptr;34963497// Save local scope position because in case of condition variable ScopePos3498// won't be restored when traversing AST.3499SaveAndRestore save_scope_pos(ScopePos);35003501// Create local scope for init statement and possible condition variable.3502// Add destructor for init statement and condition variable.3503// Store scope position for continue statement.3504if (Stmt *Init = F->getInit())3505addLocalScopeForStmt(Init);3506LocalScope::const_iterator LoopBeginScopePos = ScopePos;35073508if (VarDecl *VD = F->getConditionVariable())3509addLocalScopeForVarDecl(VD);3510LocalScope::const_iterator ContinueScopePos = ScopePos;35113512addAutomaticObjHandling(ScopePos, save_scope_pos.get(), F);35133514addLoopExit(F);35153516// "for" is a control-flow statement. Thus we stop processing the current3517// block.3518if (Block) {3519if (badCFG)3520return nullptr;3521LoopSuccessor = Block;3522} else3523LoopSuccessor = Succ;35243525// Save the current value for the break targets.3526// All breaks should go to the code following the loop.3527SaveAndRestore save_break(BreakJumpTarget);3528BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);35293530CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;35313532// Now create the loop body.3533{3534assert(F->getBody());35353536// Save the current values for Block, Succ, continue and break targets.3537SaveAndRestore save_Block(Block), save_Succ(Succ);3538SaveAndRestore save_continue(ContinueJumpTarget);35393540// Create an empty block to represent the transition block for looping back3541// to the head of the loop. If we have increment code, it will3542// go in this block as well.3543Block = Succ = TransitionBlock = createBlock(false);3544TransitionBlock->setLoopTarget(F);354535463547// Loop iteration (after increment) should end with destructor of Condition3548// variable (if any).3549addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);35503551if (Stmt *I = F->getInc()) {3552// Generate increment code in its own basic block. This is the target of3553// continue statements.3554Succ = addStmt(I);3555}35563557// Finish up the increment (or empty) block if it hasn't been already.3558if (Block) {3559assert(Block == Succ);3560if (badCFG)3561return nullptr;3562Block = nullptr;3563}35643565// The starting block for the loop increment is the block that should3566// represent the 'loop target' for looping back to the start of the loop.3567ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);3568ContinueJumpTarget.block->setLoopTarget(F);356935703571// If body is not a compound statement create implicit scope3572// and add destructors.3573if (!isa<CompoundStmt>(F->getBody()))3574addLocalScopeAndDtors(F->getBody());35753576// Now populate the body block, and in the process create new blocks as we3577// walk the body of the loop.3578BodyBlock = addStmt(F->getBody());35793580if (!BodyBlock) {3581// In the case of "for (...;...;...);" we can have a null BodyBlock.3582// Use the continue jump target as the proxy for the body.3583BodyBlock = ContinueJumpTarget.block;3584}3585else if (badCFG)3586return nullptr;3587}35883589// Because of short-circuit evaluation, the condition of the loop can span3590// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that3591// evaluate the condition.3592CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;35933594do {3595Expr *C = F->getCond();3596SaveAndRestore save_scope_pos(ScopePos);35973598// Specially handle logical operators, which have a slightly3599// more optimal CFG representation.3600if (BinaryOperator *Cond =3601dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : nullptr))3602if (Cond->isLogicalOp()) {3603std::tie(EntryConditionBlock, ExitConditionBlock) =3604VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor);3605break;3606}36073608// The default case when not handling logical operators.3609EntryConditionBlock = ExitConditionBlock = createBlock(false);3610ExitConditionBlock->setTerminator(F);36113612// See if this is a known constant.3613TryResult KnownVal(true);36143615if (C) {3616// Now add the actual condition to the condition block.3617// Because the condition itself may contain control-flow, new blocks may3618// be created. Thus we update "Succ" after adding the condition.3619Block = ExitConditionBlock;3620EntryConditionBlock = addStmt(C);36213622// If this block contains a condition variable, add both the condition3623// variable and initializer to the CFG.3624if (VarDecl *VD = F->getConditionVariable()) {3625if (Expr *Init = VD->getInit()) {3626autoCreateBlock();3627const DeclStmt *DS = F->getConditionVariableDeclStmt();3628assert(DS->isSingleDecl());3629findConstructionContexts(3630ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS),3631Init);3632appendStmt(Block, DS);3633EntryConditionBlock = addStmt(Init);3634assert(Block == EntryConditionBlock);3635maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);3636}3637}36383639if (Block && badCFG)3640return nullptr;36413642KnownVal = tryEvaluateBool(C);3643}36443645// Add the loop body entry as a successor to the condition.3646addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);3647// Link up the condition block with the code that follows the loop. (the3648// false branch).3649addSuccessor(ExitConditionBlock,3650KnownVal.isTrue() ? nullptr : LoopSuccessor);3651} while (false);36523653// Link up the loop-back block to the entry condition block.3654addSuccessor(TransitionBlock, EntryConditionBlock);36553656// The condition block is the implicit successor for any code above the loop.3657Succ = EntryConditionBlock;36583659// If the loop contains initialization, create a new block for those3660// statements. This block can also contain statements that precede the loop.3661if (Stmt *I = F->getInit()) {3662SaveAndRestore save_scope_pos(ScopePos);3663ScopePos = LoopBeginScopePos;3664Block = createBlock();3665return addStmt(I);3666}36673668// There is no loop initialization. We are thus basically a while loop.3669// NULL out Block to force lazy block construction.3670Block = nullptr;3671Succ = EntryConditionBlock;3672return EntryConditionBlock;3673}36743675CFGBlock *3676CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,3677AddStmtChoice asc) {3678findConstructionContexts(3679ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),3680MTE->getSubExpr());36813682return VisitStmt(MTE, asc);3683}36843685CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {3686if (asc.alwaysAdd(*this, M)) {3687autoCreateBlock();3688appendStmt(Block, M);3689}3690return Visit(M->getBase());3691}36923693CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {3694// Objective-C fast enumeration 'for' statements:3695// http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC3696//3697// for ( Type newVariable in collection_expression ) { statements }3698//3699// becomes:3700//3701// prologue:3702// 1. collection_expression3703// T. jump to loop_entry3704// loop_entry:3705// 1. side-effects of element expression3706// 1. ObjCForCollectionStmt [performs binding to newVariable]3707// T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]3708// TB:3709// statements3710// T. jump to loop_entry3711// FB:3712// what comes after3713//3714// and3715//3716// Type existingItem;3717// for ( existingItem in expression ) { statements }3718//3719// becomes:3720//3721// the same with newVariable replaced with existingItem; the binding works3722// the same except that for one ObjCForCollectionStmt::getElement() returns3723// a DeclStmt and the other returns a DeclRefExpr.37243725CFGBlock *LoopSuccessor = nullptr;37263727if (Block) {3728if (badCFG)3729return nullptr;3730LoopSuccessor = Block;3731Block = nullptr;3732} else3733LoopSuccessor = Succ;37343735// Build the condition blocks.3736CFGBlock *ExitConditionBlock = createBlock(false);37373738// Set the terminator for the "exit" condition block.3739ExitConditionBlock->setTerminator(S);37403741// The last statement in the block should be the ObjCForCollectionStmt, which3742// performs the actual binding to 'element' and determines if there are any3743// more items in the collection.3744appendStmt(ExitConditionBlock, S);3745Block = ExitConditionBlock;37463747// Walk the 'element' expression to see if there are any side-effects. We3748// generate new blocks as necessary. We DON'T add the statement by default to3749// the CFG unless it contains control-flow.3750CFGBlock *EntryConditionBlock = Visit(S->getElement(),3751AddStmtChoice::NotAlwaysAdd);3752if (Block) {3753if (badCFG)3754return nullptr;3755Block = nullptr;3756}37573758// The condition block is the implicit successor for the loop body as well as3759// any code above the loop.3760Succ = EntryConditionBlock;37613762// Now create the true branch.3763{3764// Save the current values for Succ, continue and break targets.3765SaveAndRestore save_Block(Block), save_Succ(Succ);3766SaveAndRestore save_continue(ContinueJumpTarget),3767save_break(BreakJumpTarget);37683769// Add an intermediate block between the BodyBlock and the3770// EntryConditionBlock to represent the "loop back" transition, for looping3771// back to the head of the loop.3772CFGBlock *LoopBackBlock = nullptr;3773Succ = LoopBackBlock = createBlock();3774LoopBackBlock->setLoopTarget(S);37753776BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);3777ContinueJumpTarget = JumpTarget(Succ, ScopePos);37783779CFGBlock *BodyBlock = addStmt(S->getBody());37803781if (!BodyBlock)3782BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;"3783else if (Block) {3784if (badCFG)3785return nullptr;3786}37873788// This new body block is a successor to our "exit" condition block.3789addSuccessor(ExitConditionBlock, BodyBlock);3790}37913792// Link up the condition block with the code that follows the loop.3793// (the false branch).3794addSuccessor(ExitConditionBlock, LoopSuccessor);37953796// Now create a prologue block to contain the collection expression.3797Block = createBlock();3798return addStmt(S->getCollection());3799}38003801CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {3802// Inline the body.3803return addStmt(S->getSubStmt());3804// TODO: consider adding cleanups for the end of @autoreleasepool scope.3805}38063807CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {3808// FIXME: Add locking 'primitives' to CFG for @synchronized.38093810// Inline the body.3811CFGBlock *SyncBlock = addStmt(S->getSynchBody());38123813// The sync body starts its own basic block. This makes it a little easier3814// for diagnostic clients.3815if (SyncBlock) {3816if (badCFG)3817return nullptr;38183819Block = nullptr;3820Succ = SyncBlock;3821}38223823// Add the @synchronized to the CFG.3824autoCreateBlock();3825appendStmt(Block, S);38263827// Inline the sync expression.3828return addStmt(S->getSynchExpr());3829}38303831CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) {3832autoCreateBlock();38333834// Add the PseudoObject as the last thing.3835appendStmt(Block, E);38363837CFGBlock *lastBlock = Block;38383839// Before that, evaluate all of the semantics in order. In3840// CFG-land, that means appending them in reverse order.3841for (unsigned i = E->getNumSemanticExprs(); i != 0; ) {3842Expr *Semantic = E->getSemanticExpr(--i);38433844// If the semantic is an opaque value, we're being asked to bind3845// it to its source expression.3846if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))3847Semantic = OVE->getSourceExpr();38483849if (CFGBlock *B = Visit(Semantic))3850lastBlock = B;3851}38523853return lastBlock;3854}38553856CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) {3857CFGBlock *LoopSuccessor = nullptr;38583859// Save local scope position because in case of condition variable ScopePos3860// won't be restored when traversing AST.3861SaveAndRestore save_scope_pos(ScopePos);38623863// Create local scope for possible condition variable.3864// Store scope position for continue statement.3865LocalScope::const_iterator LoopBeginScopePos = ScopePos;3866if (VarDecl *VD = W->getConditionVariable()) {3867addLocalScopeForVarDecl(VD);3868addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);3869}3870addLoopExit(W);38713872// "while" is a control-flow statement. Thus we stop processing the current3873// block.3874if (Block) {3875if (badCFG)3876return nullptr;3877LoopSuccessor = Block;3878Block = nullptr;3879} else {3880LoopSuccessor = Succ;3881}38823883CFGBlock *BodyBlock = nullptr, *TransitionBlock = nullptr;38843885// Process the loop body.3886{3887assert(W->getBody());38883889// Save the current values for Block, Succ, continue and break targets.3890SaveAndRestore save_Block(Block), save_Succ(Succ);3891SaveAndRestore save_continue(ContinueJumpTarget),3892save_break(BreakJumpTarget);38933894// Create an empty block to represent the transition block for looping back3895// to the head of the loop.3896Succ = TransitionBlock = createBlock(false);3897TransitionBlock->setLoopTarget(W);3898ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);38993900// All breaks should go to the code following the loop.3901BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);39023903// Loop body should end with destructor of Condition variable (if any).3904addAutomaticObjHandling(ScopePos, LoopBeginScopePos, W);39053906// If body is not a compound statement create implicit scope3907// and add destructors.3908if (!isa<CompoundStmt>(W->getBody()))3909addLocalScopeAndDtors(W->getBody());39103911// Create the body. The returned block is the entry to the loop body.3912BodyBlock = addStmt(W->getBody());39133914if (!BodyBlock)3915BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"3916else if (Block && badCFG)3917return nullptr;3918}39193920// Because of short-circuit evaluation, the condition of the loop can span3921// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that3922// evaluate the condition.3923CFGBlock *EntryConditionBlock = nullptr, *ExitConditionBlock = nullptr;39243925do {3926Expr *C = W->getCond();39273928// Specially handle logical operators, which have a slightly3929// more optimal CFG representation.3930if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens()))3931if (Cond->isLogicalOp()) {3932std::tie(EntryConditionBlock, ExitConditionBlock) =3933VisitLogicalOperator(Cond, W, BodyBlock, LoopSuccessor);3934break;3935}39363937// The default case when not handling logical operators.3938ExitConditionBlock = createBlock(false);3939ExitConditionBlock->setTerminator(W);39403941// Now add the actual condition to the condition block.3942// Because the condition itself may contain control-flow, new blocks may3943// be created. Thus we update "Succ" after adding the condition.3944Block = ExitConditionBlock;3945Block = EntryConditionBlock = addStmt(C);39463947// If this block contains a condition variable, add both the condition3948// variable and initializer to the CFG.3949if (VarDecl *VD = W->getConditionVariable()) {3950if (Expr *Init = VD->getInit()) {3951autoCreateBlock();3952const DeclStmt *DS = W->getConditionVariableDeclStmt();3953assert(DS->isSingleDecl());3954findConstructionContexts(3955ConstructionContextLayer::create(cfg->getBumpVectorContext(),3956const_cast<DeclStmt *>(DS)),3957Init);3958appendStmt(Block, DS);3959EntryConditionBlock = addStmt(Init);3960assert(Block == EntryConditionBlock);3961maybeAddScopeBeginForVarDecl(EntryConditionBlock, VD, C);3962}3963}39643965if (Block && badCFG)3966return nullptr;39673968// See if this is a known constant.3969const TryResult& KnownVal = tryEvaluateBool(C);39703971// Add the loop body entry as a successor to the condition.3972addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? nullptr : BodyBlock);3973// Link up the condition block with the code that follows the loop. (the3974// false branch).3975addSuccessor(ExitConditionBlock,3976KnownVal.isTrue() ? nullptr : LoopSuccessor);3977} while(false);39783979// Link up the loop-back block to the entry condition block.3980addSuccessor(TransitionBlock, EntryConditionBlock);39813982// There can be no more statements in the condition block since we loop back3983// to this block. NULL out Block to force lazy creation of another block.3984Block = nullptr;39853986// Return the condition block, which is the dominating block for the loop.3987Succ = EntryConditionBlock;3988return EntryConditionBlock;3989}39903991CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,3992AddStmtChoice asc) {3993if (asc.alwaysAdd(*this, A)) {3994autoCreateBlock();3995appendStmt(Block, A);3996}39973998CFGBlock *B = Block;39994000if (CFGBlock *R = Visit(A->getSubExpr()))4001B = R;40024003auto *OVE = dyn_cast<OpaqueValueExpr>(A->getCommonExpr());4004assert(OVE && "ArrayInitLoopExpr->getCommonExpr() should be wrapped in an "4005"OpaqueValueExpr!");4006if (CFGBlock *R = Visit(OVE->getSourceExpr()))4007B = R;40084009return B;4010}40114012CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) {4013// ObjCAtCatchStmt are treated like labels, so they are the first statement4014// in a block.40154016// Save local scope position because in case of exception variable ScopePos4017// won't be restored when traversing AST.4018SaveAndRestore save_scope_pos(ScopePos);40194020if (CS->getCatchBody())4021addStmt(CS->getCatchBody());40224023CFGBlock *CatchBlock = Block;4024if (!CatchBlock)4025CatchBlock = createBlock();40264027appendStmt(CatchBlock, CS);40284029// Also add the ObjCAtCatchStmt as a label, like with regular labels.4030CatchBlock->setLabel(CS);40314032// Bail out if the CFG is bad.4033if (badCFG)4034return nullptr;40354036// We set Block to NULL to allow lazy creation of a new block (if necessary).4037Block = nullptr;40384039return CatchBlock;4040}40414042CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {4043// If we were in the middle of a block we stop processing that block.4044if (badCFG)4045return nullptr;40464047// Create the new block.4048Block = createBlock(false);40494050if (TryTerminatedBlock)4051// The current try statement is the only successor.4052addSuccessor(Block, TryTerminatedBlock);4053else4054// otherwise the Exit block is the only successor.4055addSuccessor(Block, &cfg->getExit());40564057// Add the statement to the block. This may create new blocks if S contains4058// control-flow (short-circuit operations).4059return VisitStmt(S, AddStmtChoice::AlwaysAdd);4060}40614062CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) {4063// "@try"/"@catch" is a control-flow statement. Thus we stop processing the4064// current block.4065CFGBlock *TrySuccessor = nullptr;40664067if (Block) {4068if (badCFG)4069return nullptr;4070TrySuccessor = Block;4071} else4072TrySuccessor = Succ;40734074// FIXME: Implement @finally support.4075if (Terminator->getFinallyStmt())4076return NYS();40774078CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;40794080// Create a new block that will contain the try statement.4081CFGBlock *NewTryTerminatedBlock = createBlock(false);4082// Add the terminator in the try block.4083NewTryTerminatedBlock->setTerminator(Terminator);40844085bool HasCatchAll = false;4086for (ObjCAtCatchStmt *CS : Terminator->catch_stmts()) {4087// The code after the try is the implicit successor.4088Succ = TrySuccessor;4089if (CS->hasEllipsis()) {4090HasCatchAll = true;4091}4092Block = nullptr;4093CFGBlock *CatchBlock = VisitObjCAtCatchStmt(CS);4094if (!CatchBlock)4095return nullptr;4096// Add this block to the list of successors for the block with the try4097// statement.4098addSuccessor(NewTryTerminatedBlock, CatchBlock);4099}41004101// FIXME: This needs updating when @finally support is added.4102if (!HasCatchAll) {4103if (PrevTryTerminatedBlock)4104addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);4105else4106addSuccessor(NewTryTerminatedBlock, &cfg->getExit());4107}41084109// The code after the try is the implicit successor.4110Succ = TrySuccessor;41114112// Save the current "try" context.4113SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);4114cfg->addTryDispatchBlock(TryTerminatedBlock);41154116assert(Terminator->getTryBody() && "try must contain a non-NULL body");4117Block = nullptr;4118return addStmt(Terminator->getTryBody());4119}41204121CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,4122AddStmtChoice asc) {4123findConstructionContextsForArguments(ME);41244125autoCreateBlock();4126appendObjCMessage(Block, ME);41274128return VisitChildren(ME);4129}41304131CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) {4132// If we were in the middle of a block we stop processing that block.4133if (badCFG)4134return nullptr;41354136// Create the new block.4137Block = createBlock(false);41384139if (TryTerminatedBlock)4140// The current try statement is the only successor.4141addSuccessor(Block, TryTerminatedBlock);4142else4143// otherwise the Exit block is the only successor.4144addSuccessor(Block, &cfg->getExit());41454146// Add the statement to the block. This may create new blocks if S contains4147// control-flow (short-circuit operations).4148return VisitStmt(T, AddStmtChoice::AlwaysAdd);4149}41504151CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) {4152if (asc.alwaysAdd(*this, S)) {4153autoCreateBlock();4154appendStmt(Block, S);4155}41564157// C++ [expr.typeid]p3:4158// When typeid is applied to an expression other than an glvalue of a4159// polymorphic class type [...] [the] expression is an unevaluated4160// operand. [...]4161// We add only potentially evaluated statements to the block to avoid4162// CFG generation for unevaluated operands.4163if (!S->isTypeDependent() && S->isPotentiallyEvaluated())4164return VisitChildren(S);41654166// Return block without CFG for unevaluated operands.4167return Block;4168}41694170CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {4171CFGBlock *LoopSuccessor = nullptr;41724173addLoopExit(D);41744175// "do...while" is a control-flow statement. Thus we stop processing the4176// current block.4177if (Block) {4178if (badCFG)4179return nullptr;4180LoopSuccessor = Block;4181} else4182LoopSuccessor = Succ;41834184// Because of short-circuit evaluation, the condition of the loop can span4185// multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that4186// evaluate the condition.4187CFGBlock *ExitConditionBlock = createBlock(false);4188CFGBlock *EntryConditionBlock = ExitConditionBlock;41894190// Set the terminator for the "exit" condition block.4191ExitConditionBlock->setTerminator(D);41924193// Now add the actual condition to the condition block. Because the condition4194// itself may contain control-flow, new blocks may be created.4195if (Stmt *C = D->getCond()) {4196Block = ExitConditionBlock;4197EntryConditionBlock = addStmt(C);4198if (Block) {4199if (badCFG)4200return nullptr;4201}4202}42034204// The condition block is the implicit successor for the loop body.4205Succ = EntryConditionBlock;42064207// See if this is a known constant.4208const TryResult &KnownVal = tryEvaluateBool(D->getCond());42094210// Process the loop body.4211CFGBlock *BodyBlock = nullptr;4212{4213assert(D->getBody());42144215// Save the current values for Block, Succ, and continue and break targets4216SaveAndRestore save_Block(Block), save_Succ(Succ);4217SaveAndRestore save_continue(ContinueJumpTarget),4218save_break(BreakJumpTarget);42194220// All continues within this loop should go to the condition block4221ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);42224223// All breaks should go to the code following the loop.4224BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);42254226// NULL out Block to force lazy instantiation of blocks for the body.4227Block = nullptr;42284229// If body is not a compound statement create implicit scope4230// and add destructors.4231if (!isa<CompoundStmt>(D->getBody()))4232addLocalScopeAndDtors(D->getBody());42334234// Create the body. The returned block is the entry to the loop body.4235BodyBlock = addStmt(D->getBody());42364237if (!BodyBlock)4238BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"4239else if (Block) {4240if (badCFG)4241return nullptr;4242}42434244// Add an intermediate block between the BodyBlock and the4245// ExitConditionBlock to represent the "loop back" transition. Create an4246// empty block to represent the transition block for looping back to the4247// head of the loop.4248// FIXME: Can we do this more efficiently without adding another block?4249Block = nullptr;4250Succ = BodyBlock;4251CFGBlock *LoopBackBlock = createBlock();4252LoopBackBlock->setLoopTarget(D);42534254if (!KnownVal.isFalse())4255// Add the loop body entry as a successor to the condition.4256addSuccessor(ExitConditionBlock, LoopBackBlock);4257else4258addSuccessor(ExitConditionBlock, nullptr);4259}42604261// Link up the condition block with the code that follows the loop.4262// (the false branch).4263addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);42644265// There can be no more statements in the body block(s) since we loop back to4266// the body. NULL out Block to force lazy creation of another block.4267Block = nullptr;42684269// Return the loop body, which is the dominating block for the loop.4270Succ = BodyBlock;4271return BodyBlock;4272}42734274CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) {4275// "continue" is a control-flow statement. Thus we stop processing the4276// current block.4277if (badCFG)4278return nullptr;42794280// Now create a new block that ends with the continue statement.4281Block = createBlock(false);4282Block->setTerminator(C);42834284// If there is no target for the continue, then we are looking at an4285// incomplete AST. This means the CFG cannot be constructed.4286if (ContinueJumpTarget.block) {4287addAutomaticObjHandling(ScopePos, ContinueJumpTarget.scopePosition, C);4288addSuccessor(Block, ContinueJumpTarget.block);4289} else4290badCFG = true;42914292return Block;4293}42944295CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,4296AddStmtChoice asc) {4297if (asc.alwaysAdd(*this, E)) {4298autoCreateBlock();4299appendStmt(Block, E);4300}43014302// VLA types have expressions that must be evaluated.4303// Evaluation is done only for `sizeof`.43044305if (E->getKind() != UETT_SizeOf)4306return Block;43074308CFGBlock *lastBlock = Block;43094310if (E->isArgumentType()) {4311for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr());4312VA != nullptr; VA = FindVA(VA->getElementType().getTypePtr()))4313lastBlock = addStmt(VA->getSizeExpr());4314}4315return lastBlock;4316}43174318/// VisitStmtExpr - Utility method to handle (nested) statement4319/// expressions (a GCC extension).4320CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {4321if (asc.alwaysAdd(*this, SE)) {4322autoCreateBlock();4323appendStmt(Block, SE);4324}4325return VisitCompoundStmt(SE->getSubStmt(), /*ExternallyDestructed=*/true);4326}43274328CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) {4329// "switch" is a control-flow statement. Thus we stop processing the current4330// block.4331CFGBlock *SwitchSuccessor = nullptr;43324333// Save local scope position because in case of condition variable ScopePos4334// won't be restored when traversing AST.4335SaveAndRestore save_scope_pos(ScopePos);43364337// Create local scope for C++17 switch init-stmt if one exists.4338if (Stmt *Init = Terminator->getInit())4339addLocalScopeForStmt(Init);43404341// Create local scope for possible condition variable.4342// Store scope position. Add implicit destructor.4343if (VarDecl *VD = Terminator->getConditionVariable())4344addLocalScopeForVarDecl(VD);43454346addAutomaticObjHandling(ScopePos, save_scope_pos.get(), Terminator);43474348if (Block) {4349if (badCFG)4350return nullptr;4351SwitchSuccessor = Block;4352} else SwitchSuccessor = Succ;43534354// Save the current "switch" context.4355SaveAndRestore save_switch(SwitchTerminatedBlock),4356save_default(DefaultCaseBlock);4357SaveAndRestore save_break(BreakJumpTarget);43584359// Set the "default" case to be the block after the switch statement. If the4360// switch statement contains a "default:", this value will be overwritten with4361// the block for that code.4362DefaultCaseBlock = SwitchSuccessor;43634364// Create a new block that will contain the switch statement.4365SwitchTerminatedBlock = createBlock(false);43664367// Now process the switch body. The code after the switch is the implicit4368// successor.4369Succ = SwitchSuccessor;4370BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);43714372// When visiting the body, the case statements should automatically get linked4373// up to the switch. We also don't keep a pointer to the body, since all4374// control-flow from the switch goes to case/default statements.4375assert(Terminator->getBody() && "switch must contain a non-NULL body");4376Block = nullptr;43774378// For pruning unreachable case statements, save the current state4379// for tracking the condition value.4380SaveAndRestore save_switchExclusivelyCovered(switchExclusivelyCovered, false);43814382// Determine if the switch condition can be explicitly evaluated.4383assert(Terminator->getCond() && "switch condition must be non-NULL");4384Expr::EvalResult result;4385bool b = tryEvaluate(Terminator->getCond(), result);4386SaveAndRestore save_switchCond(switchCond, b ? &result : nullptr);43874388// If body is not a compound statement create implicit scope4389// and add destructors.4390if (!isa<CompoundStmt>(Terminator->getBody()))4391addLocalScopeAndDtors(Terminator->getBody());43924393addStmt(Terminator->getBody());4394if (Block) {4395if (badCFG)4396return nullptr;4397}43984399// If we have no "default:" case, the default transition is to the code4400// following the switch body. Moreover, take into account if all the4401// cases of a switch are covered (e.g., switching on an enum value).4402//4403// Note: We add a successor to a switch that is considered covered yet has no4404// case statements if the enumeration has no enumerators.4405bool SwitchAlwaysHasSuccessor = false;4406SwitchAlwaysHasSuccessor |= switchExclusivelyCovered;4407SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() &&4408Terminator->getSwitchCaseList();4409addSuccessor(SwitchTerminatedBlock, DefaultCaseBlock,4410!SwitchAlwaysHasSuccessor);44114412// Add the terminator and condition in the switch block.4413SwitchTerminatedBlock->setTerminator(Terminator);4414Block = SwitchTerminatedBlock;4415CFGBlock *LastBlock = addStmt(Terminator->getCond());44164417// If the SwitchStmt contains a condition variable, add both the4418// SwitchStmt and the condition variable initialization to the CFG.4419if (VarDecl *VD = Terminator->getConditionVariable()) {4420if (Expr *Init = VD->getInit()) {4421autoCreateBlock();4422appendStmt(Block, Terminator->getConditionVariableDeclStmt());4423LastBlock = addStmt(Init);4424maybeAddScopeBeginForVarDecl(LastBlock, VD, Init);4425}4426}44274428// Finally, if the SwitchStmt contains a C++17 init-stmt, add it to the CFG.4429if (Stmt *Init = Terminator->getInit()) {4430autoCreateBlock();4431LastBlock = addStmt(Init);4432}44334434return LastBlock;4435}44364437static bool shouldAddCase(bool &switchExclusivelyCovered,4438const Expr::EvalResult *switchCond,4439const CaseStmt *CS,4440ASTContext &Ctx) {4441if (!switchCond)4442return true;44434444bool addCase = false;44454446if (!switchExclusivelyCovered) {4447if (switchCond->Val.isInt()) {4448// Evaluate the LHS of the case value.4449const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx);4450const llvm::APSInt &condInt = switchCond->Val.getInt();44514452if (condInt == lhsInt) {4453addCase = true;4454switchExclusivelyCovered = true;4455}4456else if (condInt > lhsInt) {4457if (const Expr *RHS = CS->getRHS()) {4458// Evaluate the RHS of the case value.4459const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx);4460if (V2 >= condInt) {4461addCase = true;4462switchExclusivelyCovered = true;4463}4464}4465}4466}4467else4468addCase = true;4469}4470return addCase;4471}44724473CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) {4474// CaseStmts are essentially labels, so they are the first statement in a4475// block.4476CFGBlock *TopBlock = nullptr, *LastBlock = nullptr;44774478if (Stmt *Sub = CS->getSubStmt()) {4479// For deeply nested chains of CaseStmts, instead of doing a recursion4480// (which can blow out the stack), manually unroll and create blocks4481// along the way.4482while (isa<CaseStmt>(Sub)) {4483CFGBlock *currentBlock = createBlock(false);4484currentBlock->setLabel(CS);44854486if (TopBlock)4487addSuccessor(LastBlock, currentBlock);4488else4489TopBlock = currentBlock;44904491addSuccessor(SwitchTerminatedBlock,4492shouldAddCase(switchExclusivelyCovered, switchCond,4493CS, *Context)4494? currentBlock : nullptr);44954496LastBlock = currentBlock;4497CS = cast<CaseStmt>(Sub);4498Sub = CS->getSubStmt();4499}45004501addStmt(Sub);4502}45034504CFGBlock *CaseBlock = Block;4505if (!CaseBlock)4506CaseBlock = createBlock();45074508// Cases statements partition blocks, so this is the top of the basic block we4509// were processing (the "case XXX:" is the label).4510CaseBlock->setLabel(CS);45114512if (badCFG)4513return nullptr;45144515// Add this block to the list of successors for the block with the switch4516// statement.4517assert(SwitchTerminatedBlock);4518addSuccessor(SwitchTerminatedBlock, CaseBlock,4519shouldAddCase(switchExclusivelyCovered, switchCond,4520CS, *Context));45214522// We set Block to NULL to allow lazy creation of a new block (if necessary).4523Block = nullptr;45244525if (TopBlock) {4526addSuccessor(LastBlock, CaseBlock);4527Succ = TopBlock;4528} else {4529// This block is now the implicit successor of other blocks.4530Succ = CaseBlock;4531}45324533return Succ;4534}45354536CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) {4537if (Terminator->getSubStmt())4538addStmt(Terminator->getSubStmt());45394540DefaultCaseBlock = Block;45414542if (!DefaultCaseBlock)4543DefaultCaseBlock = createBlock();45444545// Default statements partition blocks, so this is the top of the basic block4546// we were processing (the "default:" is the label).4547DefaultCaseBlock->setLabel(Terminator);45484549if (badCFG)4550return nullptr;45514552// Unlike case statements, we don't add the default block to the successors4553// for the switch statement immediately. This is done when we finish4554// processing the switch statement. This allows for the default case4555// (including a fall-through to the code after the switch statement) to always4556// be the last successor of a switch-terminated block.45574558// We set Block to NULL to allow lazy creation of a new block (if necessary).4559Block = nullptr;45604561// This block is now the implicit successor of other blocks.4562Succ = DefaultCaseBlock;45634564return DefaultCaseBlock;4565}45664567CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {4568// "try"/"catch" is a control-flow statement. Thus we stop processing the4569// current block.4570CFGBlock *TrySuccessor = nullptr;45714572if (Block) {4573if (badCFG)4574return nullptr;4575TrySuccessor = Block;4576} else4577TrySuccessor = Succ;45784579CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;45804581// Create a new block that will contain the try statement.4582CFGBlock *NewTryTerminatedBlock = createBlock(false);4583// Add the terminator in the try block.4584NewTryTerminatedBlock->setTerminator(Terminator);45854586bool HasCatchAll = false;4587for (unsigned I = 0, E = Terminator->getNumHandlers(); I != E; ++I) {4588// The code after the try is the implicit successor.4589Succ = TrySuccessor;4590CXXCatchStmt *CS = Terminator->getHandler(I);4591if (CS->getExceptionDecl() == nullptr) {4592HasCatchAll = true;4593}4594Block = nullptr;4595CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);4596if (!CatchBlock)4597return nullptr;4598// Add this block to the list of successors for the block with the try4599// statement.4600addSuccessor(NewTryTerminatedBlock, CatchBlock);4601}4602if (!HasCatchAll) {4603if (PrevTryTerminatedBlock)4604addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);4605else4606addSuccessor(NewTryTerminatedBlock, &cfg->getExit());4607}46084609// The code after the try is the implicit successor.4610Succ = TrySuccessor;46114612// Save the current "try" context.4613SaveAndRestore SaveTry(TryTerminatedBlock, NewTryTerminatedBlock);4614cfg->addTryDispatchBlock(TryTerminatedBlock);46154616assert(Terminator->getTryBlock() && "try must contain a non-NULL body");4617Block = nullptr;4618return addStmt(Terminator->getTryBlock());4619}46204621CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) {4622// CXXCatchStmt are treated like labels, so they are the first statement in a4623// block.46244625// Save local scope position because in case of exception variable ScopePos4626// won't be restored when traversing AST.4627SaveAndRestore save_scope_pos(ScopePos);46284629// Create local scope for possible exception variable.4630// Store scope position. Add implicit destructor.4631if (VarDecl *VD = CS->getExceptionDecl()) {4632LocalScope::const_iterator BeginScopePos = ScopePos;4633addLocalScopeForVarDecl(VD);4634addAutomaticObjHandling(ScopePos, BeginScopePos, CS);4635}46364637if (CS->getHandlerBlock())4638addStmt(CS->getHandlerBlock());46394640CFGBlock *CatchBlock = Block;4641if (!CatchBlock)4642CatchBlock = createBlock();46434644// CXXCatchStmt is more than just a label. They have semantic meaning4645// as well, as they implicitly "initialize" the catch variable. Add4646// it to the CFG as a CFGElement so that the control-flow of these4647// semantics gets captured.4648appendStmt(CatchBlock, CS);46494650// Also add the CXXCatchStmt as a label, to mirror handling of regular4651// labels.4652CatchBlock->setLabel(CS);46534654// Bail out if the CFG is bad.4655if (badCFG)4656return nullptr;46574658// We set Block to NULL to allow lazy creation of a new block (if necessary).4659Block = nullptr;46604661return CatchBlock;4662}46634664CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {4665// C++0x for-range statements are specified as [stmt.ranged]:4666//4667// {4668// auto && __range = range-init;4669// for ( auto __begin = begin-expr,4670// __end = end-expr;4671// __begin != __end;4672// ++__begin ) {4673// for-range-declaration = *__begin;4674// statement4675// }4676// }46774678// Save local scope position before the addition of the implicit variables.4679SaveAndRestore save_scope_pos(ScopePos);46804681// Create local scopes and destructors for range, begin and end variables.4682if (Stmt *Range = S->getRangeStmt())4683addLocalScopeForStmt(Range);4684if (Stmt *Begin = S->getBeginStmt())4685addLocalScopeForStmt(Begin);4686if (Stmt *End = S->getEndStmt())4687addLocalScopeForStmt(End);4688addAutomaticObjHandling(ScopePos, save_scope_pos.get(), S);46894690LocalScope::const_iterator ContinueScopePos = ScopePos;46914692// "for" is a control-flow statement. Thus we stop processing the current4693// block.4694CFGBlock *LoopSuccessor = nullptr;4695if (Block) {4696if (badCFG)4697return nullptr;4698LoopSuccessor = Block;4699} else4700LoopSuccessor = Succ;47014702// Save the current value for the break targets.4703// All breaks should go to the code following the loop.4704SaveAndRestore save_break(BreakJumpTarget);4705BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);47064707// The block for the __begin != __end expression.4708CFGBlock *ConditionBlock = createBlock(false);4709ConditionBlock->setTerminator(S);47104711// Now add the actual condition to the condition block.4712if (Expr *C = S->getCond()) {4713Block = ConditionBlock;4714CFGBlock *BeginConditionBlock = addStmt(C);4715if (badCFG)4716return nullptr;4717assert(BeginConditionBlock == ConditionBlock &&4718"condition block in for-range was unexpectedly complex");4719(void)BeginConditionBlock;4720}47214722// The condition block is the implicit successor for the loop body as well as4723// any code above the loop.4724Succ = ConditionBlock;47254726// See if this is a known constant.4727TryResult KnownVal(true);47284729if (S->getCond())4730KnownVal = tryEvaluateBool(S->getCond());47314732// Now create the loop body.4733{4734assert(S->getBody());47354736// Save the current values for Block, Succ, and continue targets.4737SaveAndRestore save_Block(Block), save_Succ(Succ);4738SaveAndRestore save_continue(ContinueJumpTarget);47394740// Generate increment code in its own basic block. This is the target of4741// continue statements.4742Block = nullptr;4743Succ = addStmt(S->getInc());4744if (badCFG)4745return nullptr;4746ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);47474748// The starting block for the loop increment is the block that should4749// represent the 'loop target' for looping back to the start of the loop.4750ContinueJumpTarget.block->setLoopTarget(S);47514752// Finish up the increment block and prepare to start the loop body.4753assert(Block);4754if (badCFG)4755return nullptr;4756Block = nullptr;47574758// Add implicit scope and dtors for loop variable.4759addLocalScopeAndDtors(S->getLoopVarStmt());47604761// If body is not a compound statement create implicit scope4762// and add destructors.4763if (!isa<CompoundStmt>(S->getBody()))4764addLocalScopeAndDtors(S->getBody());47654766// Populate a new block to contain the loop body and loop variable.4767addStmt(S->getBody());47684769if (badCFG)4770return nullptr;4771CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());4772if (badCFG)4773return nullptr;47744775// This new body block is a successor to our condition block.4776addSuccessor(ConditionBlock,4777KnownVal.isFalse() ? nullptr : LoopVarStmtBlock);4778}47794780// Link up the condition block with the code that follows the loop (the4781// false branch).4782addSuccessor(ConditionBlock, KnownVal.isTrue() ? nullptr : LoopSuccessor);47834784// Add the initialization statements.4785Block = createBlock();4786addStmt(S->getBeginStmt());4787addStmt(S->getEndStmt());4788CFGBlock *Head = addStmt(S->getRangeStmt());4789if (S->getInit())4790Head = addStmt(S->getInit());4791return Head;4792}47934794CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,4795AddStmtChoice asc, bool ExternallyDestructed) {4796if (BuildOpts.AddTemporaryDtors) {4797// If adding implicit destructors visit the full expression for adding4798// destructors of temporaries.4799TempDtorContext Context;4800VisitForTemporaryDtors(E->getSubExpr(), ExternallyDestructed, Context);48014802// Full expression has to be added as CFGStmt so it will be sequenced4803// before destructors of it's temporaries.4804asc = asc.withAlwaysAdd(true);4805}4806return Visit(E->getSubExpr(), asc);4807}48084809CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,4810AddStmtChoice asc) {4811if (asc.alwaysAdd(*this, E)) {4812autoCreateBlock();4813appendStmt(Block, E);48144815findConstructionContexts(4816ConstructionContextLayer::create(cfg->getBumpVectorContext(), E),4817E->getSubExpr());48184819// We do not want to propagate the AlwaysAdd property.4820asc = asc.withAlwaysAdd(false);4821}4822return Visit(E->getSubExpr(), asc);4823}48244825CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,4826AddStmtChoice asc) {4827// If the constructor takes objects as arguments by value, we need to properly4828// construct these objects. Construction contexts we find here aren't for the4829// constructor C, they're for its arguments only.4830findConstructionContextsForArguments(C);48314832autoCreateBlock();4833appendConstructor(Block, C);48344835return VisitChildren(C);4836}48374838CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,4839AddStmtChoice asc) {4840autoCreateBlock();4841appendStmt(Block, NE);48424843findConstructionContexts(4844ConstructionContextLayer::create(cfg->getBumpVectorContext(), NE),4845const_cast<CXXConstructExpr *>(NE->getConstructExpr()));48464847if (NE->getInitializer())4848Block = Visit(NE->getInitializer());48494850if (BuildOpts.AddCXXNewAllocator)4851appendNewAllocator(Block, NE);48524853if (NE->isArray() && *NE->getArraySize())4854Block = Visit(*NE->getArraySize());48554856for (CXXNewExpr::arg_iterator I = NE->placement_arg_begin(),4857E = NE->placement_arg_end(); I != E; ++I)4858Block = Visit(*I);48594860return Block;4861}48624863CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,4864AddStmtChoice asc) {4865autoCreateBlock();4866appendStmt(Block, DE);4867QualType DTy = DE->getDestroyedType();4868if (!DTy.isNull()) {4869DTy = DTy.getNonReferenceType();4870CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();4871if (RD) {4872if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())4873appendDeleteDtor(Block, RD, DE);4874}4875}48764877return VisitChildren(DE);4878}48794880CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,4881AddStmtChoice asc) {4882if (asc.alwaysAdd(*this, E)) {4883autoCreateBlock();4884appendStmt(Block, E);4885// We do not want to propagate the AlwaysAdd property.4886asc = asc.withAlwaysAdd(false);4887}4888return Visit(E->getSubExpr(), asc);4889}48904891CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,4892AddStmtChoice asc) {4893// If the constructor takes objects as arguments by value, we need to properly4894// construct these objects. Construction contexts we find here aren't for the4895// constructor C, they're for its arguments only.4896findConstructionContextsForArguments(C);48974898autoCreateBlock();4899appendConstructor(Block, C);4900return VisitChildren(C);4901}49024903CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,4904AddStmtChoice asc) {4905if (asc.alwaysAdd(*this, E)) {4906autoCreateBlock();4907appendStmt(Block, E);4908}49094910if (E->getCastKind() == CK_IntegralToBoolean)4911tryEvaluateBool(E->getSubExpr()->IgnoreParens());49124913return Visit(E->getSubExpr(), AddStmtChoice());4914}49154916CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) {4917return Visit(E->getSubExpr(), AddStmtChoice());4918}49194920CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) {4921// Lazily create the indirect-goto dispatch block if there isn't one already.4922CFGBlock *IBlock = cfg->getIndirectGotoBlock();49234924if (!IBlock) {4925IBlock = createBlock(false);4926cfg->setIndirectGotoBlock(IBlock);4927}49284929// IndirectGoto is a control-flow statement. Thus we stop processing the4930// current block and create a new one.4931if (badCFG)4932return nullptr;49334934Block = createBlock(false);4935Block->setTerminator(I);4936addSuccessor(Block, IBlock);4937return addStmt(I->getTarget());4938}49394940CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,4941TempDtorContext &Context) {4942assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors);49434944tryAgain:4945if (!E) {4946badCFG = true;4947return nullptr;4948}4949switch (E->getStmtClass()) {4950default:4951return VisitChildrenForTemporaryDtors(E, false, Context);49524953case Stmt::InitListExprClass:4954return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);49554956case Stmt::BinaryOperatorClass:4957return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E),4958ExternallyDestructed,4959Context);49604961case Stmt::CXXBindTemporaryExprClass:4962return VisitCXXBindTemporaryExprForTemporaryDtors(4963cast<CXXBindTemporaryExpr>(E), ExternallyDestructed, Context);49644965case Stmt::BinaryConditionalOperatorClass:4966case Stmt::ConditionalOperatorClass:4967return VisitConditionalOperatorForTemporaryDtors(4968cast<AbstractConditionalOperator>(E), ExternallyDestructed, Context);49694970case Stmt::ImplicitCastExprClass:4971// For implicit cast we want ExternallyDestructed to be passed further.4972E = cast<CastExpr>(E)->getSubExpr();4973goto tryAgain;49744975case Stmt::CXXFunctionalCastExprClass:4976// For functional cast we want ExternallyDestructed to be passed further.4977E = cast<CXXFunctionalCastExpr>(E)->getSubExpr();4978goto tryAgain;49794980case Stmt::ConstantExprClass:4981E = cast<ConstantExpr>(E)->getSubExpr();4982goto tryAgain;49834984case Stmt::ParenExprClass:4985E = cast<ParenExpr>(E)->getSubExpr();4986goto tryAgain;49874988case Stmt::MaterializeTemporaryExprClass: {4989const MaterializeTemporaryExpr* MTE = cast<MaterializeTemporaryExpr>(E);4990ExternallyDestructed = (MTE->getStorageDuration() != SD_FullExpression);4991SmallVector<const Expr *, 2> CommaLHSs;4992SmallVector<SubobjectAdjustment, 2> Adjustments;4993// Find the expression whose lifetime needs to be extended.4994E = const_cast<Expr *>(4995cast<MaterializeTemporaryExpr>(E)4996->getSubExpr()4997->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));4998// Visit the skipped comma operator left-hand sides for other temporaries.4999for (const Expr *CommaLHS : CommaLHSs) {5000VisitForTemporaryDtors(const_cast<Expr *>(CommaLHS),5001/*ExternallyDestructed=*/false, Context);5002}5003goto tryAgain;5004}50055006case Stmt::BlockExprClass:5007// Don't recurse into blocks; their subexpressions don't get evaluated5008// here.5009return Block;50105011case Stmt::LambdaExprClass: {5012// For lambda expressions, only recurse into the capture initializers,5013// and not the body.5014auto *LE = cast<LambdaExpr>(E);5015CFGBlock *B = Block;5016for (Expr *Init : LE->capture_inits()) {5017if (Init) {5018if (CFGBlock *R = VisitForTemporaryDtors(5019Init, /*ExternallyDestructed=*/true, Context))5020B = R;5021}5022}5023return B;5024}50255026case Stmt::StmtExprClass:5027// Don't recurse into statement expressions; any cleanups inside them5028// will be wrapped in their own ExprWithCleanups.5029return Block;50305031case Stmt::CXXDefaultArgExprClass:5032E = cast<CXXDefaultArgExpr>(E)->getExpr();5033goto tryAgain;50345035case Stmt::CXXDefaultInitExprClass:5036E = cast<CXXDefaultInitExpr>(E)->getExpr();5037goto tryAgain;5038}5039}50405041CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,5042bool ExternallyDestructed,5043TempDtorContext &Context) {5044if (isa<LambdaExpr>(E)) {5045// Do not visit the children of lambdas; they have their own CFGs.5046return Block;5047}50485049// When visiting children for destructors we want to visit them in reverse5050// order that they will appear in the CFG. Because the CFG is built5051// bottom-up, this means we visit them in their natural order, which5052// reverses them in the CFG.5053CFGBlock *B = Block;5054for (Stmt *Child : E->children())5055if (Child)5056if (CFGBlock *R = VisitForTemporaryDtors(Child, ExternallyDestructed, Context))5057B = R;50585059return B;5060}50615062CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(5063BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) {5064if (E->isCommaOp()) {5065// For the comma operator, the LHS expression is evaluated before the RHS5066// expression, so prepend temporary destructors for the LHS first.5067CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);5068CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), ExternallyDestructed, Context);5069return RHSBlock ? RHSBlock : LHSBlock;5070}50715072if (E->isLogicalOp()) {5073VisitForTemporaryDtors(E->getLHS(), false, Context);5074TryResult RHSExecuted = tryEvaluateBool(E->getLHS());5075if (RHSExecuted.isKnown() && E->getOpcode() == BO_LOr)5076RHSExecuted.negate();50775078// We do not know at CFG-construction time whether the right-hand-side was5079// executed, thus we add a branch node that depends on the temporary5080// constructor call.5081TempDtorContext RHSContext(5082bothKnownTrue(Context.KnownExecuted, RHSExecuted));5083VisitForTemporaryDtors(E->getRHS(), false, RHSContext);5084InsertTempDtorDecisionBlock(RHSContext);50855086return Block;5087}50885089if (E->isAssignmentOp()) {5090// For assignment operators, the RHS expression is evaluated before the LHS5091// expression, so prepend temporary destructors for the RHS first.5092CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), false, Context);5093CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS(), false, Context);5094return LHSBlock ? LHSBlock : RHSBlock;5095}50965097// Any other operator is visited normally.5098return VisitChildrenForTemporaryDtors(E, ExternallyDestructed, Context);5099}51005101CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(5102CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) {5103// First add destructors for temporaries in subexpression.5104// Because VisitCXXBindTemporaryExpr calls setDestructed:5105CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr(), true, Context);5106if (!ExternallyDestructed) {5107// If lifetime of temporary is not prolonged (by assigning to constant5108// reference) add destructor for it.51095110const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();51115112if (Dtor->getParent()->isAnyDestructorNoReturn()) {5113// If the destructor is marked as a no-return destructor, we need to5114// create a new block for the destructor which does not have as a5115// successor anything built thus far. Control won't flow out of this5116// block.5117if (B) Succ = B;5118Block = createNoReturnBlock();5119} else if (Context.needsTempDtorBranch()) {5120// If we need to introduce a branch, we add a new block that we will hook5121// up to a decision block later.5122if (B) Succ = B;5123Block = createBlock();5124} else {5125autoCreateBlock();5126}5127if (Context.needsTempDtorBranch()) {5128Context.setDecisionPoint(Succ, E);5129}5130appendTemporaryDtor(Block, E);51315132B = Block;5133}5134return B;5135}51365137void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,5138CFGBlock *FalseSucc) {5139if (!Context.TerminatorExpr) {5140// If no temporary was found, we do not need to insert a decision point.5141return;5142}5143assert(Context.TerminatorExpr);5144CFGBlock *Decision = createBlock(false);5145Decision->setTerminator(CFGTerminator(Context.TerminatorExpr,5146CFGTerminator::TemporaryDtorsBranch));5147addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse());5148addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ,5149!Context.KnownExecuted.isTrue());5150Block = Decision;5151}51525153CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(5154AbstractConditionalOperator *E, bool ExternallyDestructed,5155TempDtorContext &Context) {5156VisitForTemporaryDtors(E->getCond(), false, Context);5157CFGBlock *ConditionBlock = Block;5158CFGBlock *ConditionSucc = Succ;5159TryResult ConditionVal = tryEvaluateBool(E->getCond());5160TryResult NegatedVal = ConditionVal;5161if (NegatedVal.isKnown()) NegatedVal.negate();51625163TempDtorContext TrueContext(5164bothKnownTrue(Context.KnownExecuted, ConditionVal));5165VisitForTemporaryDtors(E->getTrueExpr(), ExternallyDestructed, TrueContext);5166CFGBlock *TrueBlock = Block;51675168Block = ConditionBlock;5169Succ = ConditionSucc;5170TempDtorContext FalseContext(5171bothKnownTrue(Context.KnownExecuted, NegatedVal));5172VisitForTemporaryDtors(E->getFalseExpr(), ExternallyDestructed, FalseContext);51735174if (TrueContext.TerminatorExpr && FalseContext.TerminatorExpr) {5175InsertTempDtorDecisionBlock(FalseContext, TrueBlock);5176} else if (TrueContext.TerminatorExpr) {5177Block = TrueBlock;5178InsertTempDtorDecisionBlock(TrueContext);5179} else {5180InsertTempDtorDecisionBlock(FalseContext);5181}5182return Block;5183}51845185CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,5186AddStmtChoice asc) {5187if (asc.alwaysAdd(*this, D)) {5188autoCreateBlock();5189appendStmt(Block, D);5190}51915192// Iterate over all used expression in clauses.5193CFGBlock *B = Block;51945195// Reverse the elements to process them in natural order. Iterators are not5196// bidirectional, so we need to create temp vector.5197SmallVector<Stmt *, 8> Used(5198OMPExecutableDirective::used_clauses_children(D->clauses()));5199for (Stmt *S : llvm::reverse(Used)) {5200assert(S && "Expected non-null used-in-clause child.");5201if (CFGBlock *R = Visit(S))5202B = R;5203}5204// Visit associated structured block if any.5205if (!D->isStandaloneDirective()) {5206Stmt *S = D->getRawStmt();5207if (!isa<CompoundStmt>(S))5208addLocalScopeAndDtors(S);5209if (CFGBlock *R = addStmt(S))5210B = R;5211}52125213return B;5214}52155216/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has5217/// no successors or predecessors. If this is the first block created in the5218/// CFG, it is automatically set to be the Entry and Exit of the CFG.5219CFGBlock *CFG::createBlock() {5220bool first_block = begin() == end();52215222// Create the block.5223CFGBlock *Mem = new (getAllocator()) CFGBlock(NumBlockIDs++, BlkBVC, this);5224Blocks.push_back(Mem, BlkBVC);52255226// If this is the first block, set it as the Entry and Exit.5227if (first_block)5228Entry = Exit = &back();52295230// Return the block.5231return &back();5232}52335234/// buildCFG - Constructs a CFG from an AST.5235std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,5236ASTContext *C, const BuildOptions &BO) {5237CFGBuilder Builder(C, BO);5238return Builder.buildCFG(D, Statement);5239}52405241bool CFG::isLinear() const {5242// Quick path: if we only have the ENTRY block, the EXIT block, and some code5243// in between, then we have no room for control flow.5244if (size() <= 3)5245return true;52465247// Traverse the CFG until we find a branch.5248// TODO: While this should still be very fast,5249// maybe we should cache the answer.5250llvm::SmallPtrSet<const CFGBlock *, 4> Visited;5251const CFGBlock *B = Entry;5252while (B != Exit) {5253auto IteratorAndFlag = Visited.insert(B);5254if (!IteratorAndFlag.second) {5255// We looped back to a block that we've already visited. Not linear.5256return false;5257}52585259// Iterate over reachable successors.5260const CFGBlock *FirstReachableB = nullptr;5261for (const CFGBlock::AdjacentBlock &AB : B->succs()) {5262if (!AB.isReachable())5263continue;52645265if (FirstReachableB == nullptr) {5266FirstReachableB = &*AB;5267} else {5268// We've encountered a branch. It's not a linear CFG.5269return false;5270}5271}52725273if (!FirstReachableB) {5274// We reached a dead end. EXIT is unreachable. This is linear enough.5275return true;5276}52775278// There's only one way to move forward. Proceed.5279B = FirstReachableB;5280}52815282// We reached EXIT and found no branches.5283return true;5284}52855286const CXXDestructorDecl *5287CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const {5288switch (getKind()) {5289case CFGElement::Initializer:5290case CFGElement::NewAllocator:5291case CFGElement::LoopExit:5292case CFGElement::LifetimeEnds:5293case CFGElement::Statement:5294case CFGElement::Constructor:5295case CFGElement::CXXRecordTypedCall:5296case CFGElement::ScopeBegin:5297case CFGElement::ScopeEnd:5298case CFGElement::CleanupFunction:5299llvm_unreachable("getDestructorDecl should only be used with "5300"ImplicitDtors");5301case CFGElement::AutomaticObjectDtor: {5302const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl();5303QualType ty = var->getType();53045305// FIXME: See CFGBuilder::addLocalScopeForVarDecl.5306//5307// Lifetime-extending constructs are handled here. This works for a single5308// temporary in an initializer expression.5309if (ty->isReferenceType()) {5310if (const Expr *Init = var->getInit()) {5311ty = getReferenceInitTemporaryType(Init);5312}5313}53145315while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {5316ty = arrayType->getElementType();5317}53185319// The situation when the type of the lifetime-extending reference5320// does not correspond to the type of the object is supposed5321// to be handled by now. In particular, 'ty' is now the unwrapped5322// record type.5323const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();5324assert(classDecl);5325return classDecl->getDestructor();5326}5327case CFGElement::DeleteDtor: {5328const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr();5329QualType DTy = DE->getDestroyedType();5330DTy = DTy.getNonReferenceType();5331const CXXRecordDecl *classDecl =5332astContext.getBaseElementType(DTy)->getAsCXXRecordDecl();5333return classDecl->getDestructor();5334}5335case CFGElement::TemporaryDtor: {5336const CXXBindTemporaryExpr *bindExpr =5337castAs<CFGTemporaryDtor>().getBindTemporaryExpr();5338const CXXTemporary *temp = bindExpr->getTemporary();5339return temp->getDestructor();5340}5341case CFGElement::MemberDtor: {5342const FieldDecl *field = castAs<CFGMemberDtor>().getFieldDecl();5343QualType ty = field->getType();53445345while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) {5346ty = arrayType->getElementType();5347}53485349const CXXRecordDecl *classDecl = ty->getAsCXXRecordDecl();5350assert(classDecl);5351return classDecl->getDestructor();5352}5353case CFGElement::BaseDtor:5354// Not yet supported.5355return nullptr;5356}5357llvm_unreachable("getKind() returned bogus value");5358}53595360//===----------------------------------------------------------------------===//5361// CFGBlock operations.5362//===----------------------------------------------------------------------===//53635364CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)5365: ReachableBlock(IsReachable ? B : nullptr),5366UnreachableBlock(!IsReachable ? B : nullptr,5367B && IsReachable ? AB_Normal : AB_Unreachable) {}53685369CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)5370: ReachableBlock(B),5371UnreachableBlock(B == AlternateBlock ? nullptr : AlternateBlock,5372B == AlternateBlock ? AB_Alternate : AB_Normal) {}53735374void CFGBlock::addSuccessor(AdjacentBlock Succ,5375BumpVectorContext &C) {5376if (CFGBlock *B = Succ.getReachableBlock())5377B->Preds.push_back(AdjacentBlock(this, Succ.isReachable()), C);53785379if (CFGBlock *UnreachableB = Succ.getPossiblyUnreachableBlock())5380UnreachableB->Preds.push_back(AdjacentBlock(this, false), C);53815382Succs.push_back(Succ, C);5383}53845385bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,5386const CFGBlock *From, const CFGBlock *To) {5387if (F.IgnoreNullPredecessors && !From)5388return true;53895390if (To && From && F.IgnoreDefaultsWithCoveredEnums) {5391// If the 'To' has no label or is labeled but the label isn't a5392// CaseStmt then filter this edge.5393if (const SwitchStmt *S =5394dyn_cast_or_null<SwitchStmt>(From->getTerminatorStmt())) {5395if (S->isAllEnumCasesCovered()) {5396const Stmt *L = To->getLabel();5397if (!L || !isa<CaseStmt>(L))5398return true;5399}5400}5401}54025403return false;5404}54055406//===----------------------------------------------------------------------===//5407// CFG pretty printing5408//===----------------------------------------------------------------------===//54095410namespace {54115412class StmtPrinterHelper : public PrinterHelper {5413using StmtMapTy = llvm::DenseMap<const Stmt *, std::pair<unsigned, unsigned>>;5414using DeclMapTy = llvm::DenseMap<const Decl *, std::pair<unsigned, unsigned>>;54155416StmtMapTy StmtMap;5417DeclMapTy DeclMap;5418signed currentBlock = 0;5419unsigned currStmt = 0;5420const LangOptions &LangOpts;54215422public:5423StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)5424: LangOpts(LO) {5425if (!cfg)5426return;5427for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {5428unsigned j = 1;5429for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;5430BI != BEnd; ++BI, ++j ) {5431if (std::optional<CFGStmt> SE = BI->getAs<CFGStmt>()) {5432const Stmt *stmt= SE->getStmt();5433std::pair<unsigned, unsigned> P((*I)->getBlockID(), j);5434StmtMap[stmt] = P;54355436switch (stmt->getStmtClass()) {5437case Stmt::DeclStmtClass:5438DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P;5439break;5440case Stmt::IfStmtClass: {5441const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable();5442if (var)5443DeclMap[var] = P;5444break;5445}5446case Stmt::ForStmtClass: {5447const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable();5448if (var)5449DeclMap[var] = P;5450break;5451}5452case Stmt::WhileStmtClass: {5453const VarDecl *var =5454cast<WhileStmt>(stmt)->getConditionVariable();5455if (var)5456DeclMap[var] = P;5457break;5458}5459case Stmt::SwitchStmtClass: {5460const VarDecl *var =5461cast<SwitchStmt>(stmt)->getConditionVariable();5462if (var)5463DeclMap[var] = P;5464break;5465}5466case Stmt::CXXCatchStmtClass: {5467const VarDecl *var =5468cast<CXXCatchStmt>(stmt)->getExceptionDecl();5469if (var)5470DeclMap[var] = P;5471break;5472}5473default:5474break;5475}5476}5477}5478}5479}54805481~StmtPrinterHelper() override = default;54825483const LangOptions &getLangOpts() const { return LangOpts; }5484void setBlockID(signed i) { currentBlock = i; }5485void setStmtID(unsigned i) { currStmt = i; }54865487bool handledStmt(Stmt *S, raw_ostream &OS) override {5488StmtMapTy::iterator I = StmtMap.find(S);54895490if (I == StmtMap.end())5491return false;54925493if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock5494&& I->second.second == currStmt) {5495return false;5496}54975498OS << "[B" << I->second.first << "." << I->second.second << "]";5499return true;5500}55015502bool handleDecl(const Decl *D, raw_ostream &OS) {5503DeclMapTy::iterator I = DeclMap.find(D);55045505if (I == DeclMap.end())5506return false;55075508if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock5509&& I->second.second == currStmt) {5510return false;5511}55125513OS << "[B" << I->second.first << "." << I->second.second << "]";5514return true;5515}5516};55175518class CFGBlockTerminatorPrint5519: public StmtVisitor<CFGBlockTerminatorPrint,void> {5520raw_ostream &OS;5521StmtPrinterHelper* Helper;5522PrintingPolicy Policy;55235524public:5525CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper,5526const PrintingPolicy &Policy)5527: OS(os), Helper(helper), Policy(Policy) {5528this->Policy.IncludeNewlines = false;5529}55305531void VisitIfStmt(IfStmt *I) {5532OS << "if ";5533if (Stmt *C = I->getCond())5534C->printPretty(OS, Helper, Policy);5535}55365537// Default case.5538void VisitStmt(Stmt *Terminator) {5539Terminator->printPretty(OS, Helper, Policy);5540}55415542void VisitDeclStmt(DeclStmt *DS) {5543VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());5544OS << "static init " << VD->getName();5545}55465547void VisitForStmt(ForStmt *F) {5548OS << "for (" ;5549if (F->getInit())5550OS << "...";5551OS << "; ";5552if (Stmt *C = F->getCond())5553C->printPretty(OS, Helper, Policy);5554OS << "; ";5555if (F->getInc())5556OS << "...";5557OS << ")";5558}55595560void VisitWhileStmt(WhileStmt *W) {5561OS << "while " ;5562if (Stmt *C = W->getCond())5563C->printPretty(OS, Helper, Policy);5564}55655566void VisitDoStmt(DoStmt *D) {5567OS << "do ... while ";5568if (Stmt *C = D->getCond())5569C->printPretty(OS, Helper, Policy);5570}55715572void VisitSwitchStmt(SwitchStmt *Terminator) {5573OS << "switch ";5574Terminator->getCond()->printPretty(OS, Helper, Policy);5575}55765577void VisitCXXTryStmt(CXXTryStmt *) { OS << "try ..."; }55785579void VisitObjCAtTryStmt(ObjCAtTryStmt *) { OS << "@try ..."; }55805581void VisitSEHTryStmt(SEHTryStmt *CS) { OS << "__try ..."; }55825583void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {5584if (Stmt *Cond = C->getCond())5585Cond->printPretty(OS, Helper, Policy);5586OS << " ? ... : ...";5587}55885589void VisitChooseExpr(ChooseExpr *C) {5590OS << "__builtin_choose_expr( ";5591if (Stmt *Cond = C->getCond())5592Cond->printPretty(OS, Helper, Policy);5593OS << " )";5594}55955596void VisitIndirectGotoStmt(IndirectGotoStmt *I) {5597OS << "goto *";5598if (Stmt *T = I->getTarget())5599T->printPretty(OS, Helper, Policy);5600}56015602void VisitBinaryOperator(BinaryOperator* B) {5603if (!B->isLogicalOp()) {5604VisitExpr(B);5605return;5606}56075608if (B->getLHS())5609B->getLHS()->printPretty(OS, Helper, Policy);56105611switch (B->getOpcode()) {5612case BO_LOr:5613OS << " || ...";5614return;5615case BO_LAnd:5616OS << " && ...";5617return;5618default:5619llvm_unreachable("Invalid logical operator.");5620}5621}56225623void VisitExpr(Expr *E) {5624E->printPretty(OS, Helper, Policy);5625}56265627public:5628void print(CFGTerminator T) {5629switch (T.getKind()) {5630case CFGTerminator::StmtBranch:5631Visit(T.getStmt());5632break;5633case CFGTerminator::TemporaryDtorsBranch:5634OS << "(Temp Dtor) ";5635Visit(T.getStmt());5636break;5637case CFGTerminator::VirtualBaseBranch:5638OS << "(See if most derived ctor has already initialized vbases)";5639break;5640}5641}5642};56435644} // namespace56455646static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper,5647const CXXCtorInitializer *I) {5648if (I->isBaseInitializer())5649OS << I->getBaseClass()->getAsCXXRecordDecl()->getName();5650else if (I->isDelegatingInitializer())5651OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName();5652else5653OS << I->getAnyMember()->getName();5654OS << "(";5655if (Expr *IE = I->getInit())5656IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));5657OS << ")";56585659if (I->isBaseInitializer())5660OS << " (Base initializer)";5661else if (I->isDelegatingInitializer())5662OS << " (Delegating initializer)";5663else5664OS << " (Member initializer)";5665}56665667static void print_construction_context(raw_ostream &OS,5668StmtPrinterHelper &Helper,5669const ConstructionContext *CC) {5670SmallVector<const Stmt *, 3> Stmts;5671switch (CC->getKind()) {5672case ConstructionContext::SimpleConstructorInitializerKind: {5673OS << ", ";5674const auto *SICC = cast<SimpleConstructorInitializerConstructionContext>(CC);5675print_initializer(OS, Helper, SICC->getCXXCtorInitializer());5676return;5677}5678case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: {5679OS << ", ";5680const auto *CICC =5681cast<CXX17ElidedCopyConstructorInitializerConstructionContext>(CC);5682print_initializer(OS, Helper, CICC->getCXXCtorInitializer());5683Stmts.push_back(CICC->getCXXBindTemporaryExpr());5684break;5685}5686case ConstructionContext::SimpleVariableKind: {5687const auto *SDSCC = cast<SimpleVariableConstructionContext>(CC);5688Stmts.push_back(SDSCC->getDeclStmt());5689break;5690}5691case ConstructionContext::CXX17ElidedCopyVariableKind: {5692const auto *CDSCC = cast<CXX17ElidedCopyVariableConstructionContext>(CC);5693Stmts.push_back(CDSCC->getDeclStmt());5694Stmts.push_back(CDSCC->getCXXBindTemporaryExpr());5695break;5696}5697case ConstructionContext::NewAllocatedObjectKind: {5698const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);5699Stmts.push_back(NECC->getCXXNewExpr());5700break;5701}5702case ConstructionContext::SimpleReturnedValueKind: {5703const auto *RSCC = cast<SimpleReturnedValueConstructionContext>(CC);5704Stmts.push_back(RSCC->getReturnStmt());5705break;5706}5707case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {5708const auto *RSCC =5709cast<CXX17ElidedCopyReturnedValueConstructionContext>(CC);5710Stmts.push_back(RSCC->getReturnStmt());5711Stmts.push_back(RSCC->getCXXBindTemporaryExpr());5712break;5713}5714case ConstructionContext::SimpleTemporaryObjectKind: {5715const auto *TOCC = cast<SimpleTemporaryObjectConstructionContext>(CC);5716Stmts.push_back(TOCC->getCXXBindTemporaryExpr());5717Stmts.push_back(TOCC->getMaterializedTemporaryExpr());5718break;5719}5720case ConstructionContext::ElidedTemporaryObjectKind: {5721const auto *TOCC = cast<ElidedTemporaryObjectConstructionContext>(CC);5722Stmts.push_back(TOCC->getCXXBindTemporaryExpr());5723Stmts.push_back(TOCC->getMaterializedTemporaryExpr());5724Stmts.push_back(TOCC->getConstructorAfterElision());5725break;5726}5727case ConstructionContext::LambdaCaptureKind: {5728const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);5729Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS);5730OS << "+" << LCC->getIndex();5731return;5732}5733case ConstructionContext::ArgumentKind: {5734const auto *ACC = cast<ArgumentConstructionContext>(CC);5735if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) {5736OS << ", ";5737Helper.handledStmt(const_cast<Stmt *>(BTE), OS);5738}5739OS << ", ";5740Helper.handledStmt(const_cast<Expr *>(ACC->getCallLikeExpr()), OS);5741OS << "+" << ACC->getIndex();5742return;5743}5744}5745for (auto I: Stmts)5746if (I) {5747OS << ", ";5748Helper.handledStmt(const_cast<Stmt *>(I), OS);5749}5750}57515752static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,5753const CFGElement &E);57545755void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {5756LangOptions LangOpts;5757StmtPrinterHelper Helper(nullptr, LangOpts);5758print_elem(OS, Helper, *this);5759}57605761static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,5762const CFGElement &E) {5763switch (E.getKind()) {5764case CFGElement::Kind::Statement:5765case CFGElement::Kind::CXXRecordTypedCall:5766case CFGElement::Kind::Constructor: {5767CFGStmt CS = E.castAs<CFGStmt>();5768const Stmt *S = CS.getStmt();5769assert(S != nullptr && "Expecting non-null Stmt");57705771// special printing for statement-expressions.5772if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {5773const CompoundStmt *Sub = SE->getSubStmt();57745775auto Children = Sub->children();5776if (Children.begin() != Children.end()) {5777OS << "({ ... ; ";5778Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);5779OS << " })\n";5780return;5781}5782}5783// special printing for comma expressions.5784if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {5785if (B->getOpcode() == BO_Comma) {5786OS << "... , ";5787Helper.handledStmt(B->getRHS(),OS);5788OS << '\n';5789return;5790}5791}5792S->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));57935794if (auto VTC = E.getAs<CFGCXXRecordTypedCall>()) {5795if (isa<CXXOperatorCallExpr>(S))5796OS << " (OperatorCall)";5797OS << " (CXXRecordTypedCall";5798print_construction_context(OS, Helper, VTC->getConstructionContext());5799OS << ")";5800} else if (isa<CXXOperatorCallExpr>(S)) {5801OS << " (OperatorCall)";5802} else if (isa<CXXBindTemporaryExpr>(S)) {5803OS << " (BindTemporary)";5804} else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) {5805OS << " (CXXConstructExpr";5806if (std::optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) {5807print_construction_context(OS, Helper, CE->getConstructionContext());5808}5809OS << ", " << CCE->getType() << ")";5810} else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) {5811OS << " (" << CE->getStmtClassName() << ", " << CE->getCastKindName()5812<< ", " << CE->getType() << ")";5813}58145815// Expressions need a newline.5816if (isa<Expr>(S))5817OS << '\n';58185819break;5820}58215822case CFGElement::Kind::Initializer:5823print_initializer(OS, Helper, E.castAs<CFGInitializer>().getInitializer());5824OS << '\n';5825break;58265827case CFGElement::Kind::AutomaticObjectDtor: {5828CFGAutomaticObjDtor DE = E.castAs<CFGAutomaticObjDtor>();5829const VarDecl *VD = DE.getVarDecl();5830Helper.handleDecl(VD, OS);58315832QualType T = VD->getType();5833if (T->isReferenceType())5834T = getReferenceInitTemporaryType(VD->getInit(), nullptr);58355836OS << ".~";5837T.getUnqualifiedType().print(OS, PrintingPolicy(Helper.getLangOpts()));5838OS << "() (Implicit destructor)\n";5839break;5840}58415842case CFGElement::Kind::CleanupFunction:5843OS << "CleanupFunction ("5844<< E.castAs<CFGCleanupFunction>().getFunctionDecl()->getName() << ")\n";5845break;58465847case CFGElement::Kind::LifetimeEnds:5848Helper.handleDecl(E.castAs<CFGLifetimeEnds>().getVarDecl(), OS);5849OS << " (Lifetime ends)\n";5850break;58515852case CFGElement::Kind::LoopExit:5853OS << E.castAs<CFGLoopExit>().getLoopStmt()->getStmtClassName() << " (LoopExit)\n";5854break;58555856case CFGElement::Kind::ScopeBegin:5857OS << "CFGScopeBegin(";5858if (const VarDecl *VD = E.castAs<CFGScopeBegin>().getVarDecl())5859OS << VD->getQualifiedNameAsString();5860OS << ")\n";5861break;58625863case CFGElement::Kind::ScopeEnd:5864OS << "CFGScopeEnd(";5865if (const VarDecl *VD = E.castAs<CFGScopeEnd>().getVarDecl())5866OS << VD->getQualifiedNameAsString();5867OS << ")\n";5868break;58695870case CFGElement::Kind::NewAllocator:5871OS << "CFGNewAllocator(";5872if (const CXXNewExpr *AllocExpr = E.castAs<CFGNewAllocator>().getAllocatorExpr())5873AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));5874OS << ")\n";5875break;58765877case CFGElement::Kind::DeleteDtor: {5878CFGDeleteDtor DE = E.castAs<CFGDeleteDtor>();5879const CXXRecordDecl *RD = DE.getCXXRecordDecl();5880if (!RD)5881return;5882CXXDeleteExpr *DelExpr =5883const_cast<CXXDeleteExpr*>(DE.getDeleteExpr());5884Helper.handledStmt(cast<Stmt>(DelExpr->getArgument()), OS);5885OS << "->~" << RD->getName().str() << "()";5886OS << " (Implicit destructor)\n";5887break;5888}58895890case CFGElement::Kind::BaseDtor: {5891const CXXBaseSpecifier *BS = E.castAs<CFGBaseDtor>().getBaseSpecifier();5892OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()";5893OS << " (Base object destructor)\n";5894break;5895}58965897case CFGElement::Kind::MemberDtor: {5898const FieldDecl *FD = E.castAs<CFGMemberDtor>().getFieldDecl();5899const Type *T = FD->getType()->getBaseElementTypeUnsafe();5900OS << "this->" << FD->getName();5901OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";5902OS << " (Member object destructor)\n";5903break;5904}59055906case CFGElement::Kind::TemporaryDtor: {5907const CXXBindTemporaryExpr *BT =5908E.castAs<CFGTemporaryDtor>().getBindTemporaryExpr();5909OS << "~";5910BT->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));5911OS << "() (Temporary object destructor)\n";5912break;5913}5914}5915}59165917static void print_block(raw_ostream &OS, const CFG* cfg,5918const CFGBlock &B,5919StmtPrinterHelper &Helper, bool print_edges,5920bool ShowColors) {5921Helper.setBlockID(B.getBlockID());59225923// Print the header.5924if (ShowColors)5925OS.changeColor(raw_ostream::YELLOW, true);59265927OS << "\n [B" << B.getBlockID();59285929if (&B == &cfg->getEntry())5930OS << " (ENTRY)]\n";5931else if (&B == &cfg->getExit())5932OS << " (EXIT)]\n";5933else if (&B == cfg->getIndirectGotoBlock())5934OS << " (INDIRECT GOTO DISPATCH)]\n";5935else if (B.hasNoReturnElement())5936OS << " (NORETURN)]\n";5937else5938OS << "]\n";59395940if (ShowColors)5941OS.resetColor();59425943// Print the label of this block.5944if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) {5945if (print_edges)5946OS << " ";59475948if (LabelStmt *L = dyn_cast<LabelStmt>(Label))5949OS << L->getName();5950else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) {5951OS << "case ";5952if (const Expr *LHS = C->getLHS())5953LHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));5954if (const Expr *RHS = C->getRHS()) {5955OS << " ... ";5956RHS->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts()));5957}5958} else if (isa<DefaultStmt>(Label))5959OS << "default";5960else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {5961OS << "catch (";5962if (const VarDecl *ED = CS->getExceptionDecl())5963ED->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);5964else5965OS << "...";5966OS << ")";5967} else if (ObjCAtCatchStmt *CS = dyn_cast<ObjCAtCatchStmt>(Label)) {5968OS << "@catch (";5969if (const VarDecl *PD = CS->getCatchParamDecl())5970PD->print(OS, PrintingPolicy(Helper.getLangOpts()), 0);5971else5972OS << "...";5973OS << ")";5974} else if (SEHExceptStmt *ES = dyn_cast<SEHExceptStmt>(Label)) {5975OS << "__except (";5976ES->getFilterExpr()->printPretty(OS, &Helper,5977PrintingPolicy(Helper.getLangOpts()), 0);5978OS << ")";5979} else5980llvm_unreachable("Invalid label statement in CFGBlock.");59815982OS << ":\n";5983}59845985// Iterate through the statements in the block and print them.5986unsigned j = 1;59875988for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;5989I != E ; ++I, ++j ) {5990// Print the statement # in the basic block and the statement itself.5991if (print_edges)5992OS << " ";59935994OS << llvm::format("%3d", j) << ": ";59955996Helper.setStmtID(j);59975998print_elem(OS, Helper, *I);5999}60006001// Print the terminator of this block.6002if (B.getTerminator().isValid()) {6003if (ShowColors)6004OS.changeColor(raw_ostream::GREEN);60056006OS << " T: ";60076008Helper.setBlockID(-1);60096010PrintingPolicy PP(Helper.getLangOpts());6011CFGBlockTerminatorPrint TPrinter(OS, &Helper, PP);6012TPrinter.print(B.getTerminator());6013OS << '\n';60146015if (ShowColors)6016OS.resetColor();6017}60186019if (print_edges) {6020// Print the predecessors of this block.6021if (!B.pred_empty()) {6022const raw_ostream::Colors Color = raw_ostream::BLUE;6023if (ShowColors)6024OS.changeColor(Color);6025OS << " Preds " ;6026if (ShowColors)6027OS.resetColor();6028OS << '(' << B.pred_size() << "):";6029unsigned i = 0;60306031if (ShowColors)6032OS.changeColor(Color);60336034for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();6035I != E; ++I, ++i) {6036if (i % 10 == 8)6037OS << "\n ";60386039CFGBlock *B = *I;6040bool Reachable = true;6041if (!B) {6042Reachable = false;6043B = I->getPossiblyUnreachableBlock();6044}60456046OS << " B" << B->getBlockID();6047if (!Reachable)6048OS << "(Unreachable)";6049}60506051if (ShowColors)6052OS.resetColor();60536054OS << '\n';6055}60566057// Print the successors of this block.6058if (!B.succ_empty()) {6059const raw_ostream::Colors Color = raw_ostream::MAGENTA;6060if (ShowColors)6061OS.changeColor(Color);6062OS << " Succs ";6063if (ShowColors)6064OS.resetColor();6065OS << '(' << B.succ_size() << "):";6066unsigned i = 0;60676068if (ShowColors)6069OS.changeColor(Color);60706071for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();6072I != E; ++I, ++i) {6073if (i % 10 == 8)6074OS << "\n ";60756076CFGBlock *B = *I;60776078bool Reachable = true;6079if (!B) {6080Reachable = false;6081B = I->getPossiblyUnreachableBlock();6082}60836084if (B) {6085OS << " B" << B->getBlockID();6086if (!Reachable)6087OS << "(Unreachable)";6088}6089else {6090OS << " NULL";6091}6092}60936094if (ShowColors)6095OS.resetColor();6096OS << '\n';6097}6098}6099}61006101/// dump - A simple pretty printer of a CFG that outputs to stderr.6102void CFG::dump(const LangOptions &LO, bool ShowColors) const {6103print(llvm::errs(), LO, ShowColors);6104}61056106/// print - A simple pretty printer of a CFG that outputs to an ostream.6107void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const {6108StmtPrinterHelper Helper(this, LO);61096110// Print the entry block.6111print_block(OS, this, getEntry(), Helper, true, ShowColors);61126113// Iterate through the CFGBlocks and print them one by one.6114for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {6115// Skip the entry block, because we already printed it.6116if (&(**I) == &getEntry() || &(**I) == &getExit())6117continue;61186119print_block(OS, this, **I, Helper, true, ShowColors);6120}61216122// Print the exit block.6123print_block(OS, this, getExit(), Helper, true, ShowColors);6124OS << '\n';6125OS.flush();6126}61276128size_t CFGBlock::getIndexInCFG() const {6129return llvm::find(*getParent(), this) - getParent()->begin();6130}61316132/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.6133void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,6134bool ShowColors) const {6135print(llvm::errs(), cfg, LO, ShowColors);6136}61376138LLVM_DUMP_METHOD void CFGBlock::dump() const {6139dump(getParent(), LangOptions(), false);6140}61416142/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.6143/// Generally this will only be called from CFG::print.6144void CFGBlock::print(raw_ostream &OS, const CFG* cfg,6145const LangOptions &LO, bool ShowColors) const {6146StmtPrinterHelper Helper(cfg, LO);6147print_block(OS, cfg, *this, Helper, true, ShowColors);6148OS << '\n';6149}61506151/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.6152void CFGBlock::printTerminator(raw_ostream &OS,6153const LangOptions &LO) const {6154CFGBlockTerminatorPrint TPrinter(OS, nullptr, PrintingPolicy(LO));6155TPrinter.print(getTerminator());6156}61576158/// printTerminatorJson - Pretty-prints the terminator in JSON format.6159void CFGBlock::printTerminatorJson(raw_ostream &Out, const LangOptions &LO,6160bool AddQuotes) const {6161std::string Buf;6162llvm::raw_string_ostream TempOut(Buf);61636164printTerminator(TempOut, LO);61656166Out << JsonFormat(TempOut.str(), AddQuotes);6167}61686169// Returns true if by simply looking at the block, we can be sure that it6170// results in a sink during analysis. This is useful to know when the analysis6171// was interrupted, and we try to figure out if it would sink eventually.6172// There may be many more reasons why a sink would appear during analysis6173// (eg. checkers may generate sinks arbitrarily), but here we only consider6174// sinks that would be obvious by looking at the CFG.6175static bool isImmediateSinkBlock(const CFGBlock *Blk) {6176if (Blk->hasNoReturnElement())6177return true;61786179// FIXME: Throw-expressions are currently generating sinks during analysis:6180// they're not supported yet, and also often used for actually terminating6181// the program. So we should treat them as sinks in this analysis as well,6182// at least for now, but once we have better support for exceptions,6183// we'd need to carefully handle the case when the throw is being6184// immediately caught.6185if (llvm::any_of(*Blk, [](const CFGElement &Elm) {6186if (std::optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())6187if (isa<CXXThrowExpr>(StmtElm->getStmt()))6188return true;6189return false;6190}))6191return true;61926193return false;6194}61956196bool CFGBlock::isInevitablySinking() const {6197const CFG &Cfg = *getParent();61986199const CFGBlock *StartBlk = this;6200if (isImmediateSinkBlock(StartBlk))6201return true;62026203llvm::SmallVector<const CFGBlock *, 32> DFSWorkList;6204llvm::SmallPtrSet<const CFGBlock *, 32> Visited;62056206DFSWorkList.push_back(StartBlk);6207while (!DFSWorkList.empty()) {6208const CFGBlock *Blk = DFSWorkList.back();6209DFSWorkList.pop_back();6210Visited.insert(Blk);62116212// If at least one path reaches the CFG exit, it means that control is6213// returned to the caller. For now, say that we are not sure what6214// happens next. If necessary, this can be improved to analyze6215// the parent StackFrameContext's call site in a similar manner.6216if (Blk == &Cfg.getExit())6217return false;62186219for (const auto &Succ : Blk->succs()) {6220if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {6221if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {6222// If the block has reachable child blocks that aren't no-return,6223// add them to the worklist.6224DFSWorkList.push_back(SuccBlk);6225}6226}6227}6228}62296230// Nothing reached the exit. It can only mean one thing: there's no return.6231return true;6232}62336234const Expr *CFGBlock::getLastCondition() const {6235// If the terminator is a temporary dtor or a virtual base, etc, we can't6236// retrieve a meaningful condition, bail out.6237if (Terminator.getKind() != CFGTerminator::StmtBranch)6238return nullptr;62396240// Also, if this method was called on a block that doesn't have 2 successors,6241// this block doesn't have retrievable condition.6242if (succ_size() < 2)6243return nullptr;62446245// FIXME: Is there a better condition expression we can return in this case?6246if (size() == 0)6247return nullptr;62486249auto StmtElem = rbegin()->getAs<CFGStmt>();6250if (!StmtElem)6251return nullptr;62526253const Stmt *Cond = StmtElem->getStmt();6254if (isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))6255return nullptr;62566257// Only ObjCForCollectionStmt is known not to be a non-Expr terminator, hence6258// the cast<>.6259return cast<Expr>(Cond)->IgnoreParens();6260}62616262Stmt *CFGBlock::getTerminatorCondition(bool StripParens) {6263Stmt *Terminator = getTerminatorStmt();6264if (!Terminator)6265return nullptr;62666267Expr *E = nullptr;62686269switch (Terminator->getStmtClass()) {6270default:6271break;62726273case Stmt::CXXForRangeStmtClass:6274E = cast<CXXForRangeStmt>(Terminator)->getCond();6275break;62766277case Stmt::ForStmtClass:6278E = cast<ForStmt>(Terminator)->getCond();6279break;62806281case Stmt::WhileStmtClass:6282E = cast<WhileStmt>(Terminator)->getCond();6283break;62846285case Stmt::DoStmtClass:6286E = cast<DoStmt>(Terminator)->getCond();6287break;62886289case Stmt::IfStmtClass:6290E = cast<IfStmt>(Terminator)->getCond();6291break;62926293case Stmt::ChooseExprClass:6294E = cast<ChooseExpr>(Terminator)->getCond();6295break;62966297case Stmt::IndirectGotoStmtClass:6298E = cast<IndirectGotoStmt>(Terminator)->getTarget();6299break;63006301case Stmt::SwitchStmtClass:6302E = cast<SwitchStmt>(Terminator)->getCond();6303break;63046305case Stmt::BinaryConditionalOperatorClass:6306E = cast<BinaryConditionalOperator>(Terminator)->getCond();6307break;63086309case Stmt::ConditionalOperatorClass:6310E = cast<ConditionalOperator>(Terminator)->getCond();6311break;63126313case Stmt::BinaryOperatorClass: // '&&' and '||'6314E = cast<BinaryOperator>(Terminator)->getLHS();6315break;63166317case Stmt::ObjCForCollectionStmtClass:6318return Terminator;6319}63206321if (!StripParens)6322return E;63236324return E ? E->IgnoreParens() : nullptr;6325}63266327//===----------------------------------------------------------------------===//6328// CFG Graphviz Visualization6329//===----------------------------------------------------------------------===//63306331static StmtPrinterHelper *GraphHelper;63326333void CFG::viewCFG(const LangOptions &LO) const {6334StmtPrinterHelper H(this, LO);6335GraphHelper = &H;6336llvm::ViewGraph(this,"CFG");6337GraphHelper = nullptr;6338}63396340namespace llvm {63416342template<>6343struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {6344DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}63456346static std::string getNodeLabel(const CFGBlock *Node, const CFG *Graph) {6347std::string OutSStr;6348llvm::raw_string_ostream Out(OutSStr);6349print_block(Out,Graph, *Node, *GraphHelper, false, false);6350std::string& OutStr = Out.str();63516352if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());63536354// Process string output to make it nicer...6355for (unsigned i = 0; i != OutStr.length(); ++i)6356if (OutStr[i] == '\n') { // Left justify6357OutStr[i] = '\\';6358OutStr.insert(OutStr.begin()+i+1, 'l');6359}63606361return OutStr;6362}6363};63646365} // namespace llvm636663676368