]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.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/GRState.h"
20 #include "clang/AST/ExprObjC.h"
21
22 namespace clang {
23 namespace ento {
24
25 /// \brief Represents both explicit ObjC message expressions and implicit
26 /// messages that are sent for handling properties in dot syntax.
27 class ObjCMessage {
28   const Expr *MsgOrPropE;
29   const Expr *OriginE;
30   bool IsPropSetter;
31   SVal SetterArgV;
32
33 protected:
34   ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
35     : MsgOrPropE(E), OriginE(origE),
36       IsPropSetter(isSetter), SetterArgV(setArgV) { }
37
38 public:
39   ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
40
41   ObjCMessage(const ObjCMessageExpr *E)
42     : MsgOrPropE(E), OriginE(E) {
43     assert(E && "should not be initialized with null expression");
44   }
45
46   bool isValid() const { return MsgOrPropE != 0; }
47   bool isInvalid() const { return !isValid(); }
48
49   bool isMessageExpr() const {
50     return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
51   }
52
53   bool isPropertyGetter() const {
54     return isValid() &&
55            isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
56   }
57
58   bool isPropertySetter() const {
59     return isValid() &&
60            isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
61   }
62   
63   const Expr *getOriginExpr() const { return OriginE; }
64
65   QualType getType(ASTContext &ctx) const;
66
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();
72     return getType(ctx);
73   }
74
75   ObjCMethodFamily getMethodFamily() const;
76
77   Selector getSelector() const;
78
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();
86     return 0;
87   }
88
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();
96   }
97
98   const ObjCMethodDecl *getMethodDecl() const;
99   
100   const ObjCInterfaceDecl *getReceiverInterface() const;
101
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();
107   }
108
109    SourceRange getSourceRange() const {
110      assert(isValid() && "This ObjCMessage is uninitialized!");
111     return MsgOrPropE->getSourceRange();
112   }
113
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;
119    }
120
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());
127      return SetterArgV;
128    }
129
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();
137    }
138    
139    const Expr *getArgExpr(unsigned i) const;
140
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();
147    }
148 };
149
150 class ObjCPropertyGetter : public ObjCMessage {
151 public:
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");
156   }
157 };
158
159 class ObjCPropertySetter : public ObjCMessage {
160 public:
161   ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
162                      SVal argV)
163     : ObjCMessage(propE, storeE, true, argV) {
164     assert(propE && storeE &&"should not be initialized with null expressions");
165   }
166 };
167
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;
172   ObjCMessage Msg;
173   const GRState *State;
174 public:
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) {}
179
180   QualType getResultType(ASTContext &ctx) const;
181   
182   bool isFunctionCall() const {
183     return (bool) CallE;
184   }
185   
186   bool isCXXCall() const {
187     return CallE && isa<CXXMemberCallExpr>(CallE);
188   }
189   
190   SVal getFunctionCallee() const;
191   SVal getCXXCallee() const;
192
193   unsigned getNumArgs() const {
194     if (CallE) return CallE->getNumArgs();
195     return Msg.getNumArgs();
196   }
197
198   SVal getArgSVal(unsigned i) const {
199     assert(i < getNumArgs());
200     if (CallE) 
201       return State->getSVal(CallE->getArg(i));
202     return Msg.getArgSVal(i, State);
203   }
204
205   SVal getArgSValAsScalarOrLoc(unsigned i) const;
206
207   const Expr *getArg(unsigned i) const {
208     assert(i < getNumArgs());
209     if (CallE)
210       return CallE->getArg(i);
211     return Msg.getArgExpr(i);
212   }
213
214   SourceRange getArgSourceRange(unsigned i) const {
215     assert(i < getNumArgs());
216     if (CallE)
217       return CallE->getArg(i)->getSourceRange();
218     return Msg.getArgSourceRange(i);
219   }
220 };
221
222 }
223 }
224
225 #endif