ExprEngineCXX.cpp revision 59e7f4e6e69872d2fc4031f66b47b8ad64967e51
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 VisitAggExpr(E->getArg(0), destNodes, Pred, Dst); 82 // FIXME: this is here to force propagation if VisitAggExpr doesn't 83 if (destNodes.empty()) 84 destNodes.Add(Pred); 85 return; 86 } 87#endif 88 89 // Perform the previsit of the constructor. 90 ExplodedNodeSet SrcNodes; 91 SrcNodes.Add(Pred); 92 ExplodedNodeSet TmpNodes; 93 getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this); 94 95 // Evaluate the constructor. Currently we don't now allow checker-specific 96 // implementations of specific constructors (as we do with ordinary 97 // function calls. We can re-evaluate this in the future. 98 99#if 0 100 // Inlining currently isn't fully implemented. 101 102 if (AMgr.shouldInlineCall()) { 103 if (!Dest) 104 Dest = 105 svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 106 Pred->getLocationContext()); 107 108 // The callee stack frame context used to create the 'this' 109 // parameter region. 110 const StackFrameContext *SFC = 111 AMgr.getStackFrame(CD, Pred->getLocationContext(), 112 E, currentBuilderContext->getBlock(), 113 currentStmtIdx); 114 115 // Create the 'this' region. 116 const CXXThisRegion *ThisR = 117 getCXXThisRegion(E->getConstructor()->getParent(), SFC); 118 119 CallEnter Loc(E, SFC, Pred->getLocationContext()); 120 121 StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext); 122 for (ExplodedNodeSet::iterator NI = SrcNodes.begin(), 123 NE = SrcNodes.end(); NI != NE; ++NI) { 124 ProgramStateRef state = (*NI)->getState(); 125 // Setup 'this' region, so that the ctor is evaluated on the object pointed 126 // by 'Dest'. 127 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 128 Bldr.generateNode(Loc, *NI, state); 129 } 130 } 131#endif 132 133 // Default semantics: invalidate all regions passed as arguments. 134 ExplodedNodeSet destCall; 135 { 136 StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext); 137 for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end(); 138 i != e; ++i) 139 { 140 ExplodedNode *Pred = *i; 141 const LocationContext *LC = Pred->getLocationContext(); 142 ProgramStateRef state = Pred->getState(); 143 144 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 145 Bldr.generateNode(E, Pred, state); 146 } 147 } 148 // Do the post visit. 149 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 150} 151 152void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 153 const MemRegion *Dest, 154 const Stmt *S, 155 ExplodedNode *Pred, 156 ExplodedNodeSet &Dst) { 157 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 158 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 159 return; 160 161 // Create the context for 'this' region. 162 const StackFrameContext *SFC = 163 AnalysisDeclContexts.getContext(DD)-> 164 getStackFrame(Pred->getLocationContext(), S, 165 currentBuilderContext->getBlock(), currentStmtIdx); 166 167 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 168 169 CallEnter PP(S, SFC, Pred->getLocationContext()); 170 171 ProgramStateRef state = Pred->getState(); 172 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 173 Bldr.generateNode(PP, Pred, state); 174} 175 176void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 177 ExplodedNodeSet &Dst) { 178 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 179 180 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 181 const LocationContext *LCtx = Pred->getLocationContext(); 182 DefinedOrUnknownSVal symVal = 183 svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 184 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 185 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 186 const ElementRegion *EleReg = 187 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 188 189 if (CNE->isArray()) { 190 // FIXME: allocating an array requires simulating the constructors. 191 // For now, just return a symbolicated region. 192 ProgramStateRef state = Pred->getState(); 193 state = state->BindExpr(CNE, Pred->getLocationContext(), 194 loc::MemRegionVal(EleReg)); 195 Bldr.generateNode(CNE, Pred, state); 196 return; 197 } 198 199 // FIXME: Update for AST changes. 200#if 0 201 // Evaluate constructor arguments. 202 const FunctionProtoType *FnType = NULL; 203 const CXXConstructorDecl *CD = CNE->getConstructor(); 204 if (CD) 205 FnType = CD->getType()->getAs<FunctionProtoType>(); 206 ExplodedNodeSet argsEvaluated; 207 Bldr.takeNodes(Pred); 208 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 209 FnType, Pred, argsEvaluated); 210 Bldr.addNodes(argsEvaluated); 211 212 // Initialize the object region and bind the 'new' expression. 213 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 214 E = argsEvaluated.end(); I != E; ++I) { 215 216 ProgramStateRef state = (*I)->getState(); 217 218 // Accumulate list of regions that are invalidated. 219 // FIXME: Eventually we should unify the logic for constructor 220 // processing in one place. 221 SmallVector<const MemRegion*, 10> regionsToInvalidate; 222 for (CXXNewExpr::const_arg_iterator 223 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 224 ai != ae; ++ai) 225 { 226 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 227 if (const MemRegion *region = val.getAsRegion()) 228 regionsToInvalidate.push_back(region); 229 } 230 231 if (ObjTy->isRecordType()) { 232 regionsToInvalidate.push_back(EleReg); 233 // Invalidate the regions. 234 // TODO: Pass the call to new information as the last argument, to limit 235 // the globals which will get invalidated. 236 state = state->invalidateRegions(regionsToInvalidate, 237 CNE, blockCount, 0, 0); 238 239 } else { 240 // Invalidate the regions. 241 // TODO: Pass the call to new information as the last argument, to limit 242 // the globals which will get invalidated. 243 state = state->invalidateRegions(regionsToInvalidate, 244 CNE, blockCount, 0, 0); 245 246 if (CNE->hasInitializer()) { 247 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 248 (*I)->getLocationContext()); 249 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 250 } else { 251 // Explicitly set to undefined, because currently we retrieve symbolic 252 // value from symbolic region. 253 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 254 } 255 } 256 state = state->BindExpr(CNE, (*I)->getLocationContext(), 257 loc::MemRegionVal(EleReg)); 258 Bldr.generateNode(CNE, *I, state); 259 } 260#endif 261} 262 263void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 264 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 265 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 266 ProgramStateRef state = Pred->getState(); 267 Bldr.generateNode(CDE, Pred, state); 268} 269 270void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 271 ExplodedNode *Pred, 272 ExplodedNodeSet &Dst) { 273 const VarDecl *VD = CS->getExceptionDecl(); 274 const LocationContext *LCtx = Pred->getLocationContext(); 275 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 276 currentBuilderContext->getCurrentBlockCount()); 277 ProgramStateRef state = Pred->getState(); 278 state = state->bindLoc(state->getLValue(VD, LCtx), V); 279 280 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 281 Bldr.generateNode(CS, Pred, state); 282} 283 284void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 285 ExplodedNodeSet &Dst) { 286 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 287 288 // Get the this object region from StoreManager. 289 const LocationContext *LCtx = Pred->getLocationContext(); 290 const MemRegion *R = 291 svalBuilder.getRegionManager().getCXXThisRegion( 292 getContext().getCanonicalType(TE->getType()), 293 LCtx); 294 295 ProgramStateRef state = Pred->getState(); 296 SVal V = state->getSVal(loc::MemRegionVal(R)); 297 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 298} 299