clang API Documentation
00001 //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the C++ expression evaluation engine. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00015 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 00016 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 00018 #include "clang/AST/DeclCXX.h" 00019 #include "clang/AST/StmtCXX.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D, 00025 const StackFrameContext *SFC) { 00026 const Type *T = D->getTypeForDecl(); 00027 QualType PT = getContext().getPointerType(QualType(T, 0)); 00028 return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC); 00029 } 00030 00031 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl, 00032 const StackFrameContext *frameCtx) { 00033 return svalBuilder.getRegionManager(). 00034 getCXXThisRegion(decl->getThisType(getContext()), frameCtx); 00035 } 00036 00037 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, 00038 ExplodedNode *Pred, 00039 ExplodedNodeSet &Dst) { 00040 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00041 const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); 00042 ProgramStateRef state = Pred->getState(); 00043 const LocationContext *LCtx = Pred->getLocationContext(); 00044 00045 // Bind the temporary object to the value of the expression. Then bind 00046 // the expression to the location of the object. 00047 SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); 00048 00049 const MemRegion *R = 00050 svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); 00051 00052 state = state->bindLoc(loc::MemRegionVal(R), V); 00053 Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); 00054 } 00055 00056 void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, 00057 ExplodedNode *Pred, 00058 ExplodedNodeSet &Dst) { 00059 VisitCXXConstructExpr(expr, 0, Pred, Dst); 00060 } 00061 00062 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 00063 const MemRegion *Dest, 00064 ExplodedNode *Pred, 00065 ExplodedNodeSet &destNodes) { 00066 00067 #if 0 00068 const CXXConstructorDecl *CD = E->getConstructor(); 00069 assert(CD); 00070 #endif 00071 00072 #if 0 00073 if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 00074 // FIXME: invalidate the object. 00075 return; 00076 #endif 00077 00078 #if 0 00079 // Is the constructor elidable? 00080 if (E->isElidable()) { 00081 destNodes.Add(Pred); 00082 return; 00083 } 00084 #endif 00085 00086 // Perform the previsit of the constructor. 00087 ExplodedNodeSet SrcNodes; 00088 SrcNodes.Add(Pred); 00089 ExplodedNodeSet TmpNodes; 00090 getCheckerManager().runCheckersForPreStmt(TmpNodes, SrcNodes, E, *this); 00091 00092 // Evaluate the constructor. Currently we don't now allow checker-specific 00093 // implementations of specific constructors (as we do with ordinary 00094 // function calls. We can re-evaluate this in the future. 00095 00096 #if 0 00097 // Inlining currently isn't fully implemented. 00098 00099 if (AMgr.shouldInlineCall()) { 00100 if (!Dest) 00101 Dest = 00102 svalBuilder.getRegionManager().getCXXTempObjectRegion(E, 00103 Pred->getLocationContext()); 00104 00105 // The callee stack frame context used to create the 'this' 00106 // parameter region. 00107 const StackFrameContext *SFC = 00108 AMgr.getStackFrame(CD, Pred->getLocationContext(), 00109 E, currentBuilderContext->getBlock(), 00110 currentStmtIdx); 00111 00112 // Create the 'this' region. 00113 const CXXThisRegion *ThisR = 00114 getCXXThisRegion(E->getConstructor()->getParent(), SFC); 00115 00116 CallEnter Loc(E, SFC, Pred->getLocationContext()); 00117 00118 StmtNodeBuilder Bldr(SrcNodes, TmpNodes, *currentBuilderContext); 00119 for (ExplodedNodeSet::iterator NI = SrcNodes.begin(), 00120 NE = SrcNodes.end(); NI != NE; ++NI) { 00121 ProgramStateRef state = (*NI)->getState(); 00122 // Setup 'this' region, so that the ctor is evaluated on the object pointed 00123 // by 'Dest'. 00124 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 00125 Bldr.generateNode(Loc, *NI, state); 00126 } 00127 } 00128 #endif 00129 00130 // Default semantics: invalidate all regions passed as arguments. 00131 ExplodedNodeSet destCall; 00132 { 00133 StmtNodeBuilder Bldr(TmpNodes, destCall, *currentBuilderContext); 00134 for (ExplodedNodeSet::iterator i = TmpNodes.begin(), e = TmpNodes.end(); 00135 i != e; ++i) 00136 { 00137 ExplodedNode *Pred = *i; 00138 const LocationContext *LC = Pred->getLocationContext(); 00139 ProgramStateRef state = Pred->getState(); 00140 00141 state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); 00142 Bldr.generateNode(E, Pred, state); 00143 } 00144 } 00145 // Do the post visit. 00146 getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this); 00147 } 00148 00149 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD, 00150 const MemRegion *Dest, 00151 const Stmt *S, 00152 ExplodedNode *Pred, 00153 ExplodedNodeSet &Dst) { 00154 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00155 if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall())) 00156 return; 00157 00158 // Create the context for 'this' region. 00159 const StackFrameContext *SFC = 00160 AnalysisDeclContexts.getContext(DD)-> 00161 getStackFrame(Pred->getLocationContext(), S, 00162 currentBuilderContext->getBlock(), currentStmtIdx); 00163 00164 const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC); 00165 00166 CallEnter PP(S, SFC, Pred->getLocationContext()); 00167 00168 ProgramStateRef state = Pred->getState(); 00169 state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest)); 00170 Bldr.generateNode(PP, Pred, state); 00171 } 00172 00173 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, 00174 ExplodedNodeSet &Dst) { 00175 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00176 00177 unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); 00178 const LocationContext *LCtx = Pred->getLocationContext(); 00179 DefinedOrUnknownSVal symVal = 00180 svalBuilder.getConjuredSymbolVal(NULL, CNE, LCtx, CNE->getType(), blockCount); 00181 const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); 00182 QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); 00183 const ElementRegion *EleReg = 00184 getStoreManager().GetElementZeroRegion(NewReg, ObjTy); 00185 00186 if (CNE->isArray()) { 00187 // FIXME: allocating an array requires simulating the constructors. 00188 // For now, just return a symbolicated region. 00189 ProgramStateRef state = Pred->getState(); 00190 state = state->BindExpr(CNE, Pred->getLocationContext(), 00191 loc::MemRegionVal(EleReg)); 00192 Bldr.generateNode(CNE, Pred, state); 00193 return; 00194 } 00195 00196 // FIXME: Update for AST changes. 00197 #if 0 00198 // Evaluate constructor arguments. 00199 const FunctionProtoType *FnType = NULL; 00200 const CXXConstructorDecl *CD = CNE->getConstructor(); 00201 if (CD) 00202 FnType = CD->getType()->getAs<FunctionProtoType>(); 00203 ExplodedNodeSet argsEvaluated; 00204 Bldr.takeNodes(Pred); 00205 evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(), 00206 FnType, Pred, argsEvaluated); 00207 Bldr.addNodes(argsEvaluated); 00208 00209 // Initialize the object region and bind the 'new' expression. 00210 for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 00211 E = argsEvaluated.end(); I != E; ++I) { 00212 00213 ProgramStateRef state = (*I)->getState(); 00214 00215 // Accumulate list of regions that are invalidated. 00216 // FIXME: Eventually we should unify the logic for constructor 00217 // processing in one place. 00218 SmallVector<const MemRegion*, 10> regionsToInvalidate; 00219 for (CXXNewExpr::const_arg_iterator 00220 ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); 00221 ai != ae; ++ai) 00222 { 00223 SVal val = state->getSVal(*ai, (*I)->getLocationContext()); 00224 if (const MemRegion *region = val.getAsRegion()) 00225 regionsToInvalidate.push_back(region); 00226 } 00227 00228 if (ObjTy->isRecordType()) { 00229 regionsToInvalidate.push_back(EleReg); 00230 // Invalidate the regions. 00231 // TODO: Pass the call to new information as the last argument, to limit 00232 // the globals which will get invalidated. 00233 state = state->invalidateRegions(regionsToInvalidate, 00234 CNE, blockCount, 0, 0); 00235 00236 } else { 00237 // Invalidate the regions. 00238 // TODO: Pass the call to new information as the last argument, to limit 00239 // the globals which will get invalidated. 00240 state = state->invalidateRegions(regionsToInvalidate, 00241 CNE, blockCount, 0, 0); 00242 00243 if (CNE->hasInitializer()) { 00244 SVal V = state->getSVal(*CNE->constructor_arg_begin(), 00245 (*I)->getLocationContext()); 00246 state = state->bindLoc(loc::MemRegionVal(EleReg), V); 00247 } else { 00248 // Explicitly set to undefined, because currently we retrieve symbolic 00249 // value from symbolic region. 00250 state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); 00251 } 00252 } 00253 state = state->BindExpr(CNE, (*I)->getLocationContext(), 00254 loc::MemRegionVal(EleReg)); 00255 Bldr.generateNode(CNE, *I, state); 00256 } 00257 #endif 00258 } 00259 00260 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 00261 ExplodedNode *Pred, ExplodedNodeSet &Dst) { 00262 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00263 ProgramStateRef state = Pred->getState(); 00264 Bldr.generateNode(CDE, Pred, state); 00265 } 00266 00267 void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, 00268 ExplodedNode *Pred, 00269 ExplodedNodeSet &Dst) { 00270 const VarDecl *VD = CS->getExceptionDecl(); 00271 if (!VD) { 00272 Dst.Add(Pred); 00273 return; 00274 } 00275 00276 const LocationContext *LCtx = Pred->getLocationContext(); 00277 SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), 00278 currentBuilderContext->getCurrentBlockCount()); 00279 ProgramStateRef state = Pred->getState(); 00280 state = state->bindLoc(state->getLValue(VD, LCtx), V); 00281 00282 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00283 Bldr.generateNode(CS, Pred, state); 00284 } 00285 00286 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 00287 ExplodedNodeSet &Dst) { 00288 StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); 00289 00290 // Get the this object region from StoreManager. 00291 const LocationContext *LCtx = Pred->getLocationContext(); 00292 const MemRegion *R = 00293 svalBuilder.getRegionManager().getCXXThisRegion( 00294 getContext().getCanonicalType(TE->getType()), 00295 LCtx); 00296 00297 ProgramStateRef state = Pred->getState(); 00298 SVal V = state->getSVal(loc::MemRegionVal(R)); 00299 Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); 00300 }