1327952Sdim//===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed//
9193326Sed//  This file defines the ExprObjC interface and subclasses.
10193326Sed//
11193326Sed//===----------------------------------------------------------------------===//
12193326Sed
13193326Sed#ifndef LLVM_CLANG_AST_EXPROBJC_H
14193326Sed#define LLVM_CLANG_AST_EXPROBJC_H
15193326Sed
16327952Sdim#include "clang/AST/Decl.h"
17218893Sdim#include "clang/AST/DeclObjC.h"
18193326Sed#include "clang/AST/Expr.h"
19327952Sdim#include "clang/AST/OperationKinds.h"
20226633Sdim#include "clang/AST/SelectorLocationsKind.h"
21327952Sdim#include "clang/AST/Stmt.h"
22327952Sdim#include "clang/AST/Type.h"
23193326Sed#include "clang/Basic/IdentifierTable.h"
24327952Sdim#include "clang/Basic/LLVM.h"
25327952Sdim#include "clang/Basic/SourceLocation.h"
26327952Sdim#include "clang/Basic/Specifiers.h"
27327952Sdim#include "llvm/ADT/ArrayRef.h"
28327952Sdim#include "llvm/ADT/None.h"
29327952Sdim#include "llvm/ADT/Optional.h"
30327952Sdim#include "llvm/ADT/PointerIntPair.h"
31327952Sdim#include "llvm/ADT/PointerUnion.h"
32327952Sdim#include "llvm/ADT/StringRef.h"
33327952Sdim#include "llvm/ADT/iterator_range.h"
34327952Sdim#include "llvm/Support/Casting.h"
35234353Sdim#include "llvm/Support/Compiler.h"
36327952Sdim#include "llvm/Support/TrailingObjects.h"
37341825Sdim#include "llvm/Support/VersionTuple.h"
38327952Sdim#include "llvm/Support/type_traits.h"
39327952Sdim#include <cassert>
40327952Sdim#include <cstddef>
41327952Sdim#include <cstdint>
42193326Sed
43193326Sednamespace clang {
44198092Srdivacky
45327952Sdimclass ASTContext;
46327952Sdimclass CXXBaseSpecifier;
47327952Sdim
48193326Sed/// ObjCStringLiteral, used for Objective-C string literals
49193326Sed/// i.e. @"foo".
50193326Sedclass ObjCStringLiteral : public Expr {
51193326Sed  Stmt *String;
52193326Sed  SourceLocation AtLoc;
53327952Sdim
54193326Sedpublic:
55193326Sed  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
56327952Sdim      : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
57327952Sdim             false, false),
58327952Sdim        String(SL), AtLoc(L) {}
59193326Sed  explicit ObjCStringLiteral(EmptyShell Empty)
60327952Sdim      : Expr(ObjCStringLiteralClass, Empty) {}
61193326Sed
62193326Sed  StringLiteral *getString() { return cast<StringLiteral>(String); }
63193326Sed  const StringLiteral *getString() const { return cast<StringLiteral>(String); }
64193326Sed  void setString(StringLiteral *S) { String = S; }
65193326Sed
66193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
67193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
68193326Sed
69341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
70344779Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return String->getEndLoc(); }
71198092Srdivacky
72327952Sdim  // Iterators
73327952Sdim  child_range children() { return child_range(&String, &String+1); }
74327952Sdim
75353358Sdim  const_child_range children() const {
76353358Sdim    return const_child_range(&String, &String + 1);
77353358Sdim  }
78353358Sdim
79198092Srdivacky  static bool classof(const Stmt *T) {
80198092Srdivacky    return T->getStmtClass() == ObjCStringLiteralClass;
81193326Sed  }
82193326Sed};
83198092Srdivacky
84234353Sdim/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
85234353Sdimclass ObjCBoolLiteralExpr : public Expr {
86234353Sdim  bool Value;
87234353Sdim  SourceLocation Loc;
88327952Sdim
89234353Sdimpublic:
90327952Sdim  ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
91327952Sdim      : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
92327952Sdim             false, false),
93327952Sdim        Value(val), Loc(l) {}
94234353Sdim  explicit ObjCBoolLiteralExpr(EmptyShell Empty)
95327952Sdim      : Expr(ObjCBoolLiteralExprClass, Empty) {}
96341825Sdim
97234353Sdim  bool getValue() const { return Value; }
98234353Sdim  void setValue(bool V) { Value = V; }
99249423Sdim
100341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
101341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
102341825Sdim
103234353Sdim  SourceLocation getLocation() const { return Loc; }
104234353Sdim  void setLocation(SourceLocation L) { Loc = L; }
105341825Sdim
106234353Sdim  // Iterators
107296417Sdim  child_range children() {
108296417Sdim    return child_range(child_iterator(), child_iterator());
109296417Sdim  }
110327952Sdim
111353358Sdim  const_child_range children() const {
112353358Sdim    return const_child_range(const_child_iterator(), const_child_iterator());
113353358Sdim  }
114353358Sdim
115327952Sdim  static bool classof(const Stmt *T) {
116327952Sdim    return T->getStmtClass() == ObjCBoolLiteralExprClass;
117327952Sdim  }
118234353Sdim};
119234353Sdim
120239462Sdim/// ObjCBoxedExpr - used for generalized expression boxing.
121288943Sdim/// as in: @(strdup("hello world")), @(random()) or @(view.frame)
122239462Sdim/// Also used for boxing non-parenthesized numeric literals;
123314564Sdim/// as in: @42 or \@true (c++/objc++) or \@__objc_yes (c/objc).
124239462Sdimclass ObjCBoxedExpr : public Expr {
125239462Sdim  Stmt *SubExpr;
126239462Sdim  ObjCMethodDecl *BoxingMethod;
127239462Sdim  SourceRange Range;
128327952Sdim
129234353Sdimpublic:
130327952Sdim  friend class ASTStmtReader;
131327952Sdim
132239462Sdim  ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
133239462Sdim                     SourceRange R)
134341825Sdim      : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
135341825Sdim             E->isTypeDependent(), E->isValueDependent(),
136327952Sdim             E->isInstantiationDependent(),
137341825Sdim             E->containsUnexpandedParameterPack()),
138327952Sdim        SubExpr(E), BoxingMethod(method), Range(R) {}
139239462Sdim  explicit ObjCBoxedExpr(EmptyShell Empty)
140327952Sdim      : Expr(ObjCBoxedExprClass, Empty) {}
141341825Sdim
142239462Sdim  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
143239462Sdim  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
144341825Sdim
145239462Sdim  ObjCMethodDecl *getBoxingMethod() const {
146341825Sdim    return BoxingMethod;
147234353Sdim  }
148341825Sdim
149353358Sdim  // Indicates whether this boxed expression can be emitted as a compile-time
150353358Sdim  // constant.
151353358Sdim  bool isExpressibleAsConstantInitializer() const {
152353358Sdim    return !BoxingMethod && SubExpr;
153353358Sdim  }
154353358Sdim
155239462Sdim  SourceLocation getAtLoc() const { return Range.getBegin(); }
156327952Sdim
157341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
158341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
159341825Sdim
160234353Sdim  SourceRange getSourceRange() const LLVM_READONLY {
161239462Sdim    return Range;
162234353Sdim  }
163341825Sdim
164234353Sdim  // Iterators
165239462Sdim  child_range children() { return child_range(&SubExpr, &SubExpr+1); }
166280031Sdim
167353358Sdim  const_child_range children() const {
168353358Sdim    return const_child_range(&SubExpr, &SubExpr + 1);
169353358Sdim  }
170353358Sdim
171327952Sdim  using const_arg_iterator = ConstExprIterator;
172280031Sdim
173280031Sdim  const_arg_iterator arg_begin() const {
174280031Sdim    return reinterpret_cast<Stmt const * const*>(&SubExpr);
175280031Sdim  }
176327952Sdim
177280031Sdim  const_arg_iterator arg_end() const {
178280031Sdim    return reinterpret_cast<Stmt const * const*>(&SubExpr + 1);
179280031Sdim  }
180327952Sdim
181327952Sdim  static bool classof(const Stmt *T) {
182327952Sdim    return T->getStmtClass() == ObjCBoxedExprClass;
183327952Sdim  }
184234353Sdim};
185234353Sdim
186234353Sdim/// ObjCArrayLiteral - used for objective-c array containers; as in:
187234353Sdim/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
188296417Sdimclass ObjCArrayLiteral final
189296417Sdim    : public Expr,
190296417Sdim      private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> {
191234353Sdim  unsigned NumElements;
192234353Sdim  SourceRange Range;
193234353Sdim  ObjCMethodDecl *ArrayWithObjectsMethod;
194296417Sdim
195249423Sdim  ObjCArrayLiteral(ArrayRef<Expr *> Elements,
196234353Sdim                   QualType T, ObjCMethodDecl * Method,
197234353Sdim                   SourceRange SR);
198296417Sdim
199234353Sdim  explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
200327952Sdim      : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
201234353Sdim
202234353Sdimpublic:
203327952Sdim  friend class ASTStmtReader;
204327952Sdim  friend TrailingObjects;
205327952Sdim
206261991Sdim  static ObjCArrayLiteral *Create(const ASTContext &C,
207249423Sdim                                  ArrayRef<Expr *> Elements,
208234353Sdim                                  QualType T, ObjCMethodDecl * Method,
209234353Sdim                                  SourceRange SR);
210234353Sdim
211261991Sdim  static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
212261991Sdim                                       unsigned NumElements);
213234353Sdim
214341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
215341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
216234353Sdim  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
217234353Sdim
218341825Sdim  /// Retrieve elements of array of literals.
219296417Sdim  Expr **getElements() { return getTrailingObjects<Expr *>(); }
220234353Sdim
221341825Sdim  /// Retrieve elements of array of literals.
222296417Sdim  const Expr * const *getElements() const {
223296417Sdim    return getTrailingObjects<Expr *>();
224234353Sdim  }
225234353Sdim
226234353Sdim  /// getNumElements - Return number of elements of objective-c array literal.
227234353Sdim  unsigned getNumElements() const { return NumElements; }
228341825Sdim
229327952Sdim  /// getElement - Return the Element at the specified index.
230234353Sdim  Expr *getElement(unsigned Index) {
231234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
232341825Sdim    return getElements()[Index];
233234353Sdim  }
234234353Sdim  const Expr *getElement(unsigned Index) const {
235234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
236341825Sdim    return getElements()[Index];
237234353Sdim  }
238341825Sdim
239234353Sdim  ObjCMethodDecl *getArrayWithObjectsMethod() const {
240341825Sdim    return ArrayWithObjectsMethod;
241234353Sdim  }
242341825Sdim
243234353Sdim  // Iterators
244296417Sdim  child_range children() {
245296417Sdim    return child_range(reinterpret_cast<Stmt **>(getElements()),
246296417Sdim                       reinterpret_cast<Stmt **>(getElements()) + NumElements);
247234353Sdim  }
248296417Sdim
249353358Sdim  const_child_range children() const {
250353358Sdim    auto Children = const_cast<ObjCArrayLiteral *>(this)->children();
251353358Sdim    return const_child_range(Children.begin(), Children.end());
252353358Sdim  }
253353358Sdim
254327952Sdim  static bool classof(const Stmt *T) {
255327952Sdim      return T->getStmtClass() == ObjCArrayLiteralClass;
256327952Sdim  }
257234353Sdim};
258234353Sdim
259341825Sdim/// An element in an Objective-C dictionary literal.
260234353Sdim///
261234353Sdimstruct ObjCDictionaryElement {
262341825Sdim  /// The key for the dictionary element.
263234353Sdim  Expr *Key;
264341825Sdim
265341825Sdim  /// The value of the dictionary element.
266234353Sdim  Expr *Value;
267341825Sdim
268341825Sdim  /// The location of the ellipsis, if this is a pack expansion.
269234353Sdim  SourceLocation EllipsisLoc;
270341825Sdim
271341825Sdim  /// The number of elements this pack expansion will expand to, if
272234353Sdim  /// this is a pack expansion and is known.
273249423Sdim  Optional<unsigned> NumExpansions;
274234353Sdim
275341825Sdim  /// Determines whether this dictionary element is a pack expansion.
276234353Sdim  bool isPackExpansion() const { return EllipsisLoc.isValid(); }
277234353Sdim};
278234353Sdim
279327952Sdim} // namespace clang
280327952Sdim
281249423Sdimnamespace clang {
282327952Sdim
283341825Sdim/// Internal struct for storing Key/value pair.
284296417Sdimstruct ObjCDictionaryLiteral_KeyValuePair {
285296417Sdim  Expr *Key;
286296417Sdim  Expr *Value;
287296417Sdim};
288234353Sdim
289341825Sdim/// Internal struct to describes an element that is a pack
290296417Sdim/// expansion, used if any of the elements in the dictionary literal
291296417Sdim/// are pack expansions.
292296417Sdimstruct ObjCDictionaryLiteral_ExpansionData {
293341825Sdim  /// The location of the ellipsis, if this element is a pack
294296417Sdim  /// expansion.
295296417Sdim  SourceLocation EllipsisLoc;
296234353Sdim
297341825Sdim  /// If non-zero, the number of elements that this pack
298296417Sdim  /// expansion will expand to (+1).
299296417Sdim  unsigned NumExpansionsPlusOne;
300296417Sdim};
301296417Sdim
302296417Sdim/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
303296417Sdim/// literals; as in:  @{@"name" : NSUserName(), @"date" : [NSDate date] };
304296417Sdimclass ObjCDictionaryLiteral final
305296417Sdim    : public Expr,
306296417Sdim      private llvm::TrailingObjects<ObjCDictionaryLiteral,
307296417Sdim                                    ObjCDictionaryLiteral_KeyValuePair,
308296417Sdim                                    ObjCDictionaryLiteral_ExpansionData> {
309341825Sdim  /// The number of elements in this dictionary literal.
310234353Sdim  unsigned NumElements : 31;
311296417Sdim
312341825Sdim  /// Determine whether this dictionary literal has any pack expansions.
313234353Sdim  ///
314234353Sdim  /// If the dictionary literal has pack expansions, then there will
315234353Sdim  /// be an array of pack expansion data following the array of
316234353Sdim  /// key/value pairs, which provide the locations of the ellipses (if
317234353Sdim  /// any) and number of elements in the expansion (if known). If
318234353Sdim  /// there are no pack expansions, we optimize away this storage.
319234353Sdim  unsigned HasPackExpansions : 1;
320296417Sdim
321234353Sdim  SourceRange Range;
322234353Sdim  ObjCMethodDecl *DictWithObjectsMethod;
323296417Sdim
324327952Sdim  using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair;
325327952Sdim  using ExpansionData = ObjCDictionaryLiteral_ExpansionData;
326296417Sdim
327341825Sdim  ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
328234353Sdim                        bool HasPackExpansions,
329234353Sdim                        QualType T, ObjCMethodDecl *method,
330234353Sdim                        SourceRange SR);
331234353Sdim
332234353Sdim  explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
333234353Sdim                                 bool HasPackExpansions)
334327952Sdim      : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
335327952Sdim        HasPackExpansions(HasPackExpansions) {}
336234353Sdim
337327952Sdim  size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
338327952Sdim    return NumElements;
339327952Sdim  }
340327952Sdim
341234353Sdimpublic:
342327952Sdim  friend class ASTStmtReader;
343327952Sdim  friend class ASTStmtWriter;
344327952Sdim  friend TrailingObjects;
345327952Sdim
346261991Sdim  static ObjCDictionaryLiteral *Create(const ASTContext &C,
347341825Sdim                                       ArrayRef<ObjCDictionaryElement> VK,
348234353Sdim                                       bool HasPackExpansions,
349234353Sdim                                       QualType T, ObjCMethodDecl *method,
350234353Sdim                                       SourceRange SR);
351341825Sdim
352261991Sdim  static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
353234353Sdim                                            unsigned NumElements,
354234353Sdim                                            bool HasPackExpansions);
355341825Sdim
356341825Sdim  /// getNumElements - Return number of elements of objective-c dictionary
357234353Sdim  /// literal.
358234353Sdim  unsigned getNumElements() const { return NumElements; }
359234353Sdim
360234353Sdim  ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
361234353Sdim    assert((Index < NumElements) && "Arg access out of range!");
362296417Sdim    const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
363249423Sdim    ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
364234353Sdim    if (HasPackExpansions) {
365296417Sdim      const ExpansionData &Expansion =
366296417Sdim          getTrailingObjects<ExpansionData>()[Index];
367234353Sdim      Result.EllipsisLoc = Expansion.EllipsisLoc;
368234353Sdim      if (Expansion.NumExpansionsPlusOne > 0)
369234353Sdim        Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
370234353Sdim    }
371234353Sdim    return Result;
372234353Sdim  }
373341825Sdim
374327952Sdim  ObjCMethodDecl *getDictWithObjectsMethod() const {
375327952Sdim    return DictWithObjectsMethod;
376327952Sdim  }
377234353Sdim
378341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
379341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
380234353Sdim  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
381327952Sdim
382234353Sdim  // Iterators
383296417Sdim  child_range children() {
384234353Sdim    // Note: we're taking advantage of the layout of the KeyValuePair struct
385234353Sdim    // here. If that struct changes, this code will need to change as well.
386296417Sdim    static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
387296417Sdim                  "KeyValuePair is expected size");
388296417Sdim    return child_range(
389296417Sdim        reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()),
390296417Sdim        reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) +
391296417Sdim            NumElements * 2);
392234353Sdim  }
393327952Sdim
394353358Sdim  const_child_range children() const {
395353358Sdim    auto Children = const_cast<ObjCDictionaryLiteral *>(this)->children();
396353358Sdim    return const_child_range(Children.begin(), Children.end());
397353358Sdim  }
398353358Sdim
399327952Sdim  static bool classof(const Stmt *T) {
400327952Sdim    return T->getStmtClass() == ObjCDictionaryLiteralClass;
401327952Sdim  }
402234353Sdim};
403234353Sdim
404239462Sdim/// ObjCEncodeExpr, used for \@encode in Objective-C.  \@encode has the same
405239462Sdim/// type and behavior as StringLiteral except that the string initializer is
406239462Sdim/// obtained from ASTContext with the encoding type as an argument.
407193326Sedclass ObjCEncodeExpr : public Expr {
408207619Srdivacky  TypeSourceInfo *EncodedType;
409193326Sed  SourceLocation AtLoc, RParenLoc;
410327952Sdim
411193326Sedpublic:
412207619Srdivacky  ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
413193326Sed                 SourceLocation at, SourceLocation rp)
414327952Sdim      : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
415327952Sdim             EncodedType->getType()->isDependentType(),
416327952Sdim             EncodedType->getType()->isDependentType(),
417327952Sdim             EncodedType->getType()->isInstantiationDependentType(),
418341825Sdim             EncodedType->getType()->containsUnexpandedParameterPack()),
419327952Sdim        EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
420198092Srdivacky
421193326Sed  explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
422193326Sed
423193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
424193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
425193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
426193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
427198092Srdivacky
428207619Srdivacky  QualType getEncodedType() const { return EncodedType->getType(); }
429193326Sed
430207619Srdivacky  TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
431327952Sdim
432341825Sdim  void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
433341825Sdim    EncodedType = EncType;
434207619Srdivacky  }
435198092Srdivacky
436341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
437341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
438198092Srdivacky
439193326Sed  // Iterators
440296417Sdim  child_range children() {
441296417Sdim    return child_range(child_iterator(), child_iterator());
442296417Sdim  }
443327952Sdim
444353358Sdim  const_child_range children() const {
445353358Sdim    return const_child_range(const_child_iterator(), const_child_iterator());
446353358Sdim  }
447353358Sdim
448327952Sdim  static bool classof(const Stmt *T) {
449327952Sdim    return T->getStmtClass() == ObjCEncodeExprClass;
450327952Sdim  }
451193326Sed};
452193326Sed
453239462Sdim/// ObjCSelectorExpr used for \@selector in Objective-C.
454193326Sedclass ObjCSelectorExpr : public Expr {
455193326Sed  Selector SelName;
456193326Sed  SourceLocation AtLoc, RParenLoc;
457327952Sdim
458193326Sedpublic:
459193326Sed  ObjCSelectorExpr(QualType T, Selector selInfo,
460193326Sed                   SourceLocation at, SourceLocation rp)
461327952Sdim      : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
462327952Sdim             false, false),
463327952Sdim        SelName(selInfo), AtLoc(at), RParenLoc(rp) {}
464193326Sed  explicit ObjCSelectorExpr(EmptyShell Empty)
465327952Sdim      : Expr(ObjCSelectorExprClass, Empty) {}
466193326Sed
467193326Sed  Selector getSelector() const { return SelName; }
468193326Sed  void setSelector(Selector S) { SelName = S; }
469198092Srdivacky
470193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
471193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
472193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
473193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
474193326Sed
475341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
476341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
477198092Srdivacky
478193326Sed  /// getNumArgs - Return the number of actual arguments to this call.
479193326Sed  unsigned getNumArgs() const { return SelName.getNumArgs(); }
480198092Srdivacky
481193326Sed  // Iterators
482296417Sdim  child_range children() {
483296417Sdim    return child_range(child_iterator(), child_iterator());
484296417Sdim  }
485327952Sdim
486353358Sdim  const_child_range children() const {
487353358Sdim    return const_child_range(const_child_iterator(), const_child_iterator());
488353358Sdim  }
489353358Sdim
490327952Sdim  static bool classof(const Stmt *T) {
491327952Sdim    return T->getStmtClass() == ObjCSelectorExprClass;
492327952Sdim  }
493193326Sed};
494198092Srdivacky
495249423Sdim/// ObjCProtocolExpr used for protocol expression in Objective-C.
496249423Sdim///
497249423Sdim/// This is used as: \@protocol(foo), as in:
498249423Sdim/// \code
499249423Sdim///   [obj conformsToProtocol:@protocol(foo)]
500249423Sdim/// \endcode
501249423Sdim///
502193326Sed/// The return type is "Protocol*".
503198092Srdivackyclass ObjCProtocolExpr : public Expr {
504198092Srdivacky  ObjCProtocolDecl *TheProtocol;
505239462Sdim  SourceLocation AtLoc, ProtoLoc, RParenLoc;
506327952Sdim
507193326Sedpublic:
508327952Sdim  friend class ASTStmtReader;
509327952Sdim  friend class ASTStmtWriter;
510327952Sdim
511193326Sed  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
512239462Sdim                 SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
513327952Sdim      : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
514327952Sdim             false, false),
515327952Sdim        TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
516193326Sed  explicit ObjCProtocolExpr(EmptyShell Empty)
517327952Sdim      : Expr(ObjCProtocolExprClass, Empty) {}
518193326Sed
519194613Sed  ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
520194613Sed  void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
521198092Srdivacky
522239462Sdim  SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
523193326Sed  SourceLocation getAtLoc() const { return AtLoc; }
524193326Sed  SourceLocation getRParenLoc() const { return RParenLoc; }
525193326Sed  void setAtLoc(SourceLocation L) { AtLoc = L; }
526193326Sed  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
527193326Sed
528341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
529341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
530198092Srdivacky
531193326Sed  // Iterators
532296417Sdim  child_range children() {
533296417Sdim    return child_range(child_iterator(), child_iterator());
534296417Sdim  }
535239462Sdim
536353358Sdim  const_child_range children() const {
537353358Sdim    return const_child_range(const_child_iterator(), const_child_iterator());
538353358Sdim  }
539353358Sdim
540327952Sdim  static bool classof(const Stmt *T) {
541327952Sdim    return T->getStmtClass() == ObjCProtocolExprClass;
542327952Sdim  }
543193326Sed};
544193326Sed
545193326Sed/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
546193326Sedclass ObjCIvarRefExpr : public Expr {
547234353Sdim  ObjCIvarDecl *D;
548234353Sdim  Stmt *Base;
549193326Sed  SourceLocation Loc;
550327952Sdim
551249423Sdim  /// OpLoc - This is the location of '.' or '->'
552249423Sdim  SourceLocation OpLoc;
553198092Srdivacky
554327952Sdim  // True if this is "X->F", false if this is "X.F".
555327952Sdim  bool IsArrow : 1;
556327952Sdim
557327952Sdim  // True if ivar reference has no base (self assumed).
558327952Sdim  bool IsFreeIvar : 1;
559327952Sdim
560193326Sedpublic:
561218893Sdim  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
562249423Sdim                  SourceLocation l, SourceLocation oploc,
563249423Sdim                  Expr *base,
564327952Sdim                  bool arrow = false, bool freeIvar = false)
565327952Sdim      : Expr(ObjCIvarRefExprClass, t, VK_LValue,
566327952Sdim             d->isBitField() ? OK_BitField : OK_Ordinary,
567341825Sdim             /*TypeDependent=*/false, base->isValueDependent(),
568327952Sdim             base->isInstantiationDependent(),
569341825Sdim             base->containsUnexpandedParameterPack()),
570327952Sdim        D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow),
571327952Sdim        IsFreeIvar(freeIvar) {}
572198092Srdivacky
573193326Sed  explicit ObjCIvarRefExpr(EmptyShell Empty)
574327952Sdim      : Expr(ObjCIvarRefExprClass, Empty) {}
575193326Sed
576193326Sed  ObjCIvarDecl *getDecl() { return D; }
577193326Sed  const ObjCIvarDecl *getDecl() const { return D; }
578193326Sed  void setDecl(ObjCIvarDecl *d) { D = d; }
579198092Srdivacky
580193326Sed  const Expr *getBase() const { return cast<Expr>(Base); }
581193326Sed  Expr *getBase() { return cast<Expr>(Base); }
582193326Sed  void setBase(Expr * base) { Base = base; }
583198092Srdivacky
584193326Sed  bool isArrow() const { return IsArrow; }
585193326Sed  bool isFreeIvar() const { return IsFreeIvar; }
586193326Sed  void setIsArrow(bool A) { IsArrow = A; }
587193326Sed  void setIsFreeIvar(bool A) { IsFreeIvar = A; }
588198092Srdivacky
589193326Sed  SourceLocation getLocation() const { return Loc; }
590193326Sed  void setLocation(SourceLocation L) { Loc = L; }
591193326Sed
592341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY {
593344779Sdim    return isFreeIvar() ? Loc : getBase()->getBeginLoc();
594193326Sed  }
595341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
596341825Sdim
597249423Sdim  SourceLocation getOpLoc() const { return OpLoc; }
598249423Sdim  void setOpLoc(SourceLocation L) { OpLoc = L; }
599198092Srdivacky
600327952Sdim  // Iterators
601327952Sdim  child_range children() { return child_range(&Base, &Base+1); }
602327952Sdim
603353358Sdim  const_child_range children() const {
604353358Sdim    return const_child_range(&Base, &Base + 1);
605353358Sdim  }
606353358Sdim
607198092Srdivacky  static bool classof(const Stmt *T) {
608198092Srdivacky    return T->getStmtClass() == ObjCIvarRefExprClass;
609193326Sed  }
610193326Sed};
611193326Sed
612193326Sed/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
613193326Sed/// property.
614193326Sedclass ObjCPropertyRefExpr : public Expr {
615193326Sedprivate:
616218893Sdim  /// If the bool is true, this is an implicit property reference; the
617218893Sdim  /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
618218893Sdim  /// if the bool is false, this is an explicit property reference;
619218893Sdim  /// the pointer is an ObjCPropertyDecl and Setter is always null.
620327952Sdim  llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter;
621218893Sdim
622341825Sdim  /// Indicates whether the property reference will result in a message
623234353Sdim  /// to the getter, the setter, or both.
624234353Sdim  /// This applies to both implicit and explicit property references.
625234353Sdim  enum MethodRefFlags {
626234353Sdim    MethodRef_None = 0,
627234353Sdim    MethodRef_Getter = 0x1,
628234353Sdim    MethodRef_Setter = 0x2
629234353Sdim  };
630234353Sdim
631341825Sdim  /// Contains the Setter method pointer and MethodRefFlags bit flags.
632234353Sdim  llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
633234353Sdim
634234353Sdim  // FIXME: Maybe we should store the property identifier here,
635234353Sdim  // because it's not rederivable from the other data when there's an
636234353Sdim  // implicit property with no getter (because the 'foo' -> 'setFoo:'
637234353Sdim  // transformation is lossy on the first character).
638234353Sdim
639193326Sed  SourceLocation IdLoc;
640341825Sdim
641341825Sdim  /// When the receiver in property access is 'super', this is
642218893Sdim  /// the location of the 'super' keyword.  When it's an interface,
643218893Sdim  /// this is that interface.
644218893Sdim  SourceLocation ReceiverLoc;
645360784Sdim  llvm::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;
646341825Sdim
647193326Sedpublic:
648198092Srdivacky  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
649218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
650193326Sed                      SourceLocation l, Expr *base)
651327952Sdim      : Expr(ObjCPropertyRefExprClass, t, VK, OK,
652327952Sdim             /*TypeDependent=*/false, base->isValueDependent(),
653327952Sdim             base->isInstantiationDependent(),
654327952Sdim             base->containsUnexpandedParameterPack()),
655327952Sdim        PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) {
656234353Sdim    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
657193326Sed  }
658341825Sdim
659218893Sdim  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
660218893Sdim                      ExprValueKind VK, ExprObjectKind OK,
661218893Sdim                      SourceLocation l, SourceLocation sl, QualType st)
662327952Sdim      : Expr(ObjCPropertyRefExprClass, t, VK, OK,
663327952Sdim             /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
664327952Sdim             st->containsUnexpandedParameterPack()),
665327952Sdim        PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl),
666327952Sdim        Receiver(st.getTypePtr()) {
667234353Sdim    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
668218893Sdim  }
669198092Srdivacky
670218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
671218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
672218893Sdim                      SourceLocation IdLoc, Expr *Base)
673327952Sdim      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
674327952Sdim             Base->isValueDependent(), Base->isInstantiationDependent(),
675327952Sdim             Base->containsUnexpandedParameterPack()),
676327952Sdim        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
677327952Sdim        IdLoc(IdLoc), Receiver(Base) {
678234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
679218893Sdim  }
680218893Sdim
681218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
682218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
683218893Sdim                      SourceLocation IdLoc,
684218893Sdim                      SourceLocation SuperLoc, QualType SuperTy)
685327952Sdim      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
686327952Sdim        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
687327952Sdim        IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
688234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
689218893Sdim  }
690218893Sdim
691218893Sdim  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
692218893Sdim                      QualType T, ExprValueKind VK, ExprObjectKind OK,
693218893Sdim                      SourceLocation IdLoc,
694218893Sdim                      SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
695327952Sdim      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
696327952Sdim        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
697327952Sdim        IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
698234353Sdim    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
699218893Sdim  }
700218893Sdim
701193326Sed  explicit ObjCPropertyRefExpr(EmptyShell Empty)
702327952Sdim      : Expr(ObjCPropertyRefExprClass, Empty) {}
703193326Sed
704218893Sdim  bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
705218893Sdim  bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
706198092Srdivacky
707218893Sdim  ObjCPropertyDecl *getExplicitProperty() const {
708218893Sdim    assert(!isImplicitProperty());
709218893Sdim    return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
710218893Sdim  }
711198092Srdivacky
712218893Sdim  ObjCMethodDecl *getImplicitPropertyGetter() const {
713218893Sdim    assert(isImplicitProperty());
714218893Sdim    return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
715218893Sdim  }
716218893Sdim
717218893Sdim  ObjCMethodDecl *getImplicitPropertySetter() const {
718218893Sdim    assert(isImplicitProperty());
719234353Sdim    return SetterAndMethodRefFlags.getPointer();
720218893Sdim  }
721218893Sdim
722218893Sdim  Selector getGetterSelector() const {
723218893Sdim    if (isImplicitProperty())
724218893Sdim      return getImplicitPropertyGetter()->getSelector();
725218893Sdim    return getExplicitProperty()->getGetterName();
726218893Sdim  }
727218893Sdim
728218893Sdim  Selector getSetterSelector() const {
729218893Sdim    if (isImplicitProperty())
730218893Sdim      return getImplicitPropertySetter()->getSelector();
731218893Sdim    return getExplicitProperty()->getSetterName();
732218893Sdim  }
733218893Sdim
734341825Sdim  /// True if the property reference will result in a message to the
735234353Sdim  /// getter.
736234353Sdim  /// This applies to both implicit and explicit property references.
737234353Sdim  bool isMessagingGetter() const {
738234353Sdim    return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
739234353Sdim  }
740234353Sdim
741341825Sdim  /// True if the property reference will result in a message to the
742234353Sdim  /// setter.
743234353Sdim  /// This applies to both implicit and explicit property references.
744234353Sdim  bool isMessagingSetter() const {
745234353Sdim    return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
746234353Sdim  }
747234353Sdim
748234353Sdim  void setIsMessagingGetter(bool val = true) {
749234353Sdim    setMethodRefFlag(MethodRef_Getter, val);
750234353Sdim  }
751234353Sdim
752234353Sdim  void setIsMessagingSetter(bool val = true) {
753234353Sdim    setMethodRefFlag(MethodRef_Setter, val);
754234353Sdim  }
755234353Sdim
756341825Sdim  const Expr *getBase() const {
757341825Sdim    return cast<Expr>(Receiver.get<Stmt*>());
758218893Sdim  }
759341825Sdim  Expr *getBase() {
760341825Sdim    return cast<Expr>(Receiver.get<Stmt*>());
761218893Sdim  }
762218893Sdim
763193326Sed  SourceLocation getLocation() const { return IdLoc; }
764341825Sdim
765218893Sdim  SourceLocation getReceiverLocation() const { return ReceiverLoc; }
766327952Sdim
767341825Sdim  QualType getSuperReceiverType() const {
768341825Sdim    return QualType(Receiver.get<const Type*>(), 0);
769218893Sdim  }
770234353Sdim
771218893Sdim  ObjCInterfaceDecl *getClassReceiver() const {
772218893Sdim    return Receiver.get<ObjCInterfaceDecl*>();
773218893Sdim  }
774327952Sdim
775218893Sdim  bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
776218893Sdim  bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
777218893Sdim  bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
778193326Sed
779288943Sdim  /// Determine the type of the base, regardless of the kind of receiver.
780288943Sdim  QualType getReceiverType(const ASTContext &ctx) const;
781288943Sdim
782341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY {
783344779Sdim    return isObjectReceiver() ? getBase()->getBeginLoc()
784344779Sdim                              : getReceiverLocation();
785193326Sed  }
786327952Sdim
787341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return IdLoc; }
788198092Srdivacky
789193326Sed  // Iterators
790218893Sdim  child_range children() {
791218893Sdim    if (Receiver.is<Stmt*>()) {
792218893Sdim      Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
793218893Sdim      return child_range(begin, begin+1);
794193326Sed    }
795296417Sdim    return child_range(child_iterator(), child_iterator());
796193326Sed  }
797198092Srdivacky
798353358Sdim  const_child_range children() const {
799353358Sdim    auto Children = const_cast<ObjCPropertyRefExpr *>(this)->children();
800353358Sdim    return const_child_range(Children.begin(), Children.end());
801353358Sdim  }
802353358Sdim
803327952Sdim  static bool classof(const Stmt *T) {
804327952Sdim    return T->getStmtClass() == ObjCPropertyRefExprClass;
805327952Sdim  }
806327952Sdim
807218893Sdimprivate:
808218893Sdim  friend class ASTStmtReader;
809234353Sdim  friend class ASTStmtWriter;
810327952Sdim
811234353Sdim  void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
812218893Sdim    PropertyOrGetter.setPointer(D);
813218893Sdim    PropertyOrGetter.setInt(false);
814276479Sdim    SetterAndMethodRefFlags.setPointer(nullptr);
815234353Sdim    SetterAndMethodRefFlags.setInt(methRefFlags);
816193326Sed  }
817327952Sdim
818234353Sdim  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
819234353Sdim                           unsigned methRefFlags) {
820218893Sdim    PropertyOrGetter.setPointer(Getter);
821218893Sdim    PropertyOrGetter.setInt(true);
822234353Sdim    SetterAndMethodRefFlags.setPointer(Setter);
823234353Sdim    SetterAndMethodRefFlags.setInt(methRefFlags);
824218893Sdim  }
825327952Sdim
826218893Sdim  void setBase(Expr *Base) { Receiver = Base; }
827218893Sdim  void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
828218893Sdim  void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
829198092Srdivacky
830218893Sdim  void setLocation(SourceLocation L) { IdLoc = L; }
831218893Sdim  void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
832234353Sdim
833234353Sdim  void setMethodRefFlag(MethodRefFlags flag, bool val) {
834234353Sdim    unsigned f = SetterAndMethodRefFlags.getInt();
835234353Sdim    if (val)
836234353Sdim      f |= flag;
837234353Sdim    else
838234353Sdim      f &= ~flag;
839234353Sdim    SetterAndMethodRefFlags.setInt(f);
840234353Sdim  }
841193326Sed};
842341825Sdim
843234353Sdim/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
844234353Sdim/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
845234353Sdimclass ObjCSubscriptRefExpr : public Expr {
846234353Sdim  // Location of ']' in an indexing expression.
847234353Sdim  SourceLocation RBracket;
848327952Sdim
849234353Sdim  // array/dictionary base expression.
850234353Sdim  // for arrays, this is a numeric expression. For dictionaries, this is
851234353Sdim  // an objective-c object pointer expression.
852234353Sdim  enum { BASE, KEY, END_EXPR };
853234353Sdim  Stmt* SubExprs[END_EXPR];
854341825Sdim
855234353Sdim  ObjCMethodDecl *GetAtIndexMethodDecl;
856341825Sdim
857234353Sdim  // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
858234353Sdim  // an indexed object this is null too.
859234353Sdim  ObjCMethodDecl *SetAtIndexMethodDecl;
860341825Sdim
861234353Sdimpublic:
862234353Sdim  ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
863234353Sdim                       ExprValueKind VK, ExprObjectKind OK,
864234353Sdim                       ObjCMethodDecl *getMethod,
865234353Sdim                       ObjCMethodDecl *setMethod, SourceLocation RB)
866341825Sdim      : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
867341825Sdim             base->isTypeDependent() || key->isTypeDependent(),
868327952Sdim             base->isValueDependent() || key->isValueDependent(),
869327952Sdim             (base->isInstantiationDependent() ||
870327952Sdim              key->isInstantiationDependent()),
871327952Sdim             (base->containsUnexpandedParameterPack() ||
872327952Sdim              key->containsUnexpandedParameterPack())),
873327952Sdim        RBracket(RB), GetAtIndexMethodDecl(getMethod),
874327952Sdim        SetAtIndexMethodDecl(setMethod) {
875327952Sdim    SubExprs[BASE] = base; SubExprs[KEY] = key;
876327952Sdim  }
877198092Srdivacky
878234353Sdim  explicit ObjCSubscriptRefExpr(EmptyShell Empty)
879327952Sdim      : Expr(ObjCSubscriptRefExprClass, Empty) {}
880341825Sdim
881234353Sdim  SourceLocation getRBracket() const { return RBracket; }
882234353Sdim  void setRBracket(SourceLocation RB) { RBracket = RB; }
883249423Sdim
884341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY {
885344779Sdim    return SubExprs[BASE]->getBeginLoc();
886234353Sdim  }
887327952Sdim
888341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return RBracket; }
889341825Sdim
890234353Sdim  Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
891234353Sdim  void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
892341825Sdim
893234353Sdim  Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
894234353Sdim  void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
895341825Sdim
896234353Sdim  ObjCMethodDecl *getAtIndexMethodDecl() const {
897234353Sdim    return GetAtIndexMethodDecl;
898234353Sdim  }
899341825Sdim
900234353Sdim  ObjCMethodDecl *setAtIndexMethodDecl() const {
901234353Sdim    return SetAtIndexMethodDecl;
902234353Sdim  }
903341825Sdim
904234353Sdim  bool isArraySubscriptRefExpr() const {
905234353Sdim    return getKeyExpr()->getType()->isIntegralOrEnumerationType();
906234353Sdim  }
907341825Sdim
908234353Sdim  child_range children() {
909234353Sdim    return child_range(SubExprs, SubExprs+END_EXPR);
910234353Sdim  }
911327952Sdim
912353358Sdim  const_child_range children() const {
913353358Sdim    return const_child_range(SubExprs, SubExprs + END_EXPR);
914353358Sdim  }
915353358Sdim
916327952Sdim  static bool classof(const Stmt *T) {
917327952Sdim    return T->getStmtClass() == ObjCSubscriptRefExprClass;
918327952Sdim  }
919327952Sdim
920234353Sdimprivate:
921234353Sdim  friend class ASTStmtReader;
922234353Sdim};
923234353Sdim
924341825Sdim/// An expression that sends a message to the given Objective-C
925207619Srdivacky/// object or class.
926207619Srdivacky///
927207619Srdivacky/// The following contains two message send expressions:
928207619Srdivacky///
929207619Srdivacky/// \code
930207619Srdivacky///   [[NSString alloc] initWithString:@"Hello"]
931207619Srdivacky/// \endcode
932207619Srdivacky///
933207619Srdivacky/// The innermost message send invokes the "alloc" class method on the
934207619Srdivacky/// NSString class, while the outermost message send invokes the
935207619Srdivacky/// "initWithString" instance method on the object returned from
936207619Srdivacky/// NSString's "alloc". In all, an Objective-C message send can take
937207619Srdivacky/// on four different (although related) forms:
938207619Srdivacky///
939207619Srdivacky///   1. Send to an object instance.
940207619Srdivacky///   2. Send to a class.
941207619Srdivacky///   3. Send to the superclass instance of the current class.
942207619Srdivacky///   4. Send to the superclass of the current class.
943207619Srdivacky///
944207619Srdivacky/// All four kinds of message sends are modeled by the ObjCMessageExpr
945207619Srdivacky/// class, and can be distinguished via \c getReceiverKind(). Example:
946207619Srdivacky///
947296417Sdim/// The "void *" trailing objects are actually ONE void * (the
948296417Sdim/// receiver pointer), and NumArgs Expr *. But due to the
949296417Sdim/// implementation of children(), these must be together contiguously.
950296417Sdimclass ObjCMessageExpr final
951296417Sdim    : public Expr,
952296417Sdim      private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
953341825Sdim  /// Stores either the selector that this message is sending
954226633Sdim  /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
955226633Sdim  /// referring to the method that we type-checked against.
956327952Sdim  uintptr_t SelectorOrMethod = 0;
957226633Sdim
958226633Sdim  enum { NumArgsBitWidth = 16 };
959226633Sdim
960341825Sdim  /// The number of arguments in the message send, not
961207619Srdivacky  /// including the receiver.
962226633Sdim  unsigned NumArgs : NumArgsBitWidth;
963341825Sdim
964341825Sdim  /// The kind of message send this is, which is one of the
965207619Srdivacky  /// ReceiverKind values.
966207619Srdivacky  ///
967207619Srdivacky  /// We pad this out to a byte to avoid excessive masking and shifting.
968207619Srdivacky  unsigned Kind : 8;
969198092Srdivacky
970341825Sdim  /// Whether we have an actual method prototype in \c
971207619Srdivacky  /// SelectorOrMethod.
972207619Srdivacky  ///
973207619Srdivacky  /// When non-zero, we have a method declaration; otherwise, we just
974207619Srdivacky  /// have a selector.
975224145Sdim  unsigned HasMethod : 1;
976204962Srdivacky
977341825Sdim  /// Whether this message send is a "delegate init call",
978224145Sdim  /// i.e. a call of an init method on self from within an init method.
979224145Sdim  unsigned IsDelegateInitCall : 1;
980234353Sdim
981341825Sdim  /// Whether this message send was implicitly generated by
982234353Sdim  /// the implementation rather than explicitly written by the user.
983234353Sdim  unsigned IsImplicit : 1;
984234353Sdim
985341825Sdim  /// Whether the locations of the selector identifiers are in a
986226633Sdim  /// "standard" position, a enum SelectorLocationsKind.
987226633Sdim  unsigned SelLocsKind : 2;
988224145Sdim
989341825Sdim  /// When the message expression is a send to 'super', this is
990207619Srdivacky  /// the location of the 'super' keyword.
991207619Srdivacky  SourceLocation SuperLoc;
992198092Srdivacky
993341825Sdim  /// The source locations of the open and close square
994207619Srdivacky  /// brackets ('[' and ']', respectively).
995207619Srdivacky  SourceLocation LBracLoc, RBracLoc;
996193326Sed
997207619Srdivacky  ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
998327952Sdim      : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false),
999327952Sdim        IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) {
1000226633Sdim    setNumArgs(NumArgs);
1001226633Sdim  }
1002193326Sed
1003218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
1004207619Srdivacky                  SourceLocation LBracLoc,
1005207619Srdivacky                  SourceLocation SuperLoc,
1006207619Srdivacky                  bool IsInstanceSuper,
1007207619Srdivacky                  QualType SuperType,
1008341825Sdim                  Selector Sel,
1009226633Sdim                  ArrayRef<SourceLocation> SelLocs,
1010226633Sdim                  SelectorLocationsKind SelLocsK,
1011207619Srdivacky                  ObjCMethodDecl *Method,
1012226633Sdim                  ArrayRef<Expr *> Args,
1013234353Sdim                  SourceLocation RBracLoc,
1014234353Sdim                  bool isImplicit);
1015218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
1016207619Srdivacky                  SourceLocation LBracLoc,
1017207619Srdivacky                  TypeSourceInfo *Receiver,
1018341825Sdim                  Selector Sel,
1019226633Sdim                  ArrayRef<SourceLocation> SelLocs,
1020226633Sdim                  SelectorLocationsKind SelLocsK,
1021207619Srdivacky                  ObjCMethodDecl *Method,
1022226633Sdim                  ArrayRef<Expr *> Args,
1023234353Sdim                  SourceLocation RBracLoc,
1024234353Sdim                  bool isImplicit);
1025218893Sdim  ObjCMessageExpr(QualType T, ExprValueKind VK,
1026207619Srdivacky                  SourceLocation LBracLoc,
1027207619Srdivacky                  Expr *Receiver,
1028341825Sdim                  Selector Sel,
1029226633Sdim                  ArrayRef<SourceLocation> SelLocs,
1030226633Sdim                  SelectorLocationsKind SelLocsK,
1031207619Srdivacky                  ObjCMethodDecl *Method,
1032226633Sdim                  ArrayRef<Expr *> Args,
1033234353Sdim                  SourceLocation RBracLoc,
1034234353Sdim                  bool isImplicit);
1035198092Srdivacky
1036327952Sdim  size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }
1037327952Sdim
1038327952Sdim  void setNumArgs(unsigned Num) {
1039327952Sdim    assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
1040327952Sdim    NumArgs = Num;
1041327952Sdim  }
1042327952Sdim
1043226633Sdim  void initArgsAndSelLocs(ArrayRef<Expr *> Args,
1044226633Sdim                          ArrayRef<SourceLocation> SelLocs,
1045226633Sdim                          SelectorLocationsKind SelLocsK);
1046226633Sdim
1047341825Sdim  /// Retrieve the pointer value of the message receiver.
1048296417Sdim  void *getReceiverPointer() const { return *getTrailingObjects<void *>(); }
1049207619Srdivacky
1050341825Sdim  /// Set the pointer value of the message receiver.
1051207619Srdivacky  void setReceiverPointer(void *Value) {
1052296417Sdim    *getTrailingObjects<void *>() = Value;
1053207619Srdivacky  }
1054207619Srdivacky
1055226633Sdim  SelectorLocationsKind getSelLocsKind() const {
1056226633Sdim    return (SelectorLocationsKind)SelLocsKind;
1057226633Sdim  }
1058327952Sdim
1059226633Sdim  bool hasStandardSelLocs() const {
1060226633Sdim    return getSelLocsKind() != SelLoc_NonStandard;
1061226633Sdim  }
1062226633Sdim
1063341825Sdim  /// Get a pointer to the stored selector identifiers locations array.
1064226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
1065226633Sdim  SourceLocation *getStoredSelLocs() {
1066296417Sdim    return getTrailingObjects<SourceLocation>();
1067226633Sdim  }
1068226633Sdim  const SourceLocation *getStoredSelLocs() const {
1069296417Sdim    return getTrailingObjects<SourceLocation>();
1070226633Sdim  }
1071226633Sdim
1072341825Sdim  /// Get the number of stored selector identifiers locations.
1073226633Sdim  /// No locations will be stored if HasStandardSelLocs is true.
1074226633Sdim  unsigned getNumStoredSelLocs() const {
1075226633Sdim    if (hasStandardSelLocs())
1076226633Sdim      return 0;
1077226633Sdim    return getNumSelectorLocs();
1078226633Sdim  }
1079226633Sdim
1080261991Sdim  static ObjCMessageExpr *alloc(const ASTContext &C,
1081226633Sdim                                ArrayRef<Expr *> Args,
1082226633Sdim                                SourceLocation RBraceLoc,
1083226633Sdim                                ArrayRef<SourceLocation> SelLocs,
1084226633Sdim                                Selector Sel,
1085226633Sdim                                SelectorLocationsKind &SelLocsK);
1086261991Sdim  static ObjCMessageExpr *alloc(const ASTContext &C,
1087226633Sdim                                unsigned NumArgs,
1088226633Sdim                                unsigned NumStoredSelLocs);
1089226633Sdim
1090193326Sedpublic:
1091327952Sdim  friend class ASTStmtReader;
1092327952Sdim  friend class ASTStmtWriter;
1093327952Sdim  friend TrailingObjects;
1094327952Sdim
1095341825Sdim  /// The kind of receiver this message is sending to.
1096207619Srdivacky  enum ReceiverKind {
1097341825Sdim    /// The receiver is a class.
1098207619Srdivacky    Class = 0,
1099327952Sdim
1100341825Sdim    /// The receiver is an object instance.
1101207619Srdivacky    Instance,
1102327952Sdim
1103341825Sdim    /// The receiver is a superclass.
1104207619Srdivacky    SuperClass,
1105327952Sdim
1106341825Sdim    /// The receiver is the instance of the superclass object.
1107207619Srdivacky    SuperInstance
1108207619Srdivacky  };
1109193326Sed
1110341825Sdim  /// Create a message send to super.
1111207619Srdivacky  ///
1112207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1113207619Srdivacky  ///
1114207619Srdivacky  /// \param T The result type of this message.
1115207619Srdivacky  ///
1116218893Sdim  /// \param VK The value kind of this message.  A message returning
1117218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1118218893Sdim  /// respectively.
1119218893Sdim  ///
1120239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1121207619Srdivacky  ///
1122207619Srdivacky  /// \param SuperLoc The location of the "super" keyword.
1123207619Srdivacky  ///
1124207619Srdivacky  /// \param IsInstanceSuper Whether this is an instance "super"
1125207619Srdivacky  /// message (otherwise, it's a class "super" message).
1126207619Srdivacky  ///
1127207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1128207619Srdivacky  ///
1129207619Srdivacky  /// \param Method The Objective-C method against which this message
1130327952Sdim  /// send was type-checked. May be nullptr.
1131207619Srdivacky  ///
1132207619Srdivacky  /// \param Args The message send arguments.
1133207619Srdivacky  ///
1134207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1135261991Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1136218893Sdim                                 ExprValueKind VK,
1137207619Srdivacky                                 SourceLocation LBracLoc,
1138207619Srdivacky                                 SourceLocation SuperLoc,
1139207619Srdivacky                                 bool IsInstanceSuper,
1140207619Srdivacky                                 QualType SuperType,
1141341825Sdim                                 Selector Sel,
1142226633Sdim                                 ArrayRef<SourceLocation> SelLocs,
1143207619Srdivacky                                 ObjCMethodDecl *Method,
1144226633Sdim                                 ArrayRef<Expr *> Args,
1145234353Sdim                                 SourceLocation RBracLoc,
1146234353Sdim                                 bool isImplicit);
1147198092Srdivacky
1148341825Sdim  /// Create a class message send.
1149207619Srdivacky  ///
1150207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1151207619Srdivacky  ///
1152207619Srdivacky  /// \param T The result type of this message.
1153207619Srdivacky  ///
1154218893Sdim  /// \param VK The value kind of this message.  A message returning
1155218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1156218893Sdim  /// respectively.
1157218893Sdim  ///
1158239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1159207619Srdivacky  ///
1160207619Srdivacky  /// \param Receiver The type of the receiver, including
1161207619Srdivacky  /// source-location information.
1162207619Srdivacky  ///
1163207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1164207619Srdivacky  ///
1165207619Srdivacky  /// \param Method The Objective-C method against which this message
1166327952Sdim  /// send was type-checked. May be nullptr.
1167207619Srdivacky  ///
1168207619Srdivacky  /// \param Args The message send arguments.
1169207619Srdivacky  ///
1170207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1171261991Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1172218893Sdim                                 ExprValueKind VK,
1173207619Srdivacky                                 SourceLocation LBracLoc,
1174207619Srdivacky                                 TypeSourceInfo *Receiver,
1175341825Sdim                                 Selector Sel,
1176226633Sdim                                 ArrayRef<SourceLocation> SelLocs,
1177207619Srdivacky                                 ObjCMethodDecl *Method,
1178226633Sdim                                 ArrayRef<Expr *> Args,
1179234353Sdim                                 SourceLocation RBracLoc,
1180234353Sdim                                 bool isImplicit);
1181198092Srdivacky
1182341825Sdim  /// Create an instance message send.
1183207619Srdivacky  ///
1184207619Srdivacky  /// \param Context The ASTContext in which this expression will be created.
1185207619Srdivacky  ///
1186207619Srdivacky  /// \param T The result type of this message.
1187207619Srdivacky  ///
1188218893Sdim  /// \param VK The value kind of this message.  A message returning
1189218893Sdim  /// a l-value or r-value reference will be an l-value or x-value,
1190218893Sdim  /// respectively.
1191218893Sdim  ///
1192239462Sdim  /// \param LBracLoc The location of the open square bracket '['.
1193207619Srdivacky  ///
1194207619Srdivacky  /// \param Receiver The expression used to produce the object that
1195207619Srdivacky  /// will receive this message.
1196207619Srdivacky  ///
1197207619Srdivacky  /// \param Sel The selector used to determine which method gets called.
1198207619Srdivacky  ///
1199207619Srdivacky  /// \param Method The Objective-C method against which this message
1200327952Sdim  /// send was type-checked. May be nullptr.
1201207619Srdivacky  ///
1202207619Srdivacky  /// \param Args The message send arguments.
1203207619Srdivacky  ///
1204207619Srdivacky  /// \param RBracLoc The location of the closing square bracket ']'.
1205261991Sdim  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
1206218893Sdim                                 ExprValueKind VK,
1207207619Srdivacky                                 SourceLocation LBracLoc,
1208207619Srdivacky                                 Expr *Receiver,
1209341825Sdim                                 Selector Sel,
1210226633Sdim                                 ArrayRef<SourceLocation> SeLocs,
1211207619Srdivacky                                 ObjCMethodDecl *Method,
1212226633Sdim                                 ArrayRef<Expr *> Args,
1213234353Sdim                                 SourceLocation RBracLoc,
1214234353Sdim                                 bool isImplicit);
1215198092Srdivacky
1216341825Sdim  /// Create an empty Objective-C message expression, to be
1217207619Srdivacky  /// filled in by subsequent calls.
1218207619Srdivacky  ///
1219207619Srdivacky  /// \param Context The context in which the message send will be created.
1220207619Srdivacky  ///
1221207619Srdivacky  /// \param NumArgs The number of message arguments, not including
1222207619Srdivacky  /// the receiver.
1223261991Sdim  static ObjCMessageExpr *CreateEmpty(const ASTContext &Context,
1224226633Sdim                                      unsigned NumArgs,
1225226633Sdim                                      unsigned NumStoredSelLocs);
1226198092Srdivacky
1227341825Sdim  /// Indicates whether the message send was implicitly
1228234353Sdim  /// generated by the implementation. If false, it was written explicitly
1229234353Sdim  /// in the source code.
1230234353Sdim  bool isImplicit() const { return IsImplicit; }
1231234353Sdim
1232341825Sdim  /// Determine the kind of receiver that this message is being
1233207619Srdivacky  /// sent to.
1234207619Srdivacky  ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
1235207619Srdivacky
1236353358Sdim  /// \return the return type of the message being sent.
1237353358Sdim  /// This is not always the type of the message expression itself because
1238353358Sdim  /// of references (the expression would not have a reference type).
1239353358Sdim  /// It is also not always the declared return type of the method because
1240353358Sdim  /// of `instancetype` (in that case it's an expression type).
1241353358Sdim  QualType getCallReturnType(ASTContext &Ctx) const;
1242353358Sdim
1243341825Sdim  /// Source range of the receiver.
1244218893Sdim  SourceRange getReceiverRange() const;
1245218893Sdim
1246341825Sdim  /// Determine whether this is an instance message to either a
1247207619Srdivacky  /// computed object or to super.
1248207619Srdivacky  bool isInstanceMessage() const {
1249207619Srdivacky    return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
1250198092Srdivacky  }
1251207619Srdivacky
1252341825Sdim  /// Determine whether this is an class message to either a
1253207619Srdivacky  /// specified class or to super.
1254207619Srdivacky  bool isClassMessage() const {
1255207619Srdivacky    return getReceiverKind() == Class || getReceiverKind() == SuperClass;
1256193326Sed  }
1257198092Srdivacky
1258341825Sdim  /// Returns the object expression (receiver) for an instance message,
1259243830Sdim  /// or null for a message that is not an instance message.
1260207619Srdivacky  Expr *getInstanceReceiver() {
1261207619Srdivacky    if (getReceiverKind() == Instance)
1262207619Srdivacky      return static_cast<Expr *>(getReceiverPointer());
1263198092Srdivacky
1264276479Sdim    return nullptr;
1265207619Srdivacky  }
1266207619Srdivacky  const Expr *getInstanceReceiver() const {
1267207619Srdivacky    return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
1268207619Srdivacky  }
1269198092Srdivacky
1270341825Sdim  /// Turn this message send into an instance message that
1271207619Srdivacky  /// computes the receiver object with the given expression.
1272341825Sdim  void setInstanceReceiver(Expr *rec) {
1273207619Srdivacky    Kind = Instance;
1274207619Srdivacky    setReceiverPointer(rec);
1275207619Srdivacky  }
1276341825Sdim
1277341825Sdim  /// Returns the type of a class message send, or NULL if the
1278207619Srdivacky  /// message is not a class message.
1279341825Sdim  QualType getClassReceiver() const {
1280207619Srdivacky    if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
1281207619Srdivacky      return TSInfo->getType();
1282204962Srdivacky
1283327952Sdim    return {};
1284207619Srdivacky  }
1285204962Srdivacky
1286341825Sdim  /// Returns a type-source information of a class message
1287327952Sdim  /// send, or nullptr if the message is not a class message.
1288207619Srdivacky  TypeSourceInfo *getClassReceiverTypeInfo() const {
1289207619Srdivacky    if (getReceiverKind() == Class)
1290207619Srdivacky      return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
1291276479Sdim    return nullptr;
1292207619Srdivacky  }
1293204962Srdivacky
1294207619Srdivacky  void setClassReceiver(TypeSourceInfo *TSInfo) {
1295207619Srdivacky    Kind = Class;
1296207619Srdivacky    setReceiverPointer(TSInfo);
1297207619Srdivacky  }
1298204962Srdivacky
1299341825Sdim  /// Retrieve the location of the 'super' keyword for a class
1300207619Srdivacky  /// or instance message to 'super', otherwise an invalid source location.
1301341825Sdim  SourceLocation getSuperLoc() const {
1302207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
1303207619Srdivacky      return SuperLoc;
1304198092Srdivacky
1305207619Srdivacky    return SourceLocation();
1306193326Sed  }
1307198092Srdivacky
1308341825Sdim  /// Retrieve the receiver type to which this message is being directed.
1309243830Sdim  ///
1310243830Sdim  /// This routine cross-cuts all of the different kinds of message
1311243830Sdim  /// sends to determine what the underlying (statically known) type
1312243830Sdim  /// of the receiver will be; use \c getReceiverKind() to determine
1313243830Sdim  /// whether the message is a class or an instance method, whether it
1314243830Sdim  /// is a send to super or not, etc.
1315243830Sdim  ///
1316243830Sdim  /// \returns The type of the receiver.
1317243830Sdim  QualType getReceiverType() const;
1318243830Sdim
1319341825Sdim  /// Retrieve the Objective-C interface to which this message
1320207619Srdivacky  /// is being directed, if known.
1321207619Srdivacky  ///
1322207619Srdivacky  /// This routine cross-cuts all of the different kinds of message
1323207619Srdivacky  /// sends to determine what the underlying (statically known) type
1324207619Srdivacky  /// of the receiver will be; use \c getReceiverKind() to determine
1325207619Srdivacky  /// whether the message is a class or an instance method, whether it
1326207619Srdivacky  /// is a send to super or not, etc.
1327207619Srdivacky  ///
1328327952Sdim  /// \returns The Objective-C interface if known, otherwise nullptr.
1329207619Srdivacky  ObjCInterfaceDecl *getReceiverInterface() const;
1330207619Srdivacky
1331341825Sdim  /// Retrieve the type referred to by 'super'.
1332207619Srdivacky  ///
1333207619Srdivacky  /// The returned type will either be an ObjCInterfaceType (for an
1334207619Srdivacky  /// class message to super) or an ObjCObjectPointerType that refers
1335207619Srdivacky  /// to a class (for an instance message to super);
1336207619Srdivacky  QualType getSuperType() const {
1337207619Srdivacky    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
1338207619Srdivacky      return QualType::getFromOpaquePtr(getReceiverPointer());
1339207619Srdivacky
1340207619Srdivacky    return QualType();
1341207619Srdivacky  }
1342207619Srdivacky
1343207619Srdivacky  void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
1344207619Srdivacky    Kind = IsInstanceSuper? SuperInstance : SuperClass;
1345207619Srdivacky    SuperLoc = Loc;
1346207619Srdivacky    setReceiverPointer(T.getAsOpaquePtr());
1347207619Srdivacky  }
1348207619Srdivacky
1349207619Srdivacky  Selector getSelector() const;
1350207619Srdivacky
1351341825Sdim  void setSelector(Selector S) {
1352207619Srdivacky    HasMethod = false;
1353207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
1354207619Srdivacky  }
1355207619Srdivacky
1356341825Sdim  const ObjCMethodDecl *getMethodDecl() const {
1357207619Srdivacky    if (HasMethod)
1358207619Srdivacky      return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
1359207619Srdivacky
1360276479Sdim    return nullptr;
1361207619Srdivacky  }
1362207619Srdivacky
1363341825Sdim  ObjCMethodDecl *getMethodDecl() {
1364207619Srdivacky    if (HasMethod)
1365207619Srdivacky      return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
1366207619Srdivacky
1367276479Sdim    return nullptr;
1368207619Srdivacky  }
1369207619Srdivacky
1370341825Sdim  void setMethodDecl(ObjCMethodDecl *MD) {
1371207619Srdivacky    HasMethod = true;
1372207619Srdivacky    SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
1373207619Srdivacky  }
1374207619Srdivacky
1375221345Sdim  ObjCMethodFamily getMethodFamily() const {
1376221345Sdim    if (HasMethod) return getMethodDecl()->getMethodFamily();
1377221345Sdim    return getSelector().getMethodFamily();
1378221345Sdim  }
1379221345Sdim
1380341825Sdim  /// Return the number of actual arguments in this message,
1381207619Srdivacky  /// not counting the receiver.
1382193326Sed  unsigned getNumArgs() const { return NumArgs; }
1383207619Srdivacky
1384341825Sdim  /// Retrieve the arguments to this message, not including the
1385207619Srdivacky  /// receiver.
1386218893Sdim  Expr **getArgs() {
1387296417Sdim    return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1);
1388193326Sed  }
1389218893Sdim  const Expr * const *getArgs() const {
1390296417Sdim    return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() +
1391296417Sdim                                                 1);
1392207619Srdivacky  }
1393198092Srdivacky
1394193326Sed  /// getArg - Return the specified argument.
1395193326Sed  Expr *getArg(unsigned Arg) {
1396193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1397296417Sdim    return getArgs()[Arg];
1398193326Sed  }
1399193326Sed  const Expr *getArg(unsigned Arg) const {
1400193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1401296417Sdim    return getArgs()[Arg];
1402193326Sed  }
1403327952Sdim
1404193326Sed  /// setArg - Set the specified argument.
1405193326Sed  void setArg(unsigned Arg, Expr *ArgExpr) {
1406193326Sed    assert(Arg < NumArgs && "Arg access out of range!");
1407207619Srdivacky    getArgs()[Arg] = ArgExpr;
1408193326Sed  }
1409198092Srdivacky
1410224145Sdim  /// isDelegateInitCall - Answers whether this message send has been
1411224145Sdim  /// tagged as a "delegate init call", i.e. a call to a method in the
1412224145Sdim  /// -init family on self from within an -init method implementation.
1413224145Sdim  bool isDelegateInitCall() const { return IsDelegateInitCall; }
1414224145Sdim  void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }
1415224145Sdim
1416207619Srdivacky  SourceLocation getLeftLoc() const { return LBracLoc; }
1417207619Srdivacky  SourceLocation getRightLoc() const { return RBracLoc; }
1418193326Sed
1419234353Sdim  SourceLocation getSelectorStartLoc() const {
1420234353Sdim    if (isImplicit())
1421344779Sdim      return getBeginLoc();
1422234353Sdim    return getSelectorLoc(0);
1423234353Sdim  }
1424327952Sdim
1425226633Sdim  SourceLocation getSelectorLoc(unsigned Index) const {
1426226633Sdim    assert(Index < getNumSelectorLocs() && "Index out of range!");
1427226633Sdim    if (hasStandardSelLocs())
1428226633Sdim      return getStandardSelectorLoc(Index, getSelector(),
1429226633Sdim                                   getSelLocsKind() == SelLoc_StandardWithSpace,
1430226633Sdim                               llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
1431226633Sdim                                                  getNumArgs()),
1432226633Sdim                                   RBracLoc);
1433226633Sdim    return getStoredSelLocs()[Index];
1434226633Sdim  }
1435226633Sdim
1436226633Sdim  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
1437226633Sdim
1438226633Sdim  unsigned getNumSelectorLocs() const {
1439234353Sdim    if (isImplicit())
1440234353Sdim      return 0;
1441226633Sdim    Selector Sel = getSelector();
1442226633Sdim    if (Sel.isUnarySelector())
1443226633Sdim      return 1;
1444226633Sdim    return Sel.getNumArgs();
1445226633Sdim  }
1446226633Sdim
1447193326Sed  void setSourceRange(SourceRange R) {
1448207619Srdivacky    LBracLoc = R.getBegin();
1449207619Srdivacky    RBracLoc = R.getEnd();
1450193326Sed  }
1451327952Sdim
1452341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return LBracLoc; }
1453341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return RBracLoc; }
1454193326Sed
1455193326Sed  // Iterators
1456218893Sdim  child_range children();
1457198092Srdivacky
1458353358Sdim  const_child_range children() const;
1459353358Sdim
1460327952Sdim  using arg_iterator = ExprIterator;
1461327952Sdim  using const_arg_iterator = ConstExprIterator;
1462198092Srdivacky
1463296417Sdim  llvm::iterator_range<arg_iterator> arguments() {
1464296417Sdim    return llvm::make_range(arg_begin(), arg_end());
1465296417Sdim  }
1466296417Sdim
1467296417Sdim  llvm::iterator_range<const_arg_iterator> arguments() const {
1468296417Sdim    return llvm::make_range(arg_begin(), arg_end());
1469296417Sdim  }
1470296417Sdim
1471218893Sdim  arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
1472327952Sdim
1473341825Sdim  arg_iterator arg_end()   {
1474341825Sdim    return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
1475193326Sed  }
1476327952Sdim
1477341825Sdim  const_arg_iterator arg_begin() const {
1478341825Sdim    return reinterpret_cast<Stmt const * const*>(getArgs());
1479218893Sdim  }
1480327952Sdim
1481341825Sdim  const_arg_iterator arg_end() const {
1482341825Sdim    return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
1483218893Sdim  }
1484193326Sed
1485327952Sdim  static bool classof(const Stmt *T) {
1486327952Sdim    return T->getStmtClass() == ObjCMessageExprClass;
1487327952Sdim  }
1488193326Sed};
1489193326Sed
1490198092Srdivacky/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
1491221345Sdim/// (similar in spirit to MemberExpr).
1492198092Srdivackyclass ObjCIsaExpr : public Expr {
1493198092Srdivacky  /// Base - the expression for the base object pointer.
1494198092Srdivacky  Stmt *Base;
1495198092Srdivacky
1496198092Srdivacky  /// IsaMemberLoc - This is the location of the 'isa'.
1497198092Srdivacky  SourceLocation IsaMemberLoc;
1498341825Sdim
1499249423Sdim  /// OpLoc - This is the location of '.' or '->'
1500249423Sdim  SourceLocation OpLoc;
1501198092Srdivacky
1502198092Srdivacky  /// IsArrow - True if this is "X->F", false if this is "X.F".
1503198092Srdivacky  bool IsArrow;
1504327952Sdim
1505198092Srdivackypublic:
1506249423Sdim  ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
1507249423Sdim              QualType ty)
1508327952Sdim      : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
1509327952Sdim             /*TypeDependent=*/false, base->isValueDependent(),
1510327952Sdim             base->isInstantiationDependent(),
1511327952Sdim             /*ContainsUnexpandedParameterPack=*/false),
1512327952Sdim        Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
1513198092Srdivacky
1514341825Sdim  /// Build an empty expression.
1515327952Sdim  explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {}
1516198092Srdivacky
1517198092Srdivacky  void setBase(Expr *E) { Base = E; }
1518198092Srdivacky  Expr *getBase() const { return cast<Expr>(Base); }
1519198092Srdivacky
1520198092Srdivacky  bool isArrow() const { return IsArrow; }
1521198092Srdivacky  void setArrow(bool A) { IsArrow = A; }
1522198092Srdivacky
1523198092Srdivacky  /// getMemberLoc - Return the location of the "member", in X->F, it is the
1524198092Srdivacky  /// location of 'F'.
1525198092Srdivacky  SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
1526198092Srdivacky  void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
1527341825Sdim
1528249423Sdim  SourceLocation getOpLoc() const { return OpLoc; }
1529249423Sdim  void setOpLoc(SourceLocation L) { OpLoc = L; }
1530198092Srdivacky
1531341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY {
1532344779Sdim    return getBase()->getBeginLoc();
1533198092Srdivacky  }
1534341825Sdim
1535249423Sdim  SourceLocation getBaseLocEnd() const LLVM_READONLY {
1536344779Sdim    return getBase()->getEndLoc();
1537249423Sdim  }
1538198092Srdivacky
1539341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY { return IsaMemberLoc; }
1540341825Sdim
1541234353Sdim  SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
1542198092Srdivacky
1543327952Sdim  // Iterators
1544327952Sdim  child_range children() { return child_range(&Base, &Base+1); }
1545327952Sdim
1546353358Sdim  const_child_range children() const {
1547353358Sdim    return const_child_range(&Base, &Base + 1);
1548353358Sdim  }
1549353358Sdim
1550198092Srdivacky  static bool classof(const Stmt *T) {
1551198092Srdivacky    return T->getStmtClass() == ObjCIsaExprClass;
1552198092Srdivacky  }
1553198092Srdivacky};
1554198092Srdivacky
1555224145Sdim/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
1556224145Sdim/// argument by indirect copy-restore in ARC.  This is used to support
1557224145Sdim/// passing indirect arguments with the wrong lifetime, e.g. when
1558224145Sdim/// passing the address of a __strong local variable to an 'out'
1559224145Sdim/// parameter.  This expression kind is only valid in an "argument"
1560224145Sdim/// position to some sort of call expression.
1561224145Sdim///
1562224145Sdim/// The parameter must have type 'pointer to T', and the argument must
1563224145Sdim/// have type 'pointer to U', where T and U agree except possibly in
1564224145Sdim/// qualification.  If the argument value is null, then a null pointer
1565224145Sdim/// is passed;  otherwise it points to an object A, and:
1566224145Sdim/// 1. A temporary object B of type T is initialized, either by
1567224145Sdim///    zero-initialization (used when initializing an 'out' parameter)
1568224145Sdim///    or copy-initialization (used when initializing an 'inout'
1569224145Sdim///    parameter).
1570224145Sdim/// 2. The address of the temporary is passed to the function.
1571224145Sdim/// 3. If the call completes normally, A is move-assigned from B.
1572224145Sdim/// 4. Finally, A is destroyed immediately.
1573224145Sdim///
1574224145Sdim/// Currently 'T' must be a retainable object lifetime and must be
1575224145Sdim/// __autoreleasing;  this qualifier is ignored when initializing
1576224145Sdim/// the value.
1577224145Sdimclass ObjCIndirectCopyRestoreExpr : public Expr {
1578327952Sdim  friend class ASTReader;
1579327952Sdim  friend class ASTStmtReader;
1580327952Sdim
1581224145Sdim  Stmt *Operand;
1582224145Sdim
1583224145Sdim  // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
1584224145Sdim
1585327952Sdim  explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
1586327952Sdim      : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {}
1587224145Sdim
1588224145Sdim  void setShouldCopy(bool shouldCopy) {
1589224145Sdim    ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
1590224145Sdim  }
1591224145Sdim
1592224145Sdimpublic:
1593224145Sdim  ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
1594327952Sdim      : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
1595327952Sdim             operand->isTypeDependent(), operand->isValueDependent(),
1596327952Sdim             operand->isInstantiationDependent(),
1597327952Sdim             operand->containsUnexpandedParameterPack()),
1598327952Sdim        Operand(operand) {
1599224145Sdim    setShouldCopy(shouldCopy);
1600224145Sdim  }
1601224145Sdim
1602224145Sdim  Expr *getSubExpr() { return cast<Expr>(Operand); }
1603224145Sdim  const Expr *getSubExpr() const { return cast<Expr>(Operand); }
1604224145Sdim
1605224145Sdim  /// shouldCopy - True if we should do the 'copy' part of the
1606224145Sdim  /// copy-restore.  If false, the temporary will be zero-initialized.
1607224145Sdim  bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
1608224145Sdim
1609341825Sdim  child_range children() { return child_range(&Operand, &Operand+1); }
1610224145Sdim
1611353358Sdim  const_child_range children() const {
1612353358Sdim    return const_child_range(&Operand, &Operand + 1);
1613353358Sdim  }
1614353358Sdim
1615224145Sdim  // Source locations are determined by the subexpression.
1616341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY {
1617344779Sdim    return Operand->getBeginLoc();
1618234353Sdim  }
1619341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY {
1620344779Sdim    return Operand->getEndLoc();
1621341825Sdim  }
1622249423Sdim
1623234353Sdim  SourceLocation getExprLoc() const LLVM_READONLY {
1624234353Sdim    return getSubExpr()->getExprLoc();
1625234353Sdim  }
1626224145Sdim
1627224145Sdim  static bool classof(const Stmt *s) {
1628224145Sdim    return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
1629224145Sdim  }
1630224145Sdim};
1631224145Sdim
1632341825Sdim/// An Objective-C "bridged" cast expression, which casts between
1633224145Sdim/// Objective-C pointers and C pointers, transferring ownership in the process.
1634224145Sdim///
1635224145Sdim/// \code
1636224145Sdim/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
1637224145Sdim/// \endcode
1638296417Sdimclass ObjCBridgedCastExpr final
1639296417Sdim    : public ExplicitCastExpr,
1640344779Sdim      private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
1641327952Sdim  friend class ASTStmtReader;
1642327952Sdim  friend class ASTStmtWriter;
1643327952Sdim  friend class CastExpr;
1644327952Sdim  friend TrailingObjects;
1645327952Sdim
1646224145Sdim  SourceLocation LParenLoc;
1647224145Sdim  SourceLocation BridgeKeywordLoc;
1648224145Sdim  unsigned Kind : 2;
1649296417Sdim
1650224145Sdimpublic:
1651224145Sdim  ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
1652226633Sdim                      CastKind CK, SourceLocation BridgeKeywordLoc,
1653226633Sdim                      TypeSourceInfo *TSInfo, Expr *Operand)
1654327952Sdim      : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
1655327952Sdim                         CK, Operand, 0, TSInfo),
1656327952Sdim        LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {}
1657341825Sdim
1658341825Sdim  /// Construct an empty Objective-C bridged cast.
1659224145Sdim  explicit ObjCBridgedCastExpr(EmptyShell Shell)
1660327952Sdim      : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {}
1661224145Sdim
1662224145Sdim  SourceLocation getLParenLoc() const { return LParenLoc; }
1663224145Sdim
1664341825Sdim  /// Determine which kind of bridge is being performed via this cast.
1665341825Sdim  ObjCBridgeCastKind getBridgeKind() const {
1666341825Sdim    return static_cast<ObjCBridgeCastKind>(Kind);
1667224145Sdim  }
1668341825Sdim
1669341825Sdim  /// Retrieve the kind of bridge being performed as a string.
1670226633Sdim  StringRef getBridgeKindName() const;
1671341825Sdim
1672341825Sdim  /// The location of the bridge keyword.
1673224145Sdim  SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
1674327952Sdim
1675341825Sdim  SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
1676341825Sdim
1677341825Sdim  SourceLocation getEndLoc() const LLVM_READONLY {
1678344779Sdim    return getSubExpr()->getEndLoc();
1679224145Sdim  }
1680341825Sdim
1681224145Sdim  static bool classof(const Stmt *T) {
1682224145Sdim    return T->getStmtClass() == ObjCBridgedCastExprClass;
1683224145Sdim  }
1684224145Sdim};
1685309124Sdim
1686341825Sdim/// A runtime availability query.
1687309124Sdim///
1688309124Sdim/// There are 2 ways to spell this node:
1689309124Sdim/// \code
1690309124Sdim///   @available(macos 10.10, ios 8, *); // Objective-C
1691309124Sdim///   __builtin_available(macos 10.10, ios 8, *); // C, C++, and Objective-C
1692309124Sdim/// \endcode
1693309124Sdim///
1694309124Sdim/// Note that we only need to keep track of one \c VersionTuple here, which is
1695309124Sdim/// the one that corresponds to the current deployment target. This is meant to
1696309124Sdim/// be used in the condition of an \c if, but it is also usable as top level
1697309124Sdim/// expressions.
1698309124Sdim///
1699309124Sdimclass ObjCAvailabilityCheckExpr : public Expr {
1700327952Sdim  friend class ASTStmtReader;
1701327952Sdim
1702309124Sdim  VersionTuple VersionToCheck;
1703309124Sdim  SourceLocation AtLoc, RParen;
1704309124Sdim
1705309124Sdimpublic:
1706309124Sdim  ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc,
1707309124Sdim                            SourceLocation RParen, QualType Ty)
1708309124Sdim      : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary, false,
1709309124Sdim             false, false, false),
1710309124Sdim        VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {}
1711309124Sdim
1712309124Sdim  explicit ObjCAvailabilityCheckExpr(EmptyShell Shell)
1713309124Sdim      : Expr(ObjCAvailabilityCheckExprClass, Shell) {}
1714309124Sdim
1715341825Sdim  SourceLocation getBeginLoc() const { return AtLoc; }
1716341825Sdim  SourceLocation getEndLoc() const { return RParen; }
1717309124Sdim  SourceRange getSourceRange() const { return {AtLoc, RParen}; }
1718309124Sdim
1719341825Sdim  /// This may be '*', in which case this should fold to true.
1720309124Sdim  bool hasVersion() const { return !VersionToCheck.empty(); }
1721309124Sdim  VersionTuple getVersion() { return VersionToCheck; }
1722309124Sdim
1723309124Sdim  child_range children() {
1724309124Sdim    return child_range(child_iterator(), child_iterator());
1725309124Sdim  }
1726309124Sdim
1727353358Sdim  const_child_range children() const {
1728353358Sdim    return const_child_range(const_child_iterator(), const_child_iterator());
1729353358Sdim  }
1730353358Sdim
1731309124Sdim  static bool classof(const Stmt *T) {
1732309124Sdim    return T->getStmtClass() == ObjCAvailabilityCheckExprClass;
1733309124Sdim  }
1734309124Sdim};
1735309124Sdim
1736327952Sdim} // namespace clang
1737193326Sed
1738327952Sdim#endif // LLVM_CLANG_AST_EXPROBJC_H
1739