]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / include / clang / StaticAnalyzer / Core / PathSensitive / ObjCMessage.h
1 //===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- C++ -*--//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines ObjCMessage which serves as a common wrapper for ObjC
11 // message expressions or implicit messages for loading/storing ObjC properties.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
16 #define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
17
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"
23
24 namespace clang {
25 namespace ento {
26
27 /// \brief Represents both explicit ObjC message expressions and implicit
28 /// messages that are sent for handling properties in dot syntax.
29 class ObjCMessage {
30   const Expr *MsgOrPropE;
31   const Expr *OriginE;
32   bool IsPropSetter;
33   SVal SetterArgV;
34
35 protected:
36   ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
37     : MsgOrPropE(E), OriginE(origE),
38       IsPropSetter(isSetter), SetterArgV(setArgV) { }
39
40 public:
41   ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
42
43   ObjCMessage(const ObjCMessageExpr *E)
44     : MsgOrPropE(E), OriginE(E) {
45     assert(E && "should not be initialized with null expression");
46   }
47
48   bool isValid() const { return MsgOrPropE != 0; }
49   bool isInvalid() const { return !isValid(); }
50
51   bool isMessageExpr() const {
52     return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
53   }
54
55   bool isPropertyGetter() const {
56     return isValid() &&
57            isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
58   }
59
60   bool isPropertySetter() const {
61     return isValid() &&
62            isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
63   }
64   
65   const Expr *getOriginExpr() const { return OriginE; }
66
67   QualType getType(ASTContext &ctx) const;
68
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();
74     return getType(ctx);
75   }
76
77   ObjCMethodFamily getMethodFamily() const;
78
79   Selector getSelector() const;
80
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();
88     return 0;
89   }
90
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);
98
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));
104   }
105
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();
113   }
114
115   const ObjCMethodDecl *getMethodDecl() const;
116
117   const ObjCInterfaceDecl *getReceiverInterface() const;
118
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();
124   }
125
126   const Expr *getMsgOrPropExpr() const {
127     assert(isValid() && "This ObjCMessage is uninitialized!");
128     return MsgOrPropE;
129   }
130
131   SourceRange getSourceRange() const {
132     assert(isValid() && "This ObjCMessage is uninitialized!");
133     return MsgOrPropE->getSourceRange();
134   }
135
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;
141   }
142
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());
149     return SetterArgV;
150   }
151
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();
159   }
160
161   const Expr *getArgExpr(unsigned i) const;
162
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();
169   }
170
171   SourceRange getReceiverSourceRange() const {
172     assert(isValid() && "This ObjCMessage is uninitialized!");
173     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
174       return msgE->getReceiverRange();
175
176     const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
177     if (propE->isObjectReceiver())
178       return propE->getBase()->getSourceRange();
179
180     // FIXME: This isn't a range.
181     return propE->getReceiverLocation();
182   }
183 };
184
185 class ObjCPropertyGetter : public ObjCMessage {
186 public:
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");
191   }
192 };
193
194 class ObjCPropertySetter : public ObjCMessage {
195 public:
196   ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
197                      SVal argV)
198     : ObjCMessage(propE, storeE, true, argV) {
199     assert(propE && storeE &&"should not be initialized with null expressions");
200   }
201 };
202
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;
207   ObjCMessage Msg;
208   const ProgramState *State;
209 public:
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) {}
216
217   QualType getResultType(ASTContext &ctx) const;
218   
219   bool isFunctionCall() const {
220     return CallE && CallE.is<const CallExpr *>();
221   }
222
223   bool isCXXConstructExpr() const {
224     return CallE && CallE.is<const CXXConstructExpr *>();
225   }
226
227   bool isObjCMessage() const {
228     return !CallE;
229   }
230
231   bool isCXXCall() const {
232     const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>();
233     return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE);
234   }
235
236   const Expr *getOriginExpr() const {
237     if (!CallE)
238       return Msg.getOriginExpr();
239     if (const CXXConstructExpr *Ctor =
240           CallE.dyn_cast<const CXXConstructExpr *>())
241       return Ctor;
242     return CallE.get<const CallExpr *>();
243   }
244   
245   SVal getFunctionCallee() const;
246   SVal getCXXCallee() const;
247   SVal getInstanceMessageReceiver(const LocationContext *LC) const;
248
249   unsigned getNumArgs() const {
250     if (!CallE)
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();
256   }
257
258   SVal getArgSVal(unsigned i) const {
259     assert(i < getNumArgs());
260     if (!CallE)
261       return Msg.getArgSVal(i, State);
262     return State->getSVal(getArg(i));
263   }
264
265   const Expr *getArg(unsigned i) const {
266     assert(i < getNumArgs());
267     if (!CallE)
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);
273   }
274
275   SourceRange getArgSourceRange(unsigned i) const {
276     assert(i < getNumArgs());
277     if (CallE)
278       return getArg(i)->getSourceRange();
279     return Msg.getArgSourceRange(i);
280   }
281
282   SourceRange getReceiverSourceRange() const {
283     assert(isObjCMessage());
284     return Msg.getReceiverSourceRange();
285   }
286 };
287
288 }
289 }
290
291 #endif