Home | History | Annotate | Download | only in Core
      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