//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H

#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/FunctionRefKind.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/Availability.h"
#include "llvm/Support/TrailingObjects.h"

namespace llvm {
  struct fltSemantics;
}

namespace swift {
  enum class AccessKind : unsigned char;
  class ArchetypeType;
  class ASTContext;
  class AvailabilitySpec;
  class Type;
  class ValueDecl;
  class Decl;
  class DeclRefExpr;
  class Pattern;
  class SubscriptDecl;
  class Stmt;
  class BraceStmt;
  class ASTWalker;
  class Initializer;
  class VarDecl;
  class OpaqueValueExpr;
  class FuncDecl;
  class ConstructorDecl;
  class TypeDecl;
  class PatternBindingDecl;
  class ParameterList;
  class EnumElementDecl;

enum class ExprKind : uint8_t {
#define EXPR(Id, Parent) Id,
#define EXPR_RANGE(Id, FirstId, LastId) \
  First_##Id##Expr = FirstId, Last_##Id##Expr = LastId,
#include "swift/AST/ExprNodes.def"
};
  
/// Discriminates the different kinds of checked cast supported.
///
/// This enumeration should not exist. Only the collection downcast kinds are
/// currently significant. Please don't add new kinds.
enum class CheckedCastKind : unsigned {
  /// The kind has not been determined yet.
  Unresolved,

  /// Valid resolved kinds start here.
  First_Resolved,

  /// The requested cast is an implicit conversion, so this is a coercion.
  Coercion = First_Resolved,
  /// A non-value-changing checked cast.
  ValueCast,
  // A downcast from an array type to another array type.
  ArrayDowncast,
  // A downcast from a dictionary type to another dictionary type.
  DictionaryDowncast,
  // A downcast from a set type to another set type.
  SetDowncast,
  /// A downcast from an object of class or Objective-C existential
  /// type to its bridged value type.
  BridgeFromObjectiveC,

  Last_CheckedCastKind = BridgeFromObjectiveC,
};

enum class AccessSemantics : unsigned char {
  /// On a property or subscript reference, this is a direct access to
  /// the underlying storage.  On a function reference, this is a
  /// non-polymorphic access to a particular implementation.
  DirectToStorage,

  /// On a property or subscript reference, this is a direct,
  /// non-polymorphic access to the getter/setter accessors.
  DirectToAccessor,
  
  /// On a property or subscript reference, this is an access to a property
  /// behavior that may be an initialization. Reads always go through the
  /// 'get' accessor on the property. Writes may go through the 'init' or
  /// 'set' logic of the behavior based on its initialization state.
  BehaviorInitialization,

  /// This is an ordinary access to a declaration, using whatever
  /// polymorphism is expected.
  Ordinary,
};

/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
  Expr(const Expr&) = delete;
  void operator=(const Expr&) = delete;

  class ExprBitfields {
    friend class Expr;
    /// The subclass of Expr that this is.
    unsigned Kind : 8;
    /// How this l-value is used, if it's an l-value.
    unsigned LValueAccessKind : 2;
    /// Whether the Expr represents something directly written in source or
    /// it was implicitly generated by the type-checker.
    unsigned Implicit : 1;
  };
  enum { NumExprBits = 11 };
  static_assert(NumExprBits <= 32, "fits in an unsigned");

  class LiteralExprBitfields {
    friend class LiteralExpr;
    unsigned : NumExprBits;
  };
  enum { NumLiteralExprBits = NumExprBits + 0 };
  static_assert(NumLiteralExprBits <= 32, "fits in an unsigned");

  class NumberLiteralExprBitfields {
    friend class NumberLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned IsNegative : 1;
  };
  enum { NumNumberLiteralExprBits = NumLiteralExprBits + 1 };
  static_assert(NumNumberLiteralExprBits <= 32, "fits in an unsigned");

  class StringLiteralExprBitfields {
    friend class StringLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned Encoding : 2;
    unsigned IsSingleUnicodeScalar : 1;
    unsigned IsSingleExtendedGraphemeCluster : 1;
  };
  enum { NumStringLiteralExprBits = NumLiteralExprBits + 4 };
  static_assert(NumStringLiteralExprBits <= 32, "fits in an unsigned");

  class DeclRefExprBitfields {
    friend class DeclRefExpr;
    unsigned : NumExprBits;
    unsigned Semantics : 2; // an AccessSemantics
    unsigned FunctionRefKind : 2;
  };
  enum { NumDeclRefExprBits = NumExprBits + 4 };
  static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");

  class UnresolvedDeclRefExprBitfields {
    friend class UnresolvedDeclRefExpr;
    unsigned : NumExprBits;
    unsigned DeclRefKind : 2;
    unsigned IsSpecialized : 1;
    unsigned FunctionRefKind : 2;
  };
  enum { NumUnresolvedDeclRefExprBits = NumExprBits + 5 };
  static_assert(NumUnresolvedDeclRefExprBits <= 32, "fits in an unsigned");

  class MemberRefExprBitfields {
    friend class MemberRefExpr;
    unsigned : NumExprBits;
    unsigned Semantics : 2; // an AccessSemantics
    unsigned IsSuper : 1;
  };
  enum { NumMemberRefExprBits = NumExprBits + 3 };
  static_assert(NumMemberRefExprBits <= 32, "fits in an unsigned");

  class TupleExprBitfields {
    friend class TupleExpr;
    unsigned : NumExprBits;

    /// Whether this tuple has a trailing closure.
    unsigned HasTrailingClosure : 1;

    /// Whether this tuple has any labels.
    unsigned HasElementNames : 1;

    /// Whether this tuple has label locations.
    unsigned HasElementNameLocations : 1;
  };
  enum { NumTupleExprBits = NumExprBits + 3 };
  static_assert(NumTupleExprBits <= 32, "fits in an unsigned");

  class UnresolvedDotExprBitfields {
    friend class UnresolvedDotExpr;
    unsigned : NumExprBits;
    unsigned FunctionRefKind : 2;
  };
  enum { NumUnresolvedDotExprExprBits = NumExprBits + 2 };
  static_assert(NumUnresolvedDotExprExprBits <= 32, "fits in an unsigned");

  class SubscriptExprBitfields {
    friend class SubscriptExpr;
    unsigned : NumExprBits;
    unsigned Semantics : 2; // an AccessSemantics
    unsigned IsSuper : 1;
    /// # of argument labels stored after the SubscriptExpr.
    unsigned NumArgLabels : 16;
    /// Whether the SubscriptExpr also has source locations for the argument
    /// label.
    unsigned HasArgLabelLocs : 1;
    /// Whether the last argument is a trailing closure.
    unsigned HasTrailingClosure : 1;
  };
  enum { NumSubscriptExprBits = NumExprBits + 21 };
  static_assert(NumSubscriptExprBits <= 32, "fits in an unsigned");

  class DynamicSubscriptExprBitfields {
    friend class DynamicSubscriptExpr;
    unsigned : NumExprBits;
    /// # of argument labels stored after the DynamicSubscriptExpr.
    unsigned NumArgLabels : 16;
    /// Whether the DynamicSubscriptExpr also has source locations for the
    /// argument label.
    unsigned HasArgLabelLocs : 1;
    /// Whether the last argument is a trailing closure.
    unsigned HasTrailingClosure : 1;
  };
  enum { NumDynamicSubscriptExprBits = NumExprBits + 18 };
  static_assert(NumDynamicSubscriptExprBits <= 32, "fits in an unsigned");

  class UnresolvedMemberExprBitfields {
    friend class UnresolvedMemberExpr;
    unsigned : NumExprBits;
    /// Whether the UnresolvedMemberExpr has arguments.
    unsigned HasArguments : 1;
    /// # of argument labels stored after the UnresolvedMemberExpr.
    unsigned NumArgLabels : 16;
    /// Whether the UnresolvedMemberExpr also has source locations for the
    /// argument label.
    unsigned HasArgLabelLocs : 1;
    /// Whether the last argument is a trailing closure.
    unsigned HasTrailingClosure : 1;
  };
  enum { NumUnresolvedMemberExprBits = NumExprBits + 19 };
  static_assert(NumUnresolvedMemberExprBits <= 32, "fits in an unsigned");

  class OverloadSetRefExprBitfields {
    friend class OverloadSetRefExpr;
    unsigned : NumExprBits;
    unsigned FunctionRefKind : 2;
  };
  enum { NumOverloadSetRefExprBits = NumExprBits + 2};
  static_assert(NumOverloadSetRefExprBits <= 32, "fits in an unsigned");

  class OverloadedDeclRefExprBitfields {
    friend class OverloadedDeclRefExpr;
    unsigned : NumOverloadSetRefExprBits;
    unsigned IsSpecialized : 1;
  };
  enum { NumOverloadedDeclRefExprBits = NumOverloadSetRefExprBits + 1 };
  static_assert(NumOverloadedDeclRefExprBits <= 32, "fits in an unsigned");

  class BooleanLiteralExprBitfields {
    friend class BooleanLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned Value : 1;
  };
  enum { NumBooleanLiteralExprBits = NumLiteralExprBits + 1 };
  static_assert(NumBooleanLiteralExprBits <= 32, "fits in an unsigned");

  class MagicIdentifierLiteralExprBitfields {
    friend class MagicIdentifierLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned Kind : 3;
    unsigned StringEncoding : 1;
  };
  enum { NumMagicIdentifierLiteralExprBits = NumLiteralExprBits + 4 };
  static_assert(NumMagicIdentifierLiteralExprBits <= 32, "fits in an unsigned");

  class ObjectLiteralExprBitfields {
    friend class ObjectLiteralExpr;
    unsigned : NumLiteralExprBits;

    unsigned LitKind : 3;
    /// # of argument labels stored after the ObjectLiteralExpr.
    unsigned NumArgLabels : 16;
    /// Whether the ObjectLiteralExpr also has source locations for the argument
    /// label.
    unsigned HasArgLabelLocs : 1;
    /// Whether the last argument is a trailing closure.
    unsigned HasTrailingClosure : 1;
  };
  enum { NumObjectLiteralExprBits = NumLiteralExprBits + 21 };
  static_assert(NumObjectLiteralExprBits <= 32, "fits in an unsigned");

  class AbstractClosureExprBitfields {
    friend class AbstractClosureExpr;
    unsigned : NumExprBits;
    unsigned Discriminator : 16;

    enum : unsigned {
      InvalidDiscriminator = 0xFFFF
    };
  };
  enum { NumAbstractClosureExprBits = NumExprBits + 16 };
  static_assert(NumAbstractClosureExprBits <= 32, "fits in an unsigned");

  class ClosureExprBitfields {
    friend class ClosureExpr;
    unsigned : NumAbstractClosureExprBits;

    /// True if closure parameters were synthesized from anonymous closure
    /// variables.
    unsigned HasAnonymousClosureVars : 1;
  };
  enum { NumClosureExprBits = NumAbstractClosureExprBits + 1 };
  static_assert(NumClosureExprBits <= 32, "fits in an unsigned");

  class BindOptionalExprBitfields {
    friend class BindOptionalExpr;
    unsigned : NumExprBits;
    unsigned Depth : 16;
  };
  enum { NumBindOptionalExprBits = NumExprBits + 16 };
  static_assert(NumBindOptionalExprBits <= 32, "fits in an unsigned");

  enum { NumImplicitConversionExprBits = NumExprBits };

  class TupleShuffleExprBitfields {
    friend class TupleShuffleExpr;
    unsigned : NumImplicitConversionExprBits;
    unsigned IsSourceScalar : 1;
  };
  enum { NumTupleShuffleExprBits = NumImplicitConversionExprBits + 1 };
  static_assert(NumTupleShuffleExprBits <= 32, "fits in an unsigned");

  class ApplyExprBitfields {
    friend class ApplyExpr;
    unsigned : NumExprBits;
    unsigned ThrowsIsSet : 1;
    unsigned Throws : 1;
  };
  enum { NumApplyExprBits = NumExprBits + 2 };
  static_assert(NumApplyExprBits <= 32, "fits in an unsigned");

  class CallExprBitfields {
    friend class CallExpr;
    unsigned : NumApplyExprBits;
    /// # of argument labels stored after the CallExpr.
    unsigned NumArgLabels : 16;
    /// Whether the CallExpr also has source locations for the argument label.
    unsigned HasArgLabelLocs : 1;
    /// Whether the last argument is a trailing closure.
    unsigned HasTrailingClosure : 1;
  };
  enum { NumCallExprBits = NumApplyExprBits + 18 };
  static_assert(NumCallExprBits <= 32, "fits in an unsigned");

  enum { NumCheckedCastKindBits = 4 };
  class CheckedCastExprBitfields {
    friend class CheckedCastExpr;
    unsigned : NumExprBits;
    unsigned CastKind : NumCheckedCastKindBits;
  };
  enum { NumCheckedCastExprBits = NumExprBits + NumCheckedCastKindBits };
  static_assert(NumCheckedCastExprBits <= 32, "fits in an unsigned");
  static_assert(unsigned(CheckedCastKind::Last_CheckedCastKind)
                  < (1 << NumCheckedCastKindBits),
                "unable to fit a CheckedCastKind in the given number of bits");

  class CollectionUpcastConversionExprBitfields {
    friend class CollectionUpcastConversionExpr;
    unsigned : NumExprBits;
  };
  enum { NumCollectionUpcastConversionExprBits = NumExprBits + 0 };
  static_assert(NumCollectionUpcastConversionExprBits <= 32, "fits in an unsigned");

  class ObjCSelectorExprBitfields {
    friend class ObjCSelectorExpr;
    unsigned : NumExprBits;

    /// The selector kind.
    unsigned SelectorKind : 2;
  };
  enum { NumObjCSelectorExprBits = NumExprBits + 2 };
  static_assert(NumObjCSelectorExprBits <= 32, "fits in an unsigned");

  class ObjCKeyPathExprBitfields {
    friend class ObjCKeyPathExpr;
    unsigned : NumExprBits;

    /// The number of components in the selector path.
    unsigned NumComponents : 8;

    /// Whether the names have corresponding source locations.
    unsigned HaveSourceLocations : 1;
  };
  enum { NumObjCKeyPathExprBits = NumExprBits + 9 };
  static_assert(NumObjCKeyPathExprBits <= 32, "fits in an unsigned");

protected:
  union {
    ExprBitfields ExprBits;
    LiteralExprBitfields LiteralExprBits;
    NumberLiteralExprBitfields NumberLiteralExprBits;
    StringLiteralExprBitfields StringLiteralExprBits;
    DeclRefExprBitfields DeclRefExprBits;
    UnresolvedDeclRefExprBitfields UnresolvedDeclRefExprBits;
    TupleExprBitfields TupleExprBits;
    MemberRefExprBitfields MemberRefExprBits;
    UnresolvedDotExprBitfields UnresolvedDotExprBits;
    SubscriptExprBitfields SubscriptExprBits;
    DynamicSubscriptExprBitfields DynamicSubscriptExprBits;
    UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
    OverloadSetRefExprBitfields OverloadSetRefExprBits;
    OverloadedDeclRefExprBitfields OverloadedDeclRefExprBits;
    BooleanLiteralExprBitfields BooleanLiteralExprBits;
    MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
    ObjectLiteralExprBitfields ObjectLiteralExprBits;
    AbstractClosureExprBitfields AbstractClosureExprBits;
    ClosureExprBitfields ClosureExprBits;
    BindOptionalExprBitfields BindOptionalExprBits;
    ApplyExprBitfields ApplyExprBits;
    CallExprBitfields CallExprBits;
    CheckedCastExprBitfields CheckedCastExprBits;
    CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
    TupleShuffleExprBitfields TupleShuffleExprBits;
    ObjCSelectorExprBitfields ObjCSelectorExprBits;
    ObjCKeyPathExprBitfields ObjCKeyPathExprBits;
  };

private:
  /// Ty - This is the type of the expression.
  Type Ty;

  void setLValueAccessKind(AccessKind accessKind) {
    ExprBits.LValueAccessKind = unsigned(accessKind) + 1;
  }
 
protected:
  Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
    ExprBits.Kind = unsigned(Kind);
    ExprBits.Implicit = Implicit;
    ExprBits.LValueAccessKind = 0;
  }

public:
  /// Return the kind of this expression.
  ExprKind getKind() const { return ExprKind(ExprBits.Kind); }

  /// \brief Retrieve the name of the given expression kind.
  ///
  /// This name should only be used for debugging dumps and other
  /// developer aids, and should never be part of a diagnostic or exposed
  /// to the user of the compiler in any way.
  static StringRef getKindName(ExprKind K);

  /// getType - Return the type of this expression.
  Type getType() const { return Ty; }

  /// setType - Sets the type of this expression.
  void setType(Type T) { Ty = T; }

  /// \brief Return the source range of the expression.
  SourceRange getSourceRange() const;
  
  /// getStartLoc - Return the location of the start of the expression.
  SourceLoc getStartLoc() const;

  /// \brief Retrieve the location of the last token of the expression.
  SourceLoc getEndLoc() const;
  
  /// getLoc - Return the caret location of this expression.
  SourceLoc getLoc() const;

#define SWIFT_FORWARD_SOURCE_LOCS_TO(SUBEXPR) \
  SourceLoc getStartLoc() const { return (SUBEXPR)->getStartLoc(); } \
  SourceLoc getEndLoc() const { return (SUBEXPR)->getEndLoc(); } \
  SourceLoc getLoc() const { return (SUBEXPR)->getLoc(); } \
  SourceRange getSourceRange() const { return (SUBEXPR)->getSourceRange(); }

  SourceLoc TrailingSemiLoc;

  /// getSemanticsProvidingExpr - Find the smallest subexpression
  /// which obeys the property that evaluating it is exactly
  /// equivalent to evaluating this expression.
  ///
  /// Looks through parentheses.  Would not look through something
  /// like '(foo(), x:bar(), baz()).x'.
  Expr *getSemanticsProvidingExpr();

  const Expr *getSemanticsProvidingExpr() const {
    return const_cast<Expr *>(this)->getSemanticsProvidingExpr();
  }

  /// getValueProvidingExpr - Find the smallest subexpression which is
  /// responsible for generating the value of this expression.
  /// Evaluating the result is not necessarily equivalent to
  /// evaluating this expression because of potential missing
  /// side-effects (which may influence the returned value).
  Expr *getValueProvidingExpr();

  const Expr *getValueProvidingExpr() const {
    return const_cast<Expr *>(this)->getValueProvidingExpr();
  }

  /// If this is a reference to an operator written as a member of a type (or
  /// extension thereof), return the underlying operator reference.
  DeclRefExpr *getMemberOperatorRef();

  /// This recursively walks the AST rooted at this expression.
  Expr *walk(ASTWalker &walker);
  Expr *walk(ASTWalker &&walker) { return walk(walker); }

  /// Enumerate each immediate child expression of this node, invoking the
  /// specific functor on it.  This ignores statements and other non-expression
  /// children.
  void forEachImmediateChildExpr(const std::function<Expr*(Expr*)> &callback);

  /// Enumerate each expr node within this expression subtree, invoking the
  /// specific functor on it.  This ignores statements and other non-expression
  /// children, and if there is a closure within the expression, this does not
  /// walk into the body of it (unless it is single-expression).
  void forEachChildExpr(const std::function<Expr*(Expr*)> &callback);

  /// Determine whether this expression refers to a type by name.
  ///
  /// This distinguishes static references to types, like Int, from metatype
  /// values, "someTy: Any.Type".
  bool isTypeReference() const;

  /// Determine whether this expression refers to a statically-derived metatype.
  ///
  /// This implies `isTypeReference`, but also requires that the referenced type
  /// is not an archetype or dependent type.
  bool isStaticallyDerivedMetatype() const;

  /// isImplicit - Determines whether this expression was implicitly-generated,
  /// rather than explicitly written in the AST.
  bool isImplicit() const {
    return ExprBits.Implicit;
  }
  void setImplicit(bool Implicit = true) {
    ExprBits.Implicit = Implicit;
  }

  /// getLValueAccessKind - Determines how this l-value expression is used.
  AccessKind getLValueAccessKind() const {
    assert(hasLValueAccessKind());
    return AccessKind(ExprBits.LValueAccessKind - 1);
  }
  bool hasLValueAccessKind() const {
    return ExprBits.LValueAccessKind != 0;
  }
  void clearLValueAccessKind() {
    ExprBits.LValueAccessKind = 0;
  }

  /// Set that this l-value expression is used in the given way.
  ///
  /// This information is also correctly propagated to any l-value
  /// sub-expressions from which this l-value is derived.
  ///
  /// \param allowOverwrite - true if it's okay if an expression already
  ///   has an access kind
  void propagateLValueAccessKind(AccessKind accessKind,
                                 std::function<Type(Expr *)> getType
                                   = [](Expr *E) -> Type {
                                     return E->getType();
                                 },
                                 bool allowOverwrite = false);

  /// Retrieves the declaration that is being referenced by this
  /// expression, if any.
  ConcreteDeclRef getReferencedDecl() const;

  /// Determine whether this expression is 'super', possibly converted to
  /// a base class.
  bool isSuperExpr() const;

  /// Returns true if directly appending a parameter list would be syntactically
  /// valid.
  ///
  /// Good examples: foo.bar, baz().
  /// Bad examples: 
  bool canAppendCallParentheses() const;

  /// Returns true if this is an infix operator of some sort, including
  /// a builtin operator.
  bool isInfixOperator() const;

  /// Produce a mapping from each subexpression to its parent
  /// expression, with the provided expression serving as the root of
  /// the parent map.
  llvm::DenseMap<Expr *, Expr *> getParentMap();

  /// Produce a mapping from each subexpression to its depth in the root
  /// expression. The root expression has depth 0, its children have depth
  /// 1, etc.
  llvm::DenseMap<Expr *, unsigned> getDepthMap();

  /// Produce a mapping from each expression to its index according to a
  /// preorder traversal of the expressions. The parent has index 0, its first
  /// child has index 1, its second child has index 2 if the first child is a
  /// leaf node, etc.
  llvm::DenseMap<Expr *, unsigned> getPreorderIndexMap();

  LLVM_ATTRIBUTE_DEPRECATED(
      void dump() const LLVM_ATTRIBUTE_USED,
      "only for use within the debugger");
  void dump(raw_ostream &OS) const;
  void print(raw_ostream &OS, unsigned Indent = 0) const;
  void print(ASTPrinter &Printer, const PrintOptions &Opts) const;

  // Only allow allocation of Exprs using the allocator in ASTContext
  // or by doing a placement new.
  void *operator new(size_t Bytes, ASTContext &C,
                     unsigned Alignment = alignof(Expr));

  // Make placement new and vanilla new/delete illegal for Exprs.
  void *operator new(size_t Bytes) throw() = delete;
  void operator delete(void *Data) throw() = delete;

  void *operator new(size_t Bytes, void *Mem) { 
    assert(Mem); 
    return Mem; 
  }
};

/// Helper class to capture trailing call argument labels and related
/// information, for expression nodes that involve argument labels, trailing
/// closures, etc.
template<typename Derived>
class TrailingCallArguments
    : private llvm::TrailingObjects<Derived, Identifier, SourceLoc> {
  using TrailingObjects = llvm::TrailingObjects<Derived, Identifier, SourceLoc>;
  friend TrailingObjects;

  Derived &asDerived() {
    return *static_cast<Derived *>(this);
  }

  const Derived &asDerived() const {
    return *static_cast<const Derived *>(this);
  }

  size_t numTrailingObjects(
      typename TrailingObjects::template OverloadToken<Identifier>) const {
    return asDerived().getNumArguments();
  }

  size_t numTrailingObjects(
      typename TrailingObjects::template OverloadToken<SourceLoc>) const {
    return asDerived().hasArgumentLabelLocs()
             ? asDerived().getNumArguments()
             : 0;
  }

  /// Retrieve the buffer containing the argument labels.
  MutableArrayRef<Identifier> getArgumentLabelsBuffer() {
    return { this->template getTrailingObjects<Identifier>(),
             asDerived().getNumArguments() };
  }

  /// Retrieve the buffer containing the argument label locations.
  MutableArrayRef<SourceLoc> getArgumentLabelLocsBuffer() {
    if (!asDerived().hasArgumentLabelLocs())
      return { };
    
    return { this->template getTrailingObjects<SourceLoc>(),
             asDerived().getNumArguments() };
  }

protected:
  /// Determine the total size to allocate.
  static size_t totalSizeToAlloc(ArrayRef<Identifier> argLabels,
                                 ArrayRef<SourceLoc> argLabelLocs,
                                 bool hasTrailingClosure) {
    return TrailingObjects::template totalSizeToAlloc<Identifier, SourceLoc>(
        argLabels.size(), argLabelLocs.size());
  }

  /// Initialize the actual call arguments.
  void initializeCallArguments(ArrayRef<Identifier> argLabels,
                               ArrayRef<SourceLoc> argLabelLocs,
                               bool hasTrailingClosure) {
    if (!argLabels.empty()) {
      std::uninitialized_copy(argLabels.begin(), argLabels.end(),
                              this->template getTrailingObjects<Identifier>());
    }
    
    if (!argLabelLocs.empty())
      std::uninitialized_copy(argLabelLocs.begin(), argLabelLocs.end(),
                              this->template getTrailingObjects<SourceLoc>());
  }

public:
  /// Retrieve the argument labels provided at the call site.
  ArrayRef<Identifier> getArgumentLabels() const {
    return { this->template getTrailingObjects<Identifier>(),
             asDerived().getNumArguments() };
  }

  /// Retrieve the buffer containing the argument label locations.
  ArrayRef<SourceLoc> getArgumentLabelLocs() const {
    if (!asDerived().hasArgumentLabelLocs())
      return { };
    
    return { this->template getTrailingObjects<SourceLoc>(),
             asDerived().getNumArguments() };
  }

  /// Retrieve the location of the ith argument label.
  SourceLoc getArgumentLabelLoc(unsigned i) const {
    auto locs = getArgumentLabelLocs();
    return i < locs.size() ? locs[i] : SourceLoc();
  }
};

/// ErrorExpr - Represents a semantically erroneous subexpression in the AST,
/// typically this will have an ErrorType.
class ErrorExpr : public Expr {
  SourceRange Range;
public:
  ErrorExpr(SourceRange Range, Type Ty = Type())
    : Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {}

  SourceRange getSourceRange() const { return Range; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Error;
  }
};

/// CodeCompletionExpr - Represents the code completion token in the AST, this
/// can help us preserve the context of the code completion position.
class CodeCompletionExpr : public Expr {
  SourceRange Range;
public:
  CodeCompletionExpr(SourceRange Range, Type Ty = Type()) :
      Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Ty),
      Range(Range) {}

  SourceRange getSourceRange() const { return Range; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CodeCompletion;
  }
};

/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
  LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
  
  // Make an exact copy of this one AST node.
  LiteralExpr *shallowClone(ASTContext &Ctx) const;
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_LiteralExpr &&
           E->getKind() <= ExprKind::Last_LiteralExpr;
  }
};

/// \brief The 'nil' literal.
///
class NilLiteralExpr : public LiteralExpr {
  SourceLoc Loc;
public:
  NilLiteralExpr(SourceLoc Loc, bool Implicit = false)
  : LiteralExpr(ExprKind::NilLiteral, Implicit), Loc(Loc) {
  }
  
  SourceRange getSourceRange() const {
    return Loc;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::NilLiteral;
  }
};

/// \brief Abstract base class for numeric literals, potentially with a sign.
class NumberLiteralExpr : public LiteralExpr {
  /// The value of the literal as an ASTContext-owned string. Underscores must
  /// be stripped.
  StringRef Val;  // Use StringRef instead of APInt or APFloat, which leak.
  
protected:
  SourceLoc MinusLoc;
  SourceLoc DigitsLoc;
  
public:
   NumberLiteralExpr(ExprKind Kind,
                     StringRef Val, SourceLoc DigitsLoc, bool Implicit)
       : LiteralExpr(Kind, Implicit), Val(Val), DigitsLoc(DigitsLoc)
   {
     NumberLiteralExprBits.IsNegative = false;
   }
  
  bool isNegative() const { return NumberLiteralExprBits.IsNegative; }
  void setNegative(SourceLoc Loc) {
    MinusLoc = Loc;
    NumberLiteralExprBits.IsNegative = true;
  }

  StringRef getDigitsText() const { return Val; }

  SourceRange getSourceRange() const {
    if (isNegative())
      return { MinusLoc, DigitsLoc };
    else
      return DigitsLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_NumberLiteralExpr
      && E->getKind() <= ExprKind::Last_NumberLiteralExpr;
  }
};

  
/// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to only have
/// a BuiltinIntegerType.
class IntegerLiteralExpr : public NumberLiteralExpr {
public:
  IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false)
      : NumberLiteralExpr(ExprKind::IntegerLiteral,
                          Val, DigitsLoc, Implicit)
  {}

  APInt getValue() const;
  static APInt getValue(StringRef Text, unsigned BitWidth);

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::IntegerLiteral;
  }
};

/// FloatLiteralExpr - Floating point literal, like '4.0'.  After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public NumberLiteralExpr {
public:
  FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit = false)
    : NumberLiteralExpr(ExprKind::FloatLiteral, Val, Loc, Implicit)
  {}
  
  APFloat getValue() const;
  static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::FloatLiteral;
  }
};

/// \brief A Boolean literal ('true' or 'false')
///
class BooleanLiteralExpr : public LiteralExpr {
  SourceLoc Loc;

public:
  BooleanLiteralExpr(bool Value, SourceLoc Loc, bool Implicit = false)
    : LiteralExpr(ExprKind::BooleanLiteral, Implicit), Loc(Loc) {
    BooleanLiteralExprBits.Value = Value;
  }

  /// Retrieve the Boolean value of this literal.
  bool getValue() const { return BooleanLiteralExprBits.Value; }

  SourceRange getSourceRange() const {
    return Loc;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::BooleanLiteral;
  }
};
  
/// StringLiteralExpr - String literal, like '"foo"'.
class StringLiteralExpr : public LiteralExpr {
  StringRef Val;
  SourceRange Range;
  ConcreteDeclRef BuiltinInitializer;
  ConcreteDeclRef Initializer;

public:
  /// The encoding that should be used for the string literal.
  enum Encoding : unsigned {
    /// A UTF-8 string.
    UTF8,

    /// A UTF-16 string.
    UTF16,

    /// A single UnicodeScalar, passed as an integer.
    OneUnicodeScalar
  };

  StringLiteralExpr(StringRef Val, SourceRange Range, bool Implicit = false);

  StringRef getValue() const { return Val; }
  SourceRange getSourceRange() const { return Range; }

  /// Determine the encoding that should be used for this string literal.
  Encoding getEncoding() const {
    return static_cast<Encoding>(StringLiteralExprBits.Encoding);
  }

  /// Set the encoding that should be used for this string literal.
  void setEncoding(Encoding encoding) {
    StringLiteralExprBits.Encoding = static_cast<unsigned>(encoding);
  }

  bool isSingleUnicodeScalar() const {
    return StringLiteralExprBits.IsSingleUnicodeScalar;
  }

  bool isSingleExtendedGraphemeCluster() const {
    return StringLiteralExprBits.IsSingleExtendedGraphemeCluster;
  }

  /// Retrieve the builtin initializer that will be used to construct the string
  /// literal.
  ///
  /// Any type-checked string literal will have a builtin initializer, which is
  /// called first to form a concrete Swift type.
  ConcreteDeclRef getBuiltinInitializer() const { return BuiltinInitializer; }

  /// Set the builtin initializer that will be used to construct the string
  /// literal.
  void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
    BuiltinInitializer = builtinInitializer;
  }

  /// Retrieve the initializer that will be used to construct the string
  /// literal from the result of the initializer.
  ///
  /// Only string literals that have no builtin literal conformance will have
  /// this initializer, which will be called on the result of the builtin
  /// initializer.
  ConcreteDeclRef getInitializer() const { return Initializer; }

  /// Set the initializer that will be used to construct the string literal.
  void setInitializer(ConcreteDeclRef initializer) {
    Initializer = initializer;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::StringLiteral;
  }
};

/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
  /// Points at the beginning quote.
  SourceLoc Loc;
  MutableArrayRef<Expr *> Segments;
  Expr *SemanticExpr;
  
public:
  InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments)
    : LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
      Loc(Loc), Segments(Segments), SemanticExpr() { }
  
  MutableArrayRef<Expr *> getSegments() { return Segments; }
  ArrayRef<Expr *> getSegments() const { return Segments; }
  
  /// \brief Retrieve the expression that actually evaluates the resulting
  /// string, typically with a series of '+' operations.
  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
  
  SourceLoc getStartLoc() const {
    return Loc;
  }
  SourceLoc getEndLoc() const {
    // SourceLocs are token based, and the interpolated string is one string
    // token, so the range should be (Start == End).
    return Loc;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InterpolatedStringLiteral;
  }
};
  
/// MagicIdentifierLiteralExpr - A magic identifier like #file which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public LiteralExpr {
public:
  enum Kind : unsigned {
    File, Line, Column, Function, DSOHandle
  };
private:
  SourceLoc Loc;
  ConcreteDeclRef BuiltinInitializer;
  ConcreteDeclRef Initializer;

public:
  MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit = false)
    : LiteralExpr(ExprKind::MagicIdentifierLiteral, implicit), Loc(loc) {
    MagicIdentifierLiteralExprBits.Kind = static_cast<unsigned>(kind);
    MagicIdentifierLiteralExprBits.StringEncoding
      = static_cast<unsigned>(StringLiteralExpr::UTF8);
  }
  
  Kind getKind() const {
    return static_cast<Kind>(MagicIdentifierLiteralExprBits.Kind);
  }

  bool isFile() const { return getKind() == File; }
  bool isFunction() const { return getKind() == Function; }
  bool isLine() const { return getKind() == Line; }
  bool isColumn() const { return getKind() == Column; }
  
  bool isString() const {
    switch (getKind()) {
    case File:
    case Function:
      return true;
    case Line:
    case Column:
    case DSOHandle:
      return false;
    }
    llvm_unreachable("bad Kind");
  }

  bool isDSOHandle() const {
    return getKind() == DSOHandle;
  }

  SourceRange getSourceRange() const { return Loc; }

  // For a magic identifier that produces a string literal, retrieve the
  // encoding for that string literal.
  StringLiteralExpr::Encoding getStringEncoding() const {
    assert(isString() && "Magic identifier literal has non-string encoding");
    return static_cast<StringLiteralExpr::Encoding>(
             MagicIdentifierLiteralExprBits.StringEncoding);
  }

  // For a magic identifier that produces a string literal, set the encoding
  // for the string literal.
  void setStringEncoding(StringLiteralExpr::Encoding encoding) {
    assert(isString() && "Magic identifier literal has non-string encoding");
    MagicIdentifierLiteralExprBits.StringEncoding
      = static_cast<unsigned>(encoding);
  }

  /// Retrieve the builtin initializer that will be used to construct the string
  /// literal.
  ///
  /// Any type-checked string literal will have a builtin initializer, which is
  /// called first to form a concrete Swift type.
  ConcreteDeclRef getBuiltinInitializer() const {
    assert(isString() && "Magic identifier literal is not a string");
    return BuiltinInitializer;
  }

  /// Set the builtin initializer that will be used to construct the string
  /// literal.
  void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
    assert(isString() && "Magic identifier literal is not a string");
    BuiltinInitializer = builtinInitializer;
  }

  /// Retrieve the initializer that will be used to construct the string
  /// literal from the result of the initializer.
  ///
  /// Only string literals that have no builtin literal conformance will have
  /// this initializer, which will be called on the result of the builtin
  /// initializer.
  ConcreteDeclRef getInitializer() const {
    assert(isString() && "Magic identifier literal is not a string");
    return Initializer;
  }

  /// Set the initializer that will be used to construct the string literal.
  void setInitializer(ConcreteDeclRef initializer) {
    assert(isString() && "Magic identifier literal is not a string");
    Initializer = initializer;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MagicIdentifierLiteral;
  }
};

// ObjectLiteralExpr - An expression of the form
// '#colorLiteral(red: 1, blue: 0, green: 0, alpha: 1)' with a name and a list
// argument. The components of the list argument are meant to be themselves
// constant.
class ObjectLiteralExpr final
    : public LiteralExpr,
      public TrailingCallArguments<ObjectLiteralExpr> {
public:
  /// The kind of object literal.
  enum LiteralKind : unsigned {
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) Name,
#include "swift/Parse/Tokens.def"    
  };

private:
  Expr *Arg;
  Expr *SemanticExpr;
  SourceLoc PoundLoc;

  ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind,
                    Expr *Arg,
                    ArrayRef<Identifier> argLabels,
                    ArrayRef<SourceLoc> argLabelLocs,
                    bool hasTrailingClosure,
                    bool implicit);

public:
  /// Create a new object literal expression.
  ///
  /// Note: prefer to use the second entry point, which separates out
  /// arguments/labels/etc.
  static ObjectLiteralExpr *create(ASTContext &ctx, SourceLoc poundLoc,
                                   LiteralKind kind, Expr *arg, bool implicit);

  /// Create a new object literal expression.
  static ObjectLiteralExpr *create(ASTContext &ctx, SourceLoc poundLoc,
                                   LiteralKind kind,
                                   SourceLoc lParenLoc,
                                   ArrayRef<Expr *> args,
                                   ArrayRef<Identifier> argLabels,
                                   ArrayRef<SourceLoc> argLabelLocs,
                                   SourceLoc rParenLoc,
                                   Expr *trailingClosure,
                                   bool implicit);

  LiteralKind getLiteralKind() const {
    return static_cast<LiteralKind>(ObjectLiteralExprBits.LitKind);
  }

  Expr *getArg() const { return Arg; }
  void setArg(Expr *arg) { Arg = arg; }

  unsigned getNumArguments() const {
    return ObjectLiteralExprBits.NumArgLabels;
  }
  bool hasArgumentLabelLocs() const {
    return ObjectLiteralExprBits.HasArgLabelLocs;
  }

  /// Whether this call with written with a trailing closure.
  bool hasTrailingClosure() const {
    return ObjectLiteralExprBits.HasTrailingClosure;
  }

  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *expr) { SemanticExpr = expr; }

  SourceLoc getSourceLoc() const { return PoundLoc; }
  SourceRange getSourceRange() const { 
    return SourceRange(PoundLoc, Arg->getEndLoc());
  }

  /// Return the string form of the literal name.
  StringRef getLiteralKindRawName() const;

  StringRef getLiteralKindPlainName() const;

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ObjectLiteral;
  }
};

/// DiscardAssignmentExpr - A '_' in the left-hand side of an assignment, which
/// discards the corresponding tuple element on the right-hand side.
class DiscardAssignmentExpr : public Expr {
  SourceLoc Loc;

public:
  DiscardAssignmentExpr(SourceLoc Loc, bool Implicit)
    : Expr(ExprKind::DiscardAssignment, Implicit), Loc(Loc) {}
  
  SourceRange getSourceRange() const { return Loc; }
  SourceLoc getLoc() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DiscardAssignment;
  }
};

/// DeclRefExpr - A reference to a value, "x".
class DeclRefExpr : public Expr {
  /// This is used when the reference is specialized, e.g "GenCls<Int>", to
  /// hold information about the generic arguments.
  struct SpecializeInfo {
    ConcreteDeclRef D;
    ArrayRef<TypeRepr*> GenericArgs;
  };

  /// \brief The declaration pointer or SpecializeInfo pointer if it was
  /// explicitly specialized with <...>.
  llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
  DeclNameLoc Loc;

  SpecializeInfo *getSpecInfo() const {
    return DOrSpecialized.dyn_cast<SpecializeInfo*>();
  }

public:
  DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit,
              AccessSemantics semantics = AccessSemantics::Ordinary,
              Type Ty = Type())
    : Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
    DeclRefExprBits.Semantics = (unsigned) semantics;
    DeclRefExprBits.FunctionRefKind =
      static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
                                             : FunctionRefKind::Unapplied);
  }

  /// Retrieve the declaration to which this expression refers.
  ValueDecl *getDecl() const {
    return getDeclRef().getDecl();
  }

  /// Return true if this access is direct, meaning that it does not call the
  /// getter or setter.
  AccessSemantics getAccessSemantics() const {
    return (AccessSemantics) DeclRefExprBits.Semantics;
  }

  /// Retrieve the concrete declaration reference.
  ConcreteDeclRef getDeclRef() const {
    if (auto Spec = getSpecInfo())
      return Spec->D;
    return DOrSpecialized.get<ConcreteDeclRef>();
  }

  void setSpecialized();

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return getSpecInfo() != nullptr; }

  /// Set the generic arguments.
  ///
  /// This copies the array using ASTContext's allocator.
  void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);

  /// Returns the generic arguments if it was specialized or an empty array
  /// otherwise.
  ArrayRef<TypeRepr *> getGenericArgs() const {
    if (auto Spec = getSpecInfo())
      return Spec->GenericArgs;
    return ArrayRef<TypeRepr *>();
  }
  SourceRange getSourceRange() const { return Loc.getSourceRange(); }
  SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
  DeclNameLoc getNameLoc() const { return Loc; }

  /// Retrieve the kind of function reference.
  FunctionRefKind getFunctionRefKind() const {
    return static_cast<FunctionRefKind>(DeclRefExprBits.FunctionRefKind);
  }

  /// Set the kind of function reference.
  void setFunctionRefKind(FunctionRefKind refKind) {
    DeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DeclRef;
  }
};
  
/// A reference to 'super'. References to members of 'super' resolve to members
/// of a superclass of 'self'.
class SuperRefExpr : public Expr {
  VarDecl *Self;
  SourceLoc Loc;
  
public:
  SuperRefExpr(VarDecl *Self, SourceLoc Loc, bool Implicit,
               Type SuperTy = Type())
    : Expr(ExprKind::SuperRef, Implicit, SuperTy), Self(Self), Loc(Loc) {}
  
  VarDecl *getSelf() const { return Self; }
  
  SourceLoc getSuperLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::SuperRef;
  }
};

/// A reference to a type in expression context, spelled out as a TypeLoc. Sema
/// forms this expression as a result of name binding.  This always has
/// MetaTypetype.
class TypeExpr : public Expr {
  TypeLoc Info;
  TypeExpr(Type Ty);
public:
  // Create a TypeExpr with location information.
  TypeExpr(TypeLoc Ty);

  // The type of a TypeExpr is always a metatype type.  Return the instance
  // type, ErrorType if an error, or null if not set yet.
  Type getInstanceType() const;
  
  // Create an implicit TypeExpr, which has no location information.
  static TypeExpr *createImplicit(Type Ty, ASTContext &C) {
    return new (C) TypeExpr(Ty);
  }

  // Create an implicit TypeExpr, with location information even though it
  // shouldn't have one.  This is presently used to work around other location
  // processing bugs.  If you have an implicit location, use createImplicit.
  static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C);

  
  /// Return a TypeExpr for a TypeDecl and the specified location.
  static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D,
                                 bool isImplicit);
  static TypeExpr *createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
                                            ArrayRef<TypeRepr*> args,
                                            SourceRange angleLocs);
  TypeLoc &getTypeLoc() { return Info; }
  TypeLoc getTypeLoc() const { return Info; }
  TypeRepr *getTypeRepr() const { return Info.getTypeRepr(); }
  // NOTE: TypeExpr::getType() returns the type of the expr node, which is the
  // metatype of what is stored as an operand type.
  
  SourceRange getSourceRange() const { return Info.getSourceRange(); }
  // TODO: optimize getStartLoc() and getEndLoc() when TypeLoc allows it.

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Type;
  }
};
  
  

/// A reference to another initializer from within a constructor body,
/// either to a delegating initializer or to a super.init invocation.
/// For a reference type, this semantically references a different constructor
/// entry point, called the 'initializing constructor', from the 'allocating
/// constructor' entry point referenced by a 'new' expression.
class OtherConstructorDeclRefExpr : public Expr {
  ConcreteDeclRef Ctor;
  DeclNameLoc Loc;
  
public:
  OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, DeclNameLoc Loc,
                              bool Implicit, Type Ty = {})
    : Expr(ExprKind::OtherConstructorDeclRef, Implicit, Ty),
      Ctor(Ctor), Loc(Loc)
  {}
  
  ConstructorDecl *getDecl() const;
  ConcreteDeclRef getDeclRef() const { return Ctor; }

  SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
  DeclNameLoc getConstructorLoc() const { return Loc; }
  SourceRange getSourceRange() const { return Loc.getSourceRange(); }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OtherConstructorDeclRef;
  }
};

/// OverloadSetRefExpr - A reference to an overloaded set of values with a
/// single name.
///
/// This is an abstract class that covers the various different kinds of
/// overload sets.
class OverloadSetRefExpr : public Expr {
  ArrayRef<ValueDecl*> Decls;

protected:
  OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls,
                     FunctionRefKind functionRefKind, bool Implicit, Type Ty)
      : Expr(Kind, Implicit, Ty), Decls(decls) {
    OverloadSetRefExprBits.FunctionRefKind =
      static_cast<unsigned>(functionRefKind);
  }

public:
  ArrayRef<ValueDecl*> getDecls() const { return Decls; }

  void setDecls(ArrayRef<ValueDecl *> domain) {
    Decls = domain;
  }

  /// getBaseType - Determine the type of the base object provided for the
  /// given overload set, which is only non-null when dealing with an overloaded
  /// member reference.
  Type getBaseType() const;

  /// hasBaseObject - Determine whether this overloaded expression has a
  /// concrete base object (which is not a metatype).
  bool hasBaseObject() const;

  /// Retrieve the kind of function reference.
  FunctionRefKind getFunctionRefKind() const {
    return static_cast<FunctionRefKind>(
             OverloadSetRefExprBits.FunctionRefKind);
  }

  /// Set the kind of function reference.
  void setFunctionRefKind(FunctionRefKind refKind) {
    OverloadSetRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
  }

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_OverloadSetRefExpr &&
           E->getKind() <= ExprKind::Last_OverloadSetRefExpr;
  }
};

/// OverloadedDeclRefExpr - A reference to an overloaded name that should
/// eventually be resolved (by overload resolution) to a value reference.
class OverloadedDeclRefExpr final : public OverloadSetRefExpr {
  DeclNameLoc Loc;

public:
  OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc,
                        bool isSpecialized,
                        FunctionRefKind functionRefKind,
                        bool Implicit, Type Ty = Type())
      : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, functionRefKind,
                           Implicit, Ty),
        Loc(Loc) {
    OverloadedDeclRefExprBits.IsSpecialized = isSpecialized;
  }
  
  DeclNameLoc getNameLoc() const { return Loc; }
  SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
  SourceRange getSourceRange() const { return Loc.getSourceRange(); }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const {
    return OverloadedDeclRefExprBits.IsSpecialized;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OverloadedDeclRef;
  }
};

/// UnresolvedDeclRefExpr - This represents use of an undeclared identifier,
/// which may ultimately be a use of something that hasn't been defined yet, it
/// may be a use of something that got imported (which will be resolved during
/// sema), or may just be a use of an unknown identifier.
///
class UnresolvedDeclRefExpr : public Expr {
  DeclName Name;
  DeclNameLoc Loc;

public:
  UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, DeclNameLoc loc)
      : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
        Name(name), Loc(loc) {
    UnresolvedDeclRefExprBits.DeclRefKind = static_cast<unsigned>(refKind);
    UnresolvedDeclRefExprBits.IsSpecialized = false;
    UnresolvedDeclRefExprBits.FunctionRefKind =
      static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
                                             : FunctionRefKind::Unapplied);
  }
  
  bool hasName() const { return static_cast<bool>(Name); }
  DeclName getName() const { return Name; }

  DeclRefKind getRefKind() const {
    return static_cast<DeclRefKind>(UnresolvedDeclRefExprBits.DeclRefKind);
  }

  void setSpecialized(bool specialized) {
    UnresolvedDeclRefExprBits.IsSpecialized = specialized;
  }

  /// \brief Determine whether this declaration reference was immediately
  /// specialized by <...>.
  bool isSpecialized() const { return UnresolvedDeclRefExprBits.IsSpecialized; }

  /// Retrieve the kind of function reference.
  FunctionRefKind getFunctionRefKind() const {
    return static_cast<FunctionRefKind>(
             UnresolvedDeclRefExprBits.FunctionRefKind);
  }

  /// Set the kind of function reference.
  void setFunctionRefKind(FunctionRefKind refKind) {
    UnresolvedDeclRefExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
  }

  DeclNameLoc getNameLoc() const { return Loc; }

  SourceRange getSourceRange() const { return Loc.getSourceRange(); }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedDeclRef;
  }
};
  
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  DeclNameLoc NameLoc;
  
public:
  MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
                DeclNameLoc loc, bool Implicit,
                AccessSemantics semantics = AccessSemantics::Ordinary);
  Expr *getBase() const { return Base; }
  ConcreteDeclRef getMember() const { return Member; }
  DeclNameLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  
  void setBase(Expr *E) { Base = E; }
  
  /// Return true if this member access is direct, meaning that it
  /// does not call the getter or setter.
  AccessSemantics getAccessSemantics() const {
    return (AccessSemantics) MemberRefExprBits.Semantics;
  }

  /// Determine whether this member reference refers to the
  /// superclass's property.
  bool isSuper() const { return MemberRefExprBits.IsSuper; }

  /// Set whether this member reference refers to the superclass's
  /// property.
  void setIsSuper(bool isSuper) { MemberRefExprBits.IsSuper = isSuper; }

  SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
  SourceLoc getStartLoc() const {
    SourceLoc BaseStartLoc = Base->getStartLoc();
    if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
      return NameLoc.getBaseNameLoc();
    } else {
      return BaseStartLoc;
    }
  }
  SourceLoc getEndLoc() const {
    return NameLoc.getSourceRange().End;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MemberRef;
  }
};
  
/// Common base for expressions that involve dynamic lookup, which
/// determines at runtime whether a particular method, property, or
/// subscript is available.
class DynamicLookupExpr : public Expr {
protected:
  explicit DynamicLookupExpr(ExprKind kind) : Expr(kind, /*Implicit=*/false) { }

public:
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_DynamicLookupExpr &&
           E->getKind() <= ExprKind::Last_DynamicLookupExpr;
  }
};

/// A reference to a member of an object that was found via dynamic lookup.
///
/// A member found via dynamic lookup may not actually be available at runtime.
/// Therefore, a reference to that member always returns an optional instance.
/// Users can then propagate the optional (via ?) or assert that the member is
/// always available (via !). For example:
///
/// \code
/// class C {
///   func @objc foo(i : Int) -> String { ... }
/// };
///
/// var x : AnyObject = <some value>
/// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)?
/// \endcode
class DynamicMemberRefExpr : public DynamicLookupExpr {
  Expr *Base;
  ConcreteDeclRef Member;
  SourceLoc DotLoc;
  DeclNameLoc NameLoc;

public:
  DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
                       ConcreteDeclRef member,
                       DeclNameLoc nameLoc)
    : DynamicLookupExpr(ExprKind::DynamicMemberRef),
      Base(base), Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
    }

  /// Retrieve the base of the expression.
  Expr *getBase() const { return Base; }

  /// Replace the base of the expression.
  void setBase(Expr *base) { Base = base; }

  /// Retrieve the member to which this access refers.
  ConcreteDeclRef getMember() const { return Member; }

  /// Retrieve the location of the member name.
  DeclNameLoc getNameLoc() const { return NameLoc; }

  /// Retrieve the location of the '.'.
  SourceLoc getDotLoc() const { return DotLoc; }

  SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

  SourceLoc getStartLoc() const {
    SourceLoc BaseStartLoc = Base->getStartLoc();
    if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
      return NameLoc.getBaseNameLoc();
    } else {
      return BaseStartLoc;
    }
  }
  SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DynamicMemberRef;
  }
};

/// A subscript on an object with dynamic lookup type.
///
/// A subscript found via dynamic lookup may not actually be available
/// at runtime.  Therefore, the result of performing the subscript
/// operation always returns an optional instance.Users can then
/// propagate the optional (via ?) or assert that the member is always
/// available (via !). For example:
///
/// \code
/// class C {
///   @objc subscript (i : Int) -> String {
///     get {
///       ...
///     }
///   }
/// };
///
/// var x : AnyObject = <some value>
/// print(x[27]! // x[27] has type String?
/// \endcode
class DynamicSubscriptExpr final
    : public DynamicLookupExpr,
      public TrailingCallArguments<DynamicSubscriptExpr> {
  friend TrailingCallArguments;

  Expr *Base;
  Expr *Index;
  ConcreteDeclRef Member;

  DynamicSubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels,
                       ArrayRef<SourceLoc> argLabelLocs,
                       bool hasTrailingClosure, ConcreteDeclRef member,
                       bool implicit);

public:
  /// Create a dynamic subscript.
  ///
  /// Note: do not create new callers to this entry point; use the entry point
  /// that takes separate index arguments.
  static DynamicSubscriptExpr *create(ASTContext &ctx, Expr *base, Expr *index,
                                      ConcreteDeclRef decl,
                                      bool implicit);

  /// Create a new dynamic subscript.
  static DynamicSubscriptExpr *create(ASTContext &ctx, Expr *base,
                                      SourceLoc lSquareLoc,
                                      ArrayRef<Expr *> indexArgs,
                                      ArrayRef<Identifier> indexArgLabels,
                                      ArrayRef<SourceLoc> indexArgLabelLocs,
                                      SourceLoc rSquareLoc,
                                      Expr *trailingClosure,
                                      ConcreteDeclRef decl,
                                      bool implicit);

  /// Retrieve the base of the expression.
  Expr *getBase() const { return Base; }

  /// Replace the base of the expression.
  void setBase(Expr *base) { Base = base; }

  /// getIndex - Retrieve the index of the subscript expression, i.e., the
  /// "offset" into the base value.
  Expr *getIndex() const { return Index; }
  void setIndex(Expr *E) { Index = E; }

  unsigned getNumArguments() const {
    return DynamicSubscriptExprBits.NumArgLabels;
  }

  bool hasArgumentLabelLocs() const {
    return DynamicSubscriptExprBits.HasArgLabelLocs;
  }

  /// Whether this call with written with a trailing closure.
  bool hasTrailingClosure() const {
    return DynamicSubscriptExprBits.HasTrailingClosure;
  }

  /// Retrieve the member to which this access refers.
  ConcreteDeclRef getMember() const { return Member; }

  SourceLoc getLoc() const { return Index->getStartLoc(); }

  SourceLoc getStartLoc() const { return Base->getStartLoc(); }
  SourceLoc getEndLoc() const { return Index->getEndLoc(); }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DynamicSubscript;
  }
};

/// UnresolvedMemberExpr - This represents '.foo', an unresolved reference to a
/// member, which is to be resolved with context sensitive type information into
/// bar.foo.  These always have unresolved type.
class UnresolvedMemberExpr final
    : public Expr,
      public TrailingCallArguments<UnresolvedMemberExpr> {
  SourceLoc DotLoc;
  DeclNameLoc NameLoc;
  DeclName Name;
  Expr *Argument;

  UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc,
                       DeclName name, Expr *argument,
                       ArrayRef<Identifier> argLabels,
                       ArrayRef<SourceLoc> argLabelLocs,
                       bool hasTrailingClosure,
                       bool implicit);

public:
  /// Create a new unresolved member expression with no arguments.
  static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc,
                                      DeclNameLoc nameLoc, DeclName name,
                                      bool implicit);

  /// Create a new unresolved member expression.
  static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc,
                                      DeclNameLoc nameLoc, DeclName name,
                                      SourceLoc lParenLoc,
                                      ArrayRef<Expr *> args,
                                      ArrayRef<Identifier> argLabels,
                                      ArrayRef<SourceLoc> argLabelLocs,
                                      SourceLoc rParenLoc,
                                      Expr *trailingClosure,
                                      bool implicit);

  DeclName getName() const { return Name; }
  DeclNameLoc getNameLoc() const { return NameLoc; }
  SourceLoc getDotLoc() const { return DotLoc; }
  Expr *getArgument() const { return Argument; }
  void setArgument(Expr *argument) { Argument = argument; }

  /// Whether this reference has arguments.
  bool hasArguments() const {
    return UnresolvedMemberExprBits.HasArguments;
  }

  unsigned getNumArguments() const {
    return UnresolvedMemberExprBits.NumArgLabels;
  }

  bool hasArgumentLabelLocs() const {
    return UnresolvedMemberExprBits.HasArgLabelLocs;
  }

  /// Whether this call with written with a trailing closure.
  bool hasTrailingClosure() const {
    return UnresolvedMemberExprBits.HasTrailingClosure;
  }

  SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

  SourceLoc getStartLoc() const { return DotLoc; }
  SourceLoc getEndLoc() const {
    return (Argument ? Argument->getEndLoc() : NameLoc.getSourceRange().End);
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedMember;
  }
};

/// AnyTryExpr - An abstract superclass for 'try' and 'try!'.
///
/// These are like IdentityExpr in some ways, but they're a bit too
/// semantic differentiated to just always look through.
class AnyTryExpr : public Expr {
  Expr *SubExpr;
  SourceLoc TryLoc;

public:
  AnyTryExpr(ExprKind kind, SourceLoc tryLoc, Expr *sub,
             Type type, bool implicit)
    : Expr(kind, implicit, type), SubExpr(sub), TryLoc(tryLoc) {}

  SourceLoc getLoc() const { return SubExpr->getLoc(); }
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *E) { SubExpr = E; }

  SourceLoc getTryLoc() const { return TryLoc; }

  SourceLoc getStartLoc() const { return TryLoc; }
  SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); }

  static bool classof(const Expr *e) {
    return e->getKind() >= ExprKind::First_AnyTryExpr
        && e->getKind() <= ExprKind::Last_AnyTryExpr;
  }
};

/// TryExpr - A 'try' surrounding an expression, marking that the
/// expression contains code which might throw.
///
/// getSemanticsProvidingExpr() looks through this because it doesn't
/// provide the value and only very specific clients care where the
/// 'try' was written.
class TryExpr : public AnyTryExpr {
public:
  TryExpr(SourceLoc tryLoc, Expr *sub, Type type = Type(),
          bool implicit = false)
    : AnyTryExpr(ExprKind::Try, tryLoc, sub, type, implicit) {}

  static bool classof(const Expr *e) {
    return e->getKind() == ExprKind::Try;
  }
};

/// ForceTryExpr - A 'try!' surrounding an expression, marking that
/// the expression contains code which might throw, but that the code
/// should dynamically assert if it does.
class ForceTryExpr : public AnyTryExpr {
  SourceLoc ExclaimLoc;

public:
  ForceTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc exclaimLoc,
               Type type = Type(), bool implicit = false)
    : AnyTryExpr(ExprKind::ForceTry, tryLoc, sub, type, implicit),
      ExclaimLoc(exclaimLoc) {}

  SourceLoc getExclaimLoc() const { return ExclaimLoc; }

  static bool classof(const Expr *e) {
    return e->getKind() == ExprKind::ForceTry;
  }
};

/// A 'try?' surrounding an expression, marking that the expression contains
/// code which might throw, and that the result should be injected into an
/// Optional. If the code does throw, \c nil is produced.
class OptionalTryExpr : public AnyTryExpr {
  SourceLoc QuestionLoc;

public:
  OptionalTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc questionLoc,
                  Type type = Type(), bool implicit = false)
    : AnyTryExpr(ExprKind::OptionalTry, tryLoc, sub, type, implicit),
      QuestionLoc(questionLoc) {}

  SourceLoc getQuestionLoc() const { return QuestionLoc; }

  static bool classof(const Expr *e) {
    return e->getKind() == ExprKind::OptionalTry;
  }
};

/// An expression node that does not affect the evaluation of its subexpression.
class IdentityExpr : public Expr {
  Expr *SubExpr;
  
public:
  IdentityExpr(ExprKind kind,
               Expr *subExpr, Type ty = Type(),
               bool implicit = false)
    : Expr(kind, implicit, ty), SubExpr(subExpr)
  {}
  
  SourceLoc getLoc() const { return SubExpr->getLoc(); }
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *E) { SubExpr = E; }
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_IdentityExpr
        && E->getKind() <= ExprKind::Last_IdentityExpr;
  }
};
  
/// The '.self' pseudo-property, which has no effect except to
/// satisfy the syntactic requirement that type values appear only as part of
/// a property chain.
class DotSelfExpr : public IdentityExpr {
  SourceLoc DotLoc;
  SourceLoc SelfLoc;
  
public:
  DotSelfExpr(Expr *subExpr, SourceLoc dot, SourceLoc self,
              Type ty = Type())
    : IdentityExpr(ExprKind::DotSelf, subExpr, ty),
      DotLoc(dot), SelfLoc(self)
  {}
  
  SourceLoc getDotLoc() const { return DotLoc; }
  SourceLoc getSelfLoc() const { return SelfLoc; }

  SourceLoc getStartLoc() const { return getSubExpr()->getStartLoc(); }
  SourceLoc getEndLoc() const { return SelfLoc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DotSelf;
  }
};
  
/// A parenthesized expression like '(x+x)'.  Syntactically,
/// this is just a TupleExpr with exactly one element that has no label.
/// Semantically, however, it serves only as grouping parentheses and
/// does not form an expression of tuple type (unless the sub-expression
/// has tuple type, of course).
class ParenExpr : public IdentityExpr {
  SourceLoc LParenLoc, RParenLoc;
  
  /// \brief Whether we're wrapping a trailing closure expression.
  /// FIXME: Pack bit into superclass.
  bool HasTrailingClosure;

public:
  ParenExpr(SourceLoc lploc, Expr *subExpr, SourceLoc rploc,
            bool hasTrailingClosure,
            Type ty = Type())
    : IdentityExpr(ExprKind::Paren, subExpr, ty),
      LParenLoc(lploc), RParenLoc(rploc),
      HasTrailingClosure(hasTrailingClosure) {
    assert(lploc.isValid() == rploc.isValid() &&
           "Mismatched source location information");
  }

  SourceLoc getLParenLoc() const { return LParenLoc; }
  SourceLoc getRParenLoc() const { return RParenLoc; }

  // When the locations of the parens are invalid, ask our
  // subexpression for its source range instead.  This isn't a
  // hot path and so we don't both optimizing for it.

  SourceLoc getStartLoc() const {
    return (LParenLoc.isInvalid() ? getSubExpr()->getStartLoc() : LParenLoc);
  }
  SourceLoc getEndLoc() const {
    // If we have a trailing closure, our end point is the end of the
    // trailing closure.
    if (RParenLoc.isInvalid() || HasTrailingClosure)
      return getSubExpr()->getEndLoc();
    return RParenLoc;
  }

  /// \brief Whether this expression has a trailing closure as its argument.
  bool hasTrailingClosure() const { return HasTrailingClosure; }

  static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; }
};
  
/// TupleExpr - Parenthesized expressions like '(a: x+x)' and '(x, y, 4)'.  Also
/// used to represent the operands to a binary operator.  Note that
/// expressions like '(4)' are represented with a ParenExpr.
class TupleExpr final : public Expr,
    private llvm::TrailingObjects<TupleExpr, Expr *, Identifier, SourceLoc> {
  friend TrailingObjects;

  SourceLoc LParenLoc;
  SourceLoc RParenLoc;
  unsigned NumElements;

  size_t numTrailingObjects(OverloadToken<Expr *>) const {
    return getNumElements();
  }
  size_t numTrailingObjects(OverloadToken<Identifier>) const {
    return hasElementNames() ? getNumElements() : 0;
  }
  size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
    return hasElementNames() ? getNumElements() : 0;
  }

  /// Retrieve the buffer containing the element names.
  MutableArrayRef<Identifier> getElementNamesBuffer() {
    if (!hasElementNames())
      return { };

    return { getTrailingObjects<Identifier>(), getNumElements() };
  }

  /// Retrieve the buffer containing the element name locations.
  MutableArrayRef<SourceLoc> getElementNameLocsBuffer() {
    if (!hasElementNameLocs())
      return { };
    
    return { getTrailingObjects<SourceLoc>(), getNumElements() };
  }

  TupleExpr(SourceLoc LParenLoc, ArrayRef<Expr *> SubExprs,
            ArrayRef<Identifier> ElementNames, 
            ArrayRef<SourceLoc> ElementNameLocs,
            SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit, 
            Type Ty);

public:
  /// Create a tuple.
  static TupleExpr *create(ASTContext &ctx,
                           SourceLoc LParenLoc, 
                           ArrayRef<Expr *> SubExprs,
                           ArrayRef<Identifier> ElementNames, 
                           ArrayRef<SourceLoc> ElementNameLocs,
                           SourceLoc RParenLoc, bool HasTrailingClosure, 
                           bool Implicit, Type Ty = Type());

  /// Create an empty tuple.
  static TupleExpr *createEmpty(ASTContext &ctx, SourceLoc LParenLoc, 
                                SourceLoc RParenLoc, bool Implicit);

  /// Create an implicit tuple with no source information.
  static TupleExpr *createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs,
                                   ArrayRef<Identifier> ElementNames);

  SourceLoc getLParenLoc() const { return LParenLoc; }
  SourceLoc getRParenLoc() const { return RParenLoc; }

  SourceRange getSourceRange() const;

  /// \brief Whether this expression has a trailing closure as its argument.
  bool hasTrailingClosure() const { return TupleExprBits.HasTrailingClosure; }

  /// Retrieve the elements of this tuple.
  MutableArrayRef<Expr*> getElements() {
    return { getTrailingObjects<Expr *>(), getNumElements() };
  }

  /// Retrieve the elements of this tuple.
  ArrayRef<Expr*> getElements() const {
    return { getTrailingObjects<Expr *>(), getNumElements() };
  }
  
  unsigned getNumElements() const { return NumElements; }
  
  Expr *getElement(unsigned i) const {
    return getElements()[i];
  }
  void setElement(unsigned i, Expr *e) {
    getElements()[i] = e;
  }

  /// Whether this tuple has element names.
  bool hasElementNames() const { 
    return TupleExprBits.HasElementNames;
  }

  /// Retrieve the element names for a tuple.
  ArrayRef<Identifier> getElementNames() const { 
    return const_cast<TupleExpr *>(this)->getElementNamesBuffer();
  }
  
  /// Retrieve the ith element name.
  Identifier getElementName(unsigned i) const {
    return hasElementNames() ? getElementNames()[i] : Identifier();
  }
  
  /// Whether this tuple has element name locations.
  bool hasElementNameLocs() const { 
    return TupleExprBits.HasElementNameLocations;
  }

  /// Retrieve the locations of the element names for a tuple.
  ArrayRef<SourceLoc> getElementNameLocs() const {
    return const_cast<TupleExpr *>(this)->getElementNameLocsBuffer();
  }

  /// Retrieve the location of the ith label, if known.
  SourceLoc getElementNameLoc(unsigned i) const {
    if (hasElementNameLocs())
      return getElementNameLocs()[i];
    
    return SourceLoc();
  }

  static bool classof(const Expr *E) { return E->getKind() == ExprKind::Tuple; }
};

/// \brief A collection literal expression.
///
/// The subexpression is represented as a TupleExpr or ParenExpr and
/// passed on to the appropriate semantics-providing conversion
/// operation.
class CollectionExpr : public Expr {
  SourceLoc LBracketLoc;
  SourceLoc RBracketLoc;

  /// ASTContext allocated element lists.  Each entry is one entry of the
  /// collection.  If this is a DictionaryLiteral, each entry is a Tuple with
  /// the key and value pair.
  MutableArrayRef<Expr*> Elements;

  Expr *SemanticExpr = nullptr;

  /// True if the type of this collection expr was inferred by the collection
  /// fallback type, like [Any].
  bool IsTypeDefaulted = false;

protected:
  CollectionExpr(ExprKind Kind, SourceLoc LBracketLoc,
                 MutableArrayRef<Expr*> Elements,
                 SourceLoc RBracketLoc, Type Ty)
    : Expr(Kind, /*Implicit=*/false, Ty),
      LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc),
      Elements(Elements) { }

public:

  /// Retrieve the elements stored in the collection.
  ArrayRef<Expr *> getElements() const { return Elements; }
  MutableArrayRef<Expr *> getElements() { return Elements; }
  Expr *getElement(unsigned i) const { return Elements[i]; }
  void setElement(unsigned i, Expr *E) { Elements[i] = E; }
  unsigned getNumElements() const { return Elements.size(); }

  bool isTypeDefaulted() const { return IsTypeDefaulted; }
  void setIsTypeDefaulted(bool value = true) { IsTypeDefaulted = value; }

  SourceLoc getLBracketLoc() const { return LBracketLoc; }
  SourceLoc getRBracketLoc() const { return RBracketLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(LBracketLoc, RBracketLoc);
  }
  
  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *e) { SemanticExpr = e; }

  static bool classof(const Expr *e) {
    return e->getKind() >= ExprKind::First_CollectionExpr &&
           e->getKind() <= ExprKind::Last_CollectionExpr;
  }

};
 
/// \brief An array literal expression [a, b, c].
class ArrayExpr : public CollectionExpr {
  /// ASTContext allocated list of comma locations, there is one less entry here
  /// than the number of elements.
  MutableArrayRef<SourceLoc> CommaLocs;

  ArrayExpr(SourceLoc LBracketLoc, MutableArrayRef<Expr*> Elements,
            MutableArrayRef<SourceLoc> CommaLocs,
            SourceLoc RBracketLoc, Type Ty)
  : CollectionExpr(ExprKind::Array, LBracketLoc, Elements, RBracketLoc, Ty),
    CommaLocs(CommaLocs) {}
public:
  static ArrayExpr *create(ASTContext &C, SourceLoc LBracketLoc,
                           ArrayRef<Expr*> Elements,
                           ArrayRef<SourceLoc> CommaLocs,
                           SourceLoc RBracketLoc,
                           Type Ty = Type());

  /// ASTContext allocated list of comma locations, there is one less entry here
  /// than the number of elements.
  MutableArrayRef<SourceLoc> getCommaLocs() { return CommaLocs; }
  ArrayRef<SourceLoc> getCommaLocs() const { return CommaLocs; }

  static bool classof(const Expr *e) {
    return e->getKind() == ExprKind::Array;
  }
};

/// \brief A dictionary literal expression [a : x, b : y, c : z].
class DictionaryExpr : public CollectionExpr {
  DictionaryExpr(SourceLoc LBracketLoc, MutableArrayRef<Expr*> Elements,
                 SourceLoc RBracketLoc, Type Ty)
    : CollectionExpr(ExprKind::Dictionary, LBracketLoc, Elements, RBracketLoc,
                     Ty) { }
public:

  static DictionaryExpr *create(ASTContext &C, SourceLoc LBracketLoc,
                                ArrayRef<Expr*> Elements, SourceLoc RBracketLoc,
                                Type Ty = Type());


  static bool classof(const Expr *e) {
    return e->getKind() == ExprKind::Dictionary;
  }
};

/// Subscripting expressions like a[i] that refer to an element within a
/// container.
///
/// There is no built-in subscripting in the language. Rather, a fully
/// type-checked and well-formed subscript expression refers to a subscript
/// declaration, which provides a getter and (optionally) a setter that will
/// be used to perform reads/writes.
class SubscriptExpr final : public Expr,
                            public TrailingCallArguments<SubscriptExpr> {
  friend TrailingCallArguments;

  ConcreteDeclRef TheDecl;
  Expr *Base;
  Expr *Index;

  SubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels,
                ArrayRef<SourceLoc> argLabelLocs, bool hasTrailingClosure,
                ConcreteDeclRef decl, bool implicit, AccessSemantics semantics);
  
public:
  /// Create a subscript.
  ///
  /// Note: do not create new callers to this entry point; use the entry point
  /// that takes separate index arguments.
  static SubscriptExpr *create(ASTContext &ctx, Expr *base, Expr *index,
                               ConcreteDeclRef decl = ConcreteDeclRef(),
                               bool implicit = false,
                               AccessSemantics semantics
                                 = AccessSemantics::Ordinary);

  /// Create a new subscript.
  static SubscriptExpr *create(ASTContext &ctx, Expr *base,
                               SourceLoc lSquareLoc,
                               ArrayRef<Expr *> indexArgs,
                               ArrayRef<Identifier> indexArgLabels,
                               ArrayRef<SourceLoc> indexArgLabelLocs,
                               SourceLoc rSquareLoc,
                               Expr *trailingClosure,
                               ConcreteDeclRef decl = ConcreteDeclRef(),
                               bool implicit = false,
                               AccessSemantics semantics
                                 = AccessSemantics::Ordinary);

  /// getBase - Retrieve the base of the subscript expression, i.e., the
  /// value being indexed.
  Expr *getBase() const { return Base; }
  void setBase(Expr *E) { Base = E; }
  
  /// getIndex - Retrieve the index of the subscript expression, i.e., the
  /// "offset" into the base value.
  Expr *getIndex() const { return Index; }
  void setIndex(Expr *E) { Index = E; }

  unsigned getNumArguments() const {
    return SubscriptExprBits.NumArgLabels;
  }

  bool hasArgumentLabelLocs() const {
    return SubscriptExprBits.HasArgLabelLocs;
  }

  /// Whether this call with written with a trailing closure.
  bool hasTrailingClosure() const {
    return SubscriptExprBits.HasTrailingClosure;
  }

  /// Determine whether this subscript reference should bypass the
  /// ordinary accessors.
  AccessSemantics getAccessSemantics() const {
    return (AccessSemantics) SubscriptExprBits.Semantics;
  }
  
  /// Determine whether this member reference refers to the
  /// superclass's property.
  bool isSuper() const { return SubscriptExprBits.IsSuper; }

  /// Set whether this member reference refers to the superclass's
  /// property.
  void setIsSuper(bool isSuper) { SubscriptExprBits.IsSuper = isSuper; }

  /// Determine whether subscript operation has a known underlying
  /// subscript declaration or not.
  bool hasDecl() const { return static_cast<bool>(TheDecl); }
  
  /// Retrieve the subscript declaration that this subscripting
  /// operation refers to. Only valid when \c hasDecl() is true.
  ConcreteDeclRef getDecl() const {
    assert(hasDecl() && "No subscript declaration known!");
    return TheDecl;
  }

  SourceLoc getLoc() const { return Index->getStartLoc(); }
  SourceLoc getStartLoc() const { return Base->getStartLoc(); }
  SourceLoc getEndLoc() const { return Index->getEndLoc(); }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Subscript;
  }
};

/// A member access (foo.bar) on an expression with unresolved type.
class UnresolvedDotExpr : public Expr {
  Expr *SubExpr;
  SourceLoc DotLoc;
  DeclNameLoc NameLoc;
  DeclName Name;
public:
  UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name,
                    DeclNameLoc nameloc, bool Implicit)
    : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
      NameLoc(nameloc), Name(name) {
    UnresolvedDotExprBits.FunctionRefKind =
      static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound
                                                 : FunctionRefKind::Unapplied);
  }
  
  SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

  SourceLoc getStartLoc() const {
    return (DotLoc.isInvalid() ? NameLoc.getSourceRange().End 
                               : SubExpr->getStartLoc());
  }
  SourceLoc getEndLoc() const {
    return NameLoc.getSourceRange().End ;
  }

  SourceLoc getDotLoc() const { return DotLoc; }
  Expr *getBase() const { return SubExpr; }
  void setBase(Expr *e) { SubExpr = e; }

  DeclName getName() const { return Name; }
  DeclNameLoc getNameLoc() const { return NameLoc; }

  /// Retrieve the kind of function reference.
  FunctionRefKind getFunctionRefKind() const {
    return static_cast<FunctionRefKind>(UnresolvedDotExprBits.FunctionRefKind);
  }

  /// Set the kind of function reference.
  void setFunctionRefKind(FunctionRefKind refKind) {
    UnresolvedDotExprBits.FunctionRefKind = static_cast<unsigned>(refKind);
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedDot;
  }
};

/// TupleElementExpr - Refer to an element of a tuple,
/// e.g. "(1,field:2).field".
class TupleElementExpr : public Expr {
  Expr *SubExpr;
  SourceLoc NameLoc;
  unsigned FieldNo;
  SourceLoc DotLoc;

public:
  TupleElementExpr(Expr *SubExpr, SourceLoc DotLoc, unsigned FieldNo,
                   SourceLoc NameLoc, Type Ty)
    : Expr(ExprKind::TupleElement, /*Implicit=*/false, Ty), SubExpr(SubExpr),
      NameLoc(NameLoc), FieldNo(FieldNo), DotLoc(DotLoc) {}

  SourceLoc getLoc() const { return NameLoc; }
  Expr *getBase() const { return SubExpr; }
  void setBase(Expr *e) { SubExpr = e; }

  unsigned getFieldNumber() const { return FieldNo; }
  SourceLoc getNameLoc() const { return NameLoc; }  
  SourceLoc getDotLoc() const { return DotLoc; }
  
  SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
  SourceLoc getEndLoc() const { return getNameLoc(); }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::TupleElement;
  }
};

/// \brief Describes a monadic bind from T? to T.
///
/// In a ?-chain expression, this is the part that's spelled with a
/// postfix ?.
///
/// A BindOptionalExpr must always appear within a
/// OptionalEvaluationExpr.  If the operand of the BindOptionalExpr
/// evaluates to a missing value, the OptionalEvaluationExpr
/// immediately completes and produces a missing value in the result
/// type.
///
/// The depth of the BindOptionalExpr indicates which
/// OptionalEvaluationExpr is completed, in case the BindOptionalExpr
/// is contained within more than one such expression.
class BindOptionalExpr : public Expr {
  Expr *SubExpr;
  SourceLoc QuestionLoc;

public:
  BindOptionalExpr(Expr *subExpr, SourceLoc questionLoc,
                   unsigned depth, Type ty = Type())
    : Expr(ExprKind::BindOptional, /*Implicit=*/ questionLoc.isInvalid(), ty),
      SubExpr(subExpr), QuestionLoc(questionLoc) {
    BindOptionalExprBits.Depth = depth;
    assert(BindOptionalExprBits.Depth == depth && "bitfield truncation");
  }

  SourceRange getSourceRange() const {
    if (QuestionLoc.isInvalid())
      return SubExpr->getSourceRange();
    return SourceRange(SubExpr->getStartLoc(), QuestionLoc);
  }
  SourceLoc getStartLoc() const {
    return SubExpr->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return (QuestionLoc.isInvalid() ? SubExpr->getEndLoc() : QuestionLoc);
  }
  SourceLoc getLoc() const { 
    if (isImplicit())
      return SubExpr->getLoc();

    return getQuestionLoc(); 
  }
  SourceLoc getQuestionLoc() const { return QuestionLoc; }

  unsigned getDepth() const { return BindOptionalExprBits.Depth; }

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *expr) { SubExpr = expr; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::BindOptional;
  }
};

/// \brief Describes the outer limits of an operation containing
/// monadic binds of T? to T.
///
/// In a ?-chain expression, this is implicitly formed at the outer
/// limits of the chain.  For example, in (foo?.bar?().baz).fred,
/// this is nested immediately within the parens.
///
/// This expression will always have optional type.
class OptionalEvaluationExpr : public Expr {
  Expr *SubExpr;

public:
  OptionalEvaluationExpr(Expr *subExpr, Type ty = Type())
    : Expr(ExprKind::OptionalEvaluation, /*Implicit=*/ true, ty),
      SubExpr(subExpr) {}

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *expr) { SubExpr = expr; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OptionalEvaluation;
  }
};

/// \brief An expression that forces an optional to its underlying value.
///
/// \code
/// func parseInt(s : String) -> Int? { ... }
///
/// var maybeInt = parseInt("5")     // returns an Int?
/// var forcedInt = parseInt("5")!   // returns an Int; fails on empty optional
/// \endcode
///
class ForceValueExpr : public Expr {
  Expr *SubExpr;
  SourceLoc ExclaimLoc;

public:
  ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc)
    : Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()),
      SubExpr(subExpr), ExclaimLoc(exclaimLoc) {}

  SourceRange getSourceRange() const {
    if (ExclaimLoc.isInvalid())
      return SubExpr->getSourceRange();

    return SourceRange(SubExpr->getStartLoc(), ExclaimLoc);
  }
  SourceLoc getStartLoc() const {
    return SubExpr->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return (isImplicit() ? SubExpr->getEndLoc() : getExclaimLoc());
  }
  SourceLoc getLoc() const {
    if (!isImplicit())
      return getExclaimLoc();
    
    return SubExpr->getLoc();
  }
  SourceLoc getExclaimLoc() const { return ExclaimLoc; }

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *expr) { SubExpr = expr; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ForceValue;
  }
};

/// \brief An expression that opens up a value of protocol or protocol
/// composition type and gives a name to its dynamic type.
///
/// This expression is implicitly created by the type checker when
/// calling a method on a protocol. In the future, this may become an
/// actual operation within the language.
class OpenExistentialExpr : public Expr {
  Expr *ExistentialValue;
  OpaqueValueExpr *OpaqueValue;
  Expr *SubExpr;
  SourceLoc ExclaimLoc;

public:
  OpenExistentialExpr(Expr *existentialValue,
                      OpaqueValueExpr *opaqueValue,
                      Expr *subExpr)
    : Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExpr->getType()),
      ExistentialValue(existentialValue), OpaqueValue(opaqueValue), 
      SubExpr(subExpr) { }

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

  /// Retrieve the expression that is being evaluated using the
  /// archetype value.
  ///
  /// This subexpression (and no other) may refer to the archetype
  /// type or the opaque value that stores the archetype's value.
  Expr *getSubExpr() const { return SubExpr; }

  /// Set the subexpression that is being evaluated.
  void setSubExpr(Expr *expr) { SubExpr = expr; }

  /// Retrieve the existential value that is being opened.
  Expr *getExistentialValue() const { return ExistentialValue; }

  /// Set the existential value that is being opened.
  void setExistentialValue(Expr *expr) { ExistentialValue = expr; }

  /// Retrieve the opaque value representing the value (of archetype
  /// type) stored in the existential.
  OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }

  /// Retrieve the opened archetype, which can only be referenced
  /// within this expression's subexpression.
  ArchetypeType *getOpenedArchetype() const;

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OpenExistential;
  }
};

/// ImplicitConversionExpr - An abstract class for expressions which
/// implicitly convert the value of an expression in some way.
class ImplicitConversionExpr : public Expr {
  Expr *SubExpr;

protected:
  ImplicitConversionExpr(ExprKind kind, Expr *subExpr, Type ty)
    : Expr(kind, /*Implicit=*/true, ty), SubExpr(subExpr) {}

public:
  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_ImplicitConversionExpr &&
           E->getKind() <= ExprKind::Last_ImplicitConversionExpr;
  }
};

/// The implicit conversion from a class metatype to AnyObject.
class ClassMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
  ClassMetatypeToObjectExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ClassMetatypeToObject, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ClassMetatypeToObject;
  }
};

/// The implicit conversion from a class existential metatype to AnyObject.
class ExistentialMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
  ExistentialMetatypeToObjectExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ExistentialMetatypeToObject, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ExistentialMetatypeToObject;
  }
};
  
/// The implicit conversion from a protocol value metatype to ObjC's Protocol
/// class type.
class ProtocolMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
  ProtocolMetatypeToObjectExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ProtocolMetatypeToObject, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ProtocolMetatypeToObject;
  }
};
  
/// InjectIntoOptionalExpr - The implicit conversion from T to T?.
class InjectIntoOptionalExpr : public ImplicitConversionExpr {
public:
  InjectIntoOptionalExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::InjectIntoOptional, subExpr, ty) {}

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InjectIntoOptional;
  }
};
  
/// Convert the address of an lvalue to a raw pointer.
class LValueToPointerExpr : public ImplicitConversionExpr {
  Type AbstractionPattern;
public:
  LValueToPointerExpr(Expr *subExpr, Type ty, Type abstractionTy)
    : ImplicitConversionExpr(ExprKind::LValueToPointer, subExpr, ty),
      AbstractionPattern(abstractionTy) {}
  
  /// Get the declared type of the type for which we are performing this
  /// conversion. This defines the abstraction level at which the lvalue should
  /// be emitted before taking its address.
  Type getAbstractionPatternType() const {
    return AbstractionPattern;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::LValueToPointer;
  }
};
  
/// Convert the address of an inout property to a pointer.
class InOutToPointerExpr : public ImplicitConversionExpr {
public:
  InOutToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InOutToPointer;
  }
};
  
/// Convert the address of an array to a pointer.
class ArrayToPointerExpr : public ImplicitConversionExpr {
public:
  ArrayToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ArrayToPointer;
  }
};
  
/// Convert the a string to a pointer referencing its encoded representation.
class StringToPointerExpr : public ImplicitConversionExpr {
public:
  StringToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::StringToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::StringToPointer;
  }
};
  
/// Convert a pointer to a different kind of pointer.
class PointerToPointerExpr : public ImplicitConversionExpr {
public:
  PointerToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::PointerToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::PointerToPointer;
  }
};

/// Convert between a foreign object and its corresponding Objective-C object.
class ForeignObjectConversionExpr : public ImplicitConversionExpr {
public:
  ForeignObjectConversionExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ForeignObjectConversion, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ForeignObjectConversion;
  }
};

/// Construct an unevaluated instance of the underlying metatype.
class UnevaluatedInstanceExpr : public ImplicitConversionExpr {
public:
  UnevaluatedInstanceExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::UnevaluatedInstance, subExpr, ty) {}

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnevaluatedInstance;
  }
};

/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
/// tuple type.  The expression's type is known to be a tuple type.
///
/// If hasScalarSource() is true, the subexpression should be treated
/// as if it were implicitly injected into a single-element tuple
/// type.  Otherwise, the subexpression is known to have a tuple type.
class TupleShuffleExpr : public ImplicitConversionExpr {
public:
  enum : int {
    /// The element mapping value indicating that a field of the destination
    /// tuple should be default-initialized.
    DefaultInitialize = -1,
    /// The element mapping is part of the variadic field.
    Variadic = -2,
    /// The element mapping value indicating that the field of the
    /// destination tuple should be default-initialized with an expression
    /// provided by the caller.
    /// FIXME: Yet another indication that TupleShuffleExpr uses the wrong
    /// formulation.
    CallerDefaultInitialize = -3
  };

  enum SourceIsScalar_t : bool {
    SourceIsTuple = false,
    SourceIsScalar = true
  };

private:
  /// This contains an entry for each element in the Expr type.  Each element
  /// specifies which index from the SubExpr that the destination element gets.
  /// If the element value is DefaultInitialize, then the destination value
  /// gets the default initializer for that tuple element value.
  ArrayRef<int> ElementMapping;

  /// If we're doing a varargs shuffle, this is the array type to build.
  Type VarargsArrayTy;

  /// If there are any default arguments, the owning function
  /// declaration.
  ConcreteDeclRef DefaultArgsOwner;

  /// The arguments that are packed into the variadic element.
  ArrayRef<unsigned> VariadicArgs;

  MutableArrayRef<Expr *> CallerDefaultArgs;

public:
  TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping, 
                   SourceIsScalar_t isSourceScalar,
                   ConcreteDeclRef defaultArgsOwner,
                   ArrayRef<unsigned> VariadicArgs,
                   MutableArrayRef<Expr *> CallerDefaultArgs, Type ty)
    : ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
      ElementMapping(elementMapping), VarargsArrayTy(),
      DefaultArgsOwner(defaultArgsOwner), VariadicArgs(VariadicArgs),
      CallerDefaultArgs(CallerDefaultArgs)
  {
    TupleShuffleExprBits.IsSourceScalar = isSourceScalar;
  }

  ArrayRef<int> getElementMapping() const { return ElementMapping; }

  /// Is the source expression scalar?
  ///
  /// This doesn't necessarily mean it's not a tuple; it just means
  /// that it should be treated as if it were an element of a
  /// single-element tuple for the purposes of interpreting behavior.
  bool isSourceScalar() const { return TupleShuffleExprBits.IsSourceScalar; }

  /// Set the varargs array type to use.
  void setVarargsArrayType(Type T) { VarargsArrayTy = T; }
  Type getVarargsArrayType() const {
    assert(!VarargsArrayTy.isNull());
    return VarargsArrayTy;
  }
  Type getVarargsArrayTypeOrNull() const {
    return VarargsArrayTy;
  }

  /// Retrieve the argument indices for the variadic arguments.
  ArrayRef<unsigned> getVariadicArgs() const { return VariadicArgs; }

  /// Retrieve the owner of the default arguments.
  ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }

  /// Retrieve the caller-defaulted arguments.
  ArrayRef<Expr *> getCallerDefaultArgs() const { return CallerDefaultArgs; }

  /// Retrieve the caller-defaulted arguments.
  MutableArrayRef<Expr *> getCallerDefaultArgs() { return CallerDefaultArgs; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::TupleShuffle;
  }
};

/// LoadExpr - Turn an l-value into an r-value by performing a "load"
/// operation.  This operation may actually be a logical operation,
/// i.e. one implemented using a call to a potentially user-defined
/// function instead of a simple memory transaction.
class LoadExpr : public ImplicitConversionExpr {
public:
  LoadExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::Load, subExpr, type) {}

  static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
};

/// This is a conversion from an expression of UnresolvedType to an arbitrary
/// other type, and from an arbitrary type to UnresolvedType.  This node does
/// not appear in valid code, only in code involving diagnostics.
class UnresolvedTypeConversionExpr : public ImplicitConversionExpr {
public:
  UnresolvedTypeConversionExpr(Expr *subExpr, Type type)
  : ImplicitConversionExpr(ExprKind::UnresolvedTypeConversion, subExpr, type) {}

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedTypeConversion;
  }
};

/// FunctionConversionExpr - Convert a function to another function type,
/// which might involve renaming the parameters or handling substitutions
/// of subtypes (in the return) or supertypes (in the input).
///
/// FIXME: This should be a CapturingExpr.
class FunctionConversionExpr : public ImplicitConversionExpr {
public:
  FunctionConversionExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::FunctionConversion, subExpr, type) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::FunctionConversion;
  }
};

/// Perform a function conversion from one function that to one that has a
/// covariant result type.
///
/// This conversion is technically unsafe; however, semantic analysis will
/// only introduce such a conversion in cases where other language features
/// (i.e., Self returns) enforce static safety. Additionally, this conversion
/// avoids changing the ABI of the function in question.
class CovariantFunctionConversionExpr : public ImplicitConversionExpr {
public:
  CovariantFunctionConversionExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::CovariantFunctionConversion, subExpr,
                             type) { }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CovariantFunctionConversion;
  }
};

/// Perform a conversion from a superclass to a subclass for a call to
/// a method with a covariant result type.
///
/// This conversion is technically unsafe; however, semantic analysis will
/// only introduce such a conversion in cases where other language features
/// (i.e., Self returns) enforce static safety.
class CovariantReturnConversionExpr : public ImplicitConversionExpr {
public:
  CovariantReturnConversionExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::CovariantReturnConversion, subExpr,
                             type) { }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CovariantReturnConversion;
  }
};

/// MetatypeConversionExpr - Convert a metatype to another metatype
/// using essentially a derived-to-base conversion.
class MetatypeConversionExpr : public ImplicitConversionExpr {
public:
  MetatypeConversionExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::MetatypeConversion, subExpr, type) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::MetatypeConversion;
  }
};
  
/// CollectionUpcastConversionExpr - Convert a collection whose
/// elements have some type T to the same kind of collection whose
/// elements have type U, where U is a subtype of T.
class CollectionUpcastConversionExpr : public ImplicitConversionExpr {
public:
  struct ConversionPair {
    OpaqueValueExpr *OrigValue;
    Expr *Conversion;

    explicit operator bool() const { return OrigValue != nullptr; }
  };
private:
  ConversionPair KeyConversion;
  ConversionPair ValueConversion;
public:
  CollectionUpcastConversionExpr(Expr *subExpr, Type type,
                                 ConversionPair keyConversion,
                                 ConversionPair valueConversion)
    : ImplicitConversionExpr(
        ExprKind::CollectionUpcastConversion, subExpr, type),
      KeyConversion(keyConversion), ValueConversion(valueConversion) {
    assert((!KeyConversion || ValueConversion)
           && "key conversion without value conversion");
  }

  /// Returns the expression that should be used to perform a
  /// conversion of the collection's values; null if the conversion
  /// is formally trivial because the key type does not change.
  const ConversionPair &getKeyConversion() const {
    return KeyConversion;
  }
  void setKeyConversion(const ConversionPair &pair) {
    KeyConversion = pair;
  }

  /// Returns the expression that should be used to perform a
  /// conversion of the collection's values; null if the conversion
  /// is formally trivial because the value type does not change.
  const ConversionPair &getValueConversion() const {
    return ValueConversion;
  }
  void setValueConversion(const ConversionPair &pair) {
    ValueConversion = pair;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CollectionUpcastConversion;
  }
};
  
/// ErasureExpr - Perform type erasure by converting a value to existential
/// type. For example:
///
/// \code
/// protocol Printable {}
/// struct Book {}
///
/// var printable: Printable = Book() // erases type
/// var printableType: Printable.Type = Book.self // erases metatype
/// \endcode
///
/// The type of the expression should always satisfy isAnyExistentialType().
///
/// The type of the sub-expression should always be either:
///   - a non-existential type of the appropriate kind or
///   - an existential type of the appropriate kind which is a subtype
///     of the result type.
///
/// "Appropriate kind" means e.g. a concrete/existential metatype if the
/// result is an existential metatype.
class ErasureExpr : public ImplicitConversionExpr {
  ArrayRef<ProtocolConformanceRef> Conformances;

public:
  ErasureExpr(Expr *subExpr, Type type,
              ArrayRef<ProtocolConformanceRef> conformances)
    : ImplicitConversionExpr(ExprKind::Erasure, subExpr, type),
      Conformances(conformances) {}

  /// \brief Retrieve the mapping specifying how the type of the subexpression
  /// maps to the resulting existential type. If the resulting existential
  /// type involves several different protocols, there will be mappings for each
  /// of those protocols, in the order in which the existential type expands
  /// its properties.
  ///
  /// The entries in this array may be null, indicating that the conformance
  /// to the corresponding protocol is trivial (because the source
  /// type is either an archetype or an existential type that conforms to
  /// that corresponding protocol).
  ArrayRef<ProtocolConformanceRef> getConformances() const {
    return Conformances;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Erasure;
  }
};

/// AnyHashableErasureExpr - Perform type erasure by converting a value
/// to AnyHashable type.
///
/// The type of the sub-expression should always be a type that implements
/// the Hashable protocol.
class AnyHashableErasureExpr : public ImplicitConversionExpr {
  ProtocolConformanceRef Conformance;

public:
  AnyHashableErasureExpr(Expr *subExpr, Type type,
                         ProtocolConformanceRef conformance)
    : ImplicitConversionExpr(ExprKind::AnyHashableErasure, subExpr, type),
      Conformance(conformance) {}

  /// \brief Retrieve the mapping specifying how the type of the
  /// subexpression conforms to the Hashable protocol.
  ProtocolConformanceRef getConformance() const {
    return Conformance;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::AnyHashableErasure;
  }
};
/// UnresolvedSpecializeExpr - Represents an explicit specialization using
/// a type parameter list (e.g. "Vector<Int>") that has not been resolved.
class UnresolvedSpecializeExpr : public Expr {
  Expr *SubExpr;
  SourceLoc LAngleLoc;
  SourceLoc RAngleLoc;
  MutableArrayRef<TypeLoc> UnresolvedParams;
public:
  UnresolvedSpecializeExpr(Expr *SubExpr,
                           SourceLoc LAngleLoc,
                           MutableArrayRef<TypeLoc> UnresolvedParams,
                           SourceLoc RAngleLoc)
    : Expr(ExprKind::UnresolvedSpecialize, /*Implicit=*/false),
      SubExpr(SubExpr),
      LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
      UnresolvedParams(UnresolvedParams) { }
  
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }
  
  /// \brief Retrieve the list of type parameters. These parameters have not yet
  /// been bound to archetypes of the entity to be specialized.
  ArrayRef<TypeLoc> getUnresolvedParams() const { return UnresolvedParams; }
  MutableArrayRef<TypeLoc> getUnresolvedParams() { return UnresolvedParams; }
  
  SourceLoc getLoc() const { return LAngleLoc; }
  SourceLoc getLAngleLoc() const { return LAngleLoc; }
  SourceLoc getRAngleLoc() const { return RAngleLoc; }

  SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
  SourceLoc getEndLoc() const { return RAngleLoc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedSpecialize;
  }
};

/// \brief Describes an implicit conversion from a subclass to one of its
/// superclasses.
class DerivedToBaseExpr : public ImplicitConversionExpr {
public:
  DerivedToBaseExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::DerivedToBase, subExpr, type) {}

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DerivedToBase;
  }
};

/// \brief Describes an implicit conversion from a value of archetype type to
/// its concrete superclass.
class ArchetypeToSuperExpr : public ImplicitConversionExpr {
public:
  ArchetypeToSuperExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::ArchetypeToSuper, subExpr, type) {}

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ArchetypeToSuper;
  }
};

/// The builtin unary '&' operator, which converts the
/// given lvalue into an 'inout' argument value.
class InOutExpr : public Expr {
  Expr *SubExpr;
  SourceLoc OperLoc;

public:
  InOutExpr(SourceLoc operLoc, Expr *subExpr, Type type,
                bool isImplicit = false)
    : Expr(ExprKind::InOut, isImplicit, type),
      SubExpr(subExpr), OperLoc(operLoc) {}

  SourceLoc getStartLoc() const { return OperLoc; }
  SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
  SourceLoc getLoc() const { return OperLoc; }

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InOut;
  }
};

/// SequenceExpr - A list of binary operations which has not yet been
/// folded into a tree.  The operands all have even indices, while the
/// subexpressions with odd indices are all (potentially overloaded)
/// references to binary operators.
class SequenceExpr final : public Expr,
    private llvm::TrailingObjects<SequenceExpr, Expr *> {
  friend TrailingObjects;

  unsigned NumElements;

  SequenceExpr(ArrayRef<Expr*> elements)
    : Expr(ExprKind::Sequence, /*Implicit=*/false),
      NumElements(elements.size()) {
    assert(NumElements > 0 && "zero-length sequence!");
    std::uninitialized_copy(elements.begin(), elements.end(),
                            getTrailingObjects<Expr*>());
  }

public:
  static SequenceExpr *create(ASTContext &ctx, ArrayRef<Expr*> elements);

  SourceLoc getStartLoc() const {
    return getElement(0)->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return getElement(getNumElements() - 1)->getEndLoc();
  }
  
  unsigned getNumElements() const { return NumElements; }

  MutableArrayRef<Expr*> getElements() {
    return {getTrailingObjects<Expr*>(), NumElements};
  }

  ArrayRef<Expr*> getElements() const {
    return {getTrailingObjects<Expr*>(), NumElements};
  }

  Expr *getElement(unsigned i) const {
    return getElements()[i];
  }
  void setElement(unsigned i, Expr *e) {
    getElements()[i] = e;
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Sequence;
  }
};


/// Instances of this structure represent elements of the capture list that can
/// optionally occur in a capture expression.
struct CaptureListEntry {
  VarDecl *Var;
  PatternBindingDecl *Init;

  CaptureListEntry(VarDecl *Var, PatternBindingDecl *Init)
  : Var(Var), Init(Init) {
  }
};

/// CaptureListExpr - This expression represents the capture list on an explicit
/// closure.  Because the capture list is evaluated outside of the closure, this
/// CaptureList wraps the ClosureExpr.  The dynamic semantics are that evaluates
/// the variable bindings from the capture list, then evaluates the
/// subexpression (the closure itself) and returns the result.
class CaptureListExpr : public Expr {
  ArrayRef<CaptureListEntry> captureList;
  Expr *closureBody;
public:
  CaptureListExpr(ArrayRef<CaptureListEntry> captureList, Expr *closureBody)
    : Expr(ExprKind::CaptureList, /*Implicit=*/false, Type()),
      captureList(captureList), closureBody(closureBody) {
  }

  ArrayRef<CaptureListEntry> getCaptureList() { return captureList; }
  Expr *getClosureBody() { return closureBody; }
  const Expr *getClosureBody() const { return closureBody; }

  void setClosureBody(Expr *body) { closureBody = body; }

  /// This is a bit weird, but the capture list is lexically contained within
  /// the closure, so the ClosureExpr has the full source range.
  SWIFT_FORWARD_SOURCE_LOCS_TO(closureBody)

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::CaptureList;
  }
};


/// \brief A base class for closure expressions.
class AbstractClosureExpr : public Expr, public DeclContext {
  CaptureInfo Captures;

  /// \brief The set of parameters.
  ParameterList *parameterList;

public:
  AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
                      unsigned Discriminator, DeclContext *Parent)
      : Expr(Kind, Implicit, FnType),
        DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
        parameterList(nullptr) {
    AbstractClosureExprBits.Discriminator = Discriminator;
  }

  CaptureInfo &getCaptureInfo() { return Captures; }
  const CaptureInfo &getCaptureInfo() const { return Captures; }

  /// \brief Retrieve the parameters of this closure.
  ParameterList *getParameters() { return parameterList; }
  const ParameterList *getParameters() const { return parameterList; }
  void setParameterList(ParameterList *P);

  // Expose this to users.
  using DeclContext::setParent;

  /// Returns a discriminator which determines this expression's index
  /// in the sequence of closure expressions within the current
  /// function.
  ///
  /// There are separate sequences for explicit and implicit closures.
  /// This allows explicit closures to maintain a stable numbering
  /// across simple edits that introduce auto closures above them,
  /// which is the best we can reasonably do.
  ///
  /// (Autoclosures are likely to be eliminated immediately, even in
  /// unoptimized builds, so their names are fairly unimportant.  It's
  /// much more likely that explicit closures will survive
  /// optimization and therefore make it into e.g. stack traces.
  /// Having their symbol names be stable across minor code changes is
  /// therefore pretty useful for debugging.)
  unsigned getDiscriminator() const {
    return AbstractClosureExprBits.Discriminator;
  }
  void setDiscriminator(unsigned discriminator) {
    assert(getDiscriminator() == InvalidDiscriminator);
    assert(discriminator != InvalidDiscriminator);
    AbstractClosureExprBits.Discriminator = discriminator;
  }
  enum : unsigned {
    InvalidDiscriminator =
      decltype(AbstractClosureExprBits)::InvalidDiscriminator
  };

  ArrayRef<ParameterList *> getParameterLists() {
    return parameterList ? parameterList : ArrayRef<ParameterList *>();
  }
  
  ArrayRef<const ParameterList *> getParameterLists() const {
    return parameterList ? parameterList : ArrayRef<const ParameterList *>();
  }

  /// \brief Retrieve the result type of this closure.
  Type getResultType() const;

  /// \brief Return whether this closure is throwing when fully applied.
  bool isBodyThrowing() const;

  /// Whether this closure consists of a single expression.
  bool hasSingleExpressionBody() const;

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_AbstractClosureExpr &&
           E->getKind() <= ExprKind::Last_AbstractClosureExpr;
  }

  static bool classof(const DeclContext *DC) {
    return DC->getContextKind() == DeclContextKind::AbstractClosureExpr;
  }

  using DeclContext::operator new;
  using Expr::dump;
};

/// SerializedAbstractClosureExpr - This represents what was originally an
/// AbstractClosureExpr during serialization. It is preserved only to maintain
/// the correct AST structure and remangling after deserialization.
class SerializedAbstractClosureExpr : public SerializedLocalDeclContext {
  const Type Ty;
  llvm::PointerIntPair<Type, 1> TypeAndImplicit;
  const unsigned Discriminator;

public:
  SerializedAbstractClosureExpr(Type Ty, bool Implicit, unsigned Discriminator,
                                DeclContext *Parent)
    : SerializedLocalDeclContext(LocalDeclContextKind::AbstractClosure,
                                 Parent),
      TypeAndImplicit(llvm::PointerIntPair<Type, 1>(Ty, Implicit)),
      Discriminator(Discriminator) {}

  Type getType() const {
    return TypeAndImplicit.getPointer();
  }

  unsigned getDiscriminator() const {
    return Discriminator;
  }

  bool isImplicit() const {
    return TypeAndImplicit.getInt();
  }

  static bool classof(const DeclContext *DC) {
    if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
      return LDC->getLocalDeclContextKind() ==
        LocalDeclContextKind::AbstractClosure;
    return false;
  }
};

/// \brief An explicit unnamed function expression, which can optionally have
/// named arguments.
///
/// \code
///     { $0 + $1 }
///     { a, b -> Int in a + b }
///     { (a : Int, b : Int) -> Int in a + b }
///     { [weak c] (a : Int) -> Int in a + c!.getFoo() }
/// \endcode
class ClosureExpr : public AbstractClosureExpr {

  /// The location of the "throws", if present.
  SourceLoc ThrowsLoc;
  
  /// \brief The location of the '->' denoting an explicit return type,
  /// if present.
  SourceLoc ArrowLoc;

  /// The location of the "in", if present.
  SourceLoc InLoc;

  /// \brief The explicitly-specified result type.
  TypeLoc ExplicitResultType;

  /// \brief The body of the closure, along with a bit indicating whether it
  /// was originally just a single expression.
  llvm::PointerIntPair<BraceStmt *, 1, bool> Body;
  
public:
  ClosureExpr(ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc,
              SourceLoc inLoc, TypeLoc explicitResultType,
              unsigned discriminator, DeclContext *parent)
    : AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
                          discriminator, parent),
      ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc),
      ExplicitResultType(explicitResultType),
      Body(nullptr) {
    setParameterList(params);
    ClosureExprBits.HasAnonymousClosureVars = false;
  }

  SourceRange getSourceRange() const;
  SourceLoc getStartLoc() const;
  SourceLoc getEndLoc() const;
  SourceLoc getLoc() const;

  BraceStmt *getBody() const { return Body.getPointer(); }
  void setBody(BraceStmt *S, bool isSingleExpression) {
    Body.setPointer(S);
    Body.setInt(isSingleExpression);
  }

  /// \brief Determine whether the parameters of this closure are actually
  /// anonymous closure variables.
  bool hasAnonymousClosureVars() const {
    return ClosureExprBits.HasAnonymousClosureVars;
  }

  /// \brief Set the parameters of this closure along with a flag indicating
  /// whether these parameters are actually anonymous closure variables.
  void setHasAnonymousClosureVars() {
    ClosureExprBits.HasAnonymousClosureVars = true;
  }
  
  /// \brief Determine whether this closure expression has an
  /// explicitly-specified result type.
  bool hasExplicitResultType() const { return ArrowLoc.isValid(); }

  
  /// \brief Retrieve the location of the \c '->' for closures with an
  /// explicit result type.
  SourceLoc getArrowLoc() const {
    assert(hasExplicitResultType() && "No arrow location");
    return ArrowLoc;
  }

  /// \brief Retrieve the location of the \c in for a closure that has it.
  SourceLoc getInLoc() const {
    return InLoc;
  }
  
  /// \brief Retrieve the location of the 'throws' for a closure that has it.
  SourceLoc getThrowsLoc() const {
    return ThrowsLoc;
  }

  /// \brief Retrieve the explicit result type location information.
  TypeLoc &getExplicitResultTypeLoc() {
    assert(hasExplicitResultType() && "No explicit result type");
    return ExplicitResultType;
  }
  
  void setExplicitResultType(SourceLoc arrowLoc, TypeLoc resultType) {
    ArrowLoc = arrowLoc;
    ExplicitResultType = resultType;
  }

  /// \brief Determine whether the closure has a single expression for its
  /// body.
  ///
  /// This will be true for closures such as, e.g.,
  /// \code
  ///   { $0 + 1 }
  /// \endcode
  ///
  /// or
  ///
  /// \code
  ///   { x, y in x > y }
  /// \endcode
  ///
  /// ... even if the closure has been coerced to return Void by the type
  /// checker. This function does not return true for empty closures.
  bool hasSingleExpressionBody() const {
    return Body.getInt();
  }

  /// \brief Retrieve the body for closure that has a single expression for
  /// its body.
  ///
  /// Only valid when \c hasSingleExpressionBody() is true.
  Expr *getSingleExpressionBody() const;

  /// \brief Set the body for a closure that has a single expression as its
  /// body.
  ///
  /// This routine cannot change whether a closure has a single expression as
  /// its body; it can only update that expression.
  void setSingleExpressionBody(Expr *NewBody);

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Closure;
  }
  static bool classof(const AbstractClosureExpr *E) {
    return E->getKind() == ExprKind::Closure;
  }
  static bool classof(const DeclContext *C) {
    return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C));
  }
};


/// \brief This is a closure of the contained subexpression that is formed
/// when a scalar expression is converted to @autoclosure function type.
/// For example:
/// \code
///   func f(x : @autoclosure () -> Int)
///   f(42)  // AutoclosureExpr convert from Int to ()->Int
/// \endcode
class AutoClosureExpr : public AbstractClosureExpr {
  BraceStmt *Body;

public:
  AutoClosureExpr(Expr *Body, Type ResultTy, unsigned Discriminator,
                  DeclContext *Parent)
      : AbstractClosureExpr(ExprKind::AutoClosure, ResultTy, /*Implicit=*/true,
                            Discriminator, Parent) {
    setBody(Body);
  }

  SourceRange getSourceRange() const;
  SourceLoc getStartLoc() const;
  SourceLoc getEndLoc() const;
  SourceLoc getLoc() const;

  BraceStmt *getBody() const { return Body; }
  void setBody(Expr *E);

  // Expose this to users.
  using DeclContext::setParent;

  /// Returns the body of the autoclosure as an \c Expr.
  ///
  /// The body of an autoclosure always consists of a single expression.
  Expr *getSingleExpressionBody() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::AutoClosure;
  }
  static bool classof(const AbstractClosureExpr *E) {
    return E->getKind() == ExprKind::AutoClosure;
  }
  static bool classof(const DeclContext *C) {
    return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C));
  }
};

/// DynamicTypeExpr - "type(of: base)" - Produces a metatype value.
///
/// The metatype value comes from evaluating an expression then retrieving the
/// metatype of the result.
class DynamicTypeExpr : public Expr {
  SourceLoc KeywordLoc;
  SourceLoc LParenLoc;
  Expr *Base;
  SourceLoc RParenLoc;

public:
  explicit DynamicTypeExpr(SourceLoc KeywordLoc, SourceLoc LParenLoc,
                           Expr *Base, SourceLoc RParenLoc, Type Ty)
    : Expr(ExprKind::DynamicType, /*Implicit=*/false, Ty),
      KeywordLoc(KeywordLoc), LParenLoc(LParenLoc), Base(Base),
      RParenLoc(RParenLoc) { }

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

  SourceLoc getLoc() const { return KeywordLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(KeywordLoc, RParenLoc);
  }
  
  SourceLoc getStartLoc() const {
    return KeywordLoc;
  }
  SourceLoc getEndLoc() const {
    return RParenLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DynamicType;
  }
};

/// An expression referring to an opaque object of a fixed type.
///
/// Opaque value expressions occur when a particular value within the AST
/// needs to be re-used without being re-evaluated or for a value that is
/// a placeholder. OpaqueValueExpr nodes are introduced by some other AST
/// node (say, a \c DynamicMemberRefExpr) and can only be used within the
/// subexpressions of that AST node.
class OpaqueValueExpr : public Expr {
  SourceLoc Loc;

public:
  explicit OpaqueValueExpr(SourceLoc Loc, Type Ty)
    : Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Loc(Loc) { }

  SourceRange getSourceRange() const { return Loc; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::OpaqueValue; 
  }
};

/// ApplyExpr - Superclass of various function calls, which apply an argument to
/// a function to get a result.
class ApplyExpr : public Expr {
  /// The function being called.
  Expr *Fn;

  /// The argument being passed to it, and whether it's a 'super' argument.
  llvm::PointerIntPair<Expr *, 1, bool> ArgAndIsSuper;

protected:
  ApplyExpr(ExprKind Kind, Expr *Fn, Expr *Arg, bool Implicit, Type Ty = Type())
    : Expr(Kind, Implicit, Ty), Fn(Fn), ArgAndIsSuper(Arg, false) {
    assert(classof((Expr*)this) && "ApplyExpr::classof out of date");
    ApplyExprBits.ThrowsIsSet = false;
  }

public:
  Expr *getFn() const { return Fn; }
  void setFn(Expr *e) { Fn = e; }
  Expr *getSemanticFn() const { return Fn->getSemanticsProvidingExpr(); }
  
  Expr *getArg() const { return ArgAndIsSuper.getPointer(); }
  void setArg(Expr *e) {
    assert((getKind() != ExprKind::Binary || isa<TupleExpr>(e)) &&
           "BinaryExprs must have a TupleExpr as the argument");
    ArgAndIsSuper = {e, ArgAndIsSuper.getInt()};
  }
  
  bool isSuper() const { return ArgAndIsSuper.getInt(); }
  void setIsSuper(bool super) {
    ArgAndIsSuper = {ArgAndIsSuper.getPointer(), super};
  }

  /// Has the type-checker set the 'throws' bit yet?
  ///
  /// In general, this should only be used for debugging purposes.
  bool isThrowsSet() const { return ApplyExprBits.ThrowsIsSet; }

  /// Does this application throw?  This is only meaningful after
  /// complete type-checking.
  ///
  /// If true, the function expression must have a throwing function
  /// type.  The converse is not true because of 'rethrows' functions.
  bool throws() const {
    assert(ApplyExprBits.ThrowsIsSet);
    return ApplyExprBits.Throws;
  }
  void setThrows(bool throws) {
    assert(!ApplyExprBits.ThrowsIsSet);
    ApplyExprBits.ThrowsIsSet = true;
    ApplyExprBits.Throws = throws;
  }

  ValueDecl *getCalledValue() const;

  /// Retrieve the argument labels provided at the call site.
  ///
  /// \param scratch Scratch space that will be used when the argument labels
  /// aren't already stored in the AST context.
  ArrayRef<Identifier>
  getArgumentLabels(SmallVectorImpl<Identifier> &scratch) const;

  /// Whether this application was written using a trailing closure.
  bool hasTrailingClosure() const;

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_ApplyExpr &&
           E->getKind() <= ExprKind::Last_ApplyExpr;
  }
};
  
/// CallExpr - Application of an argument to a function, which occurs
/// syntactically through juxtaposition with a TupleExpr whose
/// leading '(' is unspaced.
class CallExpr final : public ApplyExpr,
                       public TrailingCallArguments<CallExpr> {
  friend TrailingCallArguments;

  CallExpr(Expr *fn, Expr *arg, bool Implicit,
           ArrayRef<Identifier> argLabels,
           ArrayRef<SourceLoc> argLabelLocs,
           bool hasTrailingClosure,
           Type ty);

public:
  /// Create a new call expression.
  ///
  /// Note: prefer to use the entry points that separate out the arguments.
  static CallExpr *create(ASTContext &ctx, Expr *fn, Expr *arg,
                          ArrayRef<Identifier> argLabels,
                          ArrayRef<SourceLoc> argLabelLocs,
                          bool hasTrailingClosure,
                          bool implicit, Type type = Type());

  /// Create a new implicit call expression without any source-location
  /// information.
  ///
  /// \param fn The function being called
  /// \param args The call arguments, not including a trailing closure (if any).
  /// \param argLabels The argument labels, whose size must equal args.size(),
  /// or which must be empty.
  static CallExpr *createImplicit(ASTContext &ctx, Expr *fn,
                                  ArrayRef<Expr *> args,
                                  ArrayRef<Identifier> argLabels) {
    return create(ctx, fn, SourceLoc(), args, argLabels, { }, SourceLoc(),
                  /*trailingClosure=*/nullptr, /*implicit=*/true);
  }

  /// Create a new call expression.
  ///
  /// \param fn The function being called
  /// \param args The call arguments, not including a trailing closure (if any).
  /// \param argLabels The argument labels, whose size must equal args.size(),
  /// or which must be empty.
  /// \param argLabelLocs The locations of the argument labels, whose size must
  /// equal args.size() or which must be empty.
  /// \param trailingClosure The trailing closure, if any.
  static CallExpr *create(ASTContext &ctx, Expr *fn,
                          SourceLoc lParenLoc,
                          ArrayRef<Expr *> args,
                          ArrayRef<Identifier> argLabels,
                          ArrayRef<SourceLoc> argLabelLocs,
                          SourceLoc rParenLoc,
                          Expr *trailingClosure,
                          bool implicit);

  SourceLoc getStartLoc() const {
    SourceLoc fnLoc = getFn()->getStartLoc();
    return (fnLoc.isValid() ? fnLoc : getArg()->getStartLoc());
  }
  SourceLoc getEndLoc() const {
    SourceLoc argLoc = getArg()->getEndLoc();
    return (argLoc.isValid() ? argLoc : getFn()->getEndLoc());
  }
  
  SourceLoc getLoc() const { 
    SourceLoc FnLoc = getFn()->getLoc(); 
    return FnLoc.isValid() ? FnLoc : getArg()->getLoc();
  }

  unsigned getNumArguments() const { return CallExprBits.NumArgLabels; }
  bool hasArgumentLabelLocs() const { return CallExprBits.HasArgLabelLocs; }

  /// Whether this call with written with a trailing closure.
  bool hasTrailingClosure() const { return CallExprBits.HasTrailingClosure; }

  using TrailingCallArguments::getArgumentLabels;

  /// Retrieve the expression that direct represents the callee.
  ///
  /// The "direct" callee is the expression representing the callee
  /// after looking through top-level constructs that don't affect the
  /// identity of the callee, e.g., extra parentheses, optional
  /// unwrapping (?)/forcing (!), etc.
  Expr *getDirectCallee() const;

  static bool classof(const Expr *E) { return E->getKind() == ExprKind::Call; }
};
  
/// PrefixUnaryExpr - Prefix unary expressions like '!y'.
class PrefixUnaryExpr : public ApplyExpr {
public:
  PrefixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type())
    : ApplyExpr(ExprKind::PrefixUnary, Fn, Arg, /*Implicit=*/false, Ty) {}

  SourceLoc getLoc() const { return getFn()->getStartLoc(); }

  SourceLoc getStartLoc() const {
    return getFn()->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return getArg()->getEndLoc();
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::PrefixUnary;
  }
};

/// PostfixUnaryExpr - Prefix unary expressions like '!y'.
class PostfixUnaryExpr : public ApplyExpr {
public:
  PostfixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type())
    : ApplyExpr(ExprKind::PostfixUnary, Fn, Arg, /*Implicit=*/false, Ty) {}

  SourceLoc getLoc() const { return getFn()->getStartLoc(); }
  
  SourceLoc getStartLoc() const {
    return getArg()->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return getFn()->getEndLoc();
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::PostfixUnary;
  }
};
  
/// BinaryExpr - Infix binary expressions like 'x+y'.  The argument is always
/// an implicit tuple expression of the type expected by the function.
class BinaryExpr : public ApplyExpr {
public:
  BinaryExpr(Expr *Fn, TupleExpr *Arg, bool Implicit, Type Ty = Type())
    : ApplyExpr(ExprKind::Binary, Fn, Arg, Implicit, Ty) {}

  SourceLoc getLoc() const { return getFn()->getLoc(); }

  SourceRange getSourceRange() const { return getArg()->getSourceRange(); }
  SourceLoc getStartLoc() const { return getArg()->getStartLoc(); }
  SourceLoc getEndLoc() const { return getArg()->getEndLoc(); }

  TupleExpr *getArg() const { return cast<TupleExpr>(ApplyExpr::getArg()); }

  static bool classof(const Expr *E) { return E->getKind() == ExprKind::Binary;}
};

/// SelfApplyExpr - Abstract application that provides the 'self' pointer for
/// a method curried as (this : Self) -> (params) -> result.
///
/// The application of a curried method to 'self' semantically differs from
/// normal function application because the 'self' parameter can be implicitly
/// materialized from an rvalue.
class SelfApplyExpr : public ApplyExpr {
protected:
  SelfApplyExpr(ExprKind K, Expr *FnExpr, Expr *BaseExpr, Type Ty)
    : ApplyExpr(K, FnExpr, BaseExpr, FnExpr->isImplicit(), Ty) { }
  
public:
  Expr *getBase() const { return getArg(); }
  void setBase(Expr *E) { setArg(E); }

  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_SelfApplyExpr &&
           E->getKind() <= ExprKind::Last_SelfApplyExpr;
  }
};

/// DotSyntaxCallExpr - Refer to a method of a type, e.g. P.x.  'x'
/// is modeled as a DeclRefExpr or OverloadSetRefExpr on the method.
class DotSyntaxCallExpr : public SelfApplyExpr {
  SourceLoc DotLoc;
  
public:
  DotSyntaxCallExpr(Expr *FnExpr, SourceLoc DotLoc, Expr *BaseExpr,
                    Type Ty = Type())
    : SelfApplyExpr(ExprKind::DotSyntaxCall, FnExpr, BaseExpr, Ty),
      DotLoc(DotLoc) {
    setImplicit(DotLoc.isInvalid());
  }

  SourceLoc getDotLoc() const { return DotLoc; }

  SourceLoc getLoc() const {
    return isImplicit() ? getBase()->getStartLoc() : getFn()->getLoc();
  }
  SourceLoc getStartLoc() const {
    return getBase()->getStartLoc();
  }
  SourceLoc getEndLoc() const {
    return isImplicit() ? getBase()->getEndLoc() : getFn()->getEndLoc();
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DotSyntaxCall;
  }
};

/// ConstructorRefCallExpr - Refer to a constructor for a type P.  The
/// actual reference to function which returns the constructor is modeled
/// as a DeclRefExpr.
class ConstructorRefCallExpr : public SelfApplyExpr {
public:
  ConstructorRefCallExpr(Expr *FnExpr, Expr *BaseExpr, Type Ty = Type())
    : SelfApplyExpr(ExprKind::ConstructorRefCall, FnExpr, BaseExpr, Ty) {}

  SourceLoc getLoc() const { return getFn()->getLoc(); }
  SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
  SourceLoc getEndLoc() const { return getFn()->getEndLoc(); }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ConstructorRefCall;
  }
};
  
/// DotSyntaxBaseIgnoredExpr - When a.b resolves to something that does not need
/// the actual value of the base (e.g. when applied to a metatype, module, or
/// the base of a 'static' function) this expression node is created.  The
/// semantics are that its base is evaluated and discarded, then 'b' is
/// evaluated and returned as the result of the expression.
class DotSyntaxBaseIgnoredExpr : public Expr {
  Expr *LHS;
  SourceLoc DotLoc;
  Expr *RHS;
public:
  DotSyntaxBaseIgnoredExpr(Expr *LHS, SourceLoc DotLoc, Expr *RHS)
    : Expr(ExprKind::DotSyntaxBaseIgnored, /*Implicit=*/false, RHS->getType()),
      LHS(LHS), DotLoc(DotLoc), RHS(RHS) {
  }
  
  Expr *getLHS() const { return LHS; }
  void setLHS(Expr *E) { LHS = E; }
  SourceLoc getDotLoc() const { return DotLoc; }
  Expr *getRHS() const { return RHS; }
  void setRHS(Expr *E) { RHS = E; }

  SourceLoc getStartLoc() const {
    return DotLoc.isValid() ? LHS->getStartLoc() : RHS->getStartLoc();
  }
  SourceLoc getEndLoc() const { return RHS->getEndLoc(); }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::DotSyntaxBaseIgnored;
  }
};
  
/// \brief Represents an explicit cast, 'a as T' or 'a is T', where "T" is a
/// type, and "a" is the expression that will be converted to the type.
class ExplicitCastExpr : public Expr {
  Expr *SubExpr;
  SourceLoc AsLoc;
  TypeLoc CastTy;

protected:
  ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy,
                   Type resultTy)
    : Expr(kind, /*Implicit=*/false), SubExpr(sub), AsLoc(AsLoc), CastTy(castTy)
  {}

public:
  Expr *getSubExpr() const { return SubExpr; }
  
  /// Get the type syntactically spelled in the cast. For some forms of checked
  /// cast this is different from the result type of the expression.
  TypeLoc &getCastTypeLoc() { return CastTy; }

  /// Get the type syntactically spelled in the cast. For some forms of checked
  /// cast this is different from the result type of the expression.
  TypeLoc getCastTypeLoc() const { return CastTy; }

  void setSubExpr(Expr *E) { SubExpr = E; }

  SourceLoc getLoc() const {
    if (AsLoc.isValid())
      return AsLoc;

    return SubExpr->getLoc();
  }

  SourceLoc getAsLoc() const {
    return AsLoc;
  }

  SourceRange getSourceRange() const {
    SourceRange castTyRange = CastTy.getSourceRange();
    if (castTyRange.isInvalid())
      return SubExpr->getSourceRange();
    
    auto startLoc = SubExpr ? SubExpr->getStartLoc() : AsLoc;
    auto endLoc = castTyRange.End;
    
    return {startLoc, endLoc};
  }
  
  /// True if the node has been processed by SequenceExpr folding.
  bool isFolded() const { return SubExpr; }
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_ExplicitCastExpr &&
           E->getKind() <= ExprKind::Last_ExplicitCastExpr;
  }
};

/// Return a string representation of a CheckedCastKind.
StringRef getCheckedCastKindName(CheckedCastKind kind);
  
/// \brief Abstract base class for checked casts 'as' and 'is'. These represent
/// casts that can dynamically fail.
class CheckedCastExpr : public ExplicitCastExpr {
public:
  CheckedCastExpr(ExprKind kind,
                  Expr *sub, SourceLoc asLoc, TypeLoc castTy, Type resultTy)
    : ExplicitCastExpr(kind, sub, asLoc, castTy, resultTy)
  {
    CheckedCastExprBits.CastKind = unsigned(CheckedCastKind::Unresolved);
  }
  
  /// Return the semantic kind of cast performed.
  CheckedCastKind getCastKind() const {
    return CheckedCastKind(CheckedCastExprBits.CastKind);
  }
  void setCastKind(CheckedCastKind kind) {
    CheckedCastExprBits.CastKind = unsigned(kind);
  }
  
  /// True if the cast has been type-checked and its kind has been set.
  bool isResolved() const {
    return getCastKind() >= CheckedCastKind::First_Resolved;
  }
  
  static bool classof(const Expr *E) {
    return E->getKind() >= ExprKind::First_CheckedCastExpr
        && E->getKind() <= ExprKind::Last_CheckedCastExpr;
  }
};

/// Represents an explicit forced checked cast, which converts
/// from a value of some type to some specified subtype and fails dynamically
/// if the value does not have that type.
/// Spelled 'a as! T' and produces a value of type 'T'.
class ForcedCheckedCastExpr : public CheckedCastExpr {
  SourceLoc ExclaimLoc;

public:
  ForcedCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc exclaimLoc,
                        TypeLoc type)
    : CheckedCastExpr(ExprKind::ForcedCheckedCast,
                      sub, asLoc, type, type.getType()),
      ExclaimLoc(exclaimLoc)
  {
  }

  ForcedCheckedCastExpr(SourceLoc asLoc, SourceLoc exclaimLoc, TypeLoc type)
    : ForcedCheckedCastExpr(nullptr, asLoc, exclaimLoc, type)
  {
  }

  /// Retrieve the location of the '!' that follows 'as'.
  SourceLoc getExclaimLoc() const { return ExclaimLoc; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ForcedCheckedCast;
  }
};

/// \brief Represents an explicit conditional checked cast, which converts
/// from a type to some subtype and produces an Optional value, which will be
/// .Some(x) if the cast succeeds, or .None if the cast fails.
/// Spelled 'a as? T' and produces a value of type 'T?'.
class ConditionalCheckedCastExpr : public CheckedCastExpr {
  SourceLoc QuestionLoc;

public:
  ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc questionLoc,
                             TypeLoc type)
    : CheckedCastExpr(ExprKind::ConditionalCheckedCast,
                      sub, asLoc, type, type.getType()),
      QuestionLoc(questionLoc)
  { }
  
  ConditionalCheckedCastExpr(SourceLoc asLoc, SourceLoc questionLoc,
                             TypeLoc type)
    : ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc, type)
  {}

  /// Retrieve the location of the '?' that follows 'as'.
  SourceLoc getQuestionLoc() const { return QuestionLoc; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ConditionalCheckedCast;
  }
};

/// \brief Represents a runtime type check query, 'a is T', where 'T' is a type
/// and 'a' is a value of some related type. Evaluates to a Bool true if 'a' is
/// of the type and 'a as T' would succeed, false otherwise.
///
/// FIXME: We should support type queries with a runtime metatype value too.
class IsExpr : public CheckedCastExpr {
public:
  IsExpr(Expr *sub, SourceLoc isLoc, TypeLoc type)
    : CheckedCastExpr(ExprKind::Is,
                      sub, isLoc, type, Type())
  {}
  
  IsExpr(SourceLoc isLoc, TypeLoc type)
    : IsExpr(nullptr, isLoc, type)
  {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Is;
  }
};

/// \brief Represents an explicit coercion from a value to a specific type.
///
/// Spelled 'a as T' and produces a value of type 'T'.
class CoerceExpr : public ExplicitCastExpr {
public:
  CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
    : ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType())
  { }

  CoerceExpr(SourceLoc asLoc, TypeLoc type)
    : CoerceExpr(nullptr, asLoc, type)
  { }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Coerce;
  }
};

/// \brief Represents two expressions joined by the arrow operator '->', which
/// may be preceded by the 'throws' keyword. Currently this only exists to be
/// transformed into a FunctionTypeRepr by simplifyTypeExpr() in Sema.
class ArrowExpr : public Expr {
  SourceLoc ThrowsLoc;
  SourceLoc ArrowLoc;
  Expr *Args;
  Expr *Result;
public:
  ArrowExpr(Expr *Args, SourceLoc ThrowsLoc, SourceLoc ArrowLoc, Expr *Result)
    : Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
      ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(Args), Result(Result)
  { }

  ArrowExpr(SourceLoc ThrowsLoc, SourceLoc ArrowLoc)
    : Expr(ExprKind::Arrow, /*implicit=*/false, Type()),
      ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(nullptr), Result(nullptr)
  { }

  Expr *getArgsExpr() const { return Args; }
  void setArgsExpr(Expr *E) { Args = E; }
  Expr *getResultExpr() const { return Result; }
  void setResultExpr(Expr *E) { Result = E; }
  SourceLoc getThrowsLoc() const { return ThrowsLoc; }
  SourceLoc getArrowLoc() const { return ArrowLoc; }
  bool isFolded() const { return Args != nullptr && Result != nullptr; }

  SourceLoc getSourceLoc() const { return ArrowLoc; }
  SourceLoc getStartLoc() const {
    return isFolded() ? Args->getStartLoc() :
           ThrowsLoc.isValid() ? ThrowsLoc : ArrowLoc;
  }
  SourceLoc getEndLoc() const {
    return isFolded() ? Result->getEndLoc() : ArrowLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Arrow;
  }
};

/// \brief Represents the rebinding of 'self' in a constructor that calls out
/// to another constructor. The result of the subexpression is assigned to
/// 'self', and the expression returns void.
///
/// When a super.init or delegating initializer is invoked, 'self' is
/// reassigned to the result of the initializer (after being downcast in the
/// case of super.init).
///
/// This is needed for reference types with ObjC interop, where
/// reassigning 'self' is a supported feature, and for value type delegating
/// constructors, where the delegatee constructor is responsible for
/// initializing 'self' in-place before the delegator's logic executes.
class RebindSelfInConstructorExpr : public Expr {
  Expr *SubExpr;
  VarDecl *Self;
public:
  RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self);
  
  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
  
  VarDecl *getSelf() const { return Self; }
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *Sub) { SubExpr = Sub; }

  OtherConstructorDeclRefExpr *getCalledConstructor(bool &isChainToSuper) const;
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::RebindSelfInConstructor;
  }
};
  
/// \brief The conditional expression 'x ? y : z'.
class IfExpr : public Expr {
  Expr *CondExpr, *ThenExpr, *ElseExpr;
  SourceLoc QuestionLoc, ColonLoc;
public:
  IfExpr(Expr *CondExpr,
         SourceLoc QuestionLoc, Expr *ThenExpr,
         SourceLoc ColonLoc, Expr *ElseExpr,
         Type Ty = Type())
    : Expr(ExprKind::If, /*Implicit=*/false, Ty),
      CondExpr(CondExpr), ThenExpr(ThenExpr), ElseExpr(ElseExpr),
      QuestionLoc(QuestionLoc), ColonLoc(ColonLoc)
  {}
  
  IfExpr(SourceLoc QuestionLoc, Expr *ThenExpr, SourceLoc ColonLoc)
    : IfExpr(nullptr, QuestionLoc, ThenExpr, ColonLoc, nullptr)
  {}
  
  SourceLoc getLoc() const { return QuestionLoc; }
  SourceLoc getStartLoc() const {
    return (isFolded() ? CondExpr->getStartLoc() : QuestionLoc);
  }
  SourceLoc getEndLoc() const {
    return (isFolded() ? ElseExpr->getEndLoc() : ColonLoc);
  }
  SourceLoc getQuestionLoc() const { return QuestionLoc; }
  SourceLoc getColonLoc() const { return ColonLoc; }
  
  Expr *getCondExpr() const { return CondExpr; }
  void setCondExpr(Expr *E) { CondExpr = E; }
  
  Expr *getThenExpr() const { return ThenExpr; }
  void setThenExpr(Expr *E) { ThenExpr = E; }
  
  Expr *getElseExpr() const { return ElseExpr; }
  void setElseExpr(Expr *E) { ElseExpr = E; }
  
  /// True if the node has been processed by binary expression folding.
  bool isFolded() const { return CondExpr && ElseExpr; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::If;
  }
};

/// EnumIsCaseExpr - A boolean expression that is true if an enum value is of
/// a particular case.
class EnumIsCaseExpr : public Expr {
  Expr *SubExpr;
  EnumElementDecl *Element;
  
public:
  EnumIsCaseExpr(Expr *SubExpr, EnumElementDecl *Element)
    : Expr(ExprKind::EnumIsCase, /*implicit*/ true),
      SubExpr(SubExpr), Element(Element)
  {}
  
  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *e) { SubExpr = e; }
  
  EnumElementDecl *getEnumElement() const { return Element; }
  void setEnumElement(EnumElementDecl *elt) { Element = elt; }
  
  SourceLoc getLoc() const { return SubExpr->getLoc(); }
  SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
  SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::EnumIsCase;
  }
};

/// AssignExpr - A value assignment, like "x = y".
class AssignExpr : public Expr {
  Expr *Dest;
  Expr *Src;
  SourceLoc EqualLoc;

public:  
  AssignExpr(Expr *Dest, SourceLoc EqualLoc, Expr *Src, bool Implicit)
    : Expr(ExprKind::Assign, Implicit),
      Dest(Dest), Src(Src), EqualLoc(EqualLoc) {}
  
  AssignExpr(SourceLoc EqualLoc)
    : AssignExpr(nullptr, EqualLoc, nullptr, /*Implicit=*/false)
  {}

  Expr *getDest() const { return Dest; }
  void setDest(Expr *e) { Dest = e; }
  Expr *getSrc() const { return Src; }
  void setSrc(Expr *e) { Src = e; }
  
  SourceLoc getEqualLoc() const { return EqualLoc; }
  
  SourceLoc getLoc() const { return EqualLoc; }
  SourceLoc getStartLoc() const {
    if (!isFolded()) return EqualLoc;
    return ( Dest->getStartLoc().isValid()
           ? Dest->getStartLoc()
           : Src->getStartLoc());
  }
  SourceLoc getEndLoc() const {
    if (!isFolded()) return EqualLoc;
    return (Src->getEndLoc().isValid() ? Src->getEndLoc() : Dest->getEndLoc());
  }
  
  /// True if the node has been processed by binary expression folding.
  bool isFolded() const { return Dest && Src; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Assign;
  }
};

/// \brief A pattern production that has been parsed but hasn't been resolved
/// into a complete pattern. Name binding converts these into standalone pattern
/// nodes or raises an error if a pattern production appears in an invalid
/// position.
class UnresolvedPatternExpr : public Expr {
  Pattern *subPattern;

public:
  explicit UnresolvedPatternExpr(Pattern *subPattern)
    : Expr(ExprKind::UnresolvedPattern, /*Implicit=*/false),
      subPattern(subPattern) { }
  
  const Pattern *getSubPattern() const { return subPattern; }
  Pattern *getSubPattern() { return subPattern; }
  void setSubPattern(Pattern *p) { subPattern = p; }
  
  SourceRange getSourceRange() const;
  SourceLoc getStartLoc() const;
  SourceLoc getEndLoc() const;
  SourceLoc getLoc() const;
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::UnresolvedPattern;
  }
};


/// An editor placeholder (<#such as this#>) that occurred in an expression
/// context. If the placeholder is a typed one (see \c EditorPlaceholderData)
/// its type string will be typechecked and will be associated with this expr.
class EditorPlaceholderExpr : public Expr {
  Identifier Placeholder;
  SourceLoc Loc;
  TypeLoc PlaceholderTy;
  TypeRepr *ExpansionTyR;
  Expr *SemanticExpr;

public:
  EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc,
                        TypeLoc PlaceholderTy,
                        TypeRepr *ExpansionTyR)
    : Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false),
      Placeholder(Placeholder), Loc(Loc),
      PlaceholderTy(PlaceholderTy),
      ExpansionTyR(ExpansionTyR),
      SemanticExpr(nullptr) {
  }

  Identifier getPlaceholder() const { return Placeholder; }
  SourceRange getSourceRange() const { return Loc; }
  TypeLoc &getTypeLoc() { return PlaceholderTy; }
  TypeLoc getTypeLoc() const { return PlaceholderTy; }

  /// The TypeRepr to be considered for placeholder expansion.
  TypeRepr *getTypeForExpansion() const { return ExpansionTyR; }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::EditorPlaceholder;
  }

  Expr *getSemanticExpr() const { return SemanticExpr; }
  void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
};

/// Produces the Objective-C selector of the referenced method.
///
/// \code
/// #selector(UIView.insertSubview(_:aboveSubview:))
/// \endcode
class ObjCSelectorExpr : public Expr {
  SourceLoc KeywordLoc;
  SourceLoc LParenLoc;
  SourceLoc ModifierLoc;
  Expr *SubExpr;
  SourceLoc RParenLoc;
  AbstractFunctionDecl *ResolvedMethod = nullptr;

public:
  /// The kind of #selector expression this is.
  enum ObjCSelectorKind {
    Method, Getter, Setter
  };

  ObjCSelectorExpr(ObjCSelectorKind kind, SourceLoc keywordLoc,
                   SourceLoc lParenLoc, SourceLoc modifierLoc, Expr *subExpr,
                   SourceLoc rParenLoc)
    : Expr(ExprKind::ObjCSelector, /*Implicit=*/false),
      KeywordLoc(keywordLoc), LParenLoc(lParenLoc),
      ModifierLoc(modifierLoc), SubExpr(subExpr), RParenLoc(rParenLoc) {
    ObjCSelectorExprBits.SelectorKind = static_cast<unsigned>(kind);
  }

  Expr *getSubExpr() const { return SubExpr; }
  void setSubExpr(Expr *expr) { SubExpr = expr; }

  /// Whether this selector references a property getter or setter.
  bool isPropertySelector() const {
    switch (getSelectorKind()) {
    case ObjCSelectorKind::Method:
      return false;

    case ObjCSelectorKind::Getter:
    case ObjCSelectorKind::Setter:
      return true;
    }
  }

  /// Whether this selector references a method.
  bool isMethodSelector() const {
    switch (getSelectorKind()) {
    case ObjCSelectorKind::Method:
      return true;

    case ObjCSelectorKind::Getter:
    case ObjCSelectorKind::Setter:
      return false;
    }
  }

  /// Retrieve the Objective-C method to which this expression refers.
  AbstractFunctionDecl *getMethod() const { return ResolvedMethod; }

  /// Set the Objective-C method to which this expression refers.
  void setMethod(AbstractFunctionDecl *method) { ResolvedMethod = method; }

  SourceLoc getLoc() const { return KeywordLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(KeywordLoc, RParenLoc);
  }

  /// The location at which the getter: or setter: starts. Requires the selector
  /// to be a getter or setter.
  SourceLoc getModifierLoc() const {
    assert(isPropertySelector() && "Modifiers only set on property selectors");
    return ModifierLoc;
  }

  /// Retrieve the kind of the selector (method, getter, setter)
  ObjCSelectorKind getSelectorKind() const {
    return static_cast<ObjCSelectorKind>(ObjCSelectorExprBits.SelectorKind);
  }

  /// Override the selector kind.
  ///
  /// Used by the type checker to recover from ill-formed #selector
  /// expressions.
  void overrideObjCSelectorKind(ObjCSelectorKind newKind,
                                SourceLoc modifierLoc) {
    ObjCSelectorExprBits.SelectorKind = static_cast<unsigned>(newKind);
    ModifierLoc = modifierLoc;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ObjCSelector;
  }
};

/// Produces a keypath string for the given referenced property.
///
/// \code
/// #keyPath(Person.friends.firstName)
/// \endcode
class ObjCKeyPathExpr : public Expr {
  SourceLoc KeywordLoc;
  SourceLoc LParenLoc;
  SourceLoc RParenLoc;
  Expr *SemanticExpr = nullptr;

  /// A single stored component, which will be either an identifier or
  /// a resolved declaration.
  typedef llvm::PointerUnion<Identifier, ValueDecl *> StoredComponent;

  ObjCKeyPathExpr(SourceLoc keywordLoc, SourceLoc lParenLoc,
              ArrayRef<Identifier> names,
              ArrayRef<SourceLoc> nameLocs,
              SourceLoc rParenLoc);

  /// Retrieve a mutable version of the "components" array, for
  /// initialization purposes.
  MutableArrayRef<StoredComponent> getComponentsMutable() {
    return { reinterpret_cast<StoredComponent *>(this + 1), getNumComponents() };
  }

  /// Retrieve the "components" storage.
  ArrayRef<StoredComponent> getComponents() const {
    return { reinterpret_cast<StoredComponent const *>(this + 1),
             getNumComponents() };
  }

  /// Retrieve a mutable version of the name locations array, for
  /// initialization purposes.
  MutableArrayRef<SourceLoc> getNameLocsMutable() {
    if (!ObjCKeyPathExprBits.HaveSourceLocations) return { };

    auto mutableComponents = getComponentsMutable();
    return { reinterpret_cast<SourceLoc *>(mutableComponents.end()),
             mutableComponents.size() };
  }

public:
  /// Create a new #keyPath expression.
  ///
  /// \param nameLocs The locations of the names in the key-path,
  /// which must either have the same number of entries as \p names or
  /// must be empty.
  static ObjCKeyPathExpr *create(ASTContext &ctx,
                             SourceLoc keywordLoc, SourceLoc lParenLoc,
                             ArrayRef<Identifier> names,
                             ArrayRef<SourceLoc> nameLocs,
                             SourceLoc rParenLoc);

  SourceLoc getLoc() const { return KeywordLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(KeywordLoc, RParenLoc);
  }

  /// Retrieve the number of components in the key-path.
  unsigned getNumComponents() const {
    return ObjCKeyPathExprBits.NumComponents;
  }

  /// Retrieve's the name for the (i)th component;
  Identifier getComponentName(unsigned i) const;

  /// Retrieve's the declaration corresponding to the (i)th component,
  /// or null if this component has not yet been resolved.
  ValueDecl *getComponentDecl(unsigned i) const {
    return getComponents()[i].dyn_cast<ValueDecl *>();
  }

  /// Retrieve the location corresponding to the (i)th name.
  ///
  /// If no location information is available, returns an empty
  /// \c DeclNameLoc.
  SourceLoc getComponentNameLoc(unsigned i) const {
    if (!ObjCKeyPathExprBits.HaveSourceLocations) return { };

    auto components = getComponents();
    ArrayRef<SourceLoc> nameLocs(
        reinterpret_cast<SourceLoc const *>(components.end()),
        components.size());

    return nameLocs[i];
  }

  /// Retrieve the semantic expression, which will be \c NULL prior to
  /// type checking and a string literal after type checking.
  Expr *getSemanticExpr() const { return SemanticExpr; }

  /// Set the semantic expression.
  void setSemanticExpr(Expr *expr) { SemanticExpr = expr; }

  /// Resolve the given component to the given declaration.
  void resolveComponent(unsigned idx, ValueDecl *decl) {
    getComponentsMutable()[idx] = decl;
  }

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ObjCKeyPath;
  }
};


inline bool Expr::isInfixOperator() const {
  return isa<BinaryExpr>(this) || isa<IfExpr>(this) ||
         isa<AssignExpr>(this) || isa<ExplicitCastExpr>(this);
}

#undef SWIFT_FORWARD_SOURCE_LOCS_TO
  
} // end namespace swift

#endif
