clang API Documentation
00001 //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the C++ expression evaluation engine. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 00015 #include "clang/AST/DeclCXX.h" 00016 #include "clang/AST/StmtCXX.h" 00017 #include "clang/Basic/PrettyStackTrace.h" 00018 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 00020 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 00021 00022 using namespace clang; 00023 using namespace ento; 00024 00025 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 00026 ExplodedNode *Pred, 00027 ExplodedNodeSet &Dst) { 00028 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 00029 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 00030 ProgramStateRef state = Pred->getState(); 00031 const LocationContext *LCtx = Pred->getLocationContext(); 00032 00033 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); 00034 Bldr.generateNode(ME, Pred, state); 00035 } 00036 00037 // FIXME: This is the sort of code that should eventually live in a Core 00038 // checker rather than as a special case in ExprEngine. 00039 void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 00040 const CallEvent &Call) { 00041 SVal ThisVal; 00042 bool AlwaysReturnsLValue; 00043 if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 00044 assert(Ctor->getDecl()->isTrivial()); 00045 assert(Ctor->getDecl()->isCopyOrMoveConstructor()); 00046 ThisVal = Ctor->getCXXThisVal(); 00047 AlwaysReturnsLValue = false; 00048 } else { 00049 assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); 00050 assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == 00051 OO_Equal); 00052 ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); 00053 AlwaysReturnsLValue = true; 00054 } 00055 00056 const LocationContext *LCtx = Pred->getLocationContext(); 00057 00058 ExplodedNodeSet Dst; 00059 Bldr.takeNodes(Pred); 00060 00061 SVal V = Call.getArgSVal(0); 00062 00063 // If the value being copied is not unknown, load from its location to get 00064 // an aggregate rvalue. 00065 if (Optional<Loc> L = V.getAs<Loc>()) 00066 V = Pred->getState()->getSVal(*L); 00067 else 00068 assert(V.isUnknown()); 00069 00070 const Expr *CallExpr = Call.getOriginExpr(); 00071 evalBind(Dst, CallExpr, Pred, ThisVal, V, true); 00072 00073 PostStmt PS(CallExpr, LCtx); 00074 for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); 00075 I != E; ++I) { 00076 ProgramStateRef State = (*I)->getState(); 00077 if (AlwaysReturnsLValue) 00078 State = State->BindExpr(CallExpr, LCtx, ThisVal); 00079 else 00080 State = bindReturnValue(Call, LCtx, State); 00081 Bldr.generateNode(PS, State, *I); 00082 } 00083 } 00084 00085 00086 /// Returns a region representing the first element of a (possibly 00087 /// multi-dimensional) array. 00088 /// 00089 /// On return, \p Ty will be set to the base type of the array. 00090 /// 00091 /// If the type is not an array type at all, the original value is returned. 00092 static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue, 00093 QualType &Ty) { 00094 SValBuilder &SVB = State->getStateManager().getSValBuilder(); 00095 ASTContext &Ctx = SVB.getContext(); 00096 00097 while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) { 00098 Ty = AT->getElementType(); 00099 LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue); 00100 } 00101 00102 return LValue; 00103 } 00104 00105 00106 static const MemRegion *getRegionForConstructedObject( 00107 const CXXConstructExpr *CE, ExplodedNode *Pred, ExprEngine &Eng, 00108 unsigned int CurrStmtIdx) { 00109 const LocationContext *LCtx = Pred->getLocationContext(); 00110 ProgramStateRef State = Pred->getState(); 00111 const NodeBuilderContext &CurrBldrCtx = Eng.getBuilderContext(); 00112 00113 // See if we're constructing an existing region by looking at the next 00114 // element in the CFG. 00115 const CFGBlock *B = CurrBldrCtx.getBlock(); 00116 unsigned int NextStmtIdx = CurrStmtIdx + 1; 00117 if (NextStmtIdx < B->size()) { 00118 CFGElement Next = (*B)[NextStmtIdx]; 00119 00120 // Is this a destructor? If so, we might be in the middle of an assignment 00121 // to a local or member: look ahead one more element to see what we find. 00122 while (Next.getAs<CFGImplicitDtor>() && NextStmtIdx + 1 < B->size()) { 00123 ++NextStmtIdx; 00124 Next = (*B)[NextStmtIdx]; 00125 } 00126 00127 // Is this a constructor for a local variable? 00128 if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) { 00129 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) { 00130 if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { 00131 if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) { 00132 SVal LValue = State->getLValue(Var, LCtx); 00133 QualType Ty = Var->getType(); 00134 LValue = makeZeroElementRegion(State, LValue, Ty); 00135 return LValue.getAsRegion(); 00136 } 00137 } 00138 } 00139 } 00140 00141 // Is this a constructor for a member? 00142 if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) { 00143 const CXXCtorInitializer *Init = InitElem->getInitializer(); 00144 assert(Init->isAnyMemberInitializer()); 00145 00146 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 00147 Loc ThisPtr = Eng.getSValBuilder().getCXXThis(CurCtor, 00148 LCtx->getCurrentStackFrame()); 00149 SVal ThisVal = State->getSVal(ThisPtr); 00150 00151 const ValueDecl *Field; 00152 SVal FieldVal; 00153 if (Init->isIndirectMemberInitializer()) { 00154 Field = Init->getIndirectMember(); 00155 FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); 00156 } else { 00157 Field = Init->getMember(); 00158 FieldVal = State->getLValue(Init->getMember(), ThisVal); 00159 } 00160 00161 QualType Ty = Field->getType(); 00162 FieldVal = makeZeroElementRegion(State, FieldVal, Ty); 00163 return FieldVal.getAsRegion(); 00164 } 00165 00166 // FIXME: This will eventually need to handle new-expressions as well. 00167 // Don't forget to update the pre-constructor initialization code in 00168 // ExprEngine::VisitCXXConstructExpr. 00169 } 00170 00171 // If we couldn't find an existing region to construct into, assume we're 00172 // constructing a temporary. 00173 MemRegionManager &MRMgr = Eng.getSValBuilder().getRegionManager(); 00174 return MRMgr.getCXXTempObjectRegion(CE, LCtx); 00175 } 00176 00177 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 00178 ExplodedNode *Pred, 00179 ExplodedNodeSet &destNodes) { 00180 const LocationContext *LCtx = Pred->getLocationContext(); 00181 ProgramStateRef State = Pred->getState(); 00182 00183 const MemRegion *Target = nullptr; 00184 00185 // FIXME: Handle arrays, which run the same constructor for every element. 00186 // For now, we just run the first constructor (which should still invalidate 00187 // the entire array). 00188 00189 switch (CE->getConstructionKind()) { 00190 case CXXConstructExpr::CK_Complete: { 00191 Target = getRegionForConstructedObject(CE, Pred, *this, currStmtIdx); 00192 break; 00193 } 00194 case CXXConstructExpr::CK_VirtualBase: 00195 // Make sure we are not calling virtual base class initializers twice. 00196 // Only the most-derived object should initialize virtual base classes. 00197 if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) { 00198 const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer); 00199 if (OuterCtor) { 00200 switch (OuterCtor->getConstructionKind()) { 00201 case CXXConstructExpr::CK_NonVirtualBase: 00202 case CXXConstructExpr::CK_VirtualBase: 00203 // Bail out! 00204 destNodes.Add(Pred); 00205 return; 00206 case CXXConstructExpr::CK_Complete: 00207 case CXXConstructExpr::CK_Delegating: 00208 break; 00209 } 00210 } 00211 } 00212 // FALLTHROUGH 00213 case CXXConstructExpr::CK_NonVirtualBase: 00214 case CXXConstructExpr::CK_Delegating: { 00215 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 00216 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 00217 LCtx->getCurrentStackFrame()); 00218 SVal ThisVal = State->getSVal(ThisPtr); 00219 00220 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 00221 Target = ThisVal.getAsRegion(); 00222 } else { 00223 // Cast to the base type. 00224 bool IsVirtual = 00225 (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); 00226 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), 00227 IsVirtual); 00228 Target = BaseVal.getAsRegion(); 00229 } 00230 break; 00231 } 00232 } 00233 00234 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 00235 CallEventRef<CXXConstructorCall> Call = 00236 CEMgr.getCXXConstructorCall(CE, Target, State, LCtx); 00237 00238 ExplodedNodeSet DstPreVisit; 00239 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 00240 00241 ExplodedNodeSet PreInitialized; 00242 { 00243 StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); 00244 if (CE->requiresZeroInitialization()) { 00245 // Type of the zero doesn't matter. 00246 SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy); 00247 00248 for (ExplodedNodeSet::iterator I = DstPreVisit.begin(), 00249 E = DstPreVisit.end(); 00250 I != E; ++I) { 00251 ProgramStateRef State = (*I)->getState(); 00252 // FIXME: Once we properly handle constructors in new-expressions, we'll 00253 // need to invalidate the region before setting a default value, to make 00254 // sure there aren't any lingering bindings around. This probably needs 00255 // to happen regardless of whether or not the object is zero-initialized 00256 // to handle random fields of a placement-initialized object picking up 00257 // old bindings. We might only want to do it when we need to, though. 00258 // FIXME: This isn't actually correct for arrays -- we need to zero- 00259 // initialize the entire array, not just the first element -- but our 00260 // handling of arrays everywhere else is weak as well, so this shouldn't 00261 // actually make things worse. Placement new makes this tricky as well, 00262 // since it's then possible to be initializing one part of a multi- 00263 // dimensional array. 00264 State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal); 00265 Bldr.generateNode(CE, *I, State, /*tag=*/nullptr, 00266 ProgramPoint::PreStmtKind); 00267 } 00268 } 00269 } 00270 00271 ExplodedNodeSet DstPreCall; 00272 getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, 00273 *Call, *this); 00274 00275 ExplodedNodeSet DstEvaluated; 00276 StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); 00277 00278 bool IsArray = isa<ElementRegion>(Target); 00279 if (CE->getConstructor()->isTrivial() && 00280 CE->getConstructor()->isCopyOrMoveConstructor() && 00281 !IsArray) { 00282 // FIXME: Handle other kinds of trivial constructors as well. 00283 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 00284 I != E; ++I) 00285 performTrivialCopy(Bldr, *I, *Call); 00286 00287 } else { 00288 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 00289 I != E; ++I) 00290 defaultEvalCall(Bldr, *I, *Call); 00291 } 00292 00293 ExplodedNodeSet DstPostCall; 00294 getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated, 00295 *Call, *this); 00296 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 00297 } 00298 00299 void ExprEngine::VisitCXXDestructor(QualType ObjectType, 00300 const MemRegion *Dest, 00301 const Stmt *S, 00302 bool IsBaseDtor, 00303 ExplodedNode *Pred, 00304 ExplodedNodeSet &Dst) { 00305 const LocationContext *LCtx = Pred->getLocationContext(); 00306 ProgramStateRef State = Pred->getState(); 00307 00308 // FIXME: We need to run the same destructor on every element of the array. 00309 // This workaround will just run the first destructor (which will still 00310 // invalidate the entire array). 00311 SVal DestVal = UnknownVal(); 00312 if (Dest) 00313 DestVal = loc::MemRegionVal(Dest); 00314 DestVal = makeZeroElementRegion(State, DestVal, ObjectType); 00315 Dest = DestVal.getAsRegion(); 00316 00317 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 00318 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 00319 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 00320 00321 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 00322 CallEventRef<CXXDestructorCall> Call = 00323 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); 00324 00325 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 00326 Call->getSourceRange().getBegin(), 00327 "Error evaluating destructor"); 00328 00329 ExplodedNodeSet DstPreCall; 00330 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 00331 *Call, *this); 00332 00333 ExplodedNodeSet DstInvalidated; 00334 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 00335 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 00336 I != E; ++I) 00337 defaultEvalCall(Bldr, *I, *Call); 00338 00339 ExplodedNodeSet DstPostCall; 00340 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 00341 *Call, *this); 00342 } 00343 00344 void ExprEngine::VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, 00345 ExplodedNode *Pred, 00346 ExplodedNodeSet &Dst) { 00347 ProgramStateRef State = Pred->getState(); 00348 const LocationContext *LCtx = Pred->getLocationContext(); 00349 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 00350 CNE->getStartLoc(), 00351 "Error evaluating New Allocator Call"); 00352 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 00353 CallEventRef<CXXAllocatorCall> Call = 00354 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 00355 00356 ExplodedNodeSet DstPreCall; 00357 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 00358 *Call, *this); 00359 00360 ExplodedNodeSet DstInvalidated; 00361 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 00362 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 00363 I != E; ++I) 00364 defaultEvalCall(Bldr, *I, *Call); 00365 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 00366 *Call, *this); 00367 } 00368 00369 00370 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 00371 ExplodedNodeSet &Dst) { 00372 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 00373 // Also, we need to decide how allocators actually work -- they're not 00374 // really part of the CXXNewExpr because they happen BEFORE the 00375 // CXXConstructExpr subexpression. See PR12014 for some discussion. 00376 00377 unsigned blockCount = currBldrCtx->blockCount(); 00378 const LocationContext *LCtx = Pred->getLocationContext(); 00379 DefinedOrUnknownSVal symVal = UnknownVal(); 00380 FunctionDecl *FD = CNE->getOperatorNew(); 00381 00382 bool IsStandardGlobalOpNewFunction = false; 00383 if (FD && !isa<CXXMethodDecl>(FD) && !FD->isVariadic()) { 00384 if (FD->getNumParams() == 2) { 00385 QualType T = FD->getParamDecl(1)->getType(); 00386 if (const IdentifierInfo *II = T.getBaseTypeIdentifier()) 00387 // NoThrow placement new behaves as a standard new. 00388 IsStandardGlobalOpNewFunction = II->getName().equals("nothrow_t"); 00389 } 00390 else 00391 // Placement forms are considered non-standard. 00392 IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1); 00393 } 00394 00395 // We assume all standard global 'operator new' functions allocate memory in 00396 // heap. We realize this is an approximation that might not correctly model 00397 // a custom global allocator. 00398 if (IsStandardGlobalOpNewFunction) 00399 symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount); 00400 else 00401 symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(), 00402 blockCount); 00403 00404 ProgramStateRef State = Pred->getState(); 00405 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 00406 CallEventRef<CXXAllocatorCall> Call = 00407 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 00408 00409 // Invalidate placement args. 00410 // FIXME: Once we figure out how we want allocators to work, 00411 // we should be using the usual pre-/(default-)eval-/post-call checks here. 00412 State = Call->invalidateRegions(blockCount); 00413 if (!State) 00414 return; 00415 00416 // If this allocation function is not declared as non-throwing, failures 00417 // /must/ be signalled by exceptions, and thus the return value will never be 00418 // NULL. -fno-exceptions does not influence this semantics. 00419 // FIXME: GCC has a -fcheck-new option, which forces it to consider the case 00420 // where new can return NULL. If we end up supporting that option, we can 00421 // consider adding a check for it here. 00422 // C++11 [basic.stc.dynamic.allocation]p3. 00423 if (FD) { 00424 QualType Ty = FD->getType(); 00425 if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>()) 00426 if (!ProtoType->isNothrow(getContext())) 00427 State = State->assume(symVal, true); 00428 } 00429 00430 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 00431 00432 if (CNE->isArray()) { 00433 // FIXME: allocating an array requires simulating the constructors. 00434 // For now, just return a symbolicated region. 00435 const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion(); 00436 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 00437 const ElementRegion *EleReg = 00438 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 00439 State = State->BindExpr(CNE, Pred->getLocationContext(), 00440 loc::MemRegionVal(EleReg)); 00441 Bldr.generateNode(CNE, Pred, State); 00442 return; 00443 } 00444 00445 // FIXME: Once we have proper support for CXXConstructExprs inside 00446 // CXXNewExpr, we need to make sure that the constructed object is not 00447 // immediately invalidated here. (The placement call should happen before 00448 // the constructor call anyway.) 00449 SVal Result = symVal; 00450 if (FD && FD->isReservedGlobalPlacementOperator()) { 00451 // Non-array placement new should always return the placement location. 00452 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 00453 Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), 00454 CNE->getPlacementArg(0)->getType()); 00455 } 00456 00457 // Bind the address of the object, then check to see if we cached out. 00458 State = State->BindExpr(CNE, LCtx, Result); 00459 ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State); 00460 if (!NewN) 00461 return; 00462 00463 // If the type is not a record, we won't have a CXXConstructExpr as an 00464 // initializer. Copy the value over. 00465 if (const Expr *Init = CNE->getInitializer()) { 00466 if (!isa<CXXConstructExpr>(Init)) { 00467 assert(Bldr.getResults().size() == 1); 00468 Bldr.takeNodes(NewN); 00469 evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx), 00470 /*FirstInit=*/IsStandardGlobalOpNewFunction); 00471 } 00472 } 00473 } 00474 00475 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 00476 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 00477 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 00478 ProgramStateRef state = Pred->getState(); 00479 Bldr.generateNode(CDE, Pred, state); 00480 } 00481 00482 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 00483 ExplodedNode *Pred, 00484 ExplodedNodeSet &Dst) { 00485 const VarDecl *VD = CS->getExceptionDecl(); 00486 if (!VD) { 00487 Dst.Add(Pred); 00488 return; 00489 } 00490 00491 const LocationContext *LCtx = Pred->getLocationContext(); 00492 SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), 00493 currBldrCtx->blockCount()); 00494 ProgramStateRef state = Pred->getState(); 00495 state = state->bindLoc(state->getLValue(VD, LCtx), V); 00496 00497 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 00498 Bldr.generateNode(CS, Pred, state); 00499 } 00500 00501 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 00502 ExplodedNodeSet &Dst) { 00503 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 00504 00505 // Get the this object region from StoreManager. 00506 const LocationContext *LCtx = Pred->getLocationContext(); 00507 const MemRegion *R = 00508 svalBuilder.getRegionManager().getCXXThisRegion( 00509 getContext().getCanonicalType(TE->getType()), 00510 LCtx); 00511 00512 ProgramStateRef state = Pred->getState(); 00513 SVal V = state->getSVal(loc::MemRegionVal(R)); 00514 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 00515 }