1 //===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines ObjCMessage which serves as a common wrapper for ObjC
11 // message expressions or implicit messages for loading/storing ObjC properties.
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
17 using namespace clang;
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())
27 return propE->getType();
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();
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();
46 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
48 // Case 2. Reference to implicit property.
49 if (propE->isImplicitProperty()) {
50 if (isPropertySetter())
51 return propE->getImplicitPropertySetter()->getMethodFamily();
53 return propE->getImplicitPropertyGetter()->getMethodFamily();
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();
63 if (prop->getGetterMethodDecl())
64 return prop->getGetterMethodDecl()->getMethodFamily();
65 return prop->getGetterName().getMethodFamily();
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();
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();
88 if (const Expr *recE = getInstanceReceiver())
89 recT = recE->getType();
91 assert(propE->isSuperReceiver());
92 recT = propE->getSuperReceiverType();
94 if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>())
95 return Ptr->getInterfaceDecl();
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();
111 QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
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();
123 const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
125 isLVal = FunctionCall->isLValue();
126 const Expr *Callee = FunctionCall->getCallee();
127 if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
128 resultTy = FD->getResultType();
130 resultTy = FunctionCall->getType();
134 resultTy = ctx.getPointerType(resultTy);
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);
146 SVal CallOrObjCMessage::getCXXCallee() const {
148 const CallExpr *ActualCall = CallE.get<const CallExpr *>();
150 cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
152 // FIXME: Will eventually need to cope with member pointers. This is
153 // a limitation in getImplicitObjectArgument().
157 return State->getSVal(callee);
161 CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
162 assert(isObjCMessage());
163 return Msg.getInstanceReceiverSVal(State, LC);