//===--- 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 TypeImpact : 2;
  };
  enum { NumTupleShuffleExprBits = NumImplicitConversionExprBits + 2 };
  static_assert(NumTupleShuffleExprBits <= 32, "fits in an unsigned");

  class InOutToPointerExprBitfields {
    friend class InOutToPointerExpr;
    unsigned : NumImplicitConversionExprBits;
    unsigned IsNonAccessing : 1;
  };
  enum { NumInOutToPointerExprBits = NumImplicitConversionExprBits + 1 };
  static_assert(NumInOutToPointerExprBits <= 32, "fits in an unsigned");

  class ArrayToPointerExprBitfields {
    friend class ArrayToPointerExpr;
    unsigned : NumImplicitConversionExprBits;
    unsigned IsNonAccessing : 1;
  };
  enum { NumArrayToPointerExprBits = NumImplicitConversionExprBits + 1 };
  static_assert(NumArrayToPointerExprBits <= 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;
    InOutToPointerExprBitfields InOutToPointerExprBits;
    ArrayToPointerExprBitfields ArrayToPointerExprBits;
    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 whether the semantically meaningful content of this expression is
  /// an inout expression.
  ///
  /// FIXME(Remove InOutType): This should eventually sub-in for
  /// 'E->getType()->is<InOutType>()' in all cases.
  bool isSemanticallyInOutExpr() const {
    return getSemanticsProvidingExpr()->getKind() == ExprKind::InOut;
  }
  
  /// 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, bool Negative);

  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,
                          bool Negative);
  
  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");
  }

  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,
                                 DeclContext *DC,
                                 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:
  Expr *Base;
  ConcreteDeclRef Member;

  explicit DynamicLookupExpr(ExprKind kind, ConcreteDeclRef member, Expr *base)
    : Expr(kind, /*Implicit=*/false), Base(base), Member(member) { }

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

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

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

  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 {
  SourceLoc DotLoc;
  DeclNameLoc NameLoc;

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

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

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

  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 {
    auto end = Index->getEndLoc();
    return end.isValid() ? end : Base->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; }

  Expr *getSyntacticSubExpr() const {
    if (auto *ICE = dyn_cast<ImplicitConversionExpr>(SubExpr))
      return ICE->getSyntacticSubExpr();
    return SubExpr;
  }

  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) {
    InOutToPointerExprBits.IsNonAccessing = false;
  }

  /// Is this conversion "non-accessing"?  That is, is it only using the
  /// pointer for its identity, as opposed to actually accessing the memory?
  bool isNonAccessing() const {
    return InOutToPointerExprBits.IsNonAccessing;
  }
  void setNonAccessing(bool nonAccessing = true) {
    InOutToPointerExprBits.IsNonAccessing = nonAccessing;
  }

  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) {
    ArrayToPointerExprBits.IsNonAccessing = false;
  }
  
  /// Is this conversion "non-accessing"?  That is, is it only using the
  /// pointer for its identity, as opposed to actually accessing the memory?
  bool isNonAccessing() const {
    return ArrayToPointerExprBits.IsNonAccessing;
  }
  void setNonAccessing(bool nonAccessing = true) {
    ArrayToPointerExprBits.IsNonAccessing = nonAccessing;
  }

  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.
///
/// 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 TypeImpact {
    /// The source value is a tuple which is destructured and modified to
    /// create the result, which is a tuple.
    TupleToTuple,

    /// The source value is a tuple which is destructured and modified to
    /// create the result, which is a scalar because it has one element and
    /// no labels.
    TupleToScalar,

    /// The source value is an individual value (possibly one with tuple
    /// type) which is inserted into a particular position in the result,
    /// which is a tuple.
    ScalarToTuple

    // (TupleShuffleExprs are never created for a scalar-to-scalar conversion.)
  };

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, 
                   TypeImpact typeImpact,
                   ConcreteDeclRef defaultArgsOwner,
                   ArrayRef<unsigned> VariadicArgs,
                   Type VarargsArrayTy,
                   MutableArrayRef<Expr *> CallerDefaultArgs,
                   Type ty)
    : ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
      ElementMapping(elementMapping), VarargsArrayTy(VarargsArrayTy),
      DefaultArgsOwner(defaultArgsOwner), VariadicArgs(VariadicArgs),
      CallerDefaultArgs(CallerDefaultArgs)
  {
    TupleShuffleExprBits.TypeImpact = typeImpact;
  }

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

  /// What is the type impact of this shuffle?
  TypeImpact getTypeImpact() const {
    return TypeImpact(TupleShuffleExprBits.TypeImpact);
  }

  bool isSourceScalar() const {
    return getTypeImpact() == ScalarToTuple;
  }

  bool isResultScalar() const {
    return getTypeImpact() == TupleToScalar;
  }

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

/// ConditionalBridgeFromObjCExpr - Bridge a value from a non-native
/// representation.
class ConditionalBridgeFromObjCExpr : public ImplicitConversionExpr {
  ConcreteDeclRef Conversion;

public:
  ConditionalBridgeFromObjCExpr(Expr *subExpr, Type type,
                                ConcreteDeclRef conversion)
    : ImplicitConversionExpr(ExprKind::ConditionalBridgeFromObjC, subExpr, type),
      Conversion(conversion) {
  }

  /// \brief Retrieve the conversion function.
  ConcreteDeclRef getConversion() const {
    return Conversion;
  }

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

/// BridgeFromObjCExpr - Bridge a value from a non-native representation.
class BridgeFromObjCExpr : public ImplicitConversionExpr {
public:
  BridgeFromObjCExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::BridgeFromObjC, subExpr, type) {}

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

/// BridgeToObjCExpr - Bridge a value to a non-native representation.
class BridgeToObjCExpr : public ImplicitConversionExpr {
public:
  BridgeToObjCExpr(Expr *subExpr, Type type)
    : ImplicitConversionExpr(ExprKind::BridgeToObjC, subExpr, type) {}

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

/// 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 baseType,
            bool isImplicit = false);

  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;
    ArrayRef<Identifier> SubscriptLabels;
    ArrayRef<ProtocolConformanceRef> SubscriptHashableConformances;
    Type ComponentType;
    SourceLoc Loc;
    
    explicit Component(ASTContext *ctxForCopyingLabels,
                       DeclNameOrRef decl,
                       Expr *indexExpr,
                       ArrayRef<Identifier> subscriptLabels,
                       ArrayRef<ProtocolConformanceRef> indexHashables,
                       Kind kind,
                       Type type,
                       SourceLoc loc);
    
  public:
    Component()
      : Component(nullptr, {}, nullptr, {}, {}, Kind::Invalid,
                  Type(), SourceLoc())
    {}
    
    /// Create an unresolved component for a property.
    static Component forUnresolvedProperty(DeclName UnresolvedName,
                                           SourceLoc Loc) {
      return Component(nullptr,
                       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(
                                         ASTContext &context,
                                         Expr *index,
                                         ArrayRef<Identifier> subscriptLabels,
                                         SourceLoc loc) {
      
      return Component(&context,
                       {}, index, subscriptLabels, {},
                       Kind::UnresolvedSubscript,
                       Type(), loc);
    }
    
    /// Create an unresolved optional force `!` component.
    static Component forUnresolvedOptionalForce(SourceLoc BangLoc) {
      return Component(nullptr, {}, nullptr, {}, {},
                       Kind::OptionalForce,
                       Type(),
                       BangLoc);
    }
    
    /// Create an unresolved optional chain `?` component.
    static Component forUnresolvedOptionalChain(SourceLoc QuestionLoc) {
      return Component(nullptr, {}, nullptr, {}, {},
                       Kind::OptionalChain,
                       Type(),
                       QuestionLoc);
    }
    
    /// Create a component for a property.
    static Component forProperty(ConcreteDeclRef property,
                                 Type propertyType,
                                 SourceLoc loc) {
      return Component(nullptr, 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,
                              ArrayRef<ProtocolConformanceRef> indexHashables);

    /// 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, ArrayRef<Identifier> labels,
       Type elementType, SourceLoc loc,
       ArrayRef<ProtocolConformanceRef> indexHashables);
    
    /// Create an optional-forcing `!` component.
    static Component forOptionalForce(Type forcedType, SourceLoc bangLoc) {
      return Component(nullptr, {}, nullptr, {}, {},
                       Kind::OptionalForce, forcedType,
                       bangLoc);
    }
    
    /// Create an optional-chaining `?` component.
    static Component forOptionalChain(Type unwrappedType,
                                      SourceLoc questionLoc) {
      return Component(nullptr, {}, 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, {}, 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");
      }
    }

    ArrayRef<Identifier> getSubscriptLabels() const {
      switch (getKind()) {
      case Kind::Subscript:
      case Kind::UnresolvedSubscript:
        return SubscriptLabels;
        
      case Kind::Invalid:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
      case Kind::UnresolvedProperty:
      case Kind::Property:
        llvm_unreachable("no subscript labels for this kind");
      }
    }
    
    ArrayRef<ProtocolConformanceRef>
    getSubscriptIndexHashableConformances() const {
      switch (getKind()) {
      case Kind::Subscript:
        return SubscriptHashableConformances;
        
      case Kind::UnresolvedSubscript:
      case Kind::Invalid:
      case Kind::OptionalChain:
      case Kind::OptionalWrap:
      case Kind::OptionalForce:
      case Kind::UnresolvedProperty:
      case Kind::Property:
        llvm_unreachable("no hashable conformances for this kind");
      }
    }
    
    void setSubscriptIndexHashableConformances(
      ArrayRef<ProtocolConformanceRef> hashables);

    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
