//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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/TypeRepr.h"
#include "swift/AST/Availability.h"
#include "llvm/Support/TrailingObjects.h"
#include <utility>

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 certain kinds of checked cast that have specialized diagnostic
/// and/or code generation peephole behavior.
///
/// This enumeration should not have any semantic effect on the behavior of a
/// well-typed program, since the runtime can perform all casts that are
/// statically accepted.
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 checked cast with no known specific behavior.
  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 bridging conversion that always succeeds.
  BridgingCoercion,
  /// A bridging conversion that may fail, because there are multiple Swift
  /// value types that bridge to the same Cocoa object type.
  ///
  /// This kind is only used for Swift 3 compatibility diagnostics and is
  /// treated the same as 'BridgingCoercion' otherwise. In Swift 4 or later,
  /// any conversions with this kind show up as ValueCasts.
  Swift3BridgingDowncast,

  Last_CheckedCastKind = Swift3BridgingDowncast,
};

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 : 3;
    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 FunctionRefKind : 2;
  };
  enum { NumUnresolvedDeclRefExprBits = NumExprBits + 4 };
  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 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 KeyPathExprBitfields {
    friend class KeyPathExpr;
    unsigned : NumExprBits;

    /// Whether this is an ObjC stringified keypath.
    unsigned IsObjC : 1;
  };
  enum { NumKeyPathExprBits = NumExprBits + 2 };
  static_assert(NumKeyPathExprBits <= 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;
    BooleanLiteralExprBitfields BooleanLiteralExprBits;
    MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
    ObjectLiteralExprBitfields ObjectLiteralExprBits;
    AbstractClosureExprBitfields AbstractClosureExprBits;
    ClosureExprBitfields ClosureExprBits;
    BindOptionalExprBitfields BindOptionalExprBits;
    ApplyExprBitfields ApplyExprBits;
    CallExprBitfields CallExprBits;
    CheckedCastExprBitfields CheckedCastExprBits;
    CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
    TupleShuffleExprBitfields TupleShuffleExprBits;
    ObjCSelectorExprBitfields ObjCSelectorExprBits;
    KeyPathExprBitfields KeyPathExprBits;
  };

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(llvm::function_ref<Type(const Expr *)> getType =
                           [](const Expr *E) -> Type {
    return E->getType();
  }) 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(
      llvm::function_ref<Type(const Expr *)> getType =
          [](const Expr *E) -> Type { return E->getType(); }) 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,
                                 llvm::function_ref<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 false if this expression needs to be wrapped in parens when
  /// used inside of a any postfix expression, true otherwise.
  ///
  /// \param appendingPostfixOperator if the expression being
  /// appended is a postfix operator like '!' or '?'.
  bool canAppendPostfixExpression(bool appendingPostfixOperator = false) 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> {
  // We need to friend TrailingObjects twice here to work around an MSVC bug.
  // If we have two functions of the same name with the parameter
  // typename TrailingObjectsIdentifier::template OverloadToken<T> where T is
  // different for each function, then MSVC reports a "member function already
  // defined or declared" error, which is incorrect.
  using TrailingObjectsIdentifier = llvm::TrailingObjects<Derived, Identifier>;
  friend TrailingObjectsIdentifier;

  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 TrailingObjectsIdentifier::template OverloadToken<Identifier>)
      const {
    return asDerived().getNumArguments();
  }

  size_t numTrailingObjects(
      typename TrailingObjectsIdentifier::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,
               llvm::function_ref<void(Expr *, Type)> setType,
               llvm::function_ref<Type(const Expr *)> getType) 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;
  }

  SourceLoc getMinusLoc() const {
    return MinusLoc;
  }

  SourceLoc getDigitsLoc() const {
    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 UTF-8 constant string.
    UTF8ConstString,

    /// A UTF-16 constant string.
    UTF16ConstString,

    /// 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/Syntax/TokenKinds.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, llvm::function_ref<Type(const Expr *)> getType);

  /// 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 {
  /// \brief The declaration pointer.
  ConcreteDeclRef D;
  DeclNameLoc Loc;

public:
  DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit,
              AccessSemantics semantics = AccessSemantics::Ordinary,
              Type Ty = Type())
    : Expr(ExprKind::DeclRef, Implicit, Ty), D(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 {
    return D;
  }

  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(llvm::function_ref<bool(const Expr *)> hasType =
                           [](const Expr *E) -> bool { return !!E->getType(); },
                       llvm::function_ref<Type(const Expr *)> getType =
                           [](const Expr *E) -> Type {
                         return E->getType();
                       }) 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);

  
  /// Create a TypeExpr for a TypeDecl at the specified location.
  static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D,
                                 bool isImplicit);

  /// Create a TypeExpr for a member TypeDecl of the given parent TypeDecl.
  static TypeExpr *createForMemberDecl(SourceLoc ParentNameLoc,
                                       TypeDecl *Parent,
                                       SourceLoc NameLoc,
                                       TypeDecl *Decl);

  /// Create a TypeExpr for a member TypeDecl of the given parent IdentTypeRepr.
  static TypeExpr *createForMemberDecl(IdentTypeRepr *ParentTR,
                                       SourceLoc NameLoc,
                                       TypeDecl *Decl);

  /// Create a TypeExpr from an IdentTypeRepr with the given arguments applied
  /// at the specified location.
  ///
  /// Returns nullptr if the reference cannot be formed, which is a hack due
  /// to limitations in how we model generic typealiases.
  static TypeExpr *createForSpecializedDecl(IdentTypeRepr *ParentTR,
                                            ArrayRef<TypeRepr*> Args,
                                            SourceRange AngleLocs,
                                            ASTContext &C);

  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,
                        FunctionRefKind functionRefKind,
                        bool Implicit, Type Ty = Type())
      : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, functionRefKind,
                           Implicit, Ty),
        Loc(Loc) {
  }
  
  DeclNameLoc getNameLoc() const { return Loc; }
  SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
  SourceRange getSourceRange() const { return Loc.getSourceRange(); }

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

  /// 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,
         llvm::function_ref<Type(const Expr *)> getType =
             [](const Expr *E) -> Type { return E->getType(); });

  /// 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,
         llvm::function_ref<Type(const Expr *)> getType =
             [](const Expr *E) -> Type { return E->getType(); });

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

/// Subscripting expression that applies a keypath to a base.
class KeyPathApplicationExpr : public Expr {
  Expr *Base;
  Expr *KeyPath;
  SourceLoc LBracketLoc, RBracketLoc;
  
public:
  KeyPathApplicationExpr(Expr *base, SourceLoc lBracket, Expr *keyPath,
                         SourceLoc rBracket, Type ty, bool implicit)
    : Expr(ExprKind::KeyPathApplication, implicit, ty),
      Base(base), KeyPath(keyPath), LBracketLoc(lBracket), RBracketLoc(rBracket)
  {}
  
  SourceLoc getLoc() const { return LBracketLoc; }
  SourceLoc getStartLoc() const { return Base->getStartLoc(); }
  SourceLoc getEndLoc() const { return RBracketLoc; }
  
  Expr *getBase() const { return Base; }
  void setBase(Expr *E) { Base = E; }
  Expr *getKeyPath() const { return KeyPath; }
  void setKeyPath(Expr *E) { KeyPath = E; }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::KeyPathApplication;
  }
};

/// 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; }
  void setDepth(unsigned depth) {
    BindOptionalExprBits.Depth = 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 grants temporary escapability to a nonescaping
/// closure value.
///
/// This expression is formed by the type checker when a call to the
/// `withoutActuallyEscaping` declaration is made.
class MakeTemporarilyEscapableExpr : public Expr {
  Expr *NonescapingClosureValue;
  OpaqueValueExpr *EscapingClosureValue;
  Expr *SubExpr;
  SourceLoc NameLoc, LParenLoc, RParenLoc;

public:
  MakeTemporarilyEscapableExpr(SourceLoc NameLoc,
                               SourceLoc LParenLoc,
                               Expr *NonescapingClosureValue,
                               Expr *SubExpr,
                               SourceLoc RParenLoc,
                               OpaqueValueExpr *OpaqueValueForEscapingClosure,
                               bool implicit = false)
    : Expr(ExprKind::MakeTemporarilyEscapable, implicit, Type()),
      NonescapingClosureValue(NonescapingClosureValue),
      EscapingClosureValue(OpaqueValueForEscapingClosure),
      SubExpr(SubExpr),
      NameLoc(NameLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc)
  {}
  
  SourceLoc getStartLoc() const {
    return NameLoc;
  }
  SourceLoc getEndLoc() const {
    return RParenLoc;
  }
  
  SourceLoc getLoc() const {
    return NameLoc;
  }
  
  /// Retrieve the opaque value representing the escapable copy of the
  /// closure.
  OpaqueValueExpr *getOpaqueValue() const { return EscapingClosureValue; }
  
  /// Retrieve the nonescaping closure expression.
  Expr *getNonescapingClosureValue() const {
    return NonescapingClosureValue;
  }
  void setNonescapingClosureValue(Expr *e) {
    NonescapingClosureValue = e;
  }
  
  /// Retrieve the subexpression that has access to the escapable copy of the
  /// closure.
  Expr *getSubExpr() const {
    return SubExpr;
  }
  void setSubExpr(Expr *e) {
    SubExpr = e;
  }

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

/// \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,
                      Type subExprTy)
    : Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExprTy),
      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 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;
  }
};


/// \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(llvm::function_ref<Type(const Expr *)> getType =
                         [](const Expr *E) -> Type {
    return E->getType();
  }) 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));
  }
};

/// 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;
  ClosureExpr *closureBody;
public:
  CaptureListExpr(ArrayRef<CaptureListEntry> captureList,
                  ClosureExpr *closureBody)
    : Expr(ExprKind::CaptureList, /*Implicit=*/false, Type()),
      captureList(captureList), closureBody(closureBody) {
  }

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

  void setClosureBody(ClosureExpr *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;
  }
};

/// 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(),
         llvm::function_ref<Type(const Expr *)> getType =
             [](const Expr *E) -> Type { return E->getType(); });

  /// 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,
                 llvm::function_ref<Type(const Expr *)> getType =
                     [](const Expr *E) -> Type { return E->getType(); }) {
    return create(ctx, fn, SourceLoc(), args, argLabels, { }, SourceLoc(),
                  /*trailingClosure=*/nullptr, /*implicit=*/true, getType);
  }

  /// 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,
         llvm::function_ref<Type(const Expr *)> getType =
             [](const Expr *E) -> Type { return E->getType(); });

  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 directly 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, Type rhsTy)
    : Expr(ExprKind::DotSyntaxBaseIgnored, /*Implicit=*/false, rhsTy),
      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 {
    SourceLoc loc = EqualLoc;
    if (loc.isValid()) {
      return loc;
    }
    return getStartLoc();
  }
  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;
    }

    llvm_unreachable("Unhandled ObjcSelectorKind in switch.");
  }

  /// 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 KeyPathExpr : public Expr {
  SourceLoc StartLoc;
  SourceLoc LParenLoc;
  SourceLoc EndLoc;
  Expr *ObjCStringLiteralExpr = nullptr;

  // The parsed root of a Swift keypath (the section before an unusual dot, like
  // Foo.Bar in \Foo.Bar.?.baz).
  Expr *ParsedRoot = nullptr;
  // The parsed path of a Swift keypath (the section after an unusual dot, like
  // ?.baz in \Foo.Bar.?.baz).
  Expr *ParsedPath = nullptr;

  // The processed/resolved type, like Foo.Bar in \Foo.Bar.?.baz.
  TypeRepr *RootType = nullptr;

public:
  /// A single stored component, which will be one of:
  /// - an unresolved DeclName, which has to be type-checked
  /// - a resolved ValueDecl, referring to
  /// - a subscript index expression, which may or may not be resolved
  /// - an optional chaining, forcing, or wrapping component
  class Component {
  public:
    enum class Kind: unsigned {
      Invalid,
      UnresolvedProperty,
      UnresolvedSubscript,
      Property,
      Subscript,
      OptionalForce,
      OptionalChain,
      OptionalWrap
    };
  
  private:
    union DeclNameOrRef {
      DeclName UnresolvedName;
      ConcreteDeclRef ResolvedDecl;
      
      DeclNameOrRef() : UnresolvedName{} {}
      DeclNameOrRef(DeclName un) : UnresolvedName(un) {}
      DeclNameOrRef(ConcreteDeclRef rd) : ResolvedDecl(rd) {}
    } Decl;
    
    
    llvm::PointerIntPair<Expr *, 3, Kind> SubscriptIndexExprAndKind;
    Type ComponentType;
    SourceLoc Loc;
    
    explicit Component(DeclNameOrRef decl,
                       Expr *indexExpr,
                       Kind kind,
                       Type type,
                       SourceLoc loc)
      : Decl(decl), SubscriptIndexExprAndKind(indexExpr, kind),
        ComponentType(type), Loc(loc)
    {}
    
  public:
    Component() : Component({}, nullptr, Kind::Invalid, Type(), SourceLoc()) {}
    
    /// Create an unresolved component for a property.
    static Component forUnresolvedProperty(DeclName UnresolvedName,
                                           SourceLoc Loc) {
      return Component(UnresolvedName, nullptr,
                       Kind::UnresolvedProperty,
                       Type(),
                       Loc);
    }
    
    /// Create an unresolved component for a subscript.
    static Component forUnresolvedSubscript(ASTContext &ctx,
                                     SourceLoc lSquareLoc,
                                     ArrayRef<Expr *> indexArgs,
                                     ArrayRef<Identifier> indexArgLabels,
                                     ArrayRef<SourceLoc> indexArgLabelLocs,
                                     SourceLoc rSquareLoc,
                                     Expr *trailingClosure);
    
    /// Create an unresolved component for a subscript.
    ///
    /// You shouldn't add new uses of this overload; use the one that takes a
    /// list of index arguments.
    static Component forUnresolvedSubscriptWithPrebuiltIndexExpr(Expr *index,
                                                                 SourceLoc loc){
      
      return Component({}, index, Kind::UnresolvedSubscript, Type(), loc);
    }
    
    /// Create an unresolved optional force `!` component.
    static Component forUnresolvedOptionalForce(SourceLoc BangLoc) {
      return Component({}, nullptr,
                       Kind::OptionalForce,
                       Type(),
                       BangLoc);
    }
    
    /// Create an unresolved optional chain `?` component.
    static Component forUnresolvedOptionalChain(SourceLoc QuestionLoc) {
      return Component({}, nullptr,
                       Kind::OptionalChain,
                       Type(),
                       QuestionLoc);
    }
    
    /// Create a component for a property.
    static Component forProperty(ConcreteDeclRef property,
                                 Type propertyType,
                                 SourceLoc loc) {
      return Component(property, nullptr, Kind::Property,
                       propertyType,
                       loc);
    }
    
    /// Create a component for a subscript.
    static Component forSubscript(ASTContext &ctx,
                                  ConcreteDeclRef subscript,
                                  SourceLoc lSquareLoc,
                                  ArrayRef<Expr *> indexArgs,
                                  ArrayRef<Identifier> indexArgLabels,
                                  ArrayRef<SourceLoc> indexArgLabelLocs,
                                  SourceLoc rSquareLoc,
                                  Expr *trailingClosure,
                                  Type elementType);

    /// Create a component for a subscript.
    ///
    /// You shouldn't add new uses of this overload; use the one that takes a
    /// list of index arguments.
    static Component forSubscriptWithPrebuiltIndexExpr(
      ConcreteDeclRef subscript, Expr *index, Type elementType, SourceLoc loc) {
      return Component(subscript, index, Kind::Subscript, elementType, loc);
    }
    
    /// Create an optional-forcing `!` component.
    static Component forOptionalForce(Type forcedType, SourceLoc bangLoc) {
      return Component({}, nullptr, Kind::OptionalForce, forcedType,
                       bangLoc);
    }
    
    /// Create an optional-chaining `?` component.
    static Component forOptionalChain(Type unwrappedType,
                                      SourceLoc questionLoc) {
      return Component({}, nullptr, Kind::OptionalChain, unwrappedType,
                       questionLoc);
    }
    
    /// Create an optional-wrapping component. This doesn't have a surface
    /// syntax but may appear when the non-optional result of an optional chain
    /// is implicitly wrapped.
    static Component forOptionalWrap(Type wrappedType) {
      return Component({}, nullptr, Kind::OptionalWrap, wrappedType,
                       SourceLoc());
    }
    
    SourceLoc getLoc() const {
      return Loc;
    }
    
    Kind getKind() const {
      return SubscriptIndexExprAndKind.getInt();
    }
    
    bool isValid() const {
      return getKind() != Kind::Invalid;
    }
    
    bool isResolved() const {
      if (!getComponentType())
        return false;
      
      switch (getKind()) {
      case Kind::Subscript:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
      case Kind::Property:
        return true;
      
      case Kind::UnresolvedSubscript:
      case Kind::UnresolvedProperty:
      case Kind::Invalid:
        return false;
      }
    }
    
    Expr *getIndexExpr() const {
      switch (getKind()) {
      case Kind::Subscript:
      case Kind::UnresolvedSubscript:
        return SubscriptIndexExprAndKind.getPointer();
        
      case Kind::Invalid:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
      case Kind::UnresolvedProperty:
      case Kind::Property:
        llvm_unreachable("no index expr for this kind");
      }
    }
    
    DeclName getUnresolvedDeclName() const {
      switch (getKind()) {
      case Kind::UnresolvedProperty:
        return Decl.UnresolvedName;

      case Kind::Invalid:
      case Kind::Subscript:
      case Kind::UnresolvedSubscript:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
      case Kind::Property:
        llvm_unreachable("no unresolved name for this kind");
      }
    }
    
    ConcreteDeclRef getDeclRef() const {
      switch (getKind()) {
      case Kind::Property:
      case Kind::Subscript:
        return Decl.ResolvedDecl;

      case Kind::Invalid:
      case Kind::UnresolvedProperty:
      case Kind::UnresolvedSubscript:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
        llvm_unreachable("no decl ref for this kind");
      }
    }
    
    Type getComponentType() const {
      return ComponentType;
    }
    
    void setComponentType(Type t) {
      ComponentType = t;
    }
  };

private:
  llvm::MutableArrayRef<Component> Components;

public:
  /// Create a new #keyPath expression.
  KeyPathExpr(ASTContext &C,
              SourceLoc keywordLoc, SourceLoc lParenLoc,
              ArrayRef<Component> components,
              SourceLoc rParenLoc,
              bool isImplicit = false);

  KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath,
              bool isImplicit = false)
      : Expr(ExprKind::KeyPath, isImplicit), StartLoc(backslashLoc),
        EndLoc(parsedPath ? parsedPath->getEndLoc() : parsedRoot->getEndLoc()),
        ParsedRoot(parsedRoot), ParsedPath(parsedPath) {
    assert((parsedRoot || parsedPath) &&
           "keypath must have either root or path");
    KeyPathExprBits.IsObjC = false;
  }

  SourceLoc getLoc() const { return StartLoc; }
  SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); }

  /// Get the components array.
  ArrayRef<Component> getComponents() const {
    return Components;
  }
  MutableArrayRef<Component> getMutableComponents() {
    return Components;
  }
  
  /// Resolve the components of an un-type-checked expr. This copies over the
  /// components from the argument array.
  void resolveComponents(ASTContext &C,
                         ArrayRef<Component> resolvedComponents);
  
  /// Retrieve the string literal expression, which will be \c NULL prior to
  /// type checking and a string literal after type checking for an
  /// @objc key path.
  Expr *getObjCStringLiteralExpr() const {
    return ObjCStringLiteralExpr;
  }

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

  Expr *getParsedRoot() const {
    assert(!isObjC() && "cannot get parsed root of ObjC keypath");
    return ParsedRoot;
  }
  void setParsedRoot(Expr *root) {
    assert(!isObjC() && "cannot get parsed root of ObjC keypath");
    ParsedRoot = root;
  }

  Expr *getParsedPath() const {
    assert(!isObjC() && "cannot get parsed path of ObjC keypath");
    return ParsedPath;
  }
  void setParsedPath(Expr *path) {
    assert(!isObjC() && "cannot set parsed path of ObjC keypath");
    ParsedPath = path;
  }

  TypeRepr *getRootType() const {
    assert(!isObjC() && "cannot get root type of ObjC keypath");
    return RootType;
  }
  void setRootType(TypeRepr *rootType) {
    assert(!isObjC() && "cannot set root type of ObjC keypath");
    RootType = rootType;
  }

  /// True if this is an ObjC key path expression.
  bool isObjC() const { return KeyPathExprBits.IsObjC; }

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

/// Represents the unusual behavior of a . in a \ keypath expression, such as
/// \.[0] and \Foo.?.
class KeyPathDotExpr : public Expr {
  SourceLoc DotLoc;

public:
  KeyPathDotExpr(SourceLoc dotLoc)
      : Expr(ExprKind::KeyPathDot, /*isImplicit=*/true), DotLoc(dotLoc) {}

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

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

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
