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"
19226633Sdim#include "clang/AST/SelectorLocationsKind.h"
20193326Sed#include "clang/Basic/IdentifierTable.h"
21234353Sdim#include "llvm/Support/Compiler.h"
22193326Sed
23193326Sednamespace clang {
24193326Sed  class IdentifierInfo;
25193326Sed  class ASTContext;
26198092Srdivacky
27193326Sed/// ObjCStringLiteral, used for Objective-C string literals
28193326Sed/// i.e. @"foo".
29193326Sedclass ObjCStringLiteral : public Expr {
30193326Sed  Stmt *String;
31193326Sed  SourceLocation AtLoc;
32193326Sedpublic:
33193326Sed  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
34218893Sdim    : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
35224145Sdim           false, false),
36218893Sdim      String(SL), AtLoc(L) {}
37193326Sed  explicit ObjCStringLiteral(EmptyShell Empty)
38193326Sed    : Expr(ObjCStringLiteralClass, Empty) {}
39193326Sed
40193326Sed  StringLiteral *getString() { return cast<StringLiteral>(String); }
41193326Sed  const StringLiteral *getString() const { return cast<StringLiteral>(String); }
42193326Sed  void setString(StringLiteral *S) { String = S; }
43193326Sed
44193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
45193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
46193326Sed
47249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
48249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }
49198092Srdivacky
50198092Srdivacky  static bool classof(const Stmt *T) {
51198092Srdivacky    return T->getStmtClass() == ObjCStringLiteralClass;
52193326Sed  }
53198092Srdivacky
54193326Sed  // Iterators
55218893Sdim  child_range children() { return child_range(&String, &String+1); }
56193326Sed};
57198092Srdivacky
58234353Sdim/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
59234353Sdim///
60234353Sdimclass ObjCBoolLiteralExpr : public Expr {
61234353Sdim  bool Value;
62234353Sdim  SourceLocation Loc;
63234353Sdimpublic:
64234353Sdim  ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
65234353Sdim  Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
66234353Sdim       false, false), Value(val), Loc(l) {}
67234353Sdim
68234353Sdim  explicit ObjCBoolLiteralExpr(EmptyShell Empty)
69234353Sdim  : Expr(ObjCBoolLiteralExprClass, Empty) { }
70234353Sdim
71234353Sdim  bool getValue() const { return Value; }
72234353Sdim  void setValue(bool V) { Value = V; }
73234353Sdim
74249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
75249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
76249423Sdim
77234353Sdim  SourceLocation getLocation() const { return Loc; }
78234353Sdim  void setLocation(SourceLocation L) { Loc = L; }
79234353Sdim
80234353Sdim  static bool classof(const Stmt *T) {
81234353Sdim    return T->getStmtClass() == ObjCBoolLiteralExprClass;
82234353Sdim  }
83234353Sdim
84234353Sdim  // Iterators
85234353Sdim  child_range children() { return child_range(); }
86234353Sdim};
87234353Sdim
88239462Sdim/// ObjCBoxedExpr - used for generalized expression boxing.
89239462Sdim/// as in: @(strdup("hello world")) or @(random())
90239462Sdim/// Also used for boxing non-parenthesized numeric literals;
91239462Sdim/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc).
92239462Sdimclass ObjCBoxedExpr : public Expr {
93239462Sdim  Stmt *SubExpr;
94239462Sdim  ObjCMethodDecl *BoxingMethod;
95239462Sdim  SourceRange Range;
96234353Sdimpublic:
97239462Sdim  ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
98239462Sdim                     SourceRange R)
99239462Sdim  : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
100239462Sdim         E->isTypeDependent(), E->isValueDependent(),
101239462Sdim         E->isInstantiationDependent(), E->containsUnexpandedParameterPack()),
102239462Sdim         SubExpr(E), BoxingMethod(method), Range(R) {}
103239462Sdim  explicit ObjCBoxedExpr(EmptyShell Empty)
104239462Sdim  : Expr(ObjCBoxedExprClass, Empty) {}
105234353Sdim
106239462Sdim  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
107239462Sdim  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
108234353Sdim
109239462Sdim  ObjCMethodDecl *getBoxingMethod() const {
110239462Sdim    return BoxingMethod;
111234353Sdim  }
112234353Sdim
113239462Sdim  SourceLocation getAtLoc() const { return Range.getBegin(); }
114239462Sdim
115249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
116249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
117234353Sdim  SourceRange getSourceRange() const LLVM_READONLY {
118239462Sdim    return Range;
119234353Sdim  }
120239462Sdim
121234353Sdim  static bool classof(const Stmt *T) {
122239462Sdim    return T->getStmtClass() == ObjCBoxedExprClass;
123234353Sdim  }
124234353Sdim
125234353Sdim  // Iterators
126239462Sdim  child_range children() { return child_range(&SubExpr, &SubExpr+1); }
127239462Sdim
128234353Sdim  friend class ASTStmtReader;
129234353Sdim};
130234353Sdim
131234353Sdim/// ObjCArrayLiteral - used for objective-c array containers; as in:
132234353Sdim/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
133234353Sdimclass ObjCArrayLiteral : public Expr {
134234353Sdim  unsigned NumElements;
135234353Sdim  SourceRange Range;
136234353Sdim  ObjCMethodDecl *ArrayWithObjectsMethod;
137234353Sdim
138249423Sdim  ObjCArrayLiteral(ArrayRef<Expr *> Elements,
139234353Sdim                   QualType T, ObjCMethodDecl * Method,
140234353Sdim                   SourceRange SR);
141234353Sdim
142234353Sdim  explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
143234353Sdim    : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
144234353Sdim
145234353Sdimpublic:
146263508Sdim  static ObjCArrayLiteral *Create(const ASTContext &C,
147249423Sdim                                  ArrayRef<Expr *> Elements,
148234353Sdim                                  QualType T, ObjCMethodDecl * Method,
149234353Sdim                                  SourceRange SR);
150234353Sdim
151263508Sdim  static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
152263508Sdim                                       unsigned NumElements);
153234353Sdim
154249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
155249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
156234353Sdim  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
157234353Sdim
158234353Sdim  static bool classof(const Stmt *T) {
159234353Sdim      return T->getStmtClass() == ObjCArrayLiteralClass;
160234353Sdim  }
161234353Sdim
162234353Sdim  /// \brief Retrieve elements of array of literals.
163234353Sdim  Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); }
164234353Sdim
165234353Sdim  /// \brief Retrieve elements of array of literals.
166234353Sdim  const Expr * const *getElements() const {
167234353Sdim    return reinterpret_cast<const Expr * const*>(this + 1);
168234353Sdim  }
169234353Sdim
170234353Sdim  /// getNumElements - Return number of elements of objective-c array literal.
171234353Sdim  unsigned getNumElements() const { return NumElements; }
172234353Sdim
173234353Sdim    /// getExpr - Return the Expr at the specified index.
174234353Sdim  Expr *getElement(unsigned Index) {
175234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
176234353Sdim    return cast<Expr>(getElements()[Index]);
177234353Sdim  }
178234353Sdim  const Expr *getElement(unsigned Index) const {
179234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
180234353Sdim    return cast<Expr>(getElements()[Index]);
181234353Sdim  }
182234353Sdim
183234353Sdim  ObjCMethodDecl *getArrayWithObjectsMethod() const {
184234353Sdim    return ArrayWithObjectsMethod;
185234353Sdim  }
186234353Sdim
187234353Sdim  // Iterators
188234353Sdim  child_range children() {
189234353Sdim    return child_range((Stmt **)getElements(),
190234353Sdim                       (Stmt **)getElements() + NumElements);
191234353Sdim  }
192234353Sdim
193234353Sdim  friend class ASTStmtReader;
194234353Sdim};
195234353Sdim
196234353Sdim/// \brief An element in an Objective-C dictionary literal.
197234353Sdim///
198234353Sdimstruct ObjCDictionaryElement {
199234353Sdim  /// \brief The key for the dictionary element.
200234353Sdim  Expr *Key;
201234353Sdim
202234353Sdim  /// \brief The value of the dictionary element.
203234353Sdim  Expr *Value;
204234353Sdim
205234353Sdim  /// \brief The location of the ellipsis, if this is a pack expansion.
206234353Sdim  SourceLocation EllipsisLoc;
207234353Sdim
208234353Sdim  /// \brief The number of elements this pack expansion will expand to, if
209234353Sdim  /// this is a pack expansion and is known.
210249423Sdim  Optional<unsigned> NumExpansions;
211234353Sdim
212234353Sdim  /// \brief Determines whether this dictionary element is a pack expansion.
213234353Sdim  bool isPackExpansion() const { return EllipsisLoc.isValid(); }
214234353Sdim};
215249423Sdim} // end namespace clang
216234353Sdim
217249423Sdimnamespace llvm {
218249423Sdimtemplate <> struct isPodLike<clang::ObjCDictionaryElement> : llvm::true_type {};
219249423Sdim}
220249423Sdim
221249423Sdimnamespace clang {
222234353Sdim/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
223234353Sdim/// literals; as in:  @{@"name" : NSUserName(), @"date" : [NSDate date] };
224234353Sdimclass ObjCDictionaryLiteral : public Expr {
225234353Sdim  /// \brief Key/value pair used to store the key and value of a given element.
226234353Sdim  ///
227234353Sdim  /// Objects of this type are stored directly after the expression.
228234353Sdim  struct KeyValuePair {
229234353Sdim    Expr *Key;
230234353Sdim    Expr *Value;
231234353Sdim  };
232234353Sdim
233234353Sdim  /// \brief Data that describes an element that is a pack expansion, used if any
234234353Sdim  /// of the elements in the dictionary literal are pack expansions.
235234353Sdim  struct ExpansionData {
236234353Sdim    /// \brief The location of the ellipsis, if this element is a pack
237234353Sdim    /// expansion.
238234353Sdim    SourceLocation EllipsisLoc;
239234353Sdim
240234353Sdim    /// \brief If non-zero, the number of elements that this pack
241234353Sdim    /// expansion will expand to (+1).
242234353Sdim    unsigned NumExpansionsPlusOne;
243234353Sdim  };
244234353Sdim
245234353Sdim  /// \brief The number of elements in this dictionary literal.
246234353Sdim  unsigned NumElements : 31;
247234353Sdim
248234353Sdim  /// \brief Determine whether this dictionary literal has any pack expansions.
249234353Sdim  ///
250234353Sdim  /// If the dictionary literal has pack expansions, then there will
251234353Sdim  /// be an array of pack expansion data following the array of
252234353Sdim  /// key/value pairs, which provide the locations of the ellipses (if
253234353Sdim  /// any) and number of elements in the expansion (if known). If
254234353Sdim  /// there are no pack expansions, we optimize away this storage.
255234353Sdim  unsigned HasPackExpansions : 1;
256234353Sdim
257234353Sdim  SourceRange Range;
258234353Sdim  ObjCMethodDecl *DictWithObjectsMethod;
259234353Sdim
260234353Sdim  ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
261234353Sdim                        bool HasPackExpansions,
262234353Sdim                        QualType T, ObjCMethodDecl *method,
263234353Sdim                        SourceRange SR);
264234353Sdim
265234353Sdim  explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
266234353Sdim                                 bool HasPackExpansions)
267234353Sdim    : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
268234353Sdim      HasPackExpansions(HasPackExpansions) {}
269234353Sdim
270234353Sdim  KeyValuePair *getKeyValues() {
271234353Sdim    return reinterpret_cast<KeyValuePair *>(this + 1);
272234353Sdim  }
273234353Sdim
274234353Sdim  const KeyValuePair *getKeyValues() const {
275234353Sdim    return reinterpret_cast<const KeyValuePair *>(this + 1);
276234353Sdim  }
277234353Sdim
278234353Sdim  ExpansionData *getExpansionData() {
279234353Sdim    if (!HasPackExpansions)
280234353Sdim      return 0;
281234353Sdim
282234353Sdim    return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
283234353Sdim  }
284234353Sdim
285234353Sdim  const ExpansionData *getExpansionData() const {
286234353Sdim    if (!HasPackExpansions)
287234353Sdim      return 0;
288234353Sdim
289234353Sdim    return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
290234353Sdim  }
291234353Sdim
292234353Sdimpublic:
293263508Sdim  static ObjCDictionaryLiteral *Create(const ASTContext &C,
294234353Sdim                                       ArrayRef<ObjCDictionaryElement> VK,
295234353Sdim                                       bool HasPackExpansions,
296234353Sdim                                       QualType T, ObjCMethodDecl *method,
297234353Sdim                                       SourceRange SR);
298234353Sdim
299263508Sdim  static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
300234353Sdim                                            unsigned NumElements,
301234353Sdim                                            bool HasPackExpansions);
302234353Sdim
303234353Sdim  /// getNumElements - Return number of elements of objective-c dictionary
304234353Sdim  /// literal.
305234353Sdim  unsigned getNumElements() const { return NumElements; }
306234353Sdim
307234353Sdim  ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
308234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
309234353Sdim    const KeyValuePair &KV = getKeyValues()[Index];
310249423Sdim    ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
311234353Sdim    if (HasPackExpansions) {
312234353Sdim      const ExpansionData &Expansion = getExpansionData()[Index];
313234353Sdim      Result.EllipsisLoc = Expansion.EllipsisLoc;
314234353Sdim      if (Expansion.NumExpansionsPlusOne > 0)
315234353Sdim        Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
316234353Sdim    }
317234353Sdim    return Result;
318234353Sdim  }
319234353Sdim
320234353Sdim  ObjCMethodDecl *getDictWithObjectsMethod() const
321234353Sdim    { return DictWithObjectsMethod; }
322234353Sdim
323249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
324249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
325234353Sdim  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
326234353Sdim
327234353Sdim  static bool classof(const Stmt *T) {
328234353Sdim      return T->getStmtClass() == ObjCDictionaryLiteralClass;
329234353Sdim  }
330234353Sdim
331234353Sdim  // Iterators
332234353Sdim  child_range children() {
333234353Sdim    // Note: we're taking advantage of the layout of the KeyValuePair struct
334234353Sdim    // here. If that struct changes, this code will need to change as well.
335234353Sdim    return child_range(reinterpret_cast<Stmt **>(this + 1),
336234353Sdim                       reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
337234353Sdim  }
338234353Sdim
339234353Sdim  friend class ASTStmtReader;
340234353Sdim  friend class ASTStmtWriter;
341234353Sdim};
342234353Sdim
343234353Sdim
344239462Sdim/// ObjCEncodeExpr, used for \@encode in Objective-C.  \@encode has the same
345239462Sdim/// type and behavior as StringLiteral except that the string initializer is
346239462Sdim/// obtained from ASTContext with the encoding type as an argument.
347193326Sedclass ObjCEncodeExpr : public Expr {
348207619Srdivacky  TypeSourceInfo *EncodedType;
349193326Sed  SourceLocation AtLoc, RParenLoc;
350193326Sedpublic:
351207619Srdivacky  ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
352193326Sed                 SourceLocation at, SourceLocation rp)
353218893Sdim    : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
354218893Sdim           EncodedType->getType()->isDependentType(),
355218893Sdim           EncodedType->getType()->isDependentType(),
356224145Sdim           EncodedType->getType()->isInstantiationDependentType(),
357218893Sdim           EncodedType->getType()->containsUnexpandedParameterPack()),
358207619Srdivacky      EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
359198092Srdivacky
360193326Sed  explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
361193326Sed
362198092Srdivacky
363193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
364193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
365193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
366193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
367198092Srdivacky
368207619Srdivacky  QualType getEncodedType() const { return EncodedType->getType(); }
369193326Sed
370207619Srdivacky  TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
371207619Srdivacky  void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
372207619Srdivacky    EncodedType = EncType;
373207619Srdivacky  }
374198092Srdivacky
375249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
376249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
377198092Srdivacky
378193326Sed  static bool classof(const Stmt *T) {
379193326Sed    return T->getStmtClass() == ObjCEncodeExprClass;
380193326Sed  }
381198092Srdivacky
382193326Sed  // Iterators
383218893Sdim  child_range children() { return child_range(); }
384193326Sed};
385193326Sed
386239462Sdim/// ObjCSelectorExpr used for \@selector in Objective-C.
387193326Sedclass ObjCSelectorExpr : public Expr {
388193326Sed  Selector SelName;
389193326Sed  SourceLocation AtLoc, RParenLoc;
390193326Sedpublic:
391193326Sed  ObjCSelectorExpr(QualType T, Selector selInfo,
392193326Sed                   SourceLocation at, SourceLocation rp)
393218893Sdim    : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
394224145Sdim           false, false),
395218893Sdim    SelName(selInfo), AtLoc(at), RParenLoc(rp){}
396193326Sed  explicit ObjCSelectorExpr(EmptyShell Empty)
397193326Sed   : Expr(ObjCSelectorExprClass, Empty) {}
398193326Sed
399193326Sed  Selector getSelector() const { return SelName; }
400193326Sed  void setSelector(Selector S) { SelName = S; }
401198092Srdivacky
402193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
403193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
404193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
405193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
406193326Sed
407249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
408249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
409198092Srdivacky
410193326Sed  /// getNumArgs - Return the number of actual arguments to this call.
411193326Sed  unsigned getNumArgs() const { return SelName.getNumArgs(); }
412198092Srdivacky
413193326Sed  static bool classof(const Stmt *T) {
414193326Sed    return T->getStmtClass() == ObjCSelectorExprClass;
415193326Sed  }
416198092Srdivacky
417193326Sed  // Iterators
418218893Sdim  child_range children() { return child_range(); }
419193326Sed};
420198092Srdivacky
421249423Sdim/// ObjCProtocolExpr used for protocol expression in Objective-C.
422249423Sdim///
423249423Sdim/// This is used as: \@protocol(foo), as in:
424249423Sdim/// \code
425249423Sdim///   [obj conformsToProtocol:@protocol(foo)]
426249423Sdim/// \endcode
427249423Sdim///
428193326Sed/// The return type is "Protocol*".
429198092Srdivackyclass ObjCProtocolExpr : public Expr {
430198092Srdivacky  ObjCProtocolDecl *TheProtocol;
431239462Sdim  SourceLocation AtLoc, ProtoLoc, RParenLoc;
432193326Sedpublic:
433193326Sed  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
434239462Sdim                 SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
435218893Sdim    : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
436224145Sdim           false, false),
437239462Sdim      TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
438193326Sed  explicit ObjCProtocolExpr(EmptyShell Empty)
439193326Sed    : Expr(ObjCProtocolExprClass, Empty) {}
440193326Sed
441194613Sed  ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
442194613Sed  void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
443198092Srdivacky
444239462Sdim  SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
445193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
446193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
447193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
448193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
449193326Sed
450249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
451249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
452198092Srdivacky
453193326Sed  static bool classof(const Stmt *T) {
454193326Sed    return T->getStmtClass() == ObjCProtocolExprClass;
455193326Sed  }
456198092Srdivacky
457193326Sed  // Iterators
458218893Sdim  child_range children() { return child_range(); }
459239462Sdim
460239462Sdim  friend class ASTStmtReader;
461239462Sdim  friend class ASTStmtWriter;
462193326Sed};
463193326Sed
464193326Sed/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
465193326Sedclass ObjCIvarRefExpr : public Expr {
466234353Sdim  ObjCIvarDecl *D;
467234353Sdim  Stmt *Base;
468193326Sed  SourceLocation Loc;
469249423Sdim  /// OpLoc - This is the location of '.' or '->'
470249423Sdim  SourceLocation OpLoc;
471249423Sdim
472193326Sed  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
473193326Sed  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).
474198092Srdivacky
475193326Sedpublic:
476218893Sdim  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
477249423Sdim                  SourceLocation l, SourceLocation oploc,
478249423Sdim                  Expr *base,
479198092Srdivacky                  bool arrow = false, bool freeIvar = false) :
480251662Sdim    Expr(ObjCIvarRefExprClass, t, VK_LValue,
481251662Sdim         d->isBitField() ? OK_BitField : OK_Ordinary,
482218893Sdim         /*TypeDependent=*/false, base->isValueDependent(),
483224145Sdim         base->isInstantiationDependent(),
484218893Sdim         base->containsUnexpandedParameterPack()),
485249423Sdim    D(d), Base(base), Loc(l), OpLoc(oploc),
486249423Sdim    IsArrow(arrow), IsFreeIvar(freeIvar) {}
487198092Srdivacky
488193326Sed  explicit ObjCIvarRefExpr(EmptyShell Empty)
489193326Sed    : Expr(ObjCIvarRefExprClass, Empty) {}
490193326Sed
491193326Sed  ObjCIvarDecl *getDecl() { return D; }
492193326Sed  const ObjCIvarDecl *getDecl() const { return D; }
493193326Sed  void setDecl(ObjCIvarDecl *d) { D = d; }
494198092Srdivacky
495193326Sed  const Expr *getBase() const { return cast<Expr>(Base); }
496193326Sed  Expr *getBase() { return cast<Expr>(Base); }
497193326Sed  void setBase(Expr * base) { Base = base; }
498198092Srdivacky
499193326Sed  bool isArrow() const { return IsArrow; }
500193326Sed  bool isFreeIvar() const { return IsFreeIvar; }
501193326Sed  void setIsArrow(bool A) { IsArrow = A; }
502193326Sed  void setIsFreeIvar(bool A) { IsFreeIvar = A; }
503198092Srdivacky
504193326Sed  SourceLocation getLocation() const { return Loc; }
505193326Sed  void setLocation(SourceLocation L) { Loc = L; }
506193326Sed
507249423Sdim  SourceLocation getLocStart() const LLVM_READONLY {
508249423Sdim    return isFreeIvar() ? Loc : getBase()->getLocStart();
509193326Sed  }
510249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
511249423Sdim
512249423Sdim  SourceLocation getOpLoc() const { return OpLoc; }
513249423Sdim  void setOpLoc(SourceLocation L) { OpLoc = L; }
514198092Srdivacky
515198092Srdivacky  static bool classof(const Stmt *T) {
516198092Srdivacky    return T->getStmtClass() == ObjCIvarRefExprClass;
517193326Sed  }
518198092Srdivacky
519193326Sed  // Iterators
520218893Sdim  child_range children() { return child_range(&Base, &Base+1); }
521193326Sed};
522193326Sed
523193326Sed/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
524193326Sed/// property.
525193326Sedclass ObjCPropertyRefExpr : public Expr {
526193326Sedprivate:
527218893Sdim  /// If the bool is true, this is an implicit property reference; the
528218893Sdim  /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
529218893Sdim  /// if the bool is false, this is an explicit property reference;
530218893Sdim  /// the pointer is an ObjCPropertyDecl and Setter is always null.
531218893Sdim  llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
532218893Sdim
533234353Sdim  /// \brief Indicates whether the property reference will result in a message
534234353Sdim  /// to the getter, the setter, or both.
535234353Sdim  /// This applies to both implicit and explicit property references.
536234353Sdim  enum MethodRefFlags {
537234353Sdim    MethodRef_None = 0,
538234353Sdim    MethodRef_Getter = 0x1,
539234353Sdim    MethodRef_Setter = 0x2
540234353Sdim  };
541234353Sdim
542234353Sdim  /// \brief Contains the Setter method pointer and MethodRefFlags bit flags.
543234353Sdim  llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
544234353Sdim
545234353Sdim  // FIXME: Maybe we should store the property identifier here,
546234353Sdim  // because it's not rederivable from the other data when there's an
547234353Sdim  // implicit property with no getter (because the 'foo' -> 'setFoo:'
548234353Sdim  // transformation is lossy on the first character).
549234353Sdim
550193326Sed  SourceLocation IdLoc;
551218893Sdim
552218893Sdim  /// \brief When the receiver in property access is 'super', this is
553218893Sdim  /// the location of the 'super' keyword.  When it's an interface,
554218893Sdim  /// this is that interface.
555218893Sdim  SourceLocation ReceiverLoc;
556218893Sdim  llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
557218893Sdim
558193326Sedpublic:
559198092Srdivacky  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
560218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
561193326Sed                      SourceLocation l, Expr *base)
562218893Sdim    : Expr(ObjCPropertyRefExprClass, t, VK, OK,
563218893Sdim           /*TypeDependent=*/false, base->isValueDependent(),
564224145Sdim           base->isInstantiationDependent(),
565218893Sdim           base->containsUnexpandedParameterPack()),
566234353Sdim      PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
567218893Sdim      IdLoc(l), ReceiverLoc(), Receiver(base) {
568234353Sdim    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
569193326Sed  }
570218893Sdim
571218893Sdim  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
572218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
573218893Sdim                      SourceLocation l, SourceLocation sl, QualType st)
574218893Sdim    : Expr(ObjCPropertyRefExprClass, t, VK, OK,
575224145Sdim           /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
576218893Sdim           st->containsUnexpandedParameterPack()),
577234353Sdim      PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
578218893Sdim      IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
579234353Sdim    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
580218893Sdim  }
581198092Srdivacky
582218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
583218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
584218893Sdim                      SourceLocation IdLoc, Expr *Base)
585218893Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
586224145Sdim           Base->isValueDependent(), Base->isInstantiationDependent(),
587218893Sdim           Base->containsUnexpandedParameterPack()),
588234353Sdim      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
589218893Sdim      IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
590234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
591218893Sdim  }
592218893Sdim
593218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
594218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
595218893Sdim                      SourceLocation IdLoc,
596218893Sdim                      SourceLocation SuperLoc, QualType SuperTy)
597224145Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
598234353Sdim      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
599218893Sdim      IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
600234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
601218893Sdim  }
602218893Sdim
603218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
604218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
605218893Sdim                      SourceLocation IdLoc,
606218893Sdim                      SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
607224145Sdim    : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
608234353Sdim      PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
609218893Sdim      IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
610234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
611218893Sdim  }
612218893Sdim
613193326Sed  explicit ObjCPropertyRefExpr(EmptyShell Empty)
614193326Sed    : Expr(ObjCPropertyRefExprClass, Empty) {}
615193326Sed
616218893Sdim  bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
617218893Sdim  bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
618198092Srdivacky
619218893Sdim  ObjCPropertyDecl *getExplicitProperty() const {
620218893Sdim    assert(!isImplicitProperty());
621218893Sdim    return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
622218893Sdim  }
623198092Srdivacky
624218893Sdim  ObjCMethodDecl *getImplicitPropertyGetter() const {
625218893Sdim    assert(isImplicitProperty());
626218893Sdim    return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
627218893Sdim  }
628218893Sdim
629218893Sdim  ObjCMethodDecl *getImplicitPropertySetter() const {
630218893Sdim    assert(isImplicitProperty());
631234353Sdim    return SetterAndMethodRefFlags.getPointer();
632218893Sdim  }
633218893Sdim
634218893Sdim  Selector getGetterSelector() const {
635218893Sdim    if (isImplicitProperty())
636218893Sdim      return getImplicitPropertyGetter()->getSelector();
637218893Sdim    return getExplicitProperty()->getGetterName();
638218893Sdim  }
639218893Sdim
640218893Sdim  Selector getSetterSelector() const {
641218893Sdim    if (isImplicitProperty())
642218893Sdim      return getImplicitPropertySetter()->getSelector();
643218893Sdim    return getExplicitProperty()->getSetterName();
644218893Sdim  }
645218893Sdim
646234353Sdim  /// \brief True if the property reference will result in a message to the
647234353Sdim  /// getter.
648234353Sdim  /// This applies to both implicit and explicit property references.
649234353Sdim  bool isMessagingGetter() const {
650234353Sdim    return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
651234353Sdim  }
652234353Sdim
653234353Sdim  /// \brief True if the property reference will result in a message to the
654234353Sdim  /// setter.
655234353Sdim  /// This applies to both implicit and explicit property references.
656234353Sdim  bool isMessagingSetter() const {
657234353Sdim    return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
658234353Sdim  }
659234353Sdim
660234353Sdim  void setIsMessagingGetter(bool val = true) {
661234353Sdim    setMethodRefFlag(MethodRef_Getter, val);
662234353Sdim  }
663234353Sdim
664234353Sdim  void setIsMessagingSetter(bool val = true) {
665234353Sdim    setMethodRefFlag(MethodRef_Setter, val);
666234353Sdim  }
667234353Sdim
668218893Sdim  const Expr *getBase() const {
669218893Sdim    return cast<Expr>(Receiver.get<Stmt*>());
670218893Sdim  }
671218893Sdim  Expr *getBase() {
672218893Sdim    return cast<Expr>(Receiver.get<Stmt*>());
673218893Sdim  }
674218893Sdim
675193326Sed  SourceLocation getLocation() const { return IdLoc; }
676218893Sdim
677218893Sdim  SourceLocation getReceiverLocation() const { return ReceiverLoc; }
678218893Sdim  QualType getSuperReceiverType() const {
679218893Sdim    return QualType(Receiver.get<const Type*>(), 0);
680218893Sdim  }
681221345Sdim  QualType getGetterResultType() const {
682221345Sdim    QualType ResultType;
683221345Sdim    if (isExplicitProperty()) {
684221345Sdim      const ObjCPropertyDecl *PDecl = getExplicitProperty();
685221345Sdim      if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
686221345Sdim        ResultType = Getter->getResultType();
687221345Sdim      else
688234353Sdim        ResultType = PDecl->getType();
689221345Sdim    } else {
690221345Sdim      const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
691234353Sdim      if (Getter)
692234353Sdim        ResultType = Getter->getResultType(); // with reference!
693221345Sdim    }
694221345Sdim    return ResultType;
695221345Sdim  }
696234353Sdim
697221345Sdim  QualType getSetterArgType() const {
698221345Sdim    QualType ArgType;
699221345Sdim    if (isImplicitProperty()) {
700221345Sdim      const ObjCMethodDecl *Setter = getImplicitPropertySetter();
701226633Sdim      ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
702221345Sdim      ArgType = (*P)->getType();
703221345Sdim    } else {
704221345Sdim      if (ObjCPropertyDecl *PDecl = getExplicitProperty())
705221345Sdim        if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) {
706226633Sdim          ObjCMethodDecl::param_const_iterator P = Setter->param_begin();
707221345Sdim          ArgType = (*P)->getType();
708221345Sdim        }
709221345Sdim      if (ArgType.isNull())
710221345Sdim        ArgType = getType();
711221345Sdim    }
712221345Sdim    return ArgType;
713221345Sdim  }
714221345Sdim
715218893Sdim  ObjCInterfaceDecl *getClassReceiver() const {
716218893Sdim    return Receiver.get<ObjCInterfaceDecl*>();
717218893Sdim  }
718218893Sdim  bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
719218893Sdim  bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
720218893Sdim  bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
721193326Sed
722249423Sdim  SourceLocation getLocStart() const LLVM_READONLY {
723249423Sdim    return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
724193326Sed  }
725249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
726198092Srdivacky
727198092Srdivacky  static bool classof(const Stmt *T) {
728198092Srdivacky    return T->getStmtClass() == ObjCPropertyRefExprClass;
729193326Sed  }
730198092Srdivacky
731193326Sed  // Iterators
732218893Sdim  child_range children() {
733218893Sdim    if (Receiver.is<Stmt*>()) {
734218893Sdim      Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
735218893Sdim      return child_range(begin, begin+1);
736193326Sed    }
737218893Sdim    return child_range();
738193326Sed  }
739198092Srdivacky
740218893Sdimprivate:
741218893Sdim  friend class ASTStmtReader;
742234353Sdim  friend class ASTStmtWriter;
743234353Sdim  void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
744218893Sdim    PropertyOrGetter.setPointer(D);
745218893Sdim    PropertyOrGetter.setInt(false);
746234353Sdim    SetterAndMethodRefFlags.setPointer(0);
747234353Sdim    SetterAndMethodRefFlags.setInt(methRefFlags);
748193326Sed  }
749234353Sdim  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
750234353Sdim                           unsigned methRefFlags) {
751218893Sdim    PropertyOrGetter.setPointer(Getter);
752218893Sdim    PropertyOrGetter.setInt(true);
753234353Sdim    SetterAndMethodRefFlags.setPointer(Setter);
754234353Sdim    SetterAndMethodRefFlags.setInt(methRefFlags);
755218893Sdim  }
756218893Sdim  void setBase(Expr *Base) { Receiver = Base; }
757218893Sdim  void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
758218893Sdim  void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
759198092Srdivacky
760218893Sdim  void setLocation(SourceLocation L) { IdLoc = L; }
761218893Sdim  void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
762234353Sdim
763234353Sdim  void setMethodRefFlag(MethodRefFlags flag, bool val) {
764234353Sdim    unsigned f = SetterAndMethodRefFlags.getInt();
765234353Sdim    if (val)
766234353Sdim      f |= flag;
767234353Sdim    else
768234353Sdim      f &= ~flag;
769234353Sdim    SetterAndMethodRefFlags.setInt(f);
770234353Sdim  }
771193326Sed};
772234353Sdim
773234353Sdim/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
774234353Sdim/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
775234353Sdim///
776234353Sdimclass ObjCSubscriptRefExpr : public Expr {
777234353Sdim  // Location of ']' in an indexing expression.
778234353Sdim  SourceLocation RBracket;
779234353Sdim  // array/dictionary base expression.
780234353Sdim  // for arrays, this is a numeric expression. For dictionaries, this is
781234353Sdim  // an objective-c object pointer expression.
782234353Sdim  enum { BASE, KEY, END_EXPR };
783234353Sdim  Stmt* SubExprs[END_EXPR];
784234353Sdim
785234353Sdim  ObjCMethodDecl *GetAtIndexMethodDecl;
786234353Sdim
787234353Sdim  // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
788234353Sdim  // an indexed object this is null too.
789234353Sdim  ObjCMethodDecl *SetAtIndexMethodDecl;
790234353Sdim
791234353Sdimpublic:
792234353Sdim
793234353Sdim  ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
794234353Sdim                       ExprValueKind VK, ExprObjectKind OK,
795234353Sdim                       ObjCMethodDecl *getMethod,
796234353Sdim                       ObjCMethodDecl *setMethod, SourceLocation RB)
797234353Sdim    : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
798234353Sdim           base->isTypeDependent() || key->isTypeDependent(),
799234353Sdim           base->isValueDependent() || key->isValueDependent(),
800234353Sdim           base->isInstantiationDependent() || key->isInstantiationDependent(),
801234353Sdim           (base->containsUnexpandedParameterPack() ||
802234353Sdim            key->containsUnexpandedParameterPack())),
803234353Sdim      RBracket(RB),
804234353Sdim  GetAtIndexMethodDecl(getMethod),
805234353Sdim  SetAtIndexMethodDecl(setMethod)
806234353Sdim    {SubExprs[BASE] = base; SubExprs[KEY] = key;}
807198092Srdivacky
808234353Sdim  explicit ObjCSubscriptRefExpr(EmptyShell Empty)
809234353Sdim    : Expr(ObjCSubscriptRefExprClass, Empty) {}
810234353Sdim
811263508Sdim  static ObjCSubscriptRefExpr *Create(const ASTContext &C,
812234353Sdim                                      Expr *base,
813234353Sdim                                      Expr *key, QualType T,
814234353Sdim                                      ObjCMethodDecl *getMethod,
815234353Sdim                                      ObjCMethodDecl *setMethod,
816234353Sdim                                      SourceLocation RB);
817234353Sdim
818234353Sdim  SourceLocation getRBracket() const { return RBracket; }
819234353Sdim  void setRBracket(SourceLocation RB) { RBracket = RB; }
820249423Sdim
821249423Sdim  SourceLocation getLocStart() const LLVM_READONLY {
822249423Sdim    return SubExprs[BASE]->getLocStart();
823234353Sdim  }
824249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
825249423Sdim
826234353Sdim  static bool classof(const Stmt *T) {
827234353Sdim    return T->getStmtClass() == ObjCSubscriptRefExprClass;
828234353Sdim  }
829234353Sdim
830234353Sdim  Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
831234353Sdim  void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
832234353Sdim
833234353Sdim  Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
834234353Sdim  void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
835234353Sdim
836234353Sdim  ObjCMethodDecl *getAtIndexMethodDecl() const {
837234353Sdim    return GetAtIndexMethodDecl;
838234353Sdim  }
839234353Sdim
840234353Sdim  ObjCMethodDecl *setAtIndexMethodDecl() const {
841234353Sdim    return SetAtIndexMethodDecl;
842234353Sdim  }
843234353Sdim
844234353Sdim  bool isArraySubscriptRefExpr() const {
845234353Sdim    return getKeyExpr()->getType()->isIntegralOrEnumerationType();
846234353Sdim  }
847234353Sdim
848234353Sdim  child_range children() {
849234353Sdim    return child_range(SubExprs, SubExprs+END_EXPR);
850234353Sdim  }
851234353Sdimprivate:
852234353Sdim  friend class ASTStmtReader;
853234353Sdim};
854234353Sdim
855234353Sdim
856207619Srdivacky/// \brief An expression that sends a message to the given Objective-C
857207619Srdivacky/// object or class.
858207619Srdivacky///
859207619Srdivacky/// The following contains two message send expressions:
860207619Srdivacky///
861207619Srdivacky/// \code
862207619Srdivacky///   [[NSString alloc] initWithString:@"Hello"]
863207619Srdivacky/// \endcode
864207619Srdivacky///
865207619Srdivacky/// The innermost message send invokes the "alloc" class method on the
866207619Srdivacky/// NSString class, while the outermost message send invokes the
867207619Srdivacky/// "initWithString" instance method on the object returned from
868207619Srdivacky/// NSString's "alloc". In all, an Objective-C message send can take
869207619Srdivacky/// on four different (although related) forms:
870207619Srdivacky///
871207619Srdivacky///   1. Send to an object instance.
872207619Srdivacky///   2. Send to a class.
873207619Srdivacky///   3. Send to the superclass instance of the current class.
874207619Srdivacky///   4. Send to the superclass of the current class.
875207619Srdivacky///
876207619Srdivacky/// All four kinds of message sends are modeled by the ObjCMessageExpr
877207619Srdivacky/// class, and can be distinguished via \c getReceiverKind(). Example:
878207619Srdivacky///
879193326Sedclass ObjCMessageExpr : public Expr {
880226633Sdim  /// \brief Stores either the selector that this message is sending
881226633Sdim  /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
882226633Sdim  /// referring to the method that we type-checked against.
883226633Sdim  uintptr_t SelectorOrMethod;
884226633Sdim
885226633Sdim  enum { NumArgsBitWidth = 16 };
886226633Sdim
887207619Srdivacky  /// \brief The number of arguments in the message send, not
888207619Srdivacky  /// including the receiver.
889226633Sdim  unsigned NumArgs : NumArgsBitWidth;
890226633Sdim
891226633Sdim  void setNumArgs(unsigned Num) {
892226633Sdim    assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
893226633Sdim    NumArgs = Num;
894226633Sdim  }
895198092Srdivacky
896207619Srdivacky  /// \brief The kind of message send this is, which is one of the
897207619Srdivacky  /// ReceiverKind values.
898207619Srdivacky  ///
899207619Srdivacky  /// We pad this out to a byte to avoid excessive masking and shifting.
900207619Srdivacky  unsigned Kind : 8;
901198092Srdivacky
902207619Srdivacky  /// \brief Whether we have an actual method prototype in \c
903207619Srdivacky  /// SelectorOrMethod.
904207619Srdivacky  ///
905207619Srdivacky  /// When non-zero, we have a method declaration; otherwise, we just
906207619Srdivacky  /// have a selector.
907224145Sdim  unsigned HasMethod : 1;
908204962Srdivacky
909224145Sdim  /// \brief Whether this message send is a "delegate init call",
910224145Sdim  /// i.e. a call of an init method on self from within an init method.
911224145Sdim  unsigned IsDelegateInitCall : 1;
912234353Sdim
913234353Sdim  /// \brief Whether this message send was implicitly generated by
914234353Sdim  /// the implementation rather than explicitly written by the user.
915234353Sdim  unsigned IsImplicit : 1;
916234353Sdim
917226633Sdim  /// \brief Whether the locations of the selector identifiers are in a
918226633Sdim  /// "standard" position, a enum SelectorLocationsKind.
919226633Sdim  unsigned SelLocsKind : 2;
920224145Sdim
921207619Srdivacky  /// \brief When the message expression is a send to 'super', this is
922207619Srdivacky  /// the location of the 'super' keyword.
923207619Srdivacky  SourceLocation SuperLoc;
924198092Srdivacky
925207619Srdivacky  /// \brief The source locations of the open and close square
926207619Srdivacky  /// brackets ('[' and ']', respectively).
927207619Srdivacky  SourceLocation LBracLoc, RBracLoc;
928193326Sed
929207619Srdivacky  ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
930226633Sdim    : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
931234353Sdim      HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) {
932226633Sdim    setNumArgs(NumArgs);
933226633Sdim  }
934193326Sed
935218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
936207619Srdivacky                  SourceLocation LBracLoc,
937207619Srdivacky                  SourceLocation SuperLoc,
938207619Srdivacky                  bool IsInstanceSuper,
939207619Srdivacky                  QualType SuperType,
940207619Srdivacky                  Selector Sel,
941226633Sdim                  ArrayRef<SourceLocation> SelLocs,
942226633Sdim                  SelectorLocationsKind SelLocsK,
943207619Srdivacky                  ObjCMethodDecl *Method,
944226633Sdim                  ArrayRef<Expr *> Args,
945234353Sdim                  SourceLocation RBracLoc,
946234353Sdim                  bool isImplicit);
947218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
948207619Srdivacky                  SourceLocation LBracLoc,
949207619Srdivacky                  TypeSourceInfo *Receiver,
950207619Srdivacky                  Selector Sel,
951226633Sdim                  ArrayRef<SourceLocation> SelLocs,
952226633Sdim                  SelectorLocationsKind SelLocsK,
953207619Srdivacky                  ObjCMethodDecl *Method,
954226633Sdim                  ArrayRef<Expr *> Args,
955234353Sdim                  SourceLocation RBracLoc,
956234353Sdim                  bool isImplicit);
957218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
958207619Srdivacky                  SourceLocation LBracLoc,
959207619Srdivacky                  Expr *Receiver,
960207619Srdivacky                  Selector Sel,
961226633Sdim                  ArrayRef<SourceLocation> SelLocs,
962226633Sdim                  SelectorLocationsKind SelLocsK,
963207619Srdivacky                  ObjCMethodDecl *Method,
964226633Sdim                  ArrayRef<Expr *> Args,
965234353Sdim                  SourceLocation RBracLoc,
966234353Sdim                  bool isImplicit);
967198092Srdivacky
968226633Sdim  void initArgsAndSelLocs(ArrayRef<Expr *> Args,
969226633Sdim                          ArrayRef<SourceLocation> SelLocs,
970226633Sdim                          SelectorLocationsKind SelLocsK);
971226633Sdim
972207619Srdivacky  /// \brief Retrieve the pointer value of the message receiver.
973207619Srdivacky  void *getReceiverPointer() const {
974207619Srdivacky    return *const_cast<void **>(
975207619Srdivacky                             reinterpret_cast<const void * const*>(this + 1));
976207619Srdivacky  }
977207619Srdivacky
978207619Srdivacky  /// \brief Set the pointer value of the message receiver.
979207619Srdivacky  void setReceiverPointer(void *Value) {
980207619Srdivacky    *reinterpret_cast<void **>(this + 1) = Value;
981207619Srdivacky  }
982207619Srdivacky
983226633Sdim  SelectorLocationsKind getSelLocsKind() const {
984226633Sdim    return (SelectorLocationsKind)SelLocsKind;
985226633Sdim  }
986226633Sdim  bool hasStandardSelLocs() const {
987226633Sdim    return getSelLocsKind() != SelLoc_NonStandard;
988226633Sdim  }
989226633Sdim
990226633Sdim  /// \brief Get a pointer to the stored selector identifiers locations array.
991226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
992226633Sdim  SourceLocation *getStoredSelLocs() {
993226633Sdim    return reinterpret_cast<SourceLocation*>(getArgs() + getNumArgs());
994226633Sdim  }
995226633Sdim  const SourceLocation *getStoredSelLocs() const {
996226633Sdim    return reinterpret_cast<const SourceLocation*>(getArgs() + getNumArgs());
997226633Sdim  }
998226633Sdim
999226633Sdim  /// \brief Get the number of stored selector identifiers locations.
1000226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
1001226633Sdim  unsigned getNumStoredSelLocs() const {
1002226633Sdim    if (hasStandardSelLocs())
1003226633Sdim      return 0;
1004226633Sdim    return getNumSelectorLocs();
1005226633Sdim  }
1006226633Sdim
1007263508Sdim  static ObjCMessageExpr *alloc(const ASTContext &C,
1008226633Sdim                                ArrayRef<Expr *> Args,
1009226633Sdim                                SourceLocation RBraceLoc,
1010226633Sdim                                ArrayRef<SourceLocation> SelLocs,
1011226633Sdim                                Selector Sel,
1012226633Sdim                                SelectorLocationsKind &SelLocsK);
1013263508Sdim  static ObjCMessageExpr *alloc(const ASTContext &C,
1014226633Sdim                                unsigned NumArgs,
1015226633Sdim                                unsigned NumStoredSelLocs);
1016226633Sdim
1017193326Sedpublic:
1018207619Srdivacky  /// \brief The kind of receiver this message is sending to.
1019207619Srdivacky  enum ReceiverKind {
1020207619Srdivacky    /// \brief The receiver is a class.
1021207619Srdivacky    Class = 0,
1022207619Srdivacky    /// \brief The receiver is an object instance.
1023207619Srdivacky    Instance,
1024207619Srdivacky    /// \brief The receiver is a superclass.
1025207619Srdivacky    SuperClass,
1026207619Srdivacky    /// \brief The receiver is the instance of the superclass object.
1027207619Srdivacky    SuperInstance
1028207619Srdivacky  };
1029193326Sed
1030207619Srdivacky  /// \brief Create a message send to super.
1031207619Srdivacky  ///
1032207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1033207619Srdivacky  ///
1034207619Srdivacky  /// \param T The result type of this message.
1035207619Srdivacky  ///
1036218893Sdim  /// \param VK The value kind of this message.  A message returning
1037218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1038218893Sdim  /// respectively.
1039218893Sdim  ///
1040239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1041207619Srdivacky  ///
1042207619Srdivacky  /// \param SuperLoc The location of the "super" keyword.
1043207619Srdivacky  ///
1044207619Srdivacky  /// \param IsInstanceSuper Whether this is an instance "super"
1045207619Srdivacky  /// message (otherwise, it's a class "super" message).
1046207619Srdivacky  ///
1047207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1048207619Srdivacky  ///
1049207619Srdivacky  /// \param Method The Objective-C method against which this message
1050207619Srdivacky  /// send was type-checked. May be NULL.
1051207619Srdivacky  ///
1052207619Srdivacky  /// \param Args The message send arguments.
1053207619Srdivacky  ///
1054207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1055263508Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1056218893Sdim                                 ExprValueKind VK,
1057207619Srdivacky                                 SourceLocation LBracLoc,
1058207619Srdivacky                                 SourceLocation SuperLoc,
1059207619Srdivacky                                 bool IsInstanceSuper,
1060207619Srdivacky                                 QualType SuperType,
1061207619Srdivacky                                 Selector Sel,
1062226633Sdim                                 ArrayRef<SourceLocation> SelLocs,
1063207619Srdivacky                                 ObjCMethodDecl *Method,
1064226633Sdim                                 ArrayRef<Expr *> Args,
1065234353Sdim                                 SourceLocation RBracLoc,
1066234353Sdim                                 bool isImplicit);
1067198092Srdivacky
1068207619Srdivacky  /// \brief Create a class message send.
1069207619Srdivacky  ///
1070207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1071207619Srdivacky  ///
1072207619Srdivacky  /// \param T The result type of this message.
1073207619Srdivacky  ///
1074218893Sdim  /// \param VK The value kind of this message.  A message returning
1075218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1076218893Sdim  /// respectively.
1077218893Sdim  ///
1078239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1079207619Srdivacky  ///
1080207619Srdivacky  /// \param Receiver The type of the receiver, including
1081207619Srdivacky  /// source-location information.
1082207619Srdivacky  ///
1083207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1084207619Srdivacky  ///
1085207619Srdivacky  /// \param Method The Objective-C method against which this message
1086207619Srdivacky  /// send was type-checked. May be NULL.
1087207619Srdivacky  ///
1088207619Srdivacky  /// \param Args The message send arguments.
1089207619Srdivacky  ///
1090207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1091263508Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1092218893Sdim                                 ExprValueKind VK,
1093207619Srdivacky                                 SourceLocation LBracLoc,
1094207619Srdivacky                                 TypeSourceInfo *Receiver,
1095207619Srdivacky                                 Selector Sel,
1096226633Sdim                                 ArrayRef<SourceLocation> SelLocs,
1097207619Srdivacky                                 ObjCMethodDecl *Method,
1098226633Sdim                                 ArrayRef<Expr *> Args,
1099234353Sdim                                 SourceLocation RBracLoc,
1100234353Sdim                                 bool isImplicit);
1101198092Srdivacky
1102207619Srdivacky  /// \brief Create an instance message send.
1103207619Srdivacky  ///
1104207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1105207619Srdivacky  ///
1106207619Srdivacky  /// \param T The result type of this message.
1107207619Srdivacky  ///
1108218893Sdim  /// \param VK The value kind of this message.  A message returning
1109218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1110218893Sdim  /// respectively.
1111218893Sdim  ///
1112239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1113207619Srdivacky  ///
1114207619Srdivacky  /// \param Receiver The expression used to produce the object that
1115207619Srdivacky  /// will receive this message.
1116207619Srdivacky  ///
1117207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1118207619Srdivacky  ///
1119207619Srdivacky  /// \param Method The Objective-C method against which this message
1120207619Srdivacky  /// send was type-checked. May be NULL.
1121207619Srdivacky  ///
1122207619Srdivacky  /// \param Args The message send arguments.
1123207619Srdivacky  ///
1124207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1125263508Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1126218893Sdim                                 ExprValueKind VK,
1127207619Srdivacky                                 SourceLocation LBracLoc,
1128207619Srdivacky                                 Expr *Receiver,
1129207619Srdivacky                                 Selector Sel,
1130226633Sdim                                 ArrayRef<SourceLocation> SeLocs,
1131207619Srdivacky                                 ObjCMethodDecl *Method,
1132226633Sdim                                 ArrayRef<Expr *> Args,
1133234353Sdim                                 SourceLocation RBracLoc,
1134234353Sdim                                 bool isImplicit);
1135198092Srdivacky
1136207619Srdivacky  /// \brief Create an empty Objective-C message expression, to be
1137207619Srdivacky  /// filled in by subsequent calls.
1138207619Srdivacky  ///
1139207619Srdivacky  /// \param Context The context in which the message send will be created.
1140207619Srdivacky  ///
1141207619Srdivacky  /// \param NumArgs The number of message arguments, not including
1142207619Srdivacky  /// the receiver.
1143263508Sdim  static ObjCMessageExpr *CreateEmpty(const ASTContext &Context,
1144226633Sdim                                      unsigned NumArgs,
1145226633Sdim                                      unsigned NumStoredSelLocs);
1146198092Srdivacky
1147234353Sdim  /// \brief Indicates whether the message send was implicitly
1148234353Sdim  /// generated by the implementation. If false, it was written explicitly
1149234353Sdim  /// in the source code.
1150234353Sdim  bool isImplicit() const { return IsImplicit; }
1151234353Sdim
1152207619Srdivacky  /// \brief Determine the kind of receiver that this message is being
1153207619Srdivacky  /// sent to.
1154207619Srdivacky  ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
1155207619Srdivacky
1156218893Sdim  /// \brief Source range of the receiver.
1157218893Sdim  SourceRange getReceiverRange() const;
1158218893Sdim
1159207619Srdivacky  /// \brief Determine whether this is an instance message to either a
1160207619Srdivacky  /// computed object or to super.
1161207619Srdivacky  bool isInstanceMessage() const {
1162207619Srdivacky    return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
1163198092Srdivacky  }
1164207619Srdivacky
1165207619Srdivacky  /// \brief Determine whether this is an class message to either a
1166207619Srdivacky  /// specified class or to super.
1167207619Srdivacky  bool isClassMessage() const {
1168207619Srdivacky    return getReceiverKind() == Class || getReceiverKind() == SuperClass;
1169193326Sed  }
1170198092Srdivacky
1171243830Sdim  /// \brief Returns the object expression (receiver) for an instance message,
1172243830Sdim  /// or null for a message that is not an instance message.
1173207619Srdivacky  Expr *getInstanceReceiver() {
1174207619Srdivacky    if (getReceiverKind() == Instance)
1175207619Srdivacky      return static_cast<Expr *>(getReceiverPointer());
1176198092Srdivacky
1177207619Srdivacky    return 0;
1178207619Srdivacky  }
1179207619Srdivacky  const Expr *getInstanceReceiver() const {
1180207619Srdivacky    return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
1181207619Srdivacky  }
1182198092Srdivacky
1183207619Srdivacky  /// \brief Turn this message send into an instance message that
1184207619Srdivacky  /// computes the receiver object with the given expression.
1185207619Srdivacky  void setInstanceReceiver(Expr *rec) {
1186207619Srdivacky    Kind = Instance;
1187207619Srdivacky    setReceiverPointer(rec);
1188207619Srdivacky  }
1189207619Srdivacky
1190207619Srdivacky  /// \brief Returns the type of a class message send, or NULL if the
1191207619Srdivacky  /// message is not a class message.
1192207619Srdivacky  QualType getClassReceiver() const {
1193207619Srdivacky    if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
1194207619Srdivacky      return TSInfo->getType();
1195204962Srdivacky
1196207619Srdivacky    return QualType();
1197207619Srdivacky  }
1198204962Srdivacky
1199207619Srdivacky  /// \brief Returns a type-source information of a class message
1200207619Srdivacky  /// send, or NULL if the message is not a class message.
1201207619Srdivacky  TypeSourceInfo *getClassReceiverTypeInfo() const {
1202207619Srdivacky    if (getReceiverKind() == Class)
1203207619Srdivacky      return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
1204207619Srdivacky    return 0;
1205207619Srdivacky  }
1206204962Srdivacky
1207207619Srdivacky  void setClassReceiver(TypeSourceInfo *TSInfo) {
1208207619Srdivacky    Kind = Class;
1209207619Srdivacky    setReceiverPointer(TSInfo);
1210207619Srdivacky  }
1211204962Srdivacky
1212207619Srdivacky  /// \brief Retrieve the location of the 'super' keyword for a class
1213207619Srdivacky  /// or instance message to 'super', otherwise an invalid source location.
1214207619Srdivacky  SourceLocation getSuperLoc() const {
1215207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
1216207619Srdivacky      return SuperLoc;
1217198092Srdivacky
1218207619Srdivacky    return SourceLocation();
1219193326Sed  }
1220198092Srdivacky
1221243830Sdim  /// \brief Retrieve the receiver type to which this message is being directed.
1222243830Sdim  ///
1223243830Sdim  /// This routine cross-cuts all of the different kinds of message
1224243830Sdim  /// sends to determine what the underlying (statically known) type
1225243830Sdim  /// of the receiver will be; use \c getReceiverKind() to determine
1226243830Sdim  /// whether the message is a class or an instance method, whether it
1227243830Sdim  /// is a send to super or not, etc.
1228243830Sdim  ///
1229243830Sdim  /// \returns The type of the receiver.
1230243830Sdim  QualType getReceiverType() const;
1231243830Sdim
1232207619Srdivacky  /// \brief Retrieve the Objective-C interface to which this message
1233207619Srdivacky  /// is being directed, if known.
1234207619Srdivacky  ///
1235207619Srdivacky  /// This routine cross-cuts all of the different kinds of message
1236207619Srdivacky  /// sends to determine what the underlying (statically known) type
1237207619Srdivacky  /// of the receiver will be; use \c getReceiverKind() to determine
1238207619Srdivacky  /// whether the message is a class or an instance method, whether it
1239207619Srdivacky  /// is a send to super or not, etc.
1240207619Srdivacky  ///
1241207619Srdivacky  /// \returns The Objective-C interface if known, otherwise NULL.
1242207619Srdivacky  ObjCInterfaceDecl *getReceiverInterface() const;
1243207619Srdivacky
1244207619Srdivacky  /// \brief Retrieve the type referred to by 'super'.
1245207619Srdivacky  ///
1246207619Srdivacky  /// The returned type will either be an ObjCInterfaceType (for an
1247207619Srdivacky  /// class message to super) or an ObjCObjectPointerType that refers
1248207619Srdivacky  /// to a class (for an instance message to super);
1249207619Srdivacky  QualType getSuperType() const {
1250207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
1251207619Srdivacky      return QualType::getFromOpaquePtr(getReceiverPointer());
1252207619Srdivacky
1253207619Srdivacky    return QualType();
1254207619Srdivacky  }
1255207619Srdivacky
1256207619Srdivacky  void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
1257207619Srdivacky    Kind = IsInstanceSuper? SuperInstance : SuperClass;
1258207619Srdivacky    SuperLoc = Loc;
1259207619Srdivacky    setReceiverPointer(T.getAsOpaquePtr());
1260207619Srdivacky  }
1261207619Srdivacky
1262207619Srdivacky  Selector getSelector() const;
1263207619Srdivacky
1264207619Srdivacky  void setSelector(Selector S) {
1265207619Srdivacky    HasMethod = false;
1266207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
1267207619Srdivacky  }
1268207619Srdivacky
1269207619Srdivacky  const ObjCMethodDecl *getMethodDecl() const {
1270207619Srdivacky    if (HasMethod)
1271207619Srdivacky      return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
1272207619Srdivacky
1273207619Srdivacky    return 0;
1274207619Srdivacky  }
1275207619Srdivacky
1276207619Srdivacky  ObjCMethodDecl *getMethodDecl() {
1277207619Srdivacky    if (HasMethod)
1278207619Srdivacky      return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
1279207619Srdivacky
1280207619Srdivacky    return 0;
1281207619Srdivacky  }
1282207619Srdivacky
1283207619Srdivacky  void setMethodDecl(ObjCMethodDecl *MD) {
1284207619Srdivacky    HasMethod = true;
1285207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
1286207619Srdivacky  }
1287207619Srdivacky
1288221345Sdim  ObjCMethodFamily getMethodFamily() const {
1289221345Sdim    if (HasMethod) return getMethodDecl()->getMethodFamily();
1290221345Sdim    return getSelector().getMethodFamily();
1291221345Sdim  }
1292221345Sdim
1293207619Srdivacky  /// \brief Return the number of actual arguments in this message,
1294207619Srdivacky  /// not counting the receiver.
1295193326Sed  unsigned getNumArgs() const { return NumArgs; }
1296207619Srdivacky
1297207619Srdivacky  /// \brief Retrieve the arguments to this message, not including the
1298207619Srdivacky  /// receiver.
1299218893Sdim  Expr **getArgs() {
1300218893Sdim    return reinterpret_cast<Expr **>(this + 1) + 1;
1301193326Sed  }
1302218893Sdim  const Expr * const *getArgs() const {
1303218893Sdim    return reinterpret_cast<const Expr * const *>(this + 1) + 1;
1304207619Srdivacky  }
1305198092Srdivacky
1306193326Sed  /// getArg - Return the specified argument.
1307193326Sed  Expr *getArg(unsigned Arg) {
1308193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1309207619Srdivacky    return cast<Expr>(getArgs()[Arg]);
1310193326Sed  }
1311193326Sed  const Expr *getArg(unsigned Arg) const {
1312193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1313207619Srdivacky    return cast<Expr>(getArgs()[Arg]);
1314193326Sed  }
1315193326Sed  /// setArg - Set the specified argument.
1316193326Sed  void setArg(unsigned Arg, Expr *ArgExpr) {
1317193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1318207619Srdivacky    getArgs()[Arg] = ArgExpr;
1319193326Sed  }
1320198092Srdivacky
1321224145Sdim  /// isDelegateInitCall - Answers whether this message send has been
1322224145Sdim  /// tagged as a "delegate init call", i.e. a call to a method in the
1323224145Sdim  /// -init family on self from within an -init method implementation.
1324224145Sdim  bool isDelegateInitCall() const { return IsDelegateInitCall; }
1325224145Sdim  void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }
1326224145Sdim
1327207619Srdivacky  SourceLocation getLeftLoc() const { return LBracLoc; }
1328207619Srdivacky  SourceLocation getRightLoc() const { return RBracLoc; }
1329193326Sed
1330234353Sdim  SourceLocation getSelectorStartLoc() const {
1331234353Sdim    if (isImplicit())
1332234353Sdim      return getLocStart();
1333234353Sdim    return getSelectorLoc(0);
1334234353Sdim  }
1335226633Sdim  SourceLocation getSelectorLoc(unsigned Index) const {
1336226633Sdim    assert(Index < getNumSelectorLocs() && "Index out of range!");
1337226633Sdim    if (hasStandardSelLocs())
1338226633Sdim      return getStandardSelectorLoc(Index, getSelector(),
1339226633Sdim                                   getSelLocsKind() == SelLoc_StandardWithSpace,
1340226633Sdim                               llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
1341226633Sdim                                                  getNumArgs()),
1342226633Sdim                                   RBracLoc);
1343226633Sdim    return getStoredSelLocs()[Index];
1344226633Sdim  }
1345226633Sdim
1346226633Sdim  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
1347226633Sdim
1348226633Sdim  unsigned getNumSelectorLocs() const {
1349234353Sdim    if (isImplicit())
1350234353Sdim      return 0;
1351226633Sdim    Selector Sel = getSelector();
1352226633Sdim    if (Sel.isUnarySelector())
1353226633Sdim      return 1;
1354226633Sdim    return Sel.getNumArgs();
1355226633Sdim  }
1356226633Sdim
1357193326Sed  void setSourceRange(SourceRange R) {
1358207619Srdivacky    LBracLoc = R.getBegin();
1359207619Srdivacky    RBracLoc = R.getEnd();
1360193326Sed  }
1361249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
1362249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
1363193326Sed
1364193326Sed  static bool classof(const Stmt *T) {
1365193326Sed    return T->getStmtClass() == ObjCMessageExprClass;
1366193326Sed  }
1367198092Srdivacky
1368193326Sed  // Iterators
1369218893Sdim  child_range children();
1370198092Srdivacky
1371193326Sed  typedef ExprIterator arg_iterator;
1372193326Sed  typedef ConstExprIterator const_arg_iterator;
1373198092Srdivacky
1374218893Sdim  arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
1375218893Sdim  arg_iterator arg_end()   {
1376218893Sdim    return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
1377193326Sed  }
1378218893Sdim  const_arg_iterator arg_begin() const {
1379218893Sdim    return reinterpret_cast<Stmt const * const*>(getArgs());
1380218893Sdim  }
1381218893Sdim  const_arg_iterator arg_end() const {
1382218893Sdim    return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
1383218893Sdim  }
1384193326Sed
1385218893Sdim  friend class ASTStmtReader;
1386218893Sdim  friend class ASTStmtWriter;
1387193326Sed};
1388193326Sed
1389198092Srdivacky/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
1390221345Sdim/// (similar in spirit to MemberExpr).
1391198092Srdivackyclass ObjCIsaExpr : public Expr {
1392198092Srdivacky  /// Base - the expression for the base object pointer.
1393198092Srdivacky  Stmt *Base;
1394198092Srdivacky
1395198092Srdivacky  /// IsaMemberLoc - This is the location of the 'isa'.
1396198092Srdivacky  SourceLocation IsaMemberLoc;
1397249423Sdim
1398249423Sdim  /// OpLoc - This is the location of '.' or '->'
1399249423Sdim  SourceLocation OpLoc;
1400198092Srdivacky
1401198092Srdivacky  /// IsArrow - True if this is "X->F", false if this is "X.F".
1402198092Srdivacky  bool IsArrow;
1403198092Srdivackypublic:
1404249423Sdim  ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
1405249423Sdim              QualType ty)
1406218893Sdim    : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
1407218893Sdim           /*TypeDependent=*/false, base->isValueDependent(),
1408224145Sdim           base->isInstantiationDependent(),
1409218893Sdim           /*ContainsUnexpandedParameterPack=*/false),
1410249423Sdim      Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
1411198092Srdivacky
1412198092Srdivacky  /// \brief Build an empty expression.
1413198092Srdivacky  explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
1414198092Srdivacky
1415198092Srdivacky  void setBase(Expr *E) { Base = E; }
1416198092Srdivacky  Expr *getBase() const { return cast<Expr>(Base); }
1417198092Srdivacky
1418198092Srdivacky  bool isArrow() const { return IsArrow; }
1419198092Srdivacky  void setArrow(bool A) { IsArrow = A; }
1420198092Srdivacky
1421198092Srdivacky  /// getMemberLoc - Return the location of the "member", in X->F, it is the
1422198092Srdivacky  /// location of 'F'.
1423198092Srdivacky  SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
1424198092Srdivacky  void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
1425249423Sdim
1426249423Sdim  SourceLocation getOpLoc() const { return OpLoc; }
1427249423Sdim  void setOpLoc(SourceLocation L) { OpLoc = L; }
1428198092Srdivacky
1429249423Sdim  SourceLocation getLocStart() const LLVM_READONLY {
1430249423Sdim    return getBase()->getLocStart();
1431198092Srdivacky  }
1432249423Sdim
1433249423Sdim  SourceLocation getBaseLocEnd() const LLVM_READONLY {
1434249423Sdim    return getBase()->getLocEnd();
1435249423Sdim  }
1436249423Sdim
1437249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }
1438198092Srdivacky
1439234353Sdim  SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
1440198092Srdivacky
1441198092Srdivacky  static bool classof(const Stmt *T) {
1442198092Srdivacky    return T->getStmtClass() == ObjCIsaExprClass;
1443198092Srdivacky  }
1444198092Srdivacky
1445198092Srdivacky  // Iterators
1446218893Sdim  child_range children() { return child_range(&Base, &Base+1); }
1447198092Srdivacky};
1448198092Srdivacky
1449224145Sdim
1450224145Sdim/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
1451224145Sdim/// argument by indirect copy-restore in ARC.  This is used to support
1452224145Sdim/// passing indirect arguments with the wrong lifetime, e.g. when
1453224145Sdim/// passing the address of a __strong local variable to an 'out'
1454224145Sdim/// parameter.  This expression kind is only valid in an "argument"
1455224145Sdim/// position to some sort of call expression.
1456224145Sdim///
1457224145Sdim/// The parameter must have type 'pointer to T', and the argument must
1458224145Sdim/// have type 'pointer to U', where T and U agree except possibly in
1459224145Sdim/// qualification.  If the argument value is null, then a null pointer
1460224145Sdim/// is passed;  otherwise it points to an object A, and:
1461224145Sdim/// 1. A temporary object B of type T is initialized, either by
1462224145Sdim///    zero-initialization (used when initializing an 'out' parameter)
1463224145Sdim///    or copy-initialization (used when initializing an 'inout'
1464224145Sdim///    parameter).
1465224145Sdim/// 2. The address of the temporary is passed to the function.
1466224145Sdim/// 3. If the call completes normally, A is move-assigned from B.
1467224145Sdim/// 4. Finally, A is destroyed immediately.
1468224145Sdim///
1469224145Sdim/// Currently 'T' must be a retainable object lifetime and must be
1470224145Sdim/// __autoreleasing;  this qualifier is ignored when initializing
1471224145Sdim/// the value.
1472224145Sdimclass ObjCIndirectCopyRestoreExpr : public Expr {
1473224145Sdim  Stmt *Operand;
1474224145Sdim
1475224145Sdim  // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
1476224145Sdim
1477224145Sdim  friend class ASTReader;
1478224145Sdim  friend class ASTStmtReader;
1479224145Sdim
1480224145Sdim  void setShouldCopy(bool shouldCopy) {
1481224145Sdim    ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
1482224145Sdim  }
1483224145Sdim
1484224145Sdim  explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
1485224145Sdim    : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { }
1486224145Sdim
1487224145Sdimpublic:
1488224145Sdim  ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
1489224145Sdim    : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
1490224145Sdim           operand->isTypeDependent(), operand->isValueDependent(),
1491224145Sdim           operand->isInstantiationDependent(),
1492224145Sdim           operand->containsUnexpandedParameterPack()),
1493224145Sdim      Operand(operand) {
1494224145Sdim    setShouldCopy(shouldCopy);
1495224145Sdim  }
1496224145Sdim
1497224145Sdim  Expr *getSubExpr() { return cast<Expr>(Operand); }
1498224145Sdim  const Expr *getSubExpr() const { return cast<Expr>(Operand); }
1499224145Sdim
1500224145Sdim  /// shouldCopy - True if we should do the 'copy' part of the
1501224145Sdim  /// copy-restore.  If false, the temporary will be zero-initialized.
1502224145Sdim  bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
1503224145Sdim
1504224145Sdim  child_range children() { return child_range(&Operand, &Operand+1); }
1505224145Sdim
1506224145Sdim  // Source locations are determined by the subexpression.
1507249423Sdim  SourceLocation getLocStart() const LLVM_READONLY {
1508249423Sdim    return Operand->getLocStart();
1509234353Sdim  }
1510249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();}
1511249423Sdim
1512234353Sdim  SourceLocation getExprLoc() const LLVM_READONLY {
1513234353Sdim    return getSubExpr()->getExprLoc();
1514234353Sdim  }
1515224145Sdim
1516224145Sdim  static bool classof(const Stmt *s) {
1517224145Sdim    return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
1518224145Sdim  }
1519224145Sdim};
1520224145Sdim
1521224145Sdim/// \brief An Objective-C "bridged" cast expression, which casts between
1522224145Sdim/// Objective-C pointers and C pointers, transferring ownership in the process.
1523224145Sdim///
1524224145Sdim/// \code
1525224145Sdim/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
1526224145Sdim/// \endcode
1527224145Sdimclass ObjCBridgedCastExpr : public ExplicitCastExpr {
1528224145Sdim  SourceLocation LParenLoc;
1529224145Sdim  SourceLocation BridgeKeywordLoc;
1530224145Sdim  unsigned Kind : 2;
1531224145Sdim
1532224145Sdim  friend class ASTStmtReader;
1533224145Sdim  friend class ASTStmtWriter;
1534224145Sdim
1535224145Sdimpublic:
1536224145Sdim  ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
1537226633Sdim                      CastKind CK, SourceLocation BridgeKeywordLoc,
1538226633Sdim                      TypeSourceInfo *TSInfo, Expr *Operand)
1539224145Sdim    : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
1540226633Sdim                       CK, Operand, 0, TSInfo),
1541224145Sdim      LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
1542224145Sdim
1543224145Sdim  /// \brief Construct an empty Objective-C bridged cast.
1544224145Sdim  explicit ObjCBridgedCastExpr(EmptyShell Shell)
1545224145Sdim    : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }
1546224145Sdim
1547224145Sdim  SourceLocation getLParenLoc() const { return LParenLoc; }
1548224145Sdim
1549224145Sdim  /// \brief Determine which kind of bridge is being performed via this cast.
1550224145Sdim  ObjCBridgeCastKind getBridgeKind() const {
1551224145Sdim    return static_cast<ObjCBridgeCastKind>(Kind);
1552224145Sdim  }
1553224145Sdim
1554224145Sdim  /// \brief Retrieve the kind of bridge being performed as a string.
1555226633Sdim  StringRef getBridgeKindName() const;
1556224145Sdim
1557224145Sdim  /// \brief The location of the bridge keyword.
1558224145Sdim  SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
1559224145Sdim
1560249423Sdim  SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
1561249423Sdim  SourceLocation getLocEnd() const LLVM_READONLY {
1562249423Sdim    return getSubExpr()->getLocEnd();
1563224145Sdim  }
1564224145Sdim
1565224145Sdim  static bool classof(const Stmt *T) {
1566224145Sdim    return T->getStmtClass() == ObjCBridgedCastExprClass;
1567224145Sdim  }
1568224145Sdim};
1569224145Sdim
1570193326Sed}  // end namespace clang
1571193326Sed
1572193326Sed#endif
1573