//===--- 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 IsSpecialized : 1;
    unsigned FunctionRefKind : 2;
  };
  enum { NumUnresolvedDeclRefExprBits = NumExprBits + 5 };
  static_assert(NumUnresolvedDeclRefExprBits <= 32, "fits in an unsigned");

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

  class TupleExprBitfields {
    friend class TupleExpr;
    unsigned : NumExprBits;

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

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

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

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

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

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

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

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

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

  class BooleanLiteralExprBitfields {
    friend class BooleanLiteralExpr;
    unsigned : NumLiteralExprBits;

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

  class MagicIdentifierLiteralExprBitfields {
    friend class MagicIdentifierLiteralExpr;
    unsigned : NumLiteralExprBits;

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

  class ObjectLiteralExprBitfields {
    friend class ObjectLiteralExpr;
    unsigned : NumLiteralExprBits;

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

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

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

  class ClosureExprBitfields {
    friend class ClosureExpr;
    unsigned : NumAbstractClosureExprBits;

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

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

  enum { NumImplicitConversionExprBits = NumExprBits };

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

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

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

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

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

  class ObjCSelectorExprBitfields {
    friend class ObjCSelectorExpr;
    unsigned : NumExprBits;

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

  class 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;
    OverloadedDeclRefExprBitfields OverloadedDeclRefExprBits;
    BooleanLiteralExprBitfields BooleanLiteralExprBits;
    MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
    ObjectLiteralExprBitfields ObjectLiteralExprBits;
    AbstractClosureExprBitfields AbstractClosureExprBits;
    ClosureExprBitfields ClosureExprBits;
    BindOptionalExprBitfields BindOptionalExprBits;
    ApplyExprBitfields ApplyExprBits;
    CallExprBitfields CallExprBits;
    CheckedCastExprBitfields CheckedCastExprBits;
    CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
    TupleShuffleExprBitfields TupleShuffleExprBits;
    ObjCSelectorExprBitfields ObjCSelectorExprBits;
    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 true if directly appending a parameter list would be syntactically
  /// valid.
  ///
  /// Good examples: foo.bar, baz().
  /// Bad examples: 
  bool canAppendCallParentheses() const;

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

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

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

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

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

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

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

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

/// Helper class to capture trailing call argument labels and related
/// information, for expression nodes that involve argument labels, trailing
/// closures, etc.
template<typename Derived>
class TrailingCallArguments
    : private llvm::TrailingObjects<Derived, Identifier, SourceLoc> {
  // We need to friend TrailingObjects twice here to work around an MSVC bug.
  // If we have two functions of the same name with the parameter
  // typename TrailingObjectsIdentifier::template OverloadToken<T> where T is
  // different for each function, then MSVC reports a "member function already
  // defined or declared" error, which is incorrect.
  using TrailingObjectsIdentifier = llvm::TrailingObjects<Derived, Identifier>;
  friend TrailingObjectsIdentifier;

  using TrailingObjects = llvm::TrailingObjects<Derived, Identifier, SourceLoc>;
  friend TrailingObjects;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  SourceRange getSourceRange() const { return Range; }

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

/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
  LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
  
  // Make an exact copy of this one AST node.
  LiteralExpr *
  shallowClone(ASTContext &Ctx,
               llvm::function_ref<void(Expr *, Type)> setType,
               llvm::function_ref<Type(const Expr *)> getType) const;

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

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

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

  StringRef getDigitsText() const { return Val; }

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

  SourceLoc getMinusLoc() const {
    return MinusLoc;
  }

  SourceLoc getDigitsLoc() const {
    return DigitsLoc;
  }

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

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

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

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

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

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

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

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

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

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

    /// A UTF-16 string.
    UTF16,

    /// A UTF-8 constant string.
    UTF8ConstString,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  SourceRange getSourceRange() const { return Loc; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  StringRef getLiteralKindPlainName() const;

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

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

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

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

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

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

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

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

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

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

  void setSpecialized();

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

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

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

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

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

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

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

  // The type of a TypeExpr is always a metatype type.  Return the instance
  // type, ErrorType if an error, or null if not set yet.
  Type getInstanceType(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);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  DeclNameLoc getNameLoc() const { return Loc; }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  Expr *Base;
  Expr *Index;
  ConcreteDeclRef Member;

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

public:
  /// Create a dynamic subscript.
  ///
  /// Note: do not create new callers to this entry point; use the entry point
  /// that takes separate index arguments.
  static DynamicSubscriptExpr *
  create(ASTContext &ctx, Expr *base, Expr *index, ConcreteDeclRef decl,
         bool implicit,
         llvm::function_ref<Type(const Expr *)> getType =
             [](const Expr *E) -> Type { return E->getType(); });

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  SourceLoc getTryLoc() const { return TryLoc; }

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

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

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

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

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

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

  SourceLoc getExclaimLoc() const { return ExclaimLoc; }

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

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

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

  SourceLoc getQuestionLoc() const { return QuestionLoc; }

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

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

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

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

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

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

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

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

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

  SourceLoc LParenLoc;
  SourceLoc RParenLoc;
  unsigned NumElements;

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

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

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

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

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

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

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

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

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

  SourceRange getSourceRange() const;

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

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

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

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

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

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

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

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

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

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

  Expr *SemanticExpr = nullptr;

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

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

public:

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

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

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

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

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

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

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

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

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

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


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

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

  ConcreteDeclRef TheDecl;
  Expr *Base;
  Expr *Index;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

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

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

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

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

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

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

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

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

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

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

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

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

  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

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

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

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

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

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

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

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

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

public:
  SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)

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

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

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

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

  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InjectIntoOptional;
  }
};
  
/// Convert the address of an inout property to a pointer.
class InOutToPointerExpr : public ImplicitConversionExpr {
public:
  InOutToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::InOutToPointer;
  }
};
  
/// Convert the address of an array to a pointer.
class ArrayToPointerExpr : public ImplicitConversionExpr {
public:
  ArrayToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::ArrayToPointer;
  }
};
  
/// Convert the a string to a pointer referencing its encoded representation.
class StringToPointerExpr : public ImplicitConversionExpr {
public:
  StringToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::StringToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::StringToPointer;
  }
};
  
/// Convert a pointer to a different kind of pointer.
class PointerToPointerExpr : public ImplicitConversionExpr {
public:
  PointerToPointerExpr(Expr *subExpr, Type ty)
    : ImplicitConversionExpr(ExprKind::PointerToPointer, subExpr, ty) {}
  
  static bool classof(const Expr *E) {
    return E->getKind() == ExprKind::PointerToPointer;
  }
};

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

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

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

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

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

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

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

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

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

  MutableArrayRef<Expr *> CallerDefaultArgs;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  unsigned NumElements;

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

  /// \brief Retrieve the result type of this closure.
  Type getResultType() 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 {
      UnresolvedProperty,
      UnresolvedSubscript,
      Property,
      Subscript,
      OptionalForce,
      OptionalChain,
      OptionalWrap
    };
  
  private:
    union DeclNameOrRef {
      DeclName UnresolvedName;
      ConcreteDeclRef ResolvedDecl;
      
      DeclNameOrRef() : UnresolvedName{} {}
      DeclNameOrRef(DeclName un) : UnresolvedName(un) {}
      DeclNameOrRef(ConcreteDeclRef rd) : ResolvedDecl(rd) {}
    } Decl;
    
    
    llvm::PointerIntPair<Expr *, 3, Kind> SubscriptIndexExprAndKind;
    Type ComponentType;
    SourceLoc Loc;
    
    explicit Component(DeclNameOrRef decl,
                       Expr *indexExpr,
                       Kind kind,
                       Type type,
                       SourceLoc loc)
      : Decl(decl), SubscriptIndexExprAndKind(indexExpr, kind),
        ComponentType(type), Loc(loc)
    {}
    
  public:
    Component() : Component({}, nullptr, (Kind)0, Type(), SourceLoc()) {}
    
    /// Create an unresolved component for a property.
    static Component forUnresolvedProperty(DeclName UnresolvedName,
                                           SourceLoc Loc) {
      return Component(UnresolvedName, nullptr,
                       Kind::UnresolvedProperty,
                       Type(),
                       Loc);
    }
    
    /// Create an unresolved component for a subscript.
    static Component forUnresolvedSubscript(ASTContext &ctx,
                                     SourceLoc lSquareLoc,
                                     ArrayRef<Expr *> indexArgs,
                                     ArrayRef<Identifier> indexArgLabels,
                                     ArrayRef<SourceLoc> indexArgLabelLocs,
                                     SourceLoc rSquareLoc,
                                     Expr *trailingClosure);
    
    /// Create an unresolved component for a subscript.
    ///
    /// You shouldn't add new uses of this overload; use the one that takes a
    /// list of index arguments.
    static Component forUnresolvedSubscriptWithPrebuiltIndexExpr(Expr *index,
                                                                 SourceLoc loc){
      
      return Component({}, index, Kind::UnresolvedSubscript, Type(), loc);
    }
    
    /// Create an unresolved optional force `!` component.
    static Component forUnresolvedOptionalForce(SourceLoc BangLoc) {
      return Component({}, nullptr,
                       Kind::OptionalForce,
                       Type(),
                       BangLoc);
    }
    
    /// Create an unresolved optional chain `?` component.
    static Component forUnresolvedOptionalChain(SourceLoc QuestionLoc) {
      return Component({}, nullptr,
                       Kind::OptionalChain,
                       Type(),
                       QuestionLoc);
    }
    
    /// Create a component for a property.
    static Component forProperty(ConcreteDeclRef property,
                                 Type propertyType,
                                 SourceLoc loc) {
      return Component(property, nullptr, Kind::Property,
                       propertyType,
                       loc);
    }
    
    /// Create a component for a subscript.
    static Component forSubscript(ASTContext &ctx,
                                  ConcreteDeclRef subscript,
                                  SourceLoc lSquareLoc,
                                  ArrayRef<Expr *> indexArgs,
                                  ArrayRef<Identifier> indexArgLabels,
                                  ArrayRef<SourceLoc> indexArgLabelLocs,
                                  SourceLoc rSquareLoc,
                                  Expr *trailingClosure,
                                  Type elementType);

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

      case Kind::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::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
