ExprObjC.h revision e66f4e3e3ae9d7d11b0c302211066fad69228aba
1//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 the ExprObjC interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_EXPROBJC_H
15#define LLVM_CLANG_AST_EXPROBJC_H
16
17#include "clang/AST/Expr.h"
18#include "clang/Basic/IdentifierTable.h"
19
20namespace clang {
21  class IdentifierInfo;
22  class ASTContext;
23  class ObjCMethodDecl;
24  class ObjCPropertyDecl;
25
26/// ObjCStringLiteral, used for Objective-C string literals
27/// i.e. @"foo".
28class ObjCStringLiteral : public Expr {
29  StringLiteral *String;
30  SourceLocation AtLoc;
31public:
32  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
33    : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {}
34
35  StringLiteral* getString() { return String; }
36
37  const StringLiteral* getString() const { return String; }
38
39  SourceLocation getAtLoc() const { return AtLoc; }
40
41  virtual SourceRange getSourceRange() const {
42    return SourceRange(AtLoc, String->getLocEnd());
43  }
44
45  static bool classof(const Stmt *T) {
46    return T->getStmtClass() == ObjCStringLiteralClass;
47  }
48  static bool classof(const ObjCStringLiteral *) { return true; }
49
50  // Iterators
51  virtual child_iterator child_begin();
52  virtual child_iterator child_end();
53
54  virtual void EmitImpl(llvm::Serializer& S) const;
55  static ObjCStringLiteral* CreateImpl(llvm::Deserializer& D, ASTContext& C);
56};
57
58/// ObjCEncodeExpr, used for @encode in Objective-C.
59class ObjCEncodeExpr : public Expr {
60  QualType EncType;
61  SourceLocation AtLoc, RParenLoc;
62public:
63  ObjCEncodeExpr(QualType T, QualType ET,
64                 SourceLocation at, SourceLocation rp)
65    : Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {}
66
67  SourceLocation getAtLoc() const { return AtLoc; }
68  SourceLocation getRParenLoc() const { return RParenLoc; }
69
70  virtual SourceRange getSourceRange() const {
71    return SourceRange(AtLoc, RParenLoc);
72  }
73
74  QualType getEncodedType() const { return EncType; }
75
76  static bool classof(const Stmt *T) {
77    return T->getStmtClass() == ObjCEncodeExprClass;
78  }
79  static bool classof(const ObjCEncodeExpr *) { return true; }
80
81  // Iterators
82  virtual child_iterator child_begin();
83  virtual child_iterator child_end();
84
85  virtual void EmitImpl(llvm::Serializer& S) const;
86  static ObjCEncodeExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
87};
88
89/// ObjCSelectorExpr used for @selector in Objective-C.
90class ObjCSelectorExpr : public Expr {
91  Selector SelName;
92  SourceLocation AtLoc, RParenLoc;
93public:
94  ObjCSelectorExpr(QualType T, Selector selInfo,
95                   SourceLocation at, SourceLocation rp)
96  : Expr(ObjCSelectorExprClass, T), SelName(selInfo),
97  AtLoc(at), RParenLoc(rp) {}
98
99  Selector getSelector() const { return SelName; }
100
101  SourceLocation getAtLoc() const { return AtLoc; }
102  SourceLocation getRParenLoc() const { return RParenLoc; }
103
104  virtual SourceRange getSourceRange() const {
105    return SourceRange(AtLoc, RParenLoc);
106  }
107
108  /// getNumArgs - Return the number of actual arguments to this call.
109  unsigned getNumArgs() const { return SelName.getNumArgs(); }
110
111  static bool classof(const Stmt *T) {
112    return T->getStmtClass() == ObjCSelectorExprClass;
113  }
114  static bool classof(const ObjCSelectorExpr *) { return true; }
115
116  // Iterators
117  virtual child_iterator child_begin();
118  virtual child_iterator child_end();
119
120  virtual void EmitImpl(llvm::Serializer& S) const;
121  static ObjCSelectorExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
122};
123
124/// ObjCProtocolExpr used for protocol in Objective-C.
125class ObjCProtocolExpr : public Expr {
126  ObjCProtocolDecl *Protocol;
127  SourceLocation AtLoc, RParenLoc;
128public:
129  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
130                   SourceLocation at, SourceLocation rp)
131  : Expr(ObjCProtocolExprClass, T), Protocol(protocol),
132  AtLoc(at), RParenLoc(rp) {}
133
134  ObjCProtocolDecl *getProtocol() const { return Protocol; }
135
136  SourceLocation getAtLoc() const { return AtLoc; }
137  SourceLocation getRParenLoc() const { return RParenLoc; }
138
139  virtual SourceRange getSourceRange() const {
140    return SourceRange(AtLoc, RParenLoc);
141  }
142
143  static bool classof(const Stmt *T) {
144    return T->getStmtClass() == ObjCProtocolExprClass;
145  }
146  static bool classof(const ObjCProtocolExpr *) { return true; }
147
148  // Iterators
149  virtual child_iterator child_begin();
150  virtual child_iterator child_end();
151};
152
153/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
154class ObjCIvarRefExpr : public Expr {
155  class ObjCIvarDecl *D;
156  SourceLocation Loc;
157  Stmt *Base;
158  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
159  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).
160
161public:
162  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0,
163                  bool arrow = false, bool freeIvar = false) :
164    Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow),
165    IsFreeIvar(freeIvar) {}
166
167  ObjCIvarDecl *getDecl() { return D; }
168  const ObjCIvarDecl *getDecl() const { return D; }
169  virtual SourceRange getSourceRange() const {
170    return isFreeIvar() ? SourceRange(Loc)
171                        : SourceRange(getBase()->getLocStart(), Loc);
172  }
173  const Expr *getBase() const { return cast<Expr>(Base); }
174  Expr *getBase() { return cast<Expr>(Base); }
175  void setBase(Expr * base) { Base = base; }
176  bool isArrow() const { return IsArrow; }
177  bool isFreeIvar() const { return IsFreeIvar; }
178
179  SourceLocation getLocation() const { return Loc; }
180
181  static bool classof(const Stmt *T) {
182    return T->getStmtClass() == ObjCIvarRefExprClass;
183  }
184  static bool classof(const ObjCIvarRefExpr *) { return true; }
185
186  // Iterators
187  virtual child_iterator child_begin();
188  virtual child_iterator child_end();
189
190  virtual void EmitImpl(llvm::Serializer& S) const;
191  static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
192};
193
194/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
195/// property. Note that dot-syntax can also be used to access
196/// "implicit" properties (i.e. methods following the property naming
197/// convention). Additionally, sema is not yet smart enough to know if
198/// a property reference is to a getter or a setter, so the expr must
199/// have access to both methods.
200///
201// FIXME: Consider splitting these into separate Expr classes.
202class ObjCPropertyRefExpr : public Expr {
203public:
204  enum Kind {
205    PropertyRef, // This expressions references a declared property.
206    MethodRef   // This expressions references methods.
207  };
208
209private:
210  // A dot-syntax reference via methods must always have a getter. We
211  // avoid storing the kind explicitly by relying on this invariant
212  // and assuming this is a MethodRef iff Getter is non-null. Setter
213  // can be null in situations which access a read-only property.
214  union {
215    ObjCPropertyDecl *AsProperty;
216    struct {
217      ObjCMethodDecl *Setter;
218      ObjCMethodDecl *Getter;
219    } AsMethod;
220  } Referent;
221  SourceLocation Loc;
222  Stmt *Base;
223
224public:
225  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
226                      SourceLocation l, Expr *base)
227    : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
228    Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL;
229    Referent.AsProperty = PD;
230  }
231  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
232                      QualType t,
233                      SourceLocation l, Expr *base)
234    : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
235    Referent.AsMethod.Getter = Getter;
236    Referent.AsMethod.Setter = Setter;
237  }
238
239  Kind getKind() const {
240    return Referent.AsMethod.Getter ? MethodRef : PropertyRef;
241  }
242
243  ObjCPropertyDecl *getProperty() const {
244    assert(getKind() == PropertyRef &&
245           "Cannot get property from an ObjCPropertyRefExpr using methods");
246    return Referent.AsProperty;
247  }
248  ObjCMethodDecl *getGetterMethod() const {
249    assert(getKind() == MethodRef &&
250           "Cannot get method from an ObjCPropertyRefExpr using a property");
251    return Referent.AsMethod.Getter;
252  }
253  ObjCMethodDecl *getSetterMethod() const {
254    assert(getKind() == MethodRef &&
255           "Cannot get method from an ObjCPropertyRefExpr using a property");
256    return Referent.AsMethod.Setter;
257  }
258
259  virtual SourceRange getSourceRange() const {
260    return SourceRange(getBase()->getLocStart(), Loc);
261  }
262  const Expr *getBase() const { return cast<Expr>(Base); }
263  Expr *getBase() { return cast<Expr>(Base); }
264  void setBase(Expr * base) { Base = base; }
265
266  SourceLocation getLocation() const { return Loc; }
267
268  static bool classof(const Stmt *T) {
269    return T->getStmtClass() == ObjCPropertyRefExprClass;
270  }
271  static bool classof(const ObjCPropertyRefExpr *) { return true; }
272
273  // Iterators
274  virtual child_iterator child_begin();
275  virtual child_iterator child_end();
276
277  virtual void EmitImpl(llvm::Serializer& S) const;
278  static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
279};
280
281class ObjCMessageExpr : public Expr {
282  // SubExprs - The receiver and arguments of the message expression.
283  Stmt **SubExprs;
284
285  // NumArgs - The number of arguments (not including the receiver) to the
286  //  message expression.
287  unsigned NumArgs;
288
289  // A unigue name for this message.
290  Selector SelName;
291
292  // A method prototype for this message (optional).
293  // FIXME: Since method decls contain the selector, and most messages have a
294  // prototype, consider devising a scheme for unifying SelName/MethodProto.
295  ObjCMethodDecl *MethodProto;
296
297  SourceLocation LBracloc, RBracloc;
298
299  // Constants for indexing into SubExprs.
300  enum { RECEIVER=0, ARGS_START=1 };
301
302  // Bit-swizziling flags.
303  enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
304  unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }
305
306  // constructor used during deserialization
307  ObjCMessageExpr(Selector selInfo, QualType retType,
308                  SourceLocation LBrac, SourceLocation RBrac,
309                  Stmt **subexprs, unsigned nargs)
310  : Expr(ObjCMessageExprClass, retType), SubExprs(subexprs),
311    NumArgs(nargs), SelName(selInfo), MethodProto(NULL),
312    LBracloc(LBrac), RBracloc(RBrac) {}
313
314public:
315  /// This constructor is used to represent class messages where the
316  /// ObjCInterfaceDecl* of the receiver is not known.
317  ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
318                  QualType retType, ObjCMethodDecl *methDecl,
319                  SourceLocation LBrac, SourceLocation RBrac,
320                  Expr **ArgExprs, unsigned NumArgs);
321
322  /// This constructor is used to represent class messages where the
323  /// ObjCInterfaceDecl* of the receiver is known.
324  // FIXME: clsName should be typed to ObjCInterfaceType
325  ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
326                  QualType retType, ObjCMethodDecl *methDecl,
327                  SourceLocation LBrac, SourceLocation RBrac,
328                  Expr **ArgExprs, unsigned NumArgs);
329
330  // constructor for instance messages.
331  ObjCMessageExpr(Expr *receiver, Selector selInfo,
332                  QualType retType, ObjCMethodDecl *methDecl,
333                  SourceLocation LBrac, SourceLocation RBrac,
334                  Expr **ArgExprs, unsigned NumArgs);
335
336  ~ObjCMessageExpr() {
337    delete [] SubExprs;
338  }
339
340  /// getReceiver - Returns the receiver of the message expression.
341  ///  This can be NULL if the message is for class methods.  For
342  ///  class methods, use getClassName.
343  /// FIXME: need to handle/detect 'super' usage within a class method.
344  Expr *getReceiver() {
345    uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
346    return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
347  }
348  const Expr *getReceiver() const {
349    return const_cast<ObjCMessageExpr*>(this)->getReceiver();
350  }
351
352  Selector getSelector() const { return SelName; }
353
354  const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
355  ObjCMethodDecl *getMethodDecl() { return MethodProto; }
356
357  typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
358
359  /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
360  ///  and IdentifierInfo* of the invoked class.  Both can be NULL if this
361  ///  is an instance message, and the ObjCInterfaceDecl* can be NULL if none
362  ///  was available when this ObjCMessageExpr object was constructed.
363  ClassInfo getClassInfo() const;
364
365  /// getClassName - For class methods, this returns the invoked class,
366  ///  and returns NULL otherwise.  For instance methods, use getReceiver.
367  IdentifierInfo *getClassName() const {
368    return getClassInfo().second;
369  }
370
371
372  /// getNumArgs - Return the number of actual arguments to this call.
373  unsigned getNumArgs() const { return NumArgs; }
374
375  /// getArg - Return the specified argument.
376  Expr *getArg(unsigned Arg) {
377    assert(Arg < NumArgs && "Arg access out of range!");
378    return cast<Expr>(SubExprs[Arg+ARGS_START]);
379  }
380  const Expr *getArg(unsigned Arg) const {
381    assert(Arg < NumArgs && "Arg access out of range!");
382    return cast<Expr>(SubExprs[Arg+ARGS_START]);
383  }
384  /// setArg - Set the specified argument.
385  void setArg(unsigned Arg, Expr *ArgExpr) {
386    assert(Arg < NumArgs && "Arg access out of range!");
387    SubExprs[Arg+ARGS_START] = ArgExpr;
388  }
389
390  virtual SourceRange getSourceRange() const {
391    return SourceRange(LBracloc, RBracloc);
392  }
393
394  static bool classof(const Stmt *T) {
395    return T->getStmtClass() == ObjCMessageExprClass;
396  }
397  static bool classof(const ObjCMessageExpr *) { return true; }
398
399  // Iterators
400  virtual child_iterator child_begin();
401  virtual child_iterator child_end();
402
403  typedef ExprIterator arg_iterator;
404  typedef ConstExprIterator const_arg_iterator;
405
406  arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
407  arg_iterator arg_end()   { return &SubExprs[ARGS_START] + NumArgs; }
408  const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
409  const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; }
410
411  // Serialization.
412  virtual void EmitImpl(llvm::Serializer& S) const;
413  static ObjCMessageExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
414};
415
416}  // end namespace clang
417
418#endif
419