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" 198fdb59f9STed Kremenek #include "clang/AST/StmtCXX.h" 2010e25031STed Kremenek 2110e25031STed Kremenek using namespace clang; 2210e25031STed Kremenek using namespace ento; 2310e25031STed Kremenek 2410e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 2510e25031STed Kremenek const StackFrameContext *SFC) { 2610e25031STed Kremenek const Type *T = D->getTypeForDecl(); 2710e25031STed Kremenek QualType PT = getContext().getPointerType(QualType(T, 0)); 2810e25031STed Kremenek return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 2910e25031STed Kremenek } 3010e25031STed Kremenek 3110e25031STed Kremenek const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 3210e25031STed Kremenek const StackFrameContext *frameCtx) { 3310e25031STed Kremenek return svalBuilder.getRegionManager(). 3410e25031STed Kremenek getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 3510e25031STed Kremenek } 3610e25031STed Kremenek 3710e25031STed Kremenek void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 3810e25031STed Kremenek ExplodedNode *Pred, 3910e25031STed Kremenek ExplodedNodeSet &Dst) { 40e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 412a14c695STed Kremenek const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 4249b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 43632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 4410e25031STed Kremenek 4510e25031STed Kremenek // Bind the temporary object to the value of the expression. Then bind 4610e25031STed Kremenek // the expression to the location of the object. 47632e3b7eSTed Kremenek SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 4810e25031STed Kremenek 4910e25031STed Kremenek const MemRegion *R = 50632e3b7eSTed Kremenek svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 5110e25031STed Kremenek 5210e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(R), V); 53632e3b7eSTed Kremenek Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 5410e25031STed Kremenek } 5510e25031STed Kremenek 5611764ab4SBenjamin Kramer void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 5711764ab4SBenjamin Kramer ExplodedNode *Pred, 5811764ab4SBenjamin Kramer ExplodedNodeSet &Dst) { 5911764ab4SBenjamin Kramer VisitCXXConstructExpr(expr, 0, Pred, Dst); 6011764ab4SBenjamin Kramer } 6111764ab4SBenjamin Kramer 6210e25031STed Kremenek void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 6310e25031STed Kremenek const MemRegion *Dest, 6410e25031STed Kremenek ExplodedNode *Pred, 6510e25031STed Kremenek ExplodedNodeSet &destNodes) { 6610e25031STed Kremenek 67*be84d859SMatt Beaumont-Gay #if 0 6810e25031STed Kremenek const CXXConstructorDecl *CD = E->getConstructor(); 6910e25031STed Kremenek assert(CD); 70*be84d859SMatt Beaumont-Gay #endif 7110e25031STed Kremenek 7210e25031STed Kremenek #if 0 7310e25031STed Kremenek if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 7410e25031STed Kremenek // FIXME: invalidate the object. 7510e25031STed Kremenek return; 7610e25031STed Kremenek #endif 7710e25031STed Kremenek 7810e25031STed Kremenek #if 0 7910e25031STed Kremenek // Is the constructor elidable? 8010e25031STed Kremenek if (E->isElidable()) { 8110e25031STed Kremenek VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 8210e25031STed Kremenek // FIXME: this is here to force propagation if VisitAggExpr doesn't 8310e25031STed Kremenek if (destNodes.empty()) 8410e25031STed Kremenek destNodes.Add(Pred); 8510e25031STed Kremenek return; 8610e25031STed Kremenek } 8710e25031STed Kremenek #endif 8810e25031STed Kremenek 8910e25031STed Kremenek // Perform the previsit of the constructor. 90fe66dd62SErik Verbruggen ExplodedNodeSet SrcNodes; 91fe66dd62SErik Verbruggen SrcNodes.Add(Pred); 92fe66dd62SErik Verbruggen ExplodedNodeSet TmpNodes; 93fe66dd62SErik Verbruggen getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this); 9410e25031STed Kremenek 9510e25031STed Kremenek // Evaluate the constructor. Currently we don't now allow checker-specific 9610e25031STed Kremenek // implementations of specific constructors (as we do with ordinary 9710e25031STed Kremenek // function calls. We can re-evaluate this in the future. 9810e25031STed Kremenek 9910e25031STed Kremenek #if 0 10010e25031STed Kremenek // Inlining currently isn't fully implemented. 10110e25031STed Kremenek 10210e25031STed Kremenek if (AMgr.shouldInlineCall()) { 10310e25031STed Kremenek if (!Dest) 10410e25031STed Kremenek Dest = 10510e25031STed Kremenek svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 10610e25031STed Kremenek Pred->getLocationContext()); 10710e25031STed Kremenek 10810e25031STed Kremenek // The callee stack frame context used to create the 'this' 10910e25031STed Kremenek // parameter region. 11010e25031STed Kremenek const StackFrameContext *SFC = 11110e25031STed Kremenek AMgr.getStackFrame(CD, Pred->getLocationContext(), 112e594034fSAnna Zaks E, currentBuilderContext->getBlock(), 113e594034fSAnna Zaks currentStmtIdx); 11410e25031STed Kremenek 11510e25031STed Kremenek // Create the 'this' region. 11610e25031STed Kremenek const CXXThisRegion *ThisR = 11710e25031STed Kremenek getCXXThisRegion(E->getConstructor()->getParent(), SFC); 11810e25031STed Kremenek 11910e25031STed Kremenek CallEnter Loc(E, SFC, Pred->getLocationContext()); 12010e25031STed Kremenek 121fe66dd62SErik Verbruggen StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext); 122fe66dd62SErik Verbruggen for (ExplodedNodeSet::iterator NI = SrcNodes.begin(), 123fe66dd62SErik Verbruggen NE = SrcNodes.end(); NI != NE; ++NI) { 12449b1e38eSTed Kremenek ProgramStateRef state = (*NI)->getState(); 12510e25031STed Kremenek // Setup 'this' region, so that the ctor is evaluated on the object pointed 12610e25031STed Kremenek // by 'Dest'. 12710e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 128e594034fSAnna Zaks Bldr.generateNode(Loc, *NI, state); 12910e25031STed Kremenek } 13010e25031STed Kremenek } 13110e25031STed Kremenek #endif 13210e25031STed Kremenek 13310e25031STed Kremenek // Default semantics: invalidate all regions passed as arguments. 13410e25031STed Kremenek ExplodedNodeSet destCall; 135e594034fSAnna Zaks { 136fe66dd62SErik Verbruggen StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext); 137fe66dd62SErik Verbruggen for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end(); 13810e25031STed Kremenek i != e; ++i) 13910e25031STed Kremenek { 14010e25031STed Kremenek ExplodedNode *Pred = *i; 141d188d66eSJordy Rose const LocationContext *LC = Pred->getLocationContext(); 14249b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 14310e25031STed Kremenek 144632e3b7eSTed Kremenek state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 145e594034fSAnna Zaks Bldr.generateNode(E, Pred, state); 14610e25031STed Kremenek } 147e594034fSAnna Zaks } 14810e25031STed Kremenek // Do the post visit. 14910e25031STed Kremenek getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 15010e25031STed Kremenek } 15110e25031STed Kremenek 15210e25031STed Kremenek void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 15310e25031STed Kremenek const MemRegion *Dest, 15410e25031STed Kremenek const Stmt *S, 15510e25031STed Kremenek ExplodedNode *Pred, 15610e25031STed Kremenek ExplodedNodeSet &Dst) { 157e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 15810e25031STed Kremenek if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 15910e25031STed Kremenek return; 160142adc49STed Kremenek 16110e25031STed Kremenek // Create the context for 'this' region. 162142adc49STed Kremenek const StackFrameContext *SFC = 16381ce1c8aSTed Kremenek AnalysisDeclContexts.getContext(DD)-> 164142adc49STed Kremenek getStackFrame(Pred->getLocationContext(), S, 165e594034fSAnna Zaks currentBuilderContext->getBlock(), currentStmtIdx); 16610e25031STed Kremenek 16710e25031STed Kremenek const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 16810e25031STed Kremenek 16910e25031STed Kremenek CallEnter PP(S, SFC, Pred->getLocationContext()); 17010e25031STed Kremenek 17149b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 17210e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 173e594034fSAnna Zaks Bldr.generateNode(PP, Pred, state); 17410e25031STed Kremenek } 17510e25031STed Kremenek 17610e25031STed Kremenek void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 17710e25031STed Kremenek ExplodedNodeSet &Dst) { 178e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 17910e25031STed Kremenek 180e594034fSAnna Zaks unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 181d519cae8STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 18210e25031STed Kremenek DefinedOrUnknownSVal symVal = 183d519cae8STed Kremenek svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 18410e25031STed Kremenek const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 18510e25031STed Kremenek QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 18610e25031STed Kremenek const ElementRegion *EleReg = 18710e25031STed Kremenek getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 18810e25031STed Kremenek 18910e25031STed Kremenek if (CNE->isArray()) { 19010e25031STed Kremenek // FIXME: allocating an array requires simulating the constructors. 19110e25031STed Kremenek // For now, just return a symbolicated region. 19249b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 193632e3b7eSTed Kremenek state = state->BindExpr(CNE, Pred->getLocationContext(), 194632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 195e594034fSAnna Zaks Bldr.generateNode(CNE, Pred, state); 19610e25031STed Kremenek return; 19710e25031STed Kremenek } 19810e25031STed Kremenek 1996047f07eSSebastian Redl // FIXME: Update for AST changes. 2006047f07eSSebastian Redl #if 0 20110e25031STed Kremenek // Evaluate constructor arguments. 20210e25031STed Kremenek const FunctionProtoType *FnType = NULL; 20310e25031STed Kremenek const CXXConstructorDecl *CD = CNE->getConstructor(); 20410e25031STed Kremenek if (CD) 20510e25031STed Kremenek FnType = CD->getType()->getAs<FunctionProtoType>(); 20610e25031STed Kremenek ExplodedNodeSet argsEvaluated; 207e594034fSAnna Zaks Bldr.takeNodes(Pred); 20810e25031STed Kremenek evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 20910e25031STed Kremenek FnType, Pred, argsEvaluated); 210e594034fSAnna Zaks Bldr.addNodes(argsEvaluated); 21110e25031STed Kremenek 21210e25031STed Kremenek // Initialize the object region and bind the 'new' expression. 21310e25031STed Kremenek for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 21410e25031STed Kremenek E = argsEvaluated.end(); I != E; ++I) { 21510e25031STed Kremenek 21649b1e38eSTed Kremenek ProgramStateRef state = (*I)->getState(); 21710e25031STed Kremenek 21810e25031STed Kremenek // Accumulate list of regions that are invalidated. 21910e25031STed Kremenek // FIXME: Eventually we should unify the logic for constructor 22010e25031STed Kremenek // processing in one place. 22110e25031STed Kremenek SmallVector<const MemRegion*, 10> regionsToInvalidate; 22210e25031STed Kremenek for (CXXNewExpr::const_arg_iterator 22310e25031STed Kremenek ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 22410e25031STed Kremenek ai != ae; ++ai) 22510e25031STed Kremenek { 226632e3b7eSTed Kremenek SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 22710e25031STed Kremenek if (const MemRegion *region = val.getAsRegion()) 22810e25031STed Kremenek regionsToInvalidate.push_back(region); 22910e25031STed Kremenek } 23010e25031STed Kremenek 23110e25031STed Kremenek if (ObjTy->isRecordType()) { 23210e25031STed Kremenek regionsToInvalidate.push_back(EleReg); 23310e25031STed Kremenek // Invalidate the regions. 2348158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 2358158ef0dSAnna Zaks // the globals which will get invalidated. 2361fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 2378158ef0dSAnna Zaks CNE, blockCount, 0, 0); 23810e25031STed Kremenek 23910e25031STed Kremenek } else { 24010e25031STed Kremenek // Invalidate the regions. 2418158ef0dSAnna Zaks // TODO: Pass the call to new information as the last argument, to limit 2428158ef0dSAnna Zaks // the globals which will get invalidated. 2431fad6631SJordy Rose state = state->invalidateRegions(regionsToInvalidate, 2448158ef0dSAnna Zaks CNE, blockCount, 0, 0); 24510e25031STed Kremenek 24610e25031STed Kremenek if (CNE->hasInitializer()) { 247632e3b7eSTed Kremenek SVal V = state->getSVal(*CNE->constructor_arg_begin(), 248632e3b7eSTed Kremenek (*I)->getLocationContext()); 24910e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), V); 25010e25031STed Kremenek } else { 25110e25031STed Kremenek // Explicitly set to undefined, because currently we retrieve symbolic 25210e25031STed Kremenek // value from symbolic region. 25310e25031STed Kremenek state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 25410e25031STed Kremenek } 25510e25031STed Kremenek } 256632e3b7eSTed Kremenek state = state->BindExpr(CNE, (*I)->getLocationContext(), 257632e3b7eSTed Kremenek loc::MemRegionVal(EleReg)); 258e594034fSAnna Zaks Bldr.generateNode(CNE, *I, state); 25910e25031STed Kremenek } 2606047f07eSSebastian Redl #endif 26110e25031STed Kremenek } 26210e25031STed Kremenek 26310e25031STed Kremenek void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 26410e25031STed Kremenek ExplodedNode *Pred, ExplodedNodeSet &Dst) { 26564aea652SErik Verbruggen StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 26664aea652SErik Verbruggen ProgramStateRef state = Pred->getState(); 26764aea652SErik Verbruggen Bldr.generateNode(CDE, Pred, state); 26810e25031STed Kremenek } 26910e25031STed Kremenek 2708fdb59f9STed Kremenek void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 2718fdb59f9STed Kremenek ExplodedNode *Pred, 2728fdb59f9STed Kremenek ExplodedNodeSet &Dst) { 2738fdb59f9STed Kremenek const VarDecl *VD = CS->getExceptionDecl(); 2748fdb59f9STed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 2758fdb59f9STed Kremenek SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 2768fdb59f9STed Kremenek currentBuilderContext->getCurrentBlockCount()); 2778fdb59f9STed Kremenek ProgramStateRef state = Pred->getState(); 2788fdb59f9STed Kremenek state = state->bindLoc(state->getLValue(VD, LCtx), V); 2798fdb59f9STed Kremenek 2808fdb59f9STed Kremenek StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 2818fdb59f9STed Kremenek Bldr.generateNode(CS, Pred, state); 2828fdb59f9STed Kremenek } 2838fdb59f9STed Kremenek 28410e25031STed Kremenek void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 28510e25031STed Kremenek ExplodedNodeSet &Dst) { 286e4e5712cSAnna Zaks StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 287e594034fSAnna Zaks 28810e25031STed Kremenek // Get the this object region from StoreManager. 289632e3b7eSTed Kremenek const LocationContext *LCtx = Pred->getLocationContext(); 29010e25031STed Kremenek const MemRegion *R = 29110e25031STed Kremenek svalBuilder.getRegionManager().getCXXThisRegion( 29210e25031STed Kremenek getContext().getCanonicalType(TE->getType()), 293632e3b7eSTed Kremenek LCtx); 29410e25031STed Kremenek 29549b1e38eSTed Kremenek ProgramStateRef state = Pred->getState(); 29610e25031STed Kremenek SVal V = state->getSVal(loc::MemRegionVal(R)); 297632e3b7eSTed Kremenek Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 29810e25031STed Kremenek } 299