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 {
116 isLVal = CallE->isLValue();
117 const Expr *Callee = CallE->getCallee();
118 if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
119 resultTy = FD->getResultType();
121 resultTy = CallE->getType();
124 isLVal = isa<ObjCMessageExpr>(Msg.getOriginExpr()) &&
125 Msg.getOriginExpr()->isLValue();
126 resultTy = Msg.getResultType(ctx);
130 resultTy = ctx.getPointerType(resultTy);
135 SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const {
136 assert(i < getNumArgs());
137 if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i));
138 QualType argT = Msg.getArgType(i);
139 if (Loc::isLocType(argT) || argT->isIntegerType())
140 return Msg.getArgSVal(i, State);
144 SVal CallOrObjCMessage::getFunctionCallee() const {
145 assert(isFunctionCall());
146 assert(!isCXXCall());
147 const Expr *callee = CallE->getCallee()->IgnoreParenCasts();
148 return State->getSVal(callee);
151 SVal CallOrObjCMessage::getCXXCallee() const {
154 cast<CXXMemberCallExpr>(CallE)->getImplicitObjectArgument();
155 return State->getSVal(callee);