ExprEngineCXX.cpp revision 5e5440ba9c135f523f72e7e7c5da59d390d697c5
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/PathSensitive/ExprEngine.h" 15#include "clang/AST/DeclCXX.h" 16#include "clang/AST/StmtCXX.h" 17#include "clang/Basic/PrettyStackTrace.h" 18#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 20#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 21 22using namespace clang; 23using namespace ento; 24 25void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 26 ExplodedNode *Pred, 27 ExplodedNodeSet &Dst) { 28 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 29 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 30 ProgramStateRef state = Pred->getState(); 31 const LocationContext *LCtx = Pred->getLocationContext(); 32 33 SVal V = state->getSVal(tempExpr, LCtx); 34 35 // If the value is already a CXXTempObjectRegion, it is fine as it is. 36 // Otherwise, create a new CXXTempObjectRegion, and copy the value into it. 37 const MemRegion *MR = V.getAsRegion(); 38 if (MR && isa<CXXTempObjectRegion>(MR)) 39 state = state->BindExpr(ME, LCtx, V); 40 else 41 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); 42 43 Bldr.generateNode(ME, Pred, state); 44} 45 46void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 47 const CXXConstructorCall &Call) { 48 const CXXConstructExpr *CtorExpr = Call.getOriginExpr(); 49 assert(CtorExpr->getConstructor()->isCopyOrMoveConstructor()); 50 assert(CtorExpr->getConstructor()->isTrivial()); 51 52 SVal ThisVal = Call.getCXXThisVal(); 53 const LocationContext *LCtx = Pred->getLocationContext(); 54 55 ExplodedNodeSet Dst; 56 Bldr.takeNodes(Pred); 57 58 SVal V = Call.getArgSVal(0); 59 60 // Make sure the value being copied is not unknown. 61 if (Optional<Loc> L = V.getAs<Loc>()) 62 V = Pred->getState()->getSVal(*L); 63 64 evalBind(Dst, CtorExpr, Pred, ThisVal, V, true); 65 66 PostStmt PS(CtorExpr, LCtx); 67 for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); 68 I != E; ++I) { 69 ProgramStateRef State = (*I)->getState(); 70 State = bindReturnValue(Call, LCtx, State); 71 Bldr.generateNode(PS, State, *I); 72 } 73} 74 75void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 76 ExplodedNode *Pred, 77 ExplodedNodeSet &destNodes) { 78 const LocationContext *LCtx = Pred->getLocationContext(); 79 ProgramStateRef State = Pred->getState(); 80 81 const MemRegion *Target = 0; 82 bool IsArray = false; 83 84 switch (CE->getConstructionKind()) { 85 case CXXConstructExpr::CK_Complete: { 86 // See if we're constructing an existing region by looking at the next 87 // element in the CFG. 88 const CFGBlock *B = currBldrCtx->getBlock(); 89 if (currStmtIdx + 1 < B->size()) { 90 CFGElement Next = (*B)[currStmtIdx+1]; 91 92 // Is this a constructor for a local variable? 93 if (CFGStmt StmtElem = Next.getAs<CFGStmt>()) { 94 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem.getStmt())) { 95 if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { 96 if (Var->getInit()->IgnoreImplicit() == CE) { 97 QualType Ty = Var->getType(); 98 if (const ArrayType *AT = getContext().getAsArrayType(Ty)) { 99 // FIXME: Handle arrays, which run the same constructor for 100 // every element. This workaround will just run the first 101 // constructor (which should still invalidate the entire array). 102 SVal Base = State->getLValue(Var, LCtx); 103 Target = State->getLValue(AT->getElementType(), 104 getSValBuilder().makeZeroArrayIndex(), 105 Base).getAsRegion(); 106 IsArray = true; 107 } else { 108 Target = State->getLValue(Var, LCtx).getAsRegion(); 109 } 110 } 111 } 112 } 113 } 114 115 // Is this a constructor for a member? 116 if (CFGInitializer InitElem = Next.getAs<CFGInitializer>()) { 117 const CXXCtorInitializer *Init = InitElem.getInitializer(); 118 assert(Init->isAnyMemberInitializer()); 119 120 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 121 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 122 LCtx->getCurrentStackFrame()); 123 SVal ThisVal = State->getSVal(ThisPtr); 124 125 if (Init->isIndirectMemberInitializer()) { 126 SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal); 127 Target = Field.getAsRegion(); 128 } else { 129 SVal Field = State->getLValue(Init->getMember(), ThisVal); 130 Target = Field.getAsRegion(); 131 } 132 } 133 134 // FIXME: This will eventually need to handle new-expressions as well. 135 } 136 137 // If we couldn't find an existing region to construct into, assume we're 138 // constructing a temporary. 139 if (!Target) { 140 MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); 141 Target = MRMgr.getCXXTempObjectRegion(CE, LCtx); 142 } 143 144 break; 145 } 146 case CXXConstructExpr::CK_NonVirtualBase: 147 case CXXConstructExpr::CK_VirtualBase: 148 case CXXConstructExpr::CK_Delegating: { 149 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 150 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 151 LCtx->getCurrentStackFrame()); 152 SVal ThisVal = State->getSVal(ThisPtr); 153 154 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 155 Target = ThisVal.getAsRegion(); 156 } else { 157 // Cast to the base type. 158 bool IsVirtual = 159 (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); 160 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), 161 IsVirtual); 162 Target = BaseVal.getAsRegion(); 163 } 164 break; 165 } 166 } 167 168 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 169 CallEventRef<CXXConstructorCall> Call = 170 CEMgr.getCXXConstructorCall(CE, Target, State, LCtx); 171 172 ExplodedNodeSet DstPreVisit; 173 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 174 ExplodedNodeSet DstPreCall; 175 getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, 176 *Call, *this); 177 178 ExplodedNodeSet DstEvaluated; 179 StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); 180 181 if (CE->getConstructor()->isTrivial() && 182 CE->getConstructor()->isCopyOrMoveConstructor() && 183 !IsArray) { 184 // FIXME: Handle other kinds of trivial constructors as well. 185 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 186 I != E; ++I) 187 performTrivialCopy(Bldr, *I, *Call); 188 189 } else { 190 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 191 I != E; ++I) 192 defaultEvalCall(Bldr, *I, *Call); 193 } 194 195 ExplodedNodeSet DstPostCall; 196 getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated, 197 *Call, *this); 198 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 199} 200 201void ExprEngine::VisitCXXDestructor(QualType ObjectType, 202 const MemRegion *Dest, 203 const Stmt *S, 204 bool IsBaseDtor, 205 ExplodedNode *Pred, 206 ExplodedNodeSet &Dst) { 207 const LocationContext *LCtx = Pred->getLocationContext(); 208 ProgramStateRef State = Pred->getState(); 209 210 // FIXME: We need to run the same destructor on every element of the array. 211 // This workaround will just run the first destructor (which will still 212 // invalidate the entire array). 213 // This is a loop because of multidimensional arrays. 214 while (const ArrayType *AT = getContext().getAsArrayType(ObjectType)) { 215 ObjectType = AT->getElementType(); 216 Dest = State->getLValue(ObjectType, getSValBuilder().makeZeroArrayIndex(), 217 loc::MemRegionVal(Dest)).getAsRegion(); 218 } 219 220 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 221 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 222 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 223 224 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 225 CallEventRef<CXXDestructorCall> Call = 226 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); 227 228 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 229 Call->getSourceRange().getBegin(), 230 "Error evaluating destructor"); 231 232 ExplodedNodeSet DstPreCall; 233 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 234 *Call, *this); 235 236 ExplodedNodeSet DstInvalidated; 237 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 238 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 239 I != E; ++I) 240 defaultEvalCall(Bldr, *I, *Call); 241 242 ExplodedNodeSet DstPostCall; 243 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 244 *Call, *this); 245} 246 247void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 248 ExplodedNodeSet &Dst) { 249 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 250 // Also, we need to decide how allocators actually work -- they're not 251 // really part of the CXXNewExpr because they happen BEFORE the 252 // CXXConstructExpr subexpression. See PR12014 for some discussion. 253 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 254 255 unsigned blockCount = currBldrCtx->blockCount(); 256 const LocationContext *LCtx = Pred->getLocationContext(); 257 DefinedOrUnknownSVal symVal = svalBuilder.conjureSymbolVal(0, CNE, LCtx, 258 CNE->getType(), 259 blockCount); 260 ProgramStateRef State = Pred->getState(); 261 262 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 263 CallEventRef<CXXAllocatorCall> Call = 264 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 265 266 // Invalidate placement args. 267 // FIXME: Once we figure out how we want allocators to work, 268 // we should be using the usual pre-/(default-)eval-/post-call checks here. 269 State = Call->invalidateRegions(blockCount); 270 271 // If we're compiling with exceptions enabled, and this allocation function 272 // is not declared as non-throwing, failures /must/ be signalled by 273 // exceptions, and thus the return value will never be NULL. 274 // C++11 [basic.stc.dynamic.allocation]p3. 275 FunctionDecl *FD = CNE->getOperatorNew(); 276 if (FD && getContext().getLangOpts().CXXExceptions) { 277 QualType Ty = FD->getType(); 278 if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>()) 279 if (!ProtoType->isNothrow(getContext())) 280 State = State->assume(symVal, true); 281 } 282 283 if (CNE->isArray()) { 284 // FIXME: allocating an array requires simulating the constructors. 285 // For now, just return a symbolicated region. 286 const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion(); 287 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 288 const ElementRegion *EleReg = 289 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 290 State = State->BindExpr(CNE, Pred->getLocationContext(), 291 loc::MemRegionVal(EleReg)); 292 Bldr.generateNode(CNE, Pred, State); 293 return; 294 } 295 296 // FIXME: Once we have proper support for CXXConstructExprs inside 297 // CXXNewExpr, we need to make sure that the constructed object is not 298 // immediately invalidated here. (The placement call should happen before 299 // the constructor call anyway.) 300 if (FD && FD->isReservedGlobalPlacementOperator()) { 301 // Non-array placement new should always return the placement location. 302 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 303 SVal Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), 304 CNE->getPlacementArg(0)->getType()); 305 State = State->BindExpr(CNE, LCtx, Result); 306 } else { 307 State = State->BindExpr(CNE, LCtx, symVal); 308 } 309 310 // If the type is not a record, we won't have a CXXConstructExpr as an 311 // initializer. Copy the value over. 312 if (const Expr *Init = CNE->getInitializer()) { 313 if (!isa<CXXConstructExpr>(Init)) { 314 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 315 (void)ObjTy; 316 assert(!ObjTy->isRecordType()); 317 SVal Location = State->getSVal(CNE, LCtx); 318 if (Optional<Loc> LV = Location.getAs<Loc>()) 319 State = State->bindLoc(*LV, State->getSVal(Init, LCtx)); 320 } 321 } 322 323 Bldr.generateNode(CNE, Pred, State); 324} 325 326void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 327 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 328 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 329 ProgramStateRef state = Pred->getState(); 330 Bldr.generateNode(CDE, Pred, state); 331} 332 333void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 334 ExplodedNode *Pred, 335 ExplodedNodeSet &Dst) { 336 const VarDecl *VD = CS->getExceptionDecl(); 337 if (!VD) { 338 Dst.Add(Pred); 339 return; 340 } 341 342 const LocationContext *LCtx = Pred->getLocationContext(); 343 SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), 344 currBldrCtx->blockCount()); 345 ProgramStateRef state = Pred->getState(); 346 state = state->bindLoc(state->getLValue(VD, LCtx), V); 347 348 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 349 Bldr.generateNode(CS, Pred, state); 350} 351 352void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 353 ExplodedNodeSet &Dst) { 354 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 355 356 // Get the this object region from StoreManager. 357 const LocationContext *LCtx = Pred->getLocationContext(); 358 const MemRegion *R = 359 svalBuilder.getRegionManager().getCXXThisRegion( 360 getContext().getCanonicalType(TE->getType()), 361 LCtx); 362 363 ProgramStateRef state = Pred->getState(); 364 SVal V = state->getSVal(loc::MemRegionVal(R)); 365 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 366} 367