110e25031STed Kremenek //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 210e25031STed Kremenek // 310e25031STed Kremenek // The LLVM Compiler Infrastructure 410e25031STed Kremenek // 510e25031STed Kremenek // This file is distributed under the University of Illinois Open Source 610e25031STed Kremenek // License. See LICENSE.TXT for details. 710e25031STed Kremenek // 810e25031STed Kremenek //===----------------------------------------------------------------------===// 910e25031STed Kremenek // 1010e25031STed Kremenek // This file defines the C++ expression evaluation engine. 1110e25031STed Kremenek // 1210e25031STed Kremenek //===----------------------------------------------------------------------===// 1310e25031STed Kremenek 1410e25031STed Kremenek #include "clang/StaticAnalyzer/Core/CheckerManager.h" 1510e25031STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 1610e25031STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 17742920c8SJordan Rose #include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 1810e25031STed Kremenek #include "clang/AST/DeclCXX.h" 198fdb59f9STed Kremenek #include "clang/AST/StmtCXX.h" 2010e25031STed Kremenek 2110e25031STed Kremenek using namespace clang; 2210e25031STed Kremenek using namespace ento; 2310e25031STed Kremenek 2410e25031STed Kremenek void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 2510e25031STed Kremenek ExplodedNode *Pred, 2610e25031STed Kremenek ExplodedNodeSet &Dst) { 27e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 282a14c695STed Kremenek const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 2949b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 30632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 3110e25031STed Kremenek 3210e25031STed Kremenek // Bind the temporary object to the value of the expression. Then bind 3310e25031STed Kremenek // the expression to the location of the object. 34632e3b7eSTed Kremenek SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 3510e25031STed Kremenek 3610e25031STed Kremenek const MemRegion *R = 37632e3b7eSTed Kremenek svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 3810e25031STed Kremenek 3910e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(R), V); 40632e3b7eSTed Kremenek Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 4110e25031STed Kremenek } 4210e25031STed Kremenek 43f3c12ac3SJordan Rose void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 4410e25031STed Kremenek const MemRegion *Dest, 4510e25031STed Kremenek ExplodedNode *Pred, 4610e25031STed Kremenek ExplodedNodeSet &destNodes) { 47f3c12ac3SJordan Rose CXXConstructorCall Call(CE, Dest, Pred->getState(), 4810e25031STed Kremenek Pred->getLocationContext()); 4910e25031STed Kremenek 50f3c12ac3SJordan Rose ExplodedNodeSet DstPreVisit; 51f3c12ac3SJordan Rose getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 52afe7c2c2SJordan Rose ExplodedNodeSet DstPreCall; 53afe7c2c2SJordan Rose getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, 54afe7c2c2SJordan Rose Call, *this); 5510e25031STed Kremenek 56f3c12ac3SJordan Rose ExplodedNodeSet DstInvalidated; 57*3136cf9dSAnna Zaks StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 58afe7c2c2SJordan Rose for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 59f3c12ac3SJordan Rose I != E; ++I) 60*3136cf9dSAnna Zaks defaultEvalCall(Bldr, *I, Call); 6110e25031STed Kremenek 62afe7c2c2SJordan Rose ExplodedNodeSet DstPostCall; 63afe7c2c2SJordan Rose getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated, 64afe7c2c2SJordan Rose Call, *this); 65afe7c2c2SJordan Rose getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 6610e25031STed Kremenek } 6710e25031STed Kremenek 6810e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 6910e25031STed Kremenek const MemRegion *Dest, 7010e25031STed Kremenek const Stmt *S, 7110e25031STed Kremenek ExplodedNode *Pred, 7210e25031STed Kremenek ExplodedNodeSet &Dst) { 734ee71b8aSJordan Rose CXXDestructorCall Call(DD, S, Dest, Pred->getState(), 744ee71b8aSJordan Rose Pred->getLocationContext()); 75142adc49STed Kremenek 764ee71b8aSJordan Rose ExplodedNodeSet DstPreCall; 774ee71b8aSJordan Rose getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 784ee71b8aSJordan Rose Call, *this); 7910e25031STed Kremenek 804ee71b8aSJordan Rose ExplodedNodeSet DstInvalidated; 81*3136cf9dSAnna Zaks StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 824ee71b8aSJordan Rose for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 834ee71b8aSJordan Rose I != E; ++I) 84*3136cf9dSAnna Zaks defaultEvalCall(Bldr, *I, Call); 854ee71b8aSJordan Rose 864ee71b8aSJordan Rose ExplodedNodeSet DstPostCall; 874ee71b8aSJordan Rose getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 884ee71b8aSJordan Rose Call, *this); 8910e25031STed Kremenek } 9010e25031STed Kremenek 9110e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 9210e25031STed Kremenek ExplodedNodeSet &Dst) { 93a4ee064cSJordan Rose // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 94a4ee064cSJordan Rose // Also, we need to decide how allocators actually work -- they're not 95a4ee064cSJordan Rose // really part of the CXXNewExpr because they happen BEFORE the 96a4ee064cSJordan Rose // CXXConstructExpr subexpression. See PR12014 for some discussion. 97e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 9810e25031STed Kremenek 99e594034fSAnna Zaks unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 100d519cae8STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 10110e25031STed Kremenek DefinedOrUnknownSVal symVal = 102a4ee064cSJordan Rose svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount); 10344320367SJordan Rose ProgramStateRef State = Pred->getState(); 10410e25031STed Kremenek 105a4ee064cSJordan Rose // Invalidate placement args. 106a4ee064cSJordan Rose CXXAllocatorCall Call(CNE, State, LCtx); 107a4ee064cSJordan Rose State = Call.invalidateRegions(blockCount); 108a4ee064cSJordan Rose 10910e25031STed Kremenek if (CNE->isArray()) { 11010e25031STed Kremenek // FIXME: allocating an array requires simulating the constructors. 11110e25031STed Kremenek // For now, just return a symbolicated region. 112a4ee064cSJordan Rose const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 113a4ee064cSJordan Rose QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 114a4ee064cSJordan Rose const ElementRegion *EleReg = 115a4ee064cSJordan Rose getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 11644320367SJordan Rose State = State->BindExpr(CNE, Pred->getLocationContext(), 117632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 11844320367SJordan Rose Bldr.generateNode(CNE, Pred, State); 11910e25031STed Kremenek return; 12010e25031STed Kremenek } 12110e25031STed Kremenek 122a4ee064cSJordan Rose // FIXME: Once we have proper support for CXXConstructExprs inside 123a4ee064cSJordan Rose // CXXNewExpr, we need to make sure that the constructed object is not 124a4ee064cSJordan Rose // immediately invalidated here. (The placement call should happen before 125a4ee064cSJordan Rose // the constructor call anyway.) 12644320367SJordan Rose FunctionDecl *FD = CNE->getOperatorNew(); 12744320367SJordan Rose if (FD && FD->isReservedGlobalPlacementOperator()) { 12844320367SJordan Rose // Non-array placement new should always return the placement location. 12944320367SJordan Rose SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 13044320367SJordan Rose State = State->BindExpr(CNE, LCtx, PlacementLoc); 13144320367SJordan Rose } else { 132a4ee064cSJordan Rose State = State->BindExpr(CNE, LCtx, symVal); 13344320367SJordan Rose } 13444320367SJordan Rose 1355089f3b3SJordan Rose // If the type is not a record, we won't have a CXXConstructExpr as an 1365089f3b3SJordan Rose // initializer. Copy the value over. 1375089f3b3SJordan Rose if (const Expr *Init = CNE->getInitializer()) { 1385089f3b3SJordan Rose if (!isa<CXXConstructExpr>(Init)) { 1395089f3b3SJordan Rose QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 1405089f3b3SJordan Rose (void)ObjTy; 1415089f3b3SJordan Rose assert(!ObjTy->isRecordType()); 1425089f3b3SJordan Rose SVal Location = State->getSVal(CNE, LCtx); 1435089f3b3SJordan Rose if (isa<Loc>(Location)) 1445089f3b3SJordan Rose State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx)); 1455089f3b3SJordan Rose } 1465089f3b3SJordan Rose } 1475089f3b3SJordan Rose 14844320367SJordan Rose Bldr.generateNode(CNE, Pred, State); 14910e25031STed Kremenek } 15010e25031STed Kremenek 15110e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 15210e25031STed Kremenek ExplodedNode *Pred, ExplodedNodeSet &Dst) { 15364aea652SErik Verbruggen StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 15464aea652SErik Verbruggen ProgramStateRef state = Pred->getState(); 15564aea652SErik Verbruggen Bldr.generateNode(CDE, Pred, state); 15610e25031STed Kremenek } 15710e25031STed Kremenek 1588fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 1598fdb59f9STed Kremenek ExplodedNode *Pred, 1608fdb59f9STed Kremenek ExplodedNodeSet &Dst) { 1618fdb59f9STed Kremenek const VarDecl *VD = CS->getExceptionDecl(); 162b1279b5cSTed Kremenek if (!VD) { 163b1279b5cSTed Kremenek Dst.Add(Pred); 164b1279b5cSTed Kremenek return; 165b1279b5cSTed Kremenek } 166b1279b5cSTed Kremenek 1678fdb59f9STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 1688fdb59f9STed Kremenek SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 1698fdb59f9STed Kremenek currentBuilderContext->getCurrentBlockCount()); 1708fdb59f9STed Kremenek ProgramStateRef state = Pred->getState(); 1718fdb59f9STed Kremenek state = state->bindLoc(state->getLValue(VD, LCtx), V); 1728fdb59f9STed Kremenek 1738fdb59f9STed Kremenek StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 1748fdb59f9STed Kremenek Bldr.generateNode(CS, Pred, state); 1758fdb59f9STed Kremenek } 1768fdb59f9STed Kremenek 17710e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 17810e25031STed Kremenek ExplodedNodeSet &Dst) { 179e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 180e594034fSAnna Zaks 18110e25031STed Kremenek // Get the this object region from StoreManager. 182632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 18310e25031STed Kremenek const MemRegion *R = 18410e25031STed Kremenek svalBuilder.getRegionManager().getCXXThisRegion( 18510e25031STed Kremenek getContext().getCanonicalType(TE->getType()), 186632e3b7eSTed Kremenek LCtx); 18710e25031STed Kremenek 18849b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 18910e25031STed Kremenek SVal V = state->getSVal(loc::MemRegionVal(R)); 190632e3b7eSTed Kremenek Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 19110e25031STed Kremenek } 192