brintos

brintos / llvm-project-archived public Read only

0
0
Text · 52.8 KiB · 00e3ef8 Raw
1256 lines · cpp
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//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 the C++ expression evaluation engine.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/AttrIterator.h"15#include "clang/AST/DeclCXX.h"16#include "clang/AST/ParentMap.h"17#include "clang/AST/StmtCXX.h"18#include "clang/Analysis/ConstructionContext.h"19#include "clang/Basic/PrettyStackTrace.h"20#include "clang/StaticAnalyzer/Core/CheckerManager.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"22#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"23#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"24#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"25#include "llvm/ADT/STLExtras.h"26#include "llvm/ADT/Sequence.h"27#include "llvm/Support/Casting.h"28#include <optional>29 30using namespace clang;31using namespace ento;32 33void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,34                                          ExplodedNode *Pred,35                                          ExplodedNodeSet &Dst) {36  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);37  const Expr *tempExpr = ME->getSubExpr()->IgnoreParens();38  ProgramStateRef state = Pred->getState();39  const LocationContext *LCtx = Pred->getLocationContext();40 41  state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME);42  Bldr.generateNode(ME, Pred, state);43}44 45// FIXME: This is the sort of code that should eventually live in a Core46// checker rather than as a special case in ExprEngine.47void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,48                                    const CallEvent &Call) {49  SVal ThisVal;50  bool AlwaysReturnsLValue;51  [[maybe_unused]] const CXXRecordDecl *ThisRD = nullptr;52  if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {53    assert(Ctor->getDecl()->isTrivial());54    assert(Ctor->getDecl()->isCopyOrMoveConstructor());55    ThisVal = Ctor->getCXXThisVal();56    ThisRD = Ctor->getDecl()->getParent();57    AlwaysReturnsLValue = false;58  } else {59    assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial());60    assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==61           OO_Equal);62    ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();63    ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent();64    AlwaysReturnsLValue = true;65  }66 67  const LocationContext *LCtx = Pred->getLocationContext();68  const Expr *CallExpr = Call.getOriginExpr();69 70  ExplodedNodeSet Dst;71  Bldr.takeNodes(Pred);72 73  assert(ThisRD);74 75  if (!ThisRD->isEmpty()) {76    SVal V = Call.getArgSVal(0);77    const Expr *VExpr = Call.getArgExpr(0);78 79    // If the value being copied is not unknown, load from its location to get80    // an aggregate rvalue.81    if (std::optional<Loc> L = V.getAs<Loc>())82      V = Pred->getState()->getSVal(*L);83    else84      assert(V.isUnknownOrUndef());85 86    ExplodedNodeSet Tmp;87    evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V,88                 /*isLoad=*/true);89    for (ExplodedNode *N : Tmp)90      evalBind(Dst, CallExpr, N, ThisVal, V, !AlwaysReturnsLValue);91  } else {92    // We can't copy empty classes because of empty base class optimization.93    // In that case, copying the empty base class subobject would overwrite the94    // object that it overlaps with - so let's not do that.95    // See issue-157467.cpp for an example.96    Dst.Add(Pred);97  }98 99  PostStmt PS(CallExpr, LCtx);100  for (ExplodedNode *N : Dst) {101    ProgramStateRef State = N->getState();102    if (AlwaysReturnsLValue)103      State = State->BindExpr(CallExpr, LCtx, ThisVal);104    else105      State = bindReturnValue(Call, LCtx, State);106    Bldr.generateNode(PS, State, N);107  }108}109 110SVal ExprEngine::makeElementRegion(ProgramStateRef State, SVal LValue,111                                   QualType &Ty, bool &IsArray, unsigned Idx) {112  SValBuilder &SVB = State->getStateManager().getSValBuilder();113  ASTContext &Ctx = SVB.getContext();114 115  if (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {116    while (AT) {117      Ty = AT->getElementType();118      AT = dyn_cast<ArrayType>(AT->getElementType());119    }120    LValue = State->getLValue(Ty, SVB.makeArrayIndex(Idx), LValue);121    IsArray = true;122  }123 124  return LValue;125}126 127// In case when the prvalue is returned from the function (kind is one of128// SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind), then129// it's materialization happens in context of the caller.130// We pass BldrCtx explicitly, as currBldrCtx always refers to callee's context.131SVal ExprEngine::computeObjectUnderConstruction(132    const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx,133    const LocationContext *LCtx, const ConstructionContext *CC,134    EvalCallOptions &CallOpts, unsigned Idx) {135 136  SValBuilder &SVB = getSValBuilder();137  MemRegionManager &MRMgr = SVB.getRegionManager();138  ASTContext &ACtx = SVB.getContext();139 140  // Compute the target region by exploring the construction context.141  if (CC) {142    switch (CC->getKind()) {143    case ConstructionContext::CXX17ElidedCopyVariableKind:144    case ConstructionContext::SimpleVariableKind: {145      const auto *DSCC = cast<VariableConstructionContext>(CC);146      const auto *DS = DSCC->getDeclStmt();147      const auto *Var = cast<VarDecl>(DS->getSingleDecl());148      QualType Ty = Var->getType();149      return makeElementRegion(State, State->getLValue(Var, LCtx), Ty,150                               CallOpts.IsArrayCtorOrDtor, Idx);151    }152    case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:153    case ConstructionContext::SimpleConstructorInitializerKind: {154      const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);155      const auto *Init = ICC->getCXXCtorInitializer();156      const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());157      Loc ThisPtr = SVB.getCXXThis(CurCtor, LCtx->getStackFrame());158      SVal ThisVal = State->getSVal(ThisPtr);159      if (Init->isBaseInitializer()) {160        const auto *ThisReg = cast<SubRegion>(ThisVal.getAsRegion());161        const CXXRecordDecl *BaseClass =162          Init->getBaseClass()->getAsCXXRecordDecl();163        const auto *BaseReg =164          MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg,165                                       Init->isBaseVirtual());166        return SVB.makeLoc(BaseReg);167      }168      if (Init->isDelegatingInitializer())169        return ThisVal;170 171      const ValueDecl *Field;172      SVal FieldVal;173      if (Init->isIndirectMemberInitializer()) {174        Field = Init->getIndirectMember();175        FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);176      } else {177        Field = Init->getMember();178        FieldVal = State->getLValue(Init->getMember(), ThisVal);179      }180 181      QualType Ty = Field->getType();182      return makeElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor,183                               Idx);184    }185    case ConstructionContext::NewAllocatedObjectKind: {186      if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {187        const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);188        const auto *NE = NECC->getCXXNewExpr();189        SVal V = *getObjectUnderConstruction(State, NE, LCtx);190        if (const SubRegion *MR =191                dyn_cast_or_null<SubRegion>(V.getAsRegion())) {192          if (NE->isArray()) {193            CallOpts.IsArrayCtorOrDtor = true;194 195            auto Ty = NE->getType()->getPointeeType();196            while (const auto *AT = getContext().getAsArrayType(Ty))197              Ty = AT->getElementType();198 199            auto R = MRMgr.getElementRegion(Ty, svalBuilder.makeArrayIndex(Idx),200                                            MR, SVB.getContext());201 202            return loc::MemRegionVal(R);203          }204          return  V;205        }206        // TODO: Detect when the allocator returns a null pointer.207        // Constructor shall not be called in this case.208      }209      break;210    }211    case ConstructionContext::SimpleReturnedValueKind:212    case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {213      // The temporary is to be managed by the parent stack frame.214      // So build it in the parent stack frame if we're not in the215      // top frame of the analysis.216      const StackFrameContext *SFC = LCtx->getStackFrame();217      if (const LocationContext *CallerLCtx = SFC->getParent()) {218        auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]219                       .getAs<CFGCXXRecordTypedCall>();220        if (!RTC) {221          // We were unable to find the correct construction context for the222          // call in the parent stack frame. This is equivalent to not being223          // able to find construction context at all.224          break;225        }226        if (isa<BlockInvocationContext>(CallerLCtx)) {227          // Unwrap block invocation contexts. They're mostly part of228          // the current stack frame.229          CallerLCtx = CallerLCtx->getParent();230          assert(!isa<BlockInvocationContext>(CallerLCtx));231        }232 233        NodeBuilderContext CallerBldrCtx(getCoreEngine(),234                                         SFC->getCallSiteBlock(), CallerLCtx);235        return computeObjectUnderConstruction(236            cast<Expr>(SFC->getCallSite()), State, &CallerBldrCtx, CallerLCtx,237            RTC->getConstructionContext(), CallOpts);238      } else {239        // We are on the top frame of the analysis. We do not know where is the240        // object returned to. Conjure a symbolic region for the return value.241        // TODO: We probably need a new MemRegion kind to represent the storage242        // of that SymbolicRegion, so that we could produce a fancy symbol243        // instead of an anonymous conjured symbol.244        // TODO: Do we need to track the region to avoid having it dead245        // too early? It does die too early, at least in C++17, but because246        // putting anything into a SymbolicRegion causes an immediate escape,247        // it doesn't cause any leak false positives.248        const auto *RCC = cast<ReturnedValueConstructionContext>(CC);249        // Make sure that this doesn't coincide with any other symbol250        // conjured for the returned expression.251        static const int TopLevelSymRegionTag = 0;252        const Expr *RetE = RCC->getReturnStmt()->getRetValue();253        assert(RetE && "Void returns should not have a construction context");254        QualType ReturnTy = RetE->getType();255        QualType RegionTy = ACtx.getPointerType(ReturnTy);256        return SVB.conjureSymbolVal(&TopLevelSymRegionTag, getCFGElementRef(),257                                    SFC, RegionTy, currBldrCtx->blockCount());258      }259      llvm_unreachable("Unhandled return value construction context!");260    }261    case ConstructionContext::ElidedTemporaryObjectKind: {262      assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);263      const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);264 265      // Support pre-C++17 copy elision. We'll have the elidable copy266      // constructor in the AST and in the CFG, but we'll skip it267      // and construct directly into the final object. This call268      // also sets the CallOpts flags for us.269      // If the elided copy/move constructor is not supported, there's still270      // benefit in trying to model the non-elided constructor.271      // Stash our state before trying to elide, as it'll get overwritten.272      ProgramStateRef PreElideState = State;273      EvalCallOptions PreElideCallOpts = CallOpts;274 275      SVal V = computeObjectUnderConstruction(276          TCC->getConstructorAfterElision(), State, BldrCtx, LCtx,277          TCC->getConstructionContextAfterElision(), CallOpts);278 279      // FIXME: This definition of "copy elision has not failed" is unreliable.280      // It doesn't indicate that the constructor will actually be inlined281      // later; this is still up to evalCall() to decide.282      if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion)283        return V;284 285      // Copy elision failed. Revert the changes and proceed as if we have286      // a simple temporary.287      CallOpts = PreElideCallOpts;288      CallOpts.IsElidableCtorThatHasNotBeenElided = true;289      [[fallthrough]];290    }291    case ConstructionContext::SimpleTemporaryObjectKind: {292      const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);293      const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();294 295      CallOpts.IsTemporaryCtorOrDtor = true;296      if (MTE) {297        if (const ValueDecl *VD = MTE->getExtendingDecl()) {298          StorageDuration SD = MTE->getStorageDuration();299          assert(SD != SD_FullExpression);300          if (!VD->getType()->isReferenceType()) {301            // We're lifetime-extended by a surrounding aggregate.302            // Automatic destructors aren't quite working in this case303            // on the CFG side. We should warn the caller about that.304            // FIXME: Is there a better way to retrieve this information from305            // the MaterializeTemporaryExpr?306            CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true;307          }308 309          if (SD == SD_Static || SD == SD_Thread)310            return loc::MemRegionVal(311                MRMgr.getCXXStaticLifetimeExtendedObjectRegion(E, VD));312 313          return loc::MemRegionVal(314              MRMgr.getCXXLifetimeExtendedObjectRegion(E, VD, LCtx));315        }316        assert(MTE->getStorageDuration() == SD_FullExpression);317      }318 319      return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));320    }321    case ConstructionContext::LambdaCaptureKind: {322      CallOpts.IsTemporaryCtorOrDtor = true;323 324      const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);325 326      SVal Base = loc::MemRegionVal(327          MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx));328 329      const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E);330      if (getIndexOfElementToConstruct(State, CE, LCtx)) {331        CallOpts.IsArrayCtorOrDtor = true;332        Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx),333                                Base);334      }335 336      return Base;337    }338    case ConstructionContext::ArgumentKind: {339      // Arguments are technically temporaries.340      CallOpts.IsTemporaryCtorOrDtor = true;341 342      const auto *ACC = cast<ArgumentConstructionContext>(CC);343      const Expr *E = ACC->getCallLikeExpr();344      unsigned Idx = ACC->getIndex();345 346      CallEventManager &CEMgr = getStateManager().getCallEventManager();347      auto getArgLoc = [&](CallEventRef<> Caller) -> std::optional<SVal> {348        const LocationContext *FutureSFC =349            Caller->getCalleeStackFrame(BldrCtx->blockCount());350        // Return early if we are unable to reliably foresee351        // the future stack frame.352        if (!FutureSFC)353          return std::nullopt;354 355        // This should be equivalent to Caller->getDecl() for now, but356        // FutureSFC->getDecl() is likely to support better stuff (like357        // virtual functions) earlier.358        const Decl *CalleeD = FutureSFC->getDecl();359 360        // FIXME: Support for variadic arguments is not implemented here yet.361        if (CallEvent::isVariadic(CalleeD))362          return std::nullopt;363 364        // Operator arguments do not correspond to operator parameters365        // because this-argument is implemented as a normal argument in366        // operator call expressions but not in operator declarations.367        const TypedValueRegion *TVR = Caller->getParameterLocation(368            *Caller->getAdjustedParameterIndex(Idx), BldrCtx->blockCount());369        if (!TVR)370          return std::nullopt;371 372        return loc::MemRegionVal(TVR);373      };374 375      if (const auto *CE = dyn_cast<CallExpr>(E)) {376        CallEventRef<> Caller =377            CEMgr.getSimpleCall(CE, State, LCtx, getCFGElementRef());378        if (std::optional<SVal> V = getArgLoc(Caller))379          return *V;380        else381          break;382      } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) {383        // Don't bother figuring out the target region for the future384        // constructor because we won't need it.385        CallEventRef<> Caller = CEMgr.getCXXConstructorCall(386            CCE, /*Target=*/nullptr, State, LCtx, getCFGElementRef());387        if (std::optional<SVal> V = getArgLoc(Caller))388          return *V;389        else390          break;391      } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {392        CallEventRef<> Caller =393            CEMgr.getObjCMethodCall(ME, State, LCtx, getCFGElementRef());394        if (std::optional<SVal> V = getArgLoc(Caller))395          return *V;396        else397          break;398      }399    }400    } // switch (CC->getKind())401  }402 403  // If we couldn't find an existing region to construct into, assume we're404  // constructing a temporary. Notify the caller of our failure.405  CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;406  return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));407}408 409ProgramStateRef ExprEngine::updateObjectsUnderConstruction(410    SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,411    const ConstructionContext *CC, const EvalCallOptions &CallOpts) {412  if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) {413    // Sounds like we failed to find the target region and therefore414    // copy elision failed. There's nothing we can do about it here.415    return State;416  }417 418  // See if we're constructing an existing region by looking at the419  // current construction context.420  assert(CC && "Computed target region without construction context?");421  switch (CC->getKind()) {422  case ConstructionContext::CXX17ElidedCopyVariableKind:423  case ConstructionContext::SimpleVariableKind: {424    const auto *DSCC = cast<VariableConstructionContext>(CC);425    return addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, V);426    }427    case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:428    case ConstructionContext::SimpleConstructorInitializerKind: {429      const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC);430      const auto *Init = ICC->getCXXCtorInitializer();431      // Base and delegating initializers handled above432      assert(Init->isAnyMemberInitializer() &&433             "Base and delegating initializers should have been handled by"434             "computeObjectUnderConstruction()");435      return addObjectUnderConstruction(State, Init, LCtx, V);436    }437    case ConstructionContext::NewAllocatedObjectKind: {438      return State;439    }440    case ConstructionContext::SimpleReturnedValueKind:441    case ConstructionContext::CXX17ElidedCopyReturnedValueKind: {442      const StackFrameContext *SFC = LCtx->getStackFrame();443      const LocationContext *CallerLCtx = SFC->getParent();444      if (!CallerLCtx) {445        // No extra work is necessary in top frame.446        return State;447      }448 449      auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()]450                     .getAs<CFGCXXRecordTypedCall>();451      assert(RTC && "Could not have had a target region without it");452      if (isa<BlockInvocationContext>(CallerLCtx)) {453        // Unwrap block invocation contexts. They're mostly part of454        // the current stack frame.455        CallerLCtx = CallerLCtx->getParent();456        assert(!isa<BlockInvocationContext>(CallerLCtx));457      }458 459      return updateObjectsUnderConstruction(V,460          cast<Expr>(SFC->getCallSite()), State, CallerLCtx,461          RTC->getConstructionContext(), CallOpts);462    }463    case ConstructionContext::ElidedTemporaryObjectKind: {464      assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);465      if (!CallOpts.IsElidableCtorThatHasNotBeenElided) {466        const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);467        State = updateObjectsUnderConstruction(468            V, TCC->getConstructorAfterElision(), State, LCtx,469            TCC->getConstructionContextAfterElision(), CallOpts);470 471        // Remember that we've elided the constructor.472        State = addObjectUnderConstruction(473            State, TCC->getConstructorAfterElision(), LCtx, V);474 475        // Remember that we've elided the destructor.476        if (const auto *BTE = TCC->getCXXBindTemporaryExpr())477          State = elideDestructor(State, BTE, LCtx);478 479        // Instead of materialization, shamelessly return480        // the final object destination.481        if (const auto *MTE = TCC->getMaterializedTemporaryExpr())482          State = addObjectUnderConstruction(State, MTE, LCtx, V);483 484        return State;485      }486      // If we decided not to elide the constructor, proceed as if487      // it's a simple temporary.488      [[fallthrough]];489    }490    case ConstructionContext::SimpleTemporaryObjectKind: {491      const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);492      if (const auto *BTE = TCC->getCXXBindTemporaryExpr())493        State = addObjectUnderConstruction(State, BTE, LCtx, V);494 495      if (const auto *MTE = TCC->getMaterializedTemporaryExpr())496        State = addObjectUnderConstruction(State, MTE, LCtx, V);497 498      return State;499    }500    case ConstructionContext::LambdaCaptureKind: {501      const auto *LCC = cast<LambdaCaptureConstructionContext>(CC);502 503      // If we capture and array, we want to store the super region, not a504      // sub-region.505      if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion()))506        V = loc::MemRegionVal(EL->getSuperRegion());507 508      return addObjectUnderConstruction(509          State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V);510    }511    case ConstructionContext::ArgumentKind: {512      const auto *ACC = cast<ArgumentConstructionContext>(CC);513      if (const auto *BTE = ACC->getCXXBindTemporaryExpr())514        State = addObjectUnderConstruction(State, BTE, LCtx, V);515 516      return addObjectUnderConstruction(517          State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V);518    }519  }520  llvm_unreachable("Unhandled construction context!");521}522 523static ProgramStateRef524bindRequiredArrayElementToEnvironment(ProgramStateRef State,525                                      const ArrayInitLoopExpr *AILE,526                                      const LocationContext *LCtx, NonLoc Idx) {527  SValBuilder &SVB = State->getStateManager().getSValBuilder();528  MemRegionManager &MRMgr = SVB.getRegionManager();529  ASTContext &Ctx = SVB.getContext();530 531  // HACK: There is no way we can put the index of the array element into the532  // CFG unless we unroll the loop, so we manually select and bind the required533  // parameter to the environment.534  const Expr *SourceArray = AILE->getCommonExpr()->getSourceExpr();535  const auto *Ctor =536      cast<CXXConstructExpr>(extractElementInitializerFromNestedAILE(AILE));537 538  const auto *SourceArrayRegion =539      cast<SubRegion>(State->getSVal(SourceArray, LCtx).getAsRegion());540  const ElementRegion *ElementRegion =541      MRMgr.getElementRegion(Ctor->getType(), Idx, SourceArrayRegion, Ctx);542 543  return State->BindExpr(Ctor->getArg(0), LCtx,544                         loc::MemRegionVal(ElementRegion));545}546 547void ExprEngine::handleConstructor(const Expr *E,548                                   ExplodedNode *Pred,549                                   ExplodedNodeSet &destNodes) {550  const auto *CE = dyn_cast<CXXConstructExpr>(E);551  const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E);552  assert(CE || CIE);553 554  const LocationContext *LCtx = Pred->getLocationContext();555  ProgramStateRef State = Pred->getState();556 557  SVal Target = UnknownVal();558 559  if (CE) {560    if (std::optional<SVal> ElidedTarget =561            getObjectUnderConstruction(State, CE, LCtx)) {562        // We've previously modeled an elidable constructor by pretending that563        // it in fact constructs into the correct target. This constructor can564        // therefore be skipped.565        Target = *ElidedTarget;566        StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);567        State = finishObjectConstruction(State, CE, LCtx);568        if (auto L = Target.getAs<Loc>())569          State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType()));570        Bldr.generateNode(CE, Pred, State);571        return;572    }573  }574 575  EvalCallOptions CallOpts;576  auto C = getCurrentCFGElement().getAs<CFGConstructor>();577  assert(C || getCurrentCFGElement().getAs<CFGStmt>());578  const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;579 580  const CXXConstructionKind CK =581      CE ? CE->getConstructionKind() : CIE->getConstructionKind();582  switch (CK) {583  case CXXConstructionKind::Complete: {584    // Inherited constructors are always base class constructors.585    assert(CE && !CIE && "A complete constructor is inherited?!");586 587    // If the ctor is part of an ArrayInitLoopExpr, we want to handle it588    // differently.589    auto *AILE = CC ? CC->getArrayInitLoop() : nullptr;590 591    unsigned Idx = 0;592    if (CE->getType()->isArrayType() || AILE) {593 594      auto isZeroSizeArray = [&] {595        uint64_t Size = 1;596 597        if (const auto *CAT = dyn_cast<ConstantArrayType>(CE->getType()))598          Size = getContext().getConstantArrayElementCount(CAT);599        else if (AILE)600          Size = getContext().getArrayInitLoopExprElementCount(AILE);601 602        return Size == 0;603      };604 605      // No element construction will happen in a 0 size array.606      if (isZeroSizeArray()) {607        StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx);608        static SimpleProgramPointTag T{"ExprEngine",609                                       "Skipping 0 size array construction"};610        Bldr.generateNode(CE, Pred, State, &T);611        return;612      }613 614      Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u);615      State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1);616    }617 618    if (AILE) {619      // Only set this once even though we loop through it multiple times.620      if (!getPendingInitLoop(State, CE, LCtx))621        State = setPendingInitLoop(622            State, CE, LCtx,623            getContext().getArrayInitLoopExprElementCount(AILE));624 625      State = bindRequiredArrayElementToEnvironment(626          State, AILE, LCtx, svalBuilder.makeArrayIndex(Idx));627    }628 629    // The target region is found from construction context.630    std::tie(State, Target) = handleConstructionContext(631        CE, State, currBldrCtx, LCtx, CC, CallOpts, Idx);632    break;633  }634  case CXXConstructionKind::VirtualBase: {635    // Make sure we are not calling virtual base class initializers twice.636    // Only the most-derived object should initialize virtual base classes.637    const auto *OuterCtor = dyn_cast_or_null<CXXConstructExpr>(638        LCtx->getStackFrame()->getCallSite());639    assert(640        (!OuterCtor ||641         OuterCtor->getConstructionKind() == CXXConstructionKind::Complete ||642         OuterCtor->getConstructionKind() == CXXConstructionKind::Delegating) &&643        ("This virtual base should have already been initialized by "644         "the most derived class!"));645    (void)OuterCtor;646    [[fallthrough]];647  }648  case CXXConstructionKind::NonVirtualBase:649    // In C++17, classes with non-virtual bases may be aggregates, so they would650    // be initialized as aggregates without a constructor call, so we may have651    // a base class constructed directly into an initializer list without652    // having the derived-class constructor call on the previous stack frame.653    // Initializer lists may be nested into more initializer lists that654    // correspond to surrounding aggregate initializations.655    // FIXME: For now this code essentially bails out. We need to find the656    // correct target region and set it.657    // FIXME: Instead of relying on the ParentMap, we should have the658    // trigger-statement (InitListExpr or CXXParenListInitExpr in this case)659    // passed down from CFG or otherwise always available during construction.660    if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(661            LCtx->getParentMap().getParent(E))) {662      MemRegionManager &MRMgr = getSValBuilder().getRegionManager();663      Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx));664      CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;665      break;666    }667    [[fallthrough]];668  case CXXConstructionKind::Delegating: {669    const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());670    Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,671                                              LCtx->getStackFrame());672    SVal ThisVal = State->getSVal(ThisPtr);673 674    if (CK == CXXConstructionKind::Delegating) {675      Target = ThisVal;676    } else {677      // Cast to the base type.678      bool IsVirtual = (CK == CXXConstructionKind::VirtualBase);679      SVal BaseVal =680          getStoreManager().evalDerivedToBase(ThisVal, E->getType(), IsVirtual);681      Target = BaseVal;682    }683    break;684  }685  }686 687  if (State != Pred->getState()) {688    static SimpleProgramPointTag T("ExprEngine",689                                   "Prepare for object construction");690    ExplodedNodeSet DstPrepare;691    StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx);692    BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind);693    assert(DstPrepare.size() <= 1);694    if (DstPrepare.size() == 0)695      return;696    Pred = *BldrPrepare.begin();697  }698 699  const MemRegion *TargetRegion = Target.getAsRegion();700  CallEventManager &CEMgr = getStateManager().getCallEventManager();701  CallEventRef<> Call =702      CIE ? (CallEventRef<>)CEMgr.getCXXInheritedConstructorCall(703                CIE, TargetRegion, State, LCtx, getCFGElementRef())704          : (CallEventRef<>)CEMgr.getCXXConstructorCall(705                CE, TargetRegion, State, LCtx, getCFGElementRef());706 707  ExplodedNodeSet DstPreVisit;708  getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, E, *this);709 710  ExplodedNodeSet PreInitialized;711  if (CE) {712    // FIXME: Is it possible and/or useful to do this before PreStmt?713    StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);714    for (ExplodedNode *N : DstPreVisit) {715      ProgramStateRef State = N->getState();716      if (CE->requiresZeroInitialization()) {717        // FIXME: Once we properly handle constructors in new-expressions, we'll718        // need to invalidate the region before setting a default value, to make719        // sure there aren't any lingering bindings around. This probably needs720        // to happen regardless of whether or not the object is zero-initialized721        // to handle random fields of a placement-initialized object picking up722        // old bindings. We might only want to do it when we need to, though.723        // FIXME: This isn't actually correct for arrays -- we need to zero-724        // initialize the entire array, not just the first element -- but our725        // handling of arrays everywhere else is weak as well, so this shouldn't726        // actually make things worse. Placement new makes this tricky as well,727        // since it's then possible to be initializing one part of a multi-728        // dimensional array.729        const CXXRecordDecl *TargetHeldRecord =730            dyn_cast_or_null<CXXRecordDecl>(CE->getType()->getAsRecordDecl());731 732        if (!TargetHeldRecord || !TargetHeldRecord->isEmpty())733          State = State->bindDefaultZero(Target, LCtx);734      }735 736      Bldr.generateNode(CE, N, State, /*tag=*/nullptr,737                        ProgramPoint::PreStmtKind);738    }739  } else {740    PreInitialized = DstPreVisit;741  }742 743  ExplodedNodeSet DstPreCall;744  getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,745                                            *Call, *this);746 747  ExplodedNodeSet DstEvaluated;748 749  if (CE && CE->getConstructor()->isTrivial() &&750      CE->getConstructor()->isCopyOrMoveConstructor() &&751      !CallOpts.IsArrayCtorOrDtor) {752    StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);753    // FIXME: Handle other kinds of trivial constructors as well.754    for (ExplodedNode *N : DstPreCall)755      performTrivialCopy(Bldr, N, *Call);756 757  } else {758    for (ExplodedNode *N : DstPreCall)759      getCheckerManager().runCheckersForEvalCall(DstEvaluated, N, *Call, *this,760                                                 CallOpts);761  }762 763  // If the CFG was constructed without elements for temporary destructors764  // and the just-called constructor created a temporary object then765  // stop exploration if the temporary object has a noreturn constructor.766  // This can lose coverage because the destructor, if it were present767  // in the CFG, would be called at the end of the full expression or768  // later (for life-time extended temporaries) -- but avoids infeasible769  // paths when no-return temporary destructors are used for assertions.770  ExplodedNodeSet DstEvaluatedPostProcessed;771  StmtNodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx);772  const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext();773  if (!ADC->getCFGBuildOptions().AddTemporaryDtors) {774    if (llvm::isa_and_nonnull<CXXTempObjectRegion,775                              CXXLifetimeExtendedObjectRegion>(TargetRegion) &&776        cast<CXXConstructorDecl>(Call->getDecl())777            ->getParent()778            ->isAnyDestructorNoReturn()) {779 780      // If we've inlined the constructor, then DstEvaluated would be empty.781      // In this case we still want a sink, which could be implemented782      // in processCallExit. But we don't have that implemented at the moment,783      // so if you hit this assertion, see if you can avoid inlining784      // the respective constructor when analyzer-config cfg-temporary-dtors785      // is set to false.786      // Otherwise there's nothing wrong with inlining such constructor.787      assert(!DstEvaluated.empty() &&788             "We should not have inlined this constructor!");789 790      for (ExplodedNode *N : DstEvaluated) {791        Bldr.generateSink(E, N, N->getState());792      }793 794      // There is no need to run the PostCall and PostStmt checker795      // callbacks because we just generated sinks on all nodes in th796      // frontier.797      return;798    }799  }800 801  ExplodedNodeSet DstPostArgumentCleanup;802  for (ExplodedNode *I : DstEvaluatedPostProcessed)803    finishArgumentConstruction(DstPostArgumentCleanup, I, *Call);804 805  // If there were other constructors called for object-type arguments806  // of this constructor, clean them up.807  ExplodedNodeSet DstPostCall;808  getCheckerManager().runCheckersForPostCall(DstPostCall,809                                             DstPostArgumentCleanup,810                                             *Call, *this);811  getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this);812}813 814void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,815                                       ExplodedNode *Pred,816                                       ExplodedNodeSet &Dst) {817  handleConstructor(CE, Pred, Dst);818}819 820void ExprEngine::VisitCXXInheritedCtorInitExpr(821    const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred,822    ExplodedNodeSet &Dst) {823  handleConstructor(CE, Pred, Dst);824}825 826void ExprEngine::VisitCXXDestructor(QualType ObjectType,827                                    const MemRegion *Dest,828                                    const Stmt *S,829                                    bool IsBaseDtor,830                                    ExplodedNode *Pred,831                                    ExplodedNodeSet &Dst,832                                    EvalCallOptions &CallOpts) {833  assert(S && "A destructor without a trigger!");834  const LocationContext *LCtx = Pred->getLocationContext();835  ProgramStateRef State = Pred->getState();836 837  const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();838  assert(RecordDecl && "Only CXXRecordDecls should have destructors");839  const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();840  // FIXME: There should always be a Decl, otherwise the destructor call841  // shouldn't have been added to the CFG in the first place.842  if (!DtorDecl) {843    // Skip the invalid destructor. We cannot simply return because844    // it would interrupt the analysis instead.845    static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");846    // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway.847    PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx,848                        getCFGElementRef(), &T);849    NodeBuilder Bldr(Pred, Dst, *currBldrCtx);850    Bldr.generateNode(PP, Pred->getState(), Pred);851    return;852  }853 854  if (!Dest) {855    // We're trying to destroy something that is not a region. This may happen856    // for a variety of reasons (unknown target region, concrete integer instead857    // of target region, etc.). The current code makes an attempt to recover.858    // FIXME: We probably don't really need to recover when we're dealing859    // with concrete integers specifically.860    CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true;861    if (const Expr *E = dyn_cast_or_null<Expr>(S)) {862      Dest = MRMgr.getCXXTempObjectRegion(E, Pred->getLocationContext());863    } else {864      static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor");865      NodeBuilder Bldr(Pred, Dst, *currBldrCtx);866      Bldr.generateSink(Pred->getLocation().withTag(&T),867                        Pred->getState(), Pred);868      return;869    }870  }871 872  CallEventManager &CEMgr = getStateManager().getCallEventManager();873  CallEventRef<CXXDestructorCall> Call = CEMgr.getCXXDestructorCall(874      DtorDecl, S, Dest, IsBaseDtor, State, LCtx, getCFGElementRef());875 876  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),877                                Call->getSourceRange().getBegin(),878                                "Error evaluating destructor");879 880  ExplodedNodeSet DstPreCall;881  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,882                                            *Call, *this);883 884  ExplodedNodeSet DstInvalidated;885  StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx);886  for (ExplodedNode *N : DstPreCall)887    defaultEvalCall(Bldr, N, *Call, CallOpts);888 889  getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated,890                                             *Call, *this);891}892 893void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,894                                          ExplodedNode *Pred,895                                          ExplodedNodeSet &Dst) {896  ProgramStateRef State = Pred->getState();897  const LocationContext *LCtx = Pred->getLocationContext();898  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),899                                CNE->getBeginLoc(),900                                "Error evaluating New Allocator Call");901  CallEventManager &CEMgr = getStateManager().getCallEventManager();902  CallEventRef<CXXAllocatorCall> Call =903      CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef());904 905  ExplodedNodeSet DstPreCall;906  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred,907                                            *Call, *this);908 909  ExplodedNodeSet DstPostCall;910  StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx);911  for (ExplodedNode *I : DstPreCall) {912    // Operator new calls (CXXNewExpr) are intentionally not eval-called,913    // because it does not make sense to eval-call user-provided functions.914    // 1) If the new operator can be inlined, then don't prevent it from915    //    inlining by having an eval-call of that operator.916    // 2) If it can't be inlined, then the default conservative modeling917    //    is what we want anyway.918    // So the best is to not allow eval-calling CXXNewExprs from checkers.919    // Checkers can provide their pre/post-call callbacks if needed.920    defaultEvalCall(CallBldr, I, *Call);921  }922  // If the call is inlined, DstPostCall will be empty and we bail out now.923 924  // Store return value of operator new() for future use, until the actual925  // CXXNewExpr gets processed.926  ExplodedNodeSet DstPostValue;927  StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx);928  for (ExplodedNode *I : DstPostCall) {929    // FIXME: Because CNE serves as the "call site" for the allocator (due to930    // lack of a better expression in the AST), the conjured return value symbol931    // is going to be of the same type (C++ object pointer type). Technically932    // this is not correct because the operator new's prototype always says that933    // it returns a 'void *'. So we should change the type of the symbol,934    // and then evaluate the cast over the symbolic pointer from 'void *' to935    // the object pointer type. But without changing the symbol's type it936    // is breaking too much to evaluate the no-op symbolic cast over it, so we937    // skip it for now.938    ProgramStateRef State = I->getState();939    SVal RetVal = State->getSVal(CNE, LCtx);940    // [basic.stc.dynamic.allocation] (on the return value of an allocation941    // function):942    // "The order, contiguity, and initial value of storage allocated by943    // successive calls to an allocation function are unspecified."944    State = State->bindDefaultInitial(RetVal, UndefinedVal{}, LCtx);945 946    // If this allocation function is not declared as non-throwing, failures947    // /must/ be signalled by exceptions, and thus the return value will never948    // be NULL. -fno-exceptions does not influence this semantics.949    // FIXME: GCC has a -fcheck-new option, which forces it to consider the case950    // where new can return NULL. If we end up supporting that option, we can951    // consider adding a check for it here.952    // C++11 [basic.stc.dynamic.allocation]p3.953    if (const FunctionDecl *FD = CNE->getOperatorNew()) {954      QualType Ty = FD->getType();955      if (const auto *ProtoType = Ty->getAs<FunctionProtoType>())956        if (!ProtoType->isNothrow())957          State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true);958    }959 960    ValueBldr.generateNode(961        CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal));962  }963 964  ExplodedNodeSet DstPostPostCallCallback;965  getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback,966                                             DstPostValue, *Call, *this);967  for (ExplodedNode *I : DstPostPostCallCallback) {968    getCheckerManager().runCheckersForNewAllocator(*Call, Dst, I, *this);969  }970}971 972void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,973                                   ExplodedNodeSet &Dst) {974  // FIXME: Much of this should eventually migrate to CXXAllocatorCall.975  // Also, we need to decide how allocators actually work -- they're not976  // really part of the CXXNewExpr because they happen BEFORE the977  // CXXConstructExpr subexpression. See PR12014 for some discussion.978 979  unsigned blockCount = currBldrCtx->blockCount();980  const LocationContext *LCtx = Pred->getLocationContext();981  SVal symVal = UnknownVal();982  FunctionDecl *FD = CNE->getOperatorNew();983 984  bool IsStandardGlobalOpNewFunction =985      FD->isReplaceableGlobalAllocationFunction();986 987  ProgramStateRef State = Pred->getState();988 989  // Retrieve the stored operator new() return value.990  if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {991    symVal = *getObjectUnderConstruction(State, CNE, LCtx);992    State = finishObjectConstruction(State, CNE, LCtx);993  }994 995  // We assume all standard global 'operator new' functions allocate memory in996  // heap. We realize this is an approximation that might not correctly model997  // a custom global allocator.998  if (symVal.isUnknown()) {999    if (IsStandardGlobalOpNewFunction)1000      symVal = svalBuilder.getConjuredHeapSymbolVal(getCFGElementRef(), LCtx,1001                                                    CNE->getType(), blockCount);1002    else1003      symVal = svalBuilder.conjureSymbolVal(1004          /*symbolTag=*/nullptr, getCFGElementRef(), LCtx, blockCount);1005  }1006 1007  CallEventManager &CEMgr = getStateManager().getCallEventManager();1008  CallEventRef<CXXAllocatorCall> Call =1009      CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef());1010 1011  if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {1012    // Invalidate placement args.1013    // FIXME: Once we figure out how we want allocators to work,1014    // we should be using the usual pre-/(default-)eval-/post-call checkers1015    // here.1016    State = Call->invalidateRegions(blockCount, State);1017    if (!State)1018      return;1019 1020    // If this allocation function is not declared as non-throwing, failures1021    // /must/ be signalled by exceptions, and thus the return value will never1022    // be NULL. -fno-exceptions does not influence this semantics.1023    // FIXME: GCC has a -fcheck-new option, which forces it to consider the case1024    // where new can return NULL. If we end up supporting that option, we can1025    // consider adding a check for it here.1026    // C++11 [basic.stc.dynamic.allocation]p3.1027    if (const auto *ProtoType = FD->getType()->getAs<FunctionProtoType>())1028      if (!ProtoType->isNothrow())1029        if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>())1030          State = State->assume(*dSymVal, true);1031  }1032 1033  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);1034 1035  SVal Result = symVal;1036 1037  if (CNE->isArray()) {1038 1039    if (const auto *NewReg = cast_or_null<SubRegion>(symVal.getAsRegion())) {1040      // If each element is initialized by their default constructor, the field1041      // values are properly placed inside the required region, however if an1042      // initializer list is used, this doesn't happen automatically.1043      auto *Init = CNE->getInitializer();1044      bool isInitList =1045          isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(Init);1046 1047      QualType ObjTy =1048          isInitList ? Init->getType() : CNE->getType()->getPointeeType();1049      const ElementRegion *EleReg =1050          MRMgr.getElementRegion(ObjTy, svalBuilder.makeArrayIndex(0), NewReg,1051                                 svalBuilder.getContext());1052      Result = loc::MemRegionVal(EleReg);1053 1054      // If the array is list initialized, we bind the initializer list to the1055      // memory region here, otherwise we would lose it.1056      if (isInitList) {1057        Bldr.takeNodes(Pred);1058        Pred = Bldr.generateNode(CNE, Pred, State);1059 1060        SVal V = State->getSVal(Init, LCtx);1061        ExplodedNodeSet evaluated;1062        evalBind(evaluated, CNE, Pred, Result, V, true);1063 1064        Bldr.takeNodes(Pred);1065        Bldr.addNodes(evaluated);1066 1067        Pred = *evaluated.begin();1068        State = Pred->getState();1069      }1070    }1071 1072    State = State->BindExpr(CNE, Pred->getLocationContext(), Result);1073    Bldr.generateNode(CNE, Pred, State);1074    return;1075  }1076 1077  // FIXME: Once we have proper support for CXXConstructExprs inside1078  // CXXNewExpr, we need to make sure that the constructed object is not1079  // immediately invalidated here. (The placement call should happen before1080  // the constructor call anyway.)1081  if (FD->isReservedGlobalPlacementOperator()) {1082    // Non-array placement new should always return the placement location.1083    SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);1084    Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(),1085                                  CNE->getPlacementArg(0)->getType());1086  }1087 1088  // Bind the address of the object, then check to see if we cached out.1089  State = State->BindExpr(CNE, LCtx, Result);1090  ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State);1091  if (!NewN)1092    return;1093 1094  // If the type is not a record, we won't have a CXXConstructExpr as an1095  // initializer. Copy the value over.1096  if (const Expr *Init = CNE->getInitializer()) {1097    if (!isa<CXXConstructExpr>(Init)) {1098      assert(Bldr.getResults().size() == 1);1099      Bldr.takeNodes(NewN);1100      evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx),1101               /*FirstInit=*/IsStandardGlobalOpNewFunction);1102    }1103  }1104}1105 1106void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,1107                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {1108 1109  CallEventManager &CEMgr = getStateManager().getCallEventManager();1110  CallEventRef<CXXDeallocatorCall> Call = CEMgr.getCXXDeallocatorCall(1111      CDE, Pred->getState(), Pred->getLocationContext(), getCFGElementRef());1112 1113  ExplodedNodeSet DstPreCall;1114  getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this);1115  ExplodedNodeSet DstPostCall;1116 1117  if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {1118    StmtNodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx);1119    for (ExplodedNode *I : DstPreCall) {1120      // Intentionally either inline or conservative eval-call the operator1121      // delete, but avoid triggering an eval-call event for checkers.1122      // As detailed at handling CXXNewExprs, in short, because it does not1123      // really make sense to eval-call user-provided functions.1124      defaultEvalCall(Bldr, I, *Call);1125    }1126  } else {1127    DstPostCall = DstPreCall;1128  }1129  getCheckerManager().runCheckersForPostCall(Dst, DstPostCall, *Call, *this);1130}1131 1132void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,1133                                   ExplodedNodeSet &Dst) {1134  const VarDecl *VD = CS->getExceptionDecl();1135  if (!VD) {1136    Dst.Add(Pred);1137    return;1138  }1139 1140  const LocationContext *LCtx = Pred->getLocationContext();1141  SVal V = svalBuilder.conjureSymbolVal(getCFGElementRef(), LCtx, VD->getType(),1142                                        currBldrCtx->blockCount());1143  ProgramStateRef state = Pred->getState();1144  state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);1145 1146  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);1147  Bldr.generateNode(CS, Pred, state);1148}1149 1150void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,1151                                    ExplodedNodeSet &Dst) {1152  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);1153 1154  // Get the this object region from StoreManager.1155  const LocationContext *LCtx = Pred->getLocationContext();1156  const MemRegion *R =1157    svalBuilder.getRegionManager().getCXXThisRegion(1158                                  getContext().getCanonicalType(TE->getType()),1159                                                    LCtx);1160 1161  ProgramStateRef state = Pred->getState();1162  SVal V = state->getSVal(loc::MemRegionVal(R));1163  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));1164}1165 1166void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,1167                                 ExplodedNodeSet &Dst) {1168  const LocationContext *LocCtxt = Pred->getLocationContext();1169 1170  // Get the region of the lambda itself.1171  const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(1172      LE, LocCtxt);1173  SVal V = loc::MemRegionVal(R);1174 1175  ProgramStateRef State = Pred->getState();1176 1177  // If we created a new MemRegion for the lambda, we should explicitly bind1178  // the captures.1179  for (auto const [Idx, FieldForCapture, InitExpr] :1180       llvm::zip(llvm::seq<unsigned>(0, -1), LE->getLambdaClass()->fields(),1181                 LE->capture_inits())) {1182    SVal FieldLoc = State->getLValue(FieldForCapture, V);1183 1184    SVal InitVal;1185    if (!FieldForCapture->hasCapturedVLAType()) {1186      assert(InitExpr && "Capture missing initialization expression");1187 1188      // Capturing a 0 length array is a no-op, so we ignore it to get a more1189      // accurate analysis. If it's not ignored, it would set the default1190      // binding of the lambda to 'Unknown', which can lead to falsely detecting1191      // 'Uninitialized' values as 'Unknown' and not reporting a warning.1192      const auto FTy = FieldForCapture->getType();1193      if (FTy->isConstantArrayType() &&1194          getContext().getConstantArrayElementCount(1195              getContext().getAsConstantArrayType(FTy)) == 0)1196        continue;1197 1198      // With C++17 copy elision the InitExpr can be anything, so instead of1199      // pattern matching all cases, we simple check if the current field is1200      // under construction or not, regardless what it's InitExpr is.1201      if (const auto OUC =1202              getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) {1203        InitVal = State->getSVal(OUC->getAsRegion());1204 1205        State = finishObjectConstruction(State, {LE, Idx}, LocCtxt);1206      } else1207        InitVal = State->getSVal(InitExpr, LocCtxt);1208 1209    } else {1210 1211      assert(!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) &&1212             "VLA capture by value is a compile time error!");1213 1214      // The field stores the length of a captured variable-length array.1215      // These captures don't have initialization expressions; instead we1216      // get the length from the VLAType size expression.1217      Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr();1218      InitVal = State->getSVal(SizeExpr, LocCtxt);1219    }1220 1221    State = State->bindLoc(FieldLoc, InitVal, LocCtxt);1222  }1223 1224  // Decay the Loc into an RValue, because there might be a1225  // MaterializeTemporaryExpr node above this one which expects the bound value1226  // to be an RValue.1227  SVal LambdaRVal = State->getSVal(R);1228 1229  ExplodedNodeSet Tmp;1230  StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);1231  // FIXME: is this the right program point kind?1232  Bldr.generateNode(LE, Pred,1233                    State->BindExpr(LE, LocCtxt, LambdaRVal),1234                    nullptr, ProgramPoint::PostLValueKind);1235 1236  // FIXME: Move all post/pre visits to ::Visit().1237  getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this);1238}1239 1240void ExprEngine::VisitAttributedStmt(const AttributedStmt *A,1241                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {1242  ExplodedNodeSet CheckerPreStmt;1243  getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);1244 1245  ExplodedNodeSet EvalSet;1246  StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);1247 1248  for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(A->getAttrs())) {1249    for (ExplodedNode *N : CheckerPreStmt) {1250      Visit(Attr->getAssumption()->IgnoreParens(), N, EvalSet);1251    }1252  }1253 1254  getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);1255}1256