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 22 using namespace clang; 23 using namespace ento; 24 25 void 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 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); 34 Bldr.generateNode(ME, Pred, state); 35 } 36 37 // FIXME: This is the sort of code that should eventually live in a Core 38 // checker rather than as a special case in ExprEngine. 39 void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 40 const CallEvent &Call) { 41 SVal ThisVal; 42 bool AlwaysReturnsLValue; 43 if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 44 assert(Ctor->getDecl()->isTrivial()); 45 assert(Ctor->getDecl()->isCopyOrMoveConstructor()); 46 ThisVal = Ctor->getCXXThisVal(); 47 AlwaysReturnsLValue = false; 48 } else { 49 assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); 50 assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == 51 OO_Equal); 52 ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); 53 AlwaysReturnsLValue = true; 54 } 55 56 const LocationContext *LCtx = Pred->getLocationContext(); 57 58 ExplodedNodeSet Dst; 59 Bldr.takeNodes(Pred); 60 61 SVal V = Call.getArgSVal(0); 62 63 // If the value being copied is not unknown, load from its location to get 64 // an aggregate rvalue. 65 if (Optional<Loc> L = V.getAs<Loc>()) 66 V = Pred->getState()->getSVal(*L); 67 else 68 assert(V.isUnknown()); 69 70 const Expr *CallExpr = Call.getOriginExpr(); 71 evalBind(Dst, CallExpr, Pred, ThisVal, V, true); 72 73 PostStmt PS(CallExpr, LCtx); 74 for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); 75 I != E; ++I) { 76 ProgramStateRef State = (*I)->getState(); 77 if (AlwaysReturnsLValue) 78 State = State->BindExpr(CallExpr, LCtx, ThisVal); 79 else 80 State = bindReturnValue(Call, LCtx, State); 81 Bldr.generateNode(PS, State, *I); 82 } 83 } 84 85 86 /// Returns a region representing the first element of a (possibly 87 /// multi-dimensional) array. 88 /// 89 /// On return, \p Ty will be set to the base type of the array. 90 /// 91 /// If the type is not an array type at all, the original value is returned. 92 static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue, 93 QualType &Ty) { 94 SValBuilder &SVB = State->getStateManager().getSValBuilder(); 95 ASTContext &Ctx = SVB.getContext(); 96 97 while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) { 98 Ty = AT->getElementType(); 99 LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue); 100 } 101 102 return LValue; 103 } 104 105 106 const MemRegion * 107 ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE, 108 ExplodedNode *Pred) { 109 const LocationContext *LCtx = Pred->getLocationContext(); 110 ProgramStateRef State = Pred->getState(); 111 112 // See if we're constructing an existing region by looking at the next 113 // element in the CFG. 114 115 if (auto Elem = findElementDirectlyInitializedByCurrentConstructor()) { 116 if (Optional<CFGStmt> StmtElem = Elem->getAs<CFGStmt>()) { 117 auto *DS = cast<DeclStmt>(StmtElem->getStmt()); 118 if (const auto *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { 119 if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) { 120 SVal LValue = State->getLValue(Var, LCtx); 121 QualType Ty = Var->getType(); 122 LValue = makeZeroElementRegion(State, LValue, Ty); 123 return LValue.getAsRegion(); 124 } 125 } 126 } else if (Optional<CFGInitializer> InitElem = Elem->getAs<CFGInitializer>()) { 127 const CXXCtorInitializer *Init = InitElem->getInitializer(); 128 assert(Init->isAnyMemberInitializer()); 129 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 130 Loc ThisPtr = 131 getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame()); 132 SVal ThisVal = State->getSVal(ThisPtr); 133 134 const ValueDecl *Field; 135 SVal FieldVal; 136 if (Init->isIndirectMemberInitializer()) { 137 Field = Init->getIndirectMember(); 138 FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); 139 } else { 140 Field = Init->getMember(); 141 FieldVal = State->getLValue(Init->getMember(), ThisVal); 142 } 143 144 QualType Ty = Field->getType(); 145 FieldVal = makeZeroElementRegion(State, FieldVal, Ty); 146 return FieldVal.getAsRegion(); 147 } 148 149 // FIXME: This will eventually need to handle new-expressions as well. 150 // Don't forget to update the pre-constructor initialization code in 151 // ExprEngine::VisitCXXConstructExpr. 152 } 153 // If we couldn't find an existing region to construct into, assume we're 154 // constructing a temporary. 155 MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); 156 return MRMgr.getCXXTempObjectRegion(CE, LCtx); 157 } 158 159 /// Returns true if the initializer for \Elem can be a direct 160 /// constructor. 161 static bool canHaveDirectConstructor(CFGElement Elem){ 162 // DeclStmts and CXXCtorInitializers for fields can be directly constructed. 163 164 if (Optional<CFGStmt> StmtElem = Elem.getAs<CFGStmt>()) { 165 if (isa<DeclStmt>(StmtElem->getStmt())) { 166 return true; 167 } 168 } 169 170 if (Elem.getKind() == CFGElement::Initializer) { 171 return true; 172 } 173 174 return false; 175 } 176 177 Optional<CFGElement> 178 ExprEngine::findElementDirectlyInitializedByCurrentConstructor() { 179 const NodeBuilderContext &CurrBldrCtx = getBuilderContext(); 180 // See if we're constructing an existing region by looking at the next 181 // element in the CFG. 182 const CFGBlock *B = CurrBldrCtx.getBlock(); 183 assert(isa<CXXConstructExpr>(((*B)[currStmtIdx]).castAs<CFGStmt>().getStmt())); 184 unsigned int NextStmtIdx = currStmtIdx + 1; 185 if (NextStmtIdx >= B->size()) 186 return None; 187 188 CFGElement Next = (*B)[NextStmtIdx]; 189 190 // Is this a destructor? If so, we might be in the middle of an assignment 191 // to a local or member: look ahead one more element to see what we find. 192 while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) { 193 ++NextStmtIdx; 194 Next = (*B)[NextStmtIdx]; 195 } 196 197 if (canHaveDirectConstructor(Next)) 198 return Next; 199 200 return None; 201 } 202 203 const CXXConstructExpr * 204 ExprEngine::findDirectConstructorForCurrentCFGElement() { 205 // Go backward in the CFG to see if the previous element (ignoring 206 // destructors) was a CXXConstructExpr. If so, that constructor 207 // was constructed directly into an existing region. 208 // This process is essentially the inverse of that performed in 209 // findElementDirectlyInitializedByCurrentConstructor(). 210 if (currStmtIdx == 0) 211 return nullptr; 212 213 const CFGBlock *B = getBuilderContext().getBlock(); 214 assert(canHaveDirectConstructor((*B)[currStmtIdx])); 215 216 unsigned int PreviousStmtIdx = currStmtIdx - 1; 217 CFGElement Previous = (*B)[PreviousStmtIdx]; 218 219 while (Previous.getAs<CFGImplicitDtor>() && PreviousStmtIdx > 0) { 220 --PreviousStmtIdx; 221 Previous = (*B)[PreviousStmtIdx]; 222 } 223 224 if (Optional<CFGStmt> PrevStmtElem = Previous.getAs<CFGStmt>()) { 225 if (auto *CtorExpr = dyn_cast<CXXConstructExpr>(PrevStmtElem->getStmt())) { 226 return CtorExpr; 227 } 228 } 229 230 return nullptr; 231 } 232 233 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 234 ExplodedNode *Pred, 235 ExplodedNodeSet &destNodes) { 236 const LocationContext *LCtx = Pred->getLocationContext(); 237 ProgramStateRef State = Pred->getState(); 238 239 const MemRegion *Target = nullptr; 240 241 // FIXME: Handle arrays, which run the same constructor for every element. 242 // For now, we just run the first constructor (which should still invalidate 243 // the entire array). 244 245 switch (CE->getConstructionKind()) { 246 case CXXConstructExpr::CK_Complete: { 247 Target = getRegionForConstructedObject(CE, Pred); 248 break; 249 } 250 case CXXConstructExpr::CK_VirtualBase: 251 // Make sure we are not calling virtual base class initializers twice. 252 // Only the most-derived object should initialize virtual base classes. 253 if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) { 254 const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer); 255 if (OuterCtor) { 256 switch (OuterCtor->getConstructionKind()) { 257 case CXXConstructExpr::CK_NonVirtualBase: 258 case CXXConstructExpr::CK_VirtualBase: 259 // Bail out! 260 destNodes.Add(Pred); 261 return; 262 case CXXConstructExpr::CK_Complete: 263 case CXXConstructExpr::CK_Delegating: 264 break; 265 } 266 } 267 } 268 // FALLTHROUGH 269 case CXXConstructExpr::CK_NonVirtualBase: 270 case CXXConstructExpr::CK_Delegating: { 271 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 272 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 273 LCtx->getCurrentStackFrame()); 274 SVal ThisVal = State->getSVal(ThisPtr); 275 276 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 277 Target = ThisVal.getAsRegion(); 278 } else { 279 // Cast to the base type. 280 bool IsVirtual = 281 (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); 282 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), 283 IsVirtual); 284 Target = BaseVal.getAsRegion(); 285 } 286 break; 287 } 288 } 289 290 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 291 CallEventRef<CXXConstructorCall> Call = 292 CEMgr.getCXXConstructorCall(CE, Target, State, LCtx); 293 294 ExplodedNodeSet DstPreVisit; 295 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 296 297 ExplodedNodeSet PreInitialized; 298 { 299 StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); 300 if (CE->requiresZeroInitialization()) { 301 // Type of the zero doesn't matter. 302 SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy); 303 304 for (ExplodedNodeSet::iterator I = DstPreVisit.begin(), 305 E = DstPreVisit.end(); 306 I != E; ++I) { 307 ProgramStateRef State = (*I)->getState(); 308 // FIXME: Once we properly handle constructors in new-expressions, we'll 309 // need to invalidate the region before setting a default value, to make 310 // sure there aren't any lingering bindings around. This probably needs 311 // to happen regardless of whether or not the object is zero-initialized 312 // to handle random fields of a placement-initialized object picking up 313 // old bindings. We might only want to do it when we need to, though. 314 // FIXME: This isn't actually correct for arrays -- we need to zero- 315 // initialize the entire array, not just the first element -- but our 316 // handling of arrays everywhere else is weak as well, so this shouldn't 317 // actually make things worse. Placement new makes this tricky as well, 318 // since it's then possible to be initializing one part of a multi- 319 // dimensional array. 320 State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal); 321 Bldr.generateNode(CE, *I, State, /*tag=*/nullptr, 322 ProgramPoint::PreStmtKind); 323 } 324 } 325 } 326 327 ExplodedNodeSet DstPreCall; 328 getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, 329 *Call, *this); 330 331 ExplodedNodeSet DstEvaluated; 332 StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); 333 334 bool IsArray = isa<ElementRegion>(Target); 335 if (CE->getConstructor()->isTrivial() && 336 CE->getConstructor()->isCopyOrMoveConstructor() && 337 !IsArray) { 338 // FIXME: Handle other kinds of trivial constructors as well. 339 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 340 I != E; ++I) 341 performTrivialCopy(Bldr, *I, *Call); 342 343 } else { 344 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 345 I != E; ++I) 346 defaultEvalCall(Bldr, *I, *Call); 347 } 348 349 ExplodedNodeSet DstPostCall; 350 getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated, 351 *Call, *this); 352 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 353 } 354 355 void ExprEngine::VisitCXXDestructor(QualType ObjectType, 356 const MemRegion *Dest, 357 const Stmt *S, 358 bool IsBaseDtor, 359 ExplodedNode *Pred, 360 ExplodedNodeSet &Dst) { 361 const LocationContext *LCtx = Pred->getLocationContext(); 362 ProgramStateRef State = Pred->getState(); 363 364 // FIXME: We need to run the same destructor on every element of the array. 365 // This workaround will just run the first destructor (which will still 366 // invalidate the entire array). 367 SVal DestVal = UnknownVal(); 368 if (Dest) 369 DestVal = loc::MemRegionVal(Dest); 370 DestVal = makeZeroElementRegion(State, DestVal, ObjectType); 371 Dest = DestVal.getAsRegion(); 372 373 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 374 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 375 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 376 377 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 378 CallEventRef<CXXDestructorCall> Call = 379 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); 380 381 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 382 Call->getSourceRange().getBegin(), 383 "Error evaluating destructor"); 384 385 ExplodedNodeSet DstPreCall; 386 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 387 *Call, *this); 388 389 ExplodedNodeSet DstInvalidated; 390 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 391 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 392 I != E; ++I) 393 defaultEvalCall(Bldr, *I, *Call); 394 395 ExplodedNodeSet DstPostCall; 396 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 397 *Call, *this); 398 } 399 400 void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, 401 ExplodedNode *Pred, 402 ExplodedNodeSet &Dst) { 403 ProgramStateRef State = Pred->getState(); 404 const LocationContext *LCtx = Pred->getLocationContext(); 405 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 406 CNE->getStartLoc(), 407 "Error evaluating New Allocator Call"); 408 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 409 CallEventRef<CXXAllocatorCall> Call = 410 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 411 412 ExplodedNodeSet DstPreCall; 413 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 414 *Call, *this); 415 416 ExplodedNodeSet DstInvalidated; 417 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 418 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 419 I != E; ++I) 420 defaultEvalCall(Bldr, *I, *Call); 421 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 422 *Call, *this); 423 } 424 425 426 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 427 ExplodedNodeSet &Dst) { 428 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 429 // Also, we need to decide how allocators actually work -- they're not 430 // really part of the CXXNewExpr because they happen BEFORE the 431 // CXXConstructExpr subexpression. See PR12014 for some discussion. 432 433 unsigned blockCount = currBldrCtx->blockCount(); 434 const LocationContext *LCtx = Pred->getLocationContext(); 435 DefinedOrUnknownSVal symVal = UnknownVal(); 436 FunctionDecl *FD = CNE->getOperatorNew(); 437 438 bool IsStandardGlobalOpNewFunction = false; 439 if (FD && !isa<CXXMethodDecl>(FD) && !FD->isVariadic()) { 440 if (FD->getNumParams() == 2) { 441 QualType T = FD->getParamDecl(1)->getType(); 442 if (const IdentifierInfo *II = T.getBaseTypeIdentifier()) 443 // NoThrow placement new behaves as a standard new. 444 IsStandardGlobalOpNewFunction = II->getName().equals("nothrow_t"); 445 } 446 else 447 // Placement forms are considered non-standard. 448 IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1); 449 } 450 451 // We assume all standard global 'operator new' functions allocate memory in 452 // heap. We realize this is an approximation that might not correctly model 453 // a custom global allocator. 454 if (IsStandardGlobalOpNewFunction) 455 symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount); 456 else 457 symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(), 458 blockCount); 459 460 ProgramStateRef State = Pred->getState(); 461 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 462 CallEventRef<CXXAllocatorCall> Call = 463 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 464 465 // Invalidate placement args. 466 // FIXME: Once we figure out how we want allocators to work, 467 // we should be using the usual pre-/(default-)eval-/post-call checks here. 468 State = Call->invalidateRegions(blockCount); 469 if (!State) 470 return; 471 472 // If this allocation function is not declared as non-throwing, failures 473 // /must/ be signalled by exceptions, and thus the return value will never be 474 // NULL. -fno-exceptions does not influence this semantics. 475 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case 476 // where new can return NULL. If we end up supporting that option, we can 477 // consider adding a check for it here. 478 // C++11 [basic.stc.dynamic.allocation]p3. 479 if (FD) { 480 QualType Ty = FD->getType(); 481 if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>()) 482 if (!ProtoType->isNothrow(getContext())) 483 State = State->assume(symVal, true); 484 } 485 486 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 487 488 if (CNE->isArray()) { 489 // FIXME: allocating an array requires simulating the constructors. 490 // For now, just return a symbolicated region. 491 const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion(); 492 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 493 const ElementRegion *EleReg = 494 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 495 State = State->BindExpr(CNE, Pred->getLocationContext(), 496 loc::MemRegionVal(EleReg)); 497 Bldr.generateNode(CNE, Pred, State); 498 return; 499 } 500 501 // FIXME: Once we have proper support for CXXConstructExprs inside 502 // CXXNewExpr, we need to make sure that the constructed object is not 503 // immediately invalidated here. (The placement call should happen before 504 // the constructor call anyway.) 505 SVal Result = symVal; 506 if (FD && FD->isReservedGlobalPlacementOperator()) { 507 // Non-array placement new should always return the placement location. 508 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 509 Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), 510 CNE->getPlacementArg(0)->getType()); 511 } 512 513 // Bind the address of the object, then check to see if we cached out. 514 State = State->BindExpr(CNE, LCtx, Result); 515 ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State); 516 if (!NewN) 517 return; 518 519 // If the type is not a record, we won't have a CXXConstructExpr as an 520 // initializer. Copy the value over. 521 if (const Expr *Init = CNE->getInitializer()) { 522 if (!isa<CXXConstructExpr>(Init)) { 523 assert(Bldr.getResults().size() == 1); 524 Bldr.takeNodes(NewN); 525 evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx), 526 /*FirstInit=*/IsStandardGlobalOpNewFunction); 527 } 528 } 529 } 530 531 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 532 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 533 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 534 ProgramStateRef state = Pred->getState(); 535 Bldr.generateNode(CDE, Pred, state); 536 } 537 538 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 539 ExplodedNode *Pred, 540 ExplodedNodeSet &Dst) { 541 const VarDecl *VD = CS->getExceptionDecl(); 542 if (!VD) { 543 Dst.Add(Pred); 544 return; 545 } 546 547 const LocationContext *LCtx = Pred->getLocationContext(); 548 SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), 549 currBldrCtx->blockCount()); 550 ProgramStateRef state = Pred->getState(); 551 state = state->bindLoc(state->getLValue(VD, LCtx), V); 552 553 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 554 Bldr.generateNode(CS, Pred, state); 555 } 556 557 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 558 ExplodedNodeSet &Dst) { 559 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 560 561 // Get the this object region from StoreManager. 562 const LocationContext *LCtx = Pred->getLocationContext(); 563 const MemRegion *R = 564 svalBuilder.getRegionManager().getCXXThisRegion( 565 getContext().getCanonicalType(TE->getType()), 566 LCtx); 567 568 ProgramStateRef state = Pred->getState(); 569 SVal V = state->getSVal(loc::MemRegionVal(R)); 570 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 571 } 572 573 void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, 574 ExplodedNodeSet &Dst) { 575 const LocationContext *LocCtxt = Pred->getLocationContext(); 576 577 // Get the region of the lambda itself. 578 const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion( 579 LE, LocCtxt); 580 SVal V = loc::MemRegionVal(R); 581 582 ProgramStateRef State = Pred->getState(); 583 584 // If we created a new MemRegion for the lambda, we should explicitly bind 585 // the captures. 586 CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin(); 587 for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(), 588 e = LE->capture_init_end(); 589 i != e; ++i, ++CurField) { 590 FieldDecl *FieldForCapture = *CurField; 591 SVal FieldLoc = State->getLValue(FieldForCapture, V); 592 593 SVal InitVal; 594 if (!FieldForCapture->hasCapturedVLAType()) { 595 Expr *InitExpr = *i; 596 assert(InitExpr && "Capture missing initialization expression"); 597 InitVal = State->getSVal(InitExpr, LocCtxt); 598 } else { 599 // The field stores the length of a captured variable-length array. 600 // These captures don't have initialization expressions; instead we 601 // get the length from the VLAType size expression. 602 Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr(); 603 InitVal = State->getSVal(SizeExpr, LocCtxt); 604 } 605 606 State = State->bindLoc(FieldLoc, InitVal); 607 } 608 609 // Decay the Loc into an RValue, because there might be a 610 // MaterializeTemporaryExpr node above this one which expects the bound value 611 // to be an RValue. 612 SVal LambdaRVal = State->getSVal(R); 613 614 ExplodedNodeSet Tmp; 615 StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); 616 // FIXME: is this the right program point kind? 617 Bldr.generateNode(LE, Pred, 618 State->BindExpr(LE, LocCtxt, LambdaRVal), 619 nullptr, ProgramPoint::PostLValueKind); 620 621 // FIXME: Move all post/pre visits to ::Visit(). 622 getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this); 623 } 624