ExprEngineCXX.cpp revision 3a0a9e3e8bbaa45f3ca22b1e20b3beaac0f5861e
1//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the C++ expression evaluation engine. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 16#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 17#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/StmtCXX.h" 20 21using namespace clang; 22using namespace ento; 23 24void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 25 ExplodedNode *Pred, 26 ExplodedNodeSet &Dst) { 27 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 28 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 29 ProgramStateRef state = Pred->getState(); 30 const LocationContext *LCtx = Pred->getLocationContext(); 31 32 // Bind the temporary object to the value of the expression. Then bind 33 // the expression to the location of the object. 34 SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 35 36 const MemRegion *R = 37 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 38 39 state = state->bindLoc(loc::MemRegionVal(R), V); 40 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 41} 42 43void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 44 ExplodedNode *Pred, 45 ExplodedNodeSet &destNodes) { 46 const LocationContext *LCtx = Pred->getLocationContext(); 47 ProgramStateRef State = Pred->getState(); 48 49 const MemRegion *Target = 0; 50 51 switch (CE->getConstructionKind()) { 52 case CXXConstructExpr::CK_Complete: { 53 // See if we're constructing an existing region by looking at the next 54 // element in the CFG. 55 const CFGBlock *B = currentBuilderContext->getBlock(); 56 if (currentStmtIdx + 1 < B->size()) { 57 CFGElement Next = (*B)[currentStmtIdx+1]; 58 59 // Is this a constructor for a local variable? 60 if (const CFGStmt *StmtElem = dyn_cast<CFGStmt>(&Next)) 61 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) 62 if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) 63 if (Var->getInit() == CE) 64 Target = State->getLValue(Var, LCtx).getAsRegion(); 65 66 // Is this a constructor for a member? 67 if (const CFGInitializer *InitElem = dyn_cast<CFGInitializer>(&Next)) { 68 const CXXCtorInitializer *Init = InitElem->getInitializer(); 69 assert(Init->isAnyMemberInitializer()); 70 71 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 72 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 73 LCtx->getCurrentStackFrame()); 74 SVal ThisVal = State->getSVal(ThisPtr); 75 76 if (Init->isIndirectMemberInitializer()) { 77 SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal); 78 Target = cast<loc::MemRegionVal>(Field).getRegion(); 79 } else { 80 SVal Field = State->getLValue(Init->getMember(), ThisVal); 81 Target = cast<loc::MemRegionVal>(Field).getRegion(); 82 } 83 } 84 85 // FIXME: This will eventually need to handle new-expressions as well. 86 } 87 88 // If we couldn't find an existing region to construct into, we'll just 89 // generate a symbolic region, which is fine. 90 91 break; 92 } 93 case CXXConstructExpr::CK_NonVirtualBase: 94 case CXXConstructExpr::CK_VirtualBase: 95 case CXXConstructExpr::CK_Delegating: { 96 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 97 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 98 LCtx->getCurrentStackFrame()); 99 SVal ThisVal = State->getSVal(ThisPtr); 100 101 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 102 Target = ThisVal.getAsRegion(); 103 } else { 104 // Cast to the base type. 105 QualType BaseTy = CE->getType(); 106 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy); 107 Target = cast<loc::MemRegionVal>(BaseVal).getRegion(); 108 } 109 break; 110 } 111 } 112 113 CXXConstructorCall Call(CE, Target, State, LCtx); 114 115 ExplodedNodeSet DstPreVisit; 116 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 117 ExplodedNodeSet DstPreCall; 118 getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, 119 Call, *this); 120 121 ExplodedNodeSet DstInvalidated; 122 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 123 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 124 I != E; ++I) 125 defaultEvalCall(Bldr, *I, Call); 126 127 ExplodedNodeSet DstPostCall; 128 getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated, 129 Call, *this); 130 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 131} 132 133void ExprEngine::VisitCXXDestructor(QualType ObjectType, 134 const MemRegion *Dest, 135 const Stmt *S, 136 ExplodedNode *Pred, 137 ExplodedNodeSet &Dst) { 138 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 139 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 140 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 141 142 CXXDestructorCall Call(DtorDecl, S, Dest, Pred->getState(), 143 Pred->getLocationContext()); 144 145 ExplodedNodeSet DstPreCall; 146 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 147 Call, *this); 148 149 ExplodedNodeSet DstInvalidated; 150 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currentBuilderContext); 151 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 152 I != E; ++I) 153 defaultEvalCall(Bldr, *I, Call); 154 155 ExplodedNodeSet DstPostCall; 156 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 157 Call, *this); 158} 159 160void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 161 ExplodedNodeSet &Dst) { 162 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 163 // Also, we need to decide how allocators actually work -- they're not 164 // really part of the CXXNewExpr because they happen BEFORE the 165 // CXXConstructExpr subexpression. See PR12014 for some discussion. 166 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 167 168 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 169 const LocationContext *LCtx = Pred->getLocationContext(); 170 DefinedOrUnknownSVal symVal = 171 svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount); 172 ProgramStateRef State = Pred->getState(); 173 174 // Invalidate placement args. 175 CXXAllocatorCall Call(CNE, State, LCtx); 176 State = Call.invalidateRegions(blockCount); 177 178 if (CNE->isArray()) { 179 // FIXME: allocating an array requires simulating the constructors. 180 // For now, just return a symbolicated region. 181 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 182 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 183 const ElementRegion *EleReg = 184 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 185 State = State->BindExpr(CNE, Pred->getLocationContext(), 186 loc::MemRegionVal(EleReg)); 187 Bldr.generateNode(CNE, Pred, State); 188 return; 189 } 190 191 // FIXME: Once we have proper support for CXXConstructExprs inside 192 // CXXNewExpr, we need to make sure that the constructed object is not 193 // immediately invalidated here. (The placement call should happen before 194 // the constructor call anyway.) 195 FunctionDecl *FD = CNE->getOperatorNew(); 196 if (FD && FD->isReservedGlobalPlacementOperator()) { 197 // Non-array placement new should always return the placement location. 198 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 199 State = State->BindExpr(CNE, LCtx, PlacementLoc); 200 } else { 201 State = State->BindExpr(CNE, LCtx, symVal); 202 } 203 204 // If the type is not a record, we won't have a CXXConstructExpr as an 205 // initializer. Copy the value over. 206 if (const Expr *Init = CNE->getInitializer()) { 207 if (!isa<CXXConstructExpr>(Init)) { 208 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 209 (void)ObjTy; 210 assert(!ObjTy->isRecordType()); 211 SVal Location = State->getSVal(CNE, LCtx); 212 if (isa<Loc>(Location)) 213 State = State->bindLoc(cast<Loc>(Location), State->getSVal(Init, LCtx)); 214 } 215 } 216 217 Bldr.generateNode(CNE, Pred, State); 218} 219 220void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 221 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 222 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 223 ProgramStateRef state = Pred->getState(); 224 Bldr.generateNode(CDE, Pred, state); 225} 226 227void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 228 ExplodedNode *Pred, 229 ExplodedNodeSet &Dst) { 230 const VarDecl *VD = CS->getExceptionDecl(); 231 if (!VD) { 232 Dst.Add(Pred); 233 return; 234 } 235 236 const LocationContext *LCtx = Pred->getLocationContext(); 237 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 238 currentBuilderContext->getCurrentBlockCount()); 239 ProgramStateRef state = Pred->getState(); 240 state = state->bindLoc(state->getLValue(VD, LCtx), V); 241 242 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 243 Bldr.generateNode(CS, Pred, state); 244} 245 246void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 247 ExplodedNodeSet &Dst) { 248 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 249 250 // Get the this object region from StoreManager. 251 const LocationContext *LCtx = Pred->getLocationContext(); 252 const MemRegion *R = 253 svalBuilder.getRegionManager().getCXXThisRegion( 254 getContext().getCanonicalType(TE->getType()), 255 LCtx); 256 257 ProgramStateRef state = Pred->getState(); 258 SVal V = state->getSVal(loc::MemRegionVal(R)); 259 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 260} 261