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 21 using namespace clang; 22 using namespace ento; 23 24 const 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 31 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 32 const StackFrameContext *frameCtx) { 33 return svalBuilder.getRegionManager(). 34 getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 35 } 36 37 void 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 56 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 57 ExplodedNode *Pred, 58 ExplodedNodeSet &Dst) { 59 VisitCXXConstructExpr(expr, 0, Pred, Dst); 60 } 61 62 void 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 149 void 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 173 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 174 ExplodedNodeSet &Dst) { 175 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 176 177 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 178 const LocationContext *LCtx = Pred->getLocationContext(); 179 DefinedOrUnknownSVal symVal = 180 svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 181 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 182 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 183 const ElementRegion *EleReg = 184 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 185 186 if (CNE->isArray()) { 187 // FIXME: allocating an array requires simulating the constructors. 188 // For now, just return a symbolicated region. 189 ProgramStateRef state = Pred->getState(); 190 state = state->BindExpr(CNE, Pred->getLocationContext(), 191 loc::MemRegionVal(EleReg)); 192 Bldr.generateNode(CNE, Pred, state); 193 return; 194 } 195 196 // FIXME: Update for AST changes. 197 #if 0 198 // Evaluate constructor arguments. 199 const FunctionProtoType *FnType = NULL; 200 const CXXConstructorDecl *CD = CNE->getConstructor(); 201 if (CD) 202 FnType = CD->getType()->getAs<FunctionProtoType>(); 203 ExplodedNodeSet argsEvaluated; 204 Bldr.takeNodes(Pred); 205 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 206 FnType, Pred, argsEvaluated); 207 Bldr.addNodes(argsEvaluated); 208 209 // Initialize the object region and bind the 'new' expression. 210 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 211 E = argsEvaluated.end(); I != E; ++I) { 212 213 ProgramStateRef state = (*I)->getState(); 214 215 // Accumulate list of regions that are invalidated. 216 // FIXME: Eventually we should unify the logic for constructor 217 // processing in one place. 218 SmallVector<const MemRegion*, 10> regionsToInvalidate; 219 for (CXXNewExpr::const_arg_iterator 220 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 221 ai != ae; ++ai) 222 { 223 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 224 if (const MemRegion *region = val.getAsRegion()) 225 regionsToInvalidate.push_back(region); 226 } 227 228 if (ObjTy->isRecordType()) { 229 regionsToInvalidate.push_back(EleReg); 230 // Invalidate the regions. 231 // TODO: Pass the call to new information as the last argument, to limit 232 // the globals which will get invalidated. 233 state = state->invalidateRegions(regionsToInvalidate, 234 CNE, blockCount, 0, 0); 235 236 } else { 237 // Invalidate the regions. 238 // TODO: Pass the call to new information as the last argument, to limit 239 // the globals which will get invalidated. 240 state = state->invalidateRegions(regionsToInvalidate, 241 CNE, blockCount, 0, 0); 242 243 if (CNE->hasInitializer()) { 244 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 245 (*I)->getLocationContext()); 246 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 247 } else { 248 // Explicitly set to undefined, because currently we retrieve symbolic 249 // value from symbolic region. 250 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 251 } 252 } 253 state = state->BindExpr(CNE, (*I)->getLocationContext(), 254 loc::MemRegionVal(EleReg)); 255 Bldr.generateNode(CNE, *I, state); 256 } 257 #endif 258 } 259 260 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 261 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 262 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 263 ProgramStateRef state = Pred->getState(); 264 Bldr.generateNode(CDE, Pred, state); 265 } 266 267 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 268 ExplodedNode *Pred, 269 ExplodedNodeSet &Dst) { 270 const VarDecl *VD = CS->getExceptionDecl(); 271 if (!VD) { 272 Dst.Add(Pred); 273 return; 274 } 275 276 const LocationContext *LCtx = Pred->getLocationContext(); 277 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 278 currentBuilderContext->getCurrentBlockCount()); 279 ProgramStateRef state = Pred->getState(); 280 state = state->bindLoc(state->getLValue(VD, LCtx), V); 281 282 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 283 Bldr.generateNode(CS, Pred, state); 284 } 285 286 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 287 ExplodedNodeSet &Dst) { 288 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 289 290 // Get the this object region from StoreManager. 291 const LocationContext *LCtx = Pred->getLocationContext(); 292 const MemRegion *R = 293 svalBuilder.getRegionManager().getCXXThisRegion( 294 getContext().getCanonicalType(TE->getType()), 295 LCtx); 296 297 ProgramStateRef state = Pred->getState(); 298 SVal V = state->getSVal(loc::MemRegionVal(R)); 299 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 300 } 301