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/ProgramState.h"
20 #include "clang/AST/ExprObjC.h"
21 #include "clang/AST/ExprCXX.h"
22 #include "llvm/ADT/PointerUnion.h"
27 /// \brief Represents both explicit ObjC message expressions and implicit
28 /// messages that are sent for handling properties in dot syntax.
30 const Expr *MsgOrPropE;
36 ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
37 : MsgOrPropE(E), OriginE(origE),
38 IsPropSetter(isSetter), SetterArgV(setArgV) { }
41 ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
43 ObjCMessage(const ObjCMessageExpr *E)
44 : MsgOrPropE(E), OriginE(E) {
45 assert(E && "should not be initialized with null expression");
48 bool isValid() const { return MsgOrPropE != 0; }
49 bool isInvalid() const { return !isValid(); }
51 bool isMessageExpr() const {
52 return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
55 bool isPropertyGetter() const {
57 isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
60 bool isPropertySetter() const {
62 isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
65 const Expr *getOriginExpr() const { return OriginE; }
67 QualType getType(ASTContext &ctx) const;
69 QualType getResultType(ASTContext &ctx) const {
70 assert(isValid() && "This ObjCMessage is uninitialized!");
71 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
72 if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
73 return MD->getResultType();
77 ObjCMethodFamily getMethodFamily() const;
79 Selector getSelector() const;
81 const Expr *getInstanceReceiver() const {
82 assert(isValid() && "This ObjCMessage is uninitialized!");
83 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
84 return msgE->getInstanceReceiver();
85 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
86 if (propE->isObjectReceiver())
87 return propE->getBase();
91 SVal getInstanceReceiverSVal(const ProgramState *State,
92 const LocationContext *LC) const {
93 assert(isValid() && "This ObjCMessage is uninitialized!");
94 if (!isInstanceMessage())
95 return UndefinedVal();
96 if (const Expr *Ex = getInstanceReceiver())
97 return State->getSValAsScalarOrLoc(Ex);
99 // An instance message with no expression means we are sending to super.
100 // In this case the object reference is the same as 'self'.
101 const ImplicitParamDecl *SelfDecl = LC->getSelfDecl();
102 assert(SelfDecl && "No message receiver Expr, but not in an ObjC method");
103 return State->getSVal(State->getRegion(SelfDecl, LC));
106 bool isInstanceMessage() const {
107 assert(isValid() && "This ObjCMessage is uninitialized!");
108 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
109 return msgE->isInstanceMessage();
110 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
111 // FIXME: 'super' may be super class.
112 return propE->isObjectReceiver() || propE->isSuperReceiver();
115 const ObjCMethodDecl *getMethodDecl() const;
117 const ObjCInterfaceDecl *getReceiverInterface() const;
119 SourceLocation getSuperLoc() const {
120 assert(isValid() && "This ObjCMessage is uninitialized!");
121 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
122 return msgE->getSuperLoc();
123 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
126 const Expr *getMsgOrPropExpr() const {
127 assert(isValid() && "This ObjCMessage is uninitialized!");
131 SourceRange getSourceRange() const {
132 assert(isValid() && "This ObjCMessage is uninitialized!");
133 return MsgOrPropE->getSourceRange();
136 unsigned getNumArgs() const {
137 assert(isValid() && "This ObjCMessage is uninitialized!");
138 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
139 return msgE->getNumArgs();
140 return isPropertySetter() ? 1 : 0;
143 SVal getArgSVal(unsigned i, const ProgramState *state) const {
144 assert(isValid() && "This ObjCMessage is uninitialized!");
145 assert(i < getNumArgs() && "Invalid index for argument");
146 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
147 return state->getSVal(msgE->getArg(i));
148 assert(isPropertySetter());
152 QualType getArgType(unsigned i) const {
153 assert(isValid() && "This ObjCMessage is uninitialized!");
154 assert(i < getNumArgs() && "Invalid index for argument");
155 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
156 return msgE->getArg(i)->getType();
157 assert(isPropertySetter());
158 return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
161 const Expr *getArgExpr(unsigned i) const;
163 SourceRange getArgSourceRange(unsigned i) const {
164 assert(isValid() && "This ObjCMessage is uninitialized!");
165 assert(i < getNumArgs() && "Invalid index for argument");
166 if (const Expr *argE = getArgExpr(i))
167 return argE->getSourceRange();
168 return OriginE->getSourceRange();
171 SourceRange getReceiverSourceRange() const {
172 assert(isValid() && "This ObjCMessage is uninitialized!");
173 if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
174 return msgE->getReceiverRange();
176 const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
177 if (propE->isObjectReceiver())
178 return propE->getBase()->getSourceRange();
180 // FIXME: This isn't a range.
181 return propE->getReceiverLocation();
185 class ObjCPropertyGetter : public ObjCMessage {
187 ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
188 : ObjCMessage(propE, originE, false, SVal()) {
189 assert(propE && originE &&
190 "should not be initialized with null expressions");
194 class ObjCPropertySetter : public ObjCMessage {
196 ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
198 : ObjCMessage(propE, storeE, true, argV) {
199 assert(propE && storeE &&"should not be initialized with null expressions");
203 /// \brief Common wrapper for a call expression, ObjC message, or C++
204 /// constructor, mainly to provide a common interface for their arguments.
205 class CallOrObjCMessage {
206 llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
208 const ProgramState *State;
210 CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
211 : CallE(callE), State(state) {}
212 CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state)
213 : CallE(consE), State(state) {}
214 CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
215 : CallE((CallExpr *)0), Msg(msg), State(state) {}
217 QualType getResultType(ASTContext &ctx) const;
219 bool isFunctionCall() const {
220 return CallE && CallE.is<const CallExpr *>();
223 bool isCXXConstructExpr() const {
224 return CallE && CallE.is<const CXXConstructExpr *>();
227 bool isObjCMessage() const {
231 bool isCXXCall() const {
232 const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>();
233 return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE);
236 const Expr *getOriginExpr() const {
238 return Msg.getOriginExpr();
239 if (const CXXConstructExpr *Ctor =
240 CallE.dyn_cast<const CXXConstructExpr *>())
242 return CallE.get<const CallExpr *>();
245 SVal getFunctionCallee() const;
246 SVal getCXXCallee() const;
247 SVal getInstanceMessageReceiver(const LocationContext *LC) const;
249 unsigned getNumArgs() const {
251 return Msg.getNumArgs();
252 if (const CXXConstructExpr *Ctor =
253 CallE.dyn_cast<const CXXConstructExpr *>())
254 return Ctor->getNumArgs();
255 return CallE.get<const CallExpr *>()->getNumArgs();
258 SVal getArgSVal(unsigned i) const {
259 assert(i < getNumArgs());
261 return Msg.getArgSVal(i, State);
262 return State->getSVal(getArg(i));
265 const Expr *getArg(unsigned i) const {
266 assert(i < getNumArgs());
268 return Msg.getArgExpr(i);
269 if (const CXXConstructExpr *Ctor =
270 CallE.dyn_cast<const CXXConstructExpr *>())
271 return Ctor->getArg(i);
272 return CallE.get<const CallExpr *>()->getArg(i);
275 SourceRange getArgSourceRange(unsigned i) const {
276 assert(i < getNumArgs());
278 return getArg(i)->getSourceRange();
279 return Msg.getArgSourceRange(i);
282 SourceRange getReceiverSourceRange() const {
283 assert(isObjCMessage());
284 return Msg.getReceiverSourceRange();