ExprEngineCXX.cpp revision e38c1c2c449529e60f48e740cb8662e68e5a5330
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/ObjCMessage.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/StmtCXX.h" 20 21using namespace clang; 22using namespace ento; 23 24const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 25 const StackFrameContext *SFC) { 26 const Type *T = D->getTypeForDecl(); 27 QualType PT = getContext().getPointerType(QualType(T, 0)); 28 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 29} 30 31const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 32 const StackFrameContext *frameCtx) { 33 return svalBuilder.getRegionManager(). 34 getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 35} 36 37void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 38 ExplodedNode *Pred, 39 ExplodedNodeSet &Dst) { 40 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 41 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 42 ProgramStateRef state = Pred->getState(); 43 const LocationContext *LCtx = Pred->getLocationContext(); 44 45 // Bind the temporary object to the value of the expression. Then bind 46 // the expression to the location of the object. 47 SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 48 49 const MemRegion *R = 50 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 51 52 state = state->bindLoc(loc::MemRegionVal(R), V); 53 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 54} 55 56void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 57 ExplodedNode *Pred, 58 ExplodedNodeSet &Dst) { 59 VisitCXXConstructExpr(expr, 0, Pred, Dst); 60} 61 62void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 63 const MemRegion *Dest, 64 ExplodedNode *Pred, 65 ExplodedNodeSet &destNodes) { 66 67#if 0 68 const CXXConstructorDecl *CD = E->getConstructor(); 69 assert(CD); 70#endif 71 72#if 0 73 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 74 // FIXME: invalidate the object. 75 return; 76#endif 77 78#if 0 79 // Is the constructor elidable? 80 if (E->isElidable()) { 81 destNodes.Add(Pred); 82 return; 83 } 84#endif 85 86 // Perform the previsit of the constructor. 87 ExplodedNodeSet SrcNodes; 88 SrcNodes.Add(Pred); 89 ExplodedNodeSet TmpNodes; 90 getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this); 91 92 // Evaluate the constructor. Currently we don't now allow checker-specific 93 // implementations of specific constructors (as we do with ordinary 94 // function calls. We can re-evaluate this in the future. 95 96#if 0 97 // Inlining currently isn't fully implemented. 98 99 if (AMgr.shouldInlineCall()) { 100 if (!Dest) 101 Dest = 102 svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 103 Pred->getLocationContext()); 104 105 // The callee stack frame context used to create the 'this' 106 // parameter region. 107 const StackFrameContext *SFC = 108 AMgr.getStackFrame(CD, Pred->getLocationContext(), 109 E, currentBuilderContext->getBlock(), 110 currentStmtIdx); 111 112 // Create the 'this' region. 113 const CXXThisRegion *ThisR = 114 getCXXThisRegion(E->getConstructor()->getParent(), SFC); 115 116 CallEnter Loc(E, SFC, Pred->getLocationContext()); 117 118 StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext); 119 for (ExplodedNodeSet::iterator NI = SrcNodes.begin(), 120 NE = SrcNodes.end(); NI != NE; ++NI) { 121 ProgramStateRef state = (*NI)->getState(); 122 // Setup 'this' region, so that the ctor is evaluated on the object pointed 123 // by 'Dest'. 124 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 125 Bldr.generateNode(Loc, *NI, state); 126 } 127 } 128#endif 129 130 // Default semantics: invalidate all regions passed as arguments. 131 ExplodedNodeSet destCall; 132 { 133 StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext); 134 for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end(); 135 i != e; ++i) 136 { 137 ExplodedNode *Pred = *i; 138 const LocationContext *LC = Pred->getLocationContext(); 139 ProgramStateRef state = Pred->getState(); 140 141 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 142 Bldr.generateNode(E, Pred, state); 143 } 144 } 145 // Do the post visit. 146 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 147} 148 149void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 150 const MemRegion *Dest, 151 const Stmt *S, 152 ExplodedNode *Pred, 153 ExplodedNodeSet &Dst) { 154 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 155 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 156 return; 157 158 // Create the context for 'this' region. 159 const StackFrameContext *SFC = 160 AnalysisDeclContexts.getContext(DD)-> 161 getStackFrame(Pred->getLocationContext(), S, 162 currentBuilderContext->getBlock(), currentStmtIdx); 163 164 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 165 166 CallEnter PP(S, SFC, Pred->getLocationContext()); 167 168 ProgramStateRef state = Pred->getState(); 169 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 170 Bldr.generateNode(PP, Pred, state); 171} 172 173static bool isPointerToConst(const ParmVarDecl *ParamDecl) { 174 // FIXME: Copied from ExprEngineCallAndReturn.cpp 175 QualType PointeeTy = ParamDecl->getOriginalType()->getPointeeType(); 176 if (PointeeTy != QualType() && PointeeTy.isConstQualified() && 177 !PointeeTy->isAnyPointerType() && !PointeeTy->isReferenceType()) { 178 return true; 179 } 180 return false; 181} 182 183void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 184 ExplodedNodeSet &Dst) { 185 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 186 187 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 188 const LocationContext *LCtx = Pred->getLocationContext(); 189 DefinedOrUnknownSVal symVal = 190 svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 191 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 192 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 193 const ElementRegion *EleReg = 194 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 195 ProgramStateRef State = Pred->getState(); 196 197 if (CNE->isArray()) { 198 // FIXME: allocating an array requires simulating the constructors. 199 // For now, just return a symbolicated region. 200 State = State->BindExpr(CNE, Pred->getLocationContext(), 201 loc::MemRegionVal(EleReg)); 202 Bldr.generateNode(CNE, Pred, State); 203 return; 204 } 205 206 FunctionDecl *FD = CNE->getOperatorNew(); 207 if (FD && FD->isReservedGlobalPlacementOperator()) { 208 // Non-array placement new should always return the placement location. 209 SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); 210 State = State->BindExpr(CNE, LCtx, PlacementLoc); 211 // FIXME: Once we have proper support for CXXConstructExprs inside 212 // CXXNewExpr, we need to make sure that the constructed object is not 213 // immediately invalidated here. (The placement call should happen before 214 // the constructor call anyway.) 215 } 216 217 // Invalidate placement args. 218 219 // FIXME: This is largely copied from invalidateArguments, because 220 // CallOrObjCMessage is not general enough to handle new-expressions yet. 221 SmallVector<const MemRegion *, 4> RegionsToInvalidate; 222 223 unsigned Index = 0; 224 for (CXXNewExpr::const_arg_iterator I = CNE->placement_arg_begin(), 225 E = CNE->placement_arg_end(); 226 I != E; ++I) { 227 // Pre-increment the argument index to skip over the implicit size arg. 228 ++Index; 229 if (FD && Index < FD->getNumParams()) 230 if (isPointerToConst(FD->getParamDecl(Index))) 231 continue; 232 233 SVal V = State->getSVal(*I, LCtx); 234 235 // If we are passing a location wrapped as an integer, unwrap it and 236 // invalidate the values referred by the location. 237 if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V)) 238 V = Wrapped->getLoc(); 239 else if (!isa<Loc>(V)) 240 continue; 241 242 if (const MemRegion *R = V.getAsRegion()) { 243 // Invalidate the value of the variable passed by reference. 244 245 // Are we dealing with an ElementRegion? If the element type is 246 // a basic integer type (e.g., char, int) and the underlying region 247 // is a variable region then strip off the ElementRegion. 248 // FIXME: We really need to think about this for the general case 249 // as sometimes we are reasoning about arrays and other times 250 // about (char*), etc., is just a form of passing raw bytes. 251 // e.g., void *p = alloca(); foo((char*)p); 252 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 253 // Checking for 'integral type' is probably too promiscuous, but 254 // we'll leave it in for now until we have a systematic way of 255 // handling all of these cases. Eventually we need to come up 256 // with an interface to StoreManager so that this logic can be 257 // appropriately delegated to the respective StoreManagers while 258 // still allowing us to do checker-specific logic (e.g., 259 // invalidating reference counts), probably via callbacks. 260 if (ER->getElementType()->isIntegralOrEnumerationType()) { 261 const MemRegion *superReg = ER->getSuperRegion(); 262 if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) || 263 isa<ObjCIvarRegion>(superReg)) 264 R = cast<TypedRegion>(superReg); 265 } 266 // FIXME: What about layers of ElementRegions? 267 } 268 269 // Mark this region for invalidation. We batch invalidate regions 270 // below for efficiency. 271 RegionsToInvalidate.push_back(R); 272 } else { 273 // Nuke all other arguments passed by reference. 274 // FIXME: is this necessary or correct? This handles the non-Region 275 // cases. Is it ever valid to store to these? 276 State = State->unbindLoc(cast<Loc>(V)); 277 } 278 } 279 280 // Invalidate designated regions using the batch invalidation API. 281 282 // FIXME: We can have collisions on the conjured symbol if the 283 // expression *I also creates conjured symbols. We probably want 284 // to identify conjured symbols by an expression pair: the enclosing 285 // expression (the context) and the expression itself. This should 286 // disambiguate conjured symbols. 287 unsigned Count = currentBuilderContext->getCurrentBlockCount(); 288 289 // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate 290 // global variables. 291 State = State->invalidateRegions(RegionsToInvalidate, CNE, Count, LCtx); 292 Bldr.generateNode(CNE, Pred, State); 293 return; 294 295 // FIXME: The below code is long-since dead. However, constructor handling 296 // in new-expressions is far from complete. See PR12014 for more details. 297#if 0 298 // Evaluate constructor arguments. 299 const FunctionProtoType *FnType = NULL; 300 const CXXConstructorDecl *CD = CNE->getConstructor(); 301 if (CD) 302 FnType = CD->getType()->getAs<FunctionProtoType>(); 303 ExplodedNodeSet argsEvaluated; 304 Bldr.takeNodes(Pred); 305 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 306 FnType, Pred, argsEvaluated); 307 Bldr.addNodes(argsEvaluated); 308 309 // Initialize the object region and bind the 'new' expression. 310 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 311 E = argsEvaluated.end(); I != E; ++I) { 312 313 ProgramStateRef state = (*I)->getState(); 314 315 // Accumulate list of regions that are invalidated. 316 // FIXME: Eventually we should unify the logic for constructor 317 // processing in one place. 318 SmallVector<const MemRegion*, 10> regionsToInvalidate; 319 for (CXXNewExpr::const_arg_iterator 320 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 321 ai != ae; ++ai) 322 { 323 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 324 if (const MemRegion *region = val.getAsRegion()) 325 regionsToInvalidate.push_back(region); 326 } 327 328 if (ObjTy->isRecordType()) { 329 regionsToInvalidate.push_back(EleReg); 330 // Invalidate the regions. 331 // TODO: Pass the call to new information as the last argument, to limit 332 // the globals which will get invalidated. 333 state = state->invalidateRegions(regionsToInvalidate, 334 CNE, blockCount, 0, 0); 335 336 } else { 337 // Invalidate the regions. 338 // TODO: Pass the call to new information as the last argument, to limit 339 // the globals which will get invalidated. 340 state = state->invalidateRegions(regionsToInvalidate, 341 CNE, blockCount, 0, 0); 342 343 if (CNE->hasInitializer()) { 344 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 345 (*I)->getLocationContext()); 346 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 347 } else { 348 // Explicitly set to undefined, because currently we retrieve symbolic 349 // value from symbolic region. 350 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 351 } 352 } 353 state = state->BindExpr(CNE, (*I)->getLocationContext(), 354 loc::MemRegionVal(EleReg)); 355 Bldr.generateNode(CNE, *I, state); 356 } 357#endif 358} 359 360void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 361 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 362 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 363 ProgramStateRef state = Pred->getState(); 364 Bldr.generateNode(CDE, Pred, state); 365} 366 367void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 368 ExplodedNode *Pred, 369 ExplodedNodeSet &Dst) { 370 const VarDecl *VD = CS->getExceptionDecl(); 371 if (!VD) { 372 Dst.Add(Pred); 373 return; 374 } 375 376 const LocationContext *LCtx = Pred->getLocationContext(); 377 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 378 currentBuilderContext->getCurrentBlockCount()); 379 ProgramStateRef state = Pred->getState(); 380 state = state->bindLoc(state->getLValue(VD, LCtx), V); 381 382 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 383 Bldr.generateNode(CS, Pred, state); 384} 385 386void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 387 ExplodedNodeSet &Dst) { 388 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 389 390 // Get the this object region from StoreManager. 391 const LocationContext *LCtx = Pred->getLocationContext(); 392 const MemRegion *R = 393 svalBuilder.getRegionManager().getCXXThisRegion( 394 getContext().getCanonicalType(TE->getType()), 395 LCtx); 396 397 ProgramStateRef state = Pred->getState(); 398 SVal V = state->getSVal(loc::MemRegionVal(R)); 399 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 400} 401