brintos

brintos / llvm-project-archived public Read only

0
0
Text · 154.9 KiB · a759aee Raw
4162 lines · cpp
1//===- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file defines a meta-engine for path-sensitive dataflow analysis that10//  is built on CoreEngine, but provides the boilerplate to execute transfer11//  functions and build the ExplodedGraph at the expression level.12//13//===----------------------------------------------------------------------===//14 15#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"16#include "PrettyStackTraceLocationContext.h"17#include "clang/AST/ASTContext.h"18#include "clang/AST/Decl.h"19#include "clang/AST/DeclBase.h"20#include "clang/AST/DeclCXX.h"21#include "clang/AST/DeclObjC.h"22#include "clang/AST/Expr.h"23#include "clang/AST/ExprCXX.h"24#include "clang/AST/ExprObjC.h"25#include "clang/AST/ParentMap.h"26#include "clang/AST/PrettyPrinter.h"27#include "clang/AST/Stmt.h"28#include "clang/AST/StmtCXX.h"29#include "clang/AST/StmtObjC.h"30#include "clang/AST/Type.h"31#include "clang/Analysis/AnalysisDeclContext.h"32#include "clang/Analysis/CFG.h"33#include "clang/Analysis/ConstructionContext.h"34#include "clang/Analysis/ProgramPoint.h"35#include "clang/Basic/IdentifierTable.h"36#include "clang/Basic/JsonSupport.h"37#include "clang/Basic/LLVM.h"38#include "clang/Basic/LangOptions.h"39#include "clang/Basic/PrettyStackTrace.h"40#include "clang/Basic/SourceLocation.h"41#include "clang/Basic/Specifiers.h"42#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"43#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"44#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"45#include "clang/StaticAnalyzer/Core/CheckerManager.h"46#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"47#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"48#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"49#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"50#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"51#include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h"52#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"53#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"54#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"55#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"56#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"57#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"58#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"59#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"60#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"61#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"62#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"63#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"64#include "llvm/ADT/APSInt.h"65#include "llvm/ADT/DenseMap.h"66#include "llvm/ADT/ImmutableMap.h"67#include "llvm/ADT/ImmutableSet.h"68#include "llvm/ADT/STLExtras.h"69#include "llvm/ADT/SmallVector.h"70#include "llvm/Support/Casting.h"71#include "llvm/Support/Compiler.h"72#include "llvm/Support/DOTGraphTraits.h"73#include "llvm/Support/ErrorHandling.h"74#include "llvm/Support/GraphWriter.h"75#include "llvm/Support/TimeProfiler.h"76#include "llvm/Support/raw_ostream.h"77#include <cassert>78#include <cstdint>79#include <memory>80#include <optional>81#include <string>82#include <tuple>83#include <utility>84#include <vector>85 86using namespace clang;87using namespace ento;88 89#define DEBUG_TYPE "ExprEngine"90 91STAT_COUNTER(NumRemoveDeadBindings,92             "The # of times RemoveDeadBindings is called");93STAT_COUNTER(94    NumMaxBlockCountReached,95    "The # of aborted paths due to reaching the maximum block count in "96    "a top level function");97STAT_COUNTER(98    NumMaxBlockCountReachedInInlined,99    "The # of aborted paths due to reaching the maximum block count in "100    "an inlined function");101STAT_COUNTER(NumTimesRetriedWithoutInlining,102             "The # of times we re-evaluated a call without inlining");103 104//===----------------------------------------------------------------------===//105// Internal program state traits.106//===----------------------------------------------------------------------===//107 108namespace {109 110// When modeling a C++ constructor, for a variety of reasons we need to track111// the location of the object for the duration of its ConstructionContext.112// ObjectsUnderConstruction maps statements within the construction context113// to the object's location, so that on every such statement the location114// could have been retrieved.115 116/// ConstructedObjectKey is used for being able to find the path-sensitive117/// memory region of a freshly constructed object while modeling the AST node118/// that syntactically represents the object that is being constructed.119/// Semantics of such nodes may sometimes require access to the region that's120/// not otherwise present in the program state, or to the very fact that121/// the construction context was present and contained references to these122/// AST nodes.123class ConstructedObjectKey {124  using ConstructedObjectKeyImpl =125      std::pair<ConstructionContextItem, const LocationContext *>;126  const ConstructedObjectKeyImpl Impl;127 128public:129  explicit ConstructedObjectKey(const ConstructionContextItem &Item,130                       const LocationContext *LC)131      : Impl(Item, LC) {}132 133  const ConstructionContextItem &getItem() const { return Impl.first; }134  const LocationContext *getLocationContext() const { return Impl.second; }135 136  ASTContext &getASTContext() const {137    return getLocationContext()->getDecl()->getASTContext();138  }139 140  void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,141                 PrintingPolicy &PP) const {142    const Stmt *S = getItem().getStmtOrNull();143    const CXXCtorInitializer *I = nullptr;144    if (!S)145      I = getItem().getCXXCtorInitializer();146 147    if (S)148      Out << "\"stmt_id\": " << S->getID(getASTContext());149    else150      Out << "\"init_id\": " << I->getID(getASTContext());151 152    // Kind153    Out << ", \"kind\": \"" << getItem().getKindAsString()154        << "\", \"argument_index\": ";155 156    if (getItem().getKind() == ConstructionContextItem::ArgumentKind)157      Out << getItem().getIndex();158    else159      Out << "null";160 161    // Pretty-print162    Out << ", \"pretty\": ";163 164    if (S) {165      S->printJson(Out, Helper, PP, /*AddQuotes=*/true);166    } else {167      Out << '\"' << I->getAnyMember()->getDeclName() << '\"';168    }169  }170 171  void Profile(llvm::FoldingSetNodeID &ID) const {172    ID.Add(Impl.first);173    ID.AddPointer(Impl.second);174  }175 176  bool operator==(const ConstructedObjectKey &RHS) const {177    return Impl == RHS.Impl;178  }179 180  bool operator<(const ConstructedObjectKey &RHS) const {181    return Impl < RHS.Impl;182  }183};184} // namespace185 186typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>187    ObjectsUnderConstructionMap;188REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,189                                 ObjectsUnderConstructionMap)190 191// This trait is responsible for storing the index of the element that is to be192// constructed in the next iteration. As a result a CXXConstructExpr is only193// stored if it is array type. Also the index is the index of the continuous194// memory region, which is important for multi-dimensional arrays. E.g:: int195// arr[2][2]; assume arr[1][1] will be the next element under construction, so196// the index is 3.197typedef llvm::ImmutableMap<198    std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>199    IndexOfElementToConstructMap;200REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct,201                                 IndexOfElementToConstructMap)202 203// This trait is responsible for holding our pending ArrayInitLoopExprs.204// It pairs the LocationContext and the initializer CXXConstructExpr with205// the size of the array that's being copy initialized.206typedef llvm::ImmutableMap<207    std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>208    PendingInitLoopMap;209REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingInitLoop, PendingInitLoopMap)210 211typedef llvm::ImmutableMap<const LocationContext *, unsigned>212    PendingArrayDestructionMap;213REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction,214                                 PendingArrayDestructionMap)215 216//===----------------------------------------------------------------------===//217// Engine construction and deletion.218//===----------------------------------------------------------------------===//219 220static const char* TagProviderName = "ExprEngine";221 222ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,223                       AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,224                       FunctionSummariesTy *FS, InliningModes HowToInlineIn)225    : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),226      AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),227      Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),228      StateMgr(getContext(), mgr.getStoreManagerCreator(),229               mgr.getConstraintManagerCreator(), G.getAllocator(), this),230      SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),231      svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),232      BR(mgr, *this), VisitedCallees(VisitedCalleesIn),233      HowToInline(HowToInlineIn) {234  unsigned TrimInterval = mgr.options.GraphTrimInterval;235  if (TrimInterval != 0) {236    // Enable eager node reclamation when constructing the ExplodedGraph.237    G.enableNodeReclamation(TrimInterval);238  }239}240 241//===----------------------------------------------------------------------===//242// Utility methods.243//===----------------------------------------------------------------------===//244 245ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {246  ProgramStateRef state = StateMgr.getInitialState(InitLoc);247  const Decl *D = InitLoc->getDecl();248 249  // Preconditions.250  // FIXME: It would be nice if we had a more general mechanism to add251  // such preconditions.  Some day.252  do {253    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {254      // Precondition: the first argument of 'main' is an integer guaranteed255      //  to be > 0.256      const IdentifierInfo *II = FD->getIdentifier();257      if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))258        break;259 260      const ParmVarDecl *PD = FD->getParamDecl(0);261      QualType T = PD->getType();262      const auto *BT = dyn_cast<BuiltinType>(T);263      if (!BT || !BT->isInteger())264        break;265 266      const MemRegion *R = state->getRegion(PD, InitLoc);267      if (!R)268        break;269 270      SVal V = state->getSVal(loc::MemRegionVal(R));271      SVal Constraint_untested = evalBinOp(state, BO_GT, V,272                                           svalBuilder.makeZeroVal(T),273                                           svalBuilder.getConditionType());274 275      std::optional<DefinedOrUnknownSVal> Constraint =276          Constraint_untested.getAs<DefinedOrUnknownSVal>();277 278      if (!Constraint)279        break;280 281      if (ProgramStateRef newState = state->assume(*Constraint, true))282        state = newState;283    }284    break;285  }286  while (false);287 288  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {289    // Precondition: 'self' is always non-null upon entry to an Objective-C290    // method.291    const ImplicitParamDecl *SelfD = MD->getSelfDecl();292    const MemRegion *R = state->getRegion(SelfD, InitLoc);293    SVal V = state->getSVal(loc::MemRegionVal(R));294 295    if (std::optional<Loc> LV = V.getAs<Loc>()) {296      // Assume that the pointer value in 'self' is non-null.297      state = state->assume(*LV, true);298      assert(state && "'self' cannot be null");299    }300  }301 302  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {303    if (MD->isImplicitObjectMemberFunction()) {304      // Precondition: 'this' is always non-null upon entry to the305      // top-level function.  This is our starting assumption for306      // analyzing an "open" program.307      const StackFrameContext *SFC = InitLoc->getStackFrame();308      if (SFC->getParent() == nullptr) {309        loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);310        SVal V = state->getSVal(L);311        if (std::optional<Loc> LV = V.getAs<Loc>()) {312          state = state->assume(*LV, true);313          assert(state && "'this' cannot be null");314        }315      }316    }317  }318 319  return state;320}321 322ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(323    ProgramStateRef State, const LocationContext *LC,324    const Expr *InitWithAdjustments, const Expr *Result,325    const SubRegion **OutRegionWithAdjustments) {326  // FIXME: This function is a hack that works around the quirky AST327  // we're often having with respect to C++ temporaries. If only we modelled328  // the actual execution order of statements properly in the CFG,329  // all the hassle with adjustments would not be necessary,330  // and perhaps the whole function would be removed.331  SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);332  if (!Result) {333    // If we don't have an explicit result expression, we're in "if needed"334    // mode. Only create a region if the current value is a NonLoc.335    if (!isa<NonLoc>(InitValWithAdjustments)) {336      if (OutRegionWithAdjustments)337        *OutRegionWithAdjustments = nullptr;338      return State;339    }340    Result = InitWithAdjustments;341  } else {342    // We need to create a region no matter what. Make sure we don't try to343    // stuff a Loc into a non-pointer temporary region.344    assert(!isa<Loc>(InitValWithAdjustments) ||345           Loc::isLocType(Result->getType()) ||346           Result->getType()->isMemberPointerType());347  }348 349  ProgramStateManager &StateMgr = State->getStateManager();350  MemRegionManager &MRMgr = StateMgr.getRegionManager();351  StoreManager &StoreMgr = StateMgr.getStoreManager();352 353  // MaterializeTemporaryExpr may appear out of place, after a few field and354  // base-class accesses have been made to the object, even though semantically355  // it is the whole object that gets materialized and lifetime-extended.356  //357  // For example:358  //359  //   `-MaterializeTemporaryExpr360  //     `-MemberExpr361  //       `-CXXTemporaryObjectExpr362  //363  // instead of the more natural364  //365  //   `-MemberExpr366  //     `-MaterializeTemporaryExpr367  //       `-CXXTemporaryObjectExpr368  //369  // Use the usual methods for obtaining the expression of the base object,370  // and record the adjustments that we need to make to obtain the sub-object371  // that the whole expression 'Ex' refers to. This trick is usual,372  // in the sense that CodeGen takes a similar route.373 374  SmallVector<const Expr *, 2> CommaLHSs;375  SmallVector<SubobjectAdjustment, 2> Adjustments;376 377  const Expr *Init = InitWithAdjustments->skipRValueSubobjectAdjustments(378      CommaLHSs, Adjustments);379 380  // Take the region for Init, i.e. for the whole object. If we do not remember381  // the region in which the object originally was constructed, come up with382  // a new temporary region out of thin air and copy the contents of the object383  // (which are currently present in the Environment, because Init is an rvalue)384  // into that region. This is not correct, but it is better than nothing.385  const TypedValueRegion *TR = nullptr;386  if (const auto *MT = dyn_cast<MaterializeTemporaryExpr>(Result)) {387    if (std::optional<SVal> V = getObjectUnderConstruction(State, MT, LC)) {388      State = finishObjectConstruction(State, MT, LC);389      State = State->BindExpr(Result, LC, *V);390      return State;391    } else if (const ValueDecl *VD = MT->getExtendingDecl()) {392      StorageDuration SD = MT->getStorageDuration();393      assert(SD != SD_FullExpression);394      // If this object is bound to a reference with static storage duration, we395      // put it in a different region to prevent "address leakage" warnings.396      if (SD == SD_Static || SD == SD_Thread) {397        TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(Init, VD);398      } else {399        TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);400      }401    } else {402      assert(MT->getStorageDuration() == SD_FullExpression);403      TR = MRMgr.getCXXTempObjectRegion(Init, LC);404    }405  } else {406    TR = MRMgr.getCXXTempObjectRegion(Init, LC);407  }408 409  SVal Reg = loc::MemRegionVal(TR);410  SVal BaseReg = Reg;411 412  // Make the necessary adjustments to obtain the sub-object.413  for (const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {414    switch (Adj.Kind) {415    case SubobjectAdjustment::DerivedToBaseAdjustment:416      Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);417      break;418    case SubobjectAdjustment::FieldAdjustment:419      Reg = StoreMgr.getLValueField(Adj.Field, Reg);420      break;421    case SubobjectAdjustment::MemberPointerAdjustment:422      // FIXME: Unimplemented.423      State = State->invalidateRegions(Reg, getCFGElementRef(),424                                       currBldrCtx->blockCount(), LC, true,425                                       nullptr, nullptr, nullptr);426      return State;427    }428  }429 430  // What remains is to copy the value of the object to the new region.431  // FIXME: In other words, what we should always do is copy value of the432  // Init expression (which corresponds to the bigger object) to the whole433  // temporary region TR. However, this value is often no longer present434  // in the Environment. If it has disappeared, we instead invalidate TR.435  // Still, what we can do is assign the value of expression Ex (which436  // corresponds to the sub-object) to the TR's sub-region Reg. At least,437  // values inside Reg would be correct.438  SVal InitVal = State->getSVal(Init, LC);439  if (InitVal.isUnknown()) {440    InitVal = getSValBuilder().conjureSymbolVal(441        getCFGElementRef(), LC, Init->getType(), currBldrCtx->blockCount());442    State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);443 444    // Then we'd need to take the value that certainly exists and bind it445    // over.446    if (InitValWithAdjustments.isUnknown()) {447      // Try to recover some path sensitivity in case we couldn't448      // compute the value.449      InitValWithAdjustments = getSValBuilder().conjureSymbolVal(450          getCFGElementRef(), LC, InitWithAdjustments->getType(),451          currBldrCtx->blockCount());452    }453    State =454        State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false);455  } else {456    State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);457  }458 459  // The result expression would now point to the correct sub-region of the460  // newly created temporary region. Do this last in order to getSVal of Init461  // correctly in case (Result == Init).462  if (Result->isGLValue()) {463    State = State->BindExpr(Result, LC, Reg);464  } else {465    State = State->BindExpr(Result, LC, InitValWithAdjustments);466  }467 468  // Notify checkers once for two bindLoc()s.469  State = processRegionChange(State, TR, LC);470 471  if (OutRegionWithAdjustments)472    *OutRegionWithAdjustments = cast<SubRegion>(Reg.getAsRegion());473  return State;474}475 476ProgramStateRef ExprEngine::setIndexOfElementToConstruct(477    ProgramStateRef State, const CXXConstructExpr *E,478    const LocationContext *LCtx, unsigned Idx) {479  auto Key = std::make_pair(E, LCtx->getStackFrame());480 481  assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);482 483  return State->set<IndexOfElementToConstruct>(Key, Idx);484}485 486std::optional<unsigned>487ExprEngine::getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E,488                               const LocationContext *LCtx) {489  const unsigned *V = State->get<PendingInitLoop>({E, LCtx->getStackFrame()});490  return V ? std::make_optional(*V) : std::nullopt;491}492 493ProgramStateRef ExprEngine::removePendingInitLoop(ProgramStateRef State,494                                                  const CXXConstructExpr *E,495                                                  const LocationContext *LCtx) {496  auto Key = std::make_pair(E, LCtx->getStackFrame());497 498  assert(E && State->contains<PendingInitLoop>(Key));499  return State->remove<PendingInitLoop>(Key);500}501 502ProgramStateRef ExprEngine::setPendingInitLoop(ProgramStateRef State,503                                               const CXXConstructExpr *E,504                                               const LocationContext *LCtx,505                                               unsigned Size) {506  auto Key = std::make_pair(E, LCtx->getStackFrame());507 508  assert(!State->contains<PendingInitLoop>(Key) && Size > 0);509 510  return State->set<PendingInitLoop>(Key, Size);511}512 513std::optional<unsigned>514ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State,515                                         const CXXConstructExpr *E,516                                         const LocationContext *LCtx) {517  const unsigned *V =518      State->get<IndexOfElementToConstruct>({E, LCtx->getStackFrame()});519  return V ? std::make_optional(*V) : std::nullopt;520}521 522ProgramStateRef523ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,524                                            const CXXConstructExpr *E,525                                            const LocationContext *LCtx) {526  auto Key = std::make_pair(E, LCtx->getStackFrame());527 528  assert(E && State->contains<IndexOfElementToConstruct>(Key));529  return State->remove<IndexOfElementToConstruct>(Key);530}531 532std::optional<unsigned>533ExprEngine::getPendingArrayDestruction(ProgramStateRef State,534                                       const LocationContext *LCtx) {535  assert(LCtx && "LocationContext shouldn't be null!");536 537  const unsigned *V =538      State->get<PendingArrayDestruction>(LCtx->getStackFrame());539  return V ? std::make_optional(*V) : std::nullopt;540}541 542ProgramStateRef ExprEngine::setPendingArrayDestruction(543    ProgramStateRef State, const LocationContext *LCtx, unsigned Idx) {544  assert(LCtx && "LocationContext shouldn't be null!");545 546  auto Key = LCtx->getStackFrame();547 548  return State->set<PendingArrayDestruction>(Key, Idx);549}550 551ProgramStateRef552ExprEngine::removePendingArrayDestruction(ProgramStateRef State,553                                          const LocationContext *LCtx) {554  assert(LCtx && "LocationContext shouldn't be null!");555 556  auto Key = LCtx->getStackFrame();557 558  assert(LCtx && State->contains<PendingArrayDestruction>(Key));559  return State->remove<PendingArrayDestruction>(Key);560}561 562ProgramStateRef563ExprEngine::addObjectUnderConstruction(ProgramStateRef State,564                                       const ConstructionContextItem &Item,565                                       const LocationContext *LC, SVal V) {566  ConstructedObjectKey Key(Item, LC->getStackFrame());567 568  const Expr *Init = nullptr;569 570  if (auto DS = dyn_cast_or_null<DeclStmt>(Item.getStmtOrNull())) {571    if (auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))572      Init = VD->getInit();573  }574 575  if (auto LE = dyn_cast_or_null<LambdaExpr>(Item.getStmtOrNull()))576    Init = *(LE->capture_init_begin() + Item.getIndex());577 578  if (!Init && !Item.getStmtOrNull())579    Init = Item.getCXXCtorInitializer()->getInit();580 581  // In an ArrayInitLoopExpr the real initializer is returned by582  // getSubExpr(). Note that AILEs can be nested in case of583  // multidimesnional arrays.584  if (const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init))585    Init = extractElementInitializerFromNestedAILE(AILE);586 587  // FIXME: Currently the state might already contain the marker due to588  // incorrect handling of temporaries bound to default parameters.589  // The state will already contain the marker if we construct elements590  // in an array, as we visit the same statement multiple times before591  // the array declaration. The marker is removed when we exit the592  // constructor call.593  assert((!State->get<ObjectsUnderConstruction>(Key) ||594          Key.getItem().getKind() ==595              ConstructionContextItem::TemporaryDestructorKind ||596          State->contains<IndexOfElementToConstruct>(597              {dyn_cast_or_null<CXXConstructExpr>(Init), LC})) &&598         "The object is already marked as `UnderConstruction`, when it's not "599         "supposed to!");600  return State->set<ObjectsUnderConstruction>(Key, V);601}602 603std::optional<SVal>604ExprEngine::getObjectUnderConstruction(ProgramStateRef State,605                                       const ConstructionContextItem &Item,606                                       const LocationContext *LC) {607  ConstructedObjectKey Key(Item, LC->getStackFrame());608  const SVal *V = State->get<ObjectsUnderConstruction>(Key);609  return V ? std::make_optional(*V) : std::nullopt;610}611 612ProgramStateRef613ExprEngine::finishObjectConstruction(ProgramStateRef State,614                                     const ConstructionContextItem &Item,615                                     const LocationContext *LC) {616  ConstructedObjectKey Key(Item, LC->getStackFrame());617  assert(State->contains<ObjectsUnderConstruction>(Key));618  return State->remove<ObjectsUnderConstruction>(Key);619}620 621ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,622                                            const CXXBindTemporaryExpr *BTE,623                                            const LocationContext *LC) {624  ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);625  // FIXME: Currently the state might already contain the marker due to626  // incorrect handling of temporaries bound to default parameters.627  return State->set<ObjectsUnderConstruction>(Key, UnknownVal());628}629 630ProgramStateRef631ExprEngine::cleanupElidedDestructor(ProgramStateRef State,632                                    const CXXBindTemporaryExpr *BTE,633                                    const LocationContext *LC) {634  ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);635  assert(State->contains<ObjectsUnderConstruction>(Key));636  return State->remove<ObjectsUnderConstruction>(Key);637}638 639bool ExprEngine::isDestructorElided(ProgramStateRef State,640                                    const CXXBindTemporaryExpr *BTE,641                                    const LocationContext *LC) {642  ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);643  return State->contains<ObjectsUnderConstruction>(Key);644}645 646bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,647                                               const LocationContext *FromLC,648                                               const LocationContext *ToLC) {649  const LocationContext *LC = FromLC;650  while (LC != ToLC) {651    assert(LC && "ToLC must be a parent of FromLC!");652    for (auto I : State->get<ObjectsUnderConstruction>())653      if (I.first.getLocationContext() == LC)654        return false;655 656    LC = LC->getParent();657  }658  return true;659}660 661 662//===----------------------------------------------------------------------===//663// Top-level transfer function logic (Dispatcher).664//===----------------------------------------------------------------------===//665 666/// evalAssume - Called by ConstraintManager. Used to call checker-specific667///  logic for handling assumptions on symbolic values.668ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,669                                              SVal cond, bool assumption) {670  return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);671}672 673ProgramStateRef674ExprEngine::processRegionChanges(ProgramStateRef state,675                                 const InvalidatedSymbols *invalidated,676                                 ArrayRef<const MemRegion *> Explicits,677                                 ArrayRef<const MemRegion *> Regions,678                                 const LocationContext *LCtx,679                                 const CallEvent *Call) {680  return getCheckerManager().runCheckersForRegionChanges(state, invalidated,681                                                         Explicits, Regions,682                                                         LCtx, Call);683}684 685static void686printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,687                                  const char *NL, const LocationContext *LCtx,688                                  unsigned int Space = 0, bool IsDot = false) {689  PrintingPolicy PP =690      LCtx->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();691 692  ++Space;693  bool HasItem = false;694 695  // Store the last key.696  const ConstructedObjectKey *LastKey = nullptr;697  for (const auto &I : State->get<ObjectsUnderConstruction>()) {698    const ConstructedObjectKey &Key = I.first;699    if (Key.getLocationContext() != LCtx)700      continue;701 702    if (!HasItem) {703      Out << '[' << NL;704      HasItem = true;705    }706 707    LastKey = &Key;708  }709 710  for (const auto &I : State->get<ObjectsUnderConstruction>()) {711    const ConstructedObjectKey &Key = I.first;712    SVal Value = I.second;713    if (Key.getLocationContext() != LCtx)714      continue;715 716    Indent(Out, Space, IsDot) << "{ ";717    Key.printJson(Out, nullptr, PP);718    Out << ", \"value\": \"" << Value << "\" }";719 720    if (&Key != LastKey)721      Out << ',';722    Out << NL;723  }724 725  if (HasItem)726    Indent(Out, --Space, IsDot) << ']'; // End of "location_context".727  else {728    Out << "null ";729  }730}731 732static void printIndicesOfElementsToConstructJson(733    raw_ostream &Out, ProgramStateRef State, const char *NL,734    const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {735  using KeyT = std::pair<const Expr *, const LocationContext *>;736 737  const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();738  PrintingPolicy PP = Context.getPrintingPolicy();739 740  ++Space;741  bool HasItem = false;742 743  // Store the last key.744  KeyT LastKey;745  for (const auto &I : State->get<IndexOfElementToConstruct>()) {746    const KeyT &Key = I.first;747    if (Key.second != LCtx)748      continue;749 750    if (!HasItem) {751      Out << '[' << NL;752      HasItem = true;753    }754 755    LastKey = Key;756  }757 758  for (const auto &I : State->get<IndexOfElementToConstruct>()) {759    const KeyT &Key = I.first;760    unsigned Value = I.second;761    if (Key.second != LCtx)762      continue;763 764    Indent(Out, Space, IsDot) << "{ ";765 766    // Expr767    const Expr *E = Key.first;768    Out << "\"stmt_id\": " << E->getID(Context);769 770    // Kind771    Out << ", \"kind\": null";772 773    // Pretty-print774    Out << ", \"pretty\": ";775    Out << "\"" << E->getStmtClassName() << ' '776        << E->getSourceRange().printToString(Context.getSourceManager()) << " '"777        << QualType::getAsString(E->getType().split(), PP);778    Out << "'\"";779 780    Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";781 782    if (Key != LastKey)783      Out << ',';784    Out << NL;785  }786 787  if (HasItem)788    Indent(Out, --Space, IsDot) << ']'; // End of "location_context".789  else {790    Out << "null ";791  }792}793 794static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State,795                                     const char *NL,796                                     const LocationContext *LCtx,797                                     unsigned int Space = 0,798                                     bool IsDot = false) {799  using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;800 801  const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();802  PrintingPolicy PP = Context.getPrintingPolicy();803 804  ++Space;805  bool HasItem = false;806 807  // Store the last key.808  KeyT LastKey;809  for (const auto &I : State->get<PendingInitLoop>()) {810    const KeyT &Key = I.first;811    if (Key.second != LCtx)812      continue;813 814    if (!HasItem) {815      Out << '[' << NL;816      HasItem = true;817    }818 819    LastKey = Key;820  }821 822  for (const auto &I : State->get<PendingInitLoop>()) {823    const KeyT &Key = I.first;824    unsigned Value = I.second;825    if (Key.second != LCtx)826      continue;827 828    Indent(Out, Space, IsDot) << "{ ";829 830    const CXXConstructExpr *E = Key.first;831    Out << "\"stmt_id\": " << E->getID(Context);832 833    Out << ", \"kind\": null";834    Out << ", \"pretty\": ";835    Out << '\"' << E->getStmtClassName() << ' '836        << E->getSourceRange().printToString(Context.getSourceManager()) << " '"837        << QualType::getAsString(E->getType().split(), PP);838    Out << "'\"";839 840    Out << ", \"value\": \"Flattened size: " << Value << "\"}";841 842    if (Key != LastKey)843      Out << ',';844    Out << NL;845  }846 847  if (HasItem)848    Indent(Out, --Space, IsDot) << ']'; // End of "location_context".849  else {850    Out << "null ";851  }852}853 854static void855printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State,856                                  const char *NL, const LocationContext *LCtx,857                                  unsigned int Space = 0, bool IsDot = false) {858  using KeyT = const LocationContext *;859 860  ++Space;861  bool HasItem = false;862 863  // Store the last key.864  KeyT LastKey = nullptr;865  for (const auto &I : State->get<PendingArrayDestruction>()) {866    const KeyT &Key = I.first;867    if (Key != LCtx)868      continue;869 870    if (!HasItem) {871      Out << '[' << NL;872      HasItem = true;873    }874 875    LastKey = Key;876  }877 878  for (const auto &I : State->get<PendingArrayDestruction>()) {879    const KeyT &Key = I.first;880    if (Key != LCtx)881      continue;882 883    Indent(Out, Space, IsDot) << "{ ";884 885    Out << "\"stmt_id\": null";886    Out << ", \"kind\": null";887    Out << ", \"pretty\": \"Current index: \"";888    Out << ", \"value\": \"" << I.second << "\" }";889 890    if (Key != LastKey)891      Out << ',';892    Out << NL;893  }894 895  if (HasItem)896    Indent(Out, --Space, IsDot) << ']'; // End of "location_context".897  else {898    Out << "null ";899  }900}901 902/// A helper function to generalize program state trait printing.903/// The function invokes Printer as 'Printer(Out, State, NL, LC, Space, IsDot,904/// std::forward<Args>(args)...)'. \n One possible type for Printer is905/// 'void()(raw_ostream &, ProgramStateRef, const char *, const LocationContext906/// *, unsigned int, bool, ...)' \n \param Trait The state trait to be printed.907/// \param Printer A void function that prints Trait.908/// \param Args An additional parameter pack that is passed to Print upon909/// invocation.910template <typename Trait, typename Printer, typename... Args>911static void printStateTraitWithLocationContextJson(912    raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx,913    const char *NL, unsigned int Space, bool IsDot,914    const char *jsonPropertyName, Printer printer, Args &&...args) {915 916  using RequiredType =917      void (*)(raw_ostream &, ProgramStateRef, const char *,918               const LocationContext *, unsigned int, bool, Args &&...);919 920  // Try to do as much compile time checking as possible.921  // FIXME: check for invocable instead of function?922  static_assert(std::is_function_v<std::remove_pointer_t<Printer>>,923                "Printer is not a function!");924  static_assert(std::is_convertible_v<Printer, RequiredType>,925                "Printer doesn't have the required type!");926 927  if (LCtx && !State->get<Trait>().isEmpty()) {928    Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";929    ++Space;930    Out << '[' << NL;931    LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {932      printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);933    });934 935    --Space;936    Indent(Out, Space, IsDot) << "]," << NL; // End of "jsonPropertyName".937  }938}939 940void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,941                           const LocationContext *LCtx, const char *NL,942                           unsigned int Space, bool IsDot) const {943 944  printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(945      Out, State, LCtx, NL, Space, IsDot, "constructing_objects",946      printObjectsUnderConstructionJson);947  printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(948      Out, State, LCtx, NL, Space, IsDot, "index_of_element",949      printIndicesOfElementsToConstructJson);950  printStateTraitWithLocationContextJson<PendingInitLoop>(951      Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",952      printPendingInitLoopJson);953  printStateTraitWithLocationContextJson<PendingArrayDestruction>(954      Out, State, LCtx, NL, Space, IsDot, "pending_destructors",955      printPendingArrayDestructionsJson);956 957  getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,958                                                   IsDot);959}960 961void ExprEngine::processEndWorklist() {962  // This prints the name of the top-level function if we crash.963  PrettyStackTraceLocationContext CrashInfo(getRootLocationContext());964  getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);965}966 967void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,968                                   unsigned StmtIdx, NodeBuilderContext *Ctx) {969  currStmtIdx = StmtIdx;970  currBldrCtx = Ctx;971 972  switch (E.getKind()) {973    case CFGElement::Statement:974    case CFGElement::Constructor:975    case CFGElement::CXXRecordTypedCall:976      ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);977      return;978    case CFGElement::Initializer:979      ProcessInitializer(E.castAs<CFGInitializer>(), Pred);980      return;981    case CFGElement::NewAllocator:982      ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),983                          Pred);984      return;985    case CFGElement::AutomaticObjectDtor:986    case CFGElement::DeleteDtor:987    case CFGElement::BaseDtor:988    case CFGElement::MemberDtor:989    case CFGElement::TemporaryDtor:990      ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);991      return;992    case CFGElement::LoopExit:993      ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);994      return;995    case CFGElement::LifetimeEnds:996    case CFGElement::CleanupFunction:997    case CFGElement::ScopeBegin:998    case CFGElement::ScopeEnd:999      return;1000  }1001}1002 1003static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,1004                                     const Stmt *S,1005                                     const ExplodedNode *Pred,1006                                     const LocationContext *LC) {1007  // Are we never purging state values?1008  if (AMgr.options.AnalysisPurgeOpt == PurgeNone)1009    return false;1010 1011  // Is this the beginning of a basic block?1012  if (Pred->getLocation().getAs<BlockEntrance>())1013    return true;1014 1015  // Is this on a non-expression?1016  if (!isa<Expr>(S))1017    return true;1018 1019  // Run before processing a call.1020  if (CallEvent::isCallStmt(S))1021    return true;1022 1023  // Is this an expression that is consumed by another expression?  If so,1024  // postpone cleaning out the state.1025  ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap();1026  return !PM.isConsumedExpr(cast<Expr>(S));1027}1028 1029void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,1030                            const Stmt *ReferenceStmt,1031                            const LocationContext *LC,1032                            const Stmt *DiagnosticStmt,1033                            ProgramPoint::Kind K) {1034  llvm::TimeTraceScope TimeScope("ExprEngine::removeDead");1035  assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||1036          ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))1037          && "PostStmt is not generally supported by the SymbolReaper yet");1038  assert(LC && "Must pass the current (or expiring) LocationContext");1039 1040  if (!DiagnosticStmt) {1041    DiagnosticStmt = ReferenceStmt;1042    assert(DiagnosticStmt && "Required for clearing a LocationContext");1043  }1044 1045  NumRemoveDeadBindings++;1046  ProgramStateRef CleanedState = Pred->getState();1047 1048  // LC is the location context being destroyed, but SymbolReaper wants a1049  // location context that is still live. (If this is the top-level stack1050  // frame, this will be null.)1051  if (!ReferenceStmt) {1052    assert(K == ProgramPoint::PostStmtPurgeDeadSymbolsKind &&1053           "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");1054    LC = LC->getParent();1055  }1056 1057  const StackFrameContext *SFC = LC ? LC->getStackFrame() : nullptr;1058  SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());1059 1060  for (auto I : CleanedState->get<ObjectsUnderConstruction>()) {1061    if (SymbolRef Sym = I.second.getAsSymbol())1062      SymReaper.markLive(Sym);1063    if (const MemRegion *MR = I.second.getAsRegion())1064      SymReaper.markLive(MR);1065  }1066 1067  getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);1068 1069  // Create a state in which dead bindings are removed from the environment1070  // and the store. TODO: The function should just return new env and store,1071  // not a new state.1072  CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(1073      CleanedState, SFC, SymReaper);1074 1075  // Process any special transfer function for dead symbols.1076  // Call checkers with the non-cleaned state so that they could query the1077  // values of the soon to be dead symbols.1078  ExplodedNodeSet CheckedSet;1079  getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,1080                                                DiagnosticStmt, *this, K);1081 1082  // Extend lifetime of symbols used for dynamic extent while the parent region1083  // is live. In this way size information about memory allocations is not lost1084  // if the region remains live.1085  markAllDynamicExtentLive(CleanedState, SymReaper);1086 1087  // For each node in CheckedSet, generate CleanedNodes that have the1088  // environment, the store, and the constraints cleaned up but have the1089  // user-supplied states as the predecessors.1090  StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);1091  for (const auto I : CheckedSet) {1092    ProgramStateRef CheckerState = I->getState();1093 1094    // The constraint manager has not been cleaned up yet, so clean up now.1095    CheckerState =1096        getConstraintManager().removeDeadBindings(CheckerState, SymReaper);1097 1098    assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&1099           "Checkers are not allowed to modify the Environment as a part of "1100           "checkDeadSymbols processing.");1101    assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&1102           "Checkers are not allowed to modify the Store as a part of "1103           "checkDeadSymbols processing.");1104 1105    // Create a state based on CleanedState with CheckerState GDM and1106    // generate a transition to that state.1107    ProgramStateRef CleanedCheckerSt =1108        StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);1109    Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, cleanupNodeTag(), K);1110  }1111}1112 1113const ProgramPointTag *ExprEngine::cleanupNodeTag() {1114  static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");1115  return &cleanupTag;1116}1117 1118void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {1119  // Reclaim any unnecessary nodes in the ExplodedGraph.1120  G.reclaimRecentlyAllocatedNodes();1121 1122  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),1123                                currStmt->getBeginLoc(),1124                                "Error evaluating statement");1125 1126  // Remove dead bindings and symbols.1127  ExplodedNodeSet CleanedStates;1128  if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,1129                               Pred->getLocationContext())) {1130    removeDead(Pred, CleanedStates, currStmt,1131                                    Pred->getLocationContext());1132  } else1133    CleanedStates.Add(Pred);1134 1135  // Visit the statement.1136  ExplodedNodeSet Dst;1137  for (const auto I : CleanedStates) {1138    ExplodedNodeSet DstI;1139    // Visit the statement.1140    Visit(currStmt, I, DstI);1141    Dst.insert(DstI);1142  }1143 1144  // Enqueue the new nodes onto the work list.1145  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);1146}1147 1148void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {1149  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),1150                                S->getBeginLoc(),1151                                "Error evaluating end of the loop");1152  ExplodedNodeSet Dst;1153  Dst.Add(Pred);1154  NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1155  ProgramStateRef NewState = Pred->getState();1156 1157  if(AMgr.options.ShouldUnrollLoops)1158    NewState = processLoopEnd(S, NewState);1159 1160  LoopExit PP(S, Pred->getLocationContext());1161  Bldr.generateNode(PP, NewState, Pred);1162  // Enqueue the new nodes onto the work list.1163  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);1164}1165 1166void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,1167                                    ExplodedNode *Pred) {1168  const CXXCtorInitializer *BMI = CFGInit.getInitializer();1169  const Expr *Init = BMI->getInit()->IgnoreImplicit();1170  const LocationContext *LC = Pred->getLocationContext();1171 1172  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),1173                                BMI->getSourceLocation(),1174                                "Error evaluating initializer");1175 1176  // We don't clean up dead bindings here.1177  const auto *stackFrame = cast<StackFrameContext>(Pred->getLocationContext());1178  const auto *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());1179 1180  ProgramStateRef State = Pred->getState();1181  SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));1182 1183  ExplodedNodeSet Tmp;1184  SVal FieldLoc;1185 1186  // Evaluate the initializer, if necessary1187  if (BMI->isAnyMemberInitializer()) {1188    // Constructors build the object directly in the field,1189    // but non-objects must be copied in from the initializer.1190    if (getObjectUnderConstruction(State, BMI, LC)) {1191      // The field was directly constructed, so there is no need to bind.1192      // But we still need to stop tracking the object under construction.1193      State = finishObjectConstruction(State, BMI, LC);1194      NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);1195      PostStore PS(Init, LC, /*Loc*/ nullptr, /*tag*/ nullptr);1196      Bldr.generateNode(PS, State, Pred);1197    } else {1198      const ValueDecl *Field;1199      if (BMI->isIndirectMemberInitializer()) {1200        Field = BMI->getIndirectMember();1201        FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);1202      } else {1203        Field = BMI->getMember();1204        FieldLoc = State->getLValue(BMI->getMember(), thisVal);1205      }1206 1207      SVal InitVal;1208      if (Init->getType()->isArrayType()) {1209        // Handle arrays of trivial type. We can represent this with a1210        // primitive load/copy from the base array region.1211        const ArraySubscriptExpr *ASE;1212        while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))1213          Init = ASE->getBase()->IgnoreImplicit();1214 1215        InitVal = State->getSVal(Init, stackFrame);1216 1217        // If we fail to get the value for some reason, use a symbolic value.1218        if (InitVal.isUnknownOrUndef()) {1219          SValBuilder &SVB = getSValBuilder();1220          InitVal =1221              SVB.conjureSymbolVal(getCFGElementRef(), stackFrame,1222                                   Field->getType(), currBldrCtx->blockCount());1223        }1224      } else {1225        InitVal = State->getSVal(BMI->getInit(), stackFrame);1226      }1227 1228      PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);1229      evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);1230    }1231  } else if (BMI->isBaseInitializer() && isa<InitListExpr>(Init)) {1232    // When the base class is initialized with an initialization list and the1233    // base class does not have a ctor, there will not be a CXXConstructExpr to1234    // initialize the base region. Hence, we need to make the bind for it.1235    SVal BaseLoc = getStoreManager().evalDerivedToBase(1236        thisVal, QualType(BMI->getBaseClass(), 0), BMI->isBaseVirtual());1237    SVal InitVal = State->getSVal(Init, stackFrame);1238    evalBind(Tmp, Init, Pred, BaseLoc, InitVal, /*isInit=*/true);1239  } else {1240    assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());1241    Tmp.insert(Pred);1242    // We already did all the work when visiting the CXXConstructExpr.1243  }1244 1245  // Construct PostInitializer nodes whether the state changed or not,1246  // so that the diagnostics don't get confused.1247  PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);1248  ExplodedNodeSet Dst;1249  NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);1250  for (const auto I : Tmp) {1251    ProgramStateRef State = I->getState();1252    Bldr.generateNode(PP, State, I);1253  }1254 1255  // Enqueue the new nodes onto the work list.1256  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);1257}1258 1259std::pair<ProgramStateRef, uint64_t>1260ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,1261                                            const MemRegion *Region,1262                                            const QualType &ElementTy,1263                                            const LocationContext *LCtx,1264                                            SVal *ElementCountVal) {1265  assert(Region != nullptr && "Not-null region expected");1266 1267  QualType Ty = ElementTy.getDesugaredType(getContext());1268  while (const auto *NTy = dyn_cast<ArrayType>(Ty))1269    Ty = NTy->getElementType().getDesugaredType(getContext());1270 1271  auto ElementCount = getDynamicElementCount(State, Region, svalBuilder, Ty);1272 1273  if (ElementCountVal)1274    *ElementCountVal = ElementCount;1275 1276  // Note: the destructors are called in reverse order.1277  unsigned Idx = 0;1278  if (auto OptionalIdx = getPendingArrayDestruction(State, LCtx)) {1279    Idx = *OptionalIdx;1280  } else {1281    // The element count is either unknown, or an SVal that's not an integer.1282    if (!ElementCount.isConstant())1283      return {State, 0};1284 1285    Idx = ElementCount.getAsInteger()->getLimitedValue();1286  }1287 1288  if (Idx == 0)1289    return {State, 0};1290 1291  --Idx;1292 1293  return {setPendingArrayDestruction(State, LCtx, Idx), Idx};1294}1295 1296void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,1297                                     ExplodedNode *Pred) {1298  ExplodedNodeSet Dst;1299  switch (D.getKind()) {1300  case CFGElement::AutomaticObjectDtor:1301    ProcessAutomaticObjDtor(D.castAs<CFGAutomaticObjDtor>(), Pred, Dst);1302    break;1303  case CFGElement::BaseDtor:1304    ProcessBaseDtor(D.castAs<CFGBaseDtor>(), Pred, Dst);1305    break;1306  case CFGElement::MemberDtor:1307    ProcessMemberDtor(D.castAs<CFGMemberDtor>(), Pred, Dst);1308    break;1309  case CFGElement::TemporaryDtor:1310    ProcessTemporaryDtor(D.castAs<CFGTemporaryDtor>(), Pred, Dst);1311    break;1312  case CFGElement::DeleteDtor:1313    ProcessDeleteDtor(D.castAs<CFGDeleteDtor>(), Pred, Dst);1314    break;1315  default:1316    llvm_unreachable("Unexpected dtor kind.");1317  }1318 1319  // Enqueue the new nodes onto the work list.1320  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);1321}1322 1323void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,1324                                     ExplodedNode *Pred) {1325  ExplodedNodeSet Dst;1326  AnalysisManager &AMgr = getAnalysisManager();1327  AnalyzerOptions &Opts = AMgr.options;1328  // TODO: We're not evaluating allocators for all cases just yet as1329  // we're not handling the return value correctly, which causes false1330  // positives when the alpha.cplusplus.NewDeleteLeaks check is on.1331  if (Opts.MayInlineCXXAllocator)1332    VisitCXXNewAllocatorCall(NE, Pred, Dst);1333  else {1334    NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1335    const LocationContext *LCtx = Pred->getLocationContext();1336    PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,1337                        getCFGElementRef());1338    Bldr.generateNode(PP, Pred->getState(), Pred);1339  }1340  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);1341}1342 1343void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,1344                                         ExplodedNode *Pred,1345                                         ExplodedNodeSet &Dst) {1346  const auto *DtorDecl = Dtor.getDestructorDecl(getContext());1347  const VarDecl *varDecl = Dtor.getVarDecl();1348  QualType varType = varDecl->getType();1349 1350  ProgramStateRef state = Pred->getState();1351  const LocationContext *LCtx = Pred->getLocationContext();1352 1353  SVal dest = state->getLValue(varDecl, LCtx);1354  const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();1355 1356  if (varType->isReferenceType()) {1357    const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();1358    if (!ValueRegion) {1359      // FIXME: This should not happen. The language guarantees a presence1360      // of a valid initializer here, so the reference shall not be undefined.1361      // It seems that we're calling destructors over variables that1362      // were not initialized yet.1363      return;1364    }1365    Region = ValueRegion->getBaseRegion();1366    varType = cast<TypedValueRegion>(Region)->getValueType();1367  }1368 1369  unsigned Idx = 0;1370  if (isa<ArrayType>(varType)) {1371    SVal ElementCount;1372    std::tie(state, Idx) = prepareStateForArrayDestruction(1373        state, Region, varType, LCtx, &ElementCount);1374 1375    if (ElementCount.isConstant()) {1376      uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();1377      assert(ArrayLength &&1378             "An automatic dtor for a 0 length array shouldn't be triggered!");1379 1380      // Still handle this case if we don't have assertions enabled.1381      if (!ArrayLength) {1382        static SimpleProgramPointTag PT(1383            "ExprEngine", "Skipping automatic 0 length array destruction, "1384                          "which shouldn't be in the CFG.");1385        PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx,1386                            getCFGElementRef(), &PT);1387        NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1388        Bldr.generateSink(PP, Pred->getState(), Pred);1389        return;1390      }1391    }1392  }1393 1394  EvalCallOptions CallOpts;1395  Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,1396                             CallOpts.IsArrayCtorOrDtor, Idx)1397               .getAsRegion();1398 1399  NodeBuilder Bldr(Pred, Dst, getBuilderContext());1400 1401  static SimpleProgramPointTag PT("ExprEngine",1402                                  "Prepare for object destruction");1403  PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, getCFGElementRef(),1404                     &PT);1405  Pred = Bldr.generateNode(PP, state, Pred);1406 1407  if (!Pred)1408    return;1409  Bldr.takeNodes(Pred);1410 1411  VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(),1412                     /*IsBase=*/false, Pred, Dst, CallOpts);1413}1414 1415void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,1416                                   ExplodedNode *Pred,1417                                   ExplodedNodeSet &Dst) {1418  ProgramStateRef State = Pred->getState();1419  const LocationContext *LCtx = Pred->getLocationContext();1420  const CXXDeleteExpr *DE = Dtor.getDeleteExpr();1421  const Stmt *Arg = DE->getArgument();1422  QualType DTy = DE->getDestroyedType();1423  SVal ArgVal = State->getSVal(Arg, LCtx);1424 1425  // If the argument to delete is known to be a null value,1426  // don't run destructor.1427  if (State->isNull(ArgVal).isConstrainedTrue()) {1428    QualType BTy = getContext().getBaseElementType(DTy);1429    const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();1430    const CXXDestructorDecl *Dtor = RD->getDestructor();1431 1432    PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx, getCFGElementRef());1433    NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1434    Bldr.generateNode(PP, Pred->getState(), Pred);1435    return;1436  }1437 1438  auto getDtorDecl = [](const QualType &DTy) {1439    const CXXRecordDecl *RD = DTy->getAsCXXRecordDecl();1440    return RD->getDestructor();1441  };1442 1443  unsigned Idx = 0;1444  EvalCallOptions CallOpts;1445  const MemRegion *ArgR = ArgVal.getAsRegion();1446 1447  if (DE->isArrayForm()) {1448    CallOpts.IsArrayCtorOrDtor = true;1449    // Yes, it may even be a multi-dimensional array.1450    while (const auto *AT = getContext().getAsArrayType(DTy))1451      DTy = AT->getElementType();1452 1453    if (ArgR) {1454      SVal ElementCount;1455      std::tie(State, Idx) = prepareStateForArrayDestruction(1456          State, ArgR, DTy, LCtx, &ElementCount);1457 1458      // If we're about to destruct a 0 length array, don't run any of the1459      // destructors.1460      if (ElementCount.isConstant() &&1461          ElementCount.getAsInteger()->getLimitedValue() == 0) {1462 1463        static SimpleProgramPointTag PT(1464            "ExprEngine", "Skipping 0 length array delete destruction");1465        PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,1466                            getCFGElementRef(), &PT);1467        NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1468        Bldr.generateNode(PP, Pred->getState(), Pred);1469        return;1470      }1471 1472      ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)1473                 .getAsRegion();1474    }1475  }1476 1477  NodeBuilder Bldr(Pred, Dst, getBuilderContext());1478  static SimpleProgramPointTag PT("ExprEngine",1479                                  "Prepare for object destruction");1480  PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,1481                     getCFGElementRef(), &PT);1482  Pred = Bldr.generateNode(PP, State, Pred);1483 1484  if (!Pred)1485    return;1486  Bldr.takeNodes(Pred);1487 1488  VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);1489}1490 1491void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,1492                                 ExplodedNode *Pred, ExplodedNodeSet &Dst) {1493  const LocationContext *LCtx = Pred->getLocationContext();1494 1495  const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());1496  Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,1497                                            LCtx->getStackFrame());1498  SVal ThisVal = Pred->getState()->getSVal(ThisPtr);1499 1500  // Create the base object region.1501  const CXXBaseSpecifier *Base = D.getBaseSpecifier();1502  QualType BaseTy = Base->getType();1503  SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,1504                                                     Base->isVirtual());1505 1506  EvalCallOptions CallOpts;1507  VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),1508                     /*IsBase=*/true, Pred, Dst, CallOpts);1509}1510 1511void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,1512                                   ExplodedNode *Pred, ExplodedNodeSet &Dst) {1513  const auto *DtorDecl = D.getDestructorDecl(getContext());1514  const FieldDecl *Member = D.getFieldDecl();1515  QualType T = Member->getType();1516  ProgramStateRef State = Pred->getState();1517  const LocationContext *LCtx = Pred->getLocationContext();1518 1519  const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());1520  Loc ThisStorageLoc =1521      getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());1522  Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();1523  SVal FieldVal = State->getLValue(Member, ThisLoc);1524 1525  unsigned Idx = 0;1526  if (isa<ArrayType>(T)) {1527    SVal ElementCount;1528    std::tie(State, Idx) = prepareStateForArrayDestruction(1529        State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);1530 1531    if (ElementCount.isConstant()) {1532      uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();1533      assert(ArrayLength &&1534             "A member dtor for a 0 length array shouldn't be triggered!");1535 1536      // Still handle this case if we don't have assertions enabled.1537      if (!ArrayLength) {1538        static SimpleProgramPointTag PT(1539            "ExprEngine", "Skipping member 0 length array destruction, which "1540                          "shouldn't be in the CFG.");1541        PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx,1542                            getCFGElementRef(), &PT);1543        NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1544        Bldr.generateSink(PP, Pred->getState(), Pred);1545        return;1546      }1547    }1548  }1549 1550  EvalCallOptions CallOpts;1551  FieldVal =1552      makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);1553 1554  NodeBuilder Bldr(Pred, Dst, getBuilderContext());1555 1556  static SimpleProgramPointTag PT("ExprEngine",1557                                  "Prepare for object destruction");1558  PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, getCFGElementRef(),1559                     &PT);1560  Pred = Bldr.generateNode(PP, State, Pred);1561 1562  if (!Pred)1563    return;1564  Bldr.takeNodes(Pred);1565 1566  VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(),1567                     /*IsBase=*/false, Pred, Dst, CallOpts);1568}1569 1570void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,1571                                      ExplodedNode *Pred,1572                                      ExplodedNodeSet &Dst) {1573  const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr();1574  ProgramStateRef State = Pred->getState();1575  const LocationContext *LC = Pred->getLocationContext();1576  const MemRegion *MR = nullptr;1577 1578  if (std::optional<SVal> V = getObjectUnderConstruction(1579          State, D.getBindTemporaryExpr(), Pred->getLocationContext())) {1580    // FIXME: Currently we insert temporary destructors for default parameters,1581    // but we don't insert the constructors, so the entry in1582    // ObjectsUnderConstruction may be missing.1583    State = finishObjectConstruction(State, D.getBindTemporaryExpr(),1584                                     Pred->getLocationContext());1585    MR = V->getAsRegion();1586  }1587 1588  // If copy elision has occurred, and the constructor corresponding to the1589  // destructor was elided, we need to skip the destructor as well.1590  if (isDestructorElided(State, BTE, LC)) {1591    State = cleanupElidedDestructor(State, BTE, LC);1592    NodeBuilder Bldr(Pred, Dst, *currBldrCtx);1593    PostImplicitCall PP(D.getDestructorDecl(getContext()),1594                        D.getBindTemporaryExpr()->getBeginLoc(),1595                        Pred->getLocationContext(), getCFGElementRef());1596    Bldr.generateNode(PP, State, Pred);1597    return;1598  }1599 1600  ExplodedNodeSet CleanDtorState;1601  StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);1602  StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);1603 1604  QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();1605  // FIXME: Currently CleanDtorState can be empty here due to temporaries being1606  // bound to default parameters.1607  assert(CleanDtorState.size() <= 1);1608  ExplodedNode *CleanPred =1609      CleanDtorState.empty() ? Pred : *CleanDtorState.begin();1610 1611  EvalCallOptions CallOpts;1612  CallOpts.IsTemporaryCtorOrDtor = true;1613  if (!MR) {1614    // FIXME: If we have no MR, we still need to unwrap the array to avoid1615    // destroying the whole array at once.1616    //1617    // For this case there is no universal solution as there is no way to1618    // directly create an array of temporary objects. There are some expressions1619    // however which can create temporary objects and have an array type.1620    //1621    // E.g.: std::initializer_list<S>{S(), S()};1622    //1623    // The expression above has a type of 'const struct S[2]' but it's a single1624    // 'std::initializer_list<>'. The destructors of the 2 temporary 'S()'1625    // objects will be called anyway, because they are 2 separate objects in 21626    // separate clusters, i.e.: not an array.1627    //1628    // Now the 'std::initializer_list<>' is not an array either even though it1629    // has the type of an array. The point is, we only want to invoke the1630    // destructor for the initializer list once not twice or so.1631    while (const ArrayType *AT = getContext().getAsArrayType(T)) {1632      T = AT->getElementType();1633 1634      // FIXME: Enable this flag once we handle this case properly.1635      // CallOpts.IsArrayCtorOrDtor = true;1636    }1637  } else {1638    // FIXME: We'd eventually need to makeElementRegion() trick here,1639    // but for now we don't have the respective construction contexts,1640    // so MR would always be null in this case. Do nothing for now.1641  }1642  VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),1643                     /*IsBase=*/false, CleanPred, Dst, CallOpts);1644}1645 1646void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,1647                                               NodeBuilderContext &BldCtx,1648                                               ExplodedNode *Pred,1649                                               ExplodedNodeSet &Dst,1650                                               const CFGBlock *DstT,1651                                               const CFGBlock *DstF) {1652  BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);1653  ProgramStateRef State = Pred->getState();1654  const LocationContext *LC = Pred->getLocationContext();1655  if (getObjectUnderConstruction(State, BTE, LC)) {1656    TempDtorBuilder.generateNode(State, true, Pred);1657  } else {1658    TempDtorBuilder.generateNode(State, false, Pred);1659  }1660}1661 1662void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,1663                                           ExplodedNodeSet &PreVisit,1664                                           ExplodedNodeSet &Dst) {1665  // This is a fallback solution in case we didn't have a construction1666  // context when we were constructing the temporary. Otherwise the map should1667  // have been populated there.1668  if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {1669    // In case we don't have temporary destructors in the CFG, do not mark1670    // the initialization - we would otherwise never clean it up.1671    Dst = PreVisit;1672    return;1673  }1674  StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);1675  for (ExplodedNode *Node : PreVisit) {1676    ProgramStateRef State = Node->getState();1677    const LocationContext *LC = Node->getLocationContext();1678    if (!getObjectUnderConstruction(State, BTE, LC)) {1679      // FIXME: Currently the state might also already contain the marker due to1680      // incorrect handling of temporaries bound to default parameters; for1681      // those, we currently skip the CXXBindTemporaryExpr but rely on adding1682      // temporary destructor nodes.1683      State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());1684    }1685    StmtBldr.generateNode(BTE, Node, State);1686  }1687}1688 1689ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,1690                                         ArrayRef<SVal> Vs,1691                                         PointerEscapeKind K,1692                                         const CallEvent *Call) const {1693  class CollectReachableSymbolsCallback final : public SymbolVisitor {1694    InvalidatedSymbols &Symbols;1695 1696  public:1697    explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)1698        : Symbols(Symbols) {}1699 1700    const InvalidatedSymbols &getSymbols() const { return Symbols; }1701 1702    bool VisitSymbol(SymbolRef Sym) override {1703      Symbols.insert(Sym);1704      return true;1705    }1706  };1707  InvalidatedSymbols Symbols;1708  CollectReachableSymbolsCallback CallBack(Symbols);1709  for (SVal V : Vs)1710    State->scanReachableSymbols(V, CallBack);1711 1712  return getCheckerManager().runCheckersForPointerEscape(1713      State, CallBack.getSymbols(), Call, K, nullptr);1714}1715 1716void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,1717                       ExplodedNodeSet &DstTop) {1718  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),1719                                S->getBeginLoc(), "Error evaluating statement");1720  ExplodedNodeSet Dst;1721  StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);1722 1723  assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());1724 1725  switch (S->getStmtClass()) {1726    // C++, OpenMP and ARC stuff we don't support yet.1727    case Stmt::CXXDependentScopeMemberExprClass:1728    case Stmt::CXXTryStmtClass:1729    case Stmt::CXXTypeidExprClass:1730    case Stmt::CXXUuidofExprClass:1731    case Stmt::CXXFoldExprClass:1732    case Stmt::MSPropertyRefExprClass:1733    case Stmt::MSPropertySubscriptExprClass:1734    case Stmt::CXXUnresolvedConstructExprClass:1735    case Stmt::DependentScopeDeclRefExprClass:1736    case Stmt::ArrayTypeTraitExprClass:1737    case Stmt::ExpressionTraitExprClass:1738    case Stmt::UnresolvedLookupExprClass:1739    case Stmt::UnresolvedMemberExprClass:1740    case Stmt::RecoveryExprClass:1741    case Stmt::CXXNoexceptExprClass:1742    case Stmt::PackExpansionExprClass:1743    case Stmt::PackIndexingExprClass:1744    case Stmt::SubstNonTypeTemplateParmPackExprClass:1745    case Stmt::FunctionParmPackExprClass:1746    case Stmt::CoroutineBodyStmtClass:1747    case Stmt::CoawaitExprClass:1748    case Stmt::DependentCoawaitExprClass:1749    case Stmt::CoreturnStmtClass:1750    case Stmt::CoyieldExprClass:1751    case Stmt::SEHTryStmtClass:1752    case Stmt::SEHExceptStmtClass:1753    case Stmt::SEHLeaveStmtClass:1754    case Stmt::SEHFinallyStmtClass:1755    case Stmt::OMPCanonicalLoopClass:1756    case Stmt::OMPParallelDirectiveClass:1757    case Stmt::OMPSimdDirectiveClass:1758    case Stmt::OMPForDirectiveClass:1759    case Stmt::OMPForSimdDirectiveClass:1760    case Stmt::OMPSectionsDirectiveClass:1761    case Stmt::OMPSectionDirectiveClass:1762    case Stmt::OMPScopeDirectiveClass:1763    case Stmt::OMPSingleDirectiveClass:1764    case Stmt::OMPMasterDirectiveClass:1765    case Stmt::OMPCriticalDirectiveClass:1766    case Stmt::OMPParallelForDirectiveClass:1767    case Stmt::OMPParallelForSimdDirectiveClass:1768    case Stmt::OMPParallelSectionsDirectiveClass:1769    case Stmt::OMPParallelMasterDirectiveClass:1770    case Stmt::OMPParallelMaskedDirectiveClass:1771    case Stmt::OMPTaskDirectiveClass:1772    case Stmt::OMPTaskyieldDirectiveClass:1773    case Stmt::OMPBarrierDirectiveClass:1774    case Stmt::OMPTaskwaitDirectiveClass:1775    case Stmt::OMPErrorDirectiveClass:1776    case Stmt::OMPTaskgroupDirectiveClass:1777    case Stmt::OMPFlushDirectiveClass:1778    case Stmt::OMPDepobjDirectiveClass:1779    case Stmt::OMPScanDirectiveClass:1780    case Stmt::OMPOrderedDirectiveClass:1781    case Stmt::OMPAtomicDirectiveClass:1782    case Stmt::OMPAssumeDirectiveClass:1783    case Stmt::OMPTargetDirectiveClass:1784    case Stmt::OMPTargetDataDirectiveClass:1785    case Stmt::OMPTargetEnterDataDirectiveClass:1786    case Stmt::OMPTargetExitDataDirectiveClass:1787    case Stmt::OMPTargetParallelDirectiveClass:1788    case Stmt::OMPTargetParallelForDirectiveClass:1789    case Stmt::OMPTargetUpdateDirectiveClass:1790    case Stmt::OMPTeamsDirectiveClass:1791    case Stmt::OMPCancellationPointDirectiveClass:1792    case Stmt::OMPCancelDirectiveClass:1793    case Stmt::OMPTaskLoopDirectiveClass:1794    case Stmt::OMPTaskLoopSimdDirectiveClass:1795    case Stmt::OMPMasterTaskLoopDirectiveClass:1796    case Stmt::OMPMaskedTaskLoopDirectiveClass:1797    case Stmt::OMPMasterTaskLoopSimdDirectiveClass:1798    case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:1799    case Stmt::OMPParallelMasterTaskLoopDirectiveClass:1800    case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:1801    case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:1802    case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:1803    case Stmt::OMPDistributeDirectiveClass:1804    case Stmt::OMPDistributeParallelForDirectiveClass:1805    case Stmt::OMPDistributeParallelForSimdDirectiveClass:1806    case Stmt::OMPDistributeSimdDirectiveClass:1807    case Stmt::OMPTargetParallelForSimdDirectiveClass:1808    case Stmt::OMPTargetSimdDirectiveClass:1809    case Stmt::OMPTeamsDistributeDirectiveClass:1810    case Stmt::OMPTeamsDistributeSimdDirectiveClass:1811    case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:1812    case Stmt::OMPTeamsDistributeParallelForDirectiveClass:1813    case Stmt::OMPTargetTeamsDirectiveClass:1814    case Stmt::OMPTargetTeamsDistributeDirectiveClass:1815    case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:1816    case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:1817    case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:1818    case Stmt::OMPReverseDirectiveClass:1819    case Stmt::OMPStripeDirectiveClass:1820    case Stmt::OMPTileDirectiveClass:1821    case Stmt::OMPInterchangeDirectiveClass:1822    case Stmt::OMPFuseDirectiveClass:1823    case Stmt::OMPInteropDirectiveClass:1824    case Stmt::OMPDispatchDirectiveClass:1825    case Stmt::OMPMaskedDirectiveClass:1826    case Stmt::OMPGenericLoopDirectiveClass:1827    case Stmt::OMPTeamsGenericLoopDirectiveClass:1828    case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:1829    case Stmt::OMPParallelGenericLoopDirectiveClass:1830    case Stmt::OMPTargetParallelGenericLoopDirectiveClass:1831    case Stmt::CapturedStmtClass:1832    case Stmt::SYCLKernelCallStmtClass:1833    case Stmt::OpenACCComputeConstructClass:1834    case Stmt::OpenACCLoopConstructClass:1835    case Stmt::OpenACCCombinedConstructClass:1836    case Stmt::OpenACCDataConstructClass:1837    case Stmt::OpenACCEnterDataConstructClass:1838    case Stmt::OpenACCExitDataConstructClass:1839    case Stmt::OpenACCHostDataConstructClass:1840    case Stmt::OpenACCWaitConstructClass:1841    case Stmt::OpenACCCacheConstructClass:1842    case Stmt::OpenACCInitConstructClass:1843    case Stmt::OpenACCShutdownConstructClass:1844    case Stmt::OpenACCSetConstructClass:1845    case Stmt::OpenACCUpdateConstructClass:1846    case Stmt::OpenACCAtomicConstructClass:1847    case Stmt::OMPUnrollDirectiveClass:1848    case Stmt::OMPMetaDirectiveClass:1849    case Stmt::HLSLOutArgExprClass: {1850      const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());1851      Engine.addAbortedBlock(node, currBldrCtx->getBlock());1852      break;1853    }1854 1855    case Stmt::ParenExprClass:1856      llvm_unreachable("ParenExprs already handled.");1857    case Stmt::GenericSelectionExprClass:1858      llvm_unreachable("GenericSelectionExprs already handled.");1859    // Cases that should never be evaluated simply because they shouldn't1860    // appear in the CFG.1861    case Stmt::BreakStmtClass:1862    case Stmt::CaseStmtClass:1863    case Stmt::CompoundStmtClass:1864    case Stmt::ContinueStmtClass:1865    case Stmt::CXXForRangeStmtClass:1866    case Stmt::DefaultStmtClass:1867    case Stmt::DoStmtClass:1868    case Stmt::ForStmtClass:1869    case Stmt::GotoStmtClass:1870    case Stmt::IfStmtClass:1871    case Stmt::IndirectGotoStmtClass:1872    case Stmt::LabelStmtClass:1873    case Stmt::NoStmtClass:1874    case Stmt::NullStmtClass:1875    case Stmt::SwitchStmtClass:1876    case Stmt::WhileStmtClass:1877    case Expr::MSDependentExistsStmtClass:1878      llvm_unreachable("Stmt should not be in analyzer evaluation loop");1879    case Stmt::ImplicitValueInitExprClass:1880      // These nodes are shared in the CFG and would case caching out.1881      // Moreover, no additional evaluation required for them, the1882      // analyzer can reconstruct these values from the AST.1883      llvm_unreachable("Should be pruned from CFG");1884 1885    case Stmt::ObjCSubscriptRefExprClass:1886    case Stmt::ObjCPropertyRefExprClass:1887      llvm_unreachable("These are handled by PseudoObjectExpr");1888 1889    case Stmt::GNUNullExprClass: {1890      // GNU __null is a pointer-width integer, not an actual pointer.1891      ProgramStateRef state = Pred->getState();1892      state = state->BindExpr(1893          S, Pred->getLocationContext(),1894          svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));1895      Bldr.generateNode(S, Pred, state);1896      break;1897    }1898 1899    case Stmt::ObjCAtSynchronizedStmtClass:1900      Bldr.takeNodes(Pred);1901      VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);1902      Bldr.addNodes(Dst);1903      break;1904 1905    case Expr::ConstantExprClass:1906    case Stmt::ExprWithCleanupsClass:1907      // Handled due to fully linearised CFG.1908      break;1909 1910    case Stmt::CXXBindTemporaryExprClass: {1911      Bldr.takeNodes(Pred);1912      ExplodedNodeSet PreVisit;1913      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);1914      ExplodedNodeSet Next;1915      VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);1916      getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);1917      Bldr.addNodes(Dst);1918      break;1919    }1920 1921    case Stmt::ArrayInitLoopExprClass:1922      Bldr.takeNodes(Pred);1923      VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);1924      Bldr.addNodes(Dst);1925      break;1926    // Cases not handled yet; but will handle some day.1927    case Stmt::DesignatedInitExprClass:1928    case Stmt::DesignatedInitUpdateExprClass:1929    case Stmt::ArrayInitIndexExprClass:1930    case Stmt::ExtVectorElementExprClass:1931    case Stmt::ImaginaryLiteralClass:1932    case Stmt::ObjCAtCatchStmtClass:1933    case Stmt::ObjCAtFinallyStmtClass:1934    case Stmt::ObjCAtTryStmtClass:1935    case Stmt::ObjCAutoreleasePoolStmtClass:1936    case Stmt::ObjCEncodeExprClass:1937    case Stmt::ObjCIsaExprClass:1938    case Stmt::ObjCProtocolExprClass:1939    case Stmt::ObjCSelectorExprClass:1940    case Stmt::ParenListExprClass:1941    case Stmt::ShuffleVectorExprClass:1942    case Stmt::ConvertVectorExprClass:1943    case Stmt::VAArgExprClass:1944    case Stmt::CUDAKernelCallExprClass:1945    case Stmt::OpaqueValueExprClass:1946    case Stmt::AsTypeExprClass:1947    case Stmt::ConceptSpecializationExprClass:1948    case Stmt::CXXRewrittenBinaryOperatorClass:1949    case Stmt::RequiresExprClass:1950    case Stmt::EmbedExprClass:1951      // Fall through.1952 1953    // Cases we intentionally don't evaluate, since they don't need1954    // to be explicitly evaluated.1955    case Stmt::PredefinedExprClass:1956    case Stmt::AddrLabelExprClass:1957    case Stmt::IntegerLiteralClass:1958    case Stmt::FixedPointLiteralClass:1959    case Stmt::CharacterLiteralClass:1960    case Stmt::CXXScalarValueInitExprClass:1961    case Stmt::CXXBoolLiteralExprClass:1962    case Stmt::ObjCBoolLiteralExprClass:1963    case Stmt::ObjCAvailabilityCheckExprClass:1964    case Stmt::FloatingLiteralClass:1965    case Stmt::NoInitExprClass:1966    case Stmt::SizeOfPackExprClass:1967    case Stmt::StringLiteralClass:1968    case Stmt::SourceLocExprClass:1969    case Stmt::ObjCStringLiteralClass:1970    case Stmt::CXXPseudoDestructorExprClass:1971    case Stmt::SubstNonTypeTemplateParmExprClass:1972    case Stmt::CXXNullPtrLiteralExprClass:1973    case Stmt::ArraySectionExprClass:1974    case Stmt::OMPArrayShapingExprClass:1975    case Stmt::OMPIteratorExprClass:1976    case Stmt::SYCLUniqueStableNameExprClass:1977    case Stmt::OpenACCAsteriskSizeExprClass:1978    case Stmt::TypeTraitExprClass: {1979      Bldr.takeNodes(Pred);1980      ExplodedNodeSet preVisit;1981      getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);1982      getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);1983      Bldr.addNodes(Dst);1984      break;1985    }1986 1987    case Stmt::AttributedStmtClass: {1988      Bldr.takeNodes(Pred);1989      VisitAttributedStmt(cast<AttributedStmt>(S), Pred, Dst);1990      Bldr.addNodes(Dst);1991      break;1992    }1993 1994    case Stmt::CXXDefaultArgExprClass:1995    case Stmt::CXXDefaultInitExprClass: {1996      Bldr.takeNodes(Pred);1997      ExplodedNodeSet PreVisit;1998      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);1999 2000      ExplodedNodeSet Tmp;2001      StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);2002 2003      const Expr *ArgE;2004      if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))2005        ArgE = DefE->getExpr();2006      else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))2007        ArgE = DefE->getExpr();2008      else2009        llvm_unreachable("unknown constant wrapper kind");2010 2011      bool IsTemporary = false;2012      if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {2013        ArgE = MTE->getSubExpr();2014        IsTemporary = true;2015      }2016 2017      std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);2018      if (!ConstantVal)2019        ConstantVal = UnknownVal();2020 2021      const LocationContext *LCtx = Pred->getLocationContext();2022      for (const auto I : PreVisit) {2023        ProgramStateRef State = I->getState();2024        State = State->BindExpr(S, LCtx, *ConstantVal);2025        if (IsTemporary)2026          State = createTemporaryRegionIfNeeded(State, LCtx,2027                                                cast<Expr>(S),2028                                                cast<Expr>(S));2029        Bldr2.generateNode(S, I, State);2030      }2031 2032      getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);2033      Bldr.addNodes(Dst);2034      break;2035    }2036 2037    // Cases we evaluate as opaque expressions, conjuring a symbol.2038    case Stmt::CXXStdInitializerListExprClass:2039    case Expr::ObjCArrayLiteralClass:2040    case Expr::ObjCDictionaryLiteralClass:2041    case Expr::ObjCBoxedExprClass: {2042      Bldr.takeNodes(Pred);2043 2044      ExplodedNodeSet preVisit;2045      getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);2046 2047      ExplodedNodeSet Tmp;2048      StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);2049 2050      const auto *Ex = cast<Expr>(S);2051      QualType resultType = Ex->getType();2052 2053      for (const auto N : preVisit) {2054        const LocationContext *LCtx = N->getLocationContext();2055        SVal result = svalBuilder.conjureSymbolVal(2056            /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,2057            currBldrCtx->blockCount());2058        ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);2059 2060        // Escape pointers passed into the list, unless it's an ObjC boxed2061        // expression which is not a boxable C structure.2062        if (!(isa<ObjCBoxedExpr>(Ex) &&2063              !cast<ObjCBoxedExpr>(Ex)->getSubExpr()2064                                      ->getType()->isRecordType()))2065          for (auto Child : Ex->children()) {2066            assert(Child);2067            SVal Val = State->getSVal(Child, LCtx);2068            State = escapeValues(State, Val, PSK_EscapeOther);2069          }2070 2071        Bldr2.generateNode(S, N, State);2072      }2073 2074      getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);2075      Bldr.addNodes(Dst);2076      break;2077    }2078 2079    case Stmt::ArraySubscriptExprClass:2080      Bldr.takeNodes(Pred);2081      VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);2082      Bldr.addNodes(Dst);2083      break;2084 2085    case Stmt::MatrixSubscriptExprClass:2086      llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");2087      break;2088 2089    case Stmt::GCCAsmStmtClass: {2090      Bldr.takeNodes(Pred);2091      ExplodedNodeSet PreVisit;2092      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);2093      ExplodedNodeSet PostVisit;2094      for (ExplodedNode *const N : PreVisit)2095        VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);2096      getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);2097      Bldr.addNodes(Dst);2098      break;2099    }2100 2101    case Stmt::MSAsmStmtClass:2102      Bldr.takeNodes(Pred);2103      VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);2104      Bldr.addNodes(Dst);2105      break;2106 2107    case Stmt::BlockExprClass:2108      Bldr.takeNodes(Pred);2109      VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);2110      Bldr.addNodes(Dst);2111      break;2112 2113    case Stmt::LambdaExprClass:2114      if (AMgr.options.ShouldInlineLambdas) {2115        Bldr.takeNodes(Pred);2116        VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);2117        Bldr.addNodes(Dst);2118      } else {2119        const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());2120        Engine.addAbortedBlock(node, currBldrCtx->getBlock());2121      }2122      break;2123 2124    case Stmt::BinaryOperatorClass: {2125      const auto *B = cast<BinaryOperator>(S);2126      if (B->isLogicalOp()) {2127        Bldr.takeNodes(Pred);2128        VisitLogicalExpr(B, Pred, Dst);2129        Bldr.addNodes(Dst);2130        break;2131      }2132      else if (B->getOpcode() == BO_Comma) {2133        ProgramStateRef state = Pred->getState();2134        Bldr.generateNode(B, Pred,2135                          state->BindExpr(B, Pred->getLocationContext(),2136                                          state->getSVal(B->getRHS(),2137                                                  Pred->getLocationContext())));2138        break;2139      }2140 2141      Bldr.takeNodes(Pred);2142 2143      if (AMgr.options.ShouldEagerlyAssume &&2144          (B->isRelationalOp() || B->isEqualityOp())) {2145        ExplodedNodeSet Tmp;2146        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);2147        evalEagerlyAssumeBifurcation(Dst, Tmp, cast<Expr>(S));2148      }2149      else2150        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);2151 2152      Bldr.addNodes(Dst);2153      break;2154    }2155 2156    case Stmt::CXXOperatorCallExprClass: {2157      const auto *OCE = cast<CXXOperatorCallExpr>(S);2158 2159      // For instance method operators, make sure the 'this' argument has a2160      // valid region.2161      const Decl *Callee = OCE->getCalleeDecl();2162      if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {2163        if (MD->isImplicitObjectMemberFunction()) {2164          ProgramStateRef State = Pred->getState();2165          const LocationContext *LCtx = Pred->getLocationContext();2166          ProgramStateRef NewState =2167            createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));2168          if (NewState != State) {2169            Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,2170                                     ProgramPoint::PreStmtKind);2171            // Did we cache out?2172            if (!Pred)2173              break;2174          }2175        }2176      }2177      [[fallthrough]];2178    }2179 2180    case Stmt::CallExprClass:2181    case Stmt::CXXMemberCallExprClass:2182    case Stmt::UserDefinedLiteralClass:2183      Bldr.takeNodes(Pred);2184      VisitCallExpr(cast<CallExpr>(S), Pred, Dst);2185      Bldr.addNodes(Dst);2186      break;2187 2188    case Stmt::CXXCatchStmtClass:2189      Bldr.takeNodes(Pred);2190      VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);2191      Bldr.addNodes(Dst);2192      break;2193 2194    case Stmt::CXXTemporaryObjectExprClass:2195    case Stmt::CXXConstructExprClass:2196      Bldr.takeNodes(Pred);2197      VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);2198      Bldr.addNodes(Dst);2199      break;2200 2201    case Stmt::CXXInheritedCtorInitExprClass:2202      Bldr.takeNodes(Pred);2203      VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,2204                                    Dst);2205      Bldr.addNodes(Dst);2206      break;2207 2208    case Stmt::CXXNewExprClass: {2209      Bldr.takeNodes(Pred);2210 2211      ExplodedNodeSet PreVisit;2212      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);2213 2214      ExplodedNodeSet PostVisit;2215      for (const auto i : PreVisit)2216        VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);2217 2218      getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);2219      Bldr.addNodes(Dst);2220      break;2221    }2222 2223    case Stmt::CXXDeleteExprClass: {2224      Bldr.takeNodes(Pred);2225      ExplodedNodeSet PreVisit;2226      const auto *CDE = cast<CXXDeleteExpr>(S);2227      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);2228      ExplodedNodeSet PostVisit;2229      getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);2230 2231      for (const auto i : PostVisit)2232        VisitCXXDeleteExpr(CDE, i, Dst);2233 2234      Bldr.addNodes(Dst);2235      break;2236    }2237      // FIXME: ChooseExpr is really a constant.  We need to fix2238      //        the CFG do not model them as explicit control-flow.2239 2240    case Stmt::ChooseExprClass: { // __builtin_choose_expr2241      Bldr.takeNodes(Pred);2242      const auto *C = cast<ChooseExpr>(S);2243      VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);2244      Bldr.addNodes(Dst);2245      break;2246    }2247 2248    case Stmt::CompoundAssignOperatorClass:2249      Bldr.takeNodes(Pred);2250      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);2251      Bldr.addNodes(Dst);2252      break;2253 2254    case Stmt::CompoundLiteralExprClass:2255      Bldr.takeNodes(Pred);2256      VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);2257      Bldr.addNodes(Dst);2258      break;2259 2260    case Stmt::BinaryConditionalOperatorClass:2261    case Stmt::ConditionalOperatorClass: { // '?' operator2262      Bldr.takeNodes(Pred);2263      const auto *C = cast<AbstractConditionalOperator>(S);2264      VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);2265      Bldr.addNodes(Dst);2266      break;2267    }2268 2269    case Stmt::CXXThisExprClass:2270      Bldr.takeNodes(Pred);2271      VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);2272      Bldr.addNodes(Dst);2273      break;2274 2275    case Stmt::DeclRefExprClass: {2276      Bldr.takeNodes(Pred);2277      const auto *DE = cast<DeclRefExpr>(S);2278      VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);2279      Bldr.addNodes(Dst);2280      break;2281    }2282 2283    case Stmt::DeclStmtClass:2284      Bldr.takeNodes(Pred);2285      VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);2286      Bldr.addNodes(Dst);2287      break;2288 2289    case Stmt::ImplicitCastExprClass:2290    case Stmt::CStyleCastExprClass:2291    case Stmt::CXXStaticCastExprClass:2292    case Stmt::CXXDynamicCastExprClass:2293    case Stmt::CXXReinterpretCastExprClass:2294    case Stmt::CXXConstCastExprClass:2295    case Stmt::CXXFunctionalCastExprClass:2296    case Stmt::BuiltinBitCastExprClass:2297    case Stmt::ObjCBridgedCastExprClass:2298    case Stmt::CXXAddrspaceCastExprClass: {2299      Bldr.takeNodes(Pred);2300      const auto *C = cast<CastExpr>(S);2301      ExplodedNodeSet dstExpr;2302      VisitCast(C, C->getSubExpr(), Pred, dstExpr);2303 2304      // Handle the postvisit checks.2305      getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);2306      Bldr.addNodes(Dst);2307      break;2308    }2309 2310    case Expr::MaterializeTemporaryExprClass: {2311      Bldr.takeNodes(Pred);2312      const auto *MTE = cast<MaterializeTemporaryExpr>(S);2313      ExplodedNodeSet dstPrevisit;2314      getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);2315      ExplodedNodeSet dstExpr;2316      for (const auto i : dstPrevisit)2317        CreateCXXTemporaryObject(MTE, i, dstExpr);2318      getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);2319      Bldr.addNodes(Dst);2320      break;2321    }2322 2323    case Stmt::InitListExprClass: {2324      const InitListExpr *E = cast<InitListExpr>(S);2325      Bldr.takeNodes(Pred);2326      ConstructInitList(E, E->inits(), E->isTransparent(), Pred, Dst);2327      Bldr.addNodes(Dst);2328      break;2329    }2330 2331    case Expr::CXXParenListInitExprClass: {2332      const CXXParenListInitExpr *E = cast<CXXParenListInitExpr>(S);2333      Bldr.takeNodes(Pred);2334      ConstructInitList(E, E->getInitExprs(), /*IsTransparent*/ false, Pred,2335                        Dst);2336      Bldr.addNodes(Dst);2337      break;2338    }2339 2340    case Stmt::MemberExprClass:2341      Bldr.takeNodes(Pred);2342      VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);2343      Bldr.addNodes(Dst);2344      break;2345 2346    case Stmt::AtomicExprClass:2347      Bldr.takeNodes(Pred);2348      VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);2349      Bldr.addNodes(Dst);2350      break;2351 2352    case Stmt::ObjCIvarRefExprClass:2353      Bldr.takeNodes(Pred);2354      VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);2355      Bldr.addNodes(Dst);2356      break;2357 2358    case Stmt::ObjCForCollectionStmtClass:2359      Bldr.takeNodes(Pred);2360      VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);2361      Bldr.addNodes(Dst);2362      break;2363 2364    case Stmt::ObjCMessageExprClass:2365      Bldr.takeNodes(Pred);2366      VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);2367      Bldr.addNodes(Dst);2368      break;2369 2370    case Stmt::ObjCAtThrowStmtClass:2371    case Stmt::CXXThrowExprClass:2372      // FIXME: This is not complete.  We basically treat @throw as2373      // an abort.2374      Bldr.generateSink(S, Pred, Pred->getState());2375      break;2376 2377    case Stmt::ReturnStmtClass:2378      Bldr.takeNodes(Pred);2379      VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);2380      Bldr.addNodes(Dst);2381      break;2382 2383    case Stmt::OffsetOfExprClass: {2384      Bldr.takeNodes(Pred);2385      ExplodedNodeSet PreVisit;2386      getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);2387 2388      ExplodedNodeSet PostVisit;2389      for (const auto Node : PreVisit)2390        VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);2391 2392      getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);2393      Bldr.addNodes(Dst);2394      break;2395    }2396 2397    case Stmt::UnaryExprOrTypeTraitExprClass:2398      Bldr.takeNodes(Pred);2399      VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),2400                                    Pred, Dst);2401      Bldr.addNodes(Dst);2402      break;2403 2404    case Stmt::StmtExprClass: {2405      const auto *SE = cast<StmtExpr>(S);2406 2407      if (SE->getSubStmt()->body_empty()) {2408        // Empty statement expression.2409        assert(SE->getType() == getContext().VoidTy2410               && "Empty statement expression must have void type.");2411        break;2412      }2413 2414      if (const auto *LastExpr =2415              dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {2416        ProgramStateRef state = Pred->getState();2417        Bldr.generateNode(SE, Pred,2418                          state->BindExpr(SE, Pred->getLocationContext(),2419                                          state->getSVal(LastExpr,2420                                                  Pred->getLocationContext())));2421      }2422      break;2423    }2424 2425    case Stmt::UnaryOperatorClass: {2426      Bldr.takeNodes(Pred);2427      const auto *U = cast<UnaryOperator>(S);2428      if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {2429        ExplodedNodeSet Tmp;2430        VisitUnaryOperator(U, Pred, Tmp);2431        evalEagerlyAssumeBifurcation(Dst, Tmp, U);2432      }2433      else2434        VisitUnaryOperator(U, Pred, Dst);2435      Bldr.addNodes(Dst);2436      break;2437    }2438 2439    case Stmt::PseudoObjectExprClass: {2440      Bldr.takeNodes(Pred);2441      ProgramStateRef state = Pred->getState();2442      const auto *PE = cast<PseudoObjectExpr>(S);2443      if (const Expr *Result = PE->getResultExpr()) {2444        SVal V = state->getSVal(Result, Pred->getLocationContext());2445        Bldr.generateNode(S, Pred,2446                          state->BindExpr(S, Pred->getLocationContext(), V));2447      }2448      else2449        Bldr.generateNode(S, Pred,2450                          state->BindExpr(S, Pred->getLocationContext(),2451                                                   UnknownVal()));2452 2453      Bldr.addNodes(Dst);2454      break;2455    }2456 2457    case Expr::ObjCIndirectCopyRestoreExprClass: {2458      // ObjCIndirectCopyRestoreExpr implies passing a temporary for2459      // correctness of lifetime management.  Due to limited analysis2460      // of ARC, this is implemented as direct arg passing.2461      Bldr.takeNodes(Pred);2462      ProgramStateRef state = Pred->getState();2463      const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);2464      const Expr *E = OIE->getSubExpr();2465      SVal V = state->getSVal(E, Pred->getLocationContext());2466      Bldr.generateNode(S, Pred,2467              state->BindExpr(S, Pred->getLocationContext(), V));2468      Bldr.addNodes(Dst);2469      break;2470    }2471  }2472}2473 2474bool ExprEngine::replayWithoutInlining(ExplodedNode *N,2475                                       const LocationContext *CalleeLC) {2476  const StackFrameContext *CalleeSF = CalleeLC->getStackFrame();2477  const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();2478  assert(CalleeSF && CallerSF);2479  ExplodedNode *BeforeProcessingCall = nullptr;2480  const Stmt *CE = CalleeSF->getCallSite();2481 2482  // Find the first node before we started processing the call expression.2483  while (N) {2484    ProgramPoint L = N->getLocation();2485    BeforeProcessingCall = N;2486    N = N->pred_empty() ? nullptr : *(N->pred_begin());2487 2488    // Skip the nodes corresponding to the inlined code.2489    if (L.getStackFrame() != CallerSF)2490      continue;2491    // We reached the caller. Find the node right before we started2492    // processing the call.2493    if (L.isPurgeKind())2494      continue;2495    if (L.getAs<PreImplicitCall>())2496      continue;2497    if (L.getAs<CallEnter>())2498      continue;2499    if (std::optional<StmtPoint> SP = L.getAs<StmtPoint>())2500      if (SP->getStmt() == CE)2501        continue;2502    break;2503  }2504 2505  if (!BeforeProcessingCall)2506    return false;2507 2508  // TODO: Clean up the unneeded nodes.2509 2510  // Build an Epsilon node from which we will restart the analyzes.2511  // Note that CE is permitted to be NULL!2512  static SimpleProgramPointTag PT("ExprEngine", "Replay without inlining");2513  ProgramPoint NewNodeLoc = EpsilonPoint(2514      BeforeProcessingCall->getLocationContext(), CE, nullptr, &PT);2515  // Add the special flag to GDM to signal retrying with no inlining.2516  // Note, changing the state ensures that we are not going to cache out.2517  ProgramStateRef NewNodeState = BeforeProcessingCall->getState();2518  NewNodeState =2519    NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));2520 2521  // Make the new node a successor of BeforeProcessingCall.2522  bool IsNew = false;2523  ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);2524  // We cached out at this point. Caching out is common due to us backtracking2525  // from the inlined function, which might spawn several paths.2526  if (!IsNew)2527    return true;2528 2529  NewNode->addPredecessor(BeforeProcessingCall, G);2530 2531  // Add the new node to the work list.2532  Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),2533                                  CalleeSF->getIndex());2534  NumTimesRetriedWithoutInlining++;2535  return true;2536}2537 2538/// Return the innermost location context which is inlined at `Node`, unless2539/// it's the top-level (entry point) location context.2540static const LocationContext *getInlinedLocationContext(ExplodedNode *Node,2541                                                        ExplodedGraph &G) {2542  const LocationContext *CalleeLC = Node->getLocation().getLocationContext();2543  const LocationContext *RootLC =2544      G.getRoot()->getLocation().getLocationContext();2545 2546  if (CalleeLC->getStackFrame() == RootLC->getStackFrame())2547    return nullptr;2548 2549  return CalleeLC;2550}2551 2552/// Block entrance.  (Update counters).2553void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,2554                                         NodeBuilderWithSinks &nodeBuilder,2555                                         ExplodedNode *Pred) {2556  // If we reach a loop which has a known bound (and meets2557  // other constraints) then consider completely unrolling it.2558  if(AMgr.options.ShouldUnrollLoops) {2559    unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;2560    const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();2561    if (Term) {2562      ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),2563                                                 Pred, maxBlockVisitOnPath);2564      if (NewState != Pred->getState()) {2565        ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);2566        if (!UpdatedNode)2567          return;2568        Pred = UpdatedNode;2569      }2570    }2571    // Is we are inside an unrolled loop then no need the check the counters.2572    if(isUnrolledState(Pred->getState()))2573      return;2574  }2575 2576  // If this block is terminated by a loop and it has already been visited the2577  // maximum number of times, widen the loop.2578  unsigned int BlockCount = nodeBuilder.getContext().blockCount();2579  if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&2580      AMgr.options.ShouldWidenLoops) {2581    const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();2582    if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))2583      return;2584 2585    // Widen.2586    const LocationContext *LCtx = Pred->getLocationContext();2587 2588    // FIXME:2589    // We cannot use the CFG element from the via `ExprEngine::getCFGElementRef`2590    // since we are currently at the block entrance and the current reference2591    // would be stale.  Ideally, we should pass on the terminator of the CFG2592    // block, but the terminator cannot be referred as a CFG element.2593    // Here we just pass the the first CFG element in the block.2594    ProgramStateRef WidenedState =2595        getWidenedLoopState(Pred->getState(), LCtx, BlockCount,2596                            *nodeBuilder.getContext().getBlock()->ref_begin());2597    nodeBuilder.generateNode(WidenedState, Pred);2598    return;2599  }2600 2601  // FIXME: Refactor this into a checker.2602  if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {2603    static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");2604    const ExplodedNode *Sink =2605                   nodeBuilder.generateSink(Pred->getState(), Pred, &tag);2606 2607    if (const LocationContext *LC = getInlinedLocationContext(Pred, G)) {2608      // FIXME: This will unconditionally prevent inlining this function (even2609      // from other entry points), which is not a reasonable heuristic: even if2610      // we reached max block count on this particular execution path, there2611      // may be other execution paths (especially with other parametrizations)2612      // where the analyzer can reach the end of the function (so there is no2613      // natural reason to avoid inlining it). However, disabling this would2614      // significantly increase the analysis time (because more entry points2615      // would exhaust their allocated budget), so it must be compensated by a2616      // different (more reasonable) reduction of analysis scope.2617      Engine.FunctionSummaries->markShouldNotInline(2618          LC->getStackFrame()->getDecl());2619 2620      // Re-run the call evaluation without inlining it, by storing the2621      // no-inlining policy in the state and enqueuing the new work item on2622      // the list. Replay should almost never fail. Use the stats to catch it2623      // if it does.2624      if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, LC)))2625        return;2626      NumMaxBlockCountReachedInInlined++;2627    } else2628      NumMaxBlockCountReached++;2629 2630    // Make sink nodes as exhausted(for stats) only if retry failed.2631    Engine.blocksExhausted.push_back(std::make_pair(L, Sink));2632  }2633}2634 2635void ExprEngine::runCheckersForBlockEntrance(const NodeBuilderContext &BldCtx,2636                                             const BlockEntrance &Entrance,2637                                             ExplodedNode *Pred,2638                                             ExplodedNodeSet &Dst) {2639  llvm::PrettyStackTraceFormat CrashInfo(2640      "Processing block entrance B%d -> B%d",2641      Entrance.getPreviousBlock()->getBlockID(),2642      Entrance.getBlock()->getBlockID());2643  currBldrCtx = &BldCtx;2644  getCheckerManager().runCheckersForBlockEntrance(Dst, Pred, Entrance, *this);2645  currBldrCtx = nullptr;2646}2647 2648//===----------------------------------------------------------------------===//2649// Branch processing.2650//===----------------------------------------------------------------------===//2651 2652/// RecoverCastedSymbol - A helper function for ProcessBranch that is used2653/// to try to recover some path-sensitivity for casts of symbolic2654/// integers that promote their values (which are currently not tracked well).2655/// This function returns the SVal bound to Condition->IgnoreCasts if all the2656//  cast(s) did was sign-extend the original value.2657static SVal RecoverCastedSymbol(ProgramStateRef state,2658                                const Stmt *Condition,2659                                const LocationContext *LCtx,2660                                ASTContext &Ctx) {2661 2662  const auto *Ex = dyn_cast<Expr>(Condition);2663  if (!Ex)2664    return UnknownVal();2665 2666  uint64_t bits = 0;2667  bool bitsInit = false;2668 2669  while (const auto *CE = dyn_cast<CastExpr>(Ex)) {2670    QualType T = CE->getType();2671 2672    if (!T->isIntegralOrEnumerationType())2673      return UnknownVal();2674 2675    uint64_t newBits = Ctx.getTypeSize(T);2676    if (!bitsInit || newBits < bits) {2677      bitsInit = true;2678      bits = newBits;2679    }2680 2681    Ex = CE->getSubExpr();2682  }2683 2684  // We reached a non-cast.  Is it a symbolic value?2685  QualType T = Ex->getType();2686 2687  if (!bitsInit || !T->isIntegralOrEnumerationType() ||2688      Ctx.getTypeSize(T) > bits)2689    return UnknownVal();2690 2691  return state->getSVal(Ex, LCtx);2692}2693 2694#ifndef NDEBUG2695static const Stmt *getRightmostLeaf(const Stmt *Condition) {2696  while (Condition) {2697    const auto *BO = dyn_cast<BinaryOperator>(Condition);2698    if (!BO || !BO->isLogicalOp()) {2699      return Condition;2700    }2701    Condition = BO->getRHS()->IgnoreParens();2702  }2703  return nullptr;2704}2705#endif2706 2707// Returns the condition the branch at the end of 'B' depends on and whose value2708// has been evaluated within 'B'.2709// In most cases, the terminator condition of 'B' will be evaluated fully in2710// the last statement of 'B'; in those cases, the resolved condition is the2711// given 'Condition'.2712// If the condition of the branch is a logical binary operator tree, the CFG is2713// optimized: in that case, we know that the expression formed by all but the2714// rightmost leaf of the logical binary operator tree must be true, and thus2715// the branch condition is at this point equivalent to the truth value of that2716// rightmost leaf; the CFG block thus only evaluates this rightmost leaf2717// expression in its final statement. As the full condition in that case was2718// not evaluated, and is thus not in the SVal cache, we need to use that leaf2719// expression to evaluate the truth value of the condition in the current state2720// space.2721static const Stmt *ResolveCondition(const Stmt *Condition,2722                                    const CFGBlock *B) {2723  if (const auto *Ex = dyn_cast<Expr>(Condition))2724    Condition = Ex->IgnoreParens();2725 2726  const auto *BO = dyn_cast<BinaryOperator>(Condition);2727  if (!BO || !BO->isLogicalOp())2728    return Condition;2729 2730  assert(B->getTerminator().isStmtBranch() &&2731         "Other kinds of branches are handled separately!");2732 2733  // For logical operations, we still have the case where some branches2734  // use the traditional "merge" approach and others sink the branch2735  // directly into the basic blocks representing the logical operation.2736  // We need to distinguish between those two cases here.2737 2738  // The invariants are still shifting, but it is possible that the2739  // last element in a CFGBlock is not a CFGStmt.  Look for the last2740  // CFGStmt as the value of the condition.2741  for (CFGElement Elem : llvm::reverse(*B)) {2742    std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>();2743    if (!CS)2744      continue;2745    const Stmt *LastStmt = CS->getStmt();2746    assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));2747    return LastStmt;2748  }2749  llvm_unreachable("could not resolve condition");2750}2751 2752using ObjCForLctxPair =2753    std::pair<const ObjCForCollectionStmt *, const LocationContext *>;2754 2755REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations, ObjCForLctxPair, bool)2756 2757ProgramStateRef ExprEngine::setWhetherHasMoreIteration(2758    ProgramStateRef State, const ObjCForCollectionStmt *O,2759    const LocationContext *LC, bool HasMoreIteraton) {2760  assert(!State->contains<ObjCForHasMoreIterations>({O, LC}));2761  return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);2762}2763 2764ProgramStateRef2765ExprEngine::removeIterationState(ProgramStateRef State,2766                                 const ObjCForCollectionStmt *O,2767                                 const LocationContext *LC) {2768  assert(State->contains<ObjCForHasMoreIterations>({O, LC}));2769  return State->remove<ObjCForHasMoreIterations>({O, LC});2770}2771 2772bool ExprEngine::hasMoreIteration(ProgramStateRef State,2773                                  const ObjCForCollectionStmt *O,2774                                  const LocationContext *LC) {2775  assert(State->contains<ObjCForHasMoreIterations>({O, LC}));2776  return *State->get<ObjCForHasMoreIterations>({O, LC});2777}2778 2779/// Split the state on whether there are any more iterations left for this loop.2780/// Returns a (HasMoreIteration, HasNoMoreIteration) pair, or std::nullopt when2781/// the acquisition of the loop condition value failed.2782static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>2783assumeCondition(const Stmt *Condition, ExplodedNode *N) {2784  ProgramStateRef State = N->getState();2785  if (const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(Condition)) {2786    bool HasMoreIteraton =2787        ExprEngine::hasMoreIteration(State, ObjCFor, N->getLocationContext());2788    // Checkers have already ran on branch conditions, so the current2789    // information as to whether the loop has more iteration becomes outdated2790    // after this point.2791    State = ExprEngine::removeIterationState(State, ObjCFor,2792                                             N->getLocationContext());2793    if (HasMoreIteraton)2794      return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};2795    else2796      return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};2797  }2798  SVal X = State->getSVal(Condition, N->getLocationContext());2799 2800  if (X.isUnknownOrUndef()) {2801    // Give it a chance to recover from unknown.2802    if (const auto *Ex = dyn_cast<Expr>(Condition)) {2803      if (Ex->getType()->isIntegralOrEnumerationType()) {2804        // Try to recover some path-sensitivity.  Right now casts of symbolic2805        // integers that promote their values are currently not tracked well.2806        // If 'Condition' is such an expression, try and recover the2807        // underlying value and use that instead.2808        SVal recovered =2809            RecoverCastedSymbol(State, Condition, N->getLocationContext(),2810                                N->getState()->getStateManager().getContext());2811 2812        if (!recovered.isUnknown()) {2813          X = recovered;2814        }2815      }2816    }2817  }2818 2819  // If the condition is still unknown, give up.2820  if (X.isUnknownOrUndef())2821    return std::nullopt;2822 2823  DefinedSVal V = X.castAs<DefinedSVal>();2824 2825  ProgramStateRef StTrue, StFalse;2826  return State->assume(V);2827}2828 2829void ExprEngine::processBranch(2830    const Stmt *Condition, NodeBuilderContext &BldCtx, ExplodedNode *Pred,2831    ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF,2832    std::optional<unsigned> IterationsCompletedInLoop) {2833  assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&2834         "CXXBindTemporaryExprs are handled by processBindTemporary.");2835  currBldrCtx = &BldCtx;2836 2837  // Check for NULL conditions; e.g. "for(;;)"2838  if (!Condition) {2839    BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);2840    NullCondBldr.generateNode(Pred->getState(), true, Pred);2841    return;2842  }2843 2844  if (const auto *Ex = dyn_cast<Expr>(Condition))2845    Condition = Ex->IgnoreParens();2846 2847  Condition = ResolveCondition(Condition, BldCtx.getBlock());2848  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),2849                                Condition->getBeginLoc(),2850                                "Error evaluating branch");2851 2852  ExplodedNodeSet CheckersOutSet;2853  getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,2854                                                    Pred, *this);2855  // We generated only sinks.2856  if (CheckersOutSet.empty())2857    return;2858 2859  BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);2860  for (ExplodedNode *PredN : CheckersOutSet) {2861    if (PredN->isSink())2862      continue;2863 2864    ProgramStateRef PrevState = PredN->getState();2865 2866    ProgramStateRef StTrue = PrevState, StFalse = PrevState;2867    if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))2868      std::tie(StTrue, StFalse) = *KnownCondValueAssumption;2869 2870    if (StTrue && StFalse)2871      assert(!isa<ObjCForCollectionStmt>(Condition));2872 2873    // We want to ensure consistent behavior between `eagerly-assume=false`,2874    // when the state split is always performed by the `assumeCondition()`2875    // call within this function and `eagerly-assume=true` (the default), when2876    // some conditions (comparison operators, unary negation) can trigger a2877    // state split before this callback. There are some contrived corner cases2878    // that behave differently with and without `eagerly-assume`, but I don't2879    // know about an example that could plausibly appear in "real" code.2880    bool BothFeasible =2881        (StTrue && StFalse) ||2882        didEagerlyAssumeBifurcateAt(PrevState, dyn_cast<Expr>(Condition));2883 2884    if (StTrue) {2885      // In a loop, if both branches are feasible (i.e. the analyzer doesn't2886      // understand the loop condition) and two iterations have already been2887      // completed, then don't assume a third iteration because it is a2888      // redundant execution path (unlikely to be different from earlier loop2889      // exits) and can cause false positives if e.g. the loop iterates over a2890      // two-element structure with an opaque condition.2891      //2892      // The iteration count "2" is hardcoded because it's the natural limit:2893      // * the fact that the programmer wrote a loop (and not just an `if`)2894      //   implies that they thought that the loop body might be executed twice;2895      // * however, there are situations where the programmer knows that there2896      //   are at most two iterations but writes a loop that appears to be2897      //   generic, because there is no special syntax for "loop with at most2898      //   two iterations". (This pattern is common in FFMPEG and appears in2899      //   many other projects as well.)2900      bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;2901      bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;2902 2903      // FIXME: This "don't assume third iteration" heuristic partially2904      // conflicts with the widen-loop analysis option (which is off by2905      // default). If we intend to support and stabilize the loop widening,2906      // we must ensure that it 'plays nicely' with this logic.2907      if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {2908        Builder.generateNode(StTrue, true, PredN);2909      } else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {2910        // FIXME: There is an ancient and arbitrary heuristic in2911        // `ExprEngine::processCFGBlockEntrance` which prevents all further2912        // inlining of a function if it finds an execution path within that2913        // function which reaches the `MaxBlockVisitOnPath` limit (a/k/a2914        // `analyzer-max-loop`, by default four iterations in a loop). Adding2915        // this "don't assume third iteration" logic significantly increased2916        // the analysis runtime on some inputs because less functions were2917        // arbitrarily excluded from being inlined, so more entry points used2918        // up their full allocated budget. As a hacky compensation for this,2919        // here we apply the "should not inline" mark in cases when the loop2920        // could potentially reach the `MaxBlockVisitOnPath` limit without the2921        // "don't assume third iteration" logic. This slightly overcompensates2922        // (activates if the third iteration can be entered, and will not2923        // recognize cases where the fourth iteration would't be completed), but2924        // should be good enough for practical purposes.2925        if (const LocationContext *LC = getInlinedLocationContext(Pred, G)) {2926          Engine.FunctionSummaries->markShouldNotInline(2927              LC->getStackFrame()->getDecl());2928        }2929      }2930    }2931 2932    if (StFalse) {2933      // In a loop, if both branches are feasible (i.e. the analyzer doesn't2934      // understand the loop condition), we are before the first iteration and2935      // the analyzer option `assume-at-least-one-iteration` is set to `true`,2936      // then avoid creating the execution path where the loop is skipped.2937      //2938      // In some situations this "loop is skipped" execution path is an2939      // important corner case that may evade the notice of the developer and2940      // hide significant bugs -- however, there are also many situations where2941      // it's guaranteed that at least one iteration will happen (e.g. some2942      // data structure is always nonempty), but the analyzer cannot realize2943      // this and will produce false positives when it assumes that the loop is2944      // skipped.2945      bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};2946      bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&2947                             AMgr.options.ShouldAssumeAtLeastOneIteration;2948      if (!SkipFalseBranch)2949        Builder.generateNode(StFalse, false, PredN);2950    }2951  }2952  currBldrCtx = nullptr;2953}2954 2955/// The GDM component containing the set of global variables which have been2956/// previously initialized with explicit initializers.2957REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,2958                                 llvm::ImmutableSet<const VarDecl *>)2959 2960void ExprEngine::processStaticInitializer(2961    const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred,2962    ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) {2963  currBldrCtx = &BuilderCtx;2964 2965  const auto *VD = cast<VarDecl>(DS->getSingleDecl());2966  ProgramStateRef state = Pred->getState();2967  bool initHasRun = state->contains<InitializedGlobalsSet>(VD);2968  BranchNodeBuilder Builder(Pred, Dst, BuilderCtx, DstT, DstF);2969 2970  if (!initHasRun) {2971    state = state->add<InitializedGlobalsSet>(VD);2972  }2973 2974  Builder.generateNode(state, initHasRun, Pred);2975 2976  currBldrCtx = nullptr;2977}2978 2979/// processIndirectGoto - Called by CoreEngine.  Used to generate successor2980///  nodes by processing the 'effects' of a computed goto jump.2981void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {2982  ProgramStateRef state = builder.getState();2983  SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());2984 2985  // Three possibilities:2986  //2987  //   (1) We know the computed label.2988  //   (2) The label is NULL (or some other constant), or Undefined.2989  //   (3) We have no clue about the label.  Dispatch to all targets.2990  //2991 2992  using iterator = IndirectGotoNodeBuilder::iterator;2993 2994  if (std::optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {2995    const LabelDecl *L = LV->getLabel();2996 2997    for (iterator Succ : builder) {2998      if (Succ.getLabel() == L) {2999        builder.generateNode(Succ, state);3000        return;3001      }3002    }3003 3004    llvm_unreachable("No block with label.");3005  }3006 3007  if (isa<UndefinedVal, loc::ConcreteInt>(V)) {3008    // Dispatch to the first target and mark it as a sink.3009    //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);3010    // FIXME: add checker visit.3011    //    UndefBranches.insert(N);3012    return;3013  }3014 3015  // This is really a catch-all.  We don't support symbolics yet.3016  // FIXME: Implement dispatch for symbolic pointers.3017 3018  for (iterator Succ : builder)3019    builder.generateNode(Succ, state);3020}3021 3022void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,3023                                        ExplodedNode *Pred,3024                                        ExplodedNodeSet &Dst,3025                                        const BlockEdge &L) {3026  SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);3027  getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);3028}3029 3030/// ProcessEndPath - Called by CoreEngine.  Used to generate end-of-path3031///  nodes when the control reaches the end of a function.3032void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,3033                                      ExplodedNode *Pred,3034                                      const ReturnStmt *RS) {3035  ProgramStateRef State = Pred->getState();3036 3037  if (!Pred->getStackFrame()->inTopFrame())3038    State = finishArgumentConstruction(3039        State, *getStateManager().getCallEventManager().getCaller(3040                   Pred->getStackFrame(), Pred->getState()));3041 3042  // FIXME: We currently cannot assert that temporaries are clear, because3043  // lifetime extended temporaries are not always modelled correctly. In some3044  // cases when we materialize the temporary, we do3045  // createTemporaryRegionIfNeeded(), and the region changes, and also the3046  // respective destructor becomes automatic from temporary. So for now clean up3047  // the state manually before asserting. Ideally, this braced block of code3048  // should go away.3049  {3050    const LocationContext *FromLC = Pred->getLocationContext();3051    const LocationContext *ToLC = FromLC->getStackFrame()->getParent();3052    const LocationContext *LC = FromLC;3053    while (LC != ToLC) {3054      assert(LC && "ToLC must be a parent of FromLC!");3055      for (auto I : State->get<ObjectsUnderConstruction>())3056        if (I.first.getLocationContext() == LC) {3057          // The comment above only pardons us for not cleaning up a3058          // temporary destructor. If any other statements are found here,3059          // it must be a separate problem.3060          assert(I.first.getItem().getKind() ==3061                     ConstructionContextItem::TemporaryDestructorKind ||3062                 I.first.getItem().getKind() ==3063                     ConstructionContextItem::ElidedDestructorKind);3064          State = State->remove<ObjectsUnderConstruction>(I.first);3065        }3066      LC = LC->getParent();3067    }3068  }3069 3070  // Perform the transition with cleanups.3071  if (State != Pred->getState()) {3072    ExplodedNodeSet PostCleanup;3073    NodeBuilder Bldr(Pred, PostCleanup, BC);3074    Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);3075    if (!Pred) {3076      // The node with clean temporaries already exists. We might have reached3077      // it on a path on which we initialize different temporaries.3078      return;3079    }3080  }3081 3082  assert(areAllObjectsFullyConstructed(Pred->getState(),3083                                       Pred->getLocationContext(),3084                                       Pred->getStackFrame()->getParent()));3085  ExplodedNodeSet Dst;3086  if (Pred->getLocationContext()->inTopFrame()) {3087    // Remove dead symbols.3088    ExplodedNodeSet AfterRemovedDead;3089    removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);3090 3091    // Notify checkers.3092    for (const auto I : AfterRemovedDead)3093      getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);3094  } else {3095    getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);3096  }3097 3098  Engine.enqueueEndOfFunction(Dst, RS);3099}3100 3101/// ProcessSwitch - Called by CoreEngine.  Used to generate successor3102///  nodes by processing the 'effects' of a switch statement.3103void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {3104  using iterator = SwitchNodeBuilder::iterator;3105 3106  ProgramStateRef state = builder.getState();3107  const Expr *CondE = builder.getCondition();3108  SVal  CondV_untested = state->getSVal(CondE, builder.getLocationContext());3109 3110  if (CondV_untested.isUndef()) {3111    //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);3112    // FIXME: add checker3113    //UndefBranches.insert(N);3114 3115    return;3116  }3117  DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();3118 3119  ProgramStateRef DefaultSt = state;3120 3121  iterator I = builder.begin(), EI = builder.end();3122  bool defaultIsFeasible = I == EI;3123 3124  for ( ; I != EI; ++I) {3125    // Successor may be pruned out during CFG construction.3126    if (!I.getBlock())3127      continue;3128 3129    const CaseStmt *Case = I.getCase();3130 3131    // Evaluate the LHS of the case value.3132    llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());3133    assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));3134 3135    // Get the RHS of the case, if it exists.3136    llvm::APSInt V2;3137    if (const Expr *E = Case->getRHS())3138      V2 = E->EvaluateKnownConstInt(getContext());3139    else3140      V2 = V1;3141 3142    ProgramStateRef StateCase;3143    if (std::optional<NonLoc> NL = CondV.getAs<NonLoc>())3144      std::tie(StateCase, DefaultSt) =3145          DefaultSt->assumeInclusiveRange(*NL, V1, V2);3146    else // UnknownVal3147      StateCase = DefaultSt;3148 3149    if (StateCase)3150      builder.generateCaseStmtNode(I, StateCase);3151 3152    // Now "assume" that the case doesn't match.  Add this state3153    // to the default state (if it is feasible).3154    if (DefaultSt)3155      defaultIsFeasible = true;3156    else {3157      defaultIsFeasible = false;3158      break;3159    }3160  }3161 3162  if (!defaultIsFeasible)3163    return;3164 3165  // If we have switch(enum value), the default branch is not3166  // feasible if all of the enum constants not covered by 'case:' statements3167  // are not feasible values for the switch condition.3168  //3169  // Note that this isn't as accurate as it could be.  Even if there isn't3170  // a case for a particular enum value as long as that enum value isn't3171  // feasible then it shouldn't be considered for making 'default:' reachable.3172  const SwitchStmt *SS = builder.getSwitch();3173  const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();3174  if (CondExpr->getType()->isEnumeralType()) {3175    if (SS->isAllEnumCasesCovered())3176      return;3177  }3178 3179  builder.generateDefaultCaseNode(DefaultSt);3180}3181 3182//===----------------------------------------------------------------------===//3183// Transfer functions: Loads and stores.3184//===----------------------------------------------------------------------===//3185 3186void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,3187                                        ExplodedNode *Pred,3188                                        ExplodedNodeSet &Dst) {3189  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);3190 3191  ProgramStateRef state = Pred->getState();3192  const LocationContext *LCtx = Pred->getLocationContext();3193 3194  auto resolveAsLambdaCapturedVar =3195      [&](const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {3196    const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());3197    const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);3198    if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&3199        DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&3200        MD->getParent()->isLambda()) {3201      // Lookup the field of the lambda.3202      const CXXRecordDecl *CXXRec = MD->getParent();3203      llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;3204      FieldDecl *LambdaThisCaptureField;3205      CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);3206 3207      // Sema follows a sequence of complex rules to determine whether the3208      // variable should be captured.3209      if (const FieldDecl *FD = LambdaCaptureFields[VD]) {3210        Loc CXXThis = svalBuilder.getCXXThis(MD, LCtx->getStackFrame());3211        SVal CXXThisVal = state->getSVal(CXXThis);3212        return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());3213      }3214    }3215 3216    return std::nullopt;3217  };3218 3219  if (const auto *VD = dyn_cast<VarDecl>(D)) {3220    // C permits "extern void v", and if you cast the address to a valid type,3221    // you can even do things with it. We simply pretend3222    assert(Ex->isGLValue() || VD->getType()->isVoidType());3223    const LocationContext *LocCtxt = Pred->getLocationContext();3224    std::optional<std::pair<SVal, QualType>> VInfo =3225        resolveAsLambdaCapturedVar(VD);3226 3227    if (!VInfo)3228      VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());3229 3230    SVal V = VInfo->first;3231    bool IsReference = VInfo->second->isReferenceType();3232 3233    // For references, the 'lvalue' is the pointer address stored in the3234    // reference region.3235    if (IsReference) {3236      if (const MemRegion *R = V.getAsRegion())3237        V = state->getSVal(R);3238      else3239        V = UnknownVal();3240    }3241 3242    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,3243                      ProgramPoint::PostLValueKind);3244    return;3245  }3246  if (const auto *ED = dyn_cast<EnumConstantDecl>(D)) {3247    assert(!Ex->isGLValue());3248    SVal V = svalBuilder.makeIntVal(ED->getInitVal());3249    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));3250    return;3251  }3252  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {3253    SVal V = svalBuilder.getFunctionPointer(FD);3254    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,3255                      ProgramPoint::PostLValueKind);3256    return;3257  }3258  if (isa<FieldDecl, IndirectFieldDecl>(D)) {3259    // Delegate all work related to pointer to members to the surrounding3260    // operator&.3261    return;3262  }3263  if (const auto *BD = dyn_cast<BindingDecl>(D)) {3264    // Handle structured bindings captured by lambda.3265    if (std::optional<std::pair<SVal, QualType>> VInfo =3266            resolveAsLambdaCapturedVar(BD)) {3267      auto [V, T] = VInfo.value();3268 3269      if (T->isReferenceType()) {3270        if (const MemRegion *R = V.getAsRegion())3271          V = state->getSVal(R);3272        else3273          V = UnknownVal();3274      }3275 3276      Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,3277                        ProgramPoint::PostLValueKind);3278      return;3279    }3280 3281    const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());3282 3283    SVal Base = state->getLValue(DD, LCtx);3284    if (DD->getType()->isReferenceType()) {3285      if (const MemRegion *R = Base.getAsRegion())3286        Base = state->getSVal(R);3287      else3288        Base = UnknownVal();3289    }3290 3291    SVal V = UnknownVal();3292 3293    // Handle binding to data members3294    if (const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {3295      const auto *Field = cast<FieldDecl>(ME->getMemberDecl());3296      V = state->getLValue(Field, Base);3297    }3298    // Handle binding to arrays3299    else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {3300      SVal Idx = state->getSVal(ASE->getIdx(), LCtx);3301 3302      // Note: the index of an element in a structured binding is automatically3303      // created and it is a unique identifier of the specific element. Thus it3304      // cannot be a value that varies at runtime.3305      assert(Idx.isConstant() && "BindingDecl array index is not a constant!");3306 3307      V = state->getLValue(BD->getType(), Idx, Base);3308    }3309    // Handle binding to tuple-like structures3310    else if (const auto *HV = BD->getHoldingVar()) {3311      V = state->getLValue(HV, LCtx);3312 3313      if (HV->getType()->isReferenceType()) {3314        if (const MemRegion *R = V.getAsRegion())3315          V = state->getSVal(R);3316        else3317          V = UnknownVal();3318      }3319    } else3320      llvm_unreachable("An unknown case of structured binding encountered!");3321 3322    // In case of tuple-like types the references are already handled, so we3323    // don't want to handle them again.3324    if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {3325      if (const MemRegion *R = V.getAsRegion())3326        V = state->getSVal(R);3327      else3328        V = UnknownVal();3329    }3330 3331    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,3332                      ProgramPoint::PostLValueKind);3333 3334    return;3335  }3336 3337  if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {3338    // FIXME: We should meaningfully implement this.3339    (void)TPO;3340    return;3341  }3342 3343  llvm_unreachable("Support for this Decl not implemented.");3344}3345 3346/// VisitArrayInitLoopExpr - Transfer function for array init loop.3347void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex,3348                                        ExplodedNode *Pred,3349                                        ExplodedNodeSet &Dst) {3350  ExplodedNodeSet CheckerPreStmt;3351  getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, Ex, *this);3352 3353  ExplodedNodeSet EvalSet;3354  StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);3355 3356  const Expr *Arr = Ex->getCommonExpr()->getSourceExpr();3357 3358  for (auto *Node : CheckerPreStmt) {3359 3360    // The constructor visitior has already taken care of everything.3361    if (isa<CXXConstructExpr>(Ex->getSubExpr()))3362      break;3363 3364    const LocationContext *LCtx = Node->getLocationContext();3365    ProgramStateRef state = Node->getState();3366 3367    SVal Base = UnknownVal();3368 3369    // As in case of this expression the sub-expressions are not visited by any3370    // other transfer functions, they are handled by matching their AST.3371 3372    // Case of implicit copy or move ctor of object with array member3373    //3374    // Note: ExprEngine::VisitMemberExpr is not able to bind the array to the3375    // environment.3376    //3377    //    struct S {3378    //      int arr[2];3379    //    };3380    //3381    //3382    //    S a;3383    //    S b = a;3384    //3385    // The AST in case of a *copy constructor* looks like this:3386    //    ArrayInitLoopExpr3387    //    |-OpaqueValueExpr3388    //    | `-MemberExpr              <-- match this3389    //    |   `-DeclRefExpr3390    //    ` ...3391    //3392    //3393    //    S c;3394    //    S d = std::move(d);3395    //3396    // In case of a *move constructor* the resulting AST looks like:3397    //    ArrayInitLoopExpr3398    //    |-OpaqueValueExpr3399    //    | `-MemberExpr              <-- match this first3400    //    |   `-CXXStaticCastExpr     <-- match this after3401    //    |     `-DeclRefExpr3402    //    ` ...3403    if (const auto *ME = dyn_cast<MemberExpr>(Arr)) {3404      Expr *MEBase = ME->getBase();3405 3406      // Move ctor3407      if (auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {3408        MEBase = CXXSCE->getSubExpr();3409      }3410 3411      auto ObjDeclExpr = cast<DeclRefExpr>(MEBase);3412      SVal Obj = state->getLValue(cast<VarDecl>(ObjDeclExpr->getDecl()), LCtx);3413 3414      Base = state->getLValue(cast<FieldDecl>(ME->getMemberDecl()), Obj);3415    }3416 3417    // Case of lambda capture and decomposition declaration3418    //3419    //    int arr[2];3420    //3421    //    [arr]{ int a = arr[0]; }();3422    //    auto[a, b] = arr;3423    //3424    // In both of these cases the AST looks like the following:3425    //    ArrayInitLoopExpr3426    //    |-OpaqueValueExpr3427    //    | `-DeclRefExpr             <-- match this3428    //    ` ...3429    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))3430      Base = state->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);3431 3432    // Create a lazy compound value to the original array3433    if (const MemRegion *R = Base.getAsRegion())3434      Base = state->getSVal(R);3435    else3436      Base = UnknownVal();3437 3438    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));3439  }3440 3441  getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);3442}3443 3444/// VisitArraySubscriptExpr - Transfer function for array accesses3445void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,3446                                             ExplodedNode *Pred,3447                                             ExplodedNodeSet &Dst){3448  const Expr *Base = A->getBase()->IgnoreParens();3449  const Expr *Idx  = A->getIdx()->IgnoreParens();3450 3451  ExplodedNodeSet CheckerPreStmt;3452  getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);3453 3454  ExplodedNodeSet EvalSet;3455  StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);3456 3457  bool IsVectorType = A->getBase()->getType()->isVectorType();3458 3459  // The "like" case is for situations where C standard prohibits the type to3460  // be an lvalue, e.g. taking the address of a subscript of an expression of3461  // type "void *".3462  bool IsGLValueLike = A->isGLValue() ||3463    (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);3464 3465  for (auto *Node : CheckerPreStmt) {3466    const LocationContext *LCtx = Node->getLocationContext();3467    ProgramStateRef state = Node->getState();3468 3469    if (IsGLValueLike) {3470      QualType T = A->getType();3471 3472      // One of the forbidden LValue types! We still need to have sensible3473      // symbolic locations to represent this stuff. Note that arithmetic on3474      // void pointers is a GCC extension.3475      if (T->isVoidType())3476        T = getContext().CharTy;3477 3478      SVal V = state->getLValue(T,3479                                state->getSVal(Idx, LCtx),3480                                state->getSVal(Base, LCtx));3481      Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,3482          ProgramPoint::PostLValueKind);3483    } else if (IsVectorType) {3484      // FIXME: non-glvalue vector reads are not modelled.3485      Bldr.generateNode(A, Node, state, nullptr);3486    } else {3487      llvm_unreachable("Array subscript should be an lValue when not \3488a vector and not a forbidden lvalue type");3489    }3490  }3491 3492  getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);3493}3494 3495/// VisitMemberExpr - Transfer function for member expressions.3496void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,3497                                 ExplodedNodeSet &Dst) {3498  // FIXME: Prechecks eventually go in ::Visit().3499  ExplodedNodeSet CheckedSet;3500  getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);3501 3502  ExplodedNodeSet EvalSet;3503  ValueDecl *Member = M->getMemberDecl();3504 3505  // Handle static member variables and enum constants accessed via3506  // member syntax.3507  if (isa<VarDecl, EnumConstantDecl>(Member)) {3508    for (const auto I : CheckedSet)3509      VisitCommonDeclRefExpr(M, Member, I, EvalSet);3510  } else {3511    StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);3512    ExplodedNodeSet Tmp;3513 3514    for (const auto I : CheckedSet) {3515      ProgramStateRef state = I->getState();3516      const LocationContext *LCtx = I->getLocationContext();3517      Expr *BaseExpr = M->getBase();3518 3519      // Handle C++ method calls.3520      if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {3521        if (MD->isImplicitObjectMemberFunction())3522          state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);3523 3524        SVal MDVal = svalBuilder.getFunctionPointer(MD);3525        state = state->BindExpr(M, LCtx, MDVal);3526 3527        Bldr.generateNode(M, I, state);3528        continue;3529      }3530 3531      // Handle regular struct fields / member variables.3532      const SubRegion *MR = nullptr;3533      state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,3534                                            /*Result=*/nullptr,3535                                            /*OutRegionWithAdjustments=*/&MR);3536      SVal baseExprVal =3537          MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);3538 3539      // FIXME: Copied from RegionStoreManager::bind()3540      if (const auto *SR =3541              dyn_cast_or_null<SymbolicRegion>(baseExprVal.getAsRegion())) {3542        QualType T = SR->getPointeeStaticType();3543        baseExprVal =3544            loc::MemRegionVal(getStoreManager().GetElementZeroRegion(SR, T));3545      }3546 3547      const auto *field = cast<FieldDecl>(Member);3548      SVal L = state->getLValue(field, baseExprVal);3549 3550      if (M->isGLValue() || M->getType()->isArrayType()) {3551        // We special-case rvalues of array type because the analyzer cannot3552        // reason about them, since we expect all regions to be wrapped in Locs.3553        // We instead treat these as lvalues and assume that they will decay to3554        // pointers as soon as they are used.3555        if (!M->isGLValue()) {3556          assert(M->getType()->isArrayType());3557          const auto *PE =3558            dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));3559          if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {3560            llvm_unreachable("should always be wrapped in ArrayToPointerDecay");3561          }3562        }3563 3564        if (field->getType()->isReferenceType()) {3565          if (const MemRegion *R = L.getAsRegion())3566            L = state->getSVal(R);3567          else3568            L = UnknownVal();3569        }3570 3571        Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,3572                          ProgramPoint::PostLValueKind);3573      } else {3574        Bldr.takeNodes(I);3575        evalLoad(Tmp, M, M, I, state, L);3576        Bldr.addNodes(Tmp);3577      }3578    }3579  }3580 3581  getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);3582}3583 3584void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,3585                                 ExplodedNodeSet &Dst) {3586  ExplodedNodeSet AfterPreSet;3587  getCheckerManager().runCheckersForPreStmt(AfterPreSet, Pred, AE, *this);3588 3589  // For now, treat all the arguments to C11 atomics as escaping.3590  // FIXME: Ideally we should model the behavior of the atomics precisely here.3591 3592  ExplodedNodeSet AfterInvalidateSet;3593  StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);3594 3595  for (const auto I : AfterPreSet) {3596    ProgramStateRef State = I->getState();3597    const LocationContext *LCtx = I->getLocationContext();3598 3599    SmallVector<SVal, 8> ValuesToInvalidate;3600    for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {3601      const Expr *SubExpr = AE->getSubExprs()[SI];3602      SVal SubExprVal = State->getSVal(SubExpr, LCtx);3603      ValuesToInvalidate.push_back(SubExprVal);3604    }3605 3606    State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),3607                                     currBldrCtx->blockCount(), LCtx,3608                                     /*CausedByPointerEscape*/ true,3609                                     /*Symbols=*/nullptr);3610 3611    SVal ResultVal = UnknownVal();3612    State = State->BindExpr(AE, LCtx, ResultVal);3613    Bldr.generateNode(AE, I, State, nullptr,3614                      ProgramPoint::PostStmtKind);3615  }3616 3617  getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);3618}3619 3620// A value escapes in four possible cases:3621// (1) We are binding to something that is not a memory region.3622// (2) We are binding to a MemRegion that does not have stack storage.3623// (3) We are binding to a top-level parameter region with a non-trivial3624//     destructor. We won't see the destructor during analysis, but it's there.3625// (4) We are binding to a MemRegion with stack storage that the store3626//     does not understand.3627ProgramStateRef ExprEngine::processPointerEscapedOnBind(3628    ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,3629    const LocationContext *LCtx, PointerEscapeKind Kind,3630    const CallEvent *Call) {3631  SmallVector<SVal, 8> Escaped;3632  for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {3633    // Cases (1) and (2).3634    const MemRegion *MR = LocAndVal.first.getAsRegion();3635    const MemSpaceRegion *Space = MR ? MR->getMemorySpace(State) : nullptr;3636    if (!MR || !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(Space)) {3637      Escaped.push_back(LocAndVal.second);3638      continue;3639    }3640 3641    // Case (3).3642    if (const auto *VR = dyn_cast<VarRegion>(MR->getBaseRegion()))3643      if (isa<StackArgumentsSpaceRegion>(Space) &&3644          VR->getStackFrame()->inTopFrame())3645        if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())3646          if (!RD->hasTrivialDestructor()) {3647            Escaped.push_back(LocAndVal.second);3648            continue;3649          }3650 3651    // Case (4): in order to test that, generate a new state with the binding3652    // added. If it is the same state, then it escapes (since the store cannot3653    // represent the binding).3654    // Do this only if we know that the store is not supposed to generate the3655    // same state.3656    SVal StoredVal = State->getSVal(MR);3657    if (StoredVal != LocAndVal.second)3658      if (State ==3659          (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))3660        Escaped.push_back(LocAndVal.second);3661  }3662 3663  if (Escaped.empty())3664    return State;3665 3666  return escapeValues(State, Escaped, Kind, Call);3667}3668 3669ProgramStateRef3670ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,3671                                        SVal Val, const LocationContext *LCtx) {3672  std::pair<SVal, SVal> LocAndVal(Loc, Val);3673  return processPointerEscapedOnBind(State, LocAndVal, LCtx, PSK_EscapeOnBind,3674                                     nullptr);3675}3676 3677ProgramStateRef3678ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,3679    const InvalidatedSymbols *Invalidated,3680    ArrayRef<const MemRegion *> ExplicitRegions,3681    const CallEvent *Call,3682    RegionAndSymbolInvalidationTraits &ITraits) {3683  if (!Invalidated || Invalidated->empty())3684    return State;3685 3686  if (!Call)3687    return getCheckerManager().runCheckersForPointerEscape(State,3688                                                           *Invalidated,3689                                                           nullptr,3690                                                           PSK_EscapeOther,3691                                                           &ITraits);3692 3693  // If the symbols were invalidated by a call, we want to find out which ones3694  // were invalidated directly due to being arguments to the call.3695  InvalidatedSymbols SymbolsDirectlyInvalidated;3696  for (const auto I : ExplicitRegions) {3697    if (const SymbolicRegion *R = I->StripCasts()->getAs<SymbolicRegion>())3698      SymbolsDirectlyInvalidated.insert(R->getSymbol());3699  }3700 3701  InvalidatedSymbols SymbolsIndirectlyInvalidated;3702  for (const auto &sym : *Invalidated) {3703    if (SymbolsDirectlyInvalidated.count(sym))3704      continue;3705    SymbolsIndirectlyInvalidated.insert(sym);3706  }3707 3708  if (!SymbolsDirectlyInvalidated.empty())3709    State = getCheckerManager().runCheckersForPointerEscape(State,3710        SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);3711 3712  // Notify about the symbols that get indirectly invalidated by the call.3713  if (!SymbolsIndirectlyInvalidated.empty())3714    State = getCheckerManager().runCheckersForPointerEscape(State,3715        SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);3716 3717  return State;3718}3719 3720/// evalBind - Handle the semantics of binding a value to a specific location.3721///  This method is used by evalStore and (soon) VisitDeclStmt, and others.3722void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,3723                          ExplodedNode *Pred, SVal location, SVal Val,3724                          bool AtDeclInit, const ProgramPoint *PP) {3725  const LocationContext *LC = Pred->getLocationContext();3726  PostStmt PS(StoreE, LC);3727  if (!PP)3728    PP = &PS;3729 3730  // Do a previsit of the bind.3731  ExplodedNodeSet CheckedSet;3732  getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,3733                                         StoreE, AtDeclInit, *this, *PP);3734 3735  StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);3736 3737  // If the location is not a 'Loc', it will already be handled by3738  // the checkers.  There is nothing left to do.3739  if (!isa<Loc>(location)) {3740    const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,3741                                     /*tag*/nullptr);3742    ProgramStateRef state = Pred->getState();3743    state = processPointerEscapedOnBind(state, location, Val, LC);3744    Bldr.generateNode(L, state, Pred);3745    return;3746  }3747 3748  for (const auto PredI : CheckedSet) {3749    ProgramStateRef state = PredI->getState();3750 3751    state = processPointerEscapedOnBind(state, location, Val, LC);3752 3753    // When binding the value, pass on the hint that this is a initialization.3754    // For initializations, we do not need to inform clients of region3755    // changes.3756    state = state->bindLoc(location.castAs<Loc>(), Val, LC,3757                           /* notifyChanges = */ !AtDeclInit);3758 3759    const MemRegion *LocReg = nullptr;3760    if (std::optional<loc::MemRegionVal> LocRegVal =3761            location.getAs<loc::MemRegionVal>()) {3762      LocReg = LocRegVal->getRegion();3763    }3764 3765    const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);3766    Bldr.generateNode(L, state, PredI);3767  }3768}3769 3770/// evalStore - Handle the semantics of a store via an assignment.3771///  @param Dst The node set to store generated state nodes3772///  @param AssignE The assignment expression if the store happens in an3773///         assignment.3774///  @param LocationE The location expression that is stored to.3775///  @param state The current simulation state3776///  @param location The location to store the value3777///  @param Val The value to be stored3778void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,3779                             const Expr *LocationE,3780                             ExplodedNode *Pred,3781                             ProgramStateRef state, SVal location, SVal Val,3782                             const ProgramPointTag *tag) {3783  // Proceed with the store.  We use AssignE as the anchor for the PostStore3784  // ProgramPoint if it is non-NULL, and LocationE otherwise.3785  const Expr *StoreE = AssignE ? AssignE : LocationE;3786 3787  // Evaluate the location (checks for bad dereferences).3788  ExplodedNodeSet Tmp;3789  evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);3790 3791  if (Tmp.empty())3792    return;3793 3794  if (location.isUndef())3795    return;3796 3797  for (const auto I : Tmp)3798    evalBind(Dst, StoreE, I, location, Val, false);3799}3800 3801void ExprEngine::evalLoad(ExplodedNodeSet &Dst,3802                          const Expr *NodeEx,3803                          const Expr *BoundEx,3804                          ExplodedNode *Pred,3805                          ProgramStateRef state,3806                          SVal location,3807                          const ProgramPointTag *tag,3808                          QualType LoadTy) {3809  assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");3810  assert(NodeEx);3811  assert(BoundEx);3812  // Evaluate the location (checks for bad dereferences).3813  ExplodedNodeSet Tmp;3814  evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);3815  if (Tmp.empty())3816    return;3817 3818  StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx);3819  if (location.isUndef())3820    return;3821 3822  // Proceed with the load.3823  for (const auto I : Tmp) {3824    state = I->getState();3825    const LocationContext *LCtx = I->getLocationContext();3826 3827    SVal V = UnknownVal();3828    if (location.isValid()) {3829      if (LoadTy.isNull())3830        LoadTy = BoundEx->getType();3831      V = state->getSVal(location.castAs<Loc>(), LoadTy);3832    }3833 3834    Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,3835                      ProgramPoint::PostLoadKind);3836  }3837}3838 3839void ExprEngine::evalLocation(ExplodedNodeSet &Dst,3840                              const Stmt *NodeEx,3841                              const Stmt *BoundEx,3842                              ExplodedNode *Pred,3843                              ProgramStateRef state,3844                              SVal location,3845                              bool isLoad) {3846  StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);3847  // Early checks for performance reason.3848  if (location.isUnknown()) {3849    return;3850  }3851 3852  ExplodedNodeSet Src;3853  BldrTop.takeNodes(Pred);3854  StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx);3855  if (Pred->getState() != state) {3856    // Associate this new state with an ExplodedNode.3857    // FIXME: If I pass null tag, the graph is incorrect, e.g for3858    //   int *p;3859    //   p = 0;3860    //   *p = 0xDEADBEEF;3861    // "p = 0" is not noted as "Null pointer value stored to 'p'" but3862    // instead "int *p" is noted as3863    // "Variable 'p' initialized to a null pointer value"3864 3865    static SimpleProgramPointTag tag(TagProviderName, "Location");3866    Bldr.generateNode(NodeEx, Pred, state, &tag);3867  }3868  ExplodedNodeSet Tmp;3869  getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,3870                                             NodeEx, BoundEx, *this);3871  BldrTop.addNodes(Tmp);3872}3873 3874std::pair<const ProgramPointTag *, const ProgramPointTag *>3875ExprEngine::getEagerlyAssumeBifurcationTags() {3876  static SimpleProgramPointTag TrueTag(TagProviderName, "Eagerly Assume True"),3877      FalseTag(TagProviderName, "Eagerly Assume False");3878 3879  return std::make_pair(&TrueTag, &FalseTag);3880}3881 3882/// If the last EagerlyAssume attempt was successful (i.e. the true and false3883/// cases were both feasible), this state trait stores the expression where it3884/// happened; otherwise this holds nullptr.3885REGISTER_TRAIT_WITH_PROGRAMSTATE(LastEagerlyAssumeExprIfSuccessful,3886                                 const Expr *)3887 3888void ExprEngine::evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst,3889                                              ExplodedNodeSet &Src,3890                                              const Expr *Ex) {3891  StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);3892 3893  for (ExplodedNode *Pred : Src) {3894    // Test if the previous node was as the same expression.  This can happen3895    // when the expression fails to evaluate to anything meaningful and3896    // (as an optimization) we don't generate a node.3897    ProgramPoint P = Pred->getLocation();3898    if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {3899      continue;3900    }3901 3902    ProgramStateRef State = Pred->getState();3903    State = State->set<LastEagerlyAssumeExprIfSuccessful>(nullptr);3904    SVal V = State->getSVal(Ex, Pred->getLocationContext());3905    std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();3906    if (SEV && SEV->isExpression()) {3907      const auto &[TrueTag, FalseTag] = getEagerlyAssumeBifurcationTags();3908 3909      auto [StateTrue, StateFalse] = State->assume(*SEV);3910 3911      if (StateTrue && StateFalse) {3912        StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);3913        StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);3914      }3915 3916      // First assume that the condition is true.3917      if (StateTrue) {3918        SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());3919        StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);3920        Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);3921      }3922 3923      // Next, assume that the condition is false.3924      if (StateFalse) {3925        SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());3926        StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);3927        Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);3928      }3929    }3930  }3931}3932 3933bool ExprEngine::didEagerlyAssumeBifurcateAt(ProgramStateRef State,3934                                             const Expr *Ex) const {3935  return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;3936}3937 3938void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,3939                                 ExplodedNodeSet &Dst) {3940  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);3941  // We have processed both the inputs and the outputs.  All of the outputs3942  // should evaluate to Locs.  Nuke all of their values.3943 3944  // FIXME: Some day in the future it would be nice to allow a "plug-in"3945  // which interprets the inline asm and stores proper results in the3946  // outputs.3947 3948  ProgramStateRef state = Pred->getState();3949 3950  for (const Expr *O : A->outputs()) {3951    SVal X = state->getSVal(O, Pred->getLocationContext());3952    assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.3953 3954    if (std::optional<Loc> LV = X.getAs<Loc>())3955      state = state->invalidateRegions(*LV, getCFGElementRef(),3956                                       currBldrCtx->blockCount(),3957                                       Pred->getLocationContext(),3958                                       /*CausedByPointerEscape=*/true);3959  }3960 3961  // Do not reason about locations passed inside inline assembly.3962  for (const Expr *I : A->inputs()) {3963    SVal X = state->getSVal(I, Pred->getLocationContext());3964 3965    if (std::optional<Loc> LV = X.getAs<Loc>())3966      state = state->invalidateRegions(*LV, getCFGElementRef(),3967                                       currBldrCtx->blockCount(),3968                                       Pred->getLocationContext(),3969                                       /*CausedByPointerEscape=*/true);3970  }3971 3972  Bldr.generateNode(A, Pred, state);3973}3974 3975void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,3976                                ExplodedNodeSet &Dst) {3977  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);3978  Bldr.generateNode(A, Pred, Pred->getState());3979}3980 3981//===----------------------------------------------------------------------===//3982// Visualization.3983//===----------------------------------------------------------------------===//3984 3985namespace llvm {3986 3987template<>3988struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {3989  DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}3990 3991  static bool nodeHasBugReport(const ExplodedNode *N) {3992    BugReporter &BR = static_cast<ExprEngine &>(3993      N->getState()->getStateManager().getOwningEngine()).getBugReporter();3994 3995    for (const auto &Class : BR.equivalenceClasses()) {3996      for (const auto &Report : Class.getReports()) {3997        const auto *PR = dyn_cast<PathSensitiveBugReport>(Report.get());3998        if (!PR)3999          continue;4000        const ExplodedNode *EN = PR->getErrorNode();4001        if (EN->getState() == N->getState() &&4002            EN->getLocation() == N->getLocation())4003          return true;4004      }4005    }4006    return false;4007  }4008 4009  /// \p PreCallback: callback before break.4010  /// \p PostCallback: callback after break.4011  /// \p Stop: stop iteration if returns @c true4012  /// \return Whether @c Stop ever returned @c true.4013  static bool traverseHiddenNodes(4014      const ExplodedNode *N,4015      llvm::function_ref<void(const ExplodedNode *)> PreCallback,4016      llvm::function_ref<void(const ExplodedNode *)> PostCallback,4017      llvm::function_ref<bool(const ExplodedNode *)> Stop) {4018    while (true) {4019      PreCallback(N);4020      if (Stop(N))4021        return true;4022 4023      if (N->succ_size() != 1 || !isNodeHidden(N->getFirstSucc(), nullptr))4024        break;4025      PostCallback(N);4026 4027      N = N->getFirstSucc();4028    }4029    return false;4030  }4031 4032  static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G) {4033    return N->isTrivial();4034  }4035 4036  static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){4037    std::string Buf;4038    llvm::raw_string_ostream Out(Buf);4039 4040    const bool IsDot = true;4041    const unsigned int Space = 1;4042    ProgramStateRef State = N->getState();4043 4044    Out << "{ \"state_id\": " << State->getID()4045        << ",\\l";4046 4047    Indent(Out, Space, IsDot) << "\"program_points\": [\\l";4048 4049    // Dump program point for all the previously skipped nodes.4050    traverseHiddenNodes(4051        N,4052        [&](const ExplodedNode *OtherNode) {4053          Indent(Out, Space + 1, IsDot) << "{ ";4054          OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");4055          Out << ", \"tag\": ";4056          if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())4057            Out << '\"' << Tag->getDebugTag() << '\"';4058          else4059            Out << "null";4060          Out << ", \"node_id\": " << OtherNode->getID() <<4061                 ", \"is_sink\": " << OtherNode->isSink() <<4062                 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";4063        },4064        // Adds a comma and a new-line between each program point.4065        [&](const ExplodedNode *) { Out << ",\\l"; },4066        [&](const ExplodedNode *) { return false; });4067 4068    Out << "\\l"; // Adds a new-line to the last program point.4069    Indent(Out, Space, IsDot) << "],\\l";4070 4071    State->printDOT(Out, N->getLocationContext(), Space);4072 4073    Out << "\\l}\\l";4074    return Buf;4075  }4076};4077 4078} // namespace llvm4079 4080void ExprEngine::ViewGraph(bool trim) {4081  std::string Filename = DumpGraph(trim);4082  llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);4083}4084 4085void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode *> Nodes) {4086  std::string Filename = DumpGraph(Nodes);4087  llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);4088}4089 4090std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {4091  if (trim) {4092    std::vector<const ExplodedNode *> Src;4093 4094    // Iterate through the reports and get their nodes.4095    for (const auto &Class : BR.equivalenceClasses()) {4096      const auto *R =4097          dyn_cast<PathSensitiveBugReport>(Class.getReports()[0].get());4098      if (!R)4099        continue;4100      const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());4101      Src.push_back(N);4102    }4103    return DumpGraph(Src, Filename);4104  }4105 4106  return llvm::WriteGraph(&G, "ExprEngine", /*ShortNames=*/false,4107                          /*Title=*/"Exploded Graph",4108                          /*Filename=*/std::string(Filename));4109}4110 4111std::string ExprEngine::DumpGraph(ArrayRef<const ExplodedNode *> Nodes,4112                                  StringRef Filename) {4113  std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));4114 4115  if (!TrimmedG) {4116    llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";4117    return "";4118  }4119 4120  return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",4121                          /*ShortNames=*/false,4122                          /*Title=*/"Trimmed Exploded Graph",4123                          /*Filename=*/std::string(Filename));4124}4125 4126void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {4127  static int index = 0;4128  return &index;4129}4130 4131void ExprEngine::anchor() { }4132 4133void ExprEngine::ConstructInitList(const Expr *E, ArrayRef<Expr *> Args,4134                                   bool IsTransparent, ExplodedNode *Pred,4135                                   ExplodedNodeSet &Dst) {4136  assert((isa<InitListExpr, CXXParenListInitExpr>(E)));4137 4138  const LocationContext *LC = Pred->getLocationContext();4139 4140  StmtNodeBuilder B(Pred, Dst, *currBldrCtx);4141  ProgramStateRef S = Pred->getState();4142  QualType T = E->getType().getCanonicalType();4143 4144  bool IsCompound = T->isArrayType() || T->isRecordType() ||4145                    T->isAnyComplexType() || T->isVectorType();4146 4147  if (Args.size() > 1 || (E->isPRValue() && IsCompound && !IsTransparent)) {4148    llvm::ImmutableList<SVal> ArgList = getBasicVals().getEmptySValList();4149    for (Expr *E : llvm::reverse(Args))4150      ArgList = getBasicVals().prependSVal(S->getSVal(E, LC), ArgList);4151 4152    B.generateNode(E, Pred,4153                   S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));4154  } else {4155    B.generateNode(E, Pred,4156                   S->BindExpr(E, LC,4157                               Args.size() == 04158                                   ? getSValBuilder().makeZeroVal(T)4159                                   : S->getSVal(Args.front(), LC)));4160  }4161}4162