ExprEngineCXX.cpp revision 8f6134c308951a72642eebb65a44408ea1e237a8
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 // This is an optimization for when an rvalue is constructed and then 38 // immediately materialized. 39 const MemRegion *MR = V.getAsRegion(); 40 if (const CXXTempObjectRegion *TR = 41 dyn_cast_or_null<CXXTempObjectRegion>(MR)) { 42 if (getContext().hasSameUnqualifiedType(TR->getValueType(), ME->getType())) 43 state = state->BindExpr(ME, LCtx, V); 44 } 45 46 if (state == Pred->getState()) 47 state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); 48 Bldr.generateNode(ME, Pred, state); 49} 50 51// FIXME: This is the sort of code that should eventually live in a Core 52// checker rather than as a special case in ExprEngine. 53void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, 54 const CallEvent &Call) { 55 SVal ThisVal; 56 bool AlwaysReturnsLValue; 57 if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 58 assert(Ctor->getDecl()->isTrivial()); 59 assert(Ctor->getDecl()->isCopyOrMoveConstructor()); 60 ThisVal = Ctor->getCXXThisVal(); 61 AlwaysReturnsLValue = false; 62 } else { 63 assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); 64 assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == 65 OO_Equal); 66 ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); 67 AlwaysReturnsLValue = true; 68 } 69 70 const LocationContext *LCtx = Pred->getLocationContext(); 71 72 ExplodedNodeSet Dst; 73 Bldr.takeNodes(Pred); 74 75 SVal V = Call.getArgSVal(0); 76 77 // If the value being copied is not unknown, load from its location to get 78 // an aggregate rvalue. 79 if (Optional<Loc> L = V.getAs<Loc>()) 80 V = Pred->getState()->getSVal(*L); 81 else 82 assert(V.isUnknown()); 83 84 const Expr *CallExpr = Call.getOriginExpr(); 85 evalBind(Dst, CallExpr, Pred, ThisVal, V, true); 86 87 PostStmt PS(CallExpr, LCtx); 88 for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); 89 I != E; ++I) { 90 ProgramStateRef State = (*I)->getState(); 91 if (AlwaysReturnsLValue) 92 State = State->BindExpr(CallExpr, LCtx, ThisVal); 93 else 94 State = bindReturnValue(Call, LCtx, State); 95 Bldr.generateNode(PS, State, *I); 96 } 97} 98 99 100/// Returns a region representing the first element of a (possibly 101/// multi-dimensional) array. 102/// 103/// On return, \p Ty will be set to the base type of the array. 104/// 105/// If the type is not an array type at all, the original value is returned. 106static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue, 107 QualType &Ty) { 108 SValBuilder &SVB = State->getStateManager().getSValBuilder(); 109 ASTContext &Ctx = SVB.getContext(); 110 111 while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) { 112 Ty = AT->getElementType(); 113 LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue); 114 } 115 116 return LValue; 117} 118 119void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, 120 ExplodedNode *Pred, 121 ExplodedNodeSet &destNodes) { 122 const LocationContext *LCtx = Pred->getLocationContext(); 123 ProgramStateRef State = Pred->getState(); 124 125 const MemRegion *Target = 0; 126 127 // FIXME: Handle arrays, which run the same constructor for every element. 128 // For now, we just run the first constructor (which should still invalidate 129 // the entire array). 130 131 switch (CE->getConstructionKind()) { 132 case CXXConstructExpr::CK_Complete: { 133 // See if we're constructing an existing region by looking at the next 134 // element in the CFG. 135 const CFGBlock *B = currBldrCtx->getBlock(); 136 if (currStmtIdx + 1 < B->size()) { 137 CFGElement Next = (*B)[currStmtIdx+1]; 138 139 // Is this a constructor for a local variable? 140 if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) { 141 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) { 142 if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { 143 if (Var->getInit()->IgnoreImplicit() == CE) { 144 SVal LValue = State->getLValue(Var, LCtx); 145 QualType Ty = Var->getType(); 146 LValue = makeZeroElementRegion(State, LValue, Ty); 147 Target = LValue.getAsRegion(); 148 } 149 } 150 } 151 } 152 153 // Is this a constructor for a member? 154 if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) { 155 const CXXCtorInitializer *Init = InitElem->getInitializer(); 156 assert(Init->isAnyMemberInitializer()); 157 158 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 159 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 160 LCtx->getCurrentStackFrame()); 161 SVal ThisVal = State->getSVal(ThisPtr); 162 163 const ValueDecl *Field; 164 SVal FieldVal; 165 if (Init->isIndirectMemberInitializer()) { 166 Field = Init->getIndirectMember(); 167 FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); 168 } else { 169 Field = Init->getMember(); 170 FieldVal = State->getLValue(Init->getMember(), ThisVal); 171 } 172 173 QualType Ty = Field->getType(); 174 FieldVal = makeZeroElementRegion(State, FieldVal, Ty); 175 Target = FieldVal.getAsRegion(); 176 } 177 178 // FIXME: This will eventually need to handle new-expressions as well. 179 // Don't forget to update the pre-constructor initialization code below. 180 } 181 182 // If we couldn't find an existing region to construct into, assume we're 183 // constructing a temporary. 184 if (!Target) { 185 MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); 186 Target = MRMgr.getCXXTempObjectRegion(CE, LCtx); 187 } 188 189 break; 190 } 191 case CXXConstructExpr::CK_VirtualBase: 192 // Make sure we are not calling virtual base class initializers twice. 193 // Only the most-derived object should initialize virtual base classes. 194 if (const Stmt *Outer = LCtx->getCurrentStackFrame()->getCallSite()) { 195 const CXXConstructExpr *OuterCtor = dyn_cast<CXXConstructExpr>(Outer); 196 if (OuterCtor) { 197 switch (OuterCtor->getConstructionKind()) { 198 case CXXConstructExpr::CK_NonVirtualBase: 199 case CXXConstructExpr::CK_VirtualBase: 200 // Bail out! 201 destNodes.Add(Pred); 202 return; 203 case CXXConstructExpr::CK_Complete: 204 case CXXConstructExpr::CK_Delegating: 205 break; 206 } 207 } 208 } 209 // FALLTHROUGH 210 case CXXConstructExpr::CK_NonVirtualBase: 211 case CXXConstructExpr::CK_Delegating: { 212 const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); 213 Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, 214 LCtx->getCurrentStackFrame()); 215 SVal ThisVal = State->getSVal(ThisPtr); 216 217 if (CE->getConstructionKind() == CXXConstructExpr::CK_Delegating) { 218 Target = ThisVal.getAsRegion(); 219 } else { 220 // Cast to the base type. 221 bool IsVirtual = 222 (CE->getConstructionKind() == CXXConstructExpr::CK_VirtualBase); 223 SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, CE->getType(), 224 IsVirtual); 225 Target = BaseVal.getAsRegion(); 226 } 227 break; 228 } 229 } 230 231 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 232 CallEventRef<CXXConstructorCall> Call = 233 CEMgr.getCXXConstructorCall(CE, Target, State, LCtx); 234 235 ExplodedNodeSet DstPreVisit; 236 getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this); 237 238 ExplodedNodeSet PreInitialized; 239 { 240 StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx); 241 if (CE->requiresZeroInitialization()) { 242 // Type of the zero doesn't matter. 243 SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy); 244 245 for (ExplodedNodeSet::iterator I = DstPreVisit.begin(), 246 E = DstPreVisit.end(); 247 I != E; ++I) { 248 ProgramStateRef State = (*I)->getState(); 249 // FIXME: Once we properly handle constructors in new-expressions, we'll 250 // need to invalidate the region before setting a default value, to make 251 // sure there aren't any lingering bindings around. This probably needs 252 // to happen regardless of whether or not the object is zero-initialized 253 // to handle random fields of a placement-initialized object picking up 254 // old bindings. We might only want to do it when we need to, though. 255 // FIXME: This isn't actually correct for arrays -- we need to zero- 256 // initialize the entire array, not just the first element -- but our 257 // handling of arrays everywhere else is weak as well, so this shouldn't 258 // actually make things worse. Placement new makes this tricky as well, 259 // since it's then possible to be initializing one part of a multi- 260 // dimensional array. 261 State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal); 262 Bldr.generateNode(CE, *I, State, /*tag=*/0, ProgramPoint::PreStmtKind); 263 } 264 } 265 } 266 267 ExplodedNodeSet DstPreCall; 268 getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized, 269 *Call, *this); 270 271 ExplodedNodeSet DstEvaluated; 272 StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); 273 274 bool IsArray = isa<ElementRegion>(Target); 275 if (CE->getConstructor()->isTrivial() && 276 CE->getConstructor()->isCopyOrMoveConstructor() && 277 !IsArray) { 278 // FIXME: Handle other kinds of trivial constructors as well. 279 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 280 I != E; ++I) 281 performTrivialCopy(Bldr, *I, *Call); 282 283 } else { 284 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 285 I != E; ++I) 286 defaultEvalCall(Bldr, *I, *Call); 287 } 288 289 ExplodedNodeSet DstPostCall; 290 getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated, 291 *Call, *this); 292 getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); 293} 294 295void ExprEngine::VisitCXXDestructor(QualType ObjectType, 296 const MemRegion *Dest, 297 const Stmt *S, 298 bool IsBaseDtor, 299 ExplodedNode *Pred, 300 ExplodedNodeSet &Dst) { 301 const LocationContext *LCtx = Pred->getLocationContext(); 302 ProgramStateRef State = Pred->getState(); 303 304 // FIXME: We need to run the same destructor on every element of the array. 305 // This workaround will just run the first destructor (which will still 306 // invalidate the entire array). 307 SVal DestVal = loc::MemRegionVal(Dest); 308 DestVal = makeZeroElementRegion(State, DestVal, ObjectType); 309 Dest = DestVal.getAsRegion(); 310 311 const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl(); 312 assert(RecordDecl && "Only CXXRecordDecls should have destructors"); 313 const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor(); 314 315 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 316 CallEventRef<CXXDestructorCall> Call = 317 CEMgr.getCXXDestructorCall(DtorDecl, S, Dest, IsBaseDtor, State, LCtx); 318 319 PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), 320 Call->getSourceRange().getBegin(), 321 "Error evaluating destructor"); 322 323 ExplodedNodeSet DstPreCall; 324 getCheckerManager().runCheckersForPreCall(DstPreCall, Pred, 325 *Call, *this); 326 327 ExplodedNodeSet DstInvalidated; 328 StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); 329 for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); 330 I != E; ++I) 331 defaultEvalCall(Bldr, *I, *Call); 332 333 ExplodedNodeSet DstPostCall; 334 getCheckerManager().runCheckersForPostCall(Dst, DstInvalidated, 335 *Call, *this); 336} 337 338void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 339 ExplodedNodeSet &Dst) { 340 // FIXME: Much of this should eventually migrate to CXXAllocatorCall. 341 // Also, we need to decide how allocators actually work -- they're not 342 // really part of the CXXNewExpr because they happen BEFORE the 343 // CXXConstructExpr subexpression. See PR12014 for some discussion. 344 345 unsigned blockCount = currBldrCtx->blockCount(); 346 const LocationContext *LCtx = Pred->getLocationContext(); 347 DefinedOrUnknownSVal symVal = UnknownVal(); 348 FunctionDecl *FD = CNE->getOperatorNew(); 349 350 bool IsStandardGlobalOpNewFunction = false; 351 if (FD && !isa<CXXMethodDecl>(FD) && !FD->isVariadic()) { 352 if (FD->getNumParams() == 2) { 353 QualType T = FD->getParamDecl(1)->getType(); 354 if (const IdentifierInfo *II = T.getBaseTypeIdentifier()) 355 // NoThrow placement new behaves as a standard new. 356 IsStandardGlobalOpNewFunction = II->getName().equals("nothrow_t"); 357 } 358 else 359 // Placement forms are considered non-standard. 360 IsStandardGlobalOpNewFunction = (FD->getNumParams() == 1); 361 } 362 363 // We assume all standard global 'operator new' functions allocate memory in 364 // heap. We realize this is an approximation that might not correctly model 365 // a custom global allocator. 366 if (IsStandardGlobalOpNewFunction) 367 symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount); 368 else 369 symVal = svalBuilder.conjureSymbolVal(0, CNE, LCtx, CNE->getType(), 370 blockCount); 371 372 ProgramStateRef State = Pred->getState(); 373 CallEventManager &CEMgr = getStateManager().getCallEventManager(); 374 CallEventRef<CXXAllocatorCall> Call = 375 CEMgr.getCXXAllocatorCall(CNE, State, LCtx); 376 377 // Invalidate placement args. 378 // FIXME: Once we figure out how we want allocators to work, 379 // we should be using the usual pre-/(default-)eval-/post-call checks here. 380 State = Call->invalidateRegions(blockCount); 381 if (!State) 382 return; 383 384 // If we're compiling with exceptions enabled, and this allocation function 385 // is not declared as non-throwing, failures /must/ be signalled by 386 // exceptions, and thus the return value will never be NULL. 387 // C++11 [basic.stc.dynamic.allocation]p3. 388 if (FD && getContext().getLangOpts().CXXExceptions) { 389 QualType Ty = FD->getType(); 390 if (const FunctionProtoType *ProtoType = Ty->getAs<FunctionProtoType>()) 391 if (!ProtoType->isNothrow(getContext())) 392 State = State->assume(symVal, true); 393 } 394 395 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 396 397 if (CNE->isArray()) { 398 // FIXME: allocating an array requires simulating the constructors. 399 // For now, just return a symbolicated region. 400 const MemRegion *NewReg = symVal.castAs<loc::MemRegionVal>().getRegion(); 401 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 402 const ElementRegion *EleReg = 403 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 404 State = State->BindExpr(CNE, Pred->getLocationContext(), 405 loc::MemRegionVal(EleReg)); 406 Bldr.generateNode(CNE, Pred, State); 407 return; 408 } 409 410 // FIXME: Once we have proper support for CXXConstructExprs inside 411 // CXXNewExpr, we need to make sure that the constructed object is not 412 // immediately invalidated here. (The placement call should happen before 413 // the constructor call anyway.) 414 SVal Result = symVal; 415 if (FD && FD->isReservedGlobalPlacementOperator()) { 416 // Non-array placement new should always return the placement location. 417 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 418 Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), 419 CNE->getPlacementArg(0)->getType()); 420 } 421 422 // Bind the address of the object, then check to see if we cached out. 423 State = State->BindExpr(CNE, LCtx, Result); 424 ExplodedNode *NewN = Bldr.generateNode(CNE, Pred, State); 425 if (!NewN) 426 return; 427 428 // If the type is not a record, we won't have a CXXConstructExpr as an 429 // initializer. Copy the value over. 430 if (const Expr *Init = CNE->getInitializer()) { 431 if (!isa<CXXConstructExpr>(Init)) { 432 assert(Bldr.getResults().size() == 1); 433 Bldr.takeNodes(NewN); 434 evalBind(Dst, CNE, NewN, Result, State->getSVal(Init, LCtx), 435 /*FirstInit=*/IsStandardGlobalOpNewFunction); 436 } 437 } 438} 439 440void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 441 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 442 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 443 ProgramStateRef state = Pred->getState(); 444 Bldr.generateNode(CDE, Pred, state); 445} 446 447void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 448 ExplodedNode *Pred, 449 ExplodedNodeSet &Dst) { 450 const VarDecl *VD = CS->getExceptionDecl(); 451 if (!VD) { 452 Dst.Add(Pred); 453 return; 454 } 455 456 const LocationContext *LCtx = Pred->getLocationContext(); 457 SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), 458 currBldrCtx->blockCount()); 459 ProgramStateRef state = Pred->getState(); 460 state = state->bindLoc(state->getLValue(VD, LCtx), V); 461 462 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 463 Bldr.generateNode(CS, Pred, state); 464} 465 466void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 467 ExplodedNodeSet &Dst) { 468 StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); 469 470 // Get the this object region from StoreManager. 471 const LocationContext *LCtx = Pred->getLocationContext(); 472 const MemRegion *R = 473 svalBuilder.getRegionManager().getCXXThisRegion( 474 getContext().getCanonicalType(TE->getType()), 475 LCtx); 476 477 ProgramStateRef state = Pred->getState(); 478 SVal V = state->getSVal(loc::MemRegionVal(R)); 479 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 480} 481