ExprObjC.h revision 218893
1193326Sed//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the ExprObjC interface and subclasses.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#ifndef LLVM_CLANG_AST_EXPROBJC_H
15193326Sed#define LLVM_CLANG_AST_EXPROBJC_H
16193326Sed
17218893Sdim#include "clang/AST/DeclObjC.h"
18193326Sed#include "clang/AST/Expr.h"
19193326Sed#include "clang/Basic/IdentifierTable.h"
20193326Sed
21193326Sednamespace clang {
22193326Sed  class IdentifierInfo;
23193326Sed  class ASTContext;
24198092Srdivacky
25193326Sed/// ObjCStringLiteral, used for Objective-C string literals
26193326Sed/// i.e. @"foo".
27193326Sedclass ObjCStringLiteral : public Expr {
28193326Sed  Stmt *String;
29193326Sed  SourceLocation AtLoc;
30193326Sedpublic:
31193326Sed  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
32218893Sdim    : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
33218893Sdim           false),
34218893Sdim      String(SL), AtLoc(L) {}
35193326Sed  explicit ObjCStringLiteral(EmptyShell Empty)
36193326Sed    : Expr(ObjCStringLiteralClass, Empty) {}
37193326Sed
38193326Sed  StringLiteral *getString() { return cast<StringLiteral>(String); }
39193326Sed  const StringLiteral *getString() const { return cast<StringLiteral>(String); }
40193326Sed  void setString(StringLiteral *S) { String = S; }
41193326Sed
42193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
43193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
44193326Sed
45218893Sdim  SourceRange getSourceRange() const {
46193326Sed    return SourceRange(AtLoc, String->getLocEnd());
47193326Sed  }
48198092Srdivacky
49198092Srdivacky  static bool classof(const Stmt *T) {
50198092Srdivacky    return T->getStmtClass() == ObjCStringLiteralClass;
51193326Sed  }
52198092Srdivacky  static bool classof(const ObjCStringLiteral *) { return true; }
53198092Srdivacky
54193326Sed  // Iterators
55218893Sdim  child_range children() { return child_range(&String, &String+1); }
56193326Sed};
57198092Srdivacky
58193326Sed/// ObjCEncodeExpr, used for @encode in Objective-C.  @encode has the same type
59193326Sed/// and behavior as StringLiteral except that the string initializer is obtained
60193326Sed/// from ASTContext with the encoding type as an argument.
61193326Sedclass ObjCEncodeExpr : public Expr {
62207619Srdivacky  TypeSourceInfo *EncodedType;
63193326Sed  SourceLocation AtLoc, RParenLoc;
64193326Sedpublic:
65207619Srdivacky  ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
66193326Sed                 SourceLocation at, SourceLocation rp)
67218893Sdim    : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
68218893Sdim           EncodedType->getType()->isDependentType(),
69218893Sdim           EncodedType->getType()->isDependentType(),
70218893Sdim           EncodedType->getType()->containsUnexpandedParameterPack()),
71207619Srdivacky      EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
72198092Srdivacky
73193326Sed  explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
74193326Sed
75198092Srdivacky
76193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
77193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
78193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
79193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
80198092Srdivacky
81207619Srdivacky  QualType getEncodedType() const { return EncodedType->getType(); }
82193326Sed
83207619Srdivacky  TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
84207619Srdivacky  void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
85207619Srdivacky    EncodedType = EncType;
86207619Srdivacky  }
87198092Srdivacky
88218893Sdim  SourceRange getSourceRange() const {
89193326Sed    return SourceRange(AtLoc, RParenLoc);
90193326Sed  }
91198092Srdivacky
92193326Sed  static bool classof(const Stmt *T) {
93193326Sed    return T->getStmtClass() == ObjCEncodeExprClass;
94193326Sed  }
95193326Sed  static bool classof(const ObjCEncodeExpr *) { return true; }
96198092Srdivacky
97193326Sed  // Iterators
98218893Sdim  child_range children() { return child_range(); }
99193326Sed};
100193326Sed
101193326Sed/// ObjCSelectorExpr used for @selector in Objective-C.
102193326Sedclass ObjCSelectorExpr : public Expr {
103193326Sed  Selector SelName;
104193326Sed  SourceLocation AtLoc, RParenLoc;
105193326Sedpublic:
106193326Sed  ObjCSelectorExpr(QualType T, Selector selInfo,
107193326Sed                   SourceLocation at, SourceLocation rp)
108218893Sdim    : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
109218893Sdim           false),
110218893Sdim    SelName(selInfo), AtLoc(at), RParenLoc(rp){}
111193326Sed  explicit ObjCSelectorExpr(EmptyShell Empty)
112193326Sed   : Expr(ObjCSelectorExprClass, Empty) {}
113193326Sed
114193326Sed  Selector getSelector() const { return SelName; }
115193326Sed  void setSelector(Selector S) { SelName = S; }
116198092Srdivacky
117193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
118193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
119193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
120193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
121193326Sed
122218893Sdim  SourceRange getSourceRange() const {
123193326Sed    return SourceRange(AtLoc, RParenLoc);
124193326Sed  }
125198092Srdivacky
126193326Sed  /// getNumArgs - Return the number of actual arguments to this call.
127193326Sed  unsigned getNumArgs() const { return SelName.getNumArgs(); }
128198092Srdivacky
129193326Sed  static bool classof(const Stmt *T) {
130193326Sed    return T->getStmtClass() == ObjCSelectorExprClass;
131193326Sed  }
132193326Sed  static bool classof(const ObjCSelectorExpr *) { return true; }
133198092Srdivacky
134193326Sed  // Iterators
135218893Sdim  child_range children() { return child_range(); }
136193326Sed};
137198092Srdivacky
138193326Sed/// ObjCProtocolExpr used for protocol expression in Objective-C.  This is used
139193326Sed/// as: @protocol(foo), as in:
140193326Sed///   obj conformsToProtocol:@protocol(foo)]
141193326Sed/// The return type is "Protocol*".
142198092Srdivackyclass ObjCProtocolExpr : public Expr {
143198092Srdivacky  ObjCProtocolDecl *TheProtocol;
144193326Sed  SourceLocation AtLoc, RParenLoc;
145193326Sedpublic:
146193326Sed  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
147193326Sed                   SourceLocation at, SourceLocation rp)
148218893Sdim    : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
149218893Sdim           false),
150218893Sdim      TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {}
151193326Sed  explicit ObjCProtocolExpr(EmptyShell Empty)
152193326Sed    : Expr(ObjCProtocolExprClass, Empty) {}
153193326Sed
154194613Sed  ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
155194613Sed  void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
156198092Srdivacky
157193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
158193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
159193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
160193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
161193326Sed
162218893Sdim  SourceRange getSourceRange() const {
163193326Sed    return SourceRange(AtLoc, RParenLoc);
164193326Sed  }
165198092Srdivacky
166193326Sed  static bool classof(const Stmt *T) {
167193326Sed    return T->getStmtClass() == ObjCProtocolExprClass;
168193326Sed  }
169193326Sed  static bool classof(const ObjCProtocolExpr *) { return true; }
170198092Srdivacky
171193326Sed  // Iterators
172218893Sdim  child_range children() { return child_range(); }
173193326Sed};
174193326Sed
175193326Sed/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
176193326Sedclass ObjCIvarRefExpr : public Expr {
177193326Sed  class ObjCIvarDecl *D;
178193326Sed  SourceLocation Loc;
179193326Sed  Stmt *Base;
180193326Sed  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
181193326Sed  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).
182198092Srdivacky
183193326Sedpublic:
184218893Sdim  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
185218893Sdim                  SourceLocation l, Expr *base,
186198092Srdivacky                  bool arrow = false, bool freeIvar = false) :
187218893Sdim    Expr(ObjCIvarRefExprClass, t, VK_LValue, OK_Ordinary,
188218893Sdim         /*TypeDependent=*/false, base->isValueDependent(),
189218893Sdim         base->containsUnexpandedParameterPack()),
190218893Sdim    D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {}
191198092Srdivacky
192193326Sed  explicit ObjCIvarRefExpr(EmptyShell Empty)
193193326Sed    : Expr(ObjCIvarRefExprClass, Empty) {}
194193326Sed
195193326Sed  ObjCIvarDecl *getDecl() { return D; }
196193326Sed  const ObjCIvarDecl *getDecl() const { return D; }
197193326Sed  void setDecl(ObjCIvarDecl *d) { D = d; }
198198092Srdivacky
199193326Sed  const Expr *getBase() const { return cast<Expr>(Base); }
200193326Sed  Expr *getBase() { return cast<Expr>(Base); }
201193326Sed  void setBase(Expr * base) { Base = base; }
202198092Srdivacky
203193326Sed  bool isArrow() const { return IsArrow; }
204193326Sed  bool isFreeIvar() const { return IsFreeIvar; }
205193326Sed  void setIsArrow(bool A) { IsArrow = A; }
206193326Sed  void setIsFreeIvar(bool A) { IsFreeIvar = A; }
207198092Srdivacky
208193326Sed  SourceLocation getLocation() const { return Loc; }
209193326Sed  void setLocation(SourceLocation L) { Loc = L; }
210193326Sed
211218893Sdim  SourceRange getSourceRange() const {
212193326Sed    return isFreeIvar() ? SourceRange(Loc)
213198092Srdivacky    : SourceRange(getBase()->getLocStart(), Loc);
214193326Sed  }
215198092Srdivacky
216198092Srdivacky  static bool classof(const Stmt *T) {
217198092Srdivacky    return T->getStmtClass() == ObjCIvarRefExprClass;
218193326Sed  }
219193326Sed  static bool classof(const ObjCIvarRefExpr *) { return true; }
220198092Srdivacky
221193326Sed  // Iterators
222218893Sdim  child_range children() { return child_range(&Base, &Base+1); }
223193326Sed};
224193326Sed
225193326Sed/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
226193326Sed/// property.
227193326Sed///
228193326Sedclass ObjCPropertyRefExpr : public Expr {
229193326Sedprivate:
230218893Sdim  /// If the bool is true, this is an implicit property reference; the
231218893Sdim  /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
232218893Sdim  /// if the bool is false, this is an explicit property reference;
233218893Sdim  /// the pointer is an ObjCPropertyDecl and Setter is always null.
234218893Sdim  llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
235218893Sdim  ObjCMethodDecl *Setter;
236218893Sdim
237193326Sed  SourceLocation IdLoc;
238218893Sdim
239218893Sdim  /// \brief When the receiver in property access is 'super', this is
240218893Sdim  /// the location of the 'super' keyword.  When it's an interface,
241218893Sdim  /// this is that interface.
242218893Sdim  SourceLocation ReceiverLoc;
243218893Sdim  llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
244218893Sdim
245193326Sedpublic:
246198092Srdivacky  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
247218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
248193326Sed                      SourceLocation l, Expr *base)
249218893Sdim    : Expr(ObjCPropertyRefExprClass, t, VK, OK,
250218893Sdim           /*TypeDependent=*/false, base->isValueDependent(),
251218893Sdim           base->containsUnexpandedParameterPack()),
252218893Sdim      PropertyOrGetter(PD, false), Setter(0),
253218893Sdim      IdLoc(l), ReceiverLoc(), Receiver(base) {
254193326Sed  }
255218893Sdim
256218893Sdim  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
257218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
258218893Sdim                      SourceLocation l, SourceLocation sl, QualType st)
259218893Sdim    : Expr(ObjCPropertyRefExprClass, t, VK, OK,
260218893Sdim           /*TypeDependent=*/false, false,
261218893Sdim           st->containsUnexpandedParameterPack()),
262218893Sdim      PropertyOrGetter(PD, false), Setter(0),
263218893Sdim      IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
264218893Sdim  }
265198092Srdivacky
266218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
267218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
268218893Sdim                      SourceLocation IdLoc, Expr *Base)
269218893Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
270218893Sdim           Base->isValueDependent(),
271218893Sdim           Base->containsUnexpandedParameterPack()),
272218893Sdim      PropertyOrGetter(Getter, true), Setter(Setter),
273218893Sdim      IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
274218893Sdim  }
275218893Sdim
276218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
277218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
278218893Sdim                      SourceLocation IdLoc,
279218893Sdim                      SourceLocation SuperLoc, QualType SuperTy)
280218893Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
281218893Sdim      PropertyOrGetter(Getter, true), Setter(Setter),
282218893Sdim      IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
283218893Sdim  }
284218893Sdim
285218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
286218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
287218893Sdim                      SourceLocation IdLoc,
288218893Sdim                      SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
289218893Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false),
290218893Sdim      PropertyOrGetter(Getter, true), Setter(Setter),
291218893Sdim      IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
292218893Sdim  }
293218893Sdim
294193326Sed  explicit ObjCPropertyRefExpr(EmptyShell Empty)
295193326Sed    : Expr(ObjCPropertyRefExprClass, Empty) {}
296193326Sed
297218893Sdim  bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
298218893Sdim  bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
299198092Srdivacky
300218893Sdim  ObjCPropertyDecl *getExplicitProperty() const {
301218893Sdim    assert(!isImplicitProperty());
302218893Sdim    return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
303218893Sdim  }
304198092Srdivacky
305218893Sdim  ObjCMethodDecl *getImplicitPropertyGetter() const {
306218893Sdim    assert(isImplicitProperty());
307218893Sdim    return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
308218893Sdim  }
309218893Sdim
310218893Sdim  ObjCMethodDecl *getImplicitPropertySetter() const {
311218893Sdim    assert(isImplicitProperty());
312218893Sdim    return Setter;
313218893Sdim  }
314218893Sdim
315218893Sdim  Selector getGetterSelector() const {
316218893Sdim    if (isImplicitProperty())
317218893Sdim      return getImplicitPropertyGetter()->getSelector();
318218893Sdim    return getExplicitProperty()->getGetterName();
319218893Sdim  }
320218893Sdim
321218893Sdim  Selector getSetterSelector() const {
322218893Sdim    if (isImplicitProperty())
323218893Sdim      return getImplicitPropertySetter()->getSelector();
324218893Sdim    return getExplicitProperty()->getSetterName();
325218893Sdim  }
326218893Sdim
327218893Sdim  const Expr *getBase() const {
328218893Sdim    return cast<Expr>(Receiver.get<Stmt*>());
329218893Sdim  }
330218893Sdim  Expr *getBase() {
331218893Sdim    return cast<Expr>(Receiver.get<Stmt*>());
332218893Sdim  }
333218893Sdim
334193326Sed  SourceLocation getLocation() const { return IdLoc; }
335218893Sdim
336218893Sdim  SourceLocation getReceiverLocation() const { return ReceiverLoc; }
337218893Sdim  QualType getSuperReceiverType() const {
338218893Sdim    return QualType(Receiver.get<const Type*>(), 0);
339218893Sdim  }
340218893Sdim  ObjCInterfaceDecl *getClassReceiver() const {
341218893Sdim    return Receiver.get<ObjCInterfaceDecl*>();
342218893Sdim  }
343218893Sdim  bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
344218893Sdim  bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
345218893Sdim  bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
346193326Sed
347218893Sdim  SourceRange getSourceRange() const {
348218893Sdim    return SourceRange((isObjectReceiver() ? getBase()->getLocStart()
349218893Sdim                                           : getReceiverLocation()),
350218893Sdim                       IdLoc);
351193326Sed  }
352198092Srdivacky
353198092Srdivacky  static bool classof(const Stmt *T) {
354198092Srdivacky    return T->getStmtClass() == ObjCPropertyRefExprClass;
355193326Sed  }
356193326Sed  static bool classof(const ObjCPropertyRefExpr *) { return true; }
357198092Srdivacky
358193326Sed  // Iterators
359218893Sdim  child_range children() {
360218893Sdim    if (Receiver.is<Stmt*>()) {
361218893Sdim      Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
362218893Sdim      return child_range(begin, begin+1);
363193326Sed    }
364218893Sdim    return child_range();
365193326Sed  }
366198092Srdivacky
367218893Sdimprivate:
368218893Sdim  friend class ASTStmtReader;
369218893Sdim  void setExplicitProperty(ObjCPropertyDecl *D) {
370218893Sdim    PropertyOrGetter.setPointer(D);
371218893Sdim    PropertyOrGetter.setInt(false);
372218893Sdim    Setter = 0;
373193326Sed  }
374218893Sdim  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter) {
375218893Sdim    PropertyOrGetter.setPointer(Getter);
376218893Sdim    PropertyOrGetter.setInt(true);
377218893Sdim    this->Setter = Setter;
378218893Sdim  }
379218893Sdim  void setBase(Expr *Base) { Receiver = Base; }
380218893Sdim  void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
381218893Sdim  void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
382198092Srdivacky
383218893Sdim  void setLocation(SourceLocation L) { IdLoc = L; }
384218893Sdim  void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
385193326Sed};
386198092Srdivacky
387207619Srdivacky/// \brief An expression that sends a message to the given Objective-C
388207619Srdivacky/// object or class.
389207619Srdivacky///
390207619Srdivacky/// The following contains two message send expressions:
391207619Srdivacky///
392207619Srdivacky/// \code
393207619Srdivacky///   [[NSString alloc] initWithString:@"Hello"]
394207619Srdivacky/// \endcode
395207619Srdivacky///
396207619Srdivacky/// The innermost message send invokes the "alloc" class method on the
397207619Srdivacky/// NSString class, while the outermost message send invokes the
398207619Srdivacky/// "initWithString" instance method on the object returned from
399207619Srdivacky/// NSString's "alloc". In all, an Objective-C message send can take
400207619Srdivacky/// on four different (although related) forms:
401207619Srdivacky///
402207619Srdivacky///   1. Send to an object instance.
403207619Srdivacky///   2. Send to a class.
404207619Srdivacky///   3. Send to the superclass instance of the current class.
405207619Srdivacky///   4. Send to the superclass of the current class.
406207619Srdivacky///
407207619Srdivacky/// All four kinds of message sends are modeled by the ObjCMessageExpr
408207619Srdivacky/// class, and can be distinguished via \c getReceiverKind(). Example:
409207619Srdivacky///
410193326Sedclass ObjCMessageExpr : public Expr {
411207619Srdivacky  /// \brief The number of arguments in the message send, not
412207619Srdivacky  /// including the receiver.
413207619Srdivacky  unsigned NumArgs : 16;
414198092Srdivacky
415207619Srdivacky  /// \brief The kind of message send this is, which is one of the
416207619Srdivacky  /// ReceiverKind values.
417207619Srdivacky  ///
418207619Srdivacky  /// We pad this out to a byte to avoid excessive masking and shifting.
419207619Srdivacky  unsigned Kind : 8;
420198092Srdivacky
421207619Srdivacky  /// \brief Whether we have an actual method prototype in \c
422207619Srdivacky  /// SelectorOrMethod.
423207619Srdivacky  ///
424207619Srdivacky  /// When non-zero, we have a method declaration; otherwise, we just
425207619Srdivacky  /// have a selector.
426207619Srdivacky  unsigned HasMethod : 8;
427204962Srdivacky
428207619Srdivacky  /// \brief When the message expression is a send to 'super', this is
429207619Srdivacky  /// the location of the 'super' keyword.
430207619Srdivacky  SourceLocation SuperLoc;
431198092Srdivacky
432207619Srdivacky  /// \brief Stores either the selector that this message is sending
433207619Srdivacky  /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
434207619Srdivacky  /// referring to the method that we type-checked against.
435207619Srdivacky  uintptr_t SelectorOrMethod;
436193326Sed
437218893Sdim  /// \brief Location of the selector.
438218893Sdim  SourceLocation SelectorLoc;
439218893Sdim
440207619Srdivacky  /// \brief The source locations of the open and close square
441207619Srdivacky  /// brackets ('[' and ']', respectively).
442207619Srdivacky  SourceLocation LBracLoc, RBracLoc;
443193326Sed
444207619Srdivacky  ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
445207619Srdivacky    : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0),
446207619Srdivacky      HasMethod(0), SelectorOrMethod(0) { }
447193326Sed
448218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
449207619Srdivacky                  SourceLocation LBracLoc,
450207619Srdivacky                  SourceLocation SuperLoc,
451207619Srdivacky                  bool IsInstanceSuper,
452207619Srdivacky                  QualType SuperType,
453207619Srdivacky                  Selector Sel,
454218893Sdim                  SourceLocation SelLoc,
455207619Srdivacky                  ObjCMethodDecl *Method,
456207619Srdivacky                  Expr **Args, unsigned NumArgs,
457207619Srdivacky                  SourceLocation RBracLoc);
458218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
459207619Srdivacky                  SourceLocation LBracLoc,
460207619Srdivacky                  TypeSourceInfo *Receiver,
461207619Srdivacky                  Selector Sel,
462218893Sdim                  SourceLocation SelLoc,
463207619Srdivacky                  ObjCMethodDecl *Method,
464207619Srdivacky                  Expr **Args, unsigned NumArgs,
465207619Srdivacky                  SourceLocation RBracLoc);
466218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
467207619Srdivacky                  SourceLocation LBracLoc,
468207619Srdivacky                  Expr *Receiver,
469207619Srdivacky                  Selector Sel,
470218893Sdim                  SourceLocation SelLoc,
471207619Srdivacky                  ObjCMethodDecl *Method,
472207619Srdivacky                  Expr **Args, unsigned NumArgs,
473207619Srdivacky                  SourceLocation RBracLoc);
474198092Srdivacky
475207619Srdivacky  /// \brief Retrieve the pointer value of the message receiver.
476207619Srdivacky  void *getReceiverPointer() const {
477207619Srdivacky    return *const_cast<void **>(
478207619Srdivacky                             reinterpret_cast<const void * const*>(this + 1));
479207619Srdivacky  }
480207619Srdivacky
481207619Srdivacky  /// \brief Set the pointer value of the message receiver.
482207619Srdivacky  void setReceiverPointer(void *Value) {
483207619Srdivacky    *reinterpret_cast<void **>(this + 1) = Value;
484207619Srdivacky  }
485207619Srdivacky
486193326Sedpublic:
487207619Srdivacky  /// \brief The kind of receiver this message is sending to.
488207619Srdivacky  enum ReceiverKind {
489207619Srdivacky    /// \brief The receiver is a class.
490207619Srdivacky    Class = 0,
491207619Srdivacky    /// \brief The receiver is an object instance.
492207619Srdivacky    Instance,
493207619Srdivacky    /// \brief The receiver is a superclass.
494207619Srdivacky    SuperClass,
495207619Srdivacky    /// \brief The receiver is the instance of the superclass object.
496207619Srdivacky    SuperInstance
497207619Srdivacky  };
498193326Sed
499207619Srdivacky  /// \brief Create a message send to super.
500207619Srdivacky  ///
501207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
502207619Srdivacky  ///
503207619Srdivacky  /// \param T The result type of this message.
504207619Srdivacky  ///
505218893Sdim  /// \param VK The value kind of this message.  A message returning
506218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
507218893Sdim  /// respectively.
508218893Sdim  ///
509207619Srdivacky  /// \param LBrac The location of the open square bracket '['.
510207619Srdivacky  ///
511207619Srdivacky  /// \param SuperLoc The location of the "super" keyword.
512207619Srdivacky  ///
513207619Srdivacky  /// \param IsInstanceSuper Whether this is an instance "super"
514207619Srdivacky  /// message (otherwise, it's a class "super" message).
515207619Srdivacky  ///
516207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
517207619Srdivacky  ///
518207619Srdivacky  /// \param Method The Objective-C method against which this message
519207619Srdivacky  /// send was type-checked. May be NULL.
520207619Srdivacky  ///
521207619Srdivacky  /// \param Args The message send arguments.
522207619Srdivacky  ///
523207619Srdivacky  /// \param NumArgs The number of arguments.
524207619Srdivacky  ///
525207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
526218893Sdim  static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
527218893Sdim                                 ExprValueKind VK,
528207619Srdivacky                                 SourceLocation LBracLoc,
529207619Srdivacky                                 SourceLocation SuperLoc,
530207619Srdivacky                                 bool IsInstanceSuper,
531207619Srdivacky                                 QualType SuperType,
532207619Srdivacky                                 Selector Sel,
533218893Sdim                                 SourceLocation SelLoc,
534207619Srdivacky                                 ObjCMethodDecl *Method,
535207619Srdivacky                                 Expr **Args, unsigned NumArgs,
536207619Srdivacky                                 SourceLocation RBracLoc);
537198092Srdivacky
538207619Srdivacky  /// \brief Create a class message send.
539207619Srdivacky  ///
540207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
541207619Srdivacky  ///
542207619Srdivacky  /// \param T The result type of this message.
543207619Srdivacky  ///
544218893Sdim  /// \param VK The value kind of this message.  A message returning
545218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
546218893Sdim  /// respectively.
547218893Sdim  ///
548207619Srdivacky  /// \param LBrac The location of the open square bracket '['.
549207619Srdivacky  ///
550207619Srdivacky  /// \param Receiver The type of the receiver, including
551207619Srdivacky  /// source-location information.
552207619Srdivacky  ///
553207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
554207619Srdivacky  ///
555207619Srdivacky  /// \param Method The Objective-C method against which this message
556207619Srdivacky  /// send was type-checked. May be NULL.
557207619Srdivacky  ///
558207619Srdivacky  /// \param Args The message send arguments.
559207619Srdivacky  ///
560207619Srdivacky  /// \param NumArgs The number of arguments.
561207619Srdivacky  ///
562207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
563207619Srdivacky  static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
564218893Sdim                                 ExprValueKind VK,
565207619Srdivacky                                 SourceLocation LBracLoc,
566207619Srdivacky                                 TypeSourceInfo *Receiver,
567207619Srdivacky                                 Selector Sel,
568218893Sdim                                 SourceLocation SelLoc,
569207619Srdivacky                                 ObjCMethodDecl *Method,
570207619Srdivacky                                 Expr **Args, unsigned NumArgs,
571207619Srdivacky                                 SourceLocation RBracLoc);
572198092Srdivacky
573207619Srdivacky  /// \brief Create an instance message send.
574207619Srdivacky  ///
575207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
576207619Srdivacky  ///
577207619Srdivacky  /// \param T The result type of this message.
578207619Srdivacky  ///
579218893Sdim  /// \param VK The value kind of this message.  A message returning
580218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
581218893Sdim  /// respectively.
582218893Sdim  ///
583207619Srdivacky  /// \param LBrac The location of the open square bracket '['.
584207619Srdivacky  ///
585207619Srdivacky  /// \param Receiver The expression used to produce the object that
586207619Srdivacky  /// will receive this message.
587207619Srdivacky  ///
588207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
589207619Srdivacky  ///
590207619Srdivacky  /// \param Method The Objective-C method against which this message
591207619Srdivacky  /// send was type-checked. May be NULL.
592207619Srdivacky  ///
593207619Srdivacky  /// \param Args The message send arguments.
594207619Srdivacky  ///
595207619Srdivacky  /// \param NumArgs The number of arguments.
596207619Srdivacky  ///
597207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
598207619Srdivacky  static ObjCMessageExpr *Create(ASTContext &Context, QualType T,
599218893Sdim                                 ExprValueKind VK,
600207619Srdivacky                                 SourceLocation LBracLoc,
601207619Srdivacky                                 Expr *Receiver,
602207619Srdivacky                                 Selector Sel,
603218893Sdim                                 SourceLocation SelLoc,
604207619Srdivacky                                 ObjCMethodDecl *Method,
605207619Srdivacky                                 Expr **Args, unsigned NumArgs,
606207619Srdivacky                                 SourceLocation RBracLoc);
607198092Srdivacky
608207619Srdivacky  /// \brief Create an empty Objective-C message expression, to be
609207619Srdivacky  /// filled in by subsequent calls.
610207619Srdivacky  ///
611207619Srdivacky  /// \param Context The context in which the message send will be created.
612207619Srdivacky  ///
613207619Srdivacky  /// \param NumArgs The number of message arguments, not including
614207619Srdivacky  /// the receiver.
615207619Srdivacky  static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs);
616198092Srdivacky
617207619Srdivacky  /// \brief Determine the kind of receiver that this message is being
618207619Srdivacky  /// sent to.
619207619Srdivacky  ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
620207619Srdivacky
621218893Sdim  /// \brief Source range of the receiver.
622218893Sdim  SourceRange getReceiverRange() const;
623218893Sdim
624207619Srdivacky  /// \brief Determine whether this is an instance message to either a
625207619Srdivacky  /// computed object or to super.
626207619Srdivacky  bool isInstanceMessage() const {
627207619Srdivacky    return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
628198092Srdivacky  }
629207619Srdivacky
630207619Srdivacky  /// \brief Determine whether this is an class message to either a
631207619Srdivacky  /// specified class or to super.
632207619Srdivacky  bool isClassMessage() const {
633207619Srdivacky    return getReceiverKind() == Class || getReceiverKind() == SuperClass;
634193326Sed  }
635198092Srdivacky
636207619Srdivacky  /// \brief Returns the receiver of an instance message.
637207619Srdivacky  ///
638207619Srdivacky  /// \brief Returns the object expression for an instance message, or
639207619Srdivacky  /// NULL for a message that is not an instance message.
640207619Srdivacky  Expr *getInstanceReceiver() {
641207619Srdivacky    if (getReceiverKind() == Instance)
642207619Srdivacky      return static_cast<Expr *>(getReceiverPointer());
643198092Srdivacky
644207619Srdivacky    return 0;
645207619Srdivacky  }
646207619Srdivacky  const Expr *getInstanceReceiver() const {
647207619Srdivacky    return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
648207619Srdivacky  }
649198092Srdivacky
650207619Srdivacky  /// \brief Turn this message send into an instance message that
651207619Srdivacky  /// computes the receiver object with the given expression.
652207619Srdivacky  void setInstanceReceiver(Expr *rec) {
653207619Srdivacky    Kind = Instance;
654207619Srdivacky    setReceiverPointer(rec);
655207619Srdivacky  }
656207619Srdivacky
657207619Srdivacky  /// \brief Returns the type of a class message send, or NULL if the
658207619Srdivacky  /// message is not a class message.
659207619Srdivacky  QualType getClassReceiver() const {
660207619Srdivacky    if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
661207619Srdivacky      return TSInfo->getType();
662204962Srdivacky
663207619Srdivacky    return QualType();
664207619Srdivacky  }
665204962Srdivacky
666207619Srdivacky  /// \brief Returns a type-source information of a class message
667207619Srdivacky  /// send, or NULL if the message is not a class message.
668207619Srdivacky  TypeSourceInfo *getClassReceiverTypeInfo() const {
669207619Srdivacky    if (getReceiverKind() == Class)
670207619Srdivacky      return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
671207619Srdivacky    return 0;
672207619Srdivacky  }
673204962Srdivacky
674207619Srdivacky  void setClassReceiver(TypeSourceInfo *TSInfo) {
675207619Srdivacky    Kind = Class;
676207619Srdivacky    setReceiverPointer(TSInfo);
677207619Srdivacky  }
678204962Srdivacky
679207619Srdivacky  /// \brief Retrieve the location of the 'super' keyword for a class
680207619Srdivacky  /// or instance message to 'super', otherwise an invalid source location.
681207619Srdivacky  SourceLocation getSuperLoc() const {
682207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
683207619Srdivacky      return SuperLoc;
684198092Srdivacky
685207619Srdivacky    return SourceLocation();
686193326Sed  }
687198092Srdivacky
688207619Srdivacky  /// \brief Retrieve the Objective-C interface to which this message
689207619Srdivacky  /// is being directed, if known.
690207619Srdivacky  ///
691207619Srdivacky  /// This routine cross-cuts all of the different kinds of message
692207619Srdivacky  /// sends to determine what the underlying (statically known) type
693207619Srdivacky  /// of the receiver will be; use \c getReceiverKind() to determine
694207619Srdivacky  /// whether the message is a class or an instance method, whether it
695207619Srdivacky  /// is a send to super or not, etc.
696207619Srdivacky  ///
697207619Srdivacky  /// \returns The Objective-C interface if known, otherwise NULL.
698207619Srdivacky  ObjCInterfaceDecl *getReceiverInterface() const;
699207619Srdivacky
700207619Srdivacky  /// \brief Retrieve the type referred to by 'super'.
701207619Srdivacky  ///
702207619Srdivacky  /// The returned type will either be an ObjCInterfaceType (for an
703207619Srdivacky  /// class message to super) or an ObjCObjectPointerType that refers
704207619Srdivacky  /// to a class (for an instance message to super);
705207619Srdivacky  QualType getSuperType() const {
706207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
707207619Srdivacky      return QualType::getFromOpaquePtr(getReceiverPointer());
708207619Srdivacky
709207619Srdivacky    return QualType();
710207619Srdivacky  }
711207619Srdivacky
712207619Srdivacky  void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
713207619Srdivacky    Kind = IsInstanceSuper? SuperInstance : SuperClass;
714207619Srdivacky    SuperLoc = Loc;
715207619Srdivacky    setReceiverPointer(T.getAsOpaquePtr());
716207619Srdivacky  }
717207619Srdivacky
718207619Srdivacky  Selector getSelector() const;
719207619Srdivacky
720207619Srdivacky  void setSelector(Selector S) {
721207619Srdivacky    HasMethod = false;
722207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
723207619Srdivacky  }
724207619Srdivacky
725207619Srdivacky  const ObjCMethodDecl *getMethodDecl() const {
726207619Srdivacky    if (HasMethod)
727207619Srdivacky      return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
728207619Srdivacky
729207619Srdivacky    return 0;
730207619Srdivacky  }
731207619Srdivacky
732207619Srdivacky  ObjCMethodDecl *getMethodDecl() {
733207619Srdivacky    if (HasMethod)
734207619Srdivacky      return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
735207619Srdivacky
736207619Srdivacky    return 0;
737207619Srdivacky  }
738207619Srdivacky
739207619Srdivacky  void setMethodDecl(ObjCMethodDecl *MD) {
740207619Srdivacky    HasMethod = true;
741207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
742207619Srdivacky  }
743207619Srdivacky
744207619Srdivacky  /// \brief Return the number of actual arguments in this message,
745207619Srdivacky  /// not counting the receiver.
746193326Sed  unsigned getNumArgs() const { return NumArgs; }
747207619Srdivacky
748207619Srdivacky  /// \brief Retrieve the arguments to this message, not including the
749207619Srdivacky  /// receiver.
750218893Sdim  Expr **getArgs() {
751218893Sdim    return reinterpret_cast<Expr **>(this + 1) + 1;
752193326Sed  }
753218893Sdim  const Expr * const *getArgs() const {
754218893Sdim    return reinterpret_cast<const Expr * const *>(this + 1) + 1;
755207619Srdivacky  }
756198092Srdivacky
757193326Sed  /// getArg - Return the specified argument.
758193326Sed  Expr *getArg(unsigned Arg) {
759193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
760207619Srdivacky    return cast<Expr>(getArgs()[Arg]);
761193326Sed  }
762193326Sed  const Expr *getArg(unsigned Arg) const {
763193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
764207619Srdivacky    return cast<Expr>(getArgs()[Arg]);
765193326Sed  }
766193326Sed  /// setArg - Set the specified argument.
767193326Sed  void setArg(unsigned Arg, Expr *ArgExpr) {
768193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
769207619Srdivacky    getArgs()[Arg] = ArgExpr;
770193326Sed  }
771198092Srdivacky
772207619Srdivacky  SourceLocation getLeftLoc() const { return LBracLoc; }
773207619Srdivacky  SourceLocation getRightLoc() const { return RBracLoc; }
774218893Sdim  SourceLocation getSelectorLoc() const { return SelectorLoc; }
775193326Sed
776193326Sed  void setSourceRange(SourceRange R) {
777207619Srdivacky    LBracLoc = R.getBegin();
778207619Srdivacky    RBracLoc = R.getEnd();
779193326Sed  }
780218893Sdim  SourceRange getSourceRange() const {
781207619Srdivacky    return SourceRange(LBracLoc, RBracLoc);
782193326Sed  }
783193326Sed
784193326Sed  static bool classof(const Stmt *T) {
785193326Sed    return T->getStmtClass() == ObjCMessageExprClass;
786193326Sed  }
787193326Sed  static bool classof(const ObjCMessageExpr *) { return true; }
788198092Srdivacky
789193326Sed  // Iterators
790218893Sdim  child_range children();
791198092Srdivacky
792193326Sed  typedef ExprIterator arg_iterator;
793193326Sed  typedef ConstExprIterator const_arg_iterator;
794198092Srdivacky
795218893Sdim  arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
796218893Sdim  arg_iterator arg_end()   {
797218893Sdim    return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
798193326Sed  }
799218893Sdim  const_arg_iterator arg_begin() const {
800218893Sdim    return reinterpret_cast<Stmt const * const*>(getArgs());
801218893Sdim  }
802218893Sdim  const_arg_iterator arg_end() const {
803218893Sdim    return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
804218893Sdim  }
805193326Sed
806218893Sdim  friend class ASTStmtReader;
807218893Sdim  friend class ASTStmtWriter;
808193326Sed};
809193326Sed
810198092Srdivacky/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
811198092Srdivacky/// (similiar in spirit to MemberExpr).
812198092Srdivackyclass ObjCIsaExpr : public Expr {
813198092Srdivacky  /// Base - the expression for the base object pointer.
814198092Srdivacky  Stmt *Base;
815198092Srdivacky
816198092Srdivacky  /// IsaMemberLoc - This is the location of the 'isa'.
817198092Srdivacky  SourceLocation IsaMemberLoc;
818198092Srdivacky
819198092Srdivacky  /// IsArrow - True if this is "X->F", false if this is "X.F".
820198092Srdivacky  bool IsArrow;
821198092Srdivackypublic:
822198092Srdivacky  ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
823218893Sdim    : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
824218893Sdim           /*TypeDependent=*/false, base->isValueDependent(),
825218893Sdim           /*ContainsUnexpandedParameterPack=*/false),
826198092Srdivacky      Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
827198092Srdivacky
828198092Srdivacky  /// \brief Build an empty expression.
829198092Srdivacky  explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
830198092Srdivacky
831198092Srdivacky  void setBase(Expr *E) { Base = E; }
832198092Srdivacky  Expr *getBase() const { return cast<Expr>(Base); }
833198092Srdivacky
834198092Srdivacky  bool isArrow() const { return IsArrow; }
835198092Srdivacky  void setArrow(bool A) { IsArrow = A; }
836198092Srdivacky
837198092Srdivacky  /// getMemberLoc - Return the location of the "member", in X->F, it is the
838198092Srdivacky  /// location of 'F'.
839198092Srdivacky  SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
840198092Srdivacky  void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
841198092Srdivacky
842218893Sdim  SourceRange getSourceRange() const {
843198092Srdivacky    return SourceRange(getBase()->getLocStart(), IsaMemberLoc);
844198092Srdivacky  }
845198092Srdivacky
846218893Sdim  SourceLocation getExprLoc() const { return IsaMemberLoc; }
847198092Srdivacky
848198092Srdivacky  static bool classof(const Stmt *T) {
849198092Srdivacky    return T->getStmtClass() == ObjCIsaExprClass;
850198092Srdivacky  }
851198092Srdivacky  static bool classof(const ObjCIsaExpr *) { return true; }
852198092Srdivacky
853198092Srdivacky  // Iterators
854218893Sdim  child_range children() { return child_range(&Base, &Base+1); }
855198092Srdivacky};
856198092Srdivacky
857193326Sed}  // end namespace clang
858193326Sed
859193326Sed#endif
860