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" 17087611edSJordy Rose #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 1810e25031STed Kremenek #include "clang/AST/DeclCXX.h" 1910e25031STed Kremenek 2010e25031STed Kremenek using namespace clang; 2110e25031STed Kremenek using namespace ento; 2210e25031STed Kremenek 2310e25031STed Kremenek namespace { 2410e25031STed Kremenek class CallExprWLItem { 2510e25031STed Kremenek public: 2610e25031STed Kremenek CallExpr::const_arg_iterator I; 2710e25031STed Kremenek ExplodedNode *N; 2810e25031STed Kremenek 2910e25031STed Kremenek CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n) 3010e25031STed Kremenek : I(i), N(n) {} 3110e25031STed Kremenek }; 3210e25031STed Kremenek } 3310e25031STed Kremenek 3410e25031STed Kremenek void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE, 3510e25031STed Kremenek const FunctionProtoType *FnType, 3610e25031STed Kremenek ExplodedNode *Pred, ExplodedNodeSet &Dst, 3710e25031STed Kremenek bool FstArgAsLValue) { 3810e25031STed Kremenek 3910e25031STed Kremenek 4010e25031STed Kremenek SmallVector<CallExprWLItem, 20> WorkList; 4110e25031STed Kremenek WorkList.reserve(AE - AI); 4210e25031STed Kremenek WorkList.push_back(CallExprWLItem(AI, Pred)); 4310e25031STed Kremenek 4410e25031STed Kremenek while (!WorkList.empty()) { 4510e25031STed Kremenek CallExprWLItem Item = WorkList.back(); 4610e25031STed Kremenek WorkList.pop_back(); 4710e25031STed Kremenek 4810e25031STed Kremenek if (Item.I == AE) { 4910e25031STed Kremenek Dst.insert(Item.N); 5010e25031STed Kremenek continue; 5110e25031STed Kremenek } 5210e25031STed Kremenek 5310e25031STed Kremenek // Evaluate the argument. 5410e25031STed Kremenek ExplodedNodeSet Tmp; 5510e25031STed Kremenek if (FstArgAsLValue) { 5610e25031STed Kremenek FstArgAsLValue = false; 5710e25031STed Kremenek } 5810e25031STed Kremenek 5910e25031STed Kremenek Visit(*Item.I, Item.N, Tmp); 6010e25031STed Kremenek ++(Item.I); 6110e25031STed Kremenek for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI) 6210e25031STed Kremenek WorkList.push_back(CallExprWLItem(Item.I, *NI)); 6310e25031STed Kremenek } 6410e25031STed Kremenek } 6510e25031STed Kremenek 6610e25031STed Kremenek void ExprEngine::evalCallee(const CallExpr *callExpr, 6710e25031STed Kremenek const ExplodedNodeSet &src, 6810e25031STed Kremenek ExplodedNodeSet &dest) { 6910e25031STed Kremenek 7010e25031STed Kremenek const Expr *callee = 0; 7110e25031STed Kremenek 7210e25031STed Kremenek switch (callExpr->getStmtClass()) { 7310e25031STed Kremenek case Stmt::CXXMemberCallExprClass: { 7410e25031STed Kremenek // Evaluate the implicit object argument that is the recipient of the 7510e25031STed Kremenek // call. 7610e25031STed Kremenek callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument(); 7710e25031STed Kremenek 7810e25031STed Kremenek // FIXME: handle member pointers. 7910e25031STed Kremenek if (!callee) 8010e25031STed Kremenek return; 8110e25031STed Kremenek 8210e25031STed Kremenek break; 8310e25031STed Kremenek } 8410e25031STed Kremenek default: { 8510e25031STed Kremenek callee = callExpr->getCallee()->IgnoreParens(); 8610e25031STed Kremenek break; 8710e25031STed Kremenek } 8810e25031STed Kremenek } 8910e25031STed Kremenek 9010e25031STed Kremenek for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i) 9110e25031STed Kremenek Visit(callee, *i, dest); 9210e25031STed Kremenek } 9310e25031STed Kremenek 9410e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 9510e25031STed Kremenek const StackFrameContext *SFC) { 9610e25031STed Kremenek const Type *T = D->getTypeForDecl(); 9710e25031STed Kremenek QualType PT = getContext().getPointerType(QualType(T, 0)); 9810e25031STed Kremenek return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 9910e25031STed Kremenek } 10010e25031STed Kremenek 10110e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 10210e25031STed Kremenek const StackFrameContext *frameCtx) { 10310e25031STed Kremenek return svalBuilder.getRegionManager(). 10410e25031STed Kremenek getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 10510e25031STed Kremenek } 10610e25031STed Kremenek 10710e25031STed Kremenek void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 10810e25031STed Kremenek ExplodedNode *Pred, 10910e25031STed Kremenek ExplodedNodeSet &Dst) { 110e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 1112a14c695STed Kremenek const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 11249b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 113632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 11410e25031STed Kremenek 11510e25031STed Kremenek // Bind the temporary object to the value of the expression. Then bind 11610e25031STed Kremenek // the expression to the location of the object. 117632e3b7eSTed Kremenek SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 11810e25031STed Kremenek 11910e25031STed Kremenek const MemRegion *R = 120632e3b7eSTed Kremenek svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 12110e25031STed Kremenek 12210e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(R), V); 123632e3b7eSTed Kremenek Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 12410e25031STed Kremenek } 12510e25031STed Kremenek 12611764ab4SBenjamin Kramer void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 12711764ab4SBenjamin Kramer ExplodedNode *Pred, 12811764ab4SBenjamin Kramer ExplodedNodeSet &Dst) { 12911764ab4SBenjamin Kramer VisitCXXConstructExpr(expr, 0, Pred, Dst); 13011764ab4SBenjamin Kramer } 13111764ab4SBenjamin Kramer 13210e25031STed Kremenek void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 13310e25031STed Kremenek const MemRegion *Dest, 13410e25031STed Kremenek ExplodedNode *Pred, 13510e25031STed Kremenek ExplodedNodeSet &destNodes) { 13610e25031STed Kremenek 13710e25031STed Kremenek const CXXConstructorDecl *CD = E->getConstructor(); 13810e25031STed Kremenek assert(CD); 13910e25031STed Kremenek 14010e25031STed Kremenek #if 0 14110e25031STed Kremenek if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 14210e25031STed Kremenek // FIXME: invalidate the object. 14310e25031STed Kremenek return; 14410e25031STed Kremenek #endif 14510e25031STed Kremenek 14610e25031STed Kremenek // Evaluate other arguments. 14710e25031STed Kremenek ExplodedNodeSet argsEvaluated; 14810e25031STed Kremenek const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>(); 14910e25031STed Kremenek evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated); 15010e25031STed Kremenek 15110e25031STed Kremenek #if 0 15210e25031STed Kremenek // Is the constructor elidable? 15310e25031STed Kremenek if (E->isElidable()) { 15410e25031STed Kremenek VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 15510e25031STed Kremenek // FIXME: this is here to force propagation if VisitAggExpr doesn't 15610e25031STed Kremenek if (destNodes.empty()) 15710e25031STed Kremenek destNodes.Add(Pred); 15810e25031STed Kremenek return; 15910e25031STed Kremenek } 16010e25031STed Kremenek #endif 16110e25031STed Kremenek 16210e25031STed Kremenek // Perform the previsit of the constructor. 16310e25031STed Kremenek ExplodedNodeSet destPreVisit; 16410e25031STed Kremenek getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 16510e25031STed Kremenek *this); 16610e25031STed Kremenek 16710e25031STed Kremenek // Evaluate the constructor. Currently we don't now allow checker-specific 16810e25031STed Kremenek // implementations of specific constructors (as we do with ordinary 16910e25031STed Kremenek // function calls. We can re-evaluate this in the future. 17010e25031STed Kremenek 17110e25031STed Kremenek #if 0 17210e25031STed Kremenek // Inlining currently isn't fully implemented. 17310e25031STed Kremenek 17410e25031STed Kremenek if (AMgr.shouldInlineCall()) { 17510e25031STed Kremenek if (!Dest) 17610e25031STed Kremenek Dest = 17710e25031STed Kremenek svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 17810e25031STed Kremenek Pred->getLocationContext()); 17910e25031STed Kremenek 18010e25031STed Kremenek // The callee stack frame context used to create the 'this' 18110e25031STed Kremenek // parameter region. 18210e25031STed Kremenek const StackFrameContext *SFC = 18310e25031STed Kremenek AMgr.getStackFrame(CD, Pred->getLocationContext(), 184e594034fSAnna Zaks E, currentBuilderContext->getBlock(), 185e594034fSAnna Zaks currentStmtIdx); 18610e25031STed Kremenek 18710e25031STed Kremenek // Create the 'this' region. 18810e25031STed Kremenek const CXXThisRegion *ThisR = 18910e25031STed Kremenek getCXXThisRegion(E->getConstructor()->getParent(), SFC); 19010e25031STed Kremenek 19110e25031STed Kremenek CallEnter Loc(E, SFC, Pred->getLocationContext()); 19210e25031STed Kremenek 193e4e5712cSAnna Zaks StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext); 19410e25031STed Kremenek for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), 19510e25031STed Kremenek NE = argsEvaluated.end(); NI != NE; ++NI) { 19649b1e38eSTed Kremenek ProgramStateRef state = (*NI)->getState(); 19710e25031STed Kremenek // Setup 'this' region, so that the ctor is evaluated on the object pointed 19810e25031STed Kremenek // by 'Dest'. 19910e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 200e594034fSAnna Zaks Bldr.generateNode(Loc, *NI, state); 20110e25031STed Kremenek } 20210e25031STed Kremenek } 20310e25031STed Kremenek #endif 20410e25031STed Kremenek 20510e25031STed Kremenek // Default semantics: invalidate all regions passed as arguments. 20610e25031STed Kremenek ExplodedNodeSet destCall; 207e594034fSAnna Zaks { 208e4e5712cSAnna Zaks StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext); 20910e25031STed Kremenek for (ExplodedNodeSet::iterator 21010e25031STed Kremenek i = destPreVisit.begin(), e = destPreVisit.end(); 21110e25031STed Kremenek i != e; ++i) 21210e25031STed Kremenek { 21310e25031STed Kremenek ExplodedNode *Pred = *i; 214d188d66eSJordy Rose const LocationContext *LC = Pred->getLocationContext(); 21549b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 21610e25031STed Kremenek 217632e3b7eSTed Kremenek state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 218e594034fSAnna Zaks Bldr.generateNode(E, Pred, state); 21910e25031STed Kremenek } 220e594034fSAnna Zaks } 22110e25031STed Kremenek // Do the post visit. 22210e25031STed Kremenek getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 22310e25031STed Kremenek } 22410e25031STed Kremenek 22510e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 22610e25031STed Kremenek const MemRegion *Dest, 22710e25031STed Kremenek const Stmt *S, 22810e25031STed Kremenek ExplodedNode *Pred, 22910e25031STed Kremenek ExplodedNodeSet &Dst) { 230e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 23110e25031STed Kremenek if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 23210e25031STed Kremenek return; 233142adc49STed Kremenek 23410e25031STed Kremenek // Create the context for 'this' region. 235142adc49STed Kremenek const StackFrameContext *SFC = 23681ce1c8aSTed Kremenek AnalysisDeclContexts.getContext(DD)-> 237142adc49STed Kremenek getStackFrame(Pred->getLocationContext(), S, 238e594034fSAnna Zaks currentBuilderContext->getBlock(), currentStmtIdx); 23910e25031STed Kremenek 24010e25031STed Kremenek const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 24110e25031STed Kremenek 24210e25031STed Kremenek CallEnter PP(S, SFC, Pred->getLocationContext()); 24310e25031STed Kremenek 24449b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 24510e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 246e594034fSAnna Zaks Bldr.generateNode(PP, Pred, state); 24710e25031STed Kremenek } 24810e25031STed Kremenek 24910e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 25010e25031STed Kremenek ExplodedNodeSet &Dst) { 251e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 25210e25031STed Kremenek 253e594034fSAnna Zaks unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 254d519cae8STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 25510e25031STed Kremenek DefinedOrUnknownSVal symVal = 256d519cae8STed Kremenek svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 25710e25031STed Kremenek const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 25810e25031STed Kremenek QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 25910e25031STed Kremenek const ElementRegion *EleReg = 26010e25031STed Kremenek getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 26110e25031STed Kremenek 26210e25031STed Kremenek if (CNE->isArray()) { 26310e25031STed Kremenek // FIXME: allocating an array requires simulating the constructors. 26410e25031STed Kremenek // For now, just return a symbolicated region. 26549b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 266632e3b7eSTed Kremenek state = state->BindExpr(CNE, Pred->getLocationContext(), 267632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 268e594034fSAnna Zaks Bldr.generateNode(CNE, Pred, state); 26910e25031STed Kremenek return; 27010e25031STed Kremenek } 27110e25031STed Kremenek 2726047f07eSSebastian Redl // FIXME: Update for AST changes. 2736047f07eSSebastian Redl #if 0 27410e25031STed Kremenek // Evaluate constructor arguments. 27510e25031STed Kremenek const FunctionProtoType *FnType = NULL; 27610e25031STed Kremenek const CXXConstructorDecl *CD = CNE->getConstructor(); 27710e25031STed Kremenek if (CD) 27810e25031STed Kremenek FnType = CD->getType()->getAs<FunctionProtoType>(); 27910e25031STed Kremenek ExplodedNodeSet argsEvaluated; 280e594034fSAnna Zaks Bldr.takeNodes(Pred); 28110e25031STed Kremenek evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 28210e25031STed Kremenek FnType, Pred, argsEvaluated); 283e594034fSAnna Zaks Bldr.addNodes(argsEvaluated); 28410e25031STed Kremenek 28510e25031STed Kremenek // Initialize the object region and bind the 'new' expression. 28610e25031STed Kremenek for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 28710e25031STed Kremenek E = argsEvaluated.end(); I != E; ++I) { 28810e25031STed Kremenek 28949b1e38eSTed Kremenek ProgramStateRef state = (*I)->getState(); 29010e25031STed Kremenek 29110e25031STed Kremenek // Accumulate list of regions that are invalidated. 29210e25031STed Kremenek // FIXME: Eventually we should unify the logic for constructor 29310e25031STed Kremenek // processing in one place. 29410e25031STed Kremenek SmallVector<const MemRegion*, 10> regionsToInvalidate; 29510e25031STed Kremenek for (CXXNewExpr::const_arg_iterator 29610e25031STed Kremenek ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 29710e25031STed Kremenek ai != ae; ++ai) 29810e25031STed Kremenek { 299632e3b7eSTed Kremenek SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 30010e25031STed Kremenek if (const MemRegion *region = val.getAsRegion()) 30110e25031STed Kremenek regionsToInvalidate.push_back(region); 30210e25031STed Kremenek } 30310e25031STed Kremenek 30410e25031STed Kremenek if (ObjTy->isRecordType()) { 30510e25031STed Kremenek regionsToInvalidate.push_back(EleReg); 30610e25031STed Kremenek // Invalidate the regions. 3078158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 3088158ef0dSAnna Zaks // the globals which will get invalidated. 3091fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 3108158ef0dSAnna Zaks CNE, blockCount, 0, 0); 31110e25031STed Kremenek 31210e25031STed Kremenek } else { 31310e25031STed Kremenek // Invalidate the regions. 3148158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 3158158ef0dSAnna Zaks // the globals which will get invalidated. 3161fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 3178158ef0dSAnna Zaks CNE, blockCount, 0, 0); 31810e25031STed Kremenek 31910e25031STed Kremenek if (CNE->hasInitializer()) { 320632e3b7eSTed Kremenek SVal V = state->getSVal(*CNE->constructor_arg_begin(), 321632e3b7eSTed Kremenek (*I)->getLocationContext()); 32210e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), V); 32310e25031STed Kremenek } else { 32410e25031STed Kremenek // Explicitly set to undefined, because currently we retrieve symbolic 32510e25031STed Kremenek // value from symbolic region. 32610e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 32710e25031STed Kremenek } 32810e25031STed Kremenek } 329632e3b7eSTed Kremenek state = state->BindExpr(CNE, (*I)->getLocationContext(), 330632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 331e594034fSAnna Zaks Bldr.generateNode(CNE, *I, state); 33210e25031STed Kremenek } 3336047f07eSSebastian Redl #endif 33410e25031STed Kremenek } 33510e25031STed Kremenek 33610e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 33710e25031STed Kremenek ExplodedNode *Pred, ExplodedNodeSet &Dst) { 338*64aea652SErik Verbruggen StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 339*64aea652SErik Verbruggen ProgramStateRef state = Pred->getState(); 340*64aea652SErik Verbruggen Bldr.generateNode(CDE, Pred, state); 34110e25031STed Kremenek } 34210e25031STed Kremenek 34310e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 34410e25031STed Kremenek ExplodedNodeSet &Dst) { 345e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 346e594034fSAnna Zaks 34710e25031STed Kremenek // Get the this object region from StoreManager. 348632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 34910e25031STed Kremenek const MemRegion *R = 35010e25031STed Kremenek svalBuilder.getRegionManager().getCXXThisRegion( 35110e25031STed Kremenek getContext().getCanonicalType(TE->getType()), 352632e3b7eSTed Kremenek LCtx); 35310e25031STed Kremenek 35449b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 35510e25031STed Kremenek SVal V = state->getSVal(loc::MemRegionVal(R)); 356632e3b7eSTed Kremenek Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 35710e25031STed Kremenek } 358