| //===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines ObjCMessage which serves as a common wrapper for ObjC |
| // message expressions or implicit messages for loading/storing ObjC properties. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" |
| |
| using namespace clang; |
| using namespace ento; |
| |
| QualType ObjCMessage::getType(ASTContext &ctx) const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getType(); |
| const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); |
| if (isPropertySetter()) |
| return ctx.VoidTy; |
| return propE->getType(); |
| } |
| |
| Selector ObjCMessage::getSelector() const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getSelector(); |
| const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); |
| if (isPropertySetter()) |
| return propE->getSetterSelector(); |
| return propE->getGetterSelector(); |
| } |
| |
| ObjCMethodFamily ObjCMessage::getMethodFamily() const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| // Case 1. Explicit message send. |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getMethodFamily(); |
| |
| const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); |
| |
| // Case 2. Reference to implicit property. |
| if (propE->isImplicitProperty()) { |
| if (isPropertySetter()) |
| return propE->getImplicitPropertySetter()->getMethodFamily(); |
| else |
| return propE->getImplicitPropertyGetter()->getMethodFamily(); |
| } |
| |
| // Case 3. Reference to explicit property. |
| const ObjCPropertyDecl *prop = propE->getExplicitProperty(); |
| if (isPropertySetter()) { |
| if (prop->getSetterMethodDecl()) |
| return prop->getSetterMethodDecl()->getMethodFamily(); |
| return prop->getSetterName().getMethodFamily(); |
| } else { |
| if (prop->getGetterMethodDecl()) |
| return prop->getGetterMethodDecl()->getMethodFamily(); |
| return prop->getGetterName().getMethodFamily(); |
| } |
| } |
| |
| const ObjCMethodDecl *ObjCMessage::getMethodDecl() const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getMethodDecl(); |
| const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); |
| if (propE->isImplicitProperty()) |
| return isPropertySetter() ? propE->getImplicitPropertySetter() |
| : propE->getImplicitPropertyGetter(); |
| return 0; |
| } |
| |
| const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getReceiverInterface(); |
| const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE); |
| if (propE->isClassReceiver()) |
| return propE->getClassReceiver(); |
| QualType recT; |
| if (const Expr *recE = getInstanceReceiver()) |
| recT = recE->getType(); |
| else { |
| assert(propE->isSuperReceiver()); |
| recT = propE->getSuperReceiverType(); |
| } |
| if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>()) |
| return Ptr->getInterfaceDecl(); |
| return 0; |
| } |
| |
| const Expr *ObjCMessage::getArgExpr(unsigned i) const { |
| assert(isValid() && "This ObjCMessage is uninitialized!"); |
| assert(i < getNumArgs() && "Invalid index for argument"); |
| if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE)) |
| return msgE->getArg(i); |
| assert(isPropertySetter()); |
| if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE)) |
| if (bop->isAssignmentOp()) |
| return bop->getRHS(); |
| return 0; |
| } |
| |
| QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { |
| if (CallE) { |
| const Expr *Callee = CallE->getCallee(); |
| if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl()) |
| return FD->getResultType(); |
| return CallE->getType(); |
| } |
| return Msg.getResultType(ctx); |
| } |
| |
| SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const { |
| assert(i < getNumArgs()); |
| if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i)); |
| QualType argT = Msg.getArgType(i); |
| if (Loc::isLocType(argT) || argT->isIntegerType()) |
| return Msg.getArgSVal(i, State); |
| return UnknownVal(); |
| } |