ExprObjC.h revision d17c24ff8597fe0dee4210639d225bc4f7c5ac04
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  virtual void EmitImpl(llvm::Serializer& S) const;
153  static ObjCProtocolExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
154};
155
156/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
157class ObjCIvarRefExpr : public Expr {
158  class ObjCIvarDecl *D;
159  SourceLocation Loc;
160  Stmt *Base;
161  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
162  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).
163
164public:
165  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0,
166                  bool arrow = false, bool freeIvar = false) :
167    Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow),
168    IsFreeIvar(freeIvar) {}
169
170  ObjCIvarDecl *getDecl() { return D; }
171  const ObjCIvarDecl *getDecl() const { return D; }
172  virtual SourceRange getSourceRange() const {
173    return isFreeIvar() ? SourceRange(Loc)
174                        : SourceRange(getBase()->getLocStart(), Loc);
175  }
176  const Expr *getBase() const { return cast<Expr>(Base); }
177  Expr *getBase() { return cast<Expr>(Base); }
178  void setBase(Expr * base) { Base = base; }
179  bool isArrow() const { return IsArrow; }
180  bool isFreeIvar() const { return IsFreeIvar; }
181
182  SourceLocation getLocation() const { return Loc; }
183
184  static bool classof(const Stmt *T) {
185    return T->getStmtClass() == ObjCIvarRefExprClass;
186  }
187  static bool classof(const ObjCIvarRefExpr *) { return true; }
188
189  // Iterators
190  virtual child_iterator child_begin();
191  virtual child_iterator child_end();
192
193  virtual void EmitImpl(llvm::Serializer& S) const;
194  static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
195};
196
197/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
198/// property. Note that dot-syntax can also be used to access
199/// "implicit" properties (i.e. methods following the property naming
200/// convention). Additionally, sema is not yet smart enough to know if
201/// a property reference is to a getter or a setter, so the expr must
202/// have access to both methods.
203///
204// FIXME: Consider splitting these into separate Expr classes.
205class ObjCPropertyRefExpr : public Expr {
206public:
207  enum Kind {
208    PropertyRef, // This expressions references a declared property.
209    MethodRef   // This expressions references methods.
210  };
211
212private:
213  // A dot-syntax reference via methods must always have a getter. We
214  // avoid storing the kind explicitly by relying on this invariant
215  // and assuming this is a MethodRef iff Getter is non-null. Setter
216  // can be null in situations which access a read-only property.
217  union {
218    ObjCPropertyDecl *AsProperty;
219    struct {
220      ObjCMethodDecl *Setter;
221      ObjCMethodDecl *Getter;
222    } AsMethod;
223  } Referent;
224  SourceLocation Loc;
225  Stmt *Base;
226
227public:
228  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
229                      SourceLocation l, Expr *base)
230    : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
231    Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL;
232    Referent.AsProperty = PD;
233  }
234  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
235                      QualType t,
236                      SourceLocation l, Expr *base)
237    : Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
238    Referent.AsMethod.Getter = Getter;
239    Referent.AsMethod.Setter = Setter;
240  }
241
242  Kind getKind() const {
243    return Referent.AsMethod.Getter ? MethodRef : PropertyRef;
244  }
245
246  ObjCPropertyDecl *getProperty() const {
247    assert(getKind() == PropertyRef &&
248           "Cannot get property from an ObjCPropertyRefExpr using methods");
249    return Referent.AsProperty;
250  }
251  ObjCMethodDecl *getGetterMethod() const {
252    assert(getKind() == MethodRef &&
253           "Cannot get method from an ObjCPropertyRefExpr using a property");
254    return Referent.AsMethod.Getter;
255  }
256  ObjCMethodDecl *getSetterMethod() const {
257    assert(getKind() == MethodRef &&
258           "Cannot get method from an ObjCPropertyRefExpr using a property");
259    return Referent.AsMethod.Setter;
260  }
261
262  virtual SourceRange getSourceRange() const {
263    return SourceRange(getBase()->getLocStart(), Loc);
264  }
265  const Expr *getBase() const { return cast<Expr>(Base); }
266  Expr *getBase() { return cast<Expr>(Base); }
267  void setBase(Expr * base) { Base = base; }
268
269  SourceLocation getLocation() const { return Loc; }
270
271  static bool classof(const Stmt *T) {
272    return T->getStmtClass() == ObjCPropertyRefExprClass;
273  }
274  static bool classof(const ObjCPropertyRefExpr *) { return true; }
275
276  // Iterators
277  virtual child_iterator child_begin();
278  virtual child_iterator child_end();
279
280  virtual void EmitImpl(llvm::Serializer& S) const;
281  static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
282};
283
284class ObjCMessageExpr : public Expr {
285  // SubExprs - The receiver and arguments of the message expression.
286  Stmt **SubExprs;
287
288  // NumArgs - The number of arguments (not including the receiver) to the
289  //  message expression.
290  unsigned NumArgs;
291
292  // A unigue name for this message.
293  Selector SelName;
294
295  // A method prototype for this message (optional).
296  // FIXME: Since method decls contain the selector, and most messages have a
297  // prototype, consider devising a scheme for unifying SelName/MethodProto.
298  ObjCMethodDecl *MethodProto;
299
300  SourceLocation LBracloc, RBracloc;
301
302  // Constants for indexing into SubExprs.
303  enum { RECEIVER=0, ARGS_START=1 };
304
305  // Bit-swizziling flags.
306  enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
307  unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }
308
309  // constructor used during deserialization
310  ObjCMessageExpr(Selector selInfo, QualType retType,
311                  SourceLocation LBrac, SourceLocation RBrac,
312                  Stmt **subexprs, unsigned nargs)
313  : Expr(ObjCMessageExprClass, retType), SubExprs(subexprs),
314    NumArgs(nargs), SelName(selInfo), MethodProto(NULL),
315    LBracloc(LBrac), RBracloc(RBrac) {}
316
317public:
318  /// This constructor is used to represent class messages where the
319  /// ObjCInterfaceDecl* of the receiver is not known.
320  ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
321                  QualType retType, ObjCMethodDecl *methDecl,
322                  SourceLocation LBrac, SourceLocation RBrac,
323                  Expr **ArgExprs, unsigned NumArgs);
324
325  /// This constructor is used to represent class messages where the
326  /// ObjCInterfaceDecl* of the receiver is known.
327  // FIXME: clsName should be typed to ObjCInterfaceType
328  ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
329                  QualType retType, ObjCMethodDecl *methDecl,
330                  SourceLocation LBrac, SourceLocation RBrac,
331                  Expr **ArgExprs, unsigned NumArgs);
332
333  // constructor for instance messages.
334  ObjCMessageExpr(Expr *receiver, Selector selInfo,
335                  QualType retType, ObjCMethodDecl *methDecl,
336                  SourceLocation LBrac, SourceLocation RBrac,
337                  Expr **ArgExprs, unsigned NumArgs);
338
339  ~ObjCMessageExpr() {
340    delete [] SubExprs;
341  }
342
343  /// getReceiver - Returns the receiver of the message expression.
344  ///  This can be NULL if the message is for class methods.  For
345  ///  class methods, use getClassName.
346  /// FIXME: need to handle/detect 'super' usage within a class method.
347  Expr *getReceiver() {
348    uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
349    return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
350  }
351  const Expr *getReceiver() const {
352    return const_cast<ObjCMessageExpr*>(this)->getReceiver();
353  }
354
355  Selector getSelector() const { return SelName; }
356
357  const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
358  ObjCMethodDecl *getMethodDecl() { return MethodProto; }
359
360  typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
361
362  /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
363  ///  and IdentifierInfo* of the invoked class.  Both can be NULL if this
364  ///  is an instance message, and the ObjCInterfaceDecl* can be NULL if none
365  ///  was available when this ObjCMessageExpr object was constructed.
366  ClassInfo getClassInfo() const;
367
368  /// getClassName - For class methods, this returns the invoked class,
369  ///  and returns NULL otherwise.  For instance methods, use getReceiver.
370  IdentifierInfo *getClassName() const {
371    return getClassInfo().second;
372  }
373
374
375  /// getNumArgs - Return the number of actual arguments to this call.
376  unsigned getNumArgs() const { return NumArgs; }
377
378  /// getArg - Return the specified argument.
379  Expr *getArg(unsigned Arg) {
380    assert(Arg < NumArgs && "Arg access out of range!");
381    return cast<Expr>(SubExprs[Arg+ARGS_START]);
382  }
383  const Expr *getArg(unsigned Arg) const {
384    assert(Arg < NumArgs && "Arg access out of range!");
385    return cast<Expr>(SubExprs[Arg+ARGS_START]);
386  }
387  /// setArg - Set the specified argument.
388  void setArg(unsigned Arg, Expr *ArgExpr) {
389    assert(Arg < NumArgs && "Arg access out of range!");
390    SubExprs[Arg+ARGS_START] = ArgExpr;
391  }
392
393  virtual SourceRange getSourceRange() const {
394    return SourceRange(LBracloc, RBracloc);
395  }
396
397  static bool classof(const Stmt *T) {
398    return T->getStmtClass() == ObjCMessageExprClass;
399  }
400  static bool classof(const ObjCMessageExpr *) { return true; }
401
402  // Iterators
403  virtual child_iterator child_begin();
404  virtual child_iterator child_end();
405
406  typedef ExprIterator arg_iterator;
407  typedef ConstExprIterator const_arg_iterator;
408
409  arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
410  arg_iterator arg_end()   { return &SubExprs[ARGS_START] + NumArgs; }
411  const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
412  const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; }
413
414  // Serialization.
415  virtual void EmitImpl(llvm::Serializer& S) const;
416  static ObjCMessageExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
417};
418
419}  // end namespace clang
420
421#endif
422