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 4311764ab4SBenjamin Kramer void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 4411764ab4SBenjamin Kramer ExplodedNode *Pred, 4511764ab4SBenjamin Kramer ExplodedNodeSet &Dst) { 4611764ab4SBenjamin Kramer VisitCXXConstructExpr(expr, 0, Pred, Dst); 4711764ab4SBenjamin Kramer } 4811764ab4SBenjamin Kramer 49f3c12ac3SJordan Rose void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 5010e25031STed Kremenek const MemRegion *Dest, 5110e25031STed Kremenek ExplodedNode *Pred, 5210e25031STed Kremenek ExplodedNodeSet &destNodes) { 53f3c12ac3SJordan Rose CXXConstructorCall Call(CE, Dest, Pred->getState(), 5410e25031STed Kremenek Pred->getLocationContext()); 5510e25031STed Kremenek 56f3c12ac3SJordan Rose ExplodedNodeSet DstPreVisit; 57f3c12ac3SJordan Rose getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 58*afe7c2c2SJordan Rose ExplodedNodeSet DstPreCall; 59*afe7c2c2SJordan Rose getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, 60*afe7c2c2SJordan Rose Call, *this); 6110e25031STed Kremenek 62f3c12ac3SJordan Rose ExplodedNodeSet DstInvalidated; 63*afe7c2c2SJordan Rose for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 64f3c12ac3SJordan Rose I != E; ++I) 65f3c12ac3SJordan Rose defaultEvalCall(DstInvalidated, *I, Call); 6610e25031STed Kremenek 67*afe7c2c2SJordan Rose ExplodedNodeSet DstPostCall; 68*afe7c2c2SJordan Rose getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated, 69*afe7c2c2SJordan Rose Call, *this); 70*afe7c2c2SJordan Rose getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 7110e25031STed Kremenek } 7210e25031STed Kremenek 7310e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 7410e25031STed Kremenek const MemRegion *Dest, 7510e25031STed Kremenek const Stmt *S, 7610e25031STed Kremenek ExplodedNode *Pred, 7710e25031STed Kremenek ExplodedNodeSet &Dst) { 78e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 7910e25031STed Kremenek if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 8010e25031STed Kremenek return; 81142adc49STed Kremenek 8210e25031STed Kremenek // Create the context for 'this' region. 83142adc49STed Kremenek const StackFrameContext *SFC = 8481ce1c8aSTed Kremenek AnalysisDeclContexts.getContext(DD)-> 85142adc49STed Kremenek getStackFrame(Pred->getLocationContext(), S, 86e594034fSAnna Zaks currentBuilderContext->getBlock(), currentStmtIdx); 8710e25031STed Kremenek 8810e25031STed Kremenek CallEnter PP(S, SFC, Pred->getLocationContext()); 8949b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 9072b3452cSTed Kremenek state = state->bindLoc(svalBuilder.getCXXThis(DD->getParent(), SFC), 9172b3452cSTed Kremenek loc::MemRegionVal(Dest)); 92e594034fSAnna Zaks Bldr.generateNode(PP, Pred, state); 9310e25031STed Kremenek } 9410e25031STed Kremenek 9544320367SJordan Rose static bool isPointerToConst(const ParmVarDecl *ParamDecl) { 9644320367SJordan Rose // FIXME: Copied from ExprEngineCallAndReturn.cpp 9744320367SJordan Rose QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); 9844320367SJordan Rose if (PointeeTy != QualType() && PointeeTy.isConstQualified() && 9944320367SJordan Rose !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { 10044320367SJordan Rose return true; 10144320367SJordan Rose } 10244320367SJordan Rose return false; 10344320367SJordan Rose } 10444320367SJordan Rose 10510e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 10610e25031STed Kremenek ExplodedNodeSet &Dst) { 107e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 10810e25031STed Kremenek 109e594034fSAnna Zaks unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 110d519cae8STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 11110e25031STed Kremenek DefinedOrUnknownSVal symVal = 112d519cae8STed Kremenek svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 11310e25031STed Kremenek const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 11410e25031STed Kremenek QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 11510e25031STed Kremenek const ElementRegion *EleReg = 11610e25031STed Kremenek getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 11744320367SJordan Rose ProgramStateRef State = Pred->getState(); 11810e25031STed Kremenek 11910e25031STed Kremenek if (CNE->isArray()) { 12010e25031STed Kremenek // FIXME: allocating an array requires simulating the constructors. 12110e25031STed Kremenek // For now, just return a symbolicated region. 12244320367SJordan Rose State = State->BindExpr(CNE, Pred->getLocationContext(), 123632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 12444320367SJordan Rose Bldr.generateNode(CNE, Pred, State); 12510e25031STed Kremenek return; 12610e25031STed Kremenek } 12710e25031STed Kremenek 12844320367SJordan Rose FunctionDecl *FD = CNE->getOperatorNew(); 12944320367SJordan Rose if (FD && FD->isReservedGlobalPlacementOperator()) { 13044320367SJordan Rose // Non-array placement new should always return the placement location. 13144320367SJordan Rose SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 13244320367SJordan Rose State = State->BindExpr(CNE, LCtx, PlacementLoc); 13344320367SJordan Rose // FIXME: Once we have proper support for CXXConstructExprs inside 13444320367SJordan Rose // CXXNewExpr, we need to make sure that the constructed object is not 13544320367SJordan Rose // immediately invalidated here. (The placement call should happen before 13644320367SJordan Rose // the constructor call anyway.) 13744320367SJordan Rose } 13844320367SJordan Rose 13944320367SJordan Rose // Invalidate placement args. 14044320367SJordan Rose 14144320367SJordan Rose // FIXME: This is largely copied from invalidateArguments, because 14244320367SJordan Rose // CallOrObjCMessage is not general enough to handle new-expressions yet. 14344320367SJordan Rose SmallVector<const MemRegion *, 4> RegionsToInvalidate; 14444320367SJordan Rose 14544320367SJordan Rose unsigned Index = 0; 14644320367SJordan Rose for (CXXNewExpr::const_arg_iterator I = CNE->placement_arg_begin(), 14744320367SJordan Rose E = CNE->placement_arg_end(); 14844320367SJordan Rose I != E; ++I) { 14944320367SJordan Rose // Pre-increment the argument index to skip over the implicit size arg. 15044320367SJordan Rose ++Index; 15144320367SJordan Rose if (FD && Index < FD->getNumParams()) 15244320367SJordan Rose if (isPointerToConst(FD->getParamDecl(Index))) 15344320367SJordan Rose continue; 15444320367SJordan Rose 15544320367SJordan Rose SVal V = State->getSVal(*I, LCtx); 15644320367SJordan Rose 15744320367SJordan Rose // If we are passing a location wrapped as an integer, unwrap it and 15844320367SJordan Rose // invalidate the values referred by the location. 15944320367SJordan Rose if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 16044320367SJordan Rose V = Wrapped->getLoc(); 16144320367SJordan Rose else if (!isa<Loc>(V)) 16244320367SJordan Rose continue; 16344320367SJordan Rose 16444320367SJordan Rose if (const MemRegion *R = V.getAsRegion()) { 16544320367SJordan Rose // Invalidate the value of the variable passed by reference. 16644320367SJordan Rose 16744320367SJordan Rose // Are we dealing with an ElementRegion? If the element type is 16844320367SJordan Rose // a basic integer type (e.g., char, int) and the underlying region 16944320367SJordan Rose // is a variable region then strip off the ElementRegion. 17044320367SJordan Rose // FIXME: We really need to think about this for the general case 17144320367SJordan Rose // as sometimes we are reasoning about arrays and other times 17244320367SJordan Rose // about (char*), etc., is just a form of passing raw bytes. 17344320367SJordan Rose // e.g., void *p = alloca(); foo((char*)p); 17444320367SJordan Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 17544320367SJordan Rose // Checking for 'integral type' is probably too promiscuous, but 17644320367SJordan Rose // we'll leave it in for now until we have a systematic way of 17744320367SJordan Rose // handling all of these cases. Eventually we need to come up 17844320367SJordan Rose // with an interface to StoreManager so that this logic can be 17944320367SJordan Rose // appropriately delegated to the respective StoreManagers while 18044320367SJordan Rose // still allowing us to do checker-specific logic (e.g., 18144320367SJordan Rose // invalidating reference counts), probably via callbacks. 18244320367SJordan Rose if (ER->getElementType()->isIntegralOrEnumerationType()) { 18344320367SJordan Rose const MemRegion *superReg = ER->getSuperRegion(); 18444320367SJordan Rose if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 18544320367SJordan Rose isa<ObjCIvarRegion>(superReg)) 18644320367SJordan Rose R = cast<TypedRegion>(superReg); 18744320367SJordan Rose } 18844320367SJordan Rose // FIXME: What about layers of ElementRegions? 18944320367SJordan Rose } 19044320367SJordan Rose 19144320367SJordan Rose // Mark this region for invalidation. We batch invalidate regions 19244320367SJordan Rose // below for efficiency. 19344320367SJordan Rose RegionsToInvalidate.push_back(R); 19444320367SJordan Rose } else { 19544320367SJordan Rose // Nuke all other arguments passed by reference. 19644320367SJordan Rose // FIXME: is this necessary or correct? This handles the non-Region 19744320367SJordan Rose // cases. Is it ever valid to store to these? 19844320367SJordan Rose State = State->unbindLoc(cast<Loc>(V)); 19944320367SJordan Rose } 20044320367SJordan Rose } 20144320367SJordan Rose 20244320367SJordan Rose // Invalidate designated regions using the batch invalidation API. 20344320367SJordan Rose 20444320367SJordan Rose // FIXME: We can have collisions on the conjured symbol if the 20544320367SJordan Rose // expression *I also creates conjured symbols. We probably want 20644320367SJordan Rose // to identify conjured symbols by an expression pair: the enclosing 20744320367SJordan Rose // expression (the context) and the expression itself. This should 20844320367SJordan Rose // disambiguate conjured symbols. 20944320367SJordan Rose unsigned Count = currentBuilderContext->getCurrentBlockCount(); 21044320367SJordan Rose 21144320367SJordan Rose // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 21244320367SJordan Rose // global variables. 21344320367SJordan Rose State = State->invalidateRegions(RegionsToInvalidate, CNE, Count, LCtx); 21444320367SJordan Rose Bldr.generateNode(CNE, Pred, State); 21544320367SJordan Rose return; 21644320367SJordan Rose 21744320367SJordan Rose // FIXME: The below code is long-since dead. However, constructor handling 21844320367SJordan Rose // in new-expressions is far from complete. See PR12014 for more details. 2196047f07eSSebastian Redl #if 0 22010e25031STed Kremenek // Evaluate constructor arguments. 22110e25031STed Kremenek const FunctionProtoType *FnType = NULL; 22210e25031STed Kremenek const CXXConstructorDecl *CD = CNE->getConstructor(); 22310e25031STed Kremenek if (CD) 22410e25031STed Kremenek FnType = CD->getType()->getAs<FunctionProtoType>(); 22510e25031STed Kremenek ExplodedNodeSet argsEvaluated; 226e594034fSAnna Zaks Bldr.takeNodes(Pred); 22710e25031STed Kremenek evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 22810e25031STed Kremenek FnType, Pred, argsEvaluated); 229e594034fSAnna Zaks Bldr.addNodes(argsEvaluated); 23010e25031STed Kremenek 23110e25031STed Kremenek // Initialize the object region and bind the 'new' expression. 23210e25031STed Kremenek for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 23310e25031STed Kremenek E = argsEvaluated.end(); I != E; ++I) { 23410e25031STed Kremenek 23549b1e38eSTed Kremenek ProgramStateRef state = (*I)->getState(); 23610e25031STed Kremenek 23710e25031STed Kremenek // Accumulate list of regions that are invalidated. 23810e25031STed Kremenek // FIXME: Eventually we should unify the logic for constructor 23910e25031STed Kremenek // processing in one place. 24010e25031STed Kremenek SmallVector<const MemRegion*, 10> regionsToInvalidate; 24110e25031STed Kremenek for (CXXNewExpr::const_arg_iterator 24210e25031STed Kremenek ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 24310e25031STed Kremenek ai != ae; ++ai) 24410e25031STed Kremenek { 245632e3b7eSTed Kremenek SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 24610e25031STed Kremenek if (const MemRegion *region = val.getAsRegion()) 24710e25031STed Kremenek regionsToInvalidate.push_back(region); 24810e25031STed Kremenek } 24910e25031STed Kremenek 25010e25031STed Kremenek if (ObjTy->isRecordType()) { 25110e25031STed Kremenek regionsToInvalidate.push_back(EleReg); 25210e25031STed Kremenek // Invalidate the regions. 2538158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 2548158ef0dSAnna Zaks // the globals which will get invalidated. 2551fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 2568158ef0dSAnna Zaks CNE, blockCount, 0, 0); 25710e25031STed Kremenek 25810e25031STed Kremenek } else { 25910e25031STed Kremenek // Invalidate the regions. 2608158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 2618158ef0dSAnna Zaks // the globals which will get invalidated. 2621fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 2638158ef0dSAnna Zaks CNE, blockCount, 0, 0); 26410e25031STed Kremenek 26510e25031STed Kremenek if (CNE->hasInitializer()) { 266632e3b7eSTed Kremenek SVal V = state->getSVal(*CNE->constructor_arg_begin(), 267632e3b7eSTed Kremenek (*I)->getLocationContext()); 26810e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), V); 26910e25031STed Kremenek } else { 27010e25031STed Kremenek // Explicitly set to undefined, because currently we retrieve symbolic 27110e25031STed Kremenek // value from symbolic region. 27210e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 27310e25031STed Kremenek } 27410e25031STed Kremenek } 275632e3b7eSTed Kremenek state = state->BindExpr(CNE, (*I)->getLocationContext(), 276632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 277e594034fSAnna Zaks Bldr.generateNode(CNE, *I, state); 27810e25031STed Kremenek } 2796047f07eSSebastian Redl #endif 28010e25031STed Kremenek } 28110e25031STed Kremenek 28210e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 28310e25031STed Kremenek ExplodedNode *Pred, ExplodedNodeSet &Dst) { 28464aea652SErik Verbruggen StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 28564aea652SErik Verbruggen ProgramStateRef state = Pred->getState(); 28664aea652SErik Verbruggen Bldr.generateNode(CDE, Pred, state); 28710e25031STed Kremenek } 28810e25031STed Kremenek 2898fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 2908fdb59f9STed Kremenek ExplodedNode *Pred, 2918fdb59f9STed Kremenek ExplodedNodeSet &Dst) { 2928fdb59f9STed Kremenek const VarDecl *VD = CS->getExceptionDecl(); 293b1279b5cSTed Kremenek if (!VD) { 294b1279b5cSTed Kremenek Dst.Add(Pred); 295b1279b5cSTed Kremenek return; 296b1279b5cSTed Kremenek } 297b1279b5cSTed Kremenek 2988fdb59f9STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 2998fdb59f9STed Kremenek SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 3008fdb59f9STed Kremenek currentBuilderContext->getCurrentBlockCount()); 3018fdb59f9STed Kremenek ProgramStateRef state = Pred->getState(); 3028fdb59f9STed Kremenek state = state->bindLoc(state->getLValue(VD, LCtx), V); 3038fdb59f9STed Kremenek 3048fdb59f9STed Kremenek StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 3058fdb59f9STed Kremenek Bldr.generateNode(CS, Pred, state); 3068fdb59f9STed Kremenek } 3078fdb59f9STed Kremenek 30810e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 30910e25031STed Kremenek ExplodedNodeSet &Dst) { 310e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 311e594034fSAnna Zaks 31210e25031STed Kremenek // Get the this object region from StoreManager. 313632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 31410e25031STed Kremenek const MemRegion *R = 31510e25031STed Kremenek svalBuilder.getRegionManager().getCXXThisRegion( 31610e25031STed Kremenek getContext().getCanonicalType(TE->getType()), 317632e3b7eSTed Kremenek LCtx); 31810e25031STed Kremenek 31949b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 32010e25031STed Kremenek SVal V = state->getSVal(loc::MemRegionVal(R)); 321632e3b7eSTed Kremenek Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 32210e25031STed Kremenek } 323