//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ExprObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H

#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/Support/Compiler.h"

namespace clang {
  class IdentifierInfo;
  class ASTContext;

/// 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 getLocStart() const LLVM_READONLY { return AtLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }

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

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

/// 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 getLocStart() const LLVM_READONLY { return Loc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }

  SourceLocation getLocation() const { return Loc; }
  void setLocation(SourceLocation L) { Loc = L; }
    
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBoolLiteralExprClass;
  }
    
  // Iterators
  child_range children() {
    return child_range(child_iterator(), child_iterator());
  }
};

/// 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:
  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 getLocStart() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY {
    return Range;
  }
  
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBoxedExprClass;
  }
  
  // Iterators
  child_range children() { return child_range(&SubExpr, &SubExpr+1); }

  typedef ConstExprIterator const_arg_iterator;

  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);
  }
  
  friend class ASTStmtReader;
};

/// 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:
  static ObjCArrayLiteral *Create(const ASTContext &C,
                                  ArrayRef<Expr *> Elements,
                                  QualType T, ObjCMethodDecl * Method,
                                  SourceRange SR);

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

  SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }

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

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

  /// \brief 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; }
    
    /// getExpr - Return the Expr at the specified index.
  Expr *getElement(unsigned Index) {
    assert((Index < NumElements) && "Arg access out of range!");
    return cast<Expr>(getElements()[Index]);
  }
  const Expr *getElement(unsigned Index) const {
    assert((Index < NumElements) && "Arg access out of range!");
    return cast<Expr>(getElements()[Index]);
  }
    
  ObjCMethodDecl *getArrayWithObjectsMethod() const {
    return ArrayWithObjectsMethod; 
  }
    
  // Iterators
  child_range children() {
    return child_range(reinterpret_cast<Stmt **>(getElements()),
                       reinterpret_cast<Stmt **>(getElements()) + NumElements);
  }

  friend TrailingObjects;
  friend class ASTStmtReader;
};

/// \brief An element in an Objective-C dictionary literal.
///
struct ObjCDictionaryElement {
  /// \brief The key for the dictionary element.
  Expr *Key;
  
  /// \brief The value of the dictionary element.
  Expr *Value;
  
  /// \brief The location of the ellipsis, if this is a pack expansion.
  SourceLocation EllipsisLoc;
  
  /// \brief The number of elements this pack expansion will expand to, if
  /// this is a pack expansion and is known.
  Optional<unsigned> NumExpansions;

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

namespace llvm {
template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
}

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

/// \brief 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 {
  /// \brief The location of the ellipsis, if this element is a pack
  /// expansion.
  SourceLocation EllipsisLoc;

  /// \brief 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> {
  /// \brief The number of elements in this dictionary literal.
  unsigned NumElements : 31;

  /// \brief 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;

  typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair;
  typedef ObjCDictionaryLiteral_ExpansionData ExpansionData;

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

  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) {}

public:
  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 getLocStart() const LLVM_READONLY { return Range.getBegin(); }
  SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
  SourceRange getSourceRange() const LLVM_READONLY { return Range; }
  
  static bool classof(const Stmt *T) {
      return T->getStmtClass() == ObjCDictionaryLiteralClass;
  }
    
  // 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);
  }
    
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  friend TrailingObjects;
};


/// 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 getLocStart() const LLVM_READONLY { return AtLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }

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

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

/// 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 getLocStart() const LLVM_READONLY { return AtLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }

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

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

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

/// 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:
  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 getLocStart() const LLVM_READONLY { return AtLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }

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

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

  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// 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;
  
  bool IsArrow:1;      // True if this is "X->F", false if this is "X.F".
  bool IsFreeIvar:1;   // True if ivar reference has no base (self assumed).

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 getLocStart() const LLVM_READONLY {
    return isFreeIvar() ? Loc : getBase()->getLocStart();
  }
  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
  
  SourceLocation getOpLoc() const { return OpLoc; }
  void setOpLoc(SourceLocation L) { OpLoc = L; }

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

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

/// 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;

  /// \brief 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
  };

  /// \brief 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;
  
  /// \brief 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), SetterAndMethodRefFlags(),
      IdLoc(l), ReceiverLoc(), 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), SetterAndMethodRefFlags(),
      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), ReceiverLoc(), 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();
  }

  /// \brief 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;
  }

  /// \brief 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 getLocStart() const LLVM_READONLY {
    return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
  }
  SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }

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

  // 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());
  }

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 getLocStart() const LLVM_READONLY {
    return SubExprs[BASE]->getLocStart();
  }
  SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }

  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCSubscriptRefExprClass;
  }
  
  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);
  }
private:
  friend class ASTStmtReader;
};
  

/// \brief 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> {
  /// \brief 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;

  enum { NumArgsBitWidth = 16 };

  /// \brief The number of arguments in the message send, not
  /// including the receiver.
  unsigned NumArgs : NumArgsBitWidth;
  
  /// \brief 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;

  /// \brief 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;

  /// \brief 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;

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

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

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

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

  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;
  }

  ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
    : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0), 
      HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), 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);

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

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

  /// \brief 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;
  }

  /// \brief 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>();
  }

  /// \brief 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:
  /// \brief The kind of receiver this message is sending to.
  enum ReceiverKind {
    /// \brief The receiver is a class.
    Class = 0,
    /// \brief The receiver is an object instance.
    Instance,
    /// \brief The receiver is a superclass.
    SuperClass,
    /// \brief The receiver is the instance of the superclass object.
    SuperInstance
  };

  /// \brief 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 NULL.
  ///
  /// \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);

  /// \brief 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 NULL.
  ///
  /// \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);

  /// \brief 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 NULL.
  ///
  /// \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);

  /// \brief 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);

  /// \brief 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; }

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

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

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

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

  /// \brief 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();
  }

  /// \brief 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);
  }
  
  /// \brief 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 QualType();
  }

  /// \brief Returns a type-source information of a class message
  /// send, or NULL 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);
  }

  /// \brief 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();
  }

  /// \brief 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;

  /// \brief 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 NULL.
  ObjCInterfaceDecl *getReceiverInterface() const;

  /// \brief 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();
  }

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

  /// \brief 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 getLocStart();
    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 getLocStart() const LLVM_READONLY { return LBracLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }

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

  // Iterators
  child_range children();

  typedef ExprIterator arg_iterator;
  typedef ConstExprIterator const_arg_iterator;

  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); 
  }

  friend TrailingObjects;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
};

/// 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) {}

  /// \brief 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 getLocStart() const LLVM_READONLY {
    return getBase()->getLocStart();
  }
  
  SourceLocation getBaseLocEnd() const LLVM_READONLY {
    return getBase()->getLocEnd();
  }
  
  SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }

  SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }

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

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


/// 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 {
  Stmt *Operand;

  // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;

  friend class ASTReader;
  friend class ASTStmtReader;

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

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

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 getLocStart() const LLVM_READONLY {
    return Operand->getLocStart();
  }
  SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();}

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

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

/// \brief 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 *> {
  SourceLocation LParenLoc;
  SourceLocation BridgeKeywordLoc;
  unsigned Kind : 2;

  friend TrailingObjects;
  friend class CastExpr;
  friend class ASTStmtReader;
  friend class ASTStmtWriter;
  
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) { }
  
  /// \brief Construct an empty Objective-C bridged cast.
  explicit ObjCBridgedCastExpr(EmptyShell Shell)
    : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }

  SourceLocation getLParenLoc() const { return LParenLoc; }

  /// \brief Determine which kind of bridge is being performed via this cast.
  ObjCBridgeCastKind getBridgeKind() const { 
    return static_cast<ObjCBridgeCastKind>(Kind); 
  }
  
  /// \brief Retrieve the kind of bridge being performed as a string.
  StringRef getBridgeKindName() const;
  
  /// \brief The location of the bridge keyword.
  SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
  
  SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
  SourceLocation getLocEnd() const LLVM_READONLY {
    return getSubExpr()->getLocEnd();
  }
  
  static bool classof(const Stmt *T) {
    return T->getStmtClass() == ObjCBridgedCastExprClass;
  }
};

/// \brief 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 {
  VersionTuple VersionToCheck;
  SourceLocation AtLoc, RParen;

  friend class ASTStmtReader;
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 getLocStart() const { return AtLoc; }
  SourceLocation getLocEnd() const { return RParen; }
  SourceRange getSourceRange() const { return {AtLoc, RParen}; }

  /// \brief 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;
  }
};

}  // end namespace clang

#endif
