//===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ExprObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H

#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
#include <cstdint>

namespace clang {

class ASTContext;
class CXXBaseSpecifier;

/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
class ObjCStringLiteral : public Expr {
  Stmt *String;
  SourceLocation AtLoc;

public:
  ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
      : Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
             false, false),
        String(SL), AtLoc(L) {}
  explicit ObjCStringLiteral(EmptyShell Empty)
      : Expr(ObjCStringLiteralClass, Empty) {}

  StringLiteral *getString() { return cast<StringLiteral>(String); }
  const StringLiteral *getString() const { return cast<StringLiteral>(String); }
  void setString(StringLiteral *S) { String = S; }

  SourceLocation getAtLoc() const { return AtLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return String->getEndLoc(); }

  // Iterators
  child_range children() { return child_range(&String, &String+1); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCStringLiteralClass;
  }
};

/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
class ObjCBoolLiteralExpr : public Expr {
  bool Value;
  SourceLocation Loc;

public:
  ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l)
      : Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
             false, false),
        Value(val), Loc(l) {}
  explicit ObjCBoolLiteralExpr(EmptyShell Empty)
      : Expr(ObjCBoolLiteralExprClass, Empty) {}

  bool getValue() const { return Value; }
  void setValue(bool V) { Value = V; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }

  SourceLocation getLocation() const { return Loc; }
  void setLocation(SourceLocation L) { Loc = L; }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBoolLiteralExprClass;
  }
};

/// ObjCBoxedExpr - used for generalized expression boxing.
/// as in: @(strdup("hello world")), @(random()) or @(view.frame)
/// Also used for boxing non-parenthesized numeric literals;
/// as in: @42 or \@true (c++/objc++) or \@__objc_yes (c/objc).
class ObjCBoxedExpr : public Expr {
  Stmt *SubExpr;
  ObjCMethodDecl *BoxingMethod;
  SourceRange Range;

public:
  friend class ASTStmtReader;

  ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
                     SourceRange R)
      : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
             E->isTypeDependent(), E->isValueDependent(),
             E->isInstantiationDependent(),
             E->containsUnexpandedParameterPack()),
        SubExpr(E), BoxingMethod(method), Range(R) {}
  explicit ObjCBoxedExpr(EmptyShell Empty)
      : Expr(ObjCBoxedExprClass, Empty) {}

  Expr *getSubExpr() { return cast<Expr>(SubExpr); }
  const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }

  ObjCMethodDecl *getBoxingMethod() const {
    return BoxingMethod;
  }

  SourceLocation getAtLoc() const { return Range.getBegin(); }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }

  SourceRange getSourceRange() const LLVM_READONLY {
    return Range;
  }

  // Iterators
  child_range children() { return child_range(&SubExpr, &SubExpr+1); }

  using const_arg_iterator = ConstExprIterator;

  const_arg_iterator arg_begin() const {
    return reinterpret_cast<Stmt const * const*>(&SubExpr);
  }

  const_arg_iterator arg_end() const {
    return reinterpret_cast<Stmt const * const*>(&SubExpr + 1);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBoxedExprClass;
  }
};

/// ObjCArrayLiteral - used for objective-c array containers; as in:
/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
class ObjCArrayLiteral final
    : public Expr,
      private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> {
  unsigned NumElements;
  SourceRange Range;
  ObjCMethodDecl *ArrayWithObjectsMethod;

  ObjCArrayLiteral(ArrayRef<Expr *> Elements,
                   QualType T, ObjCMethodDecl * Method,
                   SourceRange SR);

  explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
      : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}

public:
  friend class ASTStmtReader;
  friend TrailingObjects;

  static ObjCArrayLiteral *Create(const ASTContext &C,
                                  ArrayRef<Expr *> Elements,
                                  QualType T, ObjCMethodDecl * Method,
                                  SourceRange SR);

  static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
                                       unsigned NumElements);

  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }

  /// Retrieve elements of array of literals.
  Expr **getElements() { return getTrailingObjects<Expr *>(); }

  /// Retrieve elements of array of literals.
  const Expr * const *getElements() const {
    return getTrailingObjects<Expr *>();
  }

  /// getNumElements - Return number of elements of objective-c array literal.
  unsigned getNumElements() const { return NumElements; }

  /// getElement - Return the Element at the specified index.
  Expr *getElement(unsigned Index) {
    assert((Index < NumElements) && "Arg access out of range!");
    return getElements()[Index];
  }
  const Expr *getElement(unsigned Index) const {
    assert((Index < NumElements) && "Arg access out of range!");
    return getElements()[Index];
  }

  ObjCMethodDecl *getArrayWithObjectsMethod() const {
    return ArrayWithObjectsMethod;
  }

  // Iterators
  child_range children() {
    return child_range(reinterpret_cast<Stmt **>(getElements()),
                       reinterpret_cast<Stmt **>(getElements()) + NumElements);
  }

  static bool classof(const Stmt *T) {
      return T->getStmtClass() == ObjCArrayLiteralClass;
  }
};

/// An element in an Objective-C dictionary literal.
///
struct ObjCDictionaryElement {
  /// The key for the dictionary element.
  Expr *Key;

  /// The value of the dictionary element.
  Expr *Value;

  /// The location of the ellipsis, if this is a pack expansion.
  SourceLocation EllipsisLoc;

  /// The number of elements this pack expansion will expand to, if
  /// this is a pack expansion and is known.
  Optional<unsigned> NumExpansions;

  /// Determines whether this dictionary element is a pack expansion.
  bool isPackExpansion() const { return EllipsisLoc.isValid(); }
};

} // namespace clang

namespace clang {

/// Internal struct for storing Key/value pair.
struct ObjCDictionaryLiteral_KeyValuePair {
  Expr *Key;
  Expr *Value;
};

/// Internal struct to describes an element that is a pack
/// expansion, used if any of the elements in the dictionary literal
/// are pack expansions.
struct ObjCDictionaryLiteral_ExpansionData {
  /// The location of the ellipsis, if this element is a pack
  /// expansion.
  SourceLocation EllipsisLoc;

  /// If non-zero, the number of elements that this pack
  /// expansion will expand to (+1).
  unsigned NumExpansionsPlusOne;
};

/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
/// literals; as in:  @{@"name" : NSUserName(), @"date" : [NSDate date] };
class ObjCDictionaryLiteral final
    : public Expr,
      private llvm::TrailingObjects<ObjCDictionaryLiteral,
                                    ObjCDictionaryLiteral_KeyValuePair,
                                    ObjCDictionaryLiteral_ExpansionData> {
  /// The number of elements in this dictionary literal.
  unsigned NumElements : 31;

  /// Determine whether this dictionary literal has any pack expansions.
  ///
  /// If the dictionary literal has pack expansions, then there will
  /// be an array of pack expansion data following the array of
  /// key/value pairs, which provide the locations of the ellipses (if
  /// any) and number of elements in the expansion (if known). If
  /// there are no pack expansions, we optimize away this storage.
  unsigned HasPackExpansions : 1;

  SourceRange Range;
  ObjCMethodDecl *DictWithObjectsMethod;

  using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair;
  using ExpansionData = ObjCDictionaryLiteral_ExpansionData;

  ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
                        bool HasPackExpansions,
                        QualType T, ObjCMethodDecl *method,
                        SourceRange SR);

  explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
                                 bool HasPackExpansions)
      : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
        HasPackExpansions(HasPackExpansions) {}

  size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
    return NumElements;
  }

public:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  static ObjCDictionaryLiteral *Create(const ASTContext &C,
                                       ArrayRef<ObjCDictionaryElement> VK,
                                       bool HasPackExpansions,
                                       QualType T, ObjCMethodDecl *method,
                                       SourceRange SR);

  static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
                                            unsigned NumElements,
                                            bool HasPackExpansions);

  /// getNumElements - Return number of elements of objective-c dictionary
  /// literal.
  unsigned getNumElements() const { return NumElements; }

  ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
    assert((Index < NumElements) && "Arg access out of range!");
    const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
    ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
    if (HasPackExpansions) {
      const ExpansionData &Expansion =
          getTrailingObjects<ExpansionData>()[Index];
      Result.EllipsisLoc = Expansion.EllipsisLoc;
      if (Expansion.NumExpansionsPlusOne > 0)
        Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
    }
    return Result;
  }

  ObjCMethodDecl *getDictWithObjectsMethod() const {
    return DictWithObjectsMethod;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }

  // Iterators
  child_range children() {
    // Note: we're taking advantage of the layout of the KeyValuePair struct
    // here. If that struct changes, this code will need to change as well.
    static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
                  "KeyValuePair is expected size");
    return child_range(
        reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()),
        reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) +
            NumElements * 2);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCDictionaryLiteralClass;
  }
};

/// ObjCEncodeExpr, used for \@encode in Objective-C.  \@encode has the same
/// type and behavior as StringLiteral except that the string initializer is
/// obtained from ASTContext with the encoding type as an argument.
class ObjCEncodeExpr : public Expr {
  TypeSourceInfo *EncodedType;
  SourceLocation AtLoc, RParenLoc;

public:
  ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
                 SourceLocation at, SourceLocation rp)
      : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
             EncodedType->getType()->isDependentType(),
             EncodedType->getType()->isDependentType(),
             EncodedType->getType()->isInstantiationDependentType(),
             EncodedType->getType()->containsUnexpandedParameterPack()),
        EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}

  explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}

  SourceLocation getAtLoc() const { return AtLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  QualType getEncodedType() const { return EncodedType->getType(); }

  TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }

  void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
    EncodedType = EncType;
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCEncodeExprClass;
  }
};

/// ObjCSelectorExpr used for \@selector in Objective-C.
class ObjCSelectorExpr : public Expr {
  Selector SelName;
  SourceLocation AtLoc, RParenLoc;

public:
  ObjCSelectorExpr(QualType T, Selector selInfo,
                   SourceLocation at, SourceLocation rp)
      : Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
             false, false),
        SelName(selInfo), AtLoc(at), RParenLoc(rp) {}
  explicit ObjCSelectorExpr(EmptyShell Empty)
      : Expr(ObjCSelectorExprClass, Empty) {}

  Selector getSelector() const { return SelName; }
  void setSelector(Selector S) { SelName = S; }

  SourceLocation getAtLoc() const { return AtLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  /// getNumArgs - Return the number of actual arguments to this call.
  unsigned getNumArgs() const { return SelName.getNumArgs(); }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCSelectorExprClass;
  }
};

/// ObjCProtocolExpr used for protocol expression in Objective-C.
///
/// This is used as: \@protocol(foo), as in:
/// \code
///   [obj conformsToProtocol:@protocol(foo)]
/// \endcode
///
/// The return type is "Protocol*".
class ObjCProtocolExpr : public Expr {
  ObjCProtocolDecl *TheProtocol;
  SourceLocation AtLoc, ProtoLoc, RParenLoc;

public:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
                 SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
      : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
             false, false),
        TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
  explicit ObjCProtocolExpr(EmptyShell Empty)
      : Expr(ObjCProtocolExprClass, Empty) {}

  ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
  void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }

  SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
  SourceLocation getAtLoc() const { return AtLoc; }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setAtLoc(SourceLocation L) { AtLoc = L; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }

  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCProtocolExprClass;
  }
};

/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
class ObjCIvarRefExpr : public Expr {
  ObjCIvarDecl *D;
  Stmt *Base;
  SourceLocation Loc;

  /// OpLoc - This is the location of '.' or '->'
  SourceLocation OpLoc;

  // True if this is "X->F", false if this is "X.F".
  bool IsArrow : 1;

  // True if ivar reference has no base (self assumed).
  bool IsFreeIvar : 1;

public:
  ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
                  SourceLocation l, SourceLocation oploc,
                  Expr *base,
                  bool arrow = false, bool freeIvar = false)
      : Expr(ObjCIvarRefExprClass, t, VK_LValue,
             d->isBitField() ? OK_BitField : OK_Ordinary,
             /*TypeDependent=*/false, base->isValueDependent(),
             base->isInstantiationDependent(),
             base->containsUnexpandedParameterPack()),
        D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow),
        IsFreeIvar(freeIvar) {}

  explicit ObjCIvarRefExpr(EmptyShell Empty)
      : Expr(ObjCIvarRefExprClass, Empty) {}

  ObjCIvarDecl *getDecl() { return D; }
  const ObjCIvarDecl *getDecl() const { return D; }
  void setDecl(ObjCIvarDecl *d) { D = d; }

  const Expr *getBase() const { return cast<Expr>(Base); }
  Expr *getBase() { return cast<Expr>(Base); }
  void setBase(Expr * base) { Base = base; }

  bool isArrow() const { return IsArrow; }
  bool isFreeIvar() const { return IsFreeIvar; }
  void setIsArrow(bool A) { IsArrow = A; }
  void setIsFreeIvar(bool A) { IsFreeIvar = A; }

  SourceLocation getLocation() const { return Loc; }
  void setLocation(SourceLocation L) { Loc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return isFreeIvar() ? Loc : getBase()->getBeginLoc();
  }
  SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }

  SourceLocation getOpLoc() const { return OpLoc; }
  void setOpLoc(SourceLocation L) { OpLoc = L; }

  // Iterators
  child_range children() { return child_range(&Base, &Base+1); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCIvarRefExprClass;
  }
};

/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
/// property.
class ObjCPropertyRefExpr : public Expr {
private:
  /// If the bool is true, this is an implicit property reference; the
  /// pointer is an (optional) ObjCMethodDecl and Setter may be set.
  /// if the bool is false, this is an explicit property reference;
  /// the pointer is an ObjCPropertyDecl and Setter is always null.
  llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter;

  /// Indicates whether the property reference will result in a message
  /// to the getter, the setter, or both.
  /// This applies to both implicit and explicit property references.
  enum MethodRefFlags {
    MethodRef_None = 0,
    MethodRef_Getter = 0x1,
    MethodRef_Setter = 0x2
  };

  /// Contains the Setter method pointer and MethodRefFlags bit flags.
  llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;

  // FIXME: Maybe we should store the property identifier here,
  // because it's not rederivable from the other data when there's an
  // implicit property with no getter (because the 'foo' -> 'setFoo:'
  // transformation is lossy on the first character).

  SourceLocation IdLoc;

  /// When the receiver in property access is 'super', this is
  /// the location of the 'super' keyword.  When it's an interface,
  /// this is that interface.
  SourceLocation ReceiverLoc;
  llvm::PointerUnion3<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver;

public:
  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
                      ExprValueKind VK, ExprObjectKind OK,
                      SourceLocation l, Expr *base)
      : Expr(ObjCPropertyRefExprClass, t, VK, OK,
             /*TypeDependent=*/false, base->isValueDependent(),
             base->isInstantiationDependent(),
             base->containsUnexpandedParameterPack()),
        PropertyOrGetter(PD, false), IdLoc(l), Receiver(base) {
    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
  }

  ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
                      ExprValueKind VK, ExprObjectKind OK,
                      SourceLocation l, SourceLocation sl, QualType st)
      : Expr(ObjCPropertyRefExprClass, t, VK, OK,
             /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
             st->containsUnexpandedParameterPack()),
        PropertyOrGetter(PD, false), IdLoc(l), ReceiverLoc(sl),
        Receiver(st.getTypePtr()) {
    assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
  }

  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
                      QualType T, ExprValueKind VK, ExprObjectKind OK,
                      SourceLocation IdLoc, Expr *Base)
      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
             Base->isValueDependent(), Base->isInstantiationDependent(),
             Base->containsUnexpandedParameterPack()),
        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
        IdLoc(IdLoc), Receiver(Base) {
    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
  }

  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
                      QualType T, ExprValueKind VK, ExprObjectKind OK,
                      SourceLocation IdLoc,
                      SourceLocation SuperLoc, QualType SuperTy)
      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
        IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
  }

  ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
                      QualType T, ExprValueKind VK, ExprObjectKind OK,
                      SourceLocation IdLoc,
                      SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
      : Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
        PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
        IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
    assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
  }

  explicit ObjCPropertyRefExpr(EmptyShell Empty)
      : Expr(ObjCPropertyRefExprClass, Empty) {}

  bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
  bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }

  ObjCPropertyDecl *getExplicitProperty() const {
    assert(!isImplicitProperty());
    return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
  }

  ObjCMethodDecl *getImplicitPropertyGetter() const {
    assert(isImplicitProperty());
    return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
  }

  ObjCMethodDecl *getImplicitPropertySetter() const {
    assert(isImplicitProperty());
    return SetterAndMethodRefFlags.getPointer();
  }

  Selector getGetterSelector() const {
    if (isImplicitProperty())
      return getImplicitPropertyGetter()->getSelector();
    return getExplicitProperty()->getGetterName();
  }

  Selector getSetterSelector() const {
    if (isImplicitProperty())
      return getImplicitPropertySetter()->getSelector();
    return getExplicitProperty()->getSetterName();
  }

  /// True if the property reference will result in a message to the
  /// getter.
  /// This applies to both implicit and explicit property references.
  bool isMessagingGetter() const {
    return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
  }

  /// True if the property reference will result in a message to the
  /// setter.
  /// This applies to both implicit and explicit property references.
  bool isMessagingSetter() const {
    return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
  }

  void setIsMessagingGetter(bool val = true) {
    setMethodRefFlag(MethodRef_Getter, val);
  }

  void setIsMessagingSetter(bool val = true) {
    setMethodRefFlag(MethodRef_Setter, val);
  }

  const Expr *getBase() const {
    return cast<Expr>(Receiver.get<Stmt*>());
  }
  Expr *getBase() {
    return cast<Expr>(Receiver.get<Stmt*>());
  }

  SourceLocation getLocation() const { return IdLoc; }

  SourceLocation getReceiverLocation() const { return ReceiverLoc; }

  QualType getSuperReceiverType() const {
    return QualType(Receiver.get<const Type*>(), 0);
  }

  ObjCInterfaceDecl *getClassReceiver() const {
    return Receiver.get<ObjCInterfaceDecl*>();
  }

  bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
  bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
  bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }

  /// Determine the type of the base, regardless of the kind of receiver.
  QualType getReceiverType(const ASTContext &ctx) const;

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return isObjectReceiver() ? getBase()->getBeginLoc()
                              : getReceiverLocation();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return IdLoc; }

  // Iterators
  child_range children() {
    if (Receiver.is<Stmt*>()) {
      Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
      return child_range(begin, begin+1);
    }
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCPropertyRefExprClass;
  }

private:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;

  void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
    PropertyOrGetter.setPointer(D);
    PropertyOrGetter.setInt(false);
    SetterAndMethodRefFlags.setPointer(nullptr);
    SetterAndMethodRefFlags.setInt(methRefFlags);
  }

  void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
                           unsigned methRefFlags) {
    PropertyOrGetter.setPointer(Getter);
    PropertyOrGetter.setInt(true);
    SetterAndMethodRefFlags.setPointer(Setter);
    SetterAndMethodRefFlags.setInt(methRefFlags);
  }

  void setBase(Expr *Base) { Receiver = Base; }
  void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
  void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }

  void setLocation(SourceLocation L) { IdLoc = L; }
  void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }

  void setMethodRefFlag(MethodRefFlags flag, bool val) {
    unsigned f = SetterAndMethodRefFlags.getInt();
    if (val)
      f |= flag;
    else
      f &= ~flag;
    SetterAndMethodRefFlags.setInt(f);
  }
};

/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
class ObjCSubscriptRefExpr : public Expr {
  // Location of ']' in an indexing expression.
  SourceLocation RBracket;

  // array/dictionary base expression.
  // for arrays, this is a numeric expression. For dictionaries, this is
  // an objective-c object pointer expression.
  enum { BASE, KEY, END_EXPR };
  Stmt* SubExprs[END_EXPR];

  ObjCMethodDecl *GetAtIndexMethodDecl;

  // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
  // an indexed object this is null too.
  ObjCMethodDecl *SetAtIndexMethodDecl;

public:
  ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
                       ExprValueKind VK, ExprObjectKind OK,
                       ObjCMethodDecl *getMethod,
                       ObjCMethodDecl *setMethod, SourceLocation RB)
      : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
             base->isTypeDependent() || key->isTypeDependent(),
             base->isValueDependent() || key->isValueDependent(),
             (base->isInstantiationDependent() ||
              key->isInstantiationDependent()),
             (base->containsUnexpandedParameterPack() ||
              key->containsUnexpandedParameterPack())),
        RBracket(RB), GetAtIndexMethodDecl(getMethod),
        SetAtIndexMethodDecl(setMethod) {
    SubExprs[BASE] = base; SubExprs[KEY] = key;
  }

  explicit ObjCSubscriptRefExpr(EmptyShell Empty)
      : Expr(ObjCSubscriptRefExprClass, Empty) {}

  SourceLocation getRBracket() const { return RBracket; }
  void setRBracket(SourceLocation RB) { RBracket = RB; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return SubExprs[BASE]->getBeginLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return RBracket; }

  Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
  void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }

  Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
  void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }

  ObjCMethodDecl *getAtIndexMethodDecl() const {
    return GetAtIndexMethodDecl;
  }

  ObjCMethodDecl *setAtIndexMethodDecl() const {
    return SetAtIndexMethodDecl;
  }

  bool isArraySubscriptRefExpr() const {
    return getKeyExpr()->getType()->isIntegralOrEnumerationType();
  }

  child_range children() {
    return child_range(SubExprs, SubExprs+END_EXPR);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCSubscriptRefExprClass;
  }

private:
  friend class ASTStmtReader;
};

/// An expression that sends a message to the given Objective-C
/// object or class.
///
/// The following contains two message send expressions:
///
/// \code
///   [[NSString alloc] initWithString:@"Hello"]
/// \endcode
///
/// The innermost message send invokes the "alloc" class method on the
/// NSString class, while the outermost message send invokes the
/// "initWithString" instance method on the object returned from
/// NSString's "alloc". In all, an Objective-C message send can take
/// on four different (although related) forms:
///
///   1. Send to an object instance.
///   2. Send to a class.
///   3. Send to the superclass instance of the current class.
///   4. Send to the superclass of the current class.
///
/// All four kinds of message sends are modeled by the ObjCMessageExpr
/// class, and can be distinguished via \c getReceiverKind(). Example:
///
/// The "void *" trailing objects are actually ONE void * (the
/// receiver pointer), and NumArgs Expr *. But due to the
/// implementation of children(), these must be together contiguously.
class ObjCMessageExpr final
    : public Expr,
      private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
  /// Stores either the selector that this message is sending
  /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
  /// referring to the method that we type-checked against.
  uintptr_t SelectorOrMethod = 0;

  enum { NumArgsBitWidth = 16 };

  /// The number of arguments in the message send, not
  /// including the receiver.
  unsigned NumArgs : NumArgsBitWidth;

  /// The kind of message send this is, which is one of the
  /// ReceiverKind values.
  ///
  /// We pad this out to a byte to avoid excessive masking and shifting.
  unsigned Kind : 8;

  /// Whether we have an actual method prototype in \c
  /// SelectorOrMethod.
  ///
  /// When non-zero, we have a method declaration; otherwise, we just
  /// have a selector.
  unsigned HasMethod : 1;

  /// Whether this message send is a "delegate init call",
  /// i.e. a call of an init method on self from within an init method.
  unsigned IsDelegateInitCall : 1;

  /// Whether this message send was implicitly generated by
  /// the implementation rather than explicitly written by the user.
  unsigned IsImplicit : 1;

  /// Whether the locations of the selector identifiers are in a
  /// "standard" position, a enum SelectorLocationsKind.
  unsigned SelLocsKind : 2;

  /// When the message expression is a send to 'super', this is
  /// the location of the 'super' keyword.
  SourceLocation SuperLoc;

  /// The source locations of the open and close square
  /// brackets ('[' and ']', respectively).
  SourceLocation LBracLoc, RBracLoc;

  ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
      : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false),
        IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) {
    setNumArgs(NumArgs);
  }

  ObjCMessageExpr(QualType T, ExprValueKind VK,
                  SourceLocation LBracLoc,
                  SourceLocation SuperLoc,
                  bool IsInstanceSuper,
                  QualType SuperType,
                  Selector Sel,
                  ArrayRef<SourceLocation> SelLocs,
                  SelectorLocationsKind SelLocsK,
                  ObjCMethodDecl *Method,
                  ArrayRef<Expr *> Args,
                  SourceLocation RBracLoc,
                  bool isImplicit);
  ObjCMessageExpr(QualType T, ExprValueKind VK,
                  SourceLocation LBracLoc,
                  TypeSourceInfo *Receiver,
                  Selector Sel,
                  ArrayRef<SourceLocation> SelLocs,
                  SelectorLocationsKind SelLocsK,
                  ObjCMethodDecl *Method,
                  ArrayRef<Expr *> Args,
                  SourceLocation RBracLoc,
                  bool isImplicit);
  ObjCMessageExpr(QualType T, ExprValueKind VK,
                  SourceLocation LBracLoc,
                  Expr *Receiver,
                  Selector Sel,
                  ArrayRef<SourceLocation> SelLocs,
                  SelectorLocationsKind SelLocsK,
                  ObjCMethodDecl *Method,
                  ArrayRef<Expr *> Args,
                  SourceLocation RBracLoc,
                  bool isImplicit);

  size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }

  void setNumArgs(unsigned Num) {
    assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
    NumArgs = Num;
  }

  void initArgsAndSelLocs(ArrayRef<Expr *> Args,
                          ArrayRef<SourceLocation> SelLocs,
                          SelectorLocationsKind SelLocsK);

  /// Retrieve the pointer value of the message receiver.
  void *getReceiverPointer() const { return *getTrailingObjects<void *>(); }

  /// Set the pointer value of the message receiver.
  void setReceiverPointer(void *Value) {
    *getTrailingObjects<void *>() = Value;
  }

  SelectorLocationsKind getSelLocsKind() const {
    return (SelectorLocationsKind)SelLocsKind;
  }

  bool hasStandardSelLocs() const {
    return getSelLocsKind() != SelLoc_NonStandard;
  }

  /// Get a pointer to the stored selector identifiers locations array.
  /// No locations will be stored if HasStandardSelLocs is true.
  SourceLocation *getStoredSelLocs() {
    return getTrailingObjects<SourceLocation>();
  }
  const SourceLocation *getStoredSelLocs() const {
    return getTrailingObjects<SourceLocation>();
  }

  /// Get the number of stored selector identifiers locations.
  /// No locations will be stored if HasStandardSelLocs is true.
  unsigned getNumStoredSelLocs() const {
    if (hasStandardSelLocs())
      return 0;
    return getNumSelectorLocs();
  }

  static ObjCMessageExpr *alloc(const ASTContext &C,
                                ArrayRef<Expr *> Args,
                                SourceLocation RBraceLoc,
                                ArrayRef<SourceLocation> SelLocs,
                                Selector Sel,
                                SelectorLocationsKind &SelLocsK);
  static ObjCMessageExpr *alloc(const ASTContext &C,
                                unsigned NumArgs,
                                unsigned NumStoredSelLocs);

public:
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;

  /// The kind of receiver this message is sending to.
  enum ReceiverKind {
    /// The receiver is a class.
    Class = 0,

    /// The receiver is an object instance.
    Instance,

    /// The receiver is a superclass.
    SuperClass,

    /// The receiver is the instance of the superclass object.
    SuperInstance
  };

  /// Create a message send to super.
  ///
  /// \param Context The ASTContext in which this expression will be created.
  ///
  /// \param T The result type of this message.
  ///
  /// \param VK The value kind of this message.  A message returning
  /// a l-value or r-value reference will be an l-value or x-value,
  /// respectively.
  ///
  /// \param LBracLoc The location of the open square bracket '['.
  ///
  /// \param SuperLoc The location of the "super" keyword.
  ///
  /// \param IsInstanceSuper Whether this is an instance "super"
  /// message (otherwise, it's a class "super" message).
  ///
  /// \param Sel The selector used to determine which method gets called.
  ///
  /// \param Method The Objective-C method against which this message
  /// send was type-checked. May be nullptr.
  ///
  /// \param Args The message send arguments.
  ///
  /// \param RBracLoc The location of the closing square bracket ']'.
  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
                                 ExprValueKind VK,
                                 SourceLocation LBracLoc,
                                 SourceLocation SuperLoc,
                                 bool IsInstanceSuper,
                                 QualType SuperType,
                                 Selector Sel,
                                 ArrayRef<SourceLocation> SelLocs,
                                 ObjCMethodDecl *Method,
                                 ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc,
                                 bool isImplicit);

  /// Create a class message send.
  ///
  /// \param Context The ASTContext in which this expression will be created.
  ///
  /// \param T The result type of this message.
  ///
  /// \param VK The value kind of this message.  A message returning
  /// a l-value or r-value reference will be an l-value or x-value,
  /// respectively.
  ///
  /// \param LBracLoc The location of the open square bracket '['.
  ///
  /// \param Receiver The type of the receiver, including
  /// source-location information.
  ///
  /// \param Sel The selector used to determine which method gets called.
  ///
  /// \param Method The Objective-C method against which this message
  /// send was type-checked. May be nullptr.
  ///
  /// \param Args The message send arguments.
  ///
  /// \param RBracLoc The location of the closing square bracket ']'.
  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
                                 ExprValueKind VK,
                                 SourceLocation LBracLoc,
                                 TypeSourceInfo *Receiver,
                                 Selector Sel,
                                 ArrayRef<SourceLocation> SelLocs,
                                 ObjCMethodDecl *Method,
                                 ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc,
                                 bool isImplicit);

  /// Create an instance message send.
  ///
  /// \param Context The ASTContext in which this expression will be created.
  ///
  /// \param T The result type of this message.
  ///
  /// \param VK The value kind of this message.  A message returning
  /// a l-value or r-value reference will be an l-value or x-value,
  /// respectively.
  ///
  /// \param LBracLoc The location of the open square bracket '['.
  ///
  /// \param Receiver The expression used to produce the object that
  /// will receive this message.
  ///
  /// \param Sel The selector used to determine which method gets called.
  ///
  /// \param Method The Objective-C method against which this message
  /// send was type-checked. May be nullptr.
  ///
  /// \param Args The message send arguments.
  ///
  /// \param RBracLoc The location of the closing square bracket ']'.
  static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
                                 ExprValueKind VK,
                                 SourceLocation LBracLoc,
                                 Expr *Receiver,
                                 Selector Sel,
                                 ArrayRef<SourceLocation> SeLocs,
                                 ObjCMethodDecl *Method,
                                 ArrayRef<Expr *> Args,
                                 SourceLocation RBracLoc,
                                 bool isImplicit);

  /// Create an empty Objective-C message expression, to be
  /// filled in by subsequent calls.
  ///
  /// \param Context The context in which the message send will be created.
  ///
  /// \param NumArgs The number of message arguments, not including
  /// the receiver.
  static ObjCMessageExpr *CreateEmpty(const ASTContext &Context,
                                      unsigned NumArgs,
                                      unsigned NumStoredSelLocs);

  /// Indicates whether the message send was implicitly
  /// generated by the implementation. If false, it was written explicitly
  /// in the source code.
  bool isImplicit() const { return IsImplicit; }

  /// Determine the kind of receiver that this message is being
  /// sent to.
  ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }

  /// \return the return type of the message being sent.
  /// This is not always the type of the message expression itself because
  /// of references (the expression would not have a reference type).
  /// It is also not always the declared return type of the method because
  /// of `instancetype` (in that case it's an expression type).
  QualType getCallReturnType(ASTContext &Ctx) const;

  /// Source range of the receiver.
  SourceRange getReceiverRange() const;

  /// Determine whether this is an instance message to either a
  /// computed object or to super.
  bool isInstanceMessage() const {
    return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
  }

  /// Determine whether this is an class message to either a
  /// specified class or to super.
  bool isClassMessage() const {
    return getReceiverKind() == Class || getReceiverKind() == SuperClass;
  }

  /// Returns the object expression (receiver) for an instance message,
  /// or null for a message that is not an instance message.
  Expr *getInstanceReceiver() {
    if (getReceiverKind() == Instance)
      return static_cast<Expr *>(getReceiverPointer());

    return nullptr;
  }
  const Expr *getInstanceReceiver() const {
    return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
  }

  /// Turn this message send into an instance message that
  /// computes the receiver object with the given expression.
  void setInstanceReceiver(Expr *rec) {
    Kind = Instance;
    setReceiverPointer(rec);
  }

  /// Returns the type of a class message send, or NULL if the
  /// message is not a class message.
  QualType getClassReceiver() const {
    if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
      return TSInfo->getType();

    return {};
  }

  /// Returns a type-source information of a class message
  /// send, or nullptr if the message is not a class message.
  TypeSourceInfo *getClassReceiverTypeInfo() const {
    if (getReceiverKind() == Class)
      return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
    return nullptr;
  }

  void setClassReceiver(TypeSourceInfo *TSInfo) {
    Kind = Class;
    setReceiverPointer(TSInfo);
  }

  /// Retrieve the location of the 'super' keyword for a class
  /// or instance message to 'super', otherwise an invalid source location.
  SourceLocation getSuperLoc() const {
    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
      return SuperLoc;

    return SourceLocation();
  }

  /// Retrieve the receiver type to which this message is being directed.
  ///
  /// This routine cross-cuts all of the different kinds of message
  /// sends to determine what the underlying (statically known) type
  /// of the receiver will be; use \c getReceiverKind() to determine
  /// whether the message is a class or an instance method, whether it
  /// is a send to super or not, etc.
  ///
  /// \returns The type of the receiver.
  QualType getReceiverType() const;

  /// Retrieve the Objective-C interface to which this message
  /// is being directed, if known.
  ///
  /// This routine cross-cuts all of the different kinds of message
  /// sends to determine what the underlying (statically known) type
  /// of the receiver will be; use \c getReceiverKind() to determine
  /// whether the message is a class or an instance method, whether it
  /// is a send to super or not, etc.
  ///
  /// \returns The Objective-C interface if known, otherwise nullptr.
  ObjCInterfaceDecl *getReceiverInterface() const;

  /// Retrieve the type referred to by 'super'.
  ///
  /// The returned type will either be an ObjCInterfaceType (for an
  /// class message to super) or an ObjCObjectPointerType that refers
  /// to a class (for an instance message to super);
  QualType getSuperType() const {
    if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
      return QualType::getFromOpaquePtr(getReceiverPointer());

    return QualType();
  }

  void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
    Kind = IsInstanceSuper? SuperInstance : SuperClass;
    SuperLoc = Loc;
    setReceiverPointer(T.getAsOpaquePtr());
  }

  Selector getSelector() const;

  void setSelector(Selector S) {
    HasMethod = false;
    SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
  }

  const ObjCMethodDecl *getMethodDecl() const {
    if (HasMethod)
      return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);

    return nullptr;
  }

  ObjCMethodDecl *getMethodDecl() {
    if (HasMethod)
      return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);

    return nullptr;
  }

  void setMethodDecl(ObjCMethodDecl *MD) {
    HasMethod = true;
    SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
  }

  ObjCMethodFamily getMethodFamily() const {
    if (HasMethod) return getMethodDecl()->getMethodFamily();
    return getSelector().getMethodFamily();
  }

  /// Return the number of actual arguments in this message,
  /// not counting the receiver.
  unsigned getNumArgs() const { return NumArgs; }

  /// Retrieve the arguments to this message, not including the
  /// receiver.
  Expr **getArgs() {
    return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1);
  }
  const Expr * const *getArgs() const {
    return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() +
                                                 1);
  }

  /// getArg - Return the specified argument.
  Expr *getArg(unsigned Arg) {
    assert(Arg < NumArgs && "Arg access out of range!");
    return getArgs()[Arg];
  }
  const Expr *getArg(unsigned Arg) const {
    assert(Arg < NumArgs && "Arg access out of range!");
    return getArgs()[Arg];
  }

  /// setArg - Set the specified argument.
  void setArg(unsigned Arg, Expr *ArgExpr) {
    assert(Arg < NumArgs && "Arg access out of range!");
    getArgs()[Arg] = ArgExpr;
  }

  /// isDelegateInitCall - Answers whether this message send has been
  /// tagged as a "delegate init call", i.e. a call to a method in the
  /// -init family on self from within an -init method implementation.
  bool isDelegateInitCall() const { return IsDelegateInitCall; }
  void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }

  SourceLocation getLeftLoc() const { return LBracLoc; }
  SourceLocation getRightLoc() const { return RBracLoc; }

  SourceLocation getSelectorStartLoc() const {
    if (isImplicit())
      return getBeginLoc();
    return getSelectorLoc(0);
  }

  SourceLocation getSelectorLoc(unsigned Index) const {
    assert(Index < getNumSelectorLocs() && "Index out of range!");
    if (hasStandardSelLocs())
      return getStandardSelectorLoc(Index, getSelector(),
                                   getSelLocsKind() == SelLoc_StandardWithSpace,
                               llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
                                                  getNumArgs()),
                                   RBracLoc);
    return getStoredSelLocs()[Index];
  }

  void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;

  unsigned getNumSelectorLocs() const {
    if (isImplicit())
      return 0;
    Selector Sel = getSelector();
    if (Sel.isUnarySelector())
      return 1;
    return Sel.getNumArgs();
  }

  void setSourceRange(SourceRange R) {
    LBracLoc = R.getBegin();
    RBracLoc = R.getEnd();
  }

  SourceLocation getBeginLoc() const LLVM_READONLY { return LBracLoc; }
  SourceLocation getEndLoc() const LLVM_READONLY { return RBracLoc; }

  // Iterators
  child_range children();

  using arg_iterator = ExprIterator;
  using const_arg_iterator = ConstExprIterator;

  llvm::iterator_range<arg_iterator> arguments() {
    return llvm::make_range(arg_begin(), arg_end());
  }

  llvm::iterator_range<const_arg_iterator> arguments() const {
    return llvm::make_range(arg_begin(), arg_end());
  }

  arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }

  arg_iterator arg_end()   {
    return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
  }

  const_arg_iterator arg_begin() const {
    return reinterpret_cast<Stmt const * const*>(getArgs());
  }

  const_arg_iterator arg_end() const {
    return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCMessageExprClass;
  }
};

/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
/// (similar in spirit to MemberExpr).
class ObjCIsaExpr : public Expr {
  /// Base - the expression for the base object pointer.
  Stmt *Base;

  /// IsaMemberLoc - This is the location of the 'isa'.
  SourceLocation IsaMemberLoc;

  /// OpLoc - This is the location of '.' or '->'
  SourceLocation OpLoc;

  /// IsArrow - True if this is "X->F", false if this is "X.F".
  bool IsArrow;

public:
  ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
              QualType ty)
      : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
             /*TypeDependent=*/false, base->isValueDependent(),
             base->isInstantiationDependent(),
             /*ContainsUnexpandedParameterPack=*/false),
        Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}

  /// Build an empty expression.
  explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {}

  void setBase(Expr *E) { Base = E; }
  Expr *getBase() const { return cast<Expr>(Base); }

  bool isArrow() const { return IsArrow; }
  void setArrow(bool A) { IsArrow = A; }

  /// getMemberLoc - Return the location of the "member", in X->F, it is the
  /// location of 'F'.
  SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
  void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }

  SourceLocation getOpLoc() const { return OpLoc; }
  void setOpLoc(SourceLocation L) { OpLoc = L; }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return getBase()->getBeginLoc();
  }

  SourceLocation getBaseLocEnd() const LLVM_READONLY {
    return getBase()->getEndLoc();
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return IsaMemberLoc; }

  SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }

  // Iterators
  child_range children() { return child_range(&Base, &Base+1); }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCIsaExprClass;
  }
};

/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
/// argument by indirect copy-restore in ARC.  This is used to support
/// passing indirect arguments with the wrong lifetime, e.g. when
/// passing the address of a __strong local variable to an 'out'
/// parameter.  This expression kind is only valid in an "argument"
/// position to some sort of call expression.
///
/// The parameter must have type 'pointer to T', and the argument must
/// have type 'pointer to U', where T and U agree except possibly in
/// qualification.  If the argument value is null, then a null pointer
/// is passed;  otherwise it points to an object A, and:
/// 1. A temporary object B of type T is initialized, either by
///    zero-initialization (used when initializing an 'out' parameter)
///    or copy-initialization (used when initializing an 'inout'
///    parameter).
/// 2. The address of the temporary is passed to the function.
/// 3. If the call completes normally, A is move-assigned from B.
/// 4. Finally, A is destroyed immediately.
///
/// Currently 'T' must be a retainable object lifetime and must be
/// __autoreleasing;  this qualifier is ignored when initializing
/// the value.
class ObjCIndirectCopyRestoreExpr : public Expr {
  friend class ASTReader;
  friend class ASTStmtReader;

  Stmt *Operand;

  // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;

  explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
      : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {}

  void setShouldCopy(bool shouldCopy) {
    ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
  }

public:
  ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
      : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
             operand->isTypeDependent(), operand->isValueDependent(),
             operand->isInstantiationDependent(),
             operand->containsUnexpandedParameterPack()),
        Operand(operand) {
    setShouldCopy(shouldCopy);
  }

  Expr *getSubExpr() { return cast<Expr>(Operand); }
  const Expr *getSubExpr() const { return cast<Expr>(Operand); }

  /// shouldCopy - True if we should do the 'copy' part of the
  /// copy-restore.  If false, the temporary will be zero-initialized.
  bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }

  child_range children() { return child_range(&Operand, &Operand+1); }

  // Source locations are determined by the subexpression.
  SourceLocation getBeginLoc() const LLVM_READONLY {
    return Operand->getBeginLoc();
  }
  SourceLocation getEndLoc() const LLVM_READONLY {
    return Operand->getEndLoc();
  }

  SourceLocation getExprLoc() const LLVM_READONLY {
    return getSubExpr()->getExprLoc();
  }

  static bool classof(const Stmt *s) {
    return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
  }
};

/// An Objective-C "bridged" cast expression, which casts between
/// Objective-C pointers and C pointers, transferring ownership in the process.
///
/// \code
/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
/// \endcode
class ObjCBridgedCastExpr final
    : public ExplicitCastExpr,
      private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend class CastExpr;
  friend TrailingObjects;

  SourceLocation LParenLoc;
  SourceLocation BridgeKeywordLoc;
  unsigned Kind : 2;

public:
  ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
                      CastKind CK, SourceLocation BridgeKeywordLoc,
                      TypeSourceInfo *TSInfo, Expr *Operand)
      : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
                         CK, Operand, 0, TSInfo),
        LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {}

  /// Construct an empty Objective-C bridged cast.
  explicit ObjCBridgedCastExpr(EmptyShell Shell)
      : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {}

  SourceLocation getLParenLoc() const { return LParenLoc; }

  /// Determine which kind of bridge is being performed via this cast.
  ObjCBridgeCastKind getBridgeKind() const {
    return static_cast<ObjCBridgeCastKind>(Kind);
  }

  /// Retrieve the kind of bridge being performed as a string.
  StringRef getBridgeKindName() const;

  /// The location of the bridge keyword.
  SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }

  SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }

  SourceLocation getEndLoc() const LLVM_READONLY {
    return getSubExpr()->getEndLoc();
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBridgedCastExprClass;
  }
};

/// A runtime availability query.
///
/// There are 2 ways to spell this node:
/// \code
///   @available(macos 10.10, ios 8, *); // Objective-C
///   __builtin_available(macos 10.10, ios 8, *); // C, C++, and Objective-C
/// \endcode
///
/// Note that we only need to keep track of one \c VersionTuple here, which is
/// the one that corresponds to the current deployment target. This is meant to
/// be used in the condition of an \c if, but it is also usable as top level
/// expressions.
///
class ObjCAvailabilityCheckExpr : public Expr {
  friend class ASTStmtReader;

  VersionTuple VersionToCheck;
  SourceLocation AtLoc, RParen;

public:
  ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc,
                            SourceLocation RParen, QualType Ty)
      : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary, false,
             false, false, false),
        VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {}

  explicit ObjCAvailabilityCheckExpr(EmptyShell Shell)
      : Expr(ObjCAvailabilityCheckExprClass, Shell) {}

  SourceLocation getBeginLoc() const { return AtLoc; }
  SourceLocation getEndLoc() const { return RParen; }
  SourceRange getSourceRange() const { return {AtLoc, RParen}; }

  /// This may be '*', in which case this should fold to true.
  bool hasVersion() const { return !VersionToCheck.empty(); }
  VersionTuple getVersion() { return VersionToCheck; }

  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCAvailabilityCheckExprClass;
  }
};

} // namespace clang

#endif // LLVM_CLANG_AST_EXPROBJC_H
