ExprEngineCXX.cpp revision 5eca482fe895ea57bc82410222e6426c09e63284
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 const ProgramState *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::VisitCXXConstructExpr(const CXXConstructExpr *E, 127 const MemRegion *Dest, 128 ExplodedNode *Pred, 129 ExplodedNodeSet &destNodes) { 130 131 const CXXConstructorDecl *CD = E->getConstructor(); 132 assert(CD); 133 134#if 0 135 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 136 // FIXME: invalidate the object. 137 return; 138#endif 139 140 // Evaluate other arguments. 141 ExplodedNodeSet argsEvaluated; 142 const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>(); 143 evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated); 144 145#if 0 146 // Is the constructor elidable? 147 if (E->isElidable()) { 148 VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 149 // FIXME: this is here to force propagation if VisitAggExpr doesn't 150 if (destNodes.empty()) 151 destNodes.Add(Pred); 152 return; 153 } 154#endif 155 156 // Perform the previsit of the constructor. 157 ExplodedNodeSet destPreVisit; 158 getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 159 *this); 160 161 // Evaluate the constructor. Currently we don't now allow checker-specific 162 // implementations of specific constructors (as we do with ordinary 163 // function calls. We can re-evaluate this in the future. 164 165#if 0 166 // Inlining currently isn't fully implemented. 167 168 if (AMgr.shouldInlineCall()) { 169 if (!Dest) 170 Dest = 171 svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 172 Pred->getLocationContext()); 173 174 // The callee stack frame context used to create the 'this' 175 // parameter region. 176 const StackFrameContext *SFC = 177 AMgr.getStackFrame(CD, Pred->getLocationContext(), 178 E, currentBuilderContext->getBlock(), 179 currentStmtIdx); 180 181 // Create the 'this' region. 182 const CXXThisRegion *ThisR = 183 getCXXThisRegion(E->getConstructor()->getParent(), SFC); 184 185 CallEnter Loc(E, SFC, Pred->getLocationContext()); 186 187 StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext); 188 for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(), 189 NE = argsEvaluated.end(); NI != NE; ++NI) { 190 const ProgramState *state = (*NI)->getState(); 191 // Setup 'this' region, so that the ctor is evaluated on the object pointed 192 // by 'Dest'. 193 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 194 Bldr.generateNode(Loc, *NI, state); 195 } 196 } 197#endif 198 199 // Default semantics: invalidate all regions passed as arguments. 200 ExplodedNodeSet destCall; 201 { 202 StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext); 203 for (ExplodedNodeSet::iterator 204 i = destPreVisit.begin(), e = destPreVisit.end(); 205 i != e; ++i) 206 { 207 ExplodedNode *Pred = *i; 208 const LocationContext *LC = Pred->getLocationContext(); 209 const ProgramState *state = Pred->getState(); 210 211 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 212 Bldr.generateNode(E, Pred, state); 213 } 214 } 215 // Do the post visit. 216 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 217} 218 219void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 220 const MemRegion *Dest, 221 const Stmt *S, 222 ExplodedNode *Pred, 223 ExplodedNodeSet &Dst) { 224 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 225 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 226 return; 227 228 // Create the context for 'this' region. 229 const StackFrameContext *SFC = 230 AnalysisDeclContexts.getContext(DD)-> 231 getStackFrame(Pred->getLocationContext(), S, 232 currentBuilderContext->getBlock(), currentStmtIdx); 233 234 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 235 236 CallEnter PP(S, SFC, Pred->getLocationContext()); 237 238 const ProgramState *state = Pred->getState(); 239 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 240 Bldr.generateNode(PP, Pred, state); 241} 242 243void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 244 ExplodedNodeSet &Dst) { 245 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 246 247 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 248 DefinedOrUnknownSVal symVal = 249 svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount); 250 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 251 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 252 const ElementRegion *EleReg = 253 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 254 255 if (CNE->isArray()) { 256 // FIXME: allocating an array requires simulating the constructors. 257 // For now, just return a symbolicated region. 258 const ProgramState *state = Pred->getState(); 259 state = state->BindExpr(CNE, Pred->getLocationContext(), 260 loc::MemRegionVal(EleReg)); 261 Bldr.generateNode(CNE, Pred, state); 262 return; 263 } 264 265 // Evaluate constructor arguments. 266 const FunctionProtoType *FnType = NULL; 267 const CXXConstructorDecl *CD = CNE->getConstructor(); 268 if (CD) 269 FnType = CD->getType()->getAs<FunctionProtoType>(); 270 ExplodedNodeSet argsEvaluated; 271 Bldr.takeNodes(Pred); 272 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 273 FnType, Pred, argsEvaluated); 274 Bldr.addNodes(argsEvaluated); 275 276 // Initialize the object region and bind the 'new' expression. 277 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 278 E = argsEvaluated.end(); I != E; ++I) { 279 280 const ProgramState *state = (*I)->getState(); 281 282 // Accumulate list of regions that are invalidated. 283 // FIXME: Eventually we should unify the logic for constructor 284 // processing in one place. 285 SmallVector<const MemRegion*, 10> regionsToInvalidate; 286 for (CXXNewExpr::const_arg_iterator 287 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 288 ai != ae; ++ai) 289 { 290 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 291 if (const MemRegion *region = val.getAsRegion()) 292 regionsToInvalidate.push_back(region); 293 } 294 295 if (ObjTy->isRecordType()) { 296 regionsToInvalidate.push_back(EleReg); 297 // Invalidate the regions. 298 // TODO: Pass the call to new information as the last argument, to limit 299 // the globals which will get invalidated. 300 state = state->invalidateRegions(regionsToInvalidate, 301 CNE, blockCount, 0, 0); 302 303 } else { 304 // Invalidate the regions. 305 // TODO: Pass the call to new information as the last argument, to limit 306 // the globals which will get invalidated. 307 state = state->invalidateRegions(regionsToInvalidate, 308 CNE, blockCount, 0, 0); 309 310 if (CNE->hasInitializer()) { 311 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 312 (*I)->getLocationContext()); 313 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 314 } else { 315 // Explicitly set to undefined, because currently we retrieve symbolic 316 // value from symbolic region. 317 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 318 } 319 } 320 state = state->BindExpr(CNE, (*I)->getLocationContext(), 321 loc::MemRegionVal(EleReg)); 322 Bldr.generateNode(CNE, *I, state); 323 } 324} 325 326void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 327 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 328 // Should do more checking. 329 ExplodedNodeSet Argevaluated; 330 Visit(CDE->getArgument(), Pred, Argevaluated); 331 StmtNodeBuilder Bldr(Argevaluated, Dst, *currentBuilderContext); 332 for (ExplodedNodeSet::iterator I = Argevaluated.begin(), 333 E = Argevaluated.end(); I != E; ++I) { 334 const ProgramState *state = (*I)->getState(); 335 Bldr.generateNode(CDE, *I, state); 336 } 337} 338 339void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 340 ExplodedNodeSet &Dst) { 341 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 342 343 // Get the this object region from StoreManager. 344 const LocationContext *LCtx = Pred->getLocationContext(); 345 const MemRegion *R = 346 svalBuilder.getRegionManager().getCXXThisRegion( 347 getContext().getCanonicalType(TE->getType()), 348 LCtx); 349 350 const ProgramState *state = Pred->getState(); 351 SVal V = state->getSVal(loc::MemRegionVal(R)); 352 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 353} 354