Home | History | Annotate | Download | only in PathSensitive
      1 //===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- 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 ObjCMessage which serves as a common wrapper for ObjC
     11 // message expressions or implicit messages for loading/storing ObjC properties.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
     16 #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
     17 
     18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
     20 #include "clang/AST/ExprObjC.h"
     21 #include "clang/AST/ExprCXX.h"
     22 #include "llvm/ADT/PointerUnion.h"
     23 
     24 namespace clang {
     25 namespace ento {
     26 
     27 /// \brief Represents both explicit ObjC message expressions and implicit
     28 /// messages that are sent for handling properties in dot syntax.
     29 class ObjCMessage {
     30   const Expr *MsgOrPropE;
     31   const Expr *OriginE;
     32   bool IsPropSetter;
     33   SVal SetterArgV;
     34 
     35 protected:
     36   ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
     37     : MsgOrPropE(E), OriginE(origE),
     38       IsPropSetter(isSetter), SetterArgV(setArgV) { }
     39 
     40 public:
     41   ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
     42 
     43   ObjCMessage(const ObjCMessageExpr *E)
     44     : MsgOrPropE(E), OriginE(E) {
     45     assert(E && "should not be initialized with null expression");
     46   }
     47 
     48   bool isValid() const { return MsgOrPropE != 0; }
     49   bool isInvalid() const { return !isValid(); }
     50 
     51   bool isMessageExpr() const {
     52     return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
     53   }
     54 
     55   bool isPropertyGetter() const {
     56     return isValid() &&
     57            isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
     58   }
     59 
     60   bool isPropertySetter() const {
     61     return isValid() &&
     62            isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
     63   }
     64 
     65   const Expr *getOriginExpr() const { return OriginE; }
     66 
     67   QualType getType(ASTContext &ctx) const;
     68 
     69   QualType getResultType(ASTContext &ctx) const {
     70     assert(isValid() && "This ObjCMessage is uninitialized!");
     71     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     72       if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
     73         return MD->getResultType();
     74     return getType(ctx);
     75   }
     76 
     77   ObjCMethodFamily getMethodFamily() const;
     78 
     79   Selector getSelector() const;
     80 
     81   const Expr *getInstanceReceiver() const {
     82     assert(isValid() && "This ObjCMessage is uninitialized!");
     83     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     84       return msgE->getInstanceReceiver();
     85     const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     86     if (propE->isObjectReceiver())
     87       return propE->getBase();
     88     return 0;
     89   }
     90 
     91   SVal getInstanceReceiverSVal(const ProgramState *State,
     92                                const LocationContext *LC) const {
     93     assert(isValid() && "This ObjCMessage is uninitialized!");
     94     if (!isInstanceMessage())
     95       return UndefinedVal();
     96     if (const Expr *Ex = getInstanceReceiver())
     97       return State->getSValAsScalarOrLoc(Ex);
     98 
     99     // An instance message with no expression means we are sending to super.
    100     // In this case the object reference is the same as 'self'.
    101     const ImplicitParamDecl *SelfDecl = LC->getSelfDecl();
    102     assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
    103     return State->getSVal(State->getRegion(SelfDecl, LC));
    104   }
    105 
    106   bool isInstanceMessage() const {
    107     assert(isValid() && "This ObjCMessage is uninitialized!");
    108     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    109       return msgE->isInstanceMessage();
    110     const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
    111     // FIXME: 'super' may be super class.
    112     return propE->isObjectReceiver() || propE->isSuperReceiver();
    113   }
    114 
    115   const ObjCMethodDecl *getMethodDecl() const;
    116 
    117   const ObjCInterfaceDecl *getReceiverInterface() const;
    118 
    119   SourceLocation getSuperLoc() const {
    120     assert(isValid() && "This ObjCMessage is uninitialized!");
    121     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    122       return msgE->getSuperLoc();
    123     return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
    124   }
    125 
    126   const Expr *getMsgOrPropExpr() const {
    127     assert(isValid() && "This ObjCMessage is uninitialized!");
    128     return MsgOrPropE;
    129   }
    130 
    131   SourceRange getSourceRange() const {
    132     assert(isValid() && "This ObjCMessage is uninitialized!");
    133     return MsgOrPropE->getSourceRange();
    134   }
    135 
    136   unsigned getNumArgs() const {
    137     assert(isValid() && "This ObjCMessage is uninitialized!");
    138     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    139       return msgE->getNumArgs();
    140     return isPropertySetter() ? 1 : 0;
    141   }
    142 
    143   SVal getArgSVal(unsigned i, const ProgramState *state) const {
    144     assert(isValid() && "This ObjCMessage is uninitialized!");
    145     assert(i < getNumArgs() && "Invalid index for argument");
    146     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    147       return state->getSVal(msgE->getArg(i));
    148     assert(isPropertySetter());
    149     return SetterArgV;
    150   }
    151 
    152   QualType getArgType(unsigned i) const {
    153     assert(isValid() && "This ObjCMessage is uninitialized!");
    154     assert(i < getNumArgs() && "Invalid index for argument");
    155     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    156       return msgE->getArg(i)->getType();
    157     assert(isPropertySetter());
    158     return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
    159   }
    160 
    161   const Expr *getArgExpr(unsigned i) const;
    162 
    163   SourceRange getArgSourceRange(unsigned i) const {
    164     assert(isValid() && "This ObjCMessage is uninitialized!");
    165     assert(i < getNumArgs() && "Invalid index for argument");
    166     if (const Expr *argE = getArgExpr(i))
    167       return argE->getSourceRange();
    168     return OriginE->getSourceRange();
    169   }
    170 
    171   SourceRange getReceiverSourceRange() const {
    172     assert(isValid() && "This ObjCMessage is uninitialized!");
    173     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    174       return msgE->getReceiverRange();
    175 
    176     const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
    177     if (propE->isObjectReceiver())
    178       return propE->getBase()->getSourceRange();
    179 
    180     // FIXME: This isn't a range.
    181     return propE->getReceiverLocation();
    182   }
    183 };
    184 
    185 class ObjCPropertyGetter : public ObjCMessage {
    186 public:
    187   ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
    188     : ObjCMessage(propE, originE, false, SVal()) {
    189     assert(propE && originE &&
    190            "should not be initialized with null expressions");
    191   }
    192 };
    193 
    194 class ObjCPropertySetter : public ObjCMessage {
    195 public:
    196   ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
    197                      SVal argV)
    198     : ObjCMessage(propE, storeE, true, argV) {
    199     assert(propE && storeE &&"should not be initialized with null expressions");
    200   }
    201 };
    202 
    203 /// \brief Common wrapper for a call expression, ObjC message, or C++
    204 /// constructor, mainly to provide a common interface for their arguments.
    205 class CallOrObjCMessage {
    206   llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
    207   ObjCMessage Msg;
    208   const ProgramState *State;
    209 public:
    210   CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
    211     : CallE(callE), State(state) {}
    212   CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state)
    213     : CallE(consE), State(state) {}
    214   CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
    215     : CallE((CallExpr *)0), Msg(msg), State(state) {}
    216 
    217   QualType getResultType(ASTContext &ctx) const;
    218 
    219   bool isFunctionCall() const {
    220     return CallE && CallE.is<const CallExpr *>();
    221   }
    222 
    223   bool isCXXConstructExpr() const {
    224     return CallE && CallE.is<const CXXConstructExpr *>();
    225   }
    226 
    227   bool isObjCMessage() const {
    228     return !CallE;
    229   }
    230 
    231   bool isCXXCall() const {
    232     const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>();
    233     return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE);
    234   }
    235 
    236   const Expr *getOriginExpr() const {
    237     if (!CallE)
    238       return Msg.getOriginExpr();
    239     if (const CXXConstructExpr *Ctor =
    240           CallE.dyn_cast<const CXXConstructExpr *>())
    241       return Ctor;
    242     return CallE.get<const CallExpr *>();
    243   }
    244 
    245   SVal getFunctionCallee() const;
    246   SVal getCXXCallee() const;
    247   SVal getInstanceMessageReceiver(const LocationContext *LC) const;
    248 
    249   unsigned getNumArgs() const {
    250     if (!CallE)
    251       return Msg.getNumArgs();
    252     if (const CXXConstructExpr *Ctor =
    253           CallE.dyn_cast<const CXXConstructExpr *>())
    254       return Ctor->getNumArgs();
    255     return CallE.get<const CallExpr *>()->getNumArgs();
    256   }
    257 
    258   SVal getArgSVal(unsigned i) const {
    259     assert(i < getNumArgs());
    260     if (!CallE)
    261       return Msg.getArgSVal(i, State);
    262     return State->getSVal(getArg(i));
    263   }
    264 
    265   const Expr *getArg(unsigned i) const {
    266     assert(i < getNumArgs());
    267     if (!CallE)
    268       return Msg.getArgExpr(i);
    269     if (const CXXConstructExpr *Ctor =
    270           CallE.dyn_cast<const CXXConstructExpr *>())
    271       return Ctor->getArg(i);
    272     return CallE.get<const CallExpr *>()->getArg(i);
    273   }
    274 
    275   SourceRange getArgSourceRange(unsigned i) const {
    276     assert(i < getNumArgs());
    277     if (CallE)
    278       return getArg(i)->getSourceRange();
    279     return Msg.getArgSourceRange(i);
    280   }
    281 
    282   SourceRange getReceiverSourceRange() const {
    283     assert(isObjCMessage());
    284     return Msg.getReceiverSourceRange();
    285   }
    286 };
    287 
    288 }
    289 }
    290 
    291 #endif
    292