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 
     20 using namespace clang;
     21 using namespace ento;
     22 
     23 namespace {
     24 class CallExprWLItem {
     25 public:
     26   CallExpr::const_arg_iterator I;
     27   ExplodedNode *N;
     28 
     29   CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
     30     : I(i), N(n) {}
     31 };
     32 }
     33 
     34 void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
     35                                  const FunctionProtoType *FnType,
     36                                  ExplodedNode *Pred, ExplodedNodeSet &Dst,
     37                                  bool FstArgAsLValue) {
     38 
     39 
     40   SmallVector<CallExprWLItem, 20> WorkList;
     41   WorkList.reserve(AE - AI);
     42   WorkList.push_back(CallExprWLItem(AI, Pred));
     43 
     44   while (!WorkList.empty()) {
     45     CallExprWLItem Item = WorkList.back();
     46     WorkList.pop_back();
     47 
     48     if (Item.I == AE) {
     49       Dst.insert(Item.N);
     50       continue;
     51     }
     52 
     53     // Evaluate the argument.
     54     ExplodedNodeSet Tmp;
     55     if (FstArgAsLValue) {
     56       FstArgAsLValue = false;
     57     }
     58 
     59     Visit(*Item.I, Item.N, Tmp);
     60     ++(Item.I);
     61     for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
     62       WorkList.push_back(CallExprWLItem(Item.I, *NI));
     63   }
     64 }
     65 
     66 void ExprEngine::evalCallee(const CallExpr *callExpr,
     67                             const ExplodedNodeSet &src,
     68                             ExplodedNodeSet &dest) {
     69 
     70   const Expr *callee = 0;
     71 
     72   switch (callExpr->getStmtClass()) {
     73     case Stmt::CXXMemberCallExprClass: {
     74       // Evaluate the implicit object argument that is the recipient of the
     75       // call.
     76       callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
     77 
     78       // FIXME: handle member pointers.
     79       if (!callee)
     80         return;
     81 
     82       break;
     83     }
     84     default: {
     85       callee = callExpr->getCallee()->IgnoreParens();
     86       break;
     87     }
     88   }
     89 
     90   for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
     91     Visit(callee, *i, dest);
     92 }
     93 
     94 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
     95                                                  const StackFrameContext *SFC) {
     96   const Type *T = D->getTypeForDecl();
     97   QualType PT = getContext().getPointerType(QualType(T, 0));
     98   return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
     99 }
    100 
    101 const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
    102                                             const StackFrameContext *frameCtx) {
    103   return svalBuilder.getRegionManager().
    104                     getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
    105 }
    106 
    107 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
    108                                           ExplodedNode *Pred,
    109                                           ExplodedNodeSet &Dst) {
    110   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
    111   const ProgramState *state = Pred->getState();
    112 
    113   // Bind the temporary object to the value of the expression. Then bind
    114   // the expression to the location of the object.
    115   SVal V = state->getSVal(tempExpr);
    116 
    117   const MemRegion *R =
    118     svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
    119                                                  Pred->getLocationContext());
    120 
    121   state = state->bindLoc(loc::MemRegionVal(R), V);
    122   MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
    123 }
    124 
    125 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
    126                                        const MemRegion *Dest,
    127                                        ExplodedNode *Pred,
    128                                        ExplodedNodeSet &destNodes) {
    129 
    130   const CXXConstructorDecl *CD = E->getConstructor();
    131   assert(CD);
    132 
    133 #if 0
    134   if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
    135     // FIXME: invalidate the object.
    136     return;
    137 #endif
    138 
    139   // Evaluate other arguments.
    140   ExplodedNodeSet argsEvaluated;
    141   const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
    142   evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
    143 
    144 #if 0
    145   // Is the constructor elidable?
    146   if (E->isElidable()) {
    147     VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
    148     // FIXME: this is here to force propagation if VisitAggExpr doesn't
    149     if (destNodes.empty())
    150       destNodes.Add(Pred);
    151     return;
    152   }
    153 #endif
    154 
    155   // Perform the previsit of the constructor.
    156   ExplodedNodeSet destPreVisit;
    157   getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
    158                                             *this);
    159 
    160   // Evaluate the constructor.  Currently we don't now allow checker-specific
    161   // implementations of specific constructors (as we do with ordinary
    162   // function calls.  We can re-evaluate this in the future.
    163 
    164 #if 0
    165   // Inlining currently isn't fully implemented.
    166 
    167   if (AMgr.shouldInlineCall()) {
    168     if (!Dest)
    169       Dest =
    170         svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
    171                                                   Pred->getLocationContext());
    172 
    173     // The callee stack frame context used to create the 'this'
    174     // parameter region.
    175     const StackFrameContext *SFC =
    176       AMgr.getStackFrame(CD, Pred->getLocationContext(),
    177                          E, Builder->getBlock(), Builder->getIndex());
    178 
    179     // Create the 'this' region.
    180     const CXXThisRegion *ThisR =
    181       getCXXThisRegion(E->getConstructor()->getParent(), SFC);
    182 
    183     CallEnter Loc(E, SFC, Pred->getLocationContext());
    184 
    185 
    186     for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
    187                                   NE = argsEvaluated.end(); NI != NE; ++NI) {
    188       const ProgramState *state = (*NI)->getState();
    189       // Setup 'this' region, so that the ctor is evaluated on the object pointed
    190       // by 'Dest'.
    191       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
    192       if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
    193         destNodes.Add(N);
    194     }
    195   }
    196 #endif
    197 
    198   // Default semantics: invalidate all regions passed as arguments.
    199   ExplodedNodeSet destCall;
    200 
    201   for (ExplodedNodeSet::iterator
    202         i = destPreVisit.begin(), e = destPreVisit.end();
    203        i != e; ++i)
    204   {
    205     ExplodedNode *Pred = *i;
    206     const LocationContext *LC = Pred->getLocationContext();
    207     const ProgramState *state = Pred->getState();
    208 
    209     state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
    210     Builder->MakeNode(destCall, E, Pred, state);
    211   }
    212 
    213   // Do the post visit.
    214   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
    215 }
    216 
    217 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
    218                                       const MemRegion *Dest,
    219                                       const Stmt *S,
    220                                       ExplodedNode *Pred,
    221                                       ExplodedNodeSet &Dst) {
    222   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
    223     return;
    224   // Create the context for 'this' region.
    225   const StackFrameContext *SFC = AMgr.getStackFrame(DD,
    226                                                     Pred->getLocationContext(),
    227                                                     S, Builder->getBlock(),
    228                                                     Builder->getIndex());
    229 
    230   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
    231 
    232   CallEnter PP(S, SFC, Pred->getLocationContext());
    233 
    234   const ProgramState *state = Pred->getState();
    235   state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
    236   ExplodedNode *N = Builder->generateNode(PP, state, Pred);
    237   if (N)
    238     Dst.Add(N);
    239 }
    240 
    241 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
    242                                    ExplodedNodeSet &Dst) {
    243 
    244   unsigned blockCount = Builder->getCurrentBlockCount();
    245   DefinedOrUnknownSVal symVal =
    246     svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
    247   const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
    248   QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
    249   const ElementRegion *EleReg =
    250     getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
    251 
    252   if (CNE->isArray()) {
    253     // FIXME: allocating an array requires simulating the constructors.
    254     // For now, just return a symbolicated region.
    255     const ProgramState *state = Pred->getState();
    256     state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
    257     MakeNode(Dst, CNE, Pred, state);
    258     return;
    259   }
    260 
    261   // Evaluate constructor arguments.
    262   const FunctionProtoType *FnType = NULL;
    263   const CXXConstructorDecl *CD = CNE->getConstructor();
    264   if (CD)
    265     FnType = CD->getType()->getAs<FunctionProtoType>();
    266   ExplodedNodeSet argsEvaluated;
    267   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
    268                 FnType, Pred, argsEvaluated);
    269 
    270   // Initialize the object region and bind the 'new' expression.
    271   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
    272                                  E = argsEvaluated.end(); I != E; ++I) {
    273 
    274     const ProgramState *state = (*I)->getState();
    275 
    276     // Accumulate list of regions that are invalidated.
    277     // FIXME: Eventually we should unify the logic for constructor
    278     // processing in one place.
    279     SmallVector<const MemRegion*, 10> regionsToInvalidate;
    280     for (CXXNewExpr::const_arg_iterator
    281           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
    282           ai != ae; ++ai)
    283     {
    284       SVal val = state->getSVal(*ai);
    285       if (const MemRegion *region = val.getAsRegion())
    286         regionsToInvalidate.push_back(region);
    287     }
    288 
    289     if (ObjTy->isRecordType()) {
    290       regionsToInvalidate.push_back(EleReg);
    291       // Invalidate the regions.
    292       state = state->invalidateRegions(regionsToInvalidate,
    293                                        CNE, blockCount, 0,
    294                                        /* invalidateGlobals = */ true);
    295 
    296     } else {
    297       // Invalidate the regions.
    298       state = state->invalidateRegions(regionsToInvalidate,
    299                                        CNE, blockCount, 0,
    300                                        /* invalidateGlobals = */ true);
    301 
    302       if (CNE->hasInitializer()) {
    303         SVal V = state->getSVal(*CNE->constructor_arg_begin());
    304         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
    305       } else {
    306         // Explicitly set to undefined, because currently we retrieve symbolic
    307         // value from symbolic region.
    308         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
    309       }
    310     }
    311     state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
    312     MakeNode(Dst, CNE, *I, state);
    313   }
    314 }
    315 
    316 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
    317                                       ExplodedNode *Pred,ExplodedNodeSet &Dst) {
    318   // Should do more checking.
    319   ExplodedNodeSet Argevaluated;
    320   Visit(CDE->getArgument(), Pred, Argevaluated);
    321   for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
    322                                  E = Argevaluated.end(); I != E; ++I) {
    323     const ProgramState *state = (*I)->getState();
    324     MakeNode(Dst, CDE, *I, state);
    325   }
    326 }
    327 
    328 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
    329                                     ExplodedNodeSet &Dst) {
    330   // Get the this object region from StoreManager.
    331   const MemRegion *R =
    332     svalBuilder.getRegionManager().getCXXThisRegion(
    333                                   getContext().getCanonicalType(TE->getType()),
    334                                                Pred->getLocationContext());
    335 
    336   const ProgramState *state = Pred->getState();
    337   SVal V = state->getSVal(loc::MemRegionVal(R));
    338   MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
    339 }
    340