Home | History | Annotate | Download | only in Core
      1 //=-- ExprEngineCallAndReturn.cpp - Support for call/return -----*- 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 ExprEngine's support for calls and returns.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
     15 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
     16 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
     17 #include "clang/AST/DeclCXX.h"
     18 #include "clang/Analysis/Support/SaveAndRestore.h"
     19 
     20 using namespace clang;
     21 using namespace ento;
     22 
     23 namespace {
     24   // Trait class for recording returned expression in the state.
     25   struct ReturnExpr {
     26     static int TagInt;
     27     typedef const Stmt *data_type;
     28   };
     29   int ReturnExpr::TagInt;
     30 }
     31 
     32 void ExprEngine::processCallEnter(CallEnterNodeBuilder &B) {
     33   const ProgramState *state =
     34     B.getState()->enterStackFrame(B.getCalleeContext());
     35   B.generateNode(state);
     36 }
     37 
     38 void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
     39   const ProgramState *state = B.getState();
     40   const ExplodedNode *Pred = B.getPredecessor();
     41   const StackFrameContext *calleeCtx =
     42     cast<StackFrameContext>(Pred->getLocationContext());
     43   const Stmt *CE = calleeCtx->getCallSite();
     44 
     45   // If the callee returns an expression, bind its value to CallExpr.
     46   const Stmt *ReturnedExpr = state->get<ReturnExpr>();
     47   if (ReturnedExpr) {
     48     SVal RetVal = state->getSVal(ReturnedExpr);
     49     state = state->BindExpr(CE, RetVal);
     50     // Clear the return expr GDM.
     51     state = state->remove<ReturnExpr>();
     52   }
     53 
     54   // Bind the constructed object value to CXXConstructExpr.
     55   if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
     56     const CXXThisRegion *ThisR =
     57     getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
     58 
     59     SVal ThisV = state->getSVal(ThisR);
     60     // Always bind the region to the CXXConstructExpr.
     61     state = state->BindExpr(CCE, ThisV);
     62   }
     63 
     64   B.generateNode(state);
     65 }
     66 
     67 const ProgramState *
     68 ExprEngine::invalidateArguments(const ProgramState *State,
     69                                 const CallOrObjCMessage &Call,
     70                                 const LocationContext *LC) {
     71   SmallVector<const MemRegion *, 8> RegionsToInvalidate;
     72 
     73   if (Call.isObjCMessage()) {
     74     // Invalidate all instance variables of the receiver of an ObjC message.
     75     // FIXME: We should be able to do better with inter-procedural analysis.
     76     if (const MemRegion *MR = Call.getInstanceMessageReceiver(LC).getAsRegion())
     77       RegionsToInvalidate.push_back(MR);
     78 
     79   } else if (Call.isCXXCall()) {
     80     // Invalidate all instance variables for the callee of a C++ method call.
     81     // FIXME: We should be able to do better with inter-procedural analysis.
     82     // FIXME: We can probably do better for const versus non-const methods.
     83     if (const MemRegion *Callee = Call.getCXXCallee().getAsRegion())
     84       RegionsToInvalidate.push_back(Callee);
     85 
     86   } else if (Call.isFunctionCall()) {
     87     // Block calls invalidate all captured-by-reference values.
     88     if (const MemRegion *Callee = Call.getFunctionCallee().getAsRegion()) {
     89       if (isa<BlockDataRegion>(Callee))
     90         RegionsToInvalidate.push_back(Callee);
     91     }
     92   }
     93 
     94   for (unsigned idx = 0, e = Call.getNumArgs(); idx != e; ++idx) {
     95     SVal V = Call.getArgSVal(idx);
     96 
     97     // If we are passing a location wrapped as an integer, unwrap it and
     98     // invalidate the values referred by the location.
     99     if (nonloc::LocAsInteger *Wrapped = dyn_cast<nonloc::LocAsInteger>(&V))
    100       V = Wrapped->getLoc();
    101     else if (!isa<Loc>(V))
    102       continue;
    103 
    104     if (const MemRegion *R = V.getAsRegion()) {
    105       // Invalidate the value of the variable passed by reference.
    106 
    107       // Are we dealing with an ElementRegion?  If the element type is
    108       // a basic integer type (e.g., char, int) and the underying region
    109       // is a variable region then strip off the ElementRegion.
    110       // FIXME: We really need to think about this for the general case
    111       //   as sometimes we are reasoning about arrays and other times
    112       //   about (char*), etc., is just a form of passing raw bytes.
    113       //   e.g., void *p = alloca(); foo((char*)p);
    114       if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
    115         // Checking for 'integral type' is probably too promiscuous, but
    116         // we'll leave it in for now until we have a systematic way of
    117         // handling all of these cases.  Eventually we need to come up
    118         // with an interface to StoreManager so that this logic can be
    119         // approriately delegated to the respective StoreManagers while
    120         // still allowing us to do checker-specific logic (e.g.,
    121         // invalidating reference counts), probably via callbacks.
    122         if (ER->getElementType()->isIntegralOrEnumerationType()) {
    123           const MemRegion *superReg = ER->getSuperRegion();
    124           if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
    125               isa<ObjCIvarRegion>(superReg))
    126             R = cast<TypedRegion>(superReg);
    127         }
    128         // FIXME: What about layers of ElementRegions?
    129       }
    130 
    131       // Mark this region for invalidation.  We batch invalidate regions
    132       // below for efficiency.
    133       RegionsToInvalidate.push_back(R);
    134     } else {
    135       // Nuke all other arguments passed by reference.
    136       // FIXME: is this necessary or correct? This handles the non-Region
    137       //  cases.  Is it ever valid to store to these?
    138       State = State->unbindLoc(cast<Loc>(V));
    139     }
    140   }
    141 
    142   // Invalidate designated regions using the batch invalidation API.
    143 
    144   // FIXME: We can have collisions on the conjured symbol if the
    145   //  expression *I also creates conjured symbols.  We probably want
    146   //  to identify conjured symbols by an expression pair: the enclosing
    147   //  expression (the context) and the expression itself.  This should
    148   //  disambiguate conjured symbols.
    149   assert(Builder && "Invalidating arguments outside of a statement context");
    150   unsigned Count = Builder->getCurrentBlockCount();
    151   StoreManager::InvalidatedSymbols IS;
    152 
    153   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
    154   //  global variables.
    155   return State->invalidateRegions(RegionsToInvalidate,
    156                                   Call.getOriginExpr(), Count,
    157                                   &IS, doesInvalidateGlobals(Call));
    158 
    159 }
    160 
    161 void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
    162                                ExplodedNodeSet &dst) {
    163   // Perform the previsit of the CallExpr.
    164   ExplodedNodeSet dstPreVisit;
    165   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, CE, *this);
    166 
    167   // Now evaluate the call itself.
    168   class DefaultEval : public GraphExpander {
    169     ExprEngine &Eng;
    170     const CallExpr *CE;
    171   public:
    172 
    173     DefaultEval(ExprEngine &eng, const CallExpr *ce)
    174     : Eng(eng), CE(ce) {}
    175     virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
    176       // Should we inline the call?
    177       if (Eng.getAnalysisManager().shouldInlineCall() &&
    178           Eng.InlineCall(Dst, CE, Pred)) {
    179         return;
    180       }
    181 
    182       // First handle the return value.
    183       StmtNodeBuilder &Builder = Eng.getBuilder();
    184       assert(&Builder && "StmtNodeBuilder must be defined.");
    185 
    186       // Get the callee.
    187       const Expr *Callee = CE->getCallee()->IgnoreParens();
    188       const ProgramState *state = Pred->getState();
    189       SVal L = state->getSVal(Callee);
    190 
    191       // Figure out the result type. We do this dance to handle references.
    192       QualType ResultTy;
    193       if (const FunctionDecl *FD = L.getAsFunctionDecl())
    194         ResultTy = FD->getResultType();
    195       else
    196         ResultTy = CE->getType();
    197 
    198       if (CE->isLValue())
    199         ResultTy = Eng.getContext().getPointerType(ResultTy);
    200 
    201       // Conjure a symbol value to use as the result.
    202       SValBuilder &SVB = Eng.getSValBuilder();
    203       unsigned Count = Builder.getCurrentBlockCount();
    204       SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
    205 
    206       // Generate a new state with the return value set.
    207       state = state->BindExpr(CE, RetVal);
    208 
    209       // Invalidate the arguments.
    210       const LocationContext *LC = Pred->getLocationContext();
    211       state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
    212 
    213       // And make the result node.
    214       Eng.MakeNode(Dst, CE, Pred, state);
    215     }
    216   };
    217 
    218   // Finally, evaluate the function call.  We try each of the checkers
    219   // to see if the can evaluate the function call.
    220   ExplodedNodeSet dstCallEvaluated;
    221   DefaultEval defEval(*this, CE);
    222   getCheckerManager().runCheckersForEvalCall(dstCallEvaluated,
    223                                              dstPreVisit,
    224                                              CE, *this, &defEval);
    225 
    226   // Finally, perform the post-condition check of the CallExpr and store
    227   // the created nodes in 'Dst'.
    228   getCheckerManager().runCheckersForPostStmt(dst, dstCallEvaluated, CE,
    229                                              *this);
    230 }
    231 
    232 void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
    233                                  ExplodedNodeSet &Dst) {
    234   ExplodedNodeSet Src;
    235   if (const Expr *RetE = RS->getRetValue()) {
    236     // Record the returned expression in the state. It will be used in
    237     // processCallExit to bind the return value to the call expr.
    238     {
    239       static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
    240       const ProgramState *state = Pred->getState();
    241       state = state->set<ReturnExpr>(RetE);
    242       Pred = Builder->generateNode(RetE, state, Pred, &tag);
    243     }
    244     // We may get a NULL Pred because we generated a cached node.
    245     if (Pred)
    246       Visit(RetE, Pred, Src);
    247   }
    248   else {
    249     Src.Add(Pred);
    250   }
    251 
    252   getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);
    253 }
    254