ExprEngineCXX.cpp revision 226586
119304Speter//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 219304Speter// 319304Speter// The LLVM Compiler Infrastructure 419304Speter// 519304Speter// This file is distributed under the University of Illinois Open Source 619304Speter// License. See LICENSE.TXT for details. 719304Speter// 819304Speter//===----------------------------------------------------------------------===// 919304Speter// 1019304Speter// This file defines the C++ expression evaluation engine. 1119304Speter// 1219304Speter//===----------------------------------------------------------------------===// 13254225Speter 1419304Speter#include "clang/StaticAnalyzer/Core/CheckerManager.h" 1519304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 1619304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 1719304Speter#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 1819304Speter#include "clang/AST/DeclCXX.h" 1919304Speter 2019304Speterusing namespace clang; 2119304Speterusing namespace ento; 2219304Speter 2319304Speternamespace { 2419304Speterclass CallExprWLItem { 2519304Speterpublic: 2619304Speter CallExpr::const_arg_iterator I; 2719304Speter ExplodedNode *N; 2819304Speter 2919304Speter CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n) 3019304Speter : I(i), N(n) {} 3119304Speter}; 3219304Speter} 3319304Speter 3419304Spetervoid ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE, 3519304Speter const FunctionProtoType *FnType, 3619304Speter ExplodedNode *Pred, ExplodedNodeSet &Dst, 3719304Speter bool FstArgAsLValue) { 3819304Speter 3919304Speter 4019304Speter SmallVector<CallExprWLItem, 20> WorkList; 4119304Speter WorkList.reserve(AE - AI); 4219304Speter WorkList.push_back(CallExprWLItem(AI, Pred)); 43254225Speter 4419304Speter while (!WorkList.empty()) { 4519304Speter CallExprWLItem Item = WorkList.back(); 4619304Speter WorkList.pop_back(); 47254225Speter 48254225Speter if (Item.I == AE) { 4919304Speter Dst.insert(Item.N); 5019304Speter continue; 5119304Speter } 5219304Speter 5319304Speter // Evaluate the argument. 5419304Speter ExplodedNodeSet Tmp; 5519304Speter if (FstArgAsLValue) { 5619304Speter FstArgAsLValue = false; 5719304Speter } 5819304Speter 59254225Speter Visit(*Item.I, Item.N, Tmp); 6019304Speter ++(Item.I); 6119304Speter for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI) 6219304Speter WorkList.push_back(CallExprWLItem(Item.I, *NI)); 6319304Speter } 6419304Speter} 6519304Speter 6619304Spetervoid ExprEngine::evalCallee(const CallExpr *callExpr, 6719304Speter const ExplodedNodeSet &src, 6819304Speter ExplodedNodeSet &dest) { 6919304Speter 7019304Speter const Expr *callee = 0; 7119304Speter 7219304Speter switch (callExpr->getStmtClass()) { 7319304Speter case Stmt::CXXMemberCallExprClass: { 7419304Speter // Evaluate the implicit object argument that is the recipient of the 7519304Speter // call. 7619304Speter callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument(); 7719304Speter 7819304Speter // FIXME: handle member pointers. 7919304Speter if (!callee) 8019304Speter return; 8119304Speter 8219304Speter break; 8319304Speter } 8419304Speter default: { 8519304Speter callee = callExpr->getCallee()->IgnoreParens(); 8619304Speter break; 8719304Speter } 8819304Speter } 8919304Speter 9019304Speter for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i) 9119304Speter Visit(callee, *i, dest); 9219304Speter} 9319304Speter 9419304Speterconst CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 95254225Speter const StackFrameContext *SFC) { 9619304Speter const Type *T = D->getTypeForDecl(); 9719304Speter QualType PT = getContext().getPointerType(QualType(T, 0)); 9819304Speter return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 9919304Speter} 10019304Speter 10119304Speterconst CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 10219304Speter const StackFrameContext *frameCtx) { 10319304Speter return svalBuilder.getRegionManager(). 10419304Speter getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 10519304Speter} 10619304Speter 10719304Spetervoid ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 10819304Speter ExplodedNode *Pred, 10919304Speter ExplodedNodeSet &Dst) { 11019304Speter const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 11119304Speter const ProgramState *state = Pred->getState(); 11219304Speter 113254225Speter // Bind the temporary object to the value of the expression. Then bind 11419304Speter // the expression to the location of the object. 11519304Speter SVal V = state->getSVal(tempExpr); 11619304Speter 11719304Speter const MemRegion *R = 11819304Speter svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, 11919304Speter Pred->getLocationContext()); 12019304Speter 12119304Speter state = state->bindLoc(loc::MemRegionVal(R), V); 12219304Speter MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R))); 12319304Speter} 124254225Speter 12519304Spetervoid ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 12619304Speter const MemRegion *Dest, 12719304Speter ExplodedNode *Pred, 128254225Speter ExplodedNodeSet &destNodes) { 129254225Speter 13019304Speter const CXXConstructorDecl *CD = E->getConstructor(); 13119304Speter assert(CD); 13219304Speter 13319304Speter#if 0 13419304Speter if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 13519304Speter // FIXME: invalidate the object. 13619304Speter return; 13719304Speter#endif 13819304Speter 13919304Speter // Evaluate other arguments. 140254225Speter ExplodedNodeSet argsEvaluated; 14119304Speter const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>(); 14219304Speter evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated); 14319304Speter 144254225Speter#if 0 145254225Speter // Is the constructor elidable? 14619304Speter if (E->isElidable()) { 14719304Speter VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 14819304Speter // FIXME: this is here to force propagation if VisitAggExpr doesn't 14919304Speter if (destNodes.empty()) 15019304Speter destNodes.Add(Pred); 15119304Speter return; 15219304Speter } 15319304Speter#endif 15419304Speter 15519304Speter // Perform the previsit of the constructor. 156254225Speter ExplodedNodeSet destPreVisit; 15719304Speter getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 15819304Speter *this); 15919304Speter 160254225Speter // Evaluate the constructor. Currently we don't now allow checker-specific 161254225Speter // implementations of specific constructors (as we do with ordinary 16219304Speter // function calls. We can re-evaluate this in the future. 16319304Speter 16419304Speter#if 0 16519304Speter // Inlining currently isn't fully implemented. 16619304Speter 16719304Speter if (AMgr.shouldInlineCall()) { 16819304Speter if (!Dest) 16919304Speter Dest = 17019304Speter svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 17119304Speter Pred->getLocationContext()); 172254225Speter 17319304Speter // The callee stack frame context used to create the 'this' 17419304Speter // parameter region. 17519304Speter const StackFrameContext *SFC = 176254225Speter AMgr.getStackFrame(CD, Pred->getLocationContext(), 177254225Speter E, Builder->getBlock(), Builder->getIndex()); 17819304Speter 17919304Speter // Create the 'this' region. 18019304Speter const CXXThisRegion *ThisR = 18119304Speter getCXXThisRegion(E->getConstructor()->getParent(), SFC); 18219304Speter 18319304Speter CallEnter Loc(E, SFC, Pred->getLocationContext()); 18419304Speter 18519304Speter 18619304Speter for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), 18719304Speter NE = argsEvaluated.end(); NI != NE; ++NI) { 18819304Speter const ProgramState *state = (*NI)->getState(); 18919304Speter // Setup 'this' region, so that the ctor is evaluated on the object pointed 19019304Speter // by 'Dest'. 19119304Speter state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 192254225Speter if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI)) 193254225Speter destNodes.Add(N); 194254225Speter } 19519304Speter } 19619304Speter#endif 19719304Speter 19819304Speter // Default semantics: invalidate all regions passed as arguments. 19919304Speter ExplodedNodeSet destCall; 20019304Speter 20119304Speter for (ExplodedNodeSet::iterator 20219304Speter i = destPreVisit.begin(), e = destPreVisit.end(); 20319304Speter i != e; ++i) 20419304Speter { 205254225Speter ExplodedNode *Pred = *i; 20619304Speter const LocationContext *LC = Pred->getLocationContext(); 20719304Speter const ProgramState *state = Pred->getState(); 20819304Speter 209254225Speter state = invalidateArguments(state, CallOrObjCMessage(E, state), LC); 210254225Speter Builder->MakeNode(destCall, E, Pred, state); 21119304Speter } 21219304Speter 21319304Speter // Do the post visit. 21419304Speter getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 21519304Speter} 21619304Speter 21719304Spetervoid ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 21819304Speter const MemRegion *Dest, 21919304Speter const Stmt *S, 22019304Speter ExplodedNode *Pred, 221254225Speter ExplodedNodeSet &Dst) { 22219304Speter if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 22319304Speter return; 22419304Speter // Create the context for 'this' region. 225254225Speter const StackFrameContext *SFC = AMgr.getStackFrame(DD, 22619304Speter Pred->getLocationContext(), 22719304Speter S, Builder->getBlock(), 22819304Speter Builder->getIndex()); 22919304Speter 23019304Speter const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 23119304Speter 23219304Speter CallEnter PP(S, SFC, Pred->getLocationContext()); 23319304Speter 23419304Speter const ProgramState *state = Pred->getState(); 23519304Speter state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 236254225Speter ExplodedNode *N = Builder->generateNode(PP, state, Pred); 23719304Speter if (N) 23819304Speter Dst.Add(N); 23919304Speter} 24019304Speter 24119304Spetervoid ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 24219304Speter ExplodedNodeSet &Dst) { 24319304Speter 24419304Speter unsigned blockCount = Builder->getCurrentBlockCount(); 24519304Speter DefinedOrUnknownSVal symVal = 24619304Speter svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount); 24719304Speter const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 24819304Speter QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 24919304Speter const ElementRegion *EleReg = 25019304Speter getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 25119304Speter 25219304Speter if (CNE->isArray()) { 25319304Speter // FIXME: allocating an array requires simulating the constructors. 25419304Speter // For now, just return a symbolicated region. 25519304Speter const ProgramState *state = Pred->getState(); 25619304Speter state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); 25719304Speter MakeNode(Dst, CNE, Pred, state); 25819304Speter return; 25919304Speter } 26019304Speter 26119304Speter // Evaluate constructor arguments. 262254225Speter const FunctionProtoType *FnType = NULL; 263254225Speter const CXXConstructorDecl *CD = CNE->getConstructor(); 26419304Speter if (CD) 26519304Speter FnType = CD->getType()->getAs<FunctionProtoType>(); 266254225Speter ExplodedNodeSet argsEvaluated; 26719304Speter evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 26819304Speter FnType, Pred, argsEvaluated); 26919304Speter 27019304Speter // Initialize the object region and bind the 'new' expression. 27119304Speter for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 27219304Speter E = argsEvaluated.end(); I != E; ++I) { 27319304Speter 27419304Speter const ProgramState *state = (*I)->getState(); 27519304Speter 27619304Speter // Accumulate list of regions that are invalidated. 27719304Speter // FIXME: Eventually we should unify the logic for constructor 27819304Speter // processing in one place. 27919304Speter SmallVector<const MemRegion*, 10> regionsToInvalidate; 28019304Speter for (CXXNewExpr::const_arg_iterator 28119304Speter ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 28219304Speter ai != ae; ++ai) 28319304Speter { 28419304Speter SVal val = state->getSVal(*ai); 285254225Speter if (const MemRegion *region = val.getAsRegion()) 28619304Speter regionsToInvalidate.push_back(region); 28719304Speter } 28819304Speter 28919304Speter if (ObjTy->isRecordType()) { 29019304Speter regionsToInvalidate.push_back(EleReg); 29119304Speter // Invalidate the regions. 29219304Speter state = state->invalidateRegions(regionsToInvalidate, 29319304Speter CNE, blockCount, 0, 29419304Speter /* invalidateGlobals = */ true); 295254225Speter 29619304Speter } else { 29719304Speter // Invalidate the regions. 29819304Speter state = state->invalidateRegions(regionsToInvalidate, 29919304Speter CNE, blockCount, 0, 30019304Speter /* invalidateGlobals = */ true); 30119304Speter 30219304Speter if (CNE->hasInitializer()) { 30319304Speter SVal V = state->getSVal(*CNE->constructor_arg_begin()); 30419304Speter state = state->bindLoc(loc::MemRegionVal(EleReg), V); 30519304Speter } else { 30619304Speter // Explicitly set to undefined, because currently we retrieve symbolic 30719304Speter // value from symbolic region. 30819304Speter state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 30919304Speter } 310254225Speter } 31119304Speter state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); 31219304Speter MakeNode(Dst, CNE, *I, state); 31319304Speter } 31419304Speter} 31519304Speter 31619304Spetervoid ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 31719304Speter ExplodedNode *Pred,ExplodedNodeSet &Dst) { 31819304Speter // Should do more checking. 31919304Speter ExplodedNodeSet Argevaluated; 32019304Speter Visit(CDE->getArgument(), Pred, Argevaluated); 32119304Speter for (ExplodedNodeSet::iterator I = Argevaluated.begin(), 32219304Speter E = Argevaluated.end(); I != E; ++I) { 32319304Speter const ProgramState *state = (*I)->getState(); 32419304Speter MakeNode(Dst, CDE, *I, state); 325254225Speter } 32619304Speter} 32719304Speter 32819304Spetervoid ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 32919304Speter ExplodedNodeSet &Dst) { 33019304Speter // Get the this object region from StoreManager. 33119304Speter const MemRegion *R = 33219304Speter svalBuilder.getRegionManager().getCXXThisRegion( 33319304Speter getContext().getCanonicalType(TE->getType()), 33419304Speter Pred->getLocationContext()); 33519304Speter 33619304Speter const ProgramState *state = Pred->getState(); 33719304Speter SVal V = state->getSVal(loc::MemRegionVal(R)); 33819304Speter MakeNode(Dst, TE, Pred, state->BindExpr(TE, V)); 33919304Speter} 34019304Speter