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