//===--- 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 { return Index->getEndLoc(); }
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::Subscript;
  }
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  unsigned getDepth() const { return BindOptionalExprBits.Depth; }
  void setDepth(unsigned depth) {
    BindOptionalExprBits.Depth = depth;
  }

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

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

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

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

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

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

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

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

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

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

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

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

/// \brief An expression that grants temporary escapability to a nonescaping
/// closure value.
///
/// This expression is formed by the type checker when a call to the
/// `withoutActuallyEscaping` declaration is made.
class MakeTemporarilyEscapableExpr : public Expr {
  Expr *NonescapingClosureValue;
  OpaqueValueExpr *EscapingClosureValue;
  Expr *SubExpr;
  SourceLoc NameLoc, LParenLoc, RParenLoc;

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

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

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

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

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

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

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

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

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

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

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

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

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

public:
  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

  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
