clang API Documentation

ExprEngineCXX.cpp
Go to the documentation of this file.
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 }