Home | History | Annotate | Download | only in Core
      1 //===- ObjCMessage.cpp - 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 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
     16 
     17 using namespace clang;
     18 using namespace ento;
     19 
     20 QualType ObjCMessage::getType(ASTContext &ctx) const {
     21   assert(isValid() && "This ObjCMessage is uninitialized!");
     22   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     23     return msgE->getType();
     24   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     25   if (isPropertySetter())
     26     return ctx.VoidTy;
     27   return propE->getType();
     28 }
     29 
     30 Selector ObjCMessage::getSelector() const {
     31   assert(isValid() && "This ObjCMessage is uninitialized!");
     32   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     33     return msgE->getSelector();
     34   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     35   if (isPropertySetter())
     36     return propE->getSetterSelector();
     37   return propE->getGetterSelector();
     38 }
     39 
     40 ObjCMethodFamily ObjCMessage::getMethodFamily() const {
     41   assert(isValid() && "This ObjCMessage is uninitialized!");
     42   // Case 1.  Explicit message send.
     43   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     44     return msgE->getMethodFamily();
     45 
     46   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     47 
     48   // Case 2.  Reference to implicit property.
     49   if (propE->isImplicitProperty()) {
     50     if (isPropertySetter())
     51       return propE->getImplicitPropertySetter()->getMethodFamily();
     52     else
     53       return propE->getImplicitPropertyGetter()->getMethodFamily();
     54   }
     55 
     56   // Case 3.  Reference to explicit property.
     57   const ObjCPropertyDecl *prop = propE->getExplicitProperty();
     58   if (isPropertySetter()) {
     59     if (prop->getSetterMethodDecl())
     60       return prop->getSetterMethodDecl()->getMethodFamily();
     61     return prop->getSetterName().getMethodFamily();
     62   } else {
     63     if (prop->getGetterMethodDecl())
     64       return prop->getGetterMethodDecl()->getMethodFamily();
     65     return prop->getGetterName().getMethodFamily();
     66   }
     67 }
     68 
     69 const ObjCMethodDecl *ObjCMessage::getMethodDecl() const {
     70   assert(isValid() && "This ObjCMessage is uninitialized!");
     71   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     72     return msgE->getMethodDecl();
     73   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     74   if (propE->isImplicitProperty())
     75     return isPropertySetter() ? propE->getImplicitPropertySetter()
     76                               : propE->getImplicitPropertyGetter();
     77   return 0;
     78 }
     79 
     80 const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const {
     81   assert(isValid() && "This ObjCMessage is uninitialized!");
     82   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
     83     return msgE->getReceiverInterface();
     84   const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
     85   if (propE->isClassReceiver())
     86     return propE->getClassReceiver();
     87   QualType recT;
     88   if (const Expr *recE = getInstanceReceiver())
     89     recT = recE->getType();
     90   else {
     91     assert(propE->isSuperReceiver());
     92     recT = propE->getSuperReceiverType();
     93   }
     94   if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>())
     95     return Ptr->getInterfaceDecl();
     96   return 0;
     97 }
     98 
     99 const Expr *ObjCMessage::getArgExpr(unsigned i) const {
    100   assert(isValid() && "This ObjCMessage is uninitialized!");
    101   assert(i < getNumArgs() && "Invalid index for argument");
    102   if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
    103     return msgE->getArg(i);
    104   assert(isPropertySetter());
    105   if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE))
    106     if (bop->isAssignmentOp())
    107       return bop->getRHS();
    108   return 0;
    109 }
    110 
    111 QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
    112   QualType resultTy;
    113   bool isLVal = false;
    114 
    115   if (isObjCMessage()) {
    116     isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) &&
    117              Msg.getOriginExpr()->isLValue();
    118     resultTy = Msg.getResultType(ctx);
    119   } else if (const CXXConstructExpr *Ctor =
    120               CallE.dyn_cast<const CXXConstructExpr *>()) {
    121     resultTy = Ctor->getType();
    122   } else {
    123     const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
    124 
    125     isLVal = FunctionCall->isLValue();
    126     const Expr *Callee = FunctionCall->getCallee();
    127     if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
    128       resultTy = FD->getResultType();
    129     else
    130       resultTy = FunctionCall->getType();
    131   }
    132 
    133   if (isLVal)
    134     resultTy = ctx.getPointerType(resultTy);
    135 
    136   return resultTy;
    137 }
    138 
    139 SVal CallOrObjCMessage::getFunctionCallee() const {
    140   assert(isFunctionCall());
    141   assert(!isCXXCall());
    142   const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
    143   return State->getSVal(Fun);
    144 }
    145 
    146 SVal CallOrObjCMessage::getCXXCallee() const {
    147   assert(isCXXCall());
    148   const CallExpr *ActualCall = CallE.get<const CallExpr *>();
    149   const Expr *callee =
    150     cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
    151 
    152   // FIXME: Will eventually need to cope with member pointers.  This is
    153   // a limitation in getImplicitObjectArgument().
    154   if (!callee)
    155     return UnknownVal();
    156 
    157   return State->getSVal(callee);
    158 }
    159 
    160 SVal
    161 CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
    162   assert(isObjCMessage());
    163   return Msg.getInstanceReceiverSVal(State, LC);
    164 }
    165