10b57cec5SDimitry Andric //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the C++ expression evaluation engine. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 140b57cec5SDimitry Andric #include "clang/AST/ParentMap.h" 15bdd1243dSDimitry Andric #include "clang/AST/StmtCXX.h" 16bdd1243dSDimitry Andric #include "clang/Analysis/ConstructionContext.h" 170b57cec5SDimitry Andric #include "clang/Basic/PrettyStackTrace.h" 180b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h" 190b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 200b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 21bdd1243dSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 22bdd1243dSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 2306c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h" 2406c3fb27SDimitry Andric #include "llvm/ADT/Sequence.h" 25bdd1243dSDimitry Andric #include <optional> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace clang; 280b57cec5SDimitry Andric using namespace ento; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 310b57cec5SDimitry Andric ExplodedNode *Pred, 320b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 330b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 34480093f4SDimitry Andric const Expr *tempExpr = ME->getSubExpr()->IgnoreParens(); 350b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 360b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); 390b57cec5SDimitry Andric Bldr.generateNode(ME, Pred, state); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric // FIXME: This is the sort of code that should eventually live in a Core 430b57cec5SDimitry Andric // checker rather than as a special case in ExprEngine. 440b57cec5SDimitry Andric void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 450b57cec5SDimitry Andric const CallEvent &Call) { 460b57cec5SDimitry Andric SVal ThisVal; 470b57cec5SDimitry Andric bool AlwaysReturnsLValue; 480b57cec5SDimitry Andric const CXXRecordDecl *ThisRD = nullptr; 490b57cec5SDimitry Andric if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 500b57cec5SDimitry Andric assert(Ctor->getDecl()->isTrivial()); 510b57cec5SDimitry Andric assert(Ctor->getDecl()->isCopyOrMoveConstructor()); 520b57cec5SDimitry Andric ThisVal = Ctor->getCXXThisVal(); 530b57cec5SDimitry Andric ThisRD = Ctor->getDecl()->getParent(); 540b57cec5SDimitry Andric AlwaysReturnsLValue = false; 550b57cec5SDimitry Andric } else { 560b57cec5SDimitry Andric assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); 570b57cec5SDimitry Andric assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == 580b57cec5SDimitry Andric OO_Equal); 590b57cec5SDimitry Andric ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); 600b57cec5SDimitry Andric ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent(); 610b57cec5SDimitry Andric AlwaysReturnsLValue = true; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 6506c3fb27SDimitry Andric const Expr *CallExpr = Call.getOriginExpr(); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric ExplodedNodeSet Dst; 680b57cec5SDimitry Andric Bldr.takeNodes(Pred); 690b57cec5SDimitry Andric 7006c3fb27SDimitry Andric assert(ThisRD); 7106c3fb27SDimitry Andric if (!ThisRD->isEmpty()) { 7206c3fb27SDimitry Andric // Load the source value only for non-empty classes. 7306c3fb27SDimitry Andric // Otherwise it'd retrieve an UnknownVal 7406c3fb27SDimitry Andric // and bind it and RegionStore would think that the actual value 7506c3fb27SDimitry Andric // in this region at this offset is unknown. 760b57cec5SDimitry Andric SVal V = Call.getArgSVal(0); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // If the value being copied is not unknown, load from its location to get 790b57cec5SDimitry Andric // an aggregate rvalue. 80bdd1243dSDimitry Andric if (std::optional<Loc> L = V.getAs<Loc>()) 810b57cec5SDimitry Andric V = Pred->getState()->getSVal(*L); 820b57cec5SDimitry Andric else 830b57cec5SDimitry Andric assert(V.isUnknownOrUndef()); 840b57cec5SDimitry Andric evalBind(Dst, CallExpr, Pred, ThisVal, V, true); 8506c3fb27SDimitry Andric } else { 8606c3fb27SDimitry Andric Dst.Add(Pred); 8706c3fb27SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric PostStmt PS(CallExpr, LCtx); 9006c3fb27SDimitry Andric for (ExplodedNode *N : Dst) { 9106c3fb27SDimitry Andric ProgramStateRef State = N->getState(); 920b57cec5SDimitry Andric if (AlwaysReturnsLValue) 930b57cec5SDimitry Andric State = State->BindExpr(CallExpr, LCtx, ThisVal); 940b57cec5SDimitry Andric else 950b57cec5SDimitry Andric State = bindReturnValue(Call, LCtx, State); 9606c3fb27SDimitry Andric Bldr.generateNode(PS, State, N); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 100fcaf7f86SDimitry Andric SVal ExprEngine::makeElementRegion(ProgramStateRef State, SVal LValue, 101fcaf7f86SDimitry Andric QualType &Ty, bool &IsArray, unsigned Idx) { 1020b57cec5SDimitry Andric SValBuilder &SVB = State->getStateManager().getSValBuilder(); 1030b57cec5SDimitry Andric ASTContext &Ctx = SVB.getContext(); 1040b57cec5SDimitry Andric 105fcaf7f86SDimitry Andric if (const ArrayType *AT = Ctx.getAsArrayType(Ty)) { 106fcaf7f86SDimitry Andric while (AT) { 1070b57cec5SDimitry Andric Ty = AT->getElementType(); 108fcaf7f86SDimitry Andric AT = dyn_cast<ArrayType>(AT->getElementType()); 109fcaf7f86SDimitry Andric } 110fcaf7f86SDimitry Andric LValue = State->getLValue(Ty, SVB.makeArrayIndex(Idx), LValue); 1110b57cec5SDimitry Andric IsArray = true; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric return LValue; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 117bdd1243dSDimitry Andric // In case when the prvalue is returned from the function (kind is one of 118bdd1243dSDimitry Andric // SimpleReturnedValueKind, CXX17ElidedCopyReturnedValueKind), then 119bdd1243dSDimitry Andric // it's materialization happens in context of the caller. 120bdd1243dSDimitry Andric // We pass BldrCtx explicitly, as currBldrCtx always refers to callee's context. 1215ffd83dbSDimitry Andric SVal ExprEngine::computeObjectUnderConstruction( 122bdd1243dSDimitry Andric const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx, 123bdd1243dSDimitry Andric const LocationContext *LCtx, const ConstructionContext *CC, 124bdd1243dSDimitry Andric EvalCallOptions &CallOpts, unsigned Idx) { 125bdd1243dSDimitry Andric 1260b57cec5SDimitry Andric SValBuilder &SVB = getSValBuilder(); 1270b57cec5SDimitry Andric MemRegionManager &MRMgr = SVB.getRegionManager(); 1280b57cec5SDimitry Andric ASTContext &ACtx = SVB.getContext(); 1290b57cec5SDimitry Andric 1305ffd83dbSDimitry Andric // Compute the target region by exploring the construction context. 1310b57cec5SDimitry Andric if (CC) { 1320b57cec5SDimitry Andric switch (CC->getKind()) { 1330b57cec5SDimitry Andric case ConstructionContext::CXX17ElidedCopyVariableKind: 1340b57cec5SDimitry Andric case ConstructionContext::SimpleVariableKind: { 1350b57cec5SDimitry Andric const auto *DSCC = cast<VariableConstructionContext>(CC); 1360b57cec5SDimitry Andric const auto *DS = DSCC->getDeclStmt(); 1370b57cec5SDimitry Andric const auto *Var = cast<VarDecl>(DS->getSingleDecl()); 1380b57cec5SDimitry Andric QualType Ty = Var->getType(); 139fcaf7f86SDimitry Andric return makeElementRegion(State, State->getLValue(Var, LCtx), Ty, 140fcaf7f86SDimitry Andric CallOpts.IsArrayCtorOrDtor, Idx); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: 1430b57cec5SDimitry Andric case ConstructionContext::SimpleConstructorInitializerKind: { 1440b57cec5SDimitry Andric const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC); 1450b57cec5SDimitry Andric const auto *Init = ICC->getCXXCtorInitializer(); 1460b57cec5SDimitry Andric const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 1475ffd83dbSDimitry Andric Loc ThisPtr = SVB.getCXXThis(CurCtor, LCtx->getStackFrame()); 1480b57cec5SDimitry Andric SVal ThisVal = State->getSVal(ThisPtr); 149e8d8bef9SDimitry Andric if (Init->isBaseInitializer()) { 150e8d8bef9SDimitry Andric const auto *ThisReg = cast<SubRegion>(ThisVal.getAsRegion()); 151e8d8bef9SDimitry Andric const CXXRecordDecl *BaseClass = 152e8d8bef9SDimitry Andric Init->getBaseClass()->getAsCXXRecordDecl(); 153e8d8bef9SDimitry Andric const auto *BaseReg = 154e8d8bef9SDimitry Andric MRMgr.getCXXBaseObjectRegion(BaseClass, ThisReg, 155e8d8bef9SDimitry Andric Init->isBaseVirtual()); 156e8d8bef9SDimitry Andric return SVB.makeLoc(BaseReg); 157e8d8bef9SDimitry Andric } 158e8d8bef9SDimitry Andric if (Init->isDelegatingInitializer()) 159e8d8bef9SDimitry Andric return ThisVal; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric const ValueDecl *Field; 1620b57cec5SDimitry Andric SVal FieldVal; 1630b57cec5SDimitry Andric if (Init->isIndirectMemberInitializer()) { 1640b57cec5SDimitry Andric Field = Init->getIndirectMember(); 1650b57cec5SDimitry Andric FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); 1660b57cec5SDimitry Andric } else { 1670b57cec5SDimitry Andric Field = Init->getMember(); 1680b57cec5SDimitry Andric FieldVal = State->getLValue(Init->getMember(), ThisVal); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric QualType Ty = Field->getType(); 172fcaf7f86SDimitry Andric return makeElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor, 173fcaf7f86SDimitry Andric Idx); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric case ConstructionContext::NewAllocatedObjectKind: { 1760b57cec5SDimitry Andric if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { 1770b57cec5SDimitry Andric const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC); 1780b57cec5SDimitry Andric const auto *NE = NECC->getCXXNewExpr(); 1790b57cec5SDimitry Andric SVal V = *getObjectUnderConstruction(State, NE, LCtx); 1800b57cec5SDimitry Andric if (const SubRegion *MR = 1810b57cec5SDimitry Andric dyn_cast_or_null<SubRegion>(V.getAsRegion())) { 1820b57cec5SDimitry Andric if (NE->isArray()) { 1830b57cec5SDimitry Andric CallOpts.IsArrayCtorOrDtor = true; 184fcaf7f86SDimitry Andric 185bdd1243dSDimitry Andric auto Ty = NE->getType()->getPointeeType(); 186bdd1243dSDimitry Andric while (const auto *AT = getContext().getAsArrayType(Ty)) 187bdd1243dSDimitry Andric Ty = AT->getElementType(); 188bdd1243dSDimitry Andric 189bdd1243dSDimitry Andric auto R = MRMgr.getElementRegion(Ty, svalBuilder.makeArrayIndex(Idx), 190bdd1243dSDimitry Andric MR, SVB.getContext()); 191fcaf7f86SDimitry Andric 192fcaf7f86SDimitry Andric return loc::MemRegionVal(R); 1930b57cec5SDimitry Andric } 1945ffd83dbSDimitry Andric return V; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric // TODO: Detect when the allocator returns a null pointer. 1970b57cec5SDimitry Andric // Constructor shall not be called in this case. 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric break; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric case ConstructionContext::SimpleReturnedValueKind: 2020b57cec5SDimitry Andric case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { 2030b57cec5SDimitry Andric // The temporary is to be managed by the parent stack frame. 2040b57cec5SDimitry Andric // So build it in the parent stack frame if we're not in the 2050b57cec5SDimitry Andric // top frame of the analysis. 2060b57cec5SDimitry Andric const StackFrameContext *SFC = LCtx->getStackFrame(); 2070b57cec5SDimitry Andric if (const LocationContext *CallerLCtx = SFC->getParent()) { 2080b57cec5SDimitry Andric auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()] 2090b57cec5SDimitry Andric .getAs<CFGCXXRecordTypedCall>(); 2100b57cec5SDimitry Andric if (!RTC) { 2110b57cec5SDimitry Andric // We were unable to find the correct construction context for the 2120b57cec5SDimitry Andric // call in the parent stack frame. This is equivalent to not being 2130b57cec5SDimitry Andric // able to find construction context at all. 2140b57cec5SDimitry Andric break; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric if (isa<BlockInvocationContext>(CallerLCtx)) { 2170b57cec5SDimitry Andric // Unwrap block invocation contexts. They're mostly part of 2180b57cec5SDimitry Andric // the current stack frame. 2190b57cec5SDimitry Andric CallerLCtx = CallerLCtx->getParent(); 2200b57cec5SDimitry Andric assert(!isa<BlockInvocationContext>(CallerLCtx)); 2210b57cec5SDimitry Andric } 222bdd1243dSDimitry Andric 223bdd1243dSDimitry Andric NodeBuilderContext CallerBldrCtx(getCoreEngine(), 224bdd1243dSDimitry Andric SFC->getCallSiteBlock(), CallerLCtx); 2255ffd83dbSDimitry Andric return computeObjectUnderConstruction( 226bdd1243dSDimitry Andric cast<Expr>(SFC->getCallSite()), State, &CallerBldrCtx, CallerLCtx, 2270b57cec5SDimitry Andric RTC->getConstructionContext(), CallOpts); 2280b57cec5SDimitry Andric } else { 2290b57cec5SDimitry Andric // We are on the top frame of the analysis. We do not know where is the 2300b57cec5SDimitry Andric // object returned to. Conjure a symbolic region for the return value. 2310b57cec5SDimitry Andric // TODO: We probably need a new MemRegion kind to represent the storage 232*0fca6ea1SDimitry Andric // of that SymbolicRegion, so that we could produce a fancy symbol 2330b57cec5SDimitry Andric // instead of an anonymous conjured symbol. 2340b57cec5SDimitry Andric // TODO: Do we need to track the region to avoid having it dead 2350b57cec5SDimitry Andric // too early? It does die too early, at least in C++17, but because 2360b57cec5SDimitry Andric // putting anything into a SymbolicRegion causes an immediate escape, 2370b57cec5SDimitry Andric // it doesn't cause any leak false positives. 2380b57cec5SDimitry Andric const auto *RCC = cast<ReturnedValueConstructionContext>(CC); 2390b57cec5SDimitry Andric // Make sure that this doesn't coincide with any other symbol 2400b57cec5SDimitry Andric // conjured for the returned expression. 2410b57cec5SDimitry Andric static const int TopLevelSymRegionTag = 0; 2420b57cec5SDimitry Andric const Expr *RetE = RCC->getReturnStmt()->getRetValue(); 2430b57cec5SDimitry Andric assert(RetE && "Void returns should not have a construction context"); 2440b57cec5SDimitry Andric QualType ReturnTy = RetE->getType(); 2450b57cec5SDimitry Andric QualType RegionTy = ACtx.getPointerType(ReturnTy); 2465ffd83dbSDimitry Andric return SVB.conjureSymbolVal(&TopLevelSymRegionTag, RetE, SFC, RegionTy, 2475ffd83dbSDimitry Andric currBldrCtx->blockCount()); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric llvm_unreachable("Unhandled return value construction context!"); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric case ConstructionContext::ElidedTemporaryObjectKind: { 2520b57cec5SDimitry Andric assert(AMgr.getAnalyzerOptions().ShouldElideConstructors); 2530b57cec5SDimitry Andric const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC); 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // Support pre-C++17 copy elision. We'll have the elidable copy 2560b57cec5SDimitry Andric // constructor in the AST and in the CFG, but we'll skip it 2570b57cec5SDimitry Andric // and construct directly into the final object. This call 2580b57cec5SDimitry Andric // also sets the CallOpts flags for us. 2590b57cec5SDimitry Andric // If the elided copy/move constructor is not supported, there's still 2600b57cec5SDimitry Andric // benefit in trying to model the non-elided constructor. 2610b57cec5SDimitry Andric // Stash our state before trying to elide, as it'll get overwritten. 2620b57cec5SDimitry Andric ProgramStateRef PreElideState = State; 2630b57cec5SDimitry Andric EvalCallOptions PreElideCallOpts = CallOpts; 2640b57cec5SDimitry Andric 2655ffd83dbSDimitry Andric SVal V = computeObjectUnderConstruction( 266bdd1243dSDimitry Andric TCC->getConstructorAfterElision(), State, BldrCtx, LCtx, 2675ffd83dbSDimitry Andric TCC->getConstructionContextAfterElision(), CallOpts); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric // FIXME: This definition of "copy elision has not failed" is unreliable. 2700b57cec5SDimitry Andric // It doesn't indicate that the constructor will actually be inlined 2715ffd83dbSDimitry Andric // later; this is still up to evalCall() to decide. 2725ffd83dbSDimitry Andric if (!CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) 2735ffd83dbSDimitry Andric return V; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric // Copy elision failed. Revert the changes and proceed as if we have 2760b57cec5SDimitry Andric // a simple temporary. 2770b57cec5SDimitry Andric CallOpts = PreElideCallOpts; 2785ffd83dbSDimitry Andric CallOpts.IsElidableCtorThatHasNotBeenElided = true; 279bdd1243dSDimitry Andric [[fallthrough]]; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric case ConstructionContext::SimpleTemporaryObjectKind: { 2820b57cec5SDimitry Andric const auto *TCC = cast<TemporaryObjectConstructionContext>(CC); 2830b57cec5SDimitry Andric const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); 2840b57cec5SDimitry Andric 2855ffd83dbSDimitry Andric CallOpts.IsTemporaryCtorOrDtor = true; 2860b57cec5SDimitry Andric if (MTE) { 2870b57cec5SDimitry Andric if (const ValueDecl *VD = MTE->getExtendingDecl()) { 28806c3fb27SDimitry Andric StorageDuration SD = MTE->getStorageDuration(); 28906c3fb27SDimitry Andric assert(SD != SD_FullExpression); 2900b57cec5SDimitry Andric if (!VD->getType()->isReferenceType()) { 2910b57cec5SDimitry Andric // We're lifetime-extended by a surrounding aggregate. 2920b57cec5SDimitry Andric // Automatic destructors aren't quite working in this case 2930b57cec5SDimitry Andric // on the CFG side. We should warn the caller about that. 2940b57cec5SDimitry Andric // FIXME: Is there a better way to retrieve this information from 2950b57cec5SDimitry Andric // the MaterializeTemporaryExpr? 2960b57cec5SDimitry Andric CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true; 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 29906c3fb27SDimitry Andric if (SD == SD_Static || SD == SD_Thread) 30006c3fb27SDimitry Andric return loc::MemRegionVal( 30106c3fb27SDimitry Andric MRMgr.getCXXStaticLifetimeExtendedObjectRegion(E, VD)); 30206c3fb27SDimitry Andric 30306c3fb27SDimitry Andric return loc::MemRegionVal( 30406c3fb27SDimitry Andric MRMgr.getCXXLifetimeExtendedObjectRegion(E, VD, LCtx)); 30506c3fb27SDimitry Andric } 30606c3fb27SDimitry Andric assert(MTE->getStorageDuration() == SD_FullExpression); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3095ffd83dbSDimitry Andric return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); 3100b57cec5SDimitry Andric } 311972a253aSDimitry Andric case ConstructionContext::LambdaCaptureKind: { 312972a253aSDimitry Andric CallOpts.IsTemporaryCtorOrDtor = true; 313972a253aSDimitry Andric 314972a253aSDimitry Andric const auto *LCC = cast<LambdaCaptureConstructionContext>(CC); 315972a253aSDimitry Andric 316972a253aSDimitry Andric SVal Base = loc::MemRegionVal( 317972a253aSDimitry Andric MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx)); 318972a253aSDimitry Andric 319972a253aSDimitry Andric const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E); 320972a253aSDimitry Andric if (getIndexOfElementToConstruct(State, CE, LCtx)) { 321972a253aSDimitry Andric CallOpts.IsArrayCtorOrDtor = true; 322972a253aSDimitry Andric Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx), 323972a253aSDimitry Andric Base); 324972a253aSDimitry Andric } 325972a253aSDimitry Andric 326972a253aSDimitry Andric return Base; 327972a253aSDimitry Andric } 3280b57cec5SDimitry Andric case ConstructionContext::ArgumentKind: { 3290b57cec5SDimitry Andric // Arguments are technically temporaries. 3300b57cec5SDimitry Andric CallOpts.IsTemporaryCtorOrDtor = true; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric const auto *ACC = cast<ArgumentConstructionContext>(CC); 3330b57cec5SDimitry Andric const Expr *E = ACC->getCallLikeExpr(); 3340b57cec5SDimitry Andric unsigned Idx = ACC->getIndex(); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 337bdd1243dSDimitry Andric auto getArgLoc = [&](CallEventRef<> Caller) -> std::optional<SVal> { 338a7dea167SDimitry Andric const LocationContext *FutureSFC = 339bdd1243dSDimitry Andric Caller->getCalleeStackFrame(BldrCtx->blockCount()); 3400b57cec5SDimitry Andric // Return early if we are unable to reliably foresee 3410b57cec5SDimitry Andric // the future stack frame. 3420b57cec5SDimitry Andric if (!FutureSFC) 343bdd1243dSDimitry Andric return std::nullopt; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // This should be equivalent to Caller->getDecl() for now, but 3460b57cec5SDimitry Andric // FutureSFC->getDecl() is likely to support better stuff (like 3470b57cec5SDimitry Andric // virtual functions) earlier. 3480b57cec5SDimitry Andric const Decl *CalleeD = FutureSFC->getDecl(); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // FIXME: Support for variadic arguments is not implemented here yet. 3510b57cec5SDimitry Andric if (CallEvent::isVariadic(CalleeD)) 352bdd1243dSDimitry Andric return std::nullopt; 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric // Operator arguments do not correspond to operator parameters 3550b57cec5SDimitry Andric // because this-argument is implemented as a normal argument in 3560b57cec5SDimitry Andric // operator call expressions but not in operator declarations. 3575ffd83dbSDimitry Andric const TypedValueRegion *TVR = Caller->getParameterLocation( 358bdd1243dSDimitry Andric *Caller->getAdjustedParameterIndex(Idx), BldrCtx->blockCount()); 3595ffd83dbSDimitry Andric if (!TVR) 360bdd1243dSDimitry Andric return std::nullopt; 3610b57cec5SDimitry Andric 3625ffd83dbSDimitry Andric return loc::MemRegionVal(TVR); 3630b57cec5SDimitry Andric }; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric if (const auto *CE = dyn_cast<CallExpr>(E)) { 36606c3fb27SDimitry Andric CallEventRef<> Caller = 36706c3fb27SDimitry Andric CEMgr.getSimpleCall(CE, State, LCtx, getCFGElementRef()); 368bdd1243dSDimitry Andric if (std::optional<SVal> V = getArgLoc(Caller)) 3695ffd83dbSDimitry Andric return *V; 3700b57cec5SDimitry Andric else 3710b57cec5SDimitry Andric break; 3720b57cec5SDimitry Andric } else if (const auto *CCE = dyn_cast<CXXConstructExpr>(E)) { 3730b57cec5SDimitry Andric // Don't bother figuring out the target region for the future 3740b57cec5SDimitry Andric // constructor because we won't need it. 37506c3fb27SDimitry Andric CallEventRef<> Caller = CEMgr.getCXXConstructorCall( 37606c3fb27SDimitry Andric CCE, /*Target=*/nullptr, State, LCtx, getCFGElementRef()); 377bdd1243dSDimitry Andric if (std::optional<SVal> V = getArgLoc(Caller)) 3785ffd83dbSDimitry Andric return *V; 3790b57cec5SDimitry Andric else 3800b57cec5SDimitry Andric break; 3810b57cec5SDimitry Andric } else if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) { 38206c3fb27SDimitry Andric CallEventRef<> Caller = 38306c3fb27SDimitry Andric CEMgr.getObjCMethodCall(ME, State, LCtx, getCFGElementRef()); 384bdd1243dSDimitry Andric if (std::optional<SVal> V = getArgLoc(Caller)) 3855ffd83dbSDimitry Andric return *V; 3860b57cec5SDimitry Andric else 3870b57cec5SDimitry Andric break; 3885ffd83dbSDimitry Andric } 3895ffd83dbSDimitry Andric } 3905ffd83dbSDimitry Andric } // switch (CC->getKind()) 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // If we couldn't find an existing region to construct into, assume we're 3940b57cec5SDimitry Andric // constructing a temporary. Notify the caller of our failure. 3950b57cec5SDimitry Andric CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; 3965ffd83dbSDimitry Andric return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3995ffd83dbSDimitry Andric ProgramStateRef ExprEngine::updateObjectsUnderConstruction( 4005ffd83dbSDimitry Andric SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx, 4015ffd83dbSDimitry Andric const ConstructionContext *CC, const EvalCallOptions &CallOpts) { 4025ffd83dbSDimitry Andric if (CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion) { 4035ffd83dbSDimitry Andric // Sounds like we failed to find the target region and therefore 4045ffd83dbSDimitry Andric // copy elision failed. There's nothing we can do about it here. 4055ffd83dbSDimitry Andric return State; 4065ffd83dbSDimitry Andric } 4075ffd83dbSDimitry Andric 4085ffd83dbSDimitry Andric // See if we're constructing an existing region by looking at the 4095ffd83dbSDimitry Andric // current construction context. 4105ffd83dbSDimitry Andric assert(CC && "Computed target region without construction context?"); 4115ffd83dbSDimitry Andric switch (CC->getKind()) { 4125ffd83dbSDimitry Andric case ConstructionContext::CXX17ElidedCopyVariableKind: 4135ffd83dbSDimitry Andric case ConstructionContext::SimpleVariableKind: { 4145ffd83dbSDimitry Andric const auto *DSCC = cast<VariableConstructionContext>(CC); 4155ffd83dbSDimitry Andric return addObjectUnderConstruction(State, DSCC->getDeclStmt(), LCtx, V); 4165ffd83dbSDimitry Andric } 4175ffd83dbSDimitry Andric case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind: 4185ffd83dbSDimitry Andric case ConstructionContext::SimpleConstructorInitializerKind: { 4195ffd83dbSDimitry Andric const auto *ICC = cast<ConstructorInitializerConstructionContext>(CC); 420e8d8bef9SDimitry Andric const auto *Init = ICC->getCXXCtorInitializer(); 421e8d8bef9SDimitry Andric // Base and delegating initializers handled above 422e8d8bef9SDimitry Andric assert(Init->isAnyMemberInitializer() && 423e8d8bef9SDimitry Andric "Base and delegating initializers should have been handled by" 424e8d8bef9SDimitry Andric "computeObjectUnderConstruction()"); 425e8d8bef9SDimitry Andric return addObjectUnderConstruction(State, Init, LCtx, V); 4265ffd83dbSDimitry Andric } 4275ffd83dbSDimitry Andric case ConstructionContext::NewAllocatedObjectKind: { 4285ffd83dbSDimitry Andric return State; 4295ffd83dbSDimitry Andric } 4305ffd83dbSDimitry Andric case ConstructionContext::SimpleReturnedValueKind: 4315ffd83dbSDimitry Andric case ConstructionContext::CXX17ElidedCopyReturnedValueKind: { 4325ffd83dbSDimitry Andric const StackFrameContext *SFC = LCtx->getStackFrame(); 4335ffd83dbSDimitry Andric const LocationContext *CallerLCtx = SFC->getParent(); 4345ffd83dbSDimitry Andric if (!CallerLCtx) { 4355ffd83dbSDimitry Andric // No extra work is necessary in top frame. 4365ffd83dbSDimitry Andric return State; 4375ffd83dbSDimitry Andric } 4385ffd83dbSDimitry Andric 4395ffd83dbSDimitry Andric auto RTC = (*SFC->getCallSiteBlock())[SFC->getIndex()] 4405ffd83dbSDimitry Andric .getAs<CFGCXXRecordTypedCall>(); 4415ffd83dbSDimitry Andric assert(RTC && "Could not have had a target region without it"); 4425ffd83dbSDimitry Andric if (isa<BlockInvocationContext>(CallerLCtx)) { 4435ffd83dbSDimitry Andric // Unwrap block invocation contexts. They're mostly part of 4445ffd83dbSDimitry Andric // the current stack frame. 4455ffd83dbSDimitry Andric CallerLCtx = CallerLCtx->getParent(); 4465ffd83dbSDimitry Andric assert(!isa<BlockInvocationContext>(CallerLCtx)); 4475ffd83dbSDimitry Andric } 4485ffd83dbSDimitry Andric 4495ffd83dbSDimitry Andric return updateObjectsUnderConstruction(V, 4505ffd83dbSDimitry Andric cast<Expr>(SFC->getCallSite()), State, CallerLCtx, 4515ffd83dbSDimitry Andric RTC->getConstructionContext(), CallOpts); 4525ffd83dbSDimitry Andric } 4535ffd83dbSDimitry Andric case ConstructionContext::ElidedTemporaryObjectKind: { 4545ffd83dbSDimitry Andric assert(AMgr.getAnalyzerOptions().ShouldElideConstructors); 4555ffd83dbSDimitry Andric if (!CallOpts.IsElidableCtorThatHasNotBeenElided) { 4565ffd83dbSDimitry Andric const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC); 4575ffd83dbSDimitry Andric State = updateObjectsUnderConstruction( 4585ffd83dbSDimitry Andric V, TCC->getConstructorAfterElision(), State, LCtx, 4595ffd83dbSDimitry Andric TCC->getConstructionContextAfterElision(), CallOpts); 4605ffd83dbSDimitry Andric 4615ffd83dbSDimitry Andric // Remember that we've elided the constructor. 4625ffd83dbSDimitry Andric State = addObjectUnderConstruction( 4635ffd83dbSDimitry Andric State, TCC->getConstructorAfterElision(), LCtx, V); 4645ffd83dbSDimitry Andric 4655ffd83dbSDimitry Andric // Remember that we've elided the destructor. 4665ffd83dbSDimitry Andric if (const auto *BTE = TCC->getCXXBindTemporaryExpr()) 4675ffd83dbSDimitry Andric State = elideDestructor(State, BTE, LCtx); 4685ffd83dbSDimitry Andric 4695ffd83dbSDimitry Andric // Instead of materialization, shamelessly return 4705ffd83dbSDimitry Andric // the final object destination. 4715ffd83dbSDimitry Andric if (const auto *MTE = TCC->getMaterializedTemporaryExpr()) 4725ffd83dbSDimitry Andric State = addObjectUnderConstruction(State, MTE, LCtx, V); 4735ffd83dbSDimitry Andric 4745ffd83dbSDimitry Andric return State; 4755ffd83dbSDimitry Andric } 4765ffd83dbSDimitry Andric // If we decided not to elide the constructor, proceed as if 4775ffd83dbSDimitry Andric // it's a simple temporary. 478bdd1243dSDimitry Andric [[fallthrough]]; 4795ffd83dbSDimitry Andric } 4805ffd83dbSDimitry Andric case ConstructionContext::SimpleTemporaryObjectKind: { 4815ffd83dbSDimitry Andric const auto *TCC = cast<TemporaryObjectConstructionContext>(CC); 4825ffd83dbSDimitry Andric if (const auto *BTE = TCC->getCXXBindTemporaryExpr()) 4835ffd83dbSDimitry Andric State = addObjectUnderConstruction(State, BTE, LCtx, V); 4845ffd83dbSDimitry Andric 4855ffd83dbSDimitry Andric if (const auto *MTE = TCC->getMaterializedTemporaryExpr()) 4865ffd83dbSDimitry Andric State = addObjectUnderConstruction(State, MTE, LCtx, V); 4875ffd83dbSDimitry Andric 4885ffd83dbSDimitry Andric return State; 4895ffd83dbSDimitry Andric } 490972a253aSDimitry Andric case ConstructionContext::LambdaCaptureKind: { 491972a253aSDimitry Andric const auto *LCC = cast<LambdaCaptureConstructionContext>(CC); 492972a253aSDimitry Andric 493972a253aSDimitry Andric // If we capture and array, we want to store the super region, not a 494972a253aSDimitry Andric // sub-region. 495972a253aSDimitry Andric if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion())) 496972a253aSDimitry Andric V = loc::MemRegionVal(EL->getSuperRegion()); 497972a253aSDimitry Andric 498972a253aSDimitry Andric return addObjectUnderConstruction( 499972a253aSDimitry Andric State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V); 500972a253aSDimitry Andric } 5015ffd83dbSDimitry Andric case ConstructionContext::ArgumentKind: { 5025ffd83dbSDimitry Andric const auto *ACC = cast<ArgumentConstructionContext>(CC); 5035ffd83dbSDimitry Andric if (const auto *BTE = ACC->getCXXBindTemporaryExpr()) 5045ffd83dbSDimitry Andric State = addObjectUnderConstruction(State, BTE, LCtx, V); 5055ffd83dbSDimitry Andric 5065ffd83dbSDimitry Andric return addObjectUnderConstruction( 5075ffd83dbSDimitry Andric State, {ACC->getCallLikeExpr(), ACC->getIndex()}, LCtx, V); 5085ffd83dbSDimitry Andric } 5095ffd83dbSDimitry Andric } 5105ffd83dbSDimitry Andric llvm_unreachable("Unhandled construction context!"); 5115ffd83dbSDimitry Andric } 5125ffd83dbSDimitry Andric 513972a253aSDimitry Andric static ProgramStateRef 514972a253aSDimitry Andric bindRequiredArrayElementToEnvironment(ProgramStateRef State, 515972a253aSDimitry Andric const ArrayInitLoopExpr *AILE, 516972a253aSDimitry Andric const LocationContext *LCtx, SVal Idx) { 517972a253aSDimitry Andric // The ctor in this case is guaranteed to be a copy ctor, otherwise we hit a 518972a253aSDimitry Andric // compile time error. 519972a253aSDimitry Andric // 520972a253aSDimitry Andric // -ArrayInitLoopExpr <-- we're here 521972a253aSDimitry Andric // |-OpaqueValueExpr 522972a253aSDimitry Andric // | `-DeclRefExpr <-- match this 523972a253aSDimitry Andric // `-CXXConstructExpr 524972a253aSDimitry Andric // `-ImplicitCastExpr 525972a253aSDimitry Andric // `-ArraySubscriptExpr 526972a253aSDimitry Andric // |-ImplicitCastExpr 527972a253aSDimitry Andric // | `-OpaqueValueExpr 528972a253aSDimitry Andric // | `-DeclRefExpr 529972a253aSDimitry Andric // `-ArrayInitIndexExpr 530972a253aSDimitry Andric // 531972a253aSDimitry Andric // The resulting expression might look like the one below in an implicit 532972a253aSDimitry Andric // copy/move ctor. 533972a253aSDimitry Andric // 534972a253aSDimitry Andric // ArrayInitLoopExpr <-- we're here 535972a253aSDimitry Andric // |-OpaqueValueExpr 536972a253aSDimitry Andric // | `-MemberExpr <-- match this 537972a253aSDimitry Andric // | (`-CXXStaticCastExpr) <-- move ctor only 538972a253aSDimitry Andric // | `-DeclRefExpr 539972a253aSDimitry Andric // `-CXXConstructExpr 540972a253aSDimitry Andric // `-ArraySubscriptExpr 541972a253aSDimitry Andric // |-ImplicitCastExpr 542972a253aSDimitry Andric // | `-OpaqueValueExpr 543972a253aSDimitry Andric // | `-MemberExpr 544972a253aSDimitry Andric // | `-DeclRefExpr 545972a253aSDimitry Andric // `-ArrayInitIndexExpr 546972a253aSDimitry Andric // 547bdd1243dSDimitry Andric // The resulting expression for a multidimensional array. 548bdd1243dSDimitry Andric // ArrayInitLoopExpr <-- we're here 549bdd1243dSDimitry Andric // |-OpaqueValueExpr 550bdd1243dSDimitry Andric // | `-DeclRefExpr <-- match this 551bdd1243dSDimitry Andric // `-ArrayInitLoopExpr 552bdd1243dSDimitry Andric // |-OpaqueValueExpr 553bdd1243dSDimitry Andric // | `-ArraySubscriptExpr 554bdd1243dSDimitry Andric // | |-ImplicitCastExpr 555bdd1243dSDimitry Andric // | | `-OpaqueValueExpr 556bdd1243dSDimitry Andric // | | `-DeclRefExpr 557bdd1243dSDimitry Andric // | `-ArrayInitIndexExpr 558bdd1243dSDimitry Andric // `-CXXConstructExpr <-- extract this 559bdd1243dSDimitry Andric // ` ... 560bdd1243dSDimitry Andric 561bdd1243dSDimitry Andric const auto *OVESrc = AILE->getCommonExpr()->getSourceExpr(); 562bdd1243dSDimitry Andric 563972a253aSDimitry Andric // HACK: There is no way we can put the index of the array element into the 564972a253aSDimitry Andric // CFG unless we unroll the loop, so we manually select and bind the required 565972a253aSDimitry Andric // parameter to the environment. 566bdd1243dSDimitry Andric const auto *CE = 567bdd1243dSDimitry Andric cast<CXXConstructExpr>(extractElementInitializerFromNestedAILE(AILE)); 568972a253aSDimitry Andric 569972a253aSDimitry Andric SVal Base = UnknownVal(); 570972a253aSDimitry Andric if (const auto *ME = dyn_cast<MemberExpr>(OVESrc)) 571972a253aSDimitry Andric Base = State->getSVal(ME, LCtx); 572bdd1243dSDimitry Andric else if (const auto *DRE = dyn_cast<DeclRefExpr>(OVESrc)) 573972a253aSDimitry Andric Base = State->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx); 574972a253aSDimitry Andric else 575972a253aSDimitry Andric llvm_unreachable("ArrayInitLoopExpr contains unexpected source expression"); 576972a253aSDimitry Andric 577972a253aSDimitry Andric SVal NthElem = State->getLValue(CE->getType(), Idx, Base); 578972a253aSDimitry Andric 579972a253aSDimitry Andric return State->BindExpr(CE->getArg(0), LCtx, NthElem); 580972a253aSDimitry Andric } 581972a253aSDimitry Andric 5825ffd83dbSDimitry Andric void ExprEngine::handleConstructor(const Expr *E, 5830b57cec5SDimitry Andric ExplodedNode *Pred, 5840b57cec5SDimitry Andric ExplodedNodeSet &destNodes) { 5855ffd83dbSDimitry Andric const auto *CE = dyn_cast<CXXConstructExpr>(E); 5865ffd83dbSDimitry Andric const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(E); 5875ffd83dbSDimitry Andric assert(CE || CIE); 5885ffd83dbSDimitry Andric 5890b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 5900b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric SVal Target = UnknownVal(); 5930b57cec5SDimitry Andric 5945ffd83dbSDimitry Andric if (CE) { 595bdd1243dSDimitry Andric if (std::optional<SVal> ElidedTarget = 5960b57cec5SDimitry Andric getObjectUnderConstruction(State, CE, LCtx)) { 597bdd1243dSDimitry Andric // We've previously modeled an elidable constructor by pretending that 598bdd1243dSDimitry Andric // it in fact constructs into the correct target. This constructor can 5995ffd83dbSDimitry Andric // therefore be skipped. 6000b57cec5SDimitry Andric Target = *ElidedTarget; 6010b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); 6020b57cec5SDimitry Andric State = finishObjectConstruction(State, CE, LCtx); 6030b57cec5SDimitry Andric if (auto L = Target.getAs<Loc>()) 6040b57cec5SDimitry Andric State = State->BindExpr(CE, LCtx, State->getSVal(*L, CE->getType())); 6050b57cec5SDimitry Andric Bldr.generateNode(CE, Pred, State); 6060b57cec5SDimitry Andric return; 6070b57cec5SDimitry Andric } 6085ffd83dbSDimitry Andric } 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric EvalCallOptions CallOpts; 6110b57cec5SDimitry Andric auto C = getCurrentCFGElement().getAs<CFGConstructor>(); 6120b57cec5SDimitry Andric assert(C || getCurrentCFGElement().getAs<CFGStmt>()); 6130b57cec5SDimitry Andric const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr; 6140b57cec5SDimitry Andric 6155f757f3fSDimitry Andric const CXXConstructionKind CK = 6165ffd83dbSDimitry Andric CE ? CE->getConstructionKind() : CIE->getConstructionKind(); 6175ffd83dbSDimitry Andric switch (CK) { 6185f757f3fSDimitry Andric case CXXConstructionKind::Complete: { 6195ffd83dbSDimitry Andric // Inherited constructors are always base class constructors. 6205ffd83dbSDimitry Andric assert(CE && !CIE && "A complete constructor is inherited?!"); 6215ffd83dbSDimitry Andric 622972a253aSDimitry Andric // If the ctor is part of an ArrayInitLoopExpr, we want to handle it 623972a253aSDimitry Andric // differently. 624972a253aSDimitry Andric auto *AILE = CC ? CC->getArrayInitLoop() : nullptr; 625972a253aSDimitry Andric 626fcaf7f86SDimitry Andric unsigned Idx = 0; 627972a253aSDimitry Andric if (CE->getType()->isArrayType() || AILE) { 628bdd1243dSDimitry Andric 629bdd1243dSDimitry Andric auto isZeroSizeArray = [&] { 630bdd1243dSDimitry Andric uint64_t Size = 1; 631bdd1243dSDimitry Andric 632bdd1243dSDimitry Andric if (const auto *CAT = dyn_cast<ConstantArrayType>(CE->getType())) 633bdd1243dSDimitry Andric Size = getContext().getConstantArrayElementCount(CAT); 634bdd1243dSDimitry Andric else if (AILE) 635bdd1243dSDimitry Andric Size = getContext().getArrayInitLoopExprElementCount(AILE); 636bdd1243dSDimitry Andric 637bdd1243dSDimitry Andric return Size == 0; 638bdd1243dSDimitry Andric }; 639bdd1243dSDimitry Andric 640bdd1243dSDimitry Andric // No element construction will happen in a 0 size array. 641bdd1243dSDimitry Andric if (isZeroSizeArray()) { 642bdd1243dSDimitry Andric StmtNodeBuilder Bldr(Pred, destNodes, *currBldrCtx); 643bdd1243dSDimitry Andric static SimpleProgramPointTag T{"ExprEngine", 644bdd1243dSDimitry Andric "Skipping 0 size array construction"}; 645bdd1243dSDimitry Andric Bldr.generateNode(CE, Pred, State, &T); 646bdd1243dSDimitry Andric return; 647bdd1243dSDimitry Andric } 648bdd1243dSDimitry Andric 649fcaf7f86SDimitry Andric Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u); 650fcaf7f86SDimitry Andric State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1); 651fcaf7f86SDimitry Andric } 652fcaf7f86SDimitry Andric 653972a253aSDimitry Andric if (AILE) { 654972a253aSDimitry Andric // Only set this once even though we loop through it multiple times. 655972a253aSDimitry Andric if (!getPendingInitLoop(State, CE, LCtx)) 656bdd1243dSDimitry Andric State = setPendingInitLoop( 657bdd1243dSDimitry Andric State, CE, LCtx, 658bdd1243dSDimitry Andric getContext().getArrayInitLoopExprElementCount(AILE)); 659972a253aSDimitry Andric 660972a253aSDimitry Andric State = bindRequiredArrayElementToEnvironment( 661972a253aSDimitry Andric State, AILE, LCtx, svalBuilder.makeArrayIndex(Idx)); 662972a253aSDimitry Andric } 663972a253aSDimitry Andric 6645ffd83dbSDimitry Andric // The target region is found from construction context. 665bdd1243dSDimitry Andric std::tie(State, Target) = handleConstructionContext( 666bdd1243dSDimitry Andric CE, State, currBldrCtx, LCtx, CC, CallOpts, Idx); 6670b57cec5SDimitry Andric break; 6680b57cec5SDimitry Andric } 6695f757f3fSDimitry Andric case CXXConstructionKind::VirtualBase: { 6700b57cec5SDimitry Andric // Make sure we are not calling virtual base class initializers twice. 6710b57cec5SDimitry Andric // Only the most-derived object should initialize virtual base classes. 6720b57cec5SDimitry Andric const auto *OuterCtor = dyn_cast_or_null<CXXConstructExpr>( 6730b57cec5SDimitry Andric LCtx->getStackFrame()->getCallSite()); 6740b57cec5SDimitry Andric assert( 6750b57cec5SDimitry Andric (!OuterCtor || 6765f757f3fSDimitry Andric OuterCtor->getConstructionKind() == CXXConstructionKind::Complete || 6775f757f3fSDimitry Andric OuterCtor->getConstructionKind() == CXXConstructionKind::Delegating) && 6780b57cec5SDimitry Andric ("This virtual base should have already been initialized by " 6790b57cec5SDimitry Andric "the most derived class!")); 6800b57cec5SDimitry Andric (void)OuterCtor; 681bdd1243dSDimitry Andric [[fallthrough]]; 6820b57cec5SDimitry Andric } 6835f757f3fSDimitry Andric case CXXConstructionKind::NonVirtualBase: 6840b57cec5SDimitry Andric // In C++17, classes with non-virtual bases may be aggregates, so they would 6850b57cec5SDimitry Andric // be initialized as aggregates without a constructor call, so we may have 6860b57cec5SDimitry Andric // a base class constructed directly into an initializer list without 6870b57cec5SDimitry Andric // having the derived-class constructor call on the previous stack frame. 6880b57cec5SDimitry Andric // Initializer lists may be nested into more initializer lists that 6890b57cec5SDimitry Andric // correspond to surrounding aggregate initializations. 6900b57cec5SDimitry Andric // FIXME: For now this code essentially bails out. We need to find the 6910b57cec5SDimitry Andric // correct target region and set it. 6920b57cec5SDimitry Andric // FIXME: Instead of relying on the ParentMap, we should have the 6930b57cec5SDimitry Andric // trigger-statement (InitListExpr in this case) passed down from CFG or 6940b57cec5SDimitry Andric // otherwise always available during construction. 695349cc55cSDimitry Andric if (isa_and_nonnull<InitListExpr>(LCtx->getParentMap().getParent(E))) { 6960b57cec5SDimitry Andric MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); 6975ffd83dbSDimitry Andric Target = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); 6980b57cec5SDimitry Andric CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; 6990b57cec5SDimitry Andric break; 7000b57cec5SDimitry Andric } 701bdd1243dSDimitry Andric [[fallthrough]]; 7025f757f3fSDimitry Andric case CXXConstructionKind::Delegating: { 7030b57cec5SDimitry Andric const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 7040b57cec5SDimitry Andric Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 7050b57cec5SDimitry Andric LCtx->getStackFrame()); 7060b57cec5SDimitry Andric SVal ThisVal = State->getSVal(ThisPtr); 7070b57cec5SDimitry Andric 7085f757f3fSDimitry Andric if (CK == CXXConstructionKind::Delegating) { 7090b57cec5SDimitry Andric Target = ThisVal; 7100b57cec5SDimitry Andric } else { 7110b57cec5SDimitry Andric // Cast to the base type. 7125f757f3fSDimitry Andric bool IsVirtual = (CK == CXXConstructionKind::VirtualBase); 7135ffd83dbSDimitry Andric SVal BaseVal = 7145ffd83dbSDimitry Andric getStoreManager().evalDerivedToBase(ThisVal, E->getType(), IsVirtual); 7150b57cec5SDimitry Andric Target = BaseVal; 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric break; 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric if (State != Pred->getState()) { 7220b57cec5SDimitry Andric static SimpleProgramPointTag T("ExprEngine", 7230b57cec5SDimitry Andric "Prepare for object construction"); 7240b57cec5SDimitry Andric ExplodedNodeSet DstPrepare; 7250b57cec5SDimitry Andric StmtNodeBuilder BldrPrepare(Pred, DstPrepare, *currBldrCtx); 7265ffd83dbSDimitry Andric BldrPrepare.generateNode(E, Pred, State, &T, ProgramPoint::PreStmtKind); 7270b57cec5SDimitry Andric assert(DstPrepare.size() <= 1); 7280b57cec5SDimitry Andric if (DstPrepare.size() == 0) 7290b57cec5SDimitry Andric return; 7300b57cec5SDimitry Andric Pred = *BldrPrepare.begin(); 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7335ffd83dbSDimitry Andric const MemRegion *TargetRegion = Target.getAsRegion(); 7340b57cec5SDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 7355ffd83dbSDimitry Andric CallEventRef<> Call = 7365ffd83dbSDimitry Andric CIE ? (CallEventRef<>)CEMgr.getCXXInheritedConstructorCall( 73706c3fb27SDimitry Andric CIE, TargetRegion, State, LCtx, getCFGElementRef()) 7385ffd83dbSDimitry Andric : (CallEventRef<>)CEMgr.getCXXConstructorCall( 73906c3fb27SDimitry Andric CE, TargetRegion, State, LCtx, getCFGElementRef()); 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric ExplodedNodeSet DstPreVisit; 7425ffd83dbSDimitry Andric getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, E, *this); 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric ExplodedNodeSet PreInitialized; 7455ffd83dbSDimitry Andric if (CE) { 7465ffd83dbSDimitry Andric // FIXME: Is it possible and/or useful to do this before PreStmt? 7470b57cec5SDimitry Andric StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); 74806c3fb27SDimitry Andric for (ExplodedNode *N : DstPreVisit) { 74906c3fb27SDimitry Andric ProgramStateRef State = N->getState(); 7500b57cec5SDimitry Andric if (CE->requiresZeroInitialization()) { 7510b57cec5SDimitry Andric // FIXME: Once we properly handle constructors in new-expressions, we'll 7520b57cec5SDimitry Andric // need to invalidate the region before setting a default value, to make 7530b57cec5SDimitry Andric // sure there aren't any lingering bindings around. This probably needs 7540b57cec5SDimitry Andric // to happen regardless of whether or not the object is zero-initialized 7550b57cec5SDimitry Andric // to handle random fields of a placement-initialized object picking up 7560b57cec5SDimitry Andric // old bindings. We might only want to do it when we need to, though. 7570b57cec5SDimitry Andric // FIXME: This isn't actually correct for arrays -- we need to zero- 7580b57cec5SDimitry Andric // initialize the entire array, not just the first element -- but our 7590b57cec5SDimitry Andric // handling of arrays everywhere else is weak as well, so this shouldn't 7600b57cec5SDimitry Andric // actually make things worse. Placement new makes this tricky as well, 7610b57cec5SDimitry Andric // since it's then possible to be initializing one part of a multi- 7620b57cec5SDimitry Andric // dimensional array. 7630b57cec5SDimitry Andric State = State->bindDefaultZero(Target, LCtx); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 76606c3fb27SDimitry Andric Bldr.generateNode(CE, N, State, /*tag=*/nullptr, 7670b57cec5SDimitry Andric ProgramPoint::PreStmtKind); 7680b57cec5SDimitry Andric } 7695ffd83dbSDimitry Andric } else { 7705ffd83dbSDimitry Andric PreInitialized = DstPreVisit; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric ExplodedNodeSet DstPreCall; 7740b57cec5SDimitry Andric getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, 7750b57cec5SDimitry Andric *Call, *this); 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric ExplodedNodeSet DstEvaluated; 7780b57cec5SDimitry Andric 7795ffd83dbSDimitry Andric if (CE && CE->getConstructor()->isTrivial() && 7800b57cec5SDimitry Andric CE->getConstructor()->isCopyOrMoveConstructor() && 7810b57cec5SDimitry Andric !CallOpts.IsArrayCtorOrDtor) { 782e8d8bef9SDimitry Andric StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); 7830b57cec5SDimitry Andric // FIXME: Handle other kinds of trivial constructors as well. 78406c3fb27SDimitry Andric for (ExplodedNode *N : DstPreCall) 78506c3fb27SDimitry Andric performTrivialCopy(Bldr, N, *Call); 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric } else { 78806c3fb27SDimitry Andric for (ExplodedNode *N : DstPreCall) 78906c3fb27SDimitry Andric getCheckerManager().runCheckersForEvalCall(DstEvaluated, N, *Call, *this, 7905ffd83dbSDimitry Andric CallOpts); 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric // If the CFG was constructed without elements for temporary destructors 7940b57cec5SDimitry Andric // and the just-called constructor created a temporary object then 7950b57cec5SDimitry Andric // stop exploration if the temporary object has a noreturn constructor. 7960b57cec5SDimitry Andric // This can lose coverage because the destructor, if it were present 7970b57cec5SDimitry Andric // in the CFG, would be called at the end of the full expression or 7980b57cec5SDimitry Andric // later (for life-time extended temporaries) -- but avoids infeasible 7990b57cec5SDimitry Andric // paths when no-return temporary destructors are used for assertions. 800e8d8bef9SDimitry Andric ExplodedNodeSet DstEvaluatedPostProcessed; 801e8d8bef9SDimitry Andric StmtNodeBuilder Bldr(DstEvaluated, DstEvaluatedPostProcessed, *currBldrCtx); 8020b57cec5SDimitry Andric const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext(); 8030b57cec5SDimitry Andric if (!ADC->getCFGBuildOptions().AddTemporaryDtors) { 80406c3fb27SDimitry Andric if (llvm::isa_and_nonnull<CXXTempObjectRegion, 80506c3fb27SDimitry Andric CXXLifetimeExtendedObjectRegion>(TargetRegion) && 8065ffd83dbSDimitry Andric cast<CXXConstructorDecl>(Call->getDecl()) 8075ffd83dbSDimitry Andric ->getParent() 8085ffd83dbSDimitry Andric ->isAnyDestructorNoReturn()) { 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric // If we've inlined the constructor, then DstEvaluated would be empty. 8110b57cec5SDimitry Andric // In this case we still want a sink, which could be implemented 8120b57cec5SDimitry Andric // in processCallExit. But we don't have that implemented at the moment, 8130b57cec5SDimitry Andric // so if you hit this assertion, see if you can avoid inlining 8140b57cec5SDimitry Andric // the respective constructor when analyzer-config cfg-temporary-dtors 8150b57cec5SDimitry Andric // is set to false. 8160b57cec5SDimitry Andric // Otherwise there's nothing wrong with inlining such constructor. 8170b57cec5SDimitry Andric assert(!DstEvaluated.empty() && 8180b57cec5SDimitry Andric "We should not have inlined this constructor!"); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric for (ExplodedNode *N : DstEvaluated) { 8215ffd83dbSDimitry Andric Bldr.generateSink(E, N, N->getState()); 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // There is no need to run the PostCall and PostStmt checker 8250b57cec5SDimitry Andric // callbacks because we just generated sinks on all nodes in th 8260b57cec5SDimitry Andric // frontier. 8270b57cec5SDimitry Andric return; 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric ExplodedNodeSet DstPostArgumentCleanup; 832e8d8bef9SDimitry Andric for (ExplodedNode *I : DstEvaluatedPostProcessed) 8330b57cec5SDimitry Andric finishArgumentConstruction(DstPostArgumentCleanup, I, *Call); 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric // If there were other constructors called for object-type arguments 8360b57cec5SDimitry Andric // of this constructor, clean them up. 8370b57cec5SDimitry Andric ExplodedNodeSet DstPostCall; 8380b57cec5SDimitry Andric getCheckerManager().runCheckersForPostCall(DstPostCall, 8390b57cec5SDimitry Andric DstPostArgumentCleanup, 8400b57cec5SDimitry Andric *Call, *this); 8415ffd83dbSDimitry Andric getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, E, *this); 8425ffd83dbSDimitry Andric } 8435ffd83dbSDimitry Andric 8445ffd83dbSDimitry Andric void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 8455ffd83dbSDimitry Andric ExplodedNode *Pred, 8465ffd83dbSDimitry Andric ExplodedNodeSet &Dst) { 8475ffd83dbSDimitry Andric handleConstructor(CE, Pred, Dst); 8485ffd83dbSDimitry Andric } 8495ffd83dbSDimitry Andric 8505ffd83dbSDimitry Andric void ExprEngine::VisitCXXInheritedCtorInitExpr( 8515ffd83dbSDimitry Andric const CXXInheritedCtorInitExpr *CE, ExplodedNode *Pred, 8525ffd83dbSDimitry Andric ExplodedNodeSet &Dst) { 8535ffd83dbSDimitry Andric handleConstructor(CE, Pred, Dst); 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric void ExprEngine::VisitCXXDestructor(QualType ObjectType, 8570b57cec5SDimitry Andric const MemRegion *Dest, 8580b57cec5SDimitry Andric const Stmt *S, 8590b57cec5SDimitry Andric bool IsBaseDtor, 8600b57cec5SDimitry Andric ExplodedNode *Pred, 8610b57cec5SDimitry Andric ExplodedNodeSet &Dst, 862a7dea167SDimitry Andric EvalCallOptions &CallOpts) { 8630b57cec5SDimitry Andric assert(S && "A destructor without a trigger!"); 8640b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 8650b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 8680b57cec5SDimitry Andric assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 8690b57cec5SDimitry Andric const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 8700b57cec5SDimitry Andric // FIXME: There should always be a Decl, otherwise the destructor call 8710b57cec5SDimitry Andric // shouldn't have been added to the CFG in the first place. 8720b57cec5SDimitry Andric if (!DtorDecl) { 8730b57cec5SDimitry Andric // Skip the invalid destructor. We cannot simply return because 8740b57cec5SDimitry Andric // it would interrupt the analysis instead. 8750b57cec5SDimitry Andric static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor"); 8760b57cec5SDimitry Andric // FIXME: PostImplicitCall with a null decl may crash elsewhere anyway. 87706c3fb27SDimitry Andric PostImplicitCall PP(/*Decl=*/nullptr, S->getEndLoc(), LCtx, 87806c3fb27SDimitry Andric getCFGElementRef(), &T); 8790b57cec5SDimitry Andric NodeBuilder Bldr(Pred, Dst, *currBldrCtx); 8800b57cec5SDimitry Andric Bldr.generateNode(PP, Pred->getState(), Pred); 8810b57cec5SDimitry Andric return; 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 884a7dea167SDimitry Andric if (!Dest) { 885a7dea167SDimitry Andric // We're trying to destroy something that is not a region. This may happen 886a7dea167SDimitry Andric // for a variety of reasons (unknown target region, concrete integer instead 887a7dea167SDimitry Andric // of target region, etc.). The current code makes an attempt to recover. 888a7dea167SDimitry Andric // FIXME: We probably don't really need to recover when we're dealing 889a7dea167SDimitry Andric // with concrete integers specifically. 890a7dea167SDimitry Andric CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion = true; 891a7dea167SDimitry Andric if (const Expr *E = dyn_cast_or_null<Expr>(S)) { 892a7dea167SDimitry Andric Dest = MRMgr.getCXXTempObjectRegion(E, Pred->getLocationContext()); 893a7dea167SDimitry Andric } else { 894a7dea167SDimitry Andric static SimpleProgramPointTag T("ExprEngine", "SkipInvalidDestructor"); 895a7dea167SDimitry Andric NodeBuilder Bldr(Pred, Dst, *currBldrCtx); 896a7dea167SDimitry Andric Bldr.generateSink(Pred->getLocation().withTag(&T), 897a7dea167SDimitry Andric Pred->getState(), Pred); 898a7dea167SDimitry Andric return; 899a7dea167SDimitry Andric } 900a7dea167SDimitry Andric } 901a7dea167SDimitry Andric 9020b57cec5SDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 90306c3fb27SDimitry Andric CallEventRef<CXXDestructorCall> Call = CEMgr.getCXXDestructorCall( 90406c3fb27SDimitry Andric DtorDecl, S, Dest, IsBaseDtor, State, LCtx, getCFGElementRef()); 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 9070b57cec5SDimitry Andric Call->getSourceRange().getBegin(), 9080b57cec5SDimitry Andric "Error evaluating destructor"); 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric ExplodedNodeSet DstPreCall; 9110b57cec5SDimitry Andric getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 9120b57cec5SDimitry Andric *Call, *this); 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric ExplodedNodeSet DstInvalidated; 9150b57cec5SDimitry Andric StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 91606c3fb27SDimitry Andric for (ExplodedNode *N : DstPreCall) 91706c3fb27SDimitry Andric defaultEvalCall(Bldr, N, *Call, CallOpts); 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 9200b57cec5SDimitry Andric *Call, *this); 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, 9240b57cec5SDimitry Andric ExplodedNode *Pred, 9250b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 9260b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 9270b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 9280b57cec5SDimitry Andric PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 9290b57cec5SDimitry Andric CNE->getBeginLoc(), 9300b57cec5SDimitry Andric "Error evaluating New Allocator Call"); 9310b57cec5SDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 9320b57cec5SDimitry Andric CallEventRef<CXXAllocatorCall> Call = 93306c3fb27SDimitry Andric CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef()); 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric ExplodedNodeSet DstPreCall; 9360b57cec5SDimitry Andric getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 9370b57cec5SDimitry Andric *Call, *this); 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric ExplodedNodeSet DstPostCall; 9400b57cec5SDimitry Andric StmtNodeBuilder CallBldr(DstPreCall, DstPostCall, *currBldrCtx); 9415ffd83dbSDimitry Andric for (ExplodedNode *I : DstPreCall) { 9420b57cec5SDimitry Andric // FIXME: Provide evalCall for checkers? 9430b57cec5SDimitry Andric defaultEvalCall(CallBldr, I, *Call); 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric // If the call is inlined, DstPostCall will be empty and we bail out now. 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric // Store return value of operator new() for future use, until the actual 9480b57cec5SDimitry Andric // CXXNewExpr gets processed. 9490b57cec5SDimitry Andric ExplodedNodeSet DstPostValue; 9500b57cec5SDimitry Andric StmtNodeBuilder ValueBldr(DstPostCall, DstPostValue, *currBldrCtx); 9515ffd83dbSDimitry Andric for (ExplodedNode *I : DstPostCall) { 9520b57cec5SDimitry Andric // FIXME: Because CNE serves as the "call site" for the allocator (due to 9530b57cec5SDimitry Andric // lack of a better expression in the AST), the conjured return value symbol 9540b57cec5SDimitry Andric // is going to be of the same type (C++ object pointer type). Technically 9550b57cec5SDimitry Andric // this is not correct because the operator new's prototype always says that 9560b57cec5SDimitry Andric // it returns a 'void *'. So we should change the type of the symbol, 9570b57cec5SDimitry Andric // and then evaluate the cast over the symbolic pointer from 'void *' to 9580b57cec5SDimitry Andric // the object pointer type. But without changing the symbol's type it 9590b57cec5SDimitry Andric // is breaking too much to evaluate the no-op symbolic cast over it, so we 9600b57cec5SDimitry Andric // skip it for now. 9610b57cec5SDimitry Andric ProgramStateRef State = I->getState(); 9620b57cec5SDimitry Andric SVal RetVal = State->getSVal(CNE, LCtx); 963bdd1243dSDimitry Andric // [basic.stc.dynamic.allocation] (on the return value of an allocation 964bdd1243dSDimitry Andric // function): 965bdd1243dSDimitry Andric // "The order, contiguity, and initial value of storage allocated by 966bdd1243dSDimitry Andric // successive calls to an allocation function are unspecified." 967bdd1243dSDimitry Andric State = State->bindDefaultInitial(RetVal, UndefinedVal{}, LCtx); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric // If this allocation function is not declared as non-throwing, failures 9700b57cec5SDimitry Andric // /must/ be signalled by exceptions, and thus the return value will never 9710b57cec5SDimitry Andric // be NULL. -fno-exceptions does not influence this semantics. 9720b57cec5SDimitry Andric // FIXME: GCC has a -fcheck-new option, which forces it to consider the case 9730b57cec5SDimitry Andric // where new can return NULL. If we end up supporting that option, we can 9740b57cec5SDimitry Andric // consider adding a check for it here. 9750b57cec5SDimitry Andric // C++11 [basic.stc.dynamic.allocation]p3. 9760b57cec5SDimitry Andric if (const FunctionDecl *FD = CNE->getOperatorNew()) { 9770b57cec5SDimitry Andric QualType Ty = FD->getType(); 9780b57cec5SDimitry Andric if (const auto *ProtoType = Ty->getAs<FunctionProtoType>()) 9790b57cec5SDimitry Andric if (!ProtoType->isNothrow()) 9800b57cec5SDimitry Andric State = State->assume(RetVal.castAs<DefinedOrUnknownSVal>(), true); 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric ValueBldr.generateNode( 9840b57cec5SDimitry Andric CNE, I, addObjectUnderConstruction(State, CNE, LCtx, RetVal)); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric ExplodedNodeSet DstPostPostCallCallback; 9880b57cec5SDimitry Andric getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback, 9890b57cec5SDimitry Andric DstPostValue, *Call, *this); 9905ffd83dbSDimitry Andric for (ExplodedNode *I : DstPostPostCallCallback) { 9915ffd83dbSDimitry Andric getCheckerManager().runCheckersForNewAllocator(*Call, Dst, I, *this); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 9960b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 9970b57cec5SDimitry Andric // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 9980b57cec5SDimitry Andric // Also, we need to decide how allocators actually work -- they're not 9990b57cec5SDimitry Andric // really part of the CXXNewExpr because they happen BEFORE the 10000b57cec5SDimitry Andric // CXXConstructExpr subexpression. See PR12014 for some discussion. 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric unsigned blockCount = currBldrCtx->blockCount(); 10030b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 10040b57cec5SDimitry Andric SVal symVal = UnknownVal(); 10050b57cec5SDimitry Andric FunctionDecl *FD = CNE->getOperatorNew(); 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric bool IsStandardGlobalOpNewFunction = 10080b57cec5SDimitry Andric FD->isReplaceableGlobalAllocationFunction(); 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric // Retrieve the stored operator new() return value. 10130b57cec5SDimitry Andric if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { 10140b57cec5SDimitry Andric symVal = *getObjectUnderConstruction(State, CNE, LCtx); 10150b57cec5SDimitry Andric State = finishObjectConstruction(State, CNE, LCtx); 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric // We assume all standard global 'operator new' functions allocate memory in 10190b57cec5SDimitry Andric // heap. We realize this is an approximation that might not correctly model 10200b57cec5SDimitry Andric // a custom global allocator. 10210b57cec5SDimitry Andric if (symVal.isUnknown()) { 10220b57cec5SDimitry Andric if (IsStandardGlobalOpNewFunction) 10230b57cec5SDimitry Andric symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount); 10240b57cec5SDimitry Andric else 10250b57cec5SDimitry Andric symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(), 10260b57cec5SDimitry Andric blockCount); 10270b57cec5SDimitry Andric } 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 10300b57cec5SDimitry Andric CallEventRef<CXXAllocatorCall> Call = 103106c3fb27SDimitry Andric CEMgr.getCXXAllocatorCall(CNE, State, LCtx, getCFGElementRef()); 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { 10340b57cec5SDimitry Andric // Invalidate placement args. 10350b57cec5SDimitry Andric // FIXME: Once we figure out how we want allocators to work, 1036a7dea167SDimitry Andric // we should be using the usual pre-/(default-)eval-/post-call checkers 1037a7dea167SDimitry Andric // here. 10380b57cec5SDimitry Andric State = Call->invalidateRegions(blockCount); 10390b57cec5SDimitry Andric if (!State) 10400b57cec5SDimitry Andric return; 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric // If this allocation function is not declared as non-throwing, failures 10430b57cec5SDimitry Andric // /must/ be signalled by exceptions, and thus the return value will never 10440b57cec5SDimitry Andric // be NULL. -fno-exceptions does not influence this semantics. 10450b57cec5SDimitry Andric // FIXME: GCC has a -fcheck-new option, which forces it to consider the case 10460b57cec5SDimitry Andric // where new can return NULL. If we end up supporting that option, we can 10470b57cec5SDimitry Andric // consider adding a check for it here. 10480b57cec5SDimitry Andric // C++11 [basic.stc.dynamic.allocation]p3. 104981ad6265SDimitry Andric if (const auto *ProtoType = FD->getType()->getAs<FunctionProtoType>()) 10500b57cec5SDimitry Andric if (!ProtoType->isNothrow()) 10510b57cec5SDimitry Andric if (auto dSymVal = symVal.getAs<DefinedOrUnknownSVal>()) 10520b57cec5SDimitry Andric State = State->assume(*dSymVal, true); 10530b57cec5SDimitry Andric } 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric SVal Result = symVal; 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric if (CNE->isArray()) { 1060fcaf7f86SDimitry Andric 1061a7dea167SDimitry Andric if (const auto *NewReg = cast_or_null<SubRegion>(symVal.getAsRegion())) { 1062fcaf7f86SDimitry Andric // If each element is initialized by their default constructor, the field 1063fcaf7f86SDimitry Andric // values are properly placed inside the required region, however if an 1064fcaf7f86SDimitry Andric // initializer list is used, this doesn't happen automatically. 1065fcaf7f86SDimitry Andric auto *Init = CNE->getInitializer(); 1066972a253aSDimitry Andric bool isInitList = isa_and_nonnull<InitListExpr>(Init); 1067fcaf7f86SDimitry Andric 1068fcaf7f86SDimitry Andric QualType ObjTy = 1069fcaf7f86SDimitry Andric isInitList ? Init->getType() : CNE->getType()->getPointeeType(); 10700b57cec5SDimitry Andric const ElementRegion *EleReg = 1071fcaf7f86SDimitry Andric MRMgr.getElementRegion(ObjTy, svalBuilder.makeArrayIndex(0), NewReg, 1072fcaf7f86SDimitry Andric svalBuilder.getContext()); 10730b57cec5SDimitry Andric Result = loc::MemRegionVal(EleReg); 1074fcaf7f86SDimitry Andric 1075fcaf7f86SDimitry Andric // If the array is list initialized, we bind the initializer list to the 1076fcaf7f86SDimitry Andric // memory region here, otherwise we would lose it. 1077fcaf7f86SDimitry Andric if (isInitList) { 1078fcaf7f86SDimitry Andric Bldr.takeNodes(Pred); 1079fcaf7f86SDimitry Andric Pred = Bldr.generateNode(CNE, Pred, State); 1080fcaf7f86SDimitry Andric 1081fcaf7f86SDimitry Andric SVal V = State->getSVal(Init, LCtx); 1082fcaf7f86SDimitry Andric ExplodedNodeSet evaluated; 1083fcaf7f86SDimitry Andric evalBind(evaluated, CNE, Pred, Result, V, true); 1084fcaf7f86SDimitry Andric 1085fcaf7f86SDimitry Andric Bldr.takeNodes(Pred); 1086fcaf7f86SDimitry Andric Bldr.addNodes(evaluated); 1087fcaf7f86SDimitry Andric 1088fcaf7f86SDimitry Andric Pred = *evaluated.begin(); 1089fcaf7f86SDimitry Andric State = Pred->getState(); 10900b57cec5SDimitry Andric } 1091fcaf7f86SDimitry Andric } 1092fcaf7f86SDimitry Andric 10930b57cec5SDimitry Andric State = State->BindExpr(CNE, Pred->getLocationContext(), Result); 10940b57cec5SDimitry Andric Bldr.generateNode(CNE, Pred, State); 10950b57cec5SDimitry Andric return; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric // FIXME: Once we have proper support for CXXConstructExprs inside 10990b57cec5SDimitry Andric // CXXNewExpr, we need to make sure that the constructed object is not 11000b57cec5SDimitry Andric // immediately invalidated here. (The placement call should happen before 11010b57cec5SDimitry Andric // the constructor call anyway.) 110281ad6265SDimitry Andric if (FD->isReservedGlobalPlacementOperator()) { 11030b57cec5SDimitry Andric // Non-array placement new should always return the placement location. 11040b57cec5SDimitry Andric SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 11050b57cec5SDimitry Andric Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), 11060b57cec5SDimitry Andric CNE->getPlacementArg(0)->getType()); 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric // Bind the address of the object, then check to see if we cached out. 11100b57cec5SDimitry Andric State = State->BindExpr(CNE, LCtx, Result); 11110b57cec5SDimitry Andric ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State); 11120b57cec5SDimitry Andric if (!NewN) 11130b57cec5SDimitry Andric return; 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric // If the type is not a record, we won't have a CXXConstructExpr as an 11160b57cec5SDimitry Andric // initializer. Copy the value over. 11170b57cec5SDimitry Andric if (const Expr *Init = CNE->getInitializer()) { 11180b57cec5SDimitry Andric if (!isa<CXXConstructExpr>(Init)) { 11190b57cec5SDimitry Andric assert(Bldr.getResults().size() == 1); 11200b57cec5SDimitry Andric Bldr.takeNodes(NewN); 11210b57cec5SDimitry Andric evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx), 11220b57cec5SDimitry Andric /*FirstInit=*/IsStandardGlobalOpNewFunction); 11230b57cec5SDimitry Andric } 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 11280b57cec5SDimitry Andric ExplodedNode *Pred, ExplodedNodeSet &Dst) { 11295ffd83dbSDimitry Andric 11305ffd83dbSDimitry Andric CallEventManager &CEMgr = getStateManager().getCallEventManager(); 11315ffd83dbSDimitry Andric CallEventRef<CXXDeallocatorCall> Call = CEMgr.getCXXDeallocatorCall( 113206c3fb27SDimitry Andric CDE, Pred->getState(), Pred->getLocationContext(), getCFGElementRef()); 11335ffd83dbSDimitry Andric 11345ffd83dbSDimitry Andric ExplodedNodeSet DstPreCall; 11355ffd83dbSDimitry Andric getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, *Call, *this); 113681ad6265SDimitry Andric ExplodedNodeSet DstPostCall; 11375ffd83dbSDimitry Andric 113881ad6265SDimitry Andric if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) { 113981ad6265SDimitry Andric StmtNodeBuilder Bldr(DstPreCall, DstPostCall, *currBldrCtx); 114081ad6265SDimitry Andric for (ExplodedNode *I : DstPreCall) { 114181ad6265SDimitry Andric defaultEvalCall(Bldr, I, *Call); 114281ad6265SDimitry Andric } 114381ad6265SDimitry Andric } else { 114481ad6265SDimitry Andric DstPostCall = DstPreCall; 114581ad6265SDimitry Andric } 114681ad6265SDimitry Andric getCheckerManager().runCheckersForPostCall(Dst, DstPostCall, *Call, *this); 11470b57cec5SDimitry Andric } 11480b57cec5SDimitry Andric 11495ffd83dbSDimitry Andric void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, 11500b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 11510b57cec5SDimitry Andric const VarDecl *VD = CS->getExceptionDecl(); 11520b57cec5SDimitry Andric if (!VD) { 11530b57cec5SDimitry Andric Dst.Add(Pred); 11540b57cec5SDimitry Andric return; 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 11580b57cec5SDimitry Andric SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), 11590b57cec5SDimitry Andric currBldrCtx->blockCount()); 11600b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 11610b57cec5SDimitry Andric state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); 11620b57cec5SDimitry Andric 11630b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 11640b57cec5SDimitry Andric Bldr.generateNode(CS, Pred, state); 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 11680b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 11690b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 11700b57cec5SDimitry Andric 11710b57cec5SDimitry Andric // Get the this object region from StoreManager. 11720b57cec5SDimitry Andric const LocationContext *LCtx = Pred->getLocationContext(); 11730b57cec5SDimitry Andric const MemRegion *R = 11740b57cec5SDimitry Andric svalBuilder.getRegionManager().getCXXThisRegion( 11750b57cec5SDimitry Andric getContext().getCanonicalType(TE->getType()), 11760b57cec5SDimitry Andric LCtx); 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric ProgramStateRef state = Pred->getState(); 11790b57cec5SDimitry Andric SVal V = state->getSVal(loc::MemRegionVal(R)); 11800b57cec5SDimitry Andric Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, 11840b57cec5SDimitry Andric ExplodedNodeSet &Dst) { 11850b57cec5SDimitry Andric const LocationContext *LocCtxt = Pred->getLocationContext(); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric // Get the region of the lambda itself. 11880b57cec5SDimitry Andric const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion( 11890b57cec5SDimitry Andric LE, LocCtxt); 11900b57cec5SDimitry Andric SVal V = loc::MemRegionVal(R); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric ProgramStateRef State = Pred->getState(); 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric // If we created a new MemRegion for the lambda, we should explicitly bind 11950b57cec5SDimitry Andric // the captures. 119606c3fb27SDimitry Andric for (auto const [Idx, FieldForCapture, InitExpr] : 119706c3fb27SDimitry Andric llvm::zip(llvm::seq<unsigned>(0, -1), LE->getLambdaClass()->fields(), 119806c3fb27SDimitry Andric LE->capture_inits())) { 11990b57cec5SDimitry Andric SVal FieldLoc = State->getLValue(FieldForCapture, V); 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric SVal InitVal; 12020b57cec5SDimitry Andric if (!FieldForCapture->hasCapturedVLAType()) { 12030b57cec5SDimitry Andric assert(InitExpr && "Capture missing initialization expression"); 1204972a253aSDimitry Andric 1205bdd1243dSDimitry Andric // Capturing a 0 length array is a no-op, so we ignore it to get a more 1206bdd1243dSDimitry Andric // accurate analysis. If it's not ignored, it would set the default 1207bdd1243dSDimitry Andric // binding of the lambda to 'Unknown', which can lead to falsely detecting 1208bdd1243dSDimitry Andric // 'Uninitialized' values as 'Unknown' and not reporting a warning. 1209bdd1243dSDimitry Andric const auto FTy = FieldForCapture->getType(); 1210bdd1243dSDimitry Andric if (FTy->isConstantArrayType() && 1211bdd1243dSDimitry Andric getContext().getConstantArrayElementCount( 1212bdd1243dSDimitry Andric getContext().getAsConstantArrayType(FTy)) == 0) 1213bdd1243dSDimitry Andric continue; 1214bdd1243dSDimitry Andric 1215bdd1243dSDimitry Andric // With C++17 copy elision the InitExpr can be anything, so instead of 1216bdd1243dSDimitry Andric // pattern matching all cases, we simple check if the current field is 1217bdd1243dSDimitry Andric // under construction or not, regardless what it's InitExpr is. 1218bdd1243dSDimitry Andric if (const auto OUC = 1219bdd1243dSDimitry Andric getObjectUnderConstruction(State, {LE, Idx}, LocCtxt)) { 1220bdd1243dSDimitry Andric InitVal = State->getSVal(OUC->getAsRegion()); 1221972a253aSDimitry Andric 1222972a253aSDimitry Andric State = finishObjectConstruction(State, {LE, Idx}, LocCtxt); 1223972a253aSDimitry Andric } else 12240b57cec5SDimitry Andric InitVal = State->getSVal(InitExpr, LocCtxt); 1225972a253aSDimitry Andric 12260b57cec5SDimitry Andric } else { 1227972a253aSDimitry Andric 1228972a253aSDimitry Andric assert(!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) && 1229972a253aSDimitry Andric "VLA capture by value is a compile time error!"); 1230972a253aSDimitry Andric 12310b57cec5SDimitry Andric // The field stores the length of a captured variable-length array. 12320b57cec5SDimitry Andric // These captures don't have initialization expressions; instead we 12330b57cec5SDimitry Andric // get the length from the VLAType size expression. 12340b57cec5SDimitry Andric Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr(); 12350b57cec5SDimitry Andric InitVal = State->getSVal(SizeExpr, LocCtxt); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric State = State->bindLoc(FieldLoc, InitVal, LocCtxt); 12390b57cec5SDimitry Andric } 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric // Decay the Loc into an RValue, because there might be a 12420b57cec5SDimitry Andric // MaterializeTemporaryExpr node above this one which expects the bound value 12430b57cec5SDimitry Andric // to be an RValue. 12440b57cec5SDimitry Andric SVal LambdaRVal = State->getSVal(R); 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric ExplodedNodeSet Tmp; 12470b57cec5SDimitry Andric StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); 12480b57cec5SDimitry Andric // FIXME: is this the right program point kind? 12490b57cec5SDimitry Andric Bldr.generateNode(LE, Pred, 12500b57cec5SDimitry Andric State->BindExpr(LE, LocCtxt, LambdaRVal), 12510b57cec5SDimitry Andric nullptr, ProgramPoint::PostLValueKind); 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric // FIXME: Move all post/pre visits to ::Visit(). 12540b57cec5SDimitry Andric getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this); 12550b57cec5SDimitry Andric } 1256