1 //===- ObjCMessage.h - 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 #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
16 #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
20 #include "clang/AST/ExprObjC.h"
25 /// \brief Represents both explicit ObjC message expressions and implicit
26 /// messages that are sent for handling properties in dot syntax.
28 const Expr *MsgOrPropE;
34 ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
35 : MsgOrPropE(E), OriginE(origE),
36 IsPropSetter(isSetter), SetterArgV(setArgV) { }
39 ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
41 ObjCMessage(const ObjCMessageExpr *E)
42 : MsgOrPropE(E), OriginE(E) {
43 assert(E && "should not be initialized with null expression");
46 bool isValid() const { return MsgOrPropE != 0; }
47 bool isInvalid() const { return !isValid(); }
49 bool isMessageExpr() const {
50 return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
53 bool isPropertyGetter() const {
55 isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
58 bool isPropertySetter() const {
60 isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
63 const Expr *getOriginExpr() const { return OriginE; }
65 QualType getType(ASTContext &ctx) const;
67 QualType getResultType(ASTContext &ctx) const {
68 assert(isValid() && "This ObjCMessage is uninitialized!");
69 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
70 if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
71 return MD->getResultType();
75 ObjCMethodFamily getMethodFamily() const;
77 Selector getSelector() const;
79 const Expr *getInstanceReceiver() const {
80 assert(isValid() && "This ObjCMessage is uninitialized!");
81 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
82 return msgE->getInstanceReceiver();
83 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
84 if (propE->isObjectReceiver())
85 return propE->getBase();
89 bool isInstanceMessage() const {
90 assert(isValid() && "This ObjCMessage is uninitialized!");
91 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
92 return msgE->isInstanceMessage();
93 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
94 // FIXME: 'super' may be super class.
95 return propE->isObjectReceiver() || propE->isSuperReceiver();
98 const ObjCMethodDecl *getMethodDecl() const;
100 const ObjCInterfaceDecl *getReceiverInterface() const;
102 SourceLocation getSuperLoc() const {
103 assert(isValid() && "This ObjCMessage is uninitialized!");
104 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
105 return msgE->getSuperLoc();
106 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
109 SourceRange getSourceRange() const {
110 assert(isValid() && "This ObjCMessage is uninitialized!");
111 return MsgOrPropE->getSourceRange();
114 unsigned getNumArgs() const {
115 assert(isValid() && "This ObjCMessage is uninitialized!");
116 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
117 return msgE->getNumArgs();
118 return isPropertySetter() ? 1 : 0;
121 SVal getArgSVal(unsigned i, const GRState *state) const {
122 assert(isValid() && "This ObjCMessage is uninitialized!");
123 assert(i < getNumArgs() && "Invalid index for argument");
124 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
125 return state->getSVal(msgE->getArg(i));
126 assert(isPropertySetter());
130 QualType getArgType(unsigned i) const {
131 assert(isValid() && "This ObjCMessage is uninitialized!");
132 assert(i < getNumArgs() && "Invalid index for argument");
133 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
134 return msgE->getArg(i)->getType();
135 assert(isPropertySetter());
136 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
139 const Expr *getArgExpr(unsigned i) const;
141 SourceRange getArgSourceRange(unsigned i) const {
142 assert(isValid() && "This ObjCMessage is uninitialized!");
143 assert(i < getNumArgs() && "Invalid index for argument");
144 if (const Expr *argE = getArgExpr(i))
145 return argE->getSourceRange();
146 return OriginE->getSourceRange();
150 class ObjCPropertyGetter : public ObjCMessage {
152 ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
153 : ObjCMessage(propE, originE, false, SVal()) {
154 assert(propE && originE &&
155 "should not be initialized with null expressions");
159 class ObjCPropertySetter : public ObjCMessage {
161 ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
163 : ObjCMessage(propE, storeE, true, argV) {
164 assert(propE && storeE &&"should not be initialized with null expressions");
168 /// \brief Common wrapper for a call expression or an ObjC message, mainly to
169 /// provide a common interface for handling their arguments.
170 class CallOrObjCMessage {
171 const CallExpr *CallE;
173 const GRState *State;
175 CallOrObjCMessage(const CallExpr *callE, const GRState *state)
176 : CallE(callE), State(state) {}
177 CallOrObjCMessage(const ObjCMessage &msg, const GRState *state)
178 : CallE(0), Msg(msg), State(state) {}
180 QualType getResultType(ASTContext &ctx) const;
182 bool isFunctionCall() const {
186 bool isCXXCall() const {
187 return CallE && isa<CXXMemberCallExpr>(CallE);
190 SVal getFunctionCallee() const;
191 SVal getCXXCallee() const;
193 unsigned getNumArgs() const {
194 if (CallE) return CallE->getNumArgs();
195 return Msg.getNumArgs();
198 SVal getArgSVal(unsigned i) const {
199 assert(i < getNumArgs());
201 return State->getSVal(CallE->getArg(i));
202 return Msg.getArgSVal(i, State);
205 SVal getArgSValAsScalarOrLoc(unsigned i) const;
207 const Expr *getArg(unsigned i) const {
208 assert(i < getNumArgs());
210 return CallE->getArg(i);
211 return Msg.getArgExpr(i);
214 SourceRange getArgSourceRange(unsigned i) const {
215 assert(i < getNumArgs());
217 return CallE->getArg(i)->getSourceRange();
218 return Msg.getArgSourceRange(i);