ExprEngineCXX.cpp revision 5f688f4b15d02aa7ad159c46b1f78fe59d412f12
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 20using namespace clang; 21using namespace ento; 22 23namespace { 24class CallExprWLItem { 25public: 26 CallExpr::const_arg_iterator I; 27 ExplodedNode *N; 28 29 CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n) 30 : I(i), N(n) {} 31}; 32} 33 34void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE, 35 const FunctionProtoType *FnType, 36 ExplodedNode *Pred, ExplodedNodeSet &Dst, 37 bool FstArgAsLValue) { 38 39 40 SmallVector<CallExprWLItem, 20> WorkList; 41 WorkList.reserve(AE - AI); 42 WorkList.push_back(CallExprWLItem(AI, Pred)); 43 44 while (!WorkList.empty()) { 45 CallExprWLItem Item = WorkList.back(); 46 WorkList.pop_back(); 47 48 if (Item.I == AE) { 49 Dst.insert(Item.N); 50 continue; 51 } 52 53 // Evaluate the argument. 54 ExplodedNodeSet Tmp; 55 if (FstArgAsLValue) { 56 FstArgAsLValue = false; 57 } 58 59 Visit(*Item.I, Item.N, Tmp); 60 ++(Item.I); 61 for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI) 62 WorkList.push_back(CallExprWLItem(Item.I, *NI)); 63 } 64} 65 66void ExprEngine::evalCallee(const CallExpr *callExpr, 67 const ExplodedNodeSet &src, 68 ExplodedNodeSet &dest) { 69 70 const Expr *callee = 0; 71 72 switch (callExpr->getStmtClass()) { 73 case Stmt::CXXMemberCallExprClass: { 74 // Evaluate the implicit object argument that is the recipient of the 75 // call. 76 callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument(); 77 78 // FIXME: handle member pointers. 79 if (!callee) 80 return; 81 82 break; 83 } 84 default: { 85 callee = callExpr->getCallee()->IgnoreParens(); 86 break; 87 } 88 } 89 90 for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i) 91 Visit(callee, *i, dest); 92} 93 94const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 95 const StackFrameContext *SFC) { 96 const Type *T = D->getTypeForDecl(); 97 QualType PT = getContext().getPointerType(QualType(T, 0)); 98 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 99} 100 101const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 102 const StackFrameContext *frameCtx) { 103 return svalBuilder.getRegionManager(). 104 getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 105} 106 107void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 108 ExplodedNode *Pred, 109 ExplodedNodeSet &Dst) { 110 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 111 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 112 ProgramStateRef state = Pred->getState(); 113 const LocationContext *LCtx = Pred->getLocationContext(); 114 115 // Bind the temporary object to the value of the expression. Then bind 116 // the expression to the location of the object. 117 SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 118 119 const MemRegion *R = 120 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 121 122 state = state->bindLoc(loc::MemRegionVal(R), V); 123 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 124} 125 126void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 127 ExplodedNode *Pred, 128 ExplodedNodeSet &Dst) { 129 VisitCXXConstructExpr(expr, 0, Pred, Dst); 130} 131 132void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 133 const MemRegion *Dest, 134 ExplodedNode *Pred, 135 ExplodedNodeSet &destNodes) { 136 137 const CXXConstructorDecl *CD = E->getConstructor(); 138 assert(CD); 139 140#if 0 141 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 142 // FIXME: invalidate the object. 143 return; 144#endif 145 146 // Evaluate other arguments. 147 ExplodedNodeSet argsEvaluated; 148 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>(); 149 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated); 150 151#if 0 152 // Is the constructor elidable? 153 if (E->isElidable()) { 154 VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 155 // FIXME: this is here to force propagation if VisitAggExpr doesn't 156 if (destNodes.empty()) 157 destNodes.Add(Pred); 158 return; 159 } 160#endif 161 162 // Perform the previsit of the constructor. 163 ExplodedNodeSet destPreVisit; 164 getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 165 *this); 166 167 // Evaluate the constructor. Currently we don't now allow checker-specific 168 // implementations of specific constructors (as we do with ordinary 169 // function calls. We can re-evaluate this in the future. 170 171#if 0 172 // Inlining currently isn't fully implemented. 173 174 if (AMgr.shouldInlineCall()) { 175 if (!Dest) 176 Dest = 177 svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 178 Pred->getLocationContext()); 179 180 // The callee stack frame context used to create the 'this' 181 // parameter region. 182 const StackFrameContext *SFC = 183 AMgr.getStackFrame(CD, Pred->getLocationContext(), 184 E, currentBuilderContext->getBlock(), 185 currentStmtIdx); 186 187 // Create the 'this' region. 188 const CXXThisRegion *ThisR = 189 getCXXThisRegion(E->getConstructor()->getParent(), SFC); 190 191 CallEnter Loc(E, SFC, Pred->getLocationContext()); 192 193 StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext); 194 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), 195 NE = argsEvaluated.end(); NI != NE; ++NI) { 196 ProgramStateRef state = (*NI)->getState(); 197 // Setup 'this' region, so that the ctor is evaluated on the object pointed 198 // by 'Dest'. 199 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 200 Bldr.generateNode(Loc, *NI, state); 201 } 202 } 203#endif 204 205 // Default semantics: invalidate all regions passed as arguments. 206 ExplodedNodeSet destCall; 207 { 208 StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext); 209 for (ExplodedNodeSet::iterator 210 i = destPreVisit.begin(), e = destPreVisit.end(); 211 i != e; ++i) 212 { 213 ExplodedNode *Pred = *i; 214 const LocationContext *LC = Pred->getLocationContext(); 215 ProgramStateRef state = Pred->getState(); 216 217 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 218 Bldr.generateNode(E, Pred, state); 219 } 220 } 221 // Do the post visit. 222 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 223} 224 225void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 226 const MemRegion *Dest, 227 const Stmt *S, 228 ExplodedNode *Pred, 229 ExplodedNodeSet &Dst) { 230 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 231 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 232 return; 233 234 // Create the context for 'this' region. 235 const StackFrameContext *SFC = 236 AnalysisDeclContexts.getContext(DD)-> 237 getStackFrame(Pred->getLocationContext(), S, 238 currentBuilderContext->getBlock(), currentStmtIdx); 239 240 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 241 242 CallEnter PP(S, SFC, Pred->getLocationContext()); 243 244 ProgramStateRef state = Pred->getState(); 245 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 246 Bldr.generateNode(PP, Pred, state); 247} 248 249void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 250 ExplodedNodeSet &Dst) { 251 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 252 253 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 254 DefinedOrUnknownSVal symVal = 255 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount); 256 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 257 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 258 const ElementRegion *EleReg = 259 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 260 261 if (CNE->isArray()) { 262 // FIXME: allocating an array requires simulating the constructors. 263 // For now, just return a symbolicated region. 264 ProgramStateRef state = Pred->getState(); 265 state = state->BindExpr(CNE, Pred->getLocationContext(), 266 loc::MemRegionVal(EleReg)); 267 Bldr.generateNode(CNE, Pred, state); 268 return; 269 } 270 271 // FIXME: Update for AST changes. 272#if 0 273 // Evaluate constructor arguments. 274 const FunctionProtoType *FnType = NULL; 275 const CXXConstructorDecl *CD = CNE->getConstructor(); 276 if (CD) 277 FnType = CD->getType()->getAs<FunctionProtoType>(); 278 ExplodedNodeSet argsEvaluated; 279 Bldr.takeNodes(Pred); 280 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 281 FnType, Pred, argsEvaluated); 282 Bldr.addNodes(argsEvaluated); 283 284 // Initialize the object region and bind the 'new' expression. 285 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 286 E = argsEvaluated.end(); I != E; ++I) { 287 288 ProgramStateRef state = (*I)->getState(); 289 290 // Accumulate list of regions that are invalidated. 291 // FIXME: Eventually we should unify the logic for constructor 292 // processing in one place. 293 SmallVector<const MemRegion*, 10> regionsToInvalidate; 294 for (CXXNewExpr::const_arg_iterator 295 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 296 ai != ae; ++ai) 297 { 298 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 299 if (const MemRegion *region = val.getAsRegion()) 300 regionsToInvalidate.push_back(region); 301 } 302 303 if (ObjTy->isRecordType()) { 304 regionsToInvalidate.push_back(EleReg); 305 // Invalidate the regions. 306 // TODO: Pass the call to new information as the last argument, to limit 307 // the globals which will get invalidated. 308 state = state->invalidateRegions(regionsToInvalidate, 309 CNE, blockCount, 0, 0); 310 311 } else { 312 // Invalidate the regions. 313 // TODO: Pass the call to new information as the last argument, to limit 314 // the globals which will get invalidated. 315 state = state->invalidateRegions(regionsToInvalidate, 316 CNE, blockCount, 0, 0); 317 318 if (CNE->hasInitializer()) { 319 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 320 (*I)->getLocationContext()); 321 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 322 } else { 323 // Explicitly set to undefined, because currently we retrieve symbolic 324 // value from symbolic region. 325 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 326 } 327 } 328 state = state->BindExpr(CNE, (*I)->getLocationContext(), 329 loc::MemRegionVal(EleReg)); 330 Bldr.generateNode(CNE, *I, state); 331 } 332#endif 333} 334 335void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 336 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 337 // Should do more checking. 338 ExplodedNodeSet Argevaluated; 339 Visit(CDE->getArgument(), Pred, Argevaluated); 340 StmtNodeBuilder Bldr(Argevaluated, Dst, *currentBuilderContext); 341 for (ExplodedNodeSet::iterator I = Argevaluated.begin(), 342 E = Argevaluated.end(); I != E; ++I) { 343 ProgramStateRef state = (*I)->getState(); 344 Bldr.generateNode(CDE, *I, state); 345 } 346} 347 348void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 349 ExplodedNodeSet &Dst) { 350 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 351 352 // Get the this object region from StoreManager. 353 const LocationContext *LCtx = Pred->getLocationContext(); 354 const MemRegion *R = 355 svalBuilder.getRegionManager().getCXXThisRegion( 356 getContext().getCanonicalType(TE->getType()), 357 LCtx); 358 359 ProgramStateRef state = Pred->getState(); 360 SVal V = state->getSVal(loc::MemRegionVal(R)); 361 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 362} 363