//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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 Decl class and subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_DECL_H
#define SWIFT_DECL_H

#include "swift/AST/AccessScope.h"
#include "swift/AST/Attr.h"
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ClangNode.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DefaultArgumentKind.h"
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/StorageImpl.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Types.h"
#include "swift/AST/Witness.h"
#include "swift/Basic/ArrayRefView.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/OptionalEnum.h"
#include "swift/Basic/Range.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <type_traits>

namespace swift {
  enum class AccessSemantics : unsigned char;
  class AccessorDecl;
  class ApplyExpr;
  class AvailabilityContext;
  class GenericEnvironment;
  class ArchetypeType;
  class ASTContext;
  struct ASTNode;
  class ASTPrinter;
  class ASTWalker;
  class ConstructorDecl;
  class DestructorDecl;
  class DiagnosticEngine;
  class DynamicSelfType;
  class Type;
  class Expr;
  class DeclRefExpr;
  class ForeignErrorConvention;
  class LiteralExpr;
  class BraceStmt;
  class DeclAttributes;
  class GenericContext;
  class GenericSignature;
  class GenericTypeParamDecl;
  class GenericTypeParamType;
  class ModuleDecl;
  class EnumCaseDecl;
  class EnumElementDecl;
  class ParameterList;
  class ParameterTypeFlags;
  class Pattern;
  struct PrintOptions;
  struct PropertyWrapperBackingPropertyInfo;
  struct PropertyWrapperTypeInfo;
  struct PropertyWrapperMutability;
  class ProtocolDecl;
  class ProtocolType;
  struct RawComment;
  enum class ResilienceExpansion : unsigned;
  class TypeAliasDecl;
  class Stmt;
  class SubscriptDecl;
  class UnboundGenericType;
  class ValueDecl;
  class VarDecl;
  class OpaqueReturnTypeRepr;

enum class DeclKind : uint8_t {
#define DECL(Id, Parent) Id,
#define LAST_DECL(Id) Last_Decl = Id,
#define DECL_RANGE(Id, FirstId, LastId) \
  First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "swift/AST/DeclNodes.def"
};
enum : unsigned { NumDeclKindBits =
  countBitsUsed(static_cast<unsigned>(DeclKind::Last_Decl)) };


/// Fine-grained declaration kind that provides a description of the
/// kind of entity a declaration represents, as it would be used in
/// diagnostics.
///
/// For example, \c FuncDecl is a single declaration class, but it has
/// several descriptive entries depending on whether it is an
/// operator, global function, local function, method, (observing)
/// accessor, etc.
enum class DescriptiveDeclKind : uint8_t {
  Import,
  Extension,
  EnumCase,
  TopLevelCode,
  IfConfig,
  PoundDiagnostic,
  PatternBinding,
  Var,
  Param,
  Let,
  Property,
  StaticProperty,
  ClassProperty,
  InfixOperator,
  PrefixOperator,
  PostfixOperator,
  PrecedenceGroup,
  TypeAlias,
  GenericTypeParam,
  AssociatedType,
  Type,
  Enum,
  Struct,
  Class,
  Protocol,
  GenericEnum,
  GenericStruct,
  GenericClass,
  GenericType,
  Subscript,
  StaticSubscript,
  ClassSubscript,
  Constructor,
  Destructor,
  LocalFunction,
  GlobalFunction,
  OperatorFunction,
  Method,
  StaticMethod,
  ClassMethod,
  Getter,
  Setter,
  Addressor,
  MutableAddressor,
  ReadAccessor,
  ModifyAccessor,
  WillSet,
  DidSet,
  EnumElement,
  Module,
  MissingMember,
  Requirement,
  OpaqueResultType,
  OpaqueVarType
};

/// Keeps track of stage of circularity checking for the given protocol.
enum class CircularityCheck {
  /// Circularity has not yet been checked.
  Unchecked,
  /// We're currently checking circularity.
  Checking,
  /// Circularity has already been checked.
  Checked
};

/// Describes which spelling was used in the source for the 'static' or 'class'
/// keyword.
enum class StaticSpellingKind : uint8_t {
  None,
  KeywordStatic,
  KeywordClass,
};

/// Keeps track of whether an enum has cases that have associated values.
enum class AssociatedValueCheck {
  /// We have not yet checked.
  Unchecked,
  /// The enum contains no cases or all cases contain no associated values.
  NoAssociatedValues,
  /// The enum contains at least one case with associated values.
  HasAssociatedValues,
};

/// Diagnostic printing of \c StaticSpellingKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);

/// Encapsulation of the overload signature of a given declaration,
/// which is used to determine uniqueness of a declaration within a
/// given context.
///
/// Two definitions in the same context may not have the same overload
/// signature.
struct OverloadSignature {
  /// The full name of the declaration.
  DeclName Name;

  /// The kind of unary operator.
  UnaryOperatorKind UnaryOperator;

  /// Whether this is an instance member.
  unsigned IsInstanceMember : 1;

  /// Whether this is a variable.
  unsigned IsVariable : 1;

  /// Whether this is a function.
  unsigned IsFunction : 1;

  /// Whether this is a enum element.
  unsigned IsEnumElement : 1;

  /// Whether this is a nominal type.
  unsigned IsNominal : 1;

  /// Whether this is a type alias.
  unsigned IsTypeAlias : 1;

  /// Whether this signature is part of a protocol extension.
  unsigned InProtocolExtension : 1;

  /// Whether this signature is of a member defined in an extension of a generic
  /// type.
  unsigned InExtensionOfGenericType : 1;
  
  /// Whether this declaration has an opaque return type.
  unsigned HasOpaqueReturnType : 1;

  OverloadSignature()
      : UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
        IsVariable(false), IsFunction(false), InProtocolExtension(false),
        InExtensionOfGenericType(false), HasOpaqueReturnType(false) {}
};

/// Determine whether two overload signatures conflict.
///
/// \param sig1 The overload signature of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param skipProtocolExtensionCheck If \c true, members of protocol extensions
///        will be allowed to conflict with members of protocol declarations.
bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2,
                 bool skipProtocolExtensionCheck = false);

/// Determine whether two overload signatures and overload types conflict.
///
/// \param ctx The AST context.
/// \param sig1 The overload signature of the first declaration.
/// \param sig1Type The overload type of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param sig2Type The overload type of the second declaration.
/// \param wouldConflictInSwift5 If non-null, the referenced boolean will be set
///        to \c true iff the function returns \c false for this version of
///        Swift, but the given overloads will conflict in Swift 5 mode.
/// \param skipProtocolExtensionCheck If \c true, members of protocol extensions
///        will be allowed to conflict with members of protocol declarations.
bool conflicting(ASTContext &ctx,
                 const OverloadSignature& sig1, CanType sig1Type,
                 const OverloadSignature& sig2, CanType sig2Type,
                 bool *wouldConflictInSwift5 = nullptr,
                 bool skipProtocolExtensionCheck = false);

/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
public:
  enum class ValidationState {
    Unchecked,
    Checking,
    Checked,
  };

protected:
  union { uint64_t OpaqueBits;

  SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+2+1,
    Kind : bitmax(NumDeclKindBits,8),

    /// Whether this declaration is invalid.
    Invalid : 1,

    /// Whether this declaration was implicitly created, e.g.,
    /// an implicit constructor in a struct.
    Implicit : 1,

    /// Whether this declaration was mapped directly from a Clang AST.
    ///
    /// Use getClangNode() to retrieve the corresponding Clang AST.
    FromClang : 1,

    /// The validation state of this declaration.
    ValidationState : 2,

    /// Whether this declaration was added to the surrounding
    /// DeclContext of an active #if config clause.
    EscapedFromIfConfig : 1
  );

  SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16,
    /// Whether this pattern binding declares static variables.
    IsStatic : 1,

    /// Whether 'static' or 'class' was used.
    StaticSpelling : 2,

    : NumPadBits,

    /// The number of pattern binding declarations.
    NumPatternEntries : 16
  );
  
  SWIFT_INLINE_BITFIELD_FULL(EnumCaseDecl, Decl, 32,
    : NumPadBits,

    /// The number of tail-allocated element pointers.
    NumElements : 32
  );

  SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
    AlreadyInLookupTable : 1,

    /// Whether we have already checked whether this declaration is a 
    /// redeclaration.
    CheckedRedeclaration : 1,

    /// Whether the decl can be accessed by swift users; for instance,
    /// a.storage for lazy var a is a decl that cannot be accessed.
    IsUserAccessible : 1
  );

  SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
    /// Whether this property is a type property (currently unfortunately
    /// called 'static').
    IsStatic : 1
  );

  SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1,
    /// Encodes whether this is a 'let' binding.
    Introducer : 1,

    /// Whether this declaration was an element of a capture list.
    IsCaptureList : 1,

    /// Whether this vardecl has an initial value bound to it in a way
    /// that isn't represented in the AST with an initializer in the pattern
    /// binding.  This happens in cases like "for i in ...", switch cases, etc.
    HasNonPatternBindingInit : 1,

    /// Whether this is a property used in expressions in the debugger.
    /// It is up to the debugger to instruct SIL how to access this variable.
    IsDebuggerVar : 1,

    /// Whether this is the backing storage for a lazy property.
    IsLazyStorageProperty : 1,

    /// Whether this is the backing storage for a property wrapper.
    IsPropertyWrapperBackingProperty : 1
  );

  SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits,
    /// Whether we've computed the specifier yet.
    SpecifierComputed : 1,

    /// The specifier associated with this parameter.  This determines
    /// the storage semantics of the value e.g. mutability.
    Specifier : 2,

    /// Information about a symbolic default argument, like #file.
    defaultArgumentKind : NumDefaultArgumentKindBits
  );

  SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
    StaticSpelling : 2
  );
  SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1,
    /// \see AbstractFunctionDecl::BodyKind
    BodyKind : 3,

    /// Import as member status.
    IAMStatus : 8,

    /// Whether the function has an implicit 'self' parameter.
    HasImplicitSelfDecl : 1,

    /// Whether we are overridden later.
    Overridden : 1,

    /// Whether the function body throws.
    Throws : 1,

    /// Whether this member was synthesized as part of a derived
    /// protocol conformance.
    Synthesized : 1,

    /// Whether this member's body consists of a single expression.
    HasSingleExpressionBody : 1
  );

  SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2,
    /// Whether we've computed the 'static' flag yet.
    IsStaticComputed : 1,

    /// Whether this function is a 'static' method.
    IsStatic : 1,

    /// Whether 'static' or 'class' was used.
    StaticSpelling : 2,

    /// Whether we are statically dispatched even if overridable
    ForcedStaticDispatch : 1,

    /// Whether we've computed the 'self' access kind yet.
    SelfAccessComputed : 1,

    /// Backing bits for 'self' access kind.
    SelfAccess : 2
  );

  SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4+1+1,
    /// The kind of accessor this is.
    AccessorKind : 4,

    /// Whether the accessor is transparent.
    IsTransparent : 1,

    /// Whether we have computed the above.
    IsTransparentComputed : 1
  );

  SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+1+1,
    /// The body initialization kind (+1), or zero if not yet computed.
    ///
    /// This value is cached but is not serialized, because it is a property
    /// of the definition of the constructor that is useful only to semantic
    /// analysis and SIL generation.
    ComputedBodyInitKind : 3,

    /// Whether this constructor can fail, by building an Optional type.
    Failable : 1,

    /// Whether this initializer is a stub placed into a subclass to
    /// catch invalid delegations to a designated initializer not
    /// overridden by the subclass. A stub will always trap at runtime.
    ///
    /// Initializer stubs can be invoked from Objective-C or through
    /// the Objective-C runtime; there is no way to directly express
    /// an object construction that will invoke a stub.
    HasStubImplementation : 1
  );

  SWIFT_INLINE_BITFIELD_EMPTY(TypeDecl, ValueDecl);
  SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);

  SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
    : NumPadBits,

    Depth : 16,
    Index : 16
  );

  SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);

  SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1,
    /// Whether the typealias forwards perfectly to its underlying type.
    IsCompatibilityAlias : 1,
    /// Whether this was a global typealias synthesized by the debugger.
    IsDebuggerAlias : 1
  );

  SWIFT_INLINE_BITFIELD(NominalTypeDecl, GenericTypeDecl, 1+1,
    /// Whether we have already added implicitly-defined initializers
    /// to this declaration.
    AddedImplicitInitializers : 1,

    /// Whether there is are lazily-loaded conformances for this nominal type.
    HasLazyConformances : 1
  );

  SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+1+1+8+16,
    /// Whether the \c RequiresClass bit is valid.
    RequiresClassValid : 1,

    /// Whether this is a class-bounded protocol.
    RequiresClass : 1,

    /// Whether the \c ExistentialConformsToSelf bit is valid.
    ExistentialConformsToSelfValid : 1,

    /// Whether the existential of this protocol conforms to itself.
    ExistentialConformsToSelf : 1,

    /// Whether the \c ExistentialTypeSupported bit is valid.
    ExistentialTypeSupportedValid : 1,

    /// Whether the existential of this protocol can be represented.
    ExistentialTypeSupported : 1,

    /// True if the protocol has requirements that cannot be satisfied (e.g.
    /// because they could not be imported from Objective-C).
    HasMissingRequirements : 1,

    /// The stage of the circularity check for this protocol.
    Circularity : 2,

    /// Whether we've computed the inherited protocols list yet.
    InheritedProtocolsValid : 1,

    /// Whether we have a lazy-loaded requirement signature.
    HasLazyRequirementSignature : 1,

    : NumPadBits,

    /// If this is a compiler-known protocol, this will be a KnownProtocolKind
    /// value, plus one. Otherwise, it will be 0.
    KnownProtocol : 8, // '8' for speed. This only needs 6.

    /// The number of requirements in the requirement signature.
    NumRequirementsInSignature : 16
  );

  SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 2+1+2+1+7+1+1+1+1+1+1,
    /// The stage of the inheritance circularity check for this class.
    Circularity : 2,

    /// Whether this class inherits its superclass's convenience initializers.
    InheritsSuperclassInits : 1,

    /// \see ClassDecl::ForeignKind
    RawForeignKind : 2,

    /// \see ClassDecl::getEmittedMembers()
    HasForcedEmittedMembers : 1,     

    HasMissingDesignatedInitializers : 1,
    ComputedHasMissingDesignatedInitializers : 1,

    HasMissingVTableEntries : 1,
    ComputedHasMissingVTableEntries : 1,

    /// Whether instances of this class are incompatible
    /// with weak and unowned references.
    IsIncompatibleWithWeakReferences : 1
  );

  SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1,
    /// True if this struct has storage for fields that aren't accessible in
    /// Swift.
    HasUnreferenceableStorage : 1
  );
  
  SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+2+1,
    /// The stage of the raw type circularity check for this class.
    Circularity : 2,

    /// True if the enum has cases and at least one case has associated values.
    HasAssociatedValues : 2,
    /// True if the enum has at least one case that has some availability
    /// attribute.  A single bit because it's lazily computed along with the
    /// HasAssociatedValues bit.
    HasAnyUnavailableValues : 1
  );

  SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1,
    /// If the module was or is being compiled with `-enable-testing`.
    TestingEnabled : 1,

    /// If the module failed to load
    FailedToLoad : 1,

    /// Whether the module is resilient.
    ///
    /// \sa ResilienceStrategy
    RawResilienceStrategy : 1,

    /// Whether all imports have been resolved. Used to detect circular imports.
    HasResolvedImports : 1,

    /// If the module was or is being compiled with `-enable-private-imports`.
    PrivateImportsEnabled : 1,

    /// If the module is compiled with `-enable-implicit-dynamic`.
    ImplicitDynamicEnabled : 1,

    /// Whether the module is a system module.
    IsSystemModule : 1,

    /// Whether the module was imported from Clang (or, someday, maybe another
    /// language).
    IsNonSwiftModule : 1
  );

  SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
    /// Is this an assignment operator?
    IsAssignment : 1,

    /// The group's associativity.  A value of the Associativity enum.
    Associativity : 2
  );

  SWIFT_INLINE_BITFIELD(ImportDecl, Decl, 3+8,
    ImportKind : 3,

    /// The number of elements in this path.
    NumPathElements : 8
  );

  SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1,
    /// An encoding of the default and maximum access level for this extension.
    ///
    /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
    /// which works because the maximum is always greater than or equal to the
    /// default, and 'private' is never used. 0 represents an uncomputed value.
    DefaultAndMaxAccessLevel : 3,

    /// Whether there is are lazily-loaded conformances for this extension.
    HasLazyConformances : 1
  );

  SWIFT_INLINE_BITFIELD(IfConfigDecl, Decl, 1,
    /// Whether this decl is missing its closing '#endif'.
    HadMissingEnd : 1
  );

  SWIFT_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1,
    /// `true` if the diagnostic is an error, `false` if it's a warning.
    IsError : 1,

    /// Whether this diagnostic has already been emitted.
    HasBeenEmitted : 1
  );

  SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2,
    NumberOfFieldOffsetVectorEntries : 1,
    NumberOfVTableEntries : 2
  );

  } Bits;

  // Storage for the declaration attributes.
  DeclAttributes Attrs;
  
  /// The next declaration in the list of declarations within this
  /// member context.
  Decl *NextDecl = nullptr;
  
  friend class DeclIterator;
  friend class IterableDeclContext;
  friend class MemberLookupTable;

private:
  llvm::PointerUnion<DeclContext *, ASTContext *> Context;

  Decl(const Decl&) = delete;
  void operator=(const Decl&) = delete;
  SourceLoc getLocFromSource() const;

protected:

  Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
    : Context(context) {
    Bits.OpaqueBits = 0;
    Bits.Decl.Kind = unsigned(kind);
    Bits.Decl.Invalid = false;
    Bits.Decl.Implicit = false;
    Bits.Decl.FromClang = false;
    Bits.Decl.ValidationState = unsigned(ValidationState::Unchecked);
    Bits.Decl.EscapedFromIfConfig = false;
  }

  /// Get the Clang node associated with this declaration.
  ClangNode getClangNodeImpl() const;

  /// Set the Clang node associated with this declaration.
  void setClangNode(ClangNode Node);

  void updateClangNode(ClangNode node) {
    assert(hasClangNode());
    setClangNode(node);
  }
  friend class ClangImporter;

  DeclContext *getDeclContextForModule() const;

public:
  DeclKind getKind() const { return DeclKind(Bits.Decl.Kind); }

  /// Retrieve the name of the given declaration 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(DeclKind K);

  /// Retrieve the descriptive kind for this declaration.
  DescriptiveDeclKind getDescriptiveKind() const;

  /// Produce a name for the given descriptive declaration kind, which
  /// is suitable for use in diagnostics.
  static StringRef getDescriptiveKindName(DescriptiveDeclKind K);

  /// Whether swift users should be able to access this decl. For instance,
  /// var a.storage for lazy var a is an inaccessible decl. An inaccessible decl
  /// has to be implicit; but an implicit decl does not have to be inaccessible,
  /// for instance, self.
  bool isUserAccessible() const;

  /// Determine if the decl can have a comment.  If false, a comment will
  /// not be serialized.
  bool canHaveComment() const;

  LLVM_READONLY
  DeclContext *getDeclContext() const {
    if (auto dc = Context.dyn_cast<DeclContext *>())
      return dc;

    return getDeclContextForModule();
  }
  void setDeclContext(DeclContext *DC);

  /// Retrieve the innermost declaration context corresponding to this
  /// declaration, which will either be the declaration itself (if it's
  /// also a declaration context) or its declaration context.
  DeclContext *getInnermostDeclContext() const;

  /// Retrieve the module in which this declaration resides.
  LLVM_READONLY
  ModuleDecl *getModuleContext() const;

  /// getASTContext - Return the ASTContext that this decl lives in.
  LLVM_READONLY
  ASTContext &getASTContext() const {
    if (auto dc = Context.dyn_cast<DeclContext *>())
      return dc->getASTContext();

    return *Context.get<ASTContext *>();
  }

  const DeclAttributes &getAttrs() const {
    return Attrs;
  }

  DeclAttributes &getAttrs() {
    return Attrs;
  }

  /// Returns the starting location of the entire declaration.
  SourceLoc getStartLoc() const { return getSourceRange().Start; }

  /// Returns the end location of the entire declaration.
  SourceLoc getEndLoc() const { return getSourceRange().End; }

  /// Returns the preferred location when referring to declarations
  /// in diagnostics.
  SourceLoc getLoc() const;

  /// Returns the source range of the entire declaration.
  SourceRange getSourceRange() const;

  /// Returns the source range of the declaration including its attributes.
  SourceRange getSourceRangeIncludingAttrs() const;

  SourceLoc TrailingSemiLoc;

  LLVM_ATTRIBUTE_DEPRECATED(
      void dump() const LLVM_ATTRIBUTE_USED,
      "only for use within the debugger");
  LLVM_ATTRIBUTE_DEPRECATED(
      void dump(const char *filename) const LLVM_ATTRIBUTE_USED,
      "only for use within the debugger");
  void dump(raw_ostream &OS, unsigned Indent = 0) const;

  /// Pretty-print the given declaration.
  ///
  /// \param OS Output stream to which the declaration will be printed.
  void print(raw_ostream &OS) const;
  void print(raw_ostream &OS, const PrintOptions &Opts) const;

  /// Pretty-print the given declaration.
  ///
  /// \param Printer ASTPrinter object.
  ///
  /// \param Opts Options to control how pretty-printing is performed.
  ///
  /// \returns true if the declaration was printed or false if the print options
  /// required the declaration to be skipped from printing.
  bool print(ASTPrinter &Printer, const PrintOptions &Opts) const;

  /// Determine whether this declaration should be printed when
  /// encountered in its declaration context's list of members.
  bool shouldPrintInContext(const PrintOptions &PO) const;

  bool walk(ASTWalker &walker);

  /// Return whether this declaration has been determined invalid.
  bool isInvalid() const { return Bits.Decl.Invalid; }
  
  /// Mark this declaration invalid.
  void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; }

  /// Determine whether this declaration was implicitly generated by the
  /// compiler (rather than explicitly written in source code).
  bool isImplicit() const { return Bits.Decl.Implicit; }

  /// Mark this declaration as implicit.
  void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; }

  /// Get the validation state.
  ValidationState getValidationState() const {
    return ValidationState(Bits.Decl.ValidationState);
  }

private:
  friend class DeclValidationRAII;

  /// Set the validation state.
  void setValidationState(ValidationState VS) {
    assert(VS > getValidationState() && "Validation is unidirectional");
    Bits.Decl.ValidationState = unsigned(VS);
  }

public:
  /// Whether the declaration is in the middle of validation or not.
  bool isBeingValidated() const {
    switch (getValidationState()) {
    case ValidationState::Unchecked:
    case ValidationState::Checked:
      return false;
    case ValidationState::Checking:
      return true;
    }
    llvm_unreachable("Unknown ValidationState");
  }

  bool hasValidationStarted() const {
    return getValidationState() > ValidationState::Unchecked;
  }

  bool escapedFromIfConfig() const {
    return Bits.Decl.EscapedFromIfConfig;
  }

  void setEscapedFromIfConfig(bool Escaped) {
    Bits.Decl.EscapedFromIfConfig = Escaped;
  }

  /// \returns the unparsed comment attached to this declaration.
  RawComment getRawComment() const;

  Optional<StringRef> getGroupName() const;

  Optional<StringRef> getSourceFileName() const;

  Optional<unsigned> getSourceOrder() const;

  /// \returns the brief comment attached to this declaration.
  StringRef getBriefComment() const;

  /// Returns true if there is a Clang AST node associated
  /// with self.
  bool hasClangNode() const {
    return Bits.Decl.FromClang;
  }

  /// Retrieve the Clang AST node from which this declaration was
  /// synthesized, if any.
  LLVM_READONLY
  ClangNode getClangNode() const {
    if (!Bits.Decl.FromClang)
      return ClangNode();

    return getClangNodeImpl();
  }

  /// Retrieve the Clang declaration from which this declaration was
  /// synthesized, if any.
  LLVM_READONLY
  const clang::Decl *getClangDecl() const {
    if (!Bits.Decl.FromClang)
      return nullptr;

    return getClangNodeImpl().getAsDecl();
  }

  /// Retrieve the Clang macro from which this declaration was
  /// synthesized, if any.
  LLVM_READONLY
  const clang::MacroInfo *getClangMacro() {
    if (!Bits.Decl.FromClang)
      return nullptr;

    return getClangNodeImpl().getAsMacro();
  }

  /// Return the GenericContext if the Decl has one.
  LLVM_READONLY
  const GenericContext *getAsGenericContext() const;

  bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;

  AvailabilityContext getAvailabilityForLinkage() const;

  /// Whether this declaration or one of its outer contexts has the
  /// @_weakLinked attribute.
  bool isAlwaysWeakImported() const;

  /// Whether this declaration is weak-imported from the given module,
  /// either because of the presence of the @_weakLinked attribute, or
  /// because of availability.
  ///
  /// Note that \p fromModule should either be the "main module" or
  /// nullptr. (This is because when it is non-null, we query the
  /// current deployment target, and not the deployment target that
  /// the module was built with.)
  ///
  /// If \p fromModule is the main module, this returns false when the
  /// declaration is part of the main module, or if the declaration is
  /// at least as available as the current deployment target.
  ///
  /// If \p fromModule is null, we instead return true if the
  /// declaration is meant to be weak linked with _some_ deployment
  /// target; that is, the presence of the @_weakLinked attribute or
  /// any kind of availability is enough, irrespective of the current
  /// deployment target.
  bool isWeakImported(ModuleDecl *fromModule) const;

  /// Returns true if the nature of this declaration allows overrides.
  /// Note that this does not consider whether it is final or whether
  /// the class it's on is final.
  ///
  /// If this returns true, the decl can be safely casted to ValueDecl.
  bool isPotentiallyOverridable() const;

  /// Emit a diagnostic tied to this declaration.
  template<typename ...ArgTypes>
  InFlightDiagnostic diagnose(
      Diag<ArgTypes...> ID,
      typename detail::PassArgument<ArgTypes>::type... Args) const {
    return getDiags().diagnose(this, ID, std::move(Args)...);
  }

  /// Retrieve the diagnostic engine for diagnostics emission.
  LLVM_READONLY
  DiagnosticEngine &getDiags() const;

  // Make vanilla new/delete illegal for Decls.
  void *operator new(size_t Bytes) = delete;
  void operator delete(void *Data) SWIFT_DELETE_OPERATOR_DELETED;

  // Only allow allocation of Decls using the allocator in ASTContext
  // or by doing a placement new.
  void *operator new(size_t Bytes, const ASTContext &C,
                     unsigned Alignment = alignof(Decl));
  void *operator new(size_t Bytes, void *Mem) { 
    assert(Mem); 
    return Mem; 
  }
};

/// Use RAII to track Decl validation progress and non-reentrancy.
class DeclValidationRAII {
  Decl *D;

public:
  DeclValidationRAII(const DeclValidationRAII &) = delete;
  DeclValidationRAII(DeclValidationRAII &&) = delete;
  void operator =(const DeclValidationRAII &) = delete;
  void operator =(DeclValidationRAII &&) = delete;

  DeclValidationRAII(Decl *decl) : D(decl) {
    D->setValidationState(Decl::ValidationState::Checking);
  }

  ~DeclValidationRAII() {
    D->setValidationState(Decl::ValidationState::Checked);
  }
};

/// Allocates memory for a Decl with the given \p baseSize. If necessary,
/// it includes additional space immediately preceding the Decl for a ClangNode.
/// \note \p baseSize does not need to include space for a ClangNode if
/// requested -- the necessary space will be added automatically.
template <typename DeclTy, typename AllocatorTy>
void *allocateMemoryForDecl(AllocatorTy &allocator, size_t baseSize,
                            bool includeSpaceForClangNode) {
  static_assert(alignof(DeclTy) >= sizeof(void *),
                "A pointer must fit in the alignment of the DeclTy!");

  size_t size = baseSize;
  if (includeSpaceForClangNode)
    size += alignof(DeclTy);

  void *mem = allocator.Allocate(size, alignof(DeclTy));
  if (includeSpaceForClangNode)
    mem = reinterpret_cast<char *>(mem) + alignof(DeclTy);
  return mem;
}

enum class RequirementReprKind : unsigned {
  /// A type bound T : P, where T is a type that depends on a generic
  /// parameter and P is some type that should bound T, either as a concrete
  /// supertype or a protocol to which T must conform.
  TypeConstraint,

  /// A same-type requirement T == U, where T and U are types that shall be
  /// equivalent.
  SameType,

  /// A layout bound T : L, where T is a type that depends on a generic
  /// parameter and L is some layout specification that should bound T.
  LayoutConstraint,

  // Note: there is code that packs this enum in a 2-bit bitfield.  Audit users
  // when adding enumerators.
};

/// A single requirement in a 'where' clause, which places additional
/// restrictions on the generic parameters or associated types of a generic
/// function, type, or protocol.
///
/// This always represents a requirement spelled in the source code.  It is
/// never generated implicitly.
///
/// \c GenericParamList assumes these are POD-like.
class RequirementRepr {
  SourceLoc SeparatorLoc;
  RequirementReprKind Kind : 2;
  bool Invalid : 1;
  TypeLoc FirstType;

  /// The second element represents the right-hand side of the constraint.
  /// It can be e.g. a type or a layout constraint.
  union {
    TypeLoc SecondType;
    LayoutConstraintLoc SecondLayout;
  };

  /// Set during deserialization; used to print out the requirements accurately
  /// for the generated interface.
  StringRef AsWrittenString;

  RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                  TypeLoc FirstType, TypeLoc SecondType)
    : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
      FirstType(FirstType), SecondType(SecondType) { }

  RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                  TypeLoc FirstType, LayoutConstraintLoc SecondLayout)
    : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
      FirstType(FirstType), SecondLayout(SecondLayout) { }

  void printImpl(ASTPrinter &OS, bool AsWritten) const;

public:
  /// Construct a new type-constraint requirement.
  ///
  /// \param Subject The type that must conform to the given protocol or
  /// composition, or be a subclass of the given class type.
  /// \param ColonLoc The location of the ':', or an invalid location if
  /// this requirement was implied.
  /// \param Constraint The protocol or protocol composition to which the
  /// subject must conform, or superclass from which the subject must inherit.
  static RequirementRepr getTypeConstraint(TypeLoc Subject,
                                           SourceLoc ColonLoc,
                                           TypeLoc Constraint) {
    return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
  }

  /// Construct a new same-type requirement.
  ///
  /// \param FirstType The first type.
  /// \param EqualLoc The location of the '==' in the same-type constraint, or
  /// an invalid location if this requirement was implied.
  /// \param SecondType The second type.
  static RequirementRepr getSameType(TypeLoc FirstType,
                                     SourceLoc EqualLoc,
                                     TypeLoc SecondType) {
    return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
  }

  /// Construct a new layout-constraint requirement.
  ///
  /// \param Subject The type that must conform to the given layout 
  /// requirement.
  /// \param ColonLoc The location of the ':', or an invalid location if
  /// this requirement was implied.
  /// \param Layout The layout requirement to which the
  /// subject must conform.
  static RequirementRepr getLayoutConstraint(TypeLoc Subject,
                                             SourceLoc ColonLoc,
                                             LayoutConstraintLoc Layout) {
    return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
            Layout};
  }

  /// Determine the kind of requirement
  RequirementReprKind getKind() const { return Kind; }

  /// Determine whether this requirement is invalid.
  bool isInvalid() const { return Invalid; }

  /// Mark this requirement invalid.
  void setInvalid() { Invalid = true; }

  /// For a type-bound requirement, return the subject of the
  /// conformance relationship.
  Type getSubject() const {
    assert(getKind() == RequirementReprKind::TypeConstraint ||
           getKind() == RequirementReprKind::LayoutConstraint);
    return FirstType.getType();
  }

  TypeRepr *getSubjectRepr() const {
    assert(getKind() == RequirementReprKind::TypeConstraint ||
           getKind() == RequirementReprKind::LayoutConstraint);
    return FirstType.getTypeRepr();
  }

  TypeLoc &getSubjectLoc() {
    assert(getKind() == RequirementReprKind::TypeConstraint ||
           getKind() == RequirementReprKind::LayoutConstraint);
    return FirstType;
  }

  const TypeLoc &getSubjectLoc() const {
    assert(getKind() == RequirementReprKind::TypeConstraint ||
           getKind() == RequirementReprKind::LayoutConstraint);
    return FirstType;
  }

  /// For a type-bound requirement, return the protocol or to which
  /// the subject conforms or superclass it inherits.
  Type getConstraint() const {
    assert(getKind() == RequirementReprKind::TypeConstraint);
    return SecondType.getType();
  }

  TypeRepr *getConstraintRepr() const {
    assert(getKind() == RequirementReprKind::TypeConstraint);
    return SecondType.getTypeRepr();
  }

  TypeLoc &getConstraintLoc() {
    assert(getKind() == RequirementReprKind::TypeConstraint);
    return SecondType;
  }

  const TypeLoc &getConstraintLoc() const {
    assert(getKind() == RequirementReprKind::TypeConstraint);
    return SecondType;
  }

  LayoutConstraint getLayoutConstraint() const {
    assert(getKind() == RequirementReprKind::LayoutConstraint);
    return SecondLayout.getLayoutConstraint();
  }

  LayoutConstraintLoc &getLayoutConstraintLoc() {
    assert(getKind() == RequirementReprKind::LayoutConstraint);
    return SecondLayout;
  }

  const LayoutConstraintLoc &getLayoutConstraintLoc() const {
    assert(getKind() == RequirementReprKind::LayoutConstraint);
    return SecondLayout;
  }

  /// Retrieve the first type of a same-type requirement.
  Type getFirstType() const {
    assert(getKind() == RequirementReprKind::SameType);
    return FirstType.getType();
  }

  TypeRepr *getFirstTypeRepr() const {
    assert(getKind() == RequirementReprKind::SameType);
    return FirstType.getTypeRepr();
  }

  TypeLoc &getFirstTypeLoc() {
    assert(getKind() == RequirementReprKind::SameType);
    return FirstType;
  }

  const TypeLoc &getFirstTypeLoc() const {
    assert(getKind() == RequirementReprKind::SameType);
    return FirstType;
  }

  /// Retrieve the second type of a same-type requirement.
  Type getSecondType() const {
    assert(getKind() == RequirementReprKind::SameType);
    return SecondType.getType();
  }

  TypeRepr *getSecondTypeRepr() const {
    assert(getKind() == RequirementReprKind::SameType);
    return SecondType.getTypeRepr();
  }

  TypeLoc &getSecondTypeLoc() {
    assert(getKind() == RequirementReprKind::SameType);
    return SecondType;
  }

  const TypeLoc &getSecondTypeLoc() const {
    assert(getKind() == RequirementReprKind::SameType);
    return SecondType;
  }

  /// Retrieve the location of the ':' or '==' in an explicitly-written
  /// conformance or same-type requirement respectively.
  SourceLoc getSeparatorLoc() const {
    return SeparatorLoc;
  }

  SourceRange getSourceRange() const {
    if (getKind() == RequirementReprKind::LayoutConstraint)
      return SourceRange(FirstType.getSourceRange().Start,
                         SecondLayout.getSourceRange().End);
    return SourceRange(FirstType.getSourceRange().Start,
                       SecondType.getSourceRange().End);
  }

  /// Retrieve the first or subject type representation from the \c repr,
  /// or \c nullptr if \c repr is null.
  static TypeRepr *getFirstTypeRepr(const RequirementRepr *repr) {
    if (!repr) return nullptr;
    return repr->FirstType.getTypeRepr();
  }

  /// Retrieve the second or constraint type representation from the \c repr,
  /// or \c nullptr if \c repr is null.
  static TypeRepr *getSecondTypeRepr(const RequirementRepr *repr) {
    if (!repr) return nullptr;
    assert(repr->getKind() == RequirementReprKind::TypeConstraint ||
           repr->getKind() == RequirementReprKind::SameType);
    return repr->SecondType.getTypeRepr();
  }

  LLVM_ATTRIBUTE_DEPRECATED(
      void dump() const LLVM_ATTRIBUTE_USED,
      "only for use within the debugger");
  void print(raw_ostream &OS) const;
  void print(ASTPrinter &Printer) const;
};
  
/// GenericParamList - A list of generic parameters that is part of a generic
/// function or type, along with extra requirements placed on those generic
/// parameters and types derived from them.
class GenericParamList final :
    private llvm::TrailingObjects<GenericParamList, GenericTypeParamDecl *> {
  friend TrailingObjects;

  SourceRange Brackets;
  unsigned NumParams;
  SourceLoc WhereLoc;
  MutableArrayRef<RequirementRepr> Requirements;

  GenericParamList *OuterParameters;

  SourceLoc TrailingWhereLoc;
  unsigned FirstTrailingWhereArg;

  GenericParamList(SourceLoc LAngleLoc,
                   ArrayRef<GenericTypeParamDecl *> Params,
                   SourceLoc WhereLoc,
                   MutableArrayRef<RequirementRepr> Requirements,
                   SourceLoc RAngleLoc);
  
  // Don't copy.
  GenericParamList(const GenericParamList &) = delete;
  GenericParamList &operator=(const GenericParamList &) = delete;
  
public:
  /// create - Create a new generic parameter list within the given AST context.
  ///
  /// \param Context The ASTContext in which the generic parameter list will
  /// be allocated.
  /// \param LAngleLoc The location of the opening angle bracket ('<')
  /// \param Params The list of generic parameters, which will be copied into
  /// ASTContext-allocated memory.
  /// \param RAngleLoc The location of the closing angle bracket ('>')
  static GenericParamList *create(ASTContext &Context,
                                  SourceLoc LAngleLoc,
                                  ArrayRef<GenericTypeParamDecl *> Params,
                                  SourceLoc RAngleLoc);

  /// create - Create a new generic parameter list and "where" clause within
  /// the given AST context.
  ///
  /// \param Context The ASTContext in which the generic parameter list will
  /// be allocated.
  /// \param LAngleLoc The location of the opening angle bracket ('<')
  /// \param Params The list of generic parameters, which will be copied into
  /// ASTContext-allocated memory.
  /// \param WhereLoc The location of the 'where' keyword, if any.
  /// \param Requirements The list of requirements, which will be copied into
  /// ASTContext-allocated memory.
  /// \param RAngleLoc The location of the closing angle bracket ('>')
  static GenericParamList *create(const ASTContext &Context,
                                  SourceLoc LAngleLoc,
                                  ArrayRef<GenericTypeParamDecl *> Params,
                                  SourceLoc WhereLoc,
                                  ArrayRef<RequirementRepr> Requirements,
                                  SourceLoc RAngleLoc);

  MutableArrayRef<GenericTypeParamDecl *> getParams() {
    return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
  }

  ArrayRef<GenericTypeParamDecl *> getParams() const {
    return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
  }

  using iterator = GenericTypeParamDecl **;
  using const_iterator = const GenericTypeParamDecl * const *;

  unsigned size() const { return NumParams; }
  iterator begin() { return getParams().begin(); }
  iterator end() { return getParams().end(); }
  const_iterator begin() const { return getParams().begin(); }
  const_iterator end() const { return getParams().end(); }

  /// Retrieve the location of the 'where' keyword, or an invalid
  /// location if 'where' was not present.
  SourceLoc getWhereLoc() const { return WhereLoc; }

  /// Retrieve the set of additional requirements placed on these
  /// generic parameters and types derived from them.
  ///
  /// This list may contain both explicitly-written requirements as well as
  /// implicitly-generated requirements, and may be non-empty even if no
  /// 'where' keyword is present.
  MutableArrayRef<RequirementRepr> getRequirements() { return Requirements; }

  /// Retrieve the set of additional requirements placed on these
  /// generic parameters and types derived from them.
  ///
  /// This list may contain both explicitly-written requirements as well as
  /// implicitly-generated requirements, and may be non-empty even if no
  /// 'where' keyword is present.
  ArrayRef<RequirementRepr> getRequirements() const { return Requirements; }

  /// Retrieve only those requirements that are written within the brackets,
  /// which does not include any requirements written in a trailing where
  /// clause.
  ArrayRef<RequirementRepr> getNonTrailingRequirements() const {
    return Requirements.slice(0, FirstTrailingWhereArg);
  }

  /// Retrieve only those requirements written in a trailing where
  /// clause.
  ArrayRef<RequirementRepr> getTrailingRequirements() const {
    return Requirements.slice(FirstTrailingWhereArg);
  }

  /// Determine whether the generic parameters have a trailing where clause.
  bool hasTrailingWhereClause() const {
    return FirstTrailingWhereArg < Requirements.size();
  }

  /// Add a trailing 'where' clause to the list of requirements.
  ///
  /// Trailing where clauses are written outside the angle brackets, after the
  /// main part of a declaration's signature.
  void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc,
                              ArrayRef<RequirementRepr> trailingRequirements);
  
  /// Retrieve the outer generic parameter list.
  ///
  /// This is used for extensions of nested types, and in SIL mode, where a
  /// single lexical context can have multiple logical generic parameter
  /// lists.
  GenericParamList *getOuterParameters() const { return OuterParameters; }

  /// Set the outer generic parameter list. See \c getOuterParameters
  /// for more information.
  void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; }

  SourceLoc getLAngleLoc() const { return Brackets.Start; }
  SourceLoc getRAngleLoc() const { return Brackets.End; }

  SourceRange getSourceRange() const { return Brackets; }

  /// Retrieve the source range covering the where clause.
  SourceRange getWhereClauseSourceRange() const {
    if (WhereLoc.isInvalid())
      return SourceRange();

    auto endLoc = Requirements[FirstTrailingWhereArg-1].getSourceRange().End;
    return SourceRange(WhereLoc, endLoc);
  }

  /// Retrieve the source range covering the trailing where clause.
  SourceRange getTrailingWhereClauseSourceRange() const {
    if (!hasTrailingWhereClause())
      return SourceRange();

    return SourceRange(TrailingWhereLoc,
                       Requirements.back().getSourceRange().End);
  }

  /// Configure the depth of the generic parameters in this list.
  void setDepth(unsigned depth);

  /// Create a copy of the generic parameter list and all of its generic
  /// parameter declarations. The copied generic parameters are re-parented
  /// to the given DeclContext.
  GenericParamList *clone(DeclContext *dc) const;

  void print(raw_ostream &OS) const;
  void dump();
};
  
/// A trailing where clause.
class alignas(RequirementRepr) TrailingWhereClause final :
    private llvm::TrailingObjects<TrailingWhereClause, RequirementRepr> {
  friend TrailingObjects;

  SourceLoc WhereLoc;

  /// The number of requirements. The actual requirements are tail-allocated.
  unsigned NumRequirements;

  TrailingWhereClause(SourceLoc whereLoc,
                      ArrayRef<RequirementRepr> requirements);

public:
  /// Create a new trailing where clause with the given set of requirements.
  static TrailingWhereClause *create(ASTContext &ctx, SourceLoc whereLoc,
                                     ArrayRef<RequirementRepr> requirements);

  /// Retrieve the location of the 'where' keyword.
  SourceLoc getWhereLoc() const { return WhereLoc; }

  /// Retrieve the set of requirements.
  MutableArrayRef<RequirementRepr> getRequirements() {
    return {getTrailingObjects<RequirementRepr>(), NumRequirements};
  }

  /// Retrieve the set of requirements.
  ArrayRef<RequirementRepr> getRequirements() const {
    return {getTrailingObjects<RequirementRepr>(), NumRequirements};
  }

  /// Compute the source range containing this trailing where clause.
  SourceRange getSourceRange() const {
    return SourceRange(WhereLoc,
                       getRequirements().back().getSourceRange().End);
  }
};

// A private class for forcing exact field layout.
class alignas(8) _GenericContext {
// Not really public. See GenericContext.
public:
  llvm::PointerIntPair<GenericParamList *, 1, bool> GenericParamsAndBit;

  /// The trailing where clause.
  ///
  /// Note that this is not currently serialized, because semantic analysis
  /// moves the trailing where clause into the generic parameter list.
  TrailingWhereClause *TrailingWhere = nullptr;

  /// The generic signature of this declaration.
  llvm::PointerIntPair<GenericSignature, 1, bool> GenericSigAndBit;
};

class GenericContext : private _GenericContext, public DeclContext {
  friend class GenericParamListRequest;
  friend class GenericSignatureRequest;
  
protected:
  GenericContext(DeclContextKind Kind, DeclContext *Parent,
                 GenericParamList *Params);

public:
  /// Retrieve the set of parameters to a generic context, or null if
  /// this context is not generic.
  GenericParamList *getGenericParams() const;

  /// Determine whether this context has generic parameters
  /// of its own.
  ///
  /// \code
  /// class C<T> {
  ///   func f1() {}    // isGeneric == false
  ///   func f2<T>() {} // isGeneric == true
  /// }
  ///
  /// protocol P { // isGeneric == true due to implicit Self param
  ///   func p()   // isGeneric == false
  /// }
  /// \endcode
  bool isGeneric() const { return getGenericParams() != nullptr; }
  bool hasComputedGenericSignature() const;
  bool isComputingGenericSignature() const;
  
  /// Retrieve the trailing where clause for this extension, if any.
  TrailingWhereClause *getTrailingWhereClause() const {
    return TrailingWhere;
  }

  /// Set the trailing where clause for this extension.
  void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
    TrailingWhere = trailingWhereClause;
  }

  /// Retrieve the generic signature for this context.
  GenericSignature getGenericSignature() const;

  /// Retrieve the generic context for this context.
  GenericEnvironment *getGenericEnvironment() const;

  /// Retrieve the innermost generic parameter types.
  TypeArrayView<GenericTypeParamType> getInnermostGenericParamTypes() const;

  /// Retrieve the generic requirements.
  ArrayRef<Requirement> getGenericRequirements() const;

  /// Set the generic signature of this context.
  void setGenericSignature(GenericSignature genericSig);

  /// Retrieve the position of any where clause for this context's
  /// generic parameters.
  SourceRange getGenericTrailingWhereClauseSourceRange() const;
};
static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
              sizeof(GenericContext), "Please add fields to _GenericContext");

/// Describes what kind of name is being imported.
///
/// If the enumerators here are changed, make sure to update all diagnostics
/// using ImportKind as a select index.
enum class ImportKind : uint8_t {
  Module = 0,
  Type,
  Struct,
  Class,
  Enum,
  Protocol,
  Var,
  Func
};

/// ImportDecl - This represents a single import declaration, e.g.:
///   import Swift
///   import typealias Swift.Int
class ImportDecl final : public Decl,
    private llvm::TrailingObjects<ImportDecl, std::pair<Identifier,SourceLoc>> {
  friend TrailingObjects;
  friend class Decl;
public:
  typedef std::pair<Identifier, SourceLoc> AccessPathElement;

private:
  SourceLoc ImportLoc;
  SourceLoc KindLoc;

  /// The resolved module.
  ModuleDecl *Mod = nullptr;
  /// The resolved decls if this is a decl import.
  ArrayRef<ValueDecl *> Decls;

  ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
             SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);

public:
  static ImportDecl *create(ASTContext &C, DeclContext *DC,
                            SourceLoc ImportLoc, ImportKind Kind,
                            SourceLoc KindLoc,
                            ArrayRef<AccessPathElement> Path,
                            ClangNode ClangN = ClangNode());

  /// Returns the import kind that is most appropriate for \p VD.
  ///
  /// Note that this will never return \c Type; an imported typealias will use
  /// the more specific kind from its underlying type.
  static ImportKind getBestImportKind(const ValueDecl *VD);

  /// Returns the most appropriate import kind for the given list of decls.
  ///
  /// If the list is non-homogeneous, or if there is more than one decl that
  /// cannot be overloaded, returns None.
  static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);

  ArrayRef<AccessPathElement> getFullAccessPath() const {
    return {getTrailingObjects<AccessPathElement>(),
            static_cast<size_t>(Bits.ImportDecl.NumPathElements)};
  }

  ArrayRef<AccessPathElement> getModulePath() const {
    auto result = getFullAccessPath();
    if (getImportKind() != ImportKind::Module)
      result = result.slice(0, result.size()-1);
    return result;
  }

  ArrayRef<AccessPathElement> getDeclPath() const {
    if (getImportKind() == ImportKind::Module)
      return {};
    return getFullAccessPath().back();
  }

  ImportKind getImportKind() const {
    return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
  }

  bool isExported() const {
    return getAttrs().hasAttribute<ExportedAttr>();
  }

  ModuleDecl *getModule() const { return Mod; }
  void setModule(ModuleDecl *M) { Mod = M; }

  ArrayRef<ValueDecl *> getDecls() const { return Decls; }
  void setDecls(ArrayRef<ValueDecl *> Ds) { Decls = Ds; }

  const clang::Module *getClangModule() const {
    return getClangNode().getClangModule();
  }

  SourceLoc getStartLoc() const { return ImportLoc; }
  SourceLoc getLocFromSource() const { return getFullAccessPath().front().second; }
  SourceRange getSourceRange() const {
    return SourceRange(ImportLoc, getFullAccessPath().back().second);
  }
  SourceLoc getKindLoc() const { return KindLoc; }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Import;
  }
};

/// ExtensionDecl - This represents a type extension containing methods
/// associated with the type.  This is not a ValueDecl and has no Type because
/// there are no runtime values of the Extension's type.  
class ExtensionDecl final : public GenericContext, public Decl,
                            public IterableDeclContext {
  SourceLoc ExtensionLoc;  // Location of 'extension' keyword.
  SourceRange Braces;

  /// The type being extended.
  TypeRepr *ExtendedTypeRepr;

  /// The nominal type being extended.
  ///
  /// The bit indicates whether binding has been attempted. The pointer can be
  /// null if either no binding was attempted or if binding could not find  the
  /// extended nominal.
  llvm::PointerIntPair<NominalTypeDecl *, 1, bool> ExtendedNominal;

  MutableArrayRef<TypeLoc> Inherited;

  /// The next extension in the linked list of extensions.
  ///
  /// The bit indicates whether this extension has been resolved to refer to
  /// a known nominal type.
  llvm::PointerIntPair<ExtensionDecl *, 1, bool> NextExtension
    = {nullptr, false};

  /// Note that we have added a member into the iterable declaration context.
  void addedMember(Decl *member);

  friend class ExtensionIterator;
  friend class NominalTypeDecl;
  friend class MemberLookupTable;
  friend class ConformanceLookupTable;
  friend class IterableDeclContext;

  ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType,
                MutableArrayRef<TypeLoc> inherited,
                DeclContext *parent,
                TrailingWhereClause *trailingWhereClause);

  /// Retrieve the conformance loader (if any), and removing it in the
  /// same operation. The caller is responsible for loading the
  /// conformances.
  std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
    if (!Bits.ExtensionDecl.HasLazyConformances)
      return { nullptr, 0 };

    return takeConformanceLoaderSlow();
  }

  /// Slow path for \c takeConformanceLoader().
  std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();

  friend class ExtendedNominalRequest;
  friend class Decl;
public:
  using Decl::getASTContext;

  /// Create a new extension declaration.
  static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc,
                               TypeRepr *extendedType,
                               MutableArrayRef<TypeLoc> inherited,
                               DeclContext *parent,
                               TrailingWhereClause *trailingWhereClause,
                               ClangNode clangNode = ClangNode());

  SourceLoc getStartLoc() const { return ExtensionLoc; }
  SourceLoc getLocFromSource() const { return ExtensionLoc; }
  SourceRange getSourceRange() const {
    return { ExtensionLoc, Braces.End };
  }

  SourceRange getBraces() const { return Braces; }
  void setBraces(SourceRange braces) { Braces = braces; }

  bool hasBeenBound() const { return ExtendedNominal.getInt(); }

  void setExtendedNominal(NominalTypeDecl *n) {
    ExtendedNominal.setPointerAndInt(n, true);
  }

  /// Retrieve the type being extended.
  ///
  /// Only use this entry point when the complete type, as spelled in the source,
  /// is required. For most clients, \c getExtendedNominal(), which provides
  /// only the \c NominalTypeDecl, will suffice.
  Type getExtendedType() const;

  /// Retrieve the nominal type declaration that is being extended.
  /// Will  trip an assertion if the declaration has not already been computed.
  /// In order to fail fast when type checking work is attempted
  /// before extension binding has taken place.

  NominalTypeDecl *getExtendedNominal() const;

  /// Compute the nominal type declaration that is being extended.
  NominalTypeDecl *computeExtendedNominal() const;

  /// \c hasBeenBound means nothing if this extension can never been bound
  /// because it is not at the top level.
  bool canNeverBeBound() const;

  bool hasValidParent() const;

  /// Determine whether this extension has already been bound to a nominal
  /// type declaration.
  bool alreadyBoundToNominal() const { return NextExtension.getInt(); }

  /// Retrieve the extended type definition as written in the source, if it exists.
  TypeRepr *getExtendedTypeRepr() const { return ExtendedTypeRepr; }
                              
  /// Retrieve the set of protocols that this type inherits (i.e,
  /// explicitly conforms to).
  MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
  ArrayRef<TypeLoc> getInherited() const { return Inherited; }

  void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }

  bool hasDefaultAccessLevel() const {
    return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
  }

  uint8_t getDefaultAndMaxAccessLevelBits() const {
    return Bits.ExtensionDecl.DefaultAndMaxAccessLevel;
  }
  void setDefaultAndMaxAccessLevelBits(AccessLevel defaultAccess,
                                       AccessLevel maxAccess) {
    Bits.ExtensionDecl.DefaultAndMaxAccessLevel =
      (1 << (static_cast<unsigned>(defaultAccess) - 1)) |
      (1 << (static_cast<unsigned>(maxAccess) - 1));
  }

  AccessLevel getDefaultAccessLevel() const;
  AccessLevel getMaxAccessLevel() const;

  void setDefaultAndMaxAccess(AccessLevel defaultAccess,
                              AccessLevel maxAccess) {
    assert(!hasDefaultAccessLevel() && "default access level already set");
    assert(maxAccess >= defaultAccess);
    assert(maxAccess != AccessLevel::Private && "private not valid");
    assert(defaultAccess != AccessLevel::Private && "private not valid");
    setDefaultAndMaxAccessLevelBits(defaultAccess, maxAccess);
    assert(getDefaultAccessLevel() == defaultAccess && "not enough bits");
    assert(getMaxAccessLevel() == maxAccess && "not enough bits");
  }

  void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

  /// Determine whether this is a constrained extension, which adds additional
  /// requirements beyond those of the nominal type.
  bool isConstrainedExtension() const;
  
  /// Determine whether this extension context is interchangeable with the
  /// original nominal type context.
  ///
  /// False if any of the following properties hold:
  /// - the extension is defined in a different module from the original
  ///   nominal type decl,
  /// - the extension is constrained, or
  /// - the extension is to a protocol.
  /// FIXME: In a world where protocol extensions are dynamically dispatched,
  /// "extension is to a protocol" would no longer be a reason to use the
  /// extension mangling, because an extension method implementation could be
  /// resiliently moved into the original protocol itself.
  bool isEquivalentToExtendedContext() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Extension;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    return C->getIterableContextKind() 
             == IterableDeclContextKind::ExtensionDecl;
  }

  using DeclContext::operator new;
};

/// Iterator that walks the extensions of a particular type.
class ExtensionIterator {
  ExtensionDecl *current;

public:
  ExtensionIterator() : current() { }
  explicit ExtensionIterator(ExtensionDecl *current) : current(current) { }

  ExtensionDecl *operator*() const { return current; }
  ExtensionDecl *operator->() const { return current; }

  ExtensionIterator &operator++() {
    current = current->NextExtension.getPointer();
    return *this;
  }

  ExtensionIterator operator++(int) {
    ExtensionIterator tmp = *this;
    ++(*this);
    return tmp;
  }

  friend bool operator==(ExtensionIterator x, ExtensionIterator y) {
    return x.current == y.current;
  }

  friend bool operator!=(ExtensionIterator x, ExtensionIterator y) {
    return x.current != y.current;
  }
};

/// Range that covers a set of extensions.
class ExtensionRange {
  ExtensionIterator first;
  ExtensionIterator last;

public:

  ExtensionRange(ExtensionIterator first, ExtensionIterator last)
    : first(first), last(last) { }

  typedef ExtensionIterator iterator;
  iterator begin() const { return first; }
  iterator end() const { return last; }
};
  
  
/// This represents one entry in a PatternBindingDecl, which are pairs of
/// Pattern and Initialization expression.  The pattern is always present, but
/// the initializer can be null if there is none.
class PatternBindingEntry {
  enum class Flags {
    Checked = 1 << 0,
    Removed = 1 << 1,
    /// Whether the contents of this initializer were subsumed by
    /// some other initialization, e.g., a lazy property's initializer
    /// gets subsumed by the getter body.
    Subsumed    = 1 << 2
  };
  llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;

  struct InitializerAndEqualLoc {
    // When the initializer is removed we don't actually clear the pointers
    // because we might need to get initializer's source range. Since the
    // initializer is ASTContext-allocated it is safe.
    
    /// Exactly the expr the programmer wrote
    Expr *originalInit;
    /// Might be transformed, e.g. for a property wrapper. In the absence of
    /// transformation or synthesis, holds the expr as parsed.
    Expr *initAfterSynthesis;
    /// The location of the equal '=' token.
    SourceLoc EqualLoc;
  };

  union {
    /// The initializer expression and its '=' token loc.
    InitializerAndEqualLoc InitExpr;

    /// The text of the initializer expression if deserialized from a module.
    StringRef InitStringRepresentation;
  };

  /// The initializer context used for this pattern binding entry.
  llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;

  /// Values captured by this initializer.
  CaptureInfo Captures;

  friend class PatternBindingInitializer;

public:
  /// \p E is the initializer as parsed.
  PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
                      DeclContext *InitContext)
    : PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
      InitContextAndIsText({InitContext, false}) {
  }

  Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
  void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }

  /// Whether the given pattern binding entry is initialized.
  bool isInitialized() const;

  Expr *getInit() const {
    if (PatternAndFlags.getInt().contains(Flags::Removed) ||
        InitContextAndIsText.getInt())
      return nullptr;
    return InitExpr.initAfterSynthesis;
  }
  /// Retrieve the initializer if it should be executed to initialize this
  /// particular pattern binding.
  Expr *getExecutableInit() const {
    return isInitializerSubsumed() ? nullptr : getInit();
  }
  SourceRange getOriginalInitRange() const;
  void setInit(Expr *E);

  /// Gets the text of the initializer expression, stripping out inactive
  /// branches of any #ifs inside the expression.
  StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;

  /// Sets the initializer string representation to the string that was
  /// deserialized from a partial module.
  void setInitStringRepresentation(StringRef str) {
    InitStringRepresentation = str;
    InitContextAndIsText.setInt(true);
  }

  /// Whether this pattern entry can generate a string representation of its
  /// initializer expression.
  bool hasInitStringRepresentation() const;

  /// Retrieve the location of the equal '=' token.
  SourceLoc getEqualLoc() const {
    return InitContextAndIsText.getInt() ? SourceLoc() : InitExpr.EqualLoc;
  }

  /// Set the location of the equal '=' token.
  void setEqualLoc(SourceLoc equalLoc) {
    assert(!InitContextAndIsText.getInt() &&
           "cannot set equal loc for textual initializer");
    InitExpr.EqualLoc = equalLoc;
  }

  /// Retrieve the initializer after the =, if any, as it was written in the
  /// source.
  Expr *getOriginalInit() const;

  /// Set the initializer after the = as it was written in the source.
  void setOriginalInit(Expr *);

  bool isInitializerChecked() const {
    return PatternAndFlags.getInt().contains(Flags::Checked);
  }
  void setInitializerChecked() {
    PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
  }

  bool isInitializerSubsumed() const {
    return PatternAndFlags.getInt().contains(Flags::Subsumed);
  }
  void setInitializerSubsumed() {
    PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Subsumed);
  }

  // Return the first variable initialized by this pattern.
  VarDecl *getAnchoringVarDecl() const;

  // Retrieve the declaration context for the initializer.
  DeclContext *getInitContext() const {
    return InitContextAndIsText.getPointer();
  }

  /// Override the initializer context.
  void setInitContext(DeclContext *dc) {
    InitContextAndIsText.setPointer(dc);
  }

  SourceLoc getStartLoc() const;

  /// Retrieve the end location covered by this pattern binding entry.
  ///
  /// \param omitAccessors Whether the computation should omit the accessors
  /// from the source range.
  SourceLoc getEndLoc(bool omitAccessors = false) const;

  /// Retrieve the source range covered by this pattern binding entry.
  ///
  /// \param omitAccessors Whether the computation should omit the accessors
  /// from the source range.
  SourceRange getSourceRange(bool omitAccessors = false) const;

  const CaptureInfo &getCaptureInfo() const { return Captures; }
  void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }

private:
  SourceLoc getLastAccessorEndLoc() const;
};

/// This decl contains a pattern and optional initializer for a set
/// of one or more VarDecls declared together.
///
/// For example, in
/// \code
///   var (a, b) = foo(), (c,d) = bar()
/// \endcode
///
/// this includes two entries in the pattern list.  The first contains the
/// pattern "(a, b)" and the initializer "foo()".  The second contains the
/// pattern "(c, d)" and the initializer "bar()".
///
class PatternBindingDecl final : public Decl,
    private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
  friend TrailingObjects;
  friend class Decl;
  SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
  SourceLoc VarLoc;    ///< Location of the 'var' keyword.

  friend class Decl;
  
  PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                     SourceLoc VarLoc, unsigned NumPatternEntries,
                     DeclContext *Parent);
  SourceLoc getLocFromSource() const { return VarLoc; }
public:
  static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc,
                                    StaticSpellingKind StaticSpelling,
                                    SourceLoc VarLoc,
                                    ArrayRef<PatternBindingEntry> PatternList,
                                    DeclContext *Parent);

  static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc,
                                    StaticSpellingKind StaticSpelling,
                                    SourceLoc VarLoc, Pattern *Pat,
                                    SourceLoc EqualLoc, Expr *E,
                                    DeclContext *Parent);

  static PatternBindingDecl *createImplicit(ASTContext &Ctx,
                                            StaticSpellingKind StaticSpelling,
                                            Pattern *Pat, Expr *E,
                                            DeclContext *Parent,
                                            SourceLoc VarLoc = SourceLoc());

  static PatternBindingDecl *createDeserialized(
                               ASTContext &Ctx, SourceLoc StaticLoc,
                               StaticSpellingKind StaticSpelling,
                               SourceLoc VarLoc,
                               unsigned NumPatternEntries,
                               DeclContext *Parent);

  SourceLoc getStartLoc() const {
    return StaticLoc.isValid() ? StaticLoc : VarLoc;
  }
  SourceRange getSourceRange() const;

  unsigned getNumPatternEntries() const {
    return Bits.PatternBindingDecl.NumPatternEntries;
  }
  
  ArrayRef<PatternBindingEntry> getPatternList() const {
    return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
  }

  void setInitStringRepresentation(unsigned i, StringRef str) {
    getMutablePatternList()[i].setInitStringRepresentation(str);
  }

  /// Whether the given pattern entry is initialized.
  bool isInitialized(unsigned i) const {
    return getPatternList()[i].isInitialized();
  }

  Expr *getInit(unsigned i) const {
    return getPatternList()[i].getInit();
  }
  Expr *getExecutableInit(unsigned i) const {
    return getPatternList()[i].getExecutableInit();
  }

  SourceRange getOriginalInitRange(unsigned i) const {
    return getPatternList()[i].getOriginalInitRange();
  }

  void setInit(unsigned i, Expr *E) {
    getMutablePatternList()[i].setInit(E);
  }

  Pattern *getPattern(unsigned i) const {
    return getPatternList()[i].getPattern();
  }
  
  void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext);

  DeclContext *getInitContext(unsigned i) const {
    return getPatternList()[i].getInitContext();
  }

  const CaptureInfo &getCaptureInfo(unsigned i) const {
    return getPatternList()[i].getCaptureInfo();
  }

  void setCaptureInfo(unsigned i, const CaptureInfo &captures) {
    getMutablePatternList()[i].setCaptureInfo(captures);
  }

  /// Given that this PBD is the parent pattern for the specified VarDecl,
  /// return the entry of the VarDecl in our PatternList.  For example, in:
  ///
  ///   let (a,b) = foo(), (c,d) = bar()
  ///
  /// "a" and "b" will have index 0, since they correspond to the first pattern,
  /// and "c" and "d" will have index 1 since they correspond to the second one.
  unsigned getPatternEntryIndexForVarDecl(const VarDecl *VD) const;
  
  /// Return the PatternEntry (a pattern + initializer pair) for the specified
  /// VarDecl.
  const PatternBindingEntry &getPatternEntryForVarDecl(
    const VarDecl *VD) const {
    return getPatternList()[getPatternEntryIndexForVarDecl(VD)];
  }
  
  bool isInitializerChecked(unsigned i) const {
    return getPatternList()[i].isInitializerChecked();
  }

  void setInitializerChecked(unsigned i) {
    getMutablePatternList()[i].setInitializerChecked();
  }

  bool isInitializerSubsumed(unsigned i) const {
    return getPatternList()[i].isInitializerSubsumed();
  }

  void setInitializerSubsumed(unsigned i) {
    getMutablePatternList()[i].setInitializerSubsumed();
  }
  
  /// Does this binding declare something that requires storage?
  bool hasStorage() const;

  /// Determines whether this binding either has an initializer expression, or is
  /// default initialized, without performing any type checking on it.
  bool isDefaultInitializable() const {
    for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
      if (!isDefaultInitializable(i))
        return false;

    return true;
  }

  /// Can the pattern at index i be default initialized?
  bool isDefaultInitializable(unsigned i) const;
  
  /// When the pattern binding contains only a single variable with no
  /// destructuring, retrieve that variable.
  VarDecl *getSingleVar() const;

  bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; }
  void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; }
  SourceLoc getStaticLoc() const { return StaticLoc; }
  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(
        Bits.PatternBindingDecl.StaticSpelling);
  }
  /// \returns the way 'static'/'class' should be spelled for this declaration.
  StaticSpellingKind getCorrectStaticSpelling() const;

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PatternBinding;
  }

private:
  MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
    // Pattern entries are tail allocated.
    return {getTrailingObjects<PatternBindingEntry>(), getNumPatternEntries()};
  }
};
  
/// TopLevelCodeDecl - This decl is used as a container for top-level
/// expressions and statements in the main module.  It is always a direct
/// child of a SourceFile.  The primary reason for building these is to give
/// top-level statements a DeclContext which is distinct from the file itself.
/// This, among other things, makes it easier to distinguish between local
/// top-level variables (which are not live past the end of the statement) and
/// global variables.
class TopLevelCodeDecl : public DeclContext, public Decl {
  BraceStmt *Body;
  SourceLoc getLocFromSource() const { return getStartLoc(); }
  friend class Decl;
public:
  TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
    : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
      Decl(DeclKind::TopLevelCode, Parent),
      Body(Body) {}

  BraceStmt *getBody() const { return Body; }
  void setBody(BraceStmt *b) { Body = b; }

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

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::TopLevelCode;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  
  using DeclContext::operator new;
};

/// SerializedTopLevelCodeDeclContext - This represents what was originally a
/// TopLevelCodeDecl during serialization. It is preserved only to maintain the
/// correct AST structure and remangling after deserialization.
class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext {
public:
  SerializedTopLevelCodeDeclContext(DeclContext *Parent)
    : SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl,
                                 Parent) {}
  static bool classof(const DeclContext *DC) {
    if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
      return LDC->getLocalDeclContextKind() ==
        LocalDeclContextKind::TopLevelCodeDecl;
    return false;
  }
};

/// IfConfigDecl - This class represents #if/#else/#endif blocks.
/// Active and inactive block members are stored separately, with the intention
/// being that active members will be handed back to the enclosing context.
class IfConfigDecl : public Decl {
  /// An array of clauses controlling each of the #if/#elseif/#else conditions.
  /// The array is ASTContext allocated.
  ArrayRef<IfConfigClause> Clauses;
  SourceLoc EndLoc;
  SourceLoc getLocFromSource() const { return Clauses[0].Loc; }
  friend class Decl;
public:
  
  IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses,
               SourceLoc EndLoc, bool HadMissingEnd)
    : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
  {
    Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd;
  }

  ArrayRef<IfConfigClause> getClauses() const { return Clauses; }

  /// Return the active clause, or null if there is no active one.
  const IfConfigClause *getActiveClause() const {
    for (auto &Clause : Clauses)
      if (Clause.isActive) return &Clause;
    return nullptr;
  }

  const ArrayRef<ASTNode> getActiveClauseElements() const {
    if (auto *Clause = getActiveClause())
      return Clause->Elements;
    return {};
  }
  
  SourceLoc getEndLoc() const { return EndLoc; }

  bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; }
  
  SourceRange getSourceRange() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::IfConfig;
  }
};

class StringLiteralExpr;

class PoundDiagnosticDecl : public Decl {
  SourceLoc StartLoc;
  SourceLoc EndLoc;
  StringLiteralExpr *Message;
  SourceLoc getLocFromSource() const { return StartLoc; }
  friend class Decl;
public:
  PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc,
                      SourceLoc EndLoc, StringLiteralExpr *Message)
    : Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc),
      EndLoc(EndLoc), Message(Message) {
      Bits.PoundDiagnosticDecl.IsError = IsError;
      Bits.PoundDiagnosticDecl.HasBeenEmitted = false; 
    }

  DiagnosticKind getKind() {
    return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning;
  }

  StringLiteralExpr *getMessage() { return Message; }

  bool isError() {
    return Bits.PoundDiagnosticDecl.IsError;
  }

  bool hasBeenEmitted() {
    return Bits.PoundDiagnosticDecl.HasBeenEmitted;
  }

  void markEmitted() {
    Bits.PoundDiagnosticDecl.HasBeenEmitted = true;
  }
  
  SourceLoc getEndLoc() const { return EndLoc; };
  
  SourceRange getSourceRange() const {
    return SourceRange(StartLoc, EndLoc);
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PoundDiagnostic;
  }
};
  
class OpaqueTypeDecl;

/// ValueDecl - All named decls that are values in the language.  These can
/// have a type, etc.
class ValueDecl : public Decl {
  DeclName Name;
  SourceLoc NameLoc;
  llvm::PointerIntPair<Type, 3, OptionalEnum<AccessLevel>> TypeAndAccess;
  unsigned LocalDiscriminator = 0;

  struct {
    /// Whether the "IsObjC" bit has been computed yet.
    unsigned isObjCComputed : 1;

    /// Whether this declaration is exposed to Objective-C.
    unsigned isObjC : 1;

    /// Whether the "overridden" declarations have been computed already.
    unsigned hasOverriddenComputed : 1;

    /// Whether there are any "overridden" declarations. The actual overridden
    /// declarations are kept in a side table in the ASTContext.
    unsigned hasOverridden : 1;

    /// Whether the "isDynamic" bit has been computed yet.
    unsigned isDynamicComputed : 1;

    /// Whether this declaration is 'dynamic', meaning that all uses of
    /// the declaration will go through an extra level of indirection that
    /// allows the entity to be replaced at runtime.
    unsigned isDynamic : 1;

    /// Whether the "isFinal" bit has been computed yet.
    unsigned isFinalComputed : 1;

    /// Whether this declaration is 'final'. A final class can't be subclassed,
    /// a final class member can't be overriden.
    unsigned isFinal : 1;

    /// Whether the "isIUO" bit" has been computed yet.
    unsigned isIUOComputed : 1;

    /// Whether this declaration produces an implicitly unwrapped
    /// optional result.
    unsigned isIUO : 1;
  } LazySemanticInfo = { };

  friend class OverriddenDeclsRequest;
  friend class IsObjCRequest;
  friend class IsFinalRequest;
  friend class IsDynamicRequest;
  friend class IsImplicitlyUnwrappedOptionalRequest;
  friend class Decl;
  SourceLoc getLocFromSource() const { return NameLoc; }
protected:
  ValueDecl(DeclKind K,
            llvm::PointerUnion<DeclContext *, ASTContext *> context,
            DeclName name, SourceLoc NameLoc)
    : Decl(K, context), Name(name), NameLoc(NameLoc) {
    Bits.ValueDecl.AlreadyInLookupTable = false;
    Bits.ValueDecl.CheckedRedeclaration = false;
    Bits.ValueDecl.IsUserAccessible = true;
  }

  // MemberLookupTable borrows a bit from this type
  friend class MemberLookupTable;
  bool isAlreadyInLookupTable() {
    return Bits.ValueDecl.AlreadyInLookupTable;
  }
  void setAlreadyInLookupTable(bool value = true) {
    Bits.ValueDecl.AlreadyInLookupTable = value;
  }

public:
  /// Return true if this protocol member is a protocol requirement.
  ///
  /// Asserts if this is not a member of a protocol.
  bool isProtocolRequirement() const;

  /// Determine whether we have already checked whether this
  /// declaration is a redeclaration.
  bool alreadyCheckedRedeclaration() const { 
    return Bits.ValueDecl.CheckedRedeclaration;
  }

  /// Set whether we have already checked this declaration as a
  /// redeclaration.
  void setCheckedRedeclaration(bool checked) {
    Bits.ValueDecl.CheckedRedeclaration = checked;
  }

  void setUserAccessible(bool Accessible) {
    Bits.ValueDecl.IsUserAccessible = Accessible;
  }

  bool isUserAccessible() const {
    return Bits.ValueDecl.IsUserAccessible;
  }

  bool hasName() const { return bool(Name); }
  bool isOperator() const { return Name.isOperator(); }

  /// Retrieve the full name of the declaration.
  /// TODO: Rename to getName?
  DeclName getFullName() const { return Name; }
  void setName(DeclName name) { Name = name; }

  /// Retrieve the base name of the declaration, ignoring any argument
  /// names.
  DeclBaseName getBaseName() const { return Name.getBaseName(); }

  /// Retrieve the name to use for this declaration when interoperating
  /// with the Objective-C runtime.
  ///
  /// \returns A "selector" containing the runtime name. For non-method
  /// entities (classes, protocols, properties), this operation will
  /// return a zero-parameter selector with the appropriate name in its
  /// first slot.
  Optional<ObjCSelector> getObjCRuntimeName(
                                    bool skipIsObjCResolution = false) const;

  /// Determine whether the given declaration can infer @objc, or the
  /// Objective-C name, if used to satisfy the given requirement.
  bool canInferObjCFromRequirement(ValueDecl *requirement);

  SourceLoc getNameLoc() const { return NameLoc; }

  bool isUsableFromInline() const;

  /// Returns \c true if this declaration is *not* intended to be used directly
  /// by application developers despite the visibility.
  bool shouldHideFromEditor() const;

  bool hasAccess() const {
    return TypeAndAccess.getInt().hasValue();
  }

  /// Access control is done by Requests.
  friend class AccessLevelRequest;

  /// Returns the access level specified explicitly by the user, or provided by
  /// default according to language rules.
  ///
  /// Most of the time this is not the interesting value to check; access is
  /// limited by enclosing scopes per SE-0025. Use #getFormalAccessScope to
  /// check if access control is being used consistently, and to take features
  /// such as \c \@testable and \c \@usableFromInline into account.
  ///
  /// \sa getFormalAccessScope
  /// \sa hasOpenAccess
  AccessLevel getFormalAccess() const;

  /// Determine whether this Decl has either Private or FilePrivate access,
  /// and its DeclContext does not.
  bool isOutermostPrivateOrFilePrivateScope() const;

  /// Returns the outermost DeclContext from which this declaration can be
  /// accessed, or null if the declaration is public.
  ///
  /// This is used when calculating if access control is being used
  /// consistently. If \p useDC is provided (the location where the value is
  /// being used), features that affect formal access such as \c \@testable are
  /// taken into account.
  ///
  /// \invariant
  /// <code>value.isAccessibleFrom(
  ///     value.getFormalAccessScope().getDeclContext())</code>
  ///
  /// If \p treatUsableFromInlineAsPublic is true, declarations marked with the
  /// \c \@usableFromInline attribute are treated as public. This is normally
  /// false for name lookup and other source language concerns, but true when
  /// computing the linkage of generated functions.
  ///
  /// \sa getFormalAccess
  /// \sa isAccessibleFrom
  /// \sa hasOpenAccess
  AccessScope
  getFormalAccessScope(const DeclContext *useDC = nullptr,
                       bool treatUsableFromInlineAsPublic = false) const;


  /// Copy the formal access level and @usableFromInline attribute from
  /// \p source.
  ///
  /// If \p sourceIsParentContext is true, an access level of \c private will
  /// be copied as \c fileprivate, to ensure that this declaration will be
  /// available everywhere \p source is.
  void copyFormalAccessFrom(const ValueDecl *source,
                            bool sourceIsParentContext = false);

  /// Returns the access level that actually controls how a declaration should
  /// be emitted and may be used.
  ///
  /// This is the access used when making optimization and code generation
  /// decisions. It should not be used at the AST or semantic level.
  AccessLevel getEffectiveAccess() const;

  void setAccess(AccessLevel access) {
    assert(!hasAccess() && "access already set");
    overwriteAccess(access);
  }

  /// Overwrite the access of this declaration.
  ///
  /// This is needed in the LLDB REPL.
  void overwriteAccess(AccessLevel access) {
    TypeAndAccess.setInt(access);
  }

  /// Returns true if this declaration is accessible from the given context.
  ///
  /// A private declaration is accessible from any DeclContext within the same
  /// source file.
  ///
  /// An internal declaration is accessible from any DeclContext within the same
  /// module.
  ///
  /// A public declaration is accessible everywhere.
  ///
  /// If \p DC is null, returns true only if this declaration is public.
  ///
  /// If \p forConformance is true, we ignore the visibility of the protocol
  /// when evaluating protocol extension members. This language rule allows a
  /// protocol extension of a private protocol to provide default
  /// implementations for the requirements of a public protocol, even when
  /// the default implementations are not visible to name lookup.
  bool isAccessibleFrom(const DeclContext *DC,
                        bool forConformance = false) const;

  /// Returns whether this declaration should be treated as \c open from
  /// \p useDC. This is very similar to #getFormalAccess, but takes
  /// \c \@testable into account.
  ///
  /// This is mostly only useful when considering requirements on an override:
  /// if the base declaration is \c open, the override might have to be too.
  bool hasOpenAccess(const DeclContext *useDC) const;

  /// FIXME: This is deprecated.
  bool isRecursiveValidation() const;

  /// Retrieve the "interface" type of this value, which uses
  /// GenericTypeParamType if the declaration is generic. For a generic
  /// function, this will have a GenericFunctionType with a
  /// GenericSignature inside the type.
  Type getInterfaceType() const;
  bool hasInterfaceType() const;

  /// Set the interface type for the given value.
  void setInterfaceType(Type type);
  
  /// isInstanceMember - Determine whether this value is an instance member
  /// of an enum or protocol.
  bool isInstanceMember() const;

  /// Retrieve the context discriminator for this local value, which
  /// is the index of this declaration in the sequence of
  /// discriminated declarations with the same name in the current
  /// context.  Only local functions and variables with getters and
  /// setters have discriminators.
  unsigned getLocalDiscriminator() const;
  void setLocalDiscriminator(unsigned index);

  /// Retrieve the declaration that this declaration overrides, if any.
  ValueDecl *getOverriddenDecl() const;

  /// Retrieve the declarations that this declaration overrides, if any.
  llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;

  /// Set the declaration that this declaration overrides.
  void setOverriddenDecl(ValueDecl *overridden) {
    setOverriddenDecls(overridden);
  }

  /// Set the declarations that this declaration overrides.
  void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);

  /// Whether the overridden declarations have already been computed.
  bool overriddenDeclsComputed() const;

  /// Compute the untyped overload signature for this declaration.
  OverloadSignature getOverloadSignature() const;

  /// Retrieve the type used to describe this entity for the purposes of
  /// overload resolution.
  CanType getOverloadSignatureType() const;

  /// Returns true if the decl requires Objective-C interop.
  ///
  /// This can be true even if there is no 'objc' attribute on the declaration.
  /// In that case it was inferred by the type checker and set with a call to
  /// markAsObjC().
  bool isObjC() const;

  /// Note whether this declaration is known to be exposed to Objective-C.
  void setIsObjC(bool Value);

  /// Is this declaration 'final'?
  bool isFinal() const;

  /// Is this declaration marked with 'dynamic'?
  bool isDynamic() const;

  bool isObjCDynamic() const {
    return isObjC() && isDynamic();
  }

  bool isNativeDynamic() const {
    return !isObjC() && isDynamic();
  }

  /// Set whether this type is 'dynamic' or not.
  void setIsDynamic(bool value);

  /// Whether the 'dynamic' bit has been computed already.
  bool isDynamicComputed() const {
    return LazySemanticInfo.isDynamicComputed;
  }

  /// Returns true if this decl can be found by id-style dynamic lookup.
  bool canBeAccessedByDynamicLookup() const;

  /// Returns true if this declaration has an implicitly unwrapped optional
  /// result. The precise meaning depends on the declaration kind:
  /// - for properties, the value is IUO
  /// - for subscripts, the element type is IUO
  /// - for functions, the result type is IUO
  /// - for constructors, the failability kind is IUO
  bool isImplicitlyUnwrappedOptional() const;

  /// Should only be set on imported and deserialized declarations; parsed
  /// declarations compute this lazily via a request.
  void setImplicitlyUnwrappedOptional(bool isIUO) {
    LazySemanticInfo.isIUOComputed = 1;
    LazySemanticInfo.isIUO = isIUO;
  }

  /// Returns the protocol requirements that this decl conforms to.
  ArrayRef<ValueDecl *>
  getSatisfiedProtocolRequirements(bool Sorted = false) const;

  /// Determines the kind of access that should be performed by a
  /// DeclRefExpr or MemberRefExpr use of this value in the specified
  /// context.
  ///
  /// \param DC The declaration context.
  ///
  /// \param isAccessOnSelf Whether this is a member access on the implicit
  ///        'self' declaration of the declaration context.
  AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC,
                                                bool isAccessOnSelf) const;

  /// Print a reference to the given declaration.
  std::string printRef() const;

  /// Dump a reference to the given declaration.
  void dumpRef(raw_ostream &os) const;

  /// Dump a reference to the given declaration.
  void dumpRef() const;

  /// Returns true if the declaration is a static member of a type.
  ///
  /// This is not necessarily the opposite of "isInstanceMember()". Both
  /// predicates will be false for declarations that either categorically
  /// can't be "static" or are in a context where "static" doesn't make sense.
  bool isStatic() const;

  /// Retrieve the location at which we should insert a new attribute or
  /// modifier.
  SourceLoc getAttributeInsertionLoc(bool forModifier) const;

  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_ValueDecl &&
           D->getKind() <= DeclKind::Last_ValueDecl;
  }
  
  /// True if this is a C function that was imported as a member of a type in
  /// Swift.
  bool isImportAsMember() const;

  /// Returns true if the declaration's interface type is a function type with a
  /// curried self parameter.
  bool hasCurriedSelf() const;

  /// Returns true if the declaration has a parameter list associated with it.
  ///
  /// Note that not all declarations with function interface types have
  /// parameter lists, for example an enum element without associated values.
  bool hasParameterList() const;

  /// Returns the number of curry levels in the declaration's interface type.
  unsigned getNumCurryLevels() const;

  /// Get the decl for this value's opaque result type, if it has one.
  OpaqueTypeDecl *getOpaqueResultTypeDecl() const;

  /// Get the representative for this value's opaque result type, if it has one.
  OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() const;

  /// Retrieve the attribute associating this declaration with a
  /// function builder, if there is one.
  CustomAttr *getAttachedFunctionBuilder() const;

  /// Retrieve the @functionBuilder type attached to this declaration,
  /// if there is one.
  Type getFunctionBuilderType() const;
};

/// This is a common base class for declarations which declare a type.
class TypeDecl : public ValueDecl {
  MutableArrayRef<TypeLoc> Inherited;

protected:
  TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
           Identifier name, SourceLoc NameLoc,
           MutableArrayRef<TypeLoc> inherited) :
    ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}

public:
  Identifier getName() const { return getFullName().getBaseIdentifier(); }

  /// Returns the string for the base name, or "_" if this is unnamed.
  StringRef getNameStr() const {
    assert(!getFullName().isSpecial() && "Cannot get string for special names");
    return hasName() ? getBaseName().getIdentifier().str() : "_";
  }

  /// The type of this declaration's values. For the type of the
  /// declaration itself, use getInterfaceType(), which returns a
  /// metatype.
  Type getDeclaredInterfaceType() const;

  /// Retrieve the set of protocols that this type inherits (i.e,
  /// explicitly conforms to).
  MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
  ArrayRef<TypeLoc> getInherited() const { return Inherited; }

  void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }

  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_TypeDecl &&
           D->getKind() <= DeclKind::Last_TypeDecl;
  }

  /// Compute an ordering between two type declarations that is ABI-stable.
  static int compare(const TypeDecl *type1, const TypeDecl *type2);

  /// Compute an ordering between two type declarations that is ABI-stable.
  /// This version takes a pointer-to-a-pointer for use with
  /// llvm::array_pod_sort() and similar.
  template<typename T>
  static int compare(T * const* type1, T * const* type2) {
    return compare(*type1, *type2);
  }
};

/// A type declaration that can have generic parameters attached to it. Because
/// it has these generic parameters, it is always a DeclContext.
class GenericTypeDecl : public GenericContext, public TypeDecl {
public:
  GenericTypeDecl(DeclKind K, DeclContext *DC,
                  Identifier name, SourceLoc nameLoc,
                  MutableArrayRef<TypeLoc> inherited,
                  GenericParamList *GenericParams);

  // Resolve ambiguity due to multiple base classes.
  using TypeDecl::getASTContext;
  using DeclContext::operator new;
  using TypeDecl::getDeclaredInterfaceType;

  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_GenericTypeDecl &&
           D->getKind() <= DeclKind::Last_GenericTypeDecl;
  }
};

/// OpaqueTypeDecl - This is a declaration of an opaque type. The opaque type
/// is formally equivalent to its underlying type, but abstracts it away from
/// clients of the opaque type, only exposing the type as something conforming
/// to a given set of constraints.
///
/// Currently, opaque types do not normally have an explicit spelling in source
/// code. One is formed implicitly when a declaration is written with an opaque
/// result type, as in:
///
/// func foo() -> opaque SignedInteger { return 1 }
///
/// The declared type is a special kind of ArchetypeType representing the
/// abstracted underlying type.
class OpaqueTypeDecl : public GenericTypeDecl {
  /// The original declaration that "names" the opaque type. Although a specific
  /// opaque type cannot be explicitly named, oapque types can propagate
  /// arbitrarily through expressions, so we need to know *which* opaque type is
  /// propagated.
  ValueDecl *NamingDecl;
  
  /// The generic signature of the opaque interface to the type. This is the
  /// outer generic signature with an added generic parameter representing the
  /// underlying type.
  GenericSignature OpaqueInterfaceGenericSignature;
  
  /// The generic parameter that represents the underlying type.
  GenericTypeParamType *UnderlyingInterfaceType;
  
  /// If known, the underlying type and conformances of the opaque type,
  /// expressed as a SubstitutionMap for the opaque interface generic signature.
  /// This maps types in the interface generic signature to the outer generic
  /// signature of the original declaration.
  Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
  
  mutable Identifier OpaqueReturnTypeIdentifier;
  
public:
  OpaqueTypeDecl(ValueDecl *NamingDecl,
                 GenericParamList *GenericParams,
                 DeclContext *DC,
                 GenericSignature OpaqueInterfaceGenericSignature,
                 GenericTypeParamType *UnderlyingInterfaceType);
  
  ValueDecl *getNamingDecl() const { return NamingDecl; }
  
  void setNamingDecl(ValueDecl *D) {
    assert(!NamingDecl && "already have naming decl");
    NamingDecl = D;
  }

  /// Is this opaque type the opaque return type of the given function?
  ///
  /// This is more complex than just checking `getNamingDecl` because the
  /// function could also be the getter of a storage declaration.
  bool isOpaqueReturnTypeOfFunction(const AbstractFunctionDecl *func) const;

  GenericSignature getOpaqueInterfaceGenericSignature() const {
    return OpaqueInterfaceGenericSignature;
  }
  
  GenericTypeParamType *getUnderlyingInterfaceType() const {
    return UnderlyingInterfaceType;
  }
  
  Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
    return UnderlyingTypeSubstitutions;
  }
  
  void setUnderlyingTypeSubstitutions(SubstitutionMap subs) {
    assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
    UnderlyingTypeSubstitutions = subs;
  }
  
  // Opaque type decls are currently always implicit
  SourceRange getSourceRange() const { return SourceRange(); }
  
  // Get the identifier string that can be used to cross-reference unnamed
  // opaque return types across files.
  Identifier getOpaqueReturnTypeIdentifier() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::OpaqueType;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::OpaqueType;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
};

/// TypeAliasDecl - This is a declaration of a typealias, for example:
///
///    typealias Foo = Int
///
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public GenericTypeDecl {
  friend class UnderlyingTypeRequest;
  
  /// The location of the 'typealias' keyword
  SourceLoc TypeAliasLoc;

  /// The location of the equal '=' token
  SourceLoc EqualLoc;

  /// The end of the type, valid even when the type cannot be parsed
  SourceLoc TypeEndLoc;

  /// The location of the right-hand side of the typealias binding
  TypeLoc UnderlyingTy;

public:
  TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name,
                SourceLoc NameLoc, GenericParamList *GenericParams,
                DeclContext *DC);

  SourceLoc getStartLoc() const { return TypeAliasLoc; }
  SourceRange getSourceRange() const;

  /// Returns the location of the equal '=' token
  SourceLoc getEqualLoc() const {
    return EqualLoc;
  }

  void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; }

  /// Retrieve the TypeRepr corresponding to the parsed underlying type.
  TypeRepr *getUnderlyingTypeRepr() const {
    return UnderlyingTy.getTypeRepr();
  }
  void setUnderlyingTypeRepr(TypeRepr *repr) {
    UnderlyingTy = repr;
  }
  
  /// Retrieve the interface type of the underlying type.
  Type getUnderlyingType() const;
  void setUnderlyingType(Type type);

  /// For generic typealiases, return the unbound generic type.
  UnboundGenericType *getUnboundGenericType() const;

  /// Retrieve a sugared interface type containing the structure of the interface
  /// type before any semantic validation has occured.
  Type getStructuralType() const;
  
  bool isCompatibilityAlias() const {
    return Bits.TypeAliasDecl.IsCompatibilityAlias;
  }

  void markAsCompatibilityAlias(bool newValue = true) {
    Bits.TypeAliasDecl.IsCompatibilityAlias = newValue;
  }

  /// Is this a special debugger variable?
  bool isDebuggerAlias() const { return Bits.TypeAliasDecl.IsDebuggerAlias; }
  void markAsDebuggerAlias(bool isDebuggerAlias) {
    Bits.TypeAliasDecl.IsDebuggerAlias = isDebuggerAlias;
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::TypeAlias;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::TypeAlias;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
};

/// Abstract class describing generic type parameters and associated types,
/// whose common purpose is to anchor the abstract type parameter and specify
/// requirements for any corresponding type argument.
class AbstractTypeParamDecl : public TypeDecl {
protected:
  AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name,
                        SourceLoc NameLoc)
    : TypeDecl(kind, dc, name, NameLoc, { }) { }

public:
  /// Return the superclass of the generic parameter.
  Type getSuperclass() const;

  /// Retrieve the set of protocols to which this abstract type
  /// parameter conforms.
  ArrayRef<ProtocolDecl *> getConformingProtocols() const;

  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_AbstractTypeParamDecl &&
           D->getKind() <= DeclKind::Last_AbstractTypeParamDecl;
  }
};

/// A declaration of a generic type parameter.
///
/// A generic type parameter introduces a new, named type parameter along
/// with some set of requirements on any type argument used to realize this
/// type parameter. The requirements involve conformances to specific
/// protocols or inheritance from a specific class type.
///
/// In the following example, 'T' is a generic type parameter with the
/// requirement that the type argument conform to the 'Comparable' protocol.
///
/// \code
/// func min<T : Comparable>(x : T, y : T) -> T { ... }
/// \endcode
class GenericTypeParamDecl : public AbstractTypeParamDecl {
public:
  static const unsigned InvalidDepth = 0xFFFF;

  /// Construct a new generic type parameter.
  ///
  /// \param dc The DeclContext in which the generic type parameter's owner
  /// occurs. This should later be overwritten with the actual declaration
  /// context that owns the type parameter.
  ///
  /// \param name The name of the generic parameter.
  /// \param nameLoc The location of the name.
  GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
                       unsigned depth, unsigned index);

  /// The depth of this generic type parameter, i.e., the number of outer
  /// levels of generic parameter lists that enclose this type parameter.
  ///
  /// \code
  /// struct X<T> {
  ///   func f<U>() { }
  /// }
  /// \endcode
  ///
  /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
  unsigned getDepth() const { return Bits.GenericTypeParamDecl.Depth; }

  /// Set the depth of this generic type parameter.
  ///
  /// \sa getDepth
  void setDepth(unsigned depth) {
    Bits.GenericTypeParamDecl.Depth = depth;
    assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation");
  }

  /// The index of this generic type parameter within its generic parameter
  /// list.
  ///
  /// \code
  /// struct X<T, U> {
  ///   func f<V>() { }
  /// }
  /// \endcode
  ///
  /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
  unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; }

  SourceLoc getStartLoc() const { return getNameLoc(); }
  SourceRange getSourceRange() const;

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::GenericTypeParam;
  }
};

/// A declaration of an associated type.
///
/// An associated type introduces a new, named type in a protocol that
/// can vary from one conforming type to the next. Associated types have a
/// set of requirements to which the type that replaces it much realize,
/// described via conformance to specific protocols, or inheritance from a
/// specific class type.
///
/// In the following example, 'Element' is an associated type with no
/// requirements.
///
/// \code
/// protocol Enumerator {
///   typealias Element
///   func getNext() -> Element?
/// }
/// \endcode
class AssociatedTypeDecl : public AbstractTypeParamDecl {
  /// The location of the initial keyword.
  SourceLoc KeywordLoc;

  /// The default definition.
  TypeRepr *DefaultDefinition;

  /// The where clause attached to the associated type.
  TrailingWhereClause *TrailingWhere;

  LazyMemberLoader *Resolver = nullptr;
  uint64_t ResolverContextData;

  friend class DefaultDefinitionTypeRequest;

public:
  AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                     SourceLoc nameLoc, TypeRepr *defaultDefinition,
                     TrailingWhereClause *trailingWhere);
  AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                     SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
                     LazyMemberLoader *definitionResolver,
                     uint64_t resolverData);

  /// Get the protocol in which this associated type is declared.
  ProtocolDecl *getProtocol() const {
    return cast<ProtocolDecl>(getDeclContext());
  }

  /// Check if we have a default definition type.
  bool hasDefaultDefinitionType() const {
    // If we have a TypeRepr, return true immediately without kicking off
    // a request.
    return DefaultDefinition || getDefaultDefinitionType();
  }

  /// Retrieve the default definition type.
  Type getDefaultDefinitionType() const;

  /// Retrieve the default definition as written in the source.
  TypeRepr *getDefaultDefinitionTypeRepr() const {
    return DefaultDefinition;
  }

  /// Retrieve the trailing where clause for this associated type, if any.
  TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; }

  /// Set the trailing where clause for this associated type.
  void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
    TrailingWhere = trailingWhereClause;
  }

  /// Retrieve the associated type "anchor", which is the associated type
  /// declaration that will be used to describe this associated type in the
  /// ABI.
  ///
  /// The associated type "anchor" is an associated type that does not
  /// override any other associated type. There may be several such associated
  /// types; select one deterministically.
  AssociatedTypeDecl *getAssociatedTypeAnchor() const;

  /// Retrieve the (first) overridden associated type declaration, if any.
  AssociatedTypeDecl *getOverriddenDecl() const {
    return cast_or_null<AssociatedTypeDecl>(
                                   AbstractTypeParamDecl::getOverriddenDecl());
  }

  /// Retrieve the set of associated types overridden by this associated
  /// type.
  llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;

  SourceLoc getStartLoc() const { return KeywordLoc; }
  SourceRange getSourceRange() const;

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::AssociatedType;
  }
};

class MemberLookupTable;
class ConformanceLookupTable;
  
// Kinds of pointer types.
enum PointerTypeKind : unsigned {
  PTK_UnsafeMutableRawPointer,
  PTK_UnsafeRawPointer,
  PTK_UnsafeMutablePointer,
  PTK_UnsafePointer,
  PTK_AutoreleasingUnsafeMutablePointer,
};

static inline bool isRawPointerKind(PointerTypeKind PTK) {
  switch (PTK) {
  case PTK_UnsafeMutableRawPointer:
  case PTK_UnsafeRawPointer:
    return true;
  case PTK_UnsafeMutablePointer:
  case PTK_UnsafePointer:
  case PTK_AutoreleasingUnsafeMutablePointer:
    return false;
  }

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

enum KeyPathTypeKind : unsigned char {
  KPTK_AnyKeyPath,
  KPTK_PartialKeyPath,
  KPTK_KeyPath,
  KPTK_WritableKeyPath,
  KPTK_ReferenceWritableKeyPath
};

/// NominalTypeDecl - a declaration of a nominal type, like a struct.
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
  SourceRange Braces;

  /// The first extension of this type.
  ExtensionDecl *FirstExtension = nullptr;

  /// The last extension of this type, used solely for efficient
  /// insertion of new extensions.
  ExtensionDecl *LastExtension = nullptr;

  /// The generation at which we last loaded extensions.
  unsigned ExtensionGeneration;
  
  /// Prepare to traverse the list of extensions.
  void prepareExtensions();

  /// Retrieve the conformance loader (if any), and removing it in the
  /// same operation. The caller is responsible for loading the
  /// conformances.
  std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
    if (!Bits.NominalTypeDecl.HasLazyConformances)
      return { nullptr, 0 };

    return takeConformanceLoaderSlow();
  }

  /// Slow path for \c takeConformanceLoader().
  std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();

  /// A lookup table containing all of the members of this type and
  /// its extensions.
  ///
  /// The table itself is lazily constructed and updated when
  /// lookupDirect() is called. The bit indicates whether the lookup
  /// table has already added members by walking the declarations in
  /// scope; it should be manipulated through \c isLookupTablePopulated()
  /// and \c setLookupTablePopulated().
  llvm::PointerIntPair<MemberLookupTable *, 1, bool> LookupTable;

  /// Prepare the lookup table to make it ready for lookups.
  void prepareLookupTable();

  /// True if the entries in \c LookupTable are complete--that is, if a
  /// name is present, it contains all members with that name.
  bool isLookupTablePopulated() const;
  void setLookupTablePopulated(bool value);

  /// Note that we have added a member into the iterable declaration context,
  /// so that it can also be added to the lookup table (if needed).
  void addedMember(Decl *member);

  /// Note that we have added an extension into the nominal type,
  /// so that its members can eventually be added to the lookup table.
  void addedExtension(ExtensionDecl *ext);

  /// A lookup table used to find the protocol conformances of
  /// a given nominal type.
  mutable ConformanceLookupTable *ConformanceTable = nullptr;

  /// Prepare the conformance table.
  void prepareConformanceTable() const;

  /// Returns the protocol requirements that \c Member conforms to.
  ArrayRef<ValueDecl *>
    getSatisfiedProtocolRequirementsForMember(const ValueDecl *Member,
                                              bool Sorted) const;

  friend class ASTContext;
  friend class MemberLookupTable;
  friend class ConformanceLookupTable;
  friend class ExtensionDecl;
  friend class DeclContext;
  friend class IterableDeclContext;
  friend ArrayRef<ValueDecl *>
           ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const;

protected:
  Type DeclaredTy;
  Type DeclaredInterfaceTy;

  NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
                  SourceLoc NameLoc,
                  MutableArrayRef<TypeLoc> inherited,
                  GenericParamList *GenericParams) :
    GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
    IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
  {
    Bits.NominalTypeDecl.AddedImplicitInitializers = false;
    ExtensionGeneration = 0;
    Bits.NominalTypeDecl.HasLazyConformances = false;
  }

  friend class ProtocolType;

public:
  using GenericTypeDecl::getASTContext;

  SourceRange getBraces() const { return Braces; }
  
  void setBraces(SourceRange braces) { Braces = braces; }

  /// Should this declaration behave as if it must be accessed
  /// resiliently, even when we're building a non-resilient module?
  ///
  /// This is used for diagnostics, because we do not want a behavior
  /// change between builds with resilience enabled and disabled.
  bool isFormallyResilient() const;

  /// Do we need to use resilient access patterns outside of this type's
  /// resilience domain?
  bool isResilient() const;

  /// Do we need to use resilient access patterns when accessing this
  /// type from the given module?
  bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;

  /// Determine whether we have already attempted to add any
  /// implicitly-defined initializers to this declaration.
  bool addedImplicitInitializers() const {
    return Bits.NominalTypeDecl.AddedImplicitInitializers;
  }

  /// Note that we have attempted to add implicit initializers.
  void setAddedImplicitInitializers() {
    Bits.NominalTypeDecl.AddedImplicitInitializers = true;
  }

  /// getDeclaredType - Retrieve the type declared by this entity, without
  /// any generic parameters bound if this is a generic type.
  Type getDeclaredType() const;

  /// getDeclaredInterfaceType - Retrieve the type declared by this entity, with
  /// generic parameters bound if this is a generic type.
  Type getDeclaredInterfaceType() const;

  /// Add a new extension to this nominal type.
  void addExtension(ExtensionDecl *extension);

  /// Retrieve the set of extensions of this type.
  ExtensionRange getExtensions();

  /// Special-behaviour flags passed to lookupDirect()
  enum class LookupDirectFlags {
    /// Whether to include @_implements members.
    /// Used by conformance-checking to find special @_implements members.
    IncludeAttrImplements = 1 << 0,
  };

  /// Find all of the declarations with the given name within this nominal type
  /// and its extensions.
  ///
  /// This routine does not look into superclasses, nor does it consider
  /// protocols to which the nominal type conforms. Furthermore, the resulting
  /// set of declarations has not been filtered for visibility, nor have
  /// overridden declarations been removed.
  TinyPtrVector<ValueDecl *> lookupDirect(DeclName name,
                                          OptionSet<LookupDirectFlags> flags =
                                          OptionSet<LookupDirectFlags>());

  /// Collect the set of protocols to which this type should implicitly
  /// conform, such as AnyObject (for classes).
  void getImplicitProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);

  /// Look for conformances of this nominal type to the given
  /// protocol.
  ///
  /// \param module The module from which we initiate the search.
  /// FIXME: This is currently unused.
  ///
  /// \param protocol The protocol whose conformance is requested.
  /// \param conformances Will be populated with the set of protocol
  /// conformances found for this protocol.
  ///
  /// \returns true if any conformances were found. 
  bool lookupConformance(
         ModuleDecl *module, ProtocolDecl *protocol,
         SmallVectorImpl<ProtocolConformance *> &conformances) const;

  /// Retrieve all of the protocols that this nominal type conforms to.
  SmallVector<ProtocolDecl *, 2> getAllProtocols() const;

  /// Retrieve all of the protocol conformances for this nominal type.
  SmallVector<ProtocolConformance *, 2> getAllConformances(
                                          bool sorted = false) const;

  /// Register an externally-created protocol conformance in the
  /// conformance lookup table.
  ///
  /// This is used by deserialization of module files to report
  /// conformances.
  void registerProtocolConformance(ProtocolConformance *conformance);

  void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

  /// Is this the decl for Optional<T>?
  bool isOptionalDecl() const;

  /// Is this a key path type?
  Optional<KeyPathTypeKind> getKeyPathTypeKind() const;

  /// Retrieve information about this type as a property wrapper.
  PropertyWrapperTypeInfo getPropertyWrapperTypeInfo() const;

  // SWIFT_ENABLE_TENSORFLOW
  /// Get effective memberwise initializer for the given nominal type, if it
  /// exists: either a synthesized memberwise initializer or a user-defined
  /// initializer with the same signature.
  ConstructorDecl *getEffectiveMemberwiseInitializer();

  // SWIFT_ENABLE_TENSORFLOW
  /// Add `@_fixed_layout` attribute to the nominal type, if possible.
  void addFixedLayoutAttr();

private:
  /// Predicate used to filter StoredPropertyRange.
  struct ToStoredProperty {
    ToStoredProperty(bool skipInaccessible = false) :
        skipUserInaccessible(skipInaccessible) {}
    bool skipUserInaccessible;
    Optional<VarDecl *> operator()(Decl *decl) const;
  };
  
public:
  /// A range for iterating the stored member variables of a structure.
  using StoredPropertyRange = OptionalTransformRange<DeclRange,
                                                     ToStoredProperty>;

  /// Return a collection of the stored member variables of this type.
  ArrayRef<VarDecl *> getStoredProperties() const;

  /// Return a collection of the stored member variables of this type, along
  /// with placeholders for unimportable stored properties.
  ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_NominalTypeDecl &&
           D->getKind() <= DeclKind::Last_NominalTypeDecl;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() >= DeclKind::First_NominalTypeDecl &&
           D->getKind() <= DeclKind::Last_NominalTypeDecl;
  }

  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    return C->getIterableContextKind()
             == IterableDeclContextKind::NominalTypeDecl;
  }
  static bool classof(const NominalTypeDecl *D) { return true; }
  static bool classof(const ExtensionDecl *D) { return false; }
};

/// This is the declaration of an enum.
///
/// For example:
///
/// \code
///    enum Bool {
///      case false
///      case true
///    }
///
///    enum Optional<T> {
///      case none
///      case some(T)
///    }
/// \endcode
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Bool" or "Optional" in the above example).
class EnumDecl final : public NominalTypeDecl {
  SourceLoc EnumLoc;

  enum SemanticInfoFlags : uint8_t {
    // Is the raw type valid?
    HasComputedRawType         = 1 << 0,
    // Is the complete set of (auto-incremented) raw values available?
    HasFixedRawValues          = 1 << 1,
    // Is the complete set of raw values type checked?
    HasFixedRawValuesAndTypes  = 1 << 2,
  };
  
  struct {
    /// The raw type and a bit to indicate whether the
    /// raw was computed yet or not.
    llvm::PointerIntPair<Type, 3, OptionSet<SemanticInfoFlags>> RawTypeAndFlags;
    
    bool hasRawType() const {
      return RawTypeAndFlags.getInt().contains(HasComputedRawType);
    }
    void cacheRawType(Type ty) {
      auto flags = RawTypeAndFlags.getInt() | HasComputedRawType;
      RawTypeAndFlags.setPointerAndInt(ty, flags);
    }
    
    bool hasFixedRawValues() const {
      return RawTypeAndFlags.getInt().contains(HasFixedRawValues);
    }
    bool hasCheckedRawValues() const {
      return RawTypeAndFlags.getInt().contains(HasFixedRawValuesAndTypes);
    }
  } LazySemanticInfo;

  friend class EnumRawValuesRequest;
  friend class EnumRawTypeRequest;
  friend class TypeChecker;

public:
  EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc,
            MutableArrayRef<TypeLoc> Inherited,
            GenericParamList *GenericParams, DeclContext *DC);

  SourceLoc getStartLoc() const { return EnumLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(EnumLoc, getBraces().End);
  }

public:
  /// A range for iterating the elements of an enum.
  using ElementRange = DowncastFilterRange<EnumElementDecl, DeclRange>;

  /// A range for iterating the cases of an enum.
  using CaseRange = DowncastFilterRange<EnumCaseDecl, DeclRange>;

  /// Return a range that iterates over all the elements of an enum.
  ElementRange getAllElements() const {
    return ElementRange(getMembers());
  }

  unsigned getNumElements() const {
    auto eltRange = getAllElements();
    return std::distance(eltRange.begin(), eltRange.end());
  }

  /// If this enum has a unique element, return it. A unique element can
  /// either hold a value or not, and the existence of one unique element does
  /// not imply the existence or non-existence of the opposite unique element.
  EnumElementDecl *getUniqueElement(bool hasValue) const;

  /// Return a range that iterates over all the cases of an enum.
  CaseRange getAllCases() const {
    return CaseRange(getMembers());
  }

  /// Insert all of the 'case' element declarations into a DenseSet.
  void getAllElements(llvm::DenseSet<EnumElementDecl*> &elements) const {
    for (auto elt : getAllElements())
      elements.insert(elt);
  }
  
  /// Retrieve the status of circularity checking for class inheritance.
  CircularityCheck getCircularityCheck() const {
    return static_cast<CircularityCheck>(Bits.EnumDecl.Circularity);
  }
  
  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    Bits.EnumDecl.Circularity = static_cast<unsigned>(circularity);
  }
  
  /// Record that this enum has had all of its raw values computed.
  void setHasFixedRawValues();
  
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    auto NTD = dyn_cast<NominalTypeDecl>(C);
    return NTD && classof(NTD);
  }
  
  /// Determine whether this enum declares a raw type in its inheritance clause.
  bool hasRawType() const { return (bool)getRawType(); }

  /// Retrieve the declared raw type of the enum from its inheritance clause,
  /// or null if it has none.
  Type getRawType() const;

  /// Set the raw type of the enum from its inheritance clause.
  void setRawType(Type rawType) {
    auto flags = LazySemanticInfo.RawTypeAndFlags.getInt();
    LazySemanticInfo.RawTypeAndFlags.setPointerAndInt(
        rawType, flags | HasComputedRawType);
  }

  /// True if none of the enum cases have associated values.
  ///
  /// Note that this is true for enums with absolutely no cases.
  bool hasOnlyCasesWithoutAssociatedValues() const;

  /// True if any of the enum cases have availability annotations.
  ///
  /// Note that this is false for enums with absolutely no cases.
  bool hasPotentiallyUnavailableCaseValue() const;

  /// True if the enum has cases.
  bool hasCases() const {
    return !getAllElements().empty();
  }

  /// True if the enum is marked 'indirect'.
  bool isIndirect() const {
    return getAttrs().hasAttribute<IndirectAttr>();
  }

  /// True if the enum can be exhaustively switched within \p useDC.
  ///
  /// Note that this property is \e not necessarily true for all children of
  /// \p useDC. In particular, an inlinable function does not get to switch
  /// exhaustively over a non-exhaustive enum declared in the same module.
  ///
  /// This is the predicate used when deciding if a switch statement needs a
  /// default case. It should not be used for optimization or code generation.
  ///
  /// \sa isEffectivelyExhaustive
  bool isFormallyExhaustive(const DeclContext *useDC) const;

  /// True if the enum can be exhaustively switched within a function defined
  /// within \p M, with \p expansion specifying whether the function is
  /// inlinable.
  ///
  /// This is the predicate used when making optimization and code generation
  /// decisions. It should not be used at the AST or semantic level.
  ///
  /// \sa isFormallyExhaustive
  bool isEffectivelyExhaustive(ModuleDecl *M,
                               ResilienceExpansion expansion) const;
};

/// StructDecl - This is the declaration of a struct, for example:
///
///    struct Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class StructDecl final : public NominalTypeDecl {
  SourceLoc StructLoc;

public:
  StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
             MutableArrayRef<TypeLoc> Inherited,
             GenericParamList *GenericParams, DeclContext *DC);

  SourceLoc getStartLoc() const { return StructLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(StructLoc, getBraces().End);
  }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Struct;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::Struct;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Struct;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    auto NTD = dyn_cast<NominalTypeDecl>(C);
    return NTD && classof(NTD);
  }

  /// Does this struct contain unreferenceable storage, such as C fields that
  /// cannot be represented in Swift?
  bool hasUnreferenceableStorage() const {
    return Bits.StructDecl.HasUnreferenceableStorage;
  }

  void setHasUnreferenceableStorage(bool v) {
    Bits.StructDecl.HasUnreferenceableStorage = v;
  }
};

/// The kind of artificial main to generate for a class.
enum class ArtificialMainKind : uint8_t {
  NSApplicationMain,
  UIApplicationMain,
};

/// This is the base type for AncestryOptions. Each flag describes possible
/// interesting kinds of superclasses that a class may have.
enum class AncestryFlags : uint8_t {
  /// The class or one of its superclasses is @objc.
  ObjC = (1<<0),

  /// The class or one of its superclasses is @objcMembers.
  ObjCMembers = (1<<1),

  /// The class or one of its superclasses is generic.
  Generic = (1<<2),

  /// The class or one of its superclasses is resilient.
  Resilient = (1<<3),

  /// The class or one of its superclasses has resilient metadata and is in a
  /// different resilience domain.
  ResilientOther = (1<<4),

  /// The class or one of its superclasses is imported from Clang.
  ClangImported = (1<<5),

  /// The class or one of its superclasses requires stored property initializers.
  RequiresStoredPropertyInits = (1<<6),
};

/// Return type of ClassDecl::checkAncestry(). Describes a set of interesting
/// kinds of superclasses that a class may have.
using AncestryOptions = OptionSet<AncestryFlags>;

/// ClassDecl - This is the declaration of a class, for example:
///
///    class Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class ClassDecl final : public NominalTypeDecl {
  class ObjCMethodLookupTable;

  SourceLoc ClassLoc;
  ObjCMethodLookupTable *ObjCMethodLookup = nullptr;

  /// Create the Objective-C member lookup table.
  void createObjCMethodLookup();

  struct {
    /// The superclass decl and a bit to indicate whether the
    /// superclass was computed yet or not.
    llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;

    /// The superclass type and a bit to indicate whether the
    /// superclass was computed yet or not.
    llvm::PointerIntPair<Type, 1, bool> SuperclassType;
  } LazySemanticInfo;

  bool hasForcedEmittedMembers() const {
    return Bits.ClassDecl.HasForcedEmittedMembers;
  }

  void setHasForcedEmittedMembers() {
    Bits.ClassDecl.HasForcedEmittedMembers = true;
  }

  friend class SuperclassDeclRequest;
  friend class SuperclassTypeRequest;
  friend class EmittedMembersRequest;
  friend class TypeChecker;

public:
  ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
            MutableArrayRef<TypeLoc> Inherited,
            GenericParamList *GenericParams, DeclContext *DC);

  SourceLoc getStartLoc() const { return ClassLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(ClassLoc, getBraces().End);
  }

  /// Determine whether the member area of this class's metadata (which consists
  /// of field offsets and vtable entries) is to be considered opaque by clients.
  ///
  /// Note that even @_fixed_layout classes have resilient metadata if they are
  /// in a resilient module.
  bool hasResilientMetadata() const;

  /// Determine whether this class has resilient metadata when accessed from the
  /// given module and resilience expansion.
  bool hasResilientMetadata(ModuleDecl *M, ResilienceExpansion expansion) const;

  /// Determine whether this class has a superclass.
  bool hasSuperclass() const { return (bool)getSuperclassDecl(); }

  /// Retrieve the superclass of this class, or null if there is no superclass.
  Type getSuperclass() const;

  /// Retrieve the ClassDecl for the superclass of this class, or null if there
  /// is no superclass.
  ClassDecl *getSuperclassDecl() const;

  /// Check if this class is a superclass or equal to the given class.
  bool isSuperclassOf(ClassDecl *other) const;

  /// Set the superclass of this class.
  void setSuperclass(Type superclass);

  /// Retrieve the status of circularity checking for class inheritance.
  CircularityCheck getCircularityCheck() const {
    return static_cast<CircularityCheck>(Bits.ClassDecl.Circularity);
  }

  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    Bits.ClassDecl.Circularity = static_cast<unsigned>(circularity);
  }

  /// Walk this class and all of the superclasses of this class, transitively,
  /// invoking the callback function for each class.
  ///
  /// \param fn The callback function that will be invoked for each superclass.
  /// It can return \c Continue to continue the traversal. Returning
  /// \c SkipChildren halts the search and returns \c false, while returning
  /// \c Stop halts the search and returns \c true.
  ///
  /// \returns \c true if \c fn returned \c Stop for any class, \c false
  /// otherwise.
  bool walkSuperclasses(
      llvm::function_ref<TypeWalker::Action(ClassDecl *)> fn) const;

  //// Whether this class requires all of its stored properties to
  //// have initializers in the class definition.
  bool requiresStoredPropertyInits() const {
    return checkAncestry(AncestryFlags::RequiresStoredPropertyInits);
  }

  /// \see getForeignClassKind
  enum class ForeignKind : uint8_t {
    /// A normal Swift or Objective-C class.
    Normal = 0,
    /// An imported Core Foundation type. These are AnyObject-compatible but
    /// do not have runtime metadata.
    CFType,
    /// An imported Objective-C type whose class and metaclass symbols are not
    /// both available at link-time but can be accessed through the Objective-C
    /// runtime.
    RuntimeOnly
  };

  /// Whether this class is "foreign", meaning that it is implemented
  /// by a runtime that Swift does not have first-class integration
  /// with.  This generally means that:
  ///   - class data is either abstracted or cannot be made to
  ///     fit with Swift's metatype schema, and/or
  ///   - there is no facility for subclassing or adding polymorphic
  ///     methods to the class.
  ///
  /// We may find ourselves wanting to break this bit into more
  /// precise chunks later.
  ForeignKind getForeignClassKind() const {
    return static_cast<ForeignKind>(Bits.ClassDecl.RawForeignKind);
  }
  void setForeignClassKind(ForeignKind kind) {
    Bits.ClassDecl.RawForeignKind = static_cast<unsigned>(kind);
  }

  /// Returns true if this class is any kind of "foreign class".
  ///
  /// \see getForeignClassKind
  bool isForeign() const {
    return getForeignClassKind() != ForeignKind::Normal;
  }

  /// Returns true if the class has designated initializers that are not listed
  /// in its members.
  ///
  /// This can occur, for example, if the class is an Objective-C class with
  /// initializers that cannot be represented in Swift.
  bool hasMissingDesignatedInitializers() const;

  void setHasMissingDesignatedInitializers(bool newValue = true) {
    Bits.ClassDecl.ComputedHasMissingDesignatedInitializers = 1;
    Bits.ClassDecl.HasMissingDesignatedInitializers = newValue;
  }

  /// Returns true if the class has missing members that require vtable entries.
  ///
  /// In this case, the class cannot be subclassed, because we cannot construct
  /// the vtable for the subclass.
  bool hasMissingVTableEntries() const;

  void setHasMissingVTableEntries(bool newValue = true) {
    Bits.ClassDecl.ComputedHasMissingVTableEntries = 1;
    Bits.ClassDecl.HasMissingVTableEntries = newValue;
  }

  /// Returns true if this class cannot be used with weak or unowned
  /// references.
  /// 
  /// Note that this is true if this class or any of its ancestor classes
  /// are marked incompatible.
  bool isIncompatibleWithWeakReferences() const;

  void setIsIncompatibleWithWeakReferences(bool newValue = true) {
    Bits.ClassDecl.IsIncompatibleWithWeakReferences = newValue;
  }

  /// Find a method of a class that overrides a given method.
  /// Return nullptr, if no such method exists.
  AbstractFunctionDecl *findOverridingDecl(
      const AbstractFunctionDecl *method) const;

  /// Find a method implementation which will be used when a given method
  /// is invoked on an instance of this class. This implementation may stem
  /// either from a class itself or its direct or indirect superclasses.
  AbstractFunctionDecl *findImplementingMethod(
      const AbstractFunctionDecl *method) const;
  
  /// Retrieve the destructor for this class.
  DestructorDecl *getDestructor() const;

  /// Determine whether this class inherits the convenience initializers
  /// from its superclass.
  bool inheritsSuperclassInitializers();

  /// Marks that this class inherits convenience initializers from its
  /// superclass.
  ///
  /// This is computed as part of adding implicit initializers.
  void setInheritsSuperclassInitializers() {
    assert(addedImplicitInitializers());
    Bits.ClassDecl.InheritsSuperclassInits = true;
  }

  /// Walks the class hierarchy starting from this class, checking various
  /// conditions.
  AncestryOptions checkAncestry() const;

  /// Check if the class has ancestry of the given kind.
  bool checkAncestry(AncestryFlags flag) const {
    return checkAncestry().contains(flag);
  }

  /// The type of metaclass to use for a class.
  enum class MetaclassKind : uint8_t {
    ObjC,
    SwiftStub,
  };

  /// Determine which sort of metaclass to use for this class
  MetaclassKind getMetaclassKind() const;

  /// Retrieve the name to use for this class when interoperating with
  /// the Objective-C runtime.
  StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;

  /// Returns the appropriate kind of entry point to generate for this class,
  /// based on its attributes.
  ///
  /// It is an error to call this on a class that does not have a
  /// *ApplicationMain attribute.
  ArtificialMainKind getArtificialMainKind() const;

  using NominalTypeDecl::lookupDirect;

  /// Look in this class and its extensions (but not any of its protocols or
  /// superclasses) for declarations with a given Objective-C selector.
  ///
  /// Note that this can find methods, initializers, deinitializers,
  /// getters, and setters.
  ///
  /// \param selector The Objective-C selector of the method we're
  /// looking for.
  ///
  /// \param isInstance Whether we are looking for an instance method
  /// (vs. a class method).
  MutableArrayRef<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
                                                       bool isInstance);

  /// Record the presence of an @objc method with the given selector.
  void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector);

  /// Get all the members of this class, synthesizing any implicit members
  /// that appear in the vtable if needed.
  DeclRange getEmittedMembers() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Class;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::Class;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Class;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    auto NTD = dyn_cast<NominalTypeDecl>(C);
    return NTD && classof(NTD);
  }
  
  /// Returns true if the decl uses the Objective-C generics model.
  ///
  /// This is true of imported Objective-C classes.
  bool usesObjCGenericsModel() const {
    return hasClangNode() && isGenericContext() && isObjC();
  }
  
  /// True if the class is known to be implemented in Swift.
  bool hasKnownSwiftImplementation() const {
    return !hasClangNode();
  }
};


/// Describes whether a requirement refers to 'Self', for use in the
/// is-inheritable and is-available-existential checks.
struct SelfReferenceKind {
  bool result;
  bool parameter;
  bool requirement;
  bool other;

  /// The type does not refer to 'Self' at all.
  static SelfReferenceKind None() {
    return SelfReferenceKind(false, false, false, false);
  }

  /// The type refers to 'Self', but only as the result type of a method.
  static SelfReferenceKind Result() {
    return SelfReferenceKind(true, false, false, false);
  }

  /// The type refers to 'Self', but only as the parameter type of a method.
  static SelfReferenceKind Parameter() {
    return SelfReferenceKind(false, true, false, false);
  }

  /// The type refers to 'Self' within a same-type requiement.
  static SelfReferenceKind Requirement() {
    return SelfReferenceKind(false, false, true, false);
  }

  /// The type refers to 'Self' in a position that is invariant.
  static SelfReferenceKind Other() {
    return SelfReferenceKind(false, false, false, true);
  }

  SelfReferenceKind flip() const {
    return SelfReferenceKind(parameter, result, requirement, other);
  }

  SelfReferenceKind operator|=(SelfReferenceKind kind) {
    result |= kind.result;
    requirement |= kind.requirement;
    parameter |= kind.parameter;
    other |= kind.other;
    return *this;
  }

  operator bool() const {
    return result || parameter || requirement || other;
  }

private:
  SelfReferenceKind(bool result, bool parameter, bool requirement, bool other)
    : result(result), parameter(parameter), requirement(requirement),
      other(other) { }
};

/// ProtocolDecl - A declaration of a protocol, for example:
///
///   protocol Drawable {
///     func draw()
///   }
///
/// Every protocol has an implicitly-created 'Self' generic parameter that
/// stands for a type that conforms to the protocol. For example,
///
///   protocol Cloneable {
///     func clone() -> Self
///   }
///
class ProtocolDecl final : public NominalTypeDecl {
  SourceLoc ProtocolLoc;

  ArrayRef<ProtocolDecl *> InheritedProtocols;

  struct {
    /// The superclass decl and a bit to indicate whether the
    /// superclass was computed yet or not.
    llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;

    /// The superclass type and a bit to indicate whether the
    /// superclass was computed yet or not.
    llvm::PointerIntPair<Type, 1, bool> SuperclassType;
  } LazySemanticInfo;

  /// The generic signature representing exactly the new requirements introduced
  /// by this protocol.
  const Requirement *RequirementSignature = nullptr;

  /// Returns the cached result of \c requiresClass or \c None if it hasn't yet
  /// been computed.
  Optional<bool> getCachedRequiresClass() const {
    if (Bits.ProtocolDecl.RequiresClassValid)
      return Bits.ProtocolDecl.RequiresClass;

    return None;
  }

  /// Caches the result of \c requiresClass
  void setCachedRequiresClass(bool requiresClass) {
    Bits.ProtocolDecl.RequiresClassValid = true;
    Bits.ProtocolDecl.RequiresClass = requiresClass;
  }

  /// Returns the cached result of \c existentialConformsToSelf or \c None if it
  /// hasn't yet been computed.
  Optional<bool> getCachedExistentialConformsToSelf() const {
    if (Bits.ProtocolDecl.ExistentialConformsToSelfValid)
      return Bits.ProtocolDecl.ExistentialConformsToSelf;

    return None;
  }

  /// Caches the result of \c existentialConformsToSelf
  void setCachedExistentialConformsToSelf(bool result) {
    Bits.ProtocolDecl.ExistentialConformsToSelfValid = true;
    Bits.ProtocolDecl.ExistentialConformsToSelf = result;
  }

  /// Returns the cached result of \c existentialTypeSupported or \c None if it
  /// hasn't yet been computed.
  Optional<bool> getCachedExistentialTypeSupported() {
    if (Bits.ProtocolDecl.ExistentialTypeSupportedValid)
      return Bits.ProtocolDecl.ExistentialTypeSupported;

    return None;
  }

  /// Caches the result of \c existentialTypeSupported
  void setCachedExistentialTypeSupported(bool supported) {
    Bits.ProtocolDecl.ExistentialTypeSupportedValid = true;
    Bits.ProtocolDecl.ExistentialTypeSupported = supported;
  }

  ArrayRef<ProtocolDecl *> getInheritedProtocolsSlow();

  bool hasLazyRequirementSignature() const {
    return Bits.ProtocolDecl.HasLazyRequirementSignature;
  }

  friend class SuperclassDeclRequest;
  friend class SuperclassTypeRequest;
  friend class RequirementSignatureRequest;
  friend class ProtocolRequiresClassRequest;
  friend class ExistentialConformsToSelfRequest;
  friend class ExistentialTypeSupportedRequest;
  friend class TypeChecker;

public:
  ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
               Identifier Name, MutableArrayRef<TypeLoc> Inherited,
               TrailingWhereClause *TrailingWhere);

  using Decl::getASTContext;

  /// Retrieve the set of protocols inherited from this protocol.
  ArrayRef<ProtocolDecl *> getInheritedProtocols() const {
    if (Bits.ProtocolDecl.InheritedProtocolsValid)
      return InheritedProtocols;

    return const_cast<ProtocolDecl *>(this)->getInheritedProtocolsSlow();
  }

  /// Determine whether this protocol has a superclass.
  bool hasSuperclass() const { return (bool)getSuperclassDecl(); }

  /// Retrieve the superclass of this protocol, or null if there is no superclass.
  Type getSuperclass() const;

  /// Retrieve the ClassDecl for the superclass of this protocol, or null if there
  /// is no superclass.
  ClassDecl *getSuperclassDecl() const;

  /// Set the superclass of this protocol.
  void setSuperclass(Type superclass);

  /// Retrieve the set of AssociatedTypeDecl members of this protocol; this
  /// saves loading the set of members in cases where there's no possibility of
  /// a protocol having nested types (ObjC protocols).
  llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() const;

  /// Returns a protocol requirement with the given name, or nullptr if the
  /// name has multiple overloads, or no overloads at all.
  ValueDecl *getSingleRequirement(DeclName name) const;

  /// Returns an associated type with the given name, or nullptr if one does
  /// not exist.
  AssociatedTypeDecl *getAssociatedType(Identifier name) const;

  /// Walk this protocol and all of the protocols inherited by this protocol,
  /// transitively, invoking the callback function for each protocol.
  ///
  /// \param fn The callback function that will be invoked for each inherited
  /// protocol. It can return \c Continue to continue the traversal,
  /// \c SkipChildren to avoid visiting the children of the given protocol
  /// but continue the search, and \c Stop to halt the search.
  ///
  /// \returns \c true if \c fn returned \c Stop for any protocol, \c false
  /// otherwise.
  bool walkInheritedProtocols(
               llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const;

  /// Determine whether this protocol inherits from the given ("super")
  /// protocol.
  bool inheritsFrom(const ProtocolDecl *Super) const;
  
  ProtocolType *getDeclaredType() const {
    return reinterpret_cast<ProtocolType *>(
      NominalTypeDecl::getDeclaredType().getPointer());
  }
  
  SourceLoc getStartLoc() const { return ProtocolLoc; }
  SourceRange getSourceRange() const {
    return SourceRange(ProtocolLoc, getBraces().End);
  }

  /// True if this protocol can only be conformed to by class types.
  bool requiresClass() const;

  /// Determine whether an existential conforming to this protocol can be
  /// matched with a generic type parameter constrained to this protocol.
  /// This is only permitted if there is nothing "non-trivial" that we
  /// can do with the metatype, which means the protocol must not have
  /// any static methods and must be declared @objc.
  bool existentialConformsToSelf() const;

  /// Does this protocol require a self-conformance witness table?
  bool requiresSelfConformanceWitnessTable() const;

  /// Find direct Self references within the given requirement.
  ///
  /// \param allowCovariantParameters If true, 'Self' is assumed to be
  /// covariant anywhere; otherwise, only in the return type of the top-level
  /// function type.
  ///
  /// \param skipAssocTypes If true, associated types of 'Self' are ignored;
  /// otherwise, they count as an 'other' usage of 'Self'.
  SelfReferenceKind findProtocolSelfReferences(const ValueDecl *decl,
                                               bool allowCovariantParameters,
                                               bool skipAssocTypes) const;

  /// Determine whether we are allowed to refer to an existential type
  /// conforming to this protocol. This is only permitted if the type of
  /// the member does not contain any associated types, and does not
  /// contain 'Self' in 'parameter' or 'other' position.
  bool isAvailableInExistential(const ValueDecl *decl) const;

  /// Determine whether we are allowed to refer to an existential type
  /// conforming to this protocol. This is only permitted if the types of
  /// all the members do not contain any associated types, and do not
  /// contain 'Self' in 'parameter' or 'other' position.
  bool existentialTypeSupported() const;

private:
  void computeKnownProtocolKind() const;

public:
  /// If this is known to be a compiler-known protocol, returns the kind.
  /// Otherwise returns None.
  Optional<KnownProtocolKind> getKnownProtocolKind() const {
    if (Bits.ProtocolDecl.KnownProtocol == 0)
      computeKnownProtocolKind();

    if (Bits.ProtocolDecl.KnownProtocol == 1)
      return None;
    
    return static_cast<KnownProtocolKind>(Bits.ProtocolDecl.KnownProtocol - 2);
  }

  /// Check whether this protocol is of a specific, known protocol kind.
  bool isSpecificProtocol(KnownProtocolKind kind) const {
    if (auto knownKind = getKnownProtocolKind())
      return *knownKind == kind;

    return false;
  }

  /// Retrieve the status of circularity checking for protocol inheritance.
  CircularityCheck getCircularityCheck() const {
    return static_cast<CircularityCheck>(Bits.ProtocolDecl.Circularity);
  }

  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    Bits.ProtocolDecl.Circularity = static_cast<unsigned>(circularity);
  }

  /// Returns true if the protocol has requirements that are not listed in its
  /// members.
  ///
  /// This can occur, for example, if the protocol is an Objective-C protocol
  /// with requirements that cannot be represented in Swift.
  bool hasMissingRequirements() const {
    (void)getMembers();
    return Bits.ProtocolDecl.HasMissingRequirements;
  }

  void setHasMissingRequirements(bool newValue) {
    Bits.ProtocolDecl.HasMissingRequirements = newValue;
  }

  /// Returns the default type witness for an associated type, or a null
  /// type if there is no default.
  Type getDefaultTypeWitness(AssociatedTypeDecl *assocType) const;

  /// Set the default type witness for an associated type.
  void setDefaultTypeWitness(AssociatedTypeDecl *assocType, Type witness);

  /// Returns the default witness for a requirement, or nullptr if there is
  /// no default.
  Witness getDefaultWitness(ValueDecl *requirement) const;

  /// Record the default witness for a requirement.
  void setDefaultWitness(ValueDecl *requirement, Witness witness);

  /// Returns the default associated conformance witness for an associated
  /// type, or \c None if there is no default.
  Optional<ProtocolConformanceRef> getDefaultAssociatedConformanceWitness(
                                              CanType association,
                                              ProtocolDecl *requirement) const;

  /// Set the default associated conformance witness for the given
  /// associated conformance.
  void setDefaultAssociatedConformanceWitness(
                                            CanType association,
                                            ProtocolDecl *requirement,
                                            ProtocolConformanceRef conformance);

  /// Retrieve the name to use for this protocol when interoperating
  /// with the Objective-C runtime.
  StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;

  /// Retrieve the requirements that describe this protocol.
  ///
  /// These are the requirements including any inherited protocols
  /// and conformances for associated types that are introduced in this
  /// protocol. Requirements implied via any other protocol (e.g., inherited
  /// protocols of the inherited protocols) are not mentioned. The conformance
  /// requirements listed here become entries in the witness table.
  ArrayRef<Requirement> getRequirementSignature() const;

  /// Is the requirement signature currently being computed?
  bool isComputingRequirementSignature() const;

  /// Has the requirement signature been computed yet?
  bool isRequirementSignatureComputed() const {
    return RequirementSignature != nullptr;
  }

  void setRequirementSignature(ArrayRef<Requirement> requirements);

  void setLazyRequirementSignature(LazyMemberLoader *lazyLoader,
                                   uint64_t requirementSignatureData);

private:
  ArrayRef<Requirement> getCachedRequirementSignature() const;

public:
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Protocol;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::Protocol;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Protocol;
  }
  static bool classof(const DeclContext *C) {
    if (auto D = C->getAsDecl())
      return classof(D);
    return false;
  }
  static bool classof(const IterableDeclContext *C) {
    auto NTD = dyn_cast<NominalTypeDecl>(C);
    return NTD && classof(NTD);
  }
};

/// AbstractStorageDecl - This is the common superclass for VarDecl and
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
  friend class SetterAccessLevelRequest;
  friend class IsGetterMutatingRequest;
  friend class IsSetterMutatingRequest;
  friend class OpaqueReadOwnershipRequest;
  friend class StorageImplInfoRequest;
  friend class RequiresOpaqueAccessorsRequest;
  friend class RequiresOpaqueModifyCoroutineRequest;
  friend class SynthesizeAccessorRequest;

public:
  static const size_t MaxNumAccessors = 255;
private:
  /// A record of the accessors for the declaration.
  class alignas(1 << 3) AccessorRecord final :
      private llvm::TrailingObjects<AccessorRecord, AccessorDecl*> {
    friend TrailingObjects;

    using AccessorIndex = uint8_t;
    static const AccessorIndex InvalidIndex = 0;

    /// The range of the braces around the accessor clause.
    SourceRange Braces;

    /// The number of accessors currently stored in this record.
    AccessorIndex NumAccessors;

    /// The storage capacity of this record for accessors.  Always includes
    /// enough space for adding opaque accessors to the record, which are the
    /// only accessors that should ever be added retroactively; hence this
    /// field is only here for the purposes of safety checks.
    AccessorIndex AccessorsCapacity;

    /// Either 0, meaning there is no registered accessor of the given kind,
    /// or the index+1 of the accessor in the accessors array.
    AccessorIndex AccessorIndices[NumAccessorKinds];

    AccessorRecord(SourceRange braces,
                   ArrayRef<AccessorDecl*> accessors,
                   AccessorIndex accessorsCapacity);
  public:
    static AccessorRecord *create(ASTContext &ctx, SourceRange braces,
                                  ArrayRef<AccessorDecl*> accessors);

    SourceRange getBracesRange() const { return Braces; }

    inline AccessorDecl *getAccessor(AccessorKind kind) const;

    ArrayRef<AccessorDecl *> getAllAccessors() const {
      return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
    }

    void addOpaqueAccessor(AccessorDecl *accessor);

  private:
    MutableArrayRef<AccessorDecl *> getAccessorsBuffer() {
      return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
    }

    bool registerAccessor(AccessorDecl *accessor, AccessorIndex index);
  };

  llvm::PointerIntPair<AccessorRecord*, 3, OptionalEnum<AccessLevel>> Accessors;

  struct {
    unsigned IsGetterMutatingComputed : 1;
    unsigned IsGetterMutating : 1;
    unsigned IsSetterMutatingComputed : 1;
    unsigned IsSetterMutating : 1;
    unsigned OpaqueReadOwnershipComputed : 1;
    unsigned OpaqueReadOwnership : 2;
    unsigned ImplInfoComputed : 1;
    unsigned RequiresOpaqueAccessorsComputed : 1;
    unsigned RequiresOpaqueAccessors : 1;
    unsigned RequiresOpaqueModifyCoroutineComputed : 1;
    unsigned RequiresOpaqueModifyCoroutine : 1;
  } LazySemanticInfo = { };

  /// The implementation info for the accessors.
  StorageImplInfo ImplInfo;

  /// Add a synthesized accessor.
  void setSynthesizedAccessor(AccessorKind kind, AccessorDecl *getter);

protected:
  AbstractStorageDecl(DeclKind Kind, bool IsStatic, DeclContext *DC,
                      DeclName Name, SourceLoc NameLoc,
                      StorageIsMutable_t supportsMutation)
    : ValueDecl(Kind, DC, Name, NameLoc),
      ImplInfo(StorageImplInfo::getSimpleStored(supportsMutation)) {
    Bits.AbstractStorageDecl.IsStatic = IsStatic;
  }

public:

  /// Should this declaration be treated as if annotated with transparent
  /// attribute.
  bool isTransparent() const;

  /// Is this a type ('static') variable?
  bool isStatic() const {
    return Bits.AbstractStorageDecl.IsStatic;
  }
  void setStatic(bool IsStatic) {
    Bits.AbstractStorageDecl.IsStatic = IsStatic;
  }

  /// \returns the way 'static'/'class' should be spelled for this declaration.
  StaticSpellingKind getCorrectStaticSpelling() const;

  /// Return the interface type of the stored value.
  Type getValueInterfaceType() const;

  /// Determine how this storage is implemented.
  StorageImplInfo getImplInfo() const;

  /// Overwrite the registered implementation-info.  This should be
  /// used carefully.
  void setImplInfo(StorageImplInfo implInfo) {
    LazySemanticInfo.ImplInfoComputed = 1;
    ImplInfo = implInfo;
  }

  ReadImplKind getReadImpl() const {
    return getImplInfo().getReadImpl();
  }
  WriteImplKind getWriteImpl() const {
    return getImplInfo().getWriteImpl();
  }
  ReadWriteImplKind getReadWriteImpl() const {
    return getImplInfo().getReadWriteImpl();
  }


  /// Return true if this is a VarDecl that has storage associated with
  /// it.
  bool hasStorage() const {
    return getImplInfo().hasStorage();
  }

  /// Return true if this storage has the basic accessors/capability
  /// to be mutated.  This is generally constant after the accessors are
  /// installed by the parser/importer/whatever.
  ///
  /// Note that this is different from the mutability of the declaration
  /// in the user language: sometimes we can assign to declarations that
  /// don't support mutation (e.g. to initialize them), and sometimes we
  /// can't mutate things that do support mutation (e.g. because their
  /// setter is private).
  StorageIsMutable_t supportsMutation() const {
    return getImplInfo().supportsMutation();
  }

  /// isSettable - Determine whether references to this decl may appear
  /// on the left-hand side of an assignment or as the operand of a
  /// `&` or 'inout' operator.
  bool isSettable(const DeclContext *UseDC,
                  const DeclRefExpr *base = nullptr) const;

  /// Does this storage declaration have explicitly-defined accessors
  /// written in the source?
  bool hasParsedAccessors() const;

  /// Return the ownership of values opaquely read from this storage.
  OpaqueReadOwnership getOpaqueReadOwnership() const;
  void setOpaqueReadOwnership(OpaqueReadOwnership ownership) {
    LazySemanticInfo.OpaqueReadOwnership = unsigned(ownership);
    LazySemanticInfo.OpaqueReadOwnershipComputed = true;
  }

  /// Return true if reading this storage requires the ability to
  /// modify the base value.
  bool isGetterMutating() const;
  void setIsGetterMutating(bool isMutating) {
    LazySemanticInfo.IsGetterMutating = isMutating;
    LazySemanticInfo.IsGetterMutatingComputed = true;
  }
  
  /// Return true if modifying this storage requires the ability to
  /// modify the base value.
  bool isSetterMutating() const;
  void setIsSetterMutating(bool isMutating) {
    LazySemanticInfo.IsSetterMutating = isMutating;
    LazySemanticInfo.IsSetterMutatingComputed = true;
  }

  AccessorDecl *getAccessor(AccessorKind kind) const {
    if (auto info = Accessors.getPointer())
      return info->getAccessor(kind);
    return nullptr;
  }

  ArrayRef<AccessorDecl*> getAllAccessors() const {
    if (const auto *info = Accessors.getPointer())
      return info->getAllAccessors();
    return {};
  }

  /// Return an accessor that this storage is expected to have, synthesizing
  /// one if necessary. Note that will always synthesize one, even if the
  /// accessor is not part of the expected opaque set for the storage, so use
  /// with caution.
  AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const;

  /// Return an accessor part of the set of opaque accessors dictated by the
  /// requirements of the ABI.
  ///
  /// This will synthesize the accessor if one is required but not specified
  /// in source; for example, most of the time a mutable property is required
  /// to have a 'modify' accessor, but if the property was only written with
  /// 'get' and 'set' accessors, 'modify' will be synthesized to call 'get'
  /// followed by 'set'.
  ///
  /// If the accessor is not needed for ABI reasons, this returns nullptr.
  /// To ensure an accessor is always returned, use getSynthesizedAccessor().
  AccessorDecl *getOpaqueAccessor(AccessorKind kind) const;

  /// Return an accessor that was written in source. Returns null if the
  /// accessor was not explicitly defined by the user.
  AccessorDecl *getParsedAccessor(AccessorKind kind) const;

  /// Visit all parsed accessors.
  void visitParsedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

  /// Visit all opaque accessor kinds.
  void visitExpectedOpaqueAccessors(
                            llvm::function_ref<void (AccessorKind)>) const;

  /// Visit all opaque accessors.
  void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

  /// Visit all eagerly emitted accessors.
  ///
  /// This is the union of the parsed and opaque sets.
  void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;

  void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
                    SourceLoc rbraceLoc);

  /// Add a setter to an existing Computed var.
  ///
  /// This should only be used by the ClangImporter.
  void setComputedSetter(AccessorDecl *Set);

  /// Does this storage require opaque accessors of any kind?
  bool requiresOpaqueAccessors() const;

  /// Does this storage require an opaque accessor of the given kind?
  bool requiresOpaqueAccessor(AccessorKind kind) const;

  /// Does this storage require a 'get' accessor in its opaque-accessors set?
  bool requiresOpaqueGetter() const {
    return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed;
  }

  /// Does this storage require a 'read' accessor in its opaque-accessors set?
  bool requiresOpaqueReadCoroutine() const {
    return getOpaqueReadOwnership() != OpaqueReadOwnership::Owned;
  }

  /// Does this storage require a 'set' accessor in its opaque-accessors set?
  bool requiresOpaqueSetter() const { return supportsMutation(); }

  /// Does this storage require a 'modify' accessor in its opaque-accessors set?
  bool requiresOpaqueModifyCoroutine() const;

  SourceRange getBracesRange() const {
    if (auto info = Accessors.getPointer())
      return info->getBracesRange();
    return SourceRange();
  }

  AccessLevel getSetterFormalAccess() const;

  AccessScope
  getSetterFormalAccessScope(const DeclContext *useDC = nullptr,
                             bool treatUsableFromInlineAsPublic = false) const;

  void setSetterAccess(AccessLevel accessLevel) {
    assert(!Accessors.getInt().hasValue());
    overwriteSetterAccess(accessLevel);
  }

  void overwriteSetterAccess(AccessLevel accessLevel);

  /// Given that this is an Objective-C property or subscript declaration,
  /// produce its getter selector.
  ObjCSelector
  getObjCGetterSelector(Identifier preferredName = Identifier()) const;

  /// Given that this is an Objective-C property or subscript declaration,
  /// produce its setter selector.
  ObjCSelector
  getObjCSetterSelector(Identifier preferredName = Identifier()) const;

  AbstractStorageDecl *getOverriddenDecl() const {
    return cast_or_null<AbstractStorageDecl>(ValueDecl::getOverriddenDecl());
  }

  /// Returns the location of 'override' keyword, if any.
  SourceLoc getOverrideLoc() const;

  /// Returns true if this declaration has a setter accessible from the given
  /// context.
  ///
  /// If \p DC is null, returns true only if the setter is public.
  ///
  /// See \c isAccessibleFrom for a discussion of the \p forConformance
  /// parameter.
  bool isSetterAccessibleFrom(const DeclContext *DC,
                              bool forConformance=false) const;

  /// Determine how this storage declaration should actually be accessed.
  AccessStrategy getAccessStrategy(AccessSemantics semantics,
                                   AccessKind accessKind,
                                   ModuleDecl *module,
                                   ResilienceExpansion expansion) const;

  /// Should this declaration behave as if it must be accessed
  /// resiliently, even when we're building a non-resilient module?
  ///
  /// This is used for diagnostics, because we do not want a behavior
  /// change between builds with resilience enabled and disabled.
  bool isFormallyResilient() const;

  /// Do we need to use resilient access patterns outside of this
  /// property's resilience domain?
  bool isResilient() const;

  /// Do we need to use resilient access patterns when accessing this
  /// property from the given module?
  bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;

  /// True if the storage can be referenced by a keypath directly.
  /// Otherwise, its override must be referenced.
  bool isValidKeyPathComponent() const;

  /// True if the storage exports a property descriptor for key paths in
  /// other modules.
  bool exportsPropertyDescriptor() const;

  /// True if any of the accessors to the storage is private or fileprivate.
  bool hasPrivateAccessor() const;

  bool hasDidSetOrWillSetDynamicReplacement() const;

  bool hasAnyNativeDynamicAccessors() const;

  bool hasAnyDynamicReplacementAccessors() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
           D->getKind() <= DeclKind::Last_AbstractStorageDecl;
  }
};

/// Describes which synthesized property for a property with an attached
/// wrapper is being referenced.
enum class PropertyWrapperSynthesizedPropertyKind {
  /// The backing storage property, which is a stored property of the
  /// wrapper type.
  Backing,
  /// A storage wrapper (e.g., `$foo`), which is a wrapper over the
  /// wrapper instance's `projectedValue` property.
  StorageWrapper,
};

/// VarDecl - 'var' and 'let' declarations.
class VarDecl : public AbstractStorageDecl {
public:
  enum class Introducer : uint8_t {
    Let = 0,
    Var = 1
  };

protected:
  PointerUnion<PatternBindingDecl *, Stmt *, VarDecl *> Parent;

  VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
          bool issCaptureList, SourceLoc nameLoc, Identifier name,
          DeclContext *dc, StorageIsMutable_t supportsMutation);

  TypeRepr *ParentRepr = nullptr;

  Type typeInContext;

public:
  VarDecl(bool isStatic, Introducer introducer, bool isCaptureList,
          SourceLoc nameLoc, Identifier name, DeclContext *dc)
    : VarDecl(DeclKind::Var, isStatic, introducer, isCaptureList, nameLoc,
              name, dc, StorageIsMutable_t(introducer == Introducer::Var)) {}

  SourceRange getSourceRange() const;

  Identifier getName() const { return getFullName().getBaseIdentifier(); }

  /// Returns the string for the base name, or "_" if this is unnamed.
  StringRef getNameStr() const {
    assert(!getFullName().isSpecial() && "Cannot get string for special names");
    return hasName() ? getBaseName().getIdentifier().str() : "_";
  }

  /// Retrieve the TypeRepr corresponding to the parsed type of the parent
  /// pattern, if it exists.
  TypeRepr *getTypeRepr() const { return ParentRepr; }
  void setTypeRepr(TypeRepr *repr) { ParentRepr = repr; }

  bool hasType() const {
    // We have a type if either the type has been computed already or if
    // this is a deserialized declaration with an interface type.
    return !typeInContext.isNull();
  }

  /// Get the type of the variable within its context. If the context is generic,
  /// this will use archetypes.
  Type getType() const;

  /// Set the type of the variable within its context.
  void setType(Type t);

  void markInvalid();

  /// Retrieve the source range of the variable type, or an invalid range if the
  /// variable's type is not explicitly written in the source.
  ///
  /// Only for use in diagnostics.  It is not always possible to always
  /// precisely point to the variable type because of type aliases.
  SourceRange getTypeSourceRangeForDiagnostics() const;

  /// Returns whether the var is settable in the specified context: this
  /// is either because it is a stored var, because it has a custom setter, or
  /// is a let member in an initializer.
  ///
  /// Pass a null context and null base to check if it's always settable.
  bool isSettable(const DeclContext *UseDC,
                  const DeclRefExpr *base = nullptr) const;

  /// Return the parent pattern binding that may provide an initializer for this
  /// VarDecl.  This returns null if there is none associated with the VarDecl.
  PatternBindingDecl *getParentPatternBinding() const {
    if (!Parent)
      return nullptr;
    return Parent.dyn_cast<PatternBindingDecl *>();
  }
  void setParentPatternBinding(PatternBindingDecl *PBD) {
    assert(PBD);
    Parent = PBD;
  }

  /// Return the Pattern involved in initializing this VarDecl.  However, recall
  /// that the Pattern may be involved in initializing more than just this one
  /// vardecl.  For example, if this is a VarDecl for "x", the pattern may be
  /// "(x, y)" and the initializer on the PatternBindingDecl may be "(1,2)" or
  /// "foo()".
  ///
  /// If this has no parent pattern binding decl or statement associated, it
  /// returns null.
  ///
  Pattern *getParentPattern() const;

  /// Return the statement that owns the pattern associated with this VarDecl,
  /// if one exists.
  ///
  /// NOTE: After parsing and before type checking, all VarDecls from
  /// CaseLabelItem's Patterns return their CaseStmt. After type checking, we
  /// will have constructed the CaseLabelItem VarDecl linked list implying this
  /// will return nullptr. After type checking, if one wishes to find a parent
  /// pattern of a VarDecl of a CaseStmt, \see getRecursiveParentPatternStmt
  /// instead.
  Stmt *getParentPatternStmt() const {
    if (!Parent)
      return nullptr;
    return Parent.dyn_cast<Stmt *>();
  }

  void setParentPatternStmt(Stmt *s) {
    assert(s);
    Parent = s;
  }

  /// Look for the parent pattern stmt of this var decl, recursively
  /// looking through var decl pointers and then through any
  /// fallthroughts.
  Stmt *getRecursiveParentPatternStmt() const;

  /// Returns the var decl that this var decl is an implicit reference to if
  /// such a var decl exists.
  VarDecl *getParentVarDecl() const {
    if (!Parent)
      return nullptr;
    return Parent.dyn_cast<VarDecl *>();
  }

  /// Set \p v to be the pattern produced VarDecl that is the parent of this
  /// var decl.
  void setParentVarDecl(VarDecl *v) {
    assert(v && v != this);
    Parent = v;
  }

  /// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
  /// return this. Otherwise, this VarDecl must belong to a CaseStmt's
  /// CaseLabelItem. In that case, return the first case label item of the first
  /// case stmt in a sequence of case stmts that fallthrough into each other.
  ///
  /// NOTE: During type checking, we emit an error if we have a single case
  /// label item with a pattern that has multiple var decls of the same
  /// name. This means that during type checking and before type checking, we
  /// may have a _malformed_ switch stmt var decl linked list since var decls in
  /// the same case label item that have the same name will point at the same
  /// canonical var decl, namely the first var decl with the name in the
  /// canonical case label item's var decl list. This is ok, since we are going
  /// to emit the error, but it requires us to be more careful/cautious before
  /// type checking has been complete when relying on canonical var decls
  /// matching up.
  VarDecl *getCanonicalVarDecl() const;

  /// If this is a case stmt var decl, return the var decl that corresponds to
  /// this var decl in the first case label item of the case stmt. Returns
  /// nullptr if this isn't a VarDecl that is part of a case stmt.
  NullablePtr<VarDecl> getCorrespondingFirstCaseLabelItemVarDecl() const;

  /// If this is a case stmt var decl, return the case body var decl that this
  /// var decl maps to.
  NullablePtr<VarDecl> getCorrespondingCaseBodyVariable() const;

  /// Return true if this var decl is an implicit var decl belonging to a case
  /// stmt's body.
  bool isCaseBodyVariable() const;

  /// True if the global stored property requires lazy initialization.
  bool isLazilyInitializedGlobal() const;

  /// Return the initializer involved in this VarDecl.  Recall that the
  /// initializer may be involved in initializing more than just this one
  /// vardecl though.  For example, if this is a VarDecl for "x", the pattern
  /// may be "(x, y)" and the initializer on the PatternBindingDecl may be
  /// "(1,2)" or "foo()".
  ///
  /// If this has no parent pattern binding decl associated, or if that pattern
  /// binding has no initial value, this returns null.
  ///
  Expr *getParentInitializer() const {
    if (auto *PBD = getParentPatternBinding())
      return PBD->getPatternEntryForVarDecl(this).getInit();
    return nullptr;
  }

  /// Whether there exists an initializer for this \c VarDecl.
  bool isParentInitialized() const {
    if (auto *PBD = getParentPatternBinding())
      return PBD->getPatternEntryForVarDecl(this).isInitialized();
    return false;
  }

  // Return whether this VarDecl has an initial value, either by checking
  // if it has an initializer in its parent pattern binding or if it has
  // the @_hasInitialValue attribute.
  bool hasInitialValue() const {
    return getAttrs().hasAttribute<HasInitialValueAttr>() ||
           isParentInitialized();
  }

  VarDecl *getOverriddenDecl() const {
    return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
  }
  
  /// Is this an immutable 'let' property?
  ///
  /// If this is a ParamDecl, isLet() is true iff
  /// getSpecifier() == Specifier::Default.
  bool isLet() const { return getIntroducer() == Introducer::Let; }

  Introducer getIntroducer() const {
    return Introducer(Bits.VarDecl.Introducer);
  }

  void setIntroducer(Introducer value) {
    Bits.VarDecl.Introducer = uint8_t(value);
  }

  /// Is this an element in a capture list?
  bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }

  /// Return true if this vardecl has an initial value bound to it in a way
  /// that isn't represented in the AST with an initializer in the pattern
  /// binding.  This happens in cases like "for i in ...", switch cases, etc.
  bool hasNonPatternBindingInit() const {
    return Bits.VarDecl.HasNonPatternBindingInit;
  }
  void setHasNonPatternBindingInit(bool V = true) {
    Bits.VarDecl.HasNonPatternBindingInit = V;
  }

  /// Determines if this var has an initializer expression that should be
  /// exposed to clients.
  /// There's a very narrow case when we would: if the decl is an instance
  /// member with an initializer expression and the parent type is
  /// @frozen and resides in a resilient module.
  bool isInitExposedToClients() const;
  
  /// Is this a special debugger variable?
  bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
  void setDebuggerVar(bool IsDebuggerVar) {
    Bits.VarDecl.IsDebuggerVar = IsDebuggerVar;
  }

  /// Is this the synthesized storage for a 'lazy' property?
  bool isLazyStorageProperty() const {
    return Bits.VarDecl.IsLazyStorageProperty;
  }
  void setLazyStorageProperty(bool IsLazyStorage) {
    Bits.VarDecl.IsLazyStorageProperty = IsLazyStorage;
  }

  /// Retrieve the custom attributes that attach property wrappers to this
  /// property. The returned list contains all of the attached property wrapper attributes in source order,
  /// which means the outermost wrapper attribute is provided first.
  llvm::TinyPtrVector<CustomAttr *> getAttachedPropertyWrappers() const;

  /// Whether this property has any attached property wrappers.
  bool hasAttachedPropertyWrapper() const;
  
  /// Whether all of the attached property wrappers have an init(initialValue:) initializer.
  bool allAttachedPropertyWrappersHaveInitialValueInit() const;
  
  /// Retrieve the type of the attached property wrapper as a contextual
  /// type.
  ///
  /// \param index Which property wrapper type is being computed, where 0
  /// indicates the first (outermost) attached property wrapper.
  ///
  /// \returns a NULL type for properties without attached wrappers,
  /// an error type when the property wrapper type itself is erroneous,
  /// or the wrapper type itself, which may involve unbound generic
  /// types.
  Type getAttachedPropertyWrapperType(unsigned index) const;

  /// Retrieve information about the attached property wrapper type.
  ///
  /// \param i Which attached property wrapper type is being queried, where 0 is the outermost (first)
  /// attached property wrapper type.
  PropertyWrapperTypeInfo getAttachedPropertyWrapperTypeInfo(unsigned i) const;

  /// Retrieve the fully resolved attached property wrapper type.
  ///
  /// This type will be the fully-resolved form of
  /// \c getAttachedPropertyWrapperType(0), which will not contain any
  /// unbound generic types. It will be the type of the backing property.
  Type getPropertyWrapperBackingPropertyType() const;

  /// Retrieve information about the backing properties of the attached
  /// property wrapper.
  PropertyWrapperBackingPropertyInfo
      getPropertyWrapperBackingPropertyInfo() const;

  /// Retrieve information about the mutability of the composed
  /// property wrappers.
  Optional<PropertyWrapperMutability>
      getPropertyWrapperMutability() const;

  /// Retrieve the backing storage property for a property that has an
  /// attached property wrapper.
  ///
  /// The backing storage property will be a stored property of the
  /// wrapper's type. This will be equivalent to
  /// \c getAttachedPropertyWrapperType(0) when it is fully-specified;
  /// if \c getAttachedPropertyWrapperType(0) involves an unbound
  /// generic type, the backing storage property will be the appropriate
  /// bound generic version.
  VarDecl *getPropertyWrapperBackingProperty() const;

  /// Retreive the storage wrapper for a property that has an attached
  /// property wrapper.
  VarDecl *getPropertyWrapperStorageWrapper() const;

  /// Retrieve the backing storage property for a lazy property.
  VarDecl *getLazyStorageProperty() const;

  /// Whether this is a property with a property wrapper that was initialized
  /// via a value of the original type, e.g.,
  ///
  /// \code
  /// @Lazy var i = 17
  /// \end
  bool isPropertyWrapperInitializedWithInitialValue() const;

  /// Whether the memberwise initializer parameter for a property with a property wrapper type
  /// uses the wrapped type.
  bool isPropertyMemberwiseInitializedWithWrappedType() const;

  /// If this property is the backing storage for a property with an attached
  /// property wrapper, return the original property.
  ///
  /// \param kind If not \c None, only returns the original property when
  /// \c this property is the specified synthesized property.
  VarDecl *getOriginalWrappedProperty(
      Optional<PropertyWrapperSynthesizedPropertyKind> kind = None) const;

  /// Set the property that wraps to this property as it's backing
  /// property.
  void setOriginalWrappedProperty(VarDecl *originalProperty);

  /// Return the Objective-C runtime name for this property.
  Identifier getObjCPropertyName() const;

  /// Retrieve the default Objective-C selector for the getter of a
  /// property of the given name.
  static ObjCSelector getDefaultObjCGetterSelector(ASTContext &ctx,
                                                   Identifier propertyName);

  /// Retrieve the default Objective-C selector for the setter of a
  /// property of the given name.
  static ObjCSelector getDefaultObjCSetterSelector(ASTContext &ctx,
                                                   Identifier propertyName);

  /// If this is a simple 'let' constant, emit a note with a fixit indicating
  /// that it can be rewritten to a 'var'.  This is used in situations where the
  /// compiler detects obvious attempts to mutate a constant.
  void emitLetToVarNoteIfSimple(DeclContext *UseDC) const;

  /// Returns true if the name is the self identifier and is implicit.
  bool isSelfParameter() const;

  /// Determine whether this property will be part of the implicit memberwise
  /// initializer.
  ///
  /// \param preferDeclaredProperties When encountering a `lazy` property
  /// or a property that has an attached property wrapper, prefer the
  /// actual declared property (which may or may not be considered "stored"
  /// as the moment) to the backing storage property. Otherwise, the stored
  /// backing property will be treated as the member-initialized property.
  bool isMemberwiseInitialized(bool preferDeclaredProperties) const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { 
    return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param; 
  }
};

enum class ParamSpecifier : uint8_t {
  Default = 0,
  InOut = 1,
  Shared = 2,
  Owned = 3,
};

/// A function parameter declaration.
class ParamDecl : public VarDecl {
  Identifier ArgumentName;
  SourceLoc ParameterNameLoc;
  SourceLoc ArgumentNameLoc;
  SourceLoc SpecifierLoc;

  struct StoredDefaultArgument {
    PointerUnion<Expr *, VarDecl *> DefaultArg;
    Initializer *InitContext = nullptr;
    StringRef StringRepresentation;
    CaptureInfo Captures;
  };

  enum class Flags : uint8_t {
    /// Whether or not this parameter is vargs.
    IsVariadic = 1 << 0,

    /// Whether or not this parameter is `@autoclosure`.
    IsAutoClosure = 1 << 1,
  };

  /// The default value, if any, along with flags.
  llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
      DefaultValueAndFlags;

  friend class ParamSpecifierRequest;

public:
  ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc,
            Identifier argumentName, SourceLoc parameterNameLoc,
            Identifier parameterName, DeclContext *dc);

  /// Create a new ParamDecl identical to the first except without the interface type.
  static ParamDecl *cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD);
  
  /// Retrieve the argument (API) name for this function parameter.
  Identifier getArgumentName() const { return ArgumentName; }

  /// Retrieve the parameter (local) name for this function parameter.
  Identifier getParameterName() const { return getName(); }

  /// Retrieve the source location of the argument (API) name.
  ///
  /// The resulting source location will be valid if the argument name
  /// was specified separately from the parameter name.
  SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; }

  SourceLoc getParameterNameLoc() const { return ParameterNameLoc; }

  SourceLoc getSpecifierLoc() const { return SpecifierLoc; }

  DefaultArgumentKind getDefaultArgumentKind() const {
    return static_cast<DefaultArgumentKind>(Bits.ParamDecl.defaultArgumentKind);
  }
  bool isDefaultArgument() const {
    return getDefaultArgumentKind() != DefaultArgumentKind::None;
  }
  void setDefaultArgumentKind(DefaultArgumentKind K) {
    Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
  }
  
  Expr *getDefaultValue() const {
    if (auto stored = DefaultValueAndFlags.getPointer())
      return stored->DefaultArg.dyn_cast<Expr *>();
    return nullptr;
  }

  VarDecl *getStoredProperty() const {
    if (auto stored = DefaultValueAndFlags.getPointer())
      return stored->DefaultArg.dyn_cast<VarDecl *>();
    return nullptr;
  }

  void setDefaultValue(Expr *E);

  void setStoredProperty(VarDecl *var);

  Initializer *getDefaultArgumentInitContext() const {
    if (auto stored = DefaultValueAndFlags.getPointer())
      return stored->InitContext;
    return nullptr;
  }

  void setDefaultArgumentInitContext(Initializer *initContext);

  const CaptureInfo &getDefaultArgumentCaptureInfo() const {
    assert(DefaultValueAndFlags.getPointer());
    return DefaultValueAndFlags.getPointer()->Captures;
  }

  void setDefaultArgumentCaptureInfo(const CaptureInfo &captures);

  /// Extracts the text of the default argument attached to the provided
  /// ParamDecl, removing all inactive #if clauses and providing only the
  /// text of active #if clauses.
  ///
  /// For example, the default argument:
  /// ```
  /// {
  ///   #if false
  ///   print("false")
  ///   #else
  ///   print("true")
  ///   #endif
  /// }
  /// ```
  /// will return
  /// ```
  /// {
  ///   print("true")
  /// }
  /// ```
  /// \sa getDefaultValue
  StringRef getDefaultValueStringRepresentation(
    SmallVectorImpl<char> &scratch) const;

  void setDefaultValueStringRepresentation(StringRef stringRepresentation);

  /// Whether or not this parameter is varargs.
  bool isVariadic() const {
    return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
  }
  void setVariadic(bool value = true) {
    auto flags = DefaultValueAndFlags.getInt();
    DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
                                      : flags - Flags::IsVariadic);
  }

  /// Whether or not this parameter is marked with `@autoclosure`.
  bool isAutoClosure() const {
    return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure);
  }
  void setAutoClosure(bool value = true) {
    auto flags = DefaultValueAndFlags.getInt();
    DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure
                                      : flags - Flags::IsAutoClosure);
  }

  /// Remove the type of this varargs element designator, without the array
  /// type wrapping it.  A parameter like "Int..." will have formal parameter
  /// type of "[Int]" and this returns "Int".
  static Type getVarargBaseTy(Type VarArgT);
  
  /// Remove the type of this varargs element designator, without the array
  /// type wrapping it.
  Type getVarargBaseTy() const {
    assert(isVariadic());
    return getVarargBaseTy(getInterfaceType());
  }

  /// Determine whether this declaration is an anonymous closure parameter.
  bool isAnonClosureParam() const;

  using Specifier = ParamSpecifier;

  Optional<Specifier> getCachedSpecifier() const {
    if (Bits.ParamDecl.SpecifierComputed)
      return Specifier(Bits.ParamDecl.Specifier);

    return None;
  }

  /// Return the raw specifier value for this parameter.
  Specifier getSpecifier() const;
  void setSpecifier(Specifier Spec);

  /// Is the type of this parameter 'inout'?
  bool isInOut() const { return getSpecifier() == Specifier::InOut; }
  /// Is this an immutable 'shared' property?
  bool isShared() const { return getSpecifier() == Specifier::Shared; }
  /// Is this an immutable 'owned' property?
  bool isOwned() const { return getSpecifier() == Specifier::Owned; }

  bool isImmutable() const {
    return isImmutableSpecifier(getSpecifier());
  }
  static bool isImmutableSpecifier(Specifier sp) {
    switch (sp) {
    case Specifier::Default:
    case Specifier::Shared:
    case Specifier::Owned:
      return true;
    case Specifier::InOut:
      return false;
    }
    llvm_unreachable("unhandled specifier");
  }

  ValueOwnership getValueOwnership() const {
    return getValueOwnershipForSpecifier(getSpecifier());
  }

  static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
    switch (specifier) {
    case Specifier::Default:
      return ValueOwnership::Default;
    case Specifier::InOut:
      return ValueOwnership::InOut;
    case Specifier::Shared:
      return ValueOwnership::Shared;
    case Specifier::Owned:
      return ValueOwnership::Owned;
    }
    llvm_unreachable("unhandled specifier");
  }

  static Specifier
  getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
    switch (ownership) {
    case ValueOwnership::Default:
      return Specifier::Default;
    case ValueOwnership::Shared:
      return Specifier::Shared;
    case ValueOwnership::InOut:
      return Specifier::InOut;
    case ValueOwnership::Owned:
      return Specifier::Owned;
    }
    llvm_unreachable("unhandled ownership");
  }

  SourceRange getSourceRange() const;

  AnyFunctionType::Param toFunctionParam(Type type = Type()) const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { 
    return D->getKind() == DeclKind::Param;
  }
};
  
/// Describes the kind of subscripting used in Objective-C.
enum class ObjCSubscriptKind {
  /// Objective-C indexed subscripting, which is based on an integral
  /// index.
  Indexed,
  /// Objective-C keyed subscripting, which is based on an object
  /// argument or metatype thereof.
  Keyed
};

/// Declares a subscripting operator for a type.
///
/// A subscript declaration is defined as a get/set pair that produces a
/// specific type. For example:
///
/// \code
/// subscript (i : Int) -> String {
///   get { /* return ith String */ }
///   set { /* set ith string to value */ }
/// }
/// \endcode
///
/// A type with a subscript declaration can be used as the base of a subscript
/// expression a[i], where a is of the subscriptable type and i is the type
/// of the index. A subscript can have multiple indices:
///
/// \code
/// struct Matrix {
///   subscript (i : Int, j : Int) -> Double {
///     get { /* return element at position (i, j) */ }
///     set { /* set element at position (i, j) */ }
///   }
/// }
/// \endcode
///
/// A given type can have multiple subscript declarations, so long as the
/// signatures (indices and element type) are distinct.
///
class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
  SourceLoc StaticLoc;
  SourceLoc ArrowLoc;
  SourceLoc EndLoc;
  ParameterList *Indices;
  TypeLoc ElementTy;

public:
  SubscriptDecl(DeclName Name,
                SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                SourceLoc SubscriptLoc, ParameterList *Indices,
                SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                GenericParamList *GenericParams)
    : GenericContext(DeclContextKind::SubscriptDecl, Parent, GenericParams),
      AbstractStorageDecl(DeclKind::Subscript,
                          StaticSpelling != StaticSpellingKind::None,
                          Parent, Name, SubscriptLoc,
                          /*will be overwritten*/ StorageIsNotMutable),
      StaticLoc(StaticLoc), ArrowLoc(ArrowLoc),
      Indices(nullptr), ElementTy(ElementTy) {
    Bits.SubscriptDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);
    setIndices(Indices);
  }
  
  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(Bits.SubscriptDecl.StaticSpelling);
  }
  
  SourceLoc getStaticLoc() const { return StaticLoc; }
  SourceLoc getSubscriptLoc() const { return getNameLoc(); }
  
  SourceLoc getStartLoc() const {
    return getStaticLoc().isValid() ? getStaticLoc() : getSubscriptLoc();
  }
  SourceLoc getEndLoc() const { return EndLoc; }

  void setEndLoc(SourceLoc sl) { EndLoc = sl; }
  SourceRange getSourceRange() const;
  SourceRange getSignatureSourceRange() const;

  /// Retrieve the indices for this subscript operation.
  ParameterList *getIndices() { return Indices; }
  const ParameterList *getIndices() const { return Indices; }
  void setIndices(ParameterList *p);

  /// Retrieve the type of the element referenced by a subscript
  /// operation.
  Type getElementInterfaceType() const;
  TypeLoc &getElementTypeLoc() { return ElementTy; }
  const TypeLoc &getElementTypeLoc() const { return ElementTy; }

  /// Determine the kind of Objective-C subscripting this declaration
  /// implies.
  ObjCSubscriptKind getObjCSubscriptKind() const;

  SubscriptDecl *getOverriddenDecl() const {
    return cast_or_null<SubscriptDecl>(
                                  AbstractStorageDecl::getOverriddenDecl());
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Subscript;
  }
  
  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }

  using DeclContext::operator new;
  using Decl::getASTContext;
};

/// Encodes imported-as-member status for C functions that get imported
/// as methods.
class ImportAsMemberStatus {
  friend class AbstractFunctionDecl;

  // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
  // index of n
  uint8_t rawValue;

public:
  ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {}

  uint8_t getRawValue() const { return rawValue; }

  bool isImportAsMember() const { return rawValue != 0; }
  bool isInstance() const { return rawValue >= 2; }
  bool isStatic() const { return rawValue == 1; }
  uint8_t getSelfIndex() const {
    assert(isInstance() && "not set");
    return rawValue - 2;
  }
  void setStatic() {
    assert(!isStatic() && "already set");
    rawValue = 1;
  }
  void setSelfIndex(uint8_t idx) {
    assert(!isImportAsMember() && "already set");
    assert(idx <= UINT8_MAX-2 && "out of bounds");
    rawValue = idx + 2;
  }
};

/// Base class for function-like declarations.
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
  friend class NeedsNewVTableEntryRequest;

public:
  enum class BodyKind {
    /// The function did not have a body in the source code file.
    None,

    /// Function body is delayed, to be parsed later.
    Unparsed,

    /// Function body is parsed and available as an AST subtree.
    Parsed,

    /// Function body is not available, although it was written in the source.
    Skipped,

    /// Function body will be synthesized on demand.
    Synthesize,

    /// Function body is present and type-checked.
    TypeChecked,

    /// This is a memberwise initializer that will be synthesized by SILGen.
    MemberwiseInitializer,

    /// Function body text was deserialized from a .swiftmodule.
    Deserialized

    // This enum currently needs to fit in a 3-bit bitfield.
  };

  BodyKind getBodyKind() const {
    return BodyKind(Bits.AbstractFunctionDecl.BodyKind);
  }

  struct BodySynthesizer {
    std::pair<BraceStmt *, bool> (* Fn)(AbstractFunctionDecl *, void *);
    void *Context;
  };

private:
  ParameterList *Params;

protected:
  // If a function has a body at all, we have either a parsed body AST node or
  // we have saved the end location of the unparsed body.
  union {
    /// This enum member is active if getBodyKind() is BodyKind::Parsed or
    /// BodyKind::TypeChecked.
    BraceStmt *Body;

    /// This enum member is active if getBodyKind() is BodyKind::Deserialized.
    StringRef BodyStringRepresentation;

    /// This enum member is active if getBodyKind() == BodyKind::Synthesize.
    BodySynthesizer Synthesizer;

    /// The location of the function body when the body is delayed or skipped.
    ///
    /// This enum member is active if getBodyKind() is BodyKind::Unparsed or
    /// BodyKind::Skipped.
    SourceRange BodyRange;
  };

  friend class ParseAbstractFunctionBodyRequest;

  CaptureInfo Captures;

  /// Location of the 'throws' token.
  SourceLoc ThrowsLoc;

  struct {
    unsigned NeedsNewVTableEntryComputed : 1;
    unsigned NeedsNewVTableEntry : 1;
  } LazySemanticInfo = { };

  AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                       SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                       bool HasImplicitSelfDecl,
                       GenericParamList *GenericParams)
      : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent, GenericParams),
        ValueDecl(Kind, Parent, Name, NameLoc),
        Body(nullptr), ThrowsLoc(ThrowsLoc) {
    setBodyKind(BodyKind::None);
    Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
    Bits.AbstractFunctionDecl.Overridden = false;
    Bits.AbstractFunctionDecl.Throws = Throws;
    Bits.AbstractFunctionDecl.Synthesized = false;
    Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
  }

  void setBodyKind(BodyKind K) {
    Bits.AbstractFunctionDecl.BodyKind = unsigned(K);
  }

public:
  void setHasSingleExpressionBody(bool Has = true) { 
    Bits.AbstractFunctionDecl.HasSingleExpressionBody = Has;
  }

  bool hasSingleExpressionBody() const {
    return Bits.AbstractFunctionDecl.HasSingleExpressionBody;
  }

  Expr *getSingleExpressionBody() const;
  void setSingleExpressionBody(Expr *NewBody);

  /// Returns the string for the base name, or "_" if this is unnamed.
  StringRef getNameStr() const {
    assert(!getFullName().isSpecial() && "Cannot get string for special names");
    return hasName() ? getBaseName().getIdentifier().str() : "_";
  }

  /// Should this declaration be treated as if annotated with transparent
  /// attribute.
  bool isTransparent() const;

  // Expose our import as member status
  ImportAsMemberStatus getImportAsMemberStatus() const {
    return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus);
  }
  bool isImportAsMember() const {
    return getImportAsMemberStatus().isImportAsMember();
  }
  bool isImportAsInstanceMember() const {
    return getImportAsMemberStatus().isInstance();
  }
  bool isImportAsStaticMember() const {
    return getImportAsMemberStatus().isStatic();
  }
  uint8_t getSelfIndex() const {
    return getImportAsMemberStatus().getSelfIndex();
  }

  void setImportAsStaticMember() {
    auto newValue = getImportAsMemberStatus();
    newValue.setStatic();
    Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
  }
  void setSelfIndex(uint8_t idx) {
    auto newValue = getImportAsMemberStatus();
    newValue.setSelfIndex(idx);
    Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
  }

  /// Retrieve the location of the 'throws' keyword, if present.
  SourceLoc getThrowsLoc() const { return ThrowsLoc; }

  /// Returns true if the function body throws.
  bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }

  // FIXME: Hack that provides names with keyword arguments for accessors.
  DeclName getEffectiveFullName() const;

  /// Returns true if the function has a body written in the source file.
  ///
  /// Note that a true return value does not imply that the body was actually
  /// parsed.
  bool hasBody() const {
    return getBodyKind() != BodyKind::None &&
           getBodyKind() != BodyKind::Skipped;
  }

  /// Returns true if the text of this function's body can be retrieved either
  /// by extracting the text from the source buffer or reading the inlinable
  /// body from a deserialized swiftmodule.
  bool hasInlinableBodyText() const;

  /// Returns the function body, if it was parsed, or nullptr otherwise.
  ///
  /// Note that a null return value does not imply that the source code did not
  /// have a body for this function.
  ///
  /// \sa hasBody()
  BraceStmt *getBody(bool canSynthesize = true) const;

  void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
    assert(getBodyKind() != BodyKind::Skipped &&
           "cannot set a body if it was skipped");

    Body = S;
    setBodyKind(NewBodyKind);
  }

  /// Note that the body was skipped for this function.  Function body
  /// cannot be attached after this call.
  void setBodySkipped(SourceRange bodyRange) {
    // FIXME: Remove 'Parsed' from this once we can delay parsing function
    //        bodies. Right now -experimental-skip-non-inlinable-function-bodies
    //        requires being able to change the state from Parsed to Skipped,
    //        because we're still eagerly parsing function bodies.
    assert(getBodyKind() == BodyKind::None ||
           getBodyKind() == BodyKind::Unparsed ||
           getBodyKind() == BodyKind::Parsed);
    assert(bodyRange.isValid());
    BodyRange = bodyRange;
    setBodyKind(BodyKind::Skipped);
  }

  /// Note that parsing for the body was delayed.
  void setBodyDelayed(SourceRange bodyRange) {
    assert(getBodyKind() == BodyKind::None);
    assert(bodyRange.isValid());
    BodyRange = bodyRange;
    setBodyKind(BodyKind::Unparsed);
  }

  /// Provide the parsed body for the function.
  void setBodyParsed(BraceStmt *S) {
    setBody(S, BodyKind::Parsed);
  }

  /// Note that parsing for the body was delayed.
  ///
  /// The function should return the body statement and a flag indicating
  /// whether that body is already type-checked.
  void setBodySynthesizer(
      std::pair<BraceStmt *, bool> (* fn)(AbstractFunctionDecl *, void *),
      void *context = nullptr) {
    assert(getBodyKind() == BodyKind::None);
    Synthesizer = {fn, context};
    setBodyKind(BodyKind::Synthesize);
  }

  /// Note that this is a memberwise initializer and thus the body will be
  /// generated by SILGen.
  void setIsMemberwiseInitializer() {
    assert(getBodyKind() == BodyKind::None);
    assert(isa<ConstructorDecl>(this));
    setBodyKind(BodyKind::MemberwiseInitializer);
  }

  /// Gets the body of this function, stripping the unused portions of #if
  /// configs inside the body. If this function was not deserialized from a
  /// .swiftmodule, this body is reconstructed from the original
  /// source buffer.
  StringRef getInlinableBodyText(SmallVectorImpl<char> &scratch) const;

  void setBodyStringRepresentation(StringRef body) {
    assert(getBodyKind() == BodyKind::None);
    setBodyKind(BodyKind::Deserialized);
    BodyStringRepresentation = body;
  }

  bool isBodyTypeChecked() const {
    return getBodyKind() == BodyKind::TypeChecked;
  }

  bool isBodySkipped() const {
    return getBodyKind() == BodyKind::Skipped;
  }

  bool isMemberwiseInitializer() const {
    return getBodyKind() == BodyKind::MemberwiseInitializer;
  }

  /// For a method of a class, checks whether it will require a new entry in the
  /// vtable.
  bool needsNewVTableEntry() const;

  bool isEffectiveLinkageMoreVisibleThan(ValueDecl *other) const {
    return (std::min(getEffectiveAccess(), AccessLevel::Public) >
            std::min(other->getEffectiveAccess(), AccessLevel::Public));
  }

  bool isSynthesized() const {
    return Bits.AbstractFunctionDecl.Synthesized;
  }

  void setSynthesized(bool value = true) {
    Bits.AbstractFunctionDecl.Synthesized = value;
  }

public:
  /// Compute the interface type of this function declaration from the
  /// parameter types.
  void computeType(AnyFunctionType::ExtInfo Info = FunctionType::ExtInfo());

  /// Retrieve the source range of the function body.
  SourceRange getBodySourceRange() const;

  /// Retrieve the source range of the function declaration name + patterns.
  SourceRange getSignatureSourceRange() const;

  const CaptureInfo &getCaptureInfo() const { return Captures; }
  void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }

  /// Retrieve the Objective-C selector that names this method.
  ObjCSelector getObjCSelector(DeclName preferredName = DeclName(),
                               bool skipIsObjCResolution = false) const;

  /// Determine whether the given method would produce an Objective-C
  /// instance method.
  bool isObjCInstanceMethod() const;

  /// Determine whether the name of an argument is an API name by default
  /// depending on the function context.
  bool argumentNameIsAPIByDefault() const;

  /// Retrieve the function's parameter list, not including 'self' if present.
  ParameterList *getParameters() {
    return Params;
  }
  const ParameterList *getParameters() const {
    return Params;
  }

  void setParameters(ParameterList *Params);

  bool hasImplicitSelfDecl() const {
    return Bits.AbstractFunctionDecl.HasImplicitSelfDecl;
  }

  ParamDecl **getImplicitSelfDeclStorage();

  /// Retrieve the implicit 'self' parameter for methods. Returns nullptr for
  /// free functions.
  const ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true) const {
    return const_cast<AbstractFunctionDecl*>(this)
        ->getImplicitSelfDecl(createIfNeeded);
  }
  ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true);

  /// Retrieve the declaration that this method overrides, if any.
  AbstractFunctionDecl *getOverriddenDecl() const {
    return cast_or_null<AbstractFunctionDecl>(ValueDecl::getOverriddenDecl());
  }

  /// Whether the declaration is later overridden in the module
  ///
  /// Overrides are resolved during type checking; only query this field after
  /// the whole module has been checked
  bool isOverridden() const { return Bits.AbstractFunctionDecl.Overridden; }

  /// The declaration has been overridden in the module
  ///
  /// Resolved during type checking
  void setIsOverridden() { Bits.AbstractFunctionDecl.Overridden = true; }

  /// Set information about the foreign error convention used by this
  /// declaration.
  void setForeignErrorConvention(const ForeignErrorConvention &convention);

  /// Get information about the foreign error convention used by this
  /// declaration, given that it is @objc and 'throws'.
  Optional<ForeignErrorConvention> getForeignErrorConvention() const;

  /// If this is a foreign C function imported as a method, get the index of
  /// the foreign parameter imported as `self`. If the function is imported
  /// as a static method, `-1` is returned to represent the `self` parameter
  /// being dropped altogether. `None` is returned for a normal function
  /// or method.
  Optional<int> getForeignFunctionAsMethodSelfParameterIndex() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_AbstractFunctionDecl &&
           D->getKind() <= DeclKind::Last_AbstractFunctionDecl;
  }

  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }
  
  /// True if the declaration is forced to be statically dispatched.
  bool hasForcedStaticDispatch() const;

  /// Get the type of this declaration without the Self clause.
  /// Asserts if not in type context.
  Type getMethodInterfaceType() const;

  /// Tests if this is a function returning a DynamicSelfType, or a
  /// constructor.
  bool hasDynamicSelfResult() const;

  using DeclContext::operator new;
  using Decl::getASTContext;
};

class OperatorDecl;

enum class SelfAccessKind : uint8_t {
  NonMutating,
  Mutating,
  Consuming,
};

/// Diagnostic printing of \c SelfAccessKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK);
  
/// FuncDecl - 'func' declaration.
class FuncDecl : public AbstractFunctionDecl {
  friend class AbstractFunctionDecl;
  friend class SelfAccessKindRequest;
  friend class IsStaticRequest;

  SourceLoc StaticLoc;  // Location of the 'static' token or invalid.
  SourceLoc FuncLoc;    // Location of the 'func' token.

  TypeLoc FnRetType;

protected:
  FuncDecl(DeclKind Kind,
           SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
           SourceLoc FuncLoc,
           DeclName Name, SourceLoc NameLoc,
           bool Throws, SourceLoc ThrowsLoc,
           bool HasImplicitSelfDecl,
           GenericParamList *GenericParams, DeclContext *Parent)
    : AbstractFunctionDecl(Kind, Parent,
                           Name, NameLoc,
                           Throws, ThrowsLoc,
                           HasImplicitSelfDecl, GenericParams),
      StaticLoc(StaticLoc), FuncLoc(FuncLoc) {
    assert(!Name.getBaseName().isSpecial());

    Bits.FuncDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);

    Bits.FuncDecl.ForcedStaticDispatch = false;
    Bits.FuncDecl.SelfAccess =
      static_cast<unsigned>(SelfAccessKind::NonMutating);
    Bits.FuncDecl.SelfAccessComputed = false;
    Bits.FuncDecl.IsStaticComputed = false;
    Bits.FuncDecl.IsStatic = false;
  }

private:
  static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
                              StaticSpellingKind StaticSpelling,
                              SourceLoc FuncLoc,
                              DeclName Name, SourceLoc NameLoc,
                              bool Throws, SourceLoc ThrowsLoc,
                              GenericParamList *GenericParams,
                              DeclContext *Parent,
                              ClangNode ClangN);

  Optional<SelfAccessKind> getCachedSelfAccessKind() const {
    if (Bits.FuncDecl.SelfAccessComputed)
      return static_cast<SelfAccessKind>(Bits.FuncDecl.SelfAccess);

    return None;
  }

  Optional<bool> getCachedIsStatic() const {
    if (Bits.FuncDecl.IsStaticComputed)
      return Bits.FuncDecl.IsStatic;

    return None;
  }

public:
  /// Factory function only for use by deserialization.
  static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc,
                                      StaticSpellingKind StaticSpelling,
                                      SourceLoc FuncLoc,
                                      DeclName Name, SourceLoc NameLoc,
                                      bool Throws, SourceLoc ThrowsLoc,
                                      GenericParamList *GenericParams,
                                      DeclContext *Parent);

  static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
                          StaticSpellingKind StaticSpelling,
                          SourceLoc FuncLoc,
                          DeclName Name, SourceLoc NameLoc,
                          bool Throws, SourceLoc ThrowsLoc,
                          GenericParamList *GenericParams,
                          ParameterList *ParameterList,
                          TypeLoc FnRetType, DeclContext *Parent,
                          ClangNode ClangN = ClangNode());

  Identifier getName() const { return getFullName().getBaseIdentifier(); }

  bool isStatic() const;
  bool isCallable() const {
    return getName().str() == "callAsFunction" && isInstanceMember();
  }

  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(Bits.FuncDecl.StaticSpelling);
  }
  /// \returns the way 'static'/'class' should be spelled for this declaration.
  StaticSpellingKind getCorrectStaticSpelling() const;
  void setStatic(bool IsStatic = true) {
    Bits.FuncDecl.IsStaticComputed = true;
    Bits.FuncDecl.IsStatic = IsStatic;
  }

  bool isMutating() const {
    return getSelfAccessKind() == SelfAccessKind::Mutating;
  }
  bool isNonMutating() const {
    return getSelfAccessKind() == SelfAccessKind::NonMutating;
  }
  bool isConsuming() const {
    return getSelfAccessKind() == SelfAccessKind::Consuming;
  }
  bool isCallAsFunctionMethod() const;

  SelfAccessKind getSelfAccessKind() const;

  void setSelfAccessKind(SelfAccessKind mod) {
    Bits.FuncDecl.SelfAccess = static_cast<unsigned>(mod);
    Bits.FuncDecl.SelfAccessComputed = true;
  }

  SourceLoc getStaticLoc() const { return StaticLoc; }
  SourceLoc getFuncLoc() const { return FuncLoc; }

  SourceLoc getStartLoc() const {
    return StaticLoc.isValid() && !isa<AccessorDecl>(this)
              ? StaticLoc : FuncLoc;
  }
  SourceRange getSourceRange() const;

  TypeLoc &getBodyResultTypeLoc() { return FnRetType; }
  const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; }

  /// Retrieve the result interface type of this function.
  Type getResultInterfaceType() const;

  /// isUnaryOperator - Determine whether this is a unary operator
  /// implementation.  This check is a syntactic rather than type-based check,
  /// which looks at the number of parameters specified, in order to allow
  /// for the definition of unary operators on tuples, as in:
  ///
  ///   prefix func + (param : (a:Int, b:Int))
  ///
  /// This also allows the unary-operator-ness of a func decl to be determined
  /// prior to type checking.
  bool isUnaryOperator() const;
  
  /// isBinaryOperator - Determine whether this is a binary operator
  /// implementation.  This check is a syntactic rather than type-based check,
  /// which looks at the number of parameters specified, in order to allow
  /// distinguishing a binary operator from a unary operator on tuples, as in:
  ///
  ///   prefix func + (_:(a:Int, b:Int)) // unary operator +(1,2)
  ///   infix func  + (a:Int, b:Int)     // binary operator 1 + 2
  ///
  /// This also allows the binary-operator-ness of a func decl to be determined
  /// prior to type checking.
  bool isBinaryOperator() const;

  void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
    return getCaptureInfo().getLocalCaptures(Result);
  }

  ParamDecl **getImplicitSelfDeclStorage();

  /// Get the supertype method this method overrides, if any.
  FuncDecl *getOverriddenDecl() const {
    return cast_or_null<FuncDecl>(AbstractFunctionDecl::getOverriddenDecl());
  }

  OperatorDecl *getOperatorDecl() const;

  /// Returns true if the function is forced to be statically dispatched.
  bool hasForcedStaticDispatch() const {
    return Bits.FuncDecl.ForcedStaticDispatch;
  }
  void setForcedStaticDispatch(bool flag) {
    Bits.FuncDecl.ForcedStaticDispatch = flag;
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Func ||
           D->getKind() == DeclKind::Accessor;
  }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }

  /// True if the function is a defer body.
  bool isDeferBody() const;

  /// Perform basic checking to determine whether the @IBAction or
  /// @IBSegueAction attribute can be applied to this function.
  bool isPotentialIBActionTarget() const;
};

/// This represents an accessor function, such as a getter or setter.
class AccessorDecl final : public FuncDecl {
  /// Location of the accessor keyword, e.g. 'set'.
  SourceLoc AccessorKeywordLoc;

  AbstractStorageDecl *Storage;

  AccessorDecl(SourceLoc declLoc, SourceLoc accessorKeywordLoc,
               AccessorKind accessorKind, AbstractStorageDecl *storage,
               SourceLoc staticLoc, StaticSpellingKind staticSpelling,
               bool throws, SourceLoc throwsLoc,
               bool hasImplicitSelfDecl, GenericParamList *genericParams,
               DeclContext *parent)
    : FuncDecl(DeclKind::Accessor,
               staticLoc, staticSpelling, /*func loc*/ declLoc,
               /*name*/ Identifier(), /*name loc*/ declLoc,
               throws, throwsLoc, hasImplicitSelfDecl, genericParams, parent),
      AccessorKeywordLoc(accessorKeywordLoc),
      Storage(storage) {
    Bits.AccessorDecl.AccessorKind = unsigned(accessorKind);
  }

  static AccessorDecl *createImpl(ASTContext &ctx,
                                  SourceLoc declLoc,
                                  SourceLoc accessorKeywordLoc,
                                  AccessorKind accessorKind,
                                  AbstractStorageDecl *storage,
                                  SourceLoc staticLoc,
                                  StaticSpellingKind staticSpelling,
                                  bool throws, SourceLoc throwsLoc,
                                  GenericParamList *genericParams,
                                  DeclContext *parent,
                                  ClangNode clangNode);

  Optional<bool> getCachedIsTransparent() const {
    if (Bits.AccessorDecl.IsTransparentComputed)
      return Bits.AccessorDecl.IsTransparent;
    return None;
  }

  friend class IsAccessorTransparentRequest;

public:
  static AccessorDecl *createDeserialized(ASTContext &ctx,
                              SourceLoc declLoc,
                              SourceLoc accessorKeywordLoc,
                              AccessorKind accessorKind,
                              AbstractStorageDecl *storage,
                              SourceLoc staticLoc,
                              StaticSpellingKind staticSpelling,
                              bool throws, SourceLoc throwsLoc,
                              GenericParamList *genericParams,
                              DeclContext *parent);

  static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc,
                              SourceLoc accessorKeywordLoc,
                              AccessorKind accessorKind,
                              AbstractStorageDecl *storage,
                              SourceLoc staticLoc,
                              StaticSpellingKind staticSpelling,
                              bool throws, SourceLoc throwsLoc,
                              GenericParamList *genericParams,
                              ParameterList *parameterList,
                              TypeLoc fnRetType, DeclContext *parent,
                              ClangNode clangNode = ClangNode());

  SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }

  AbstractStorageDecl *getStorage() const {
    return Storage;
  }

  AccessorKind getAccessorKind() const {
    return AccessorKind(Bits.AccessorDecl.AccessorKind);
  }

  bool isGetter() const { return getAccessorKind() == AccessorKind::Get; }
  bool isSetter() const { return getAccessorKind() == AccessorKind::Set; }
  bool isAnyAddressor() const {
    auto kind = getAccessorKind();
    return kind == AccessorKind::Address
        || kind == AccessorKind::MutableAddress;
  }

  /// isGetterOrSetter - Determine whether this is specifically a getter or
  /// a setter, as opposed to some other kind of accessor.
  ///
  /// For example, only getters and setters can be exposed to Objective-C.
  bool isGetterOrSetter() const { return isGetter() || isSetter(); }

  bool isObservingAccessor() const {
    switch (getAccessorKind()) {
#define OBSERVING_ACCESSOR(ID, KEYWORD) \
    case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
    case AccessorKind::ID: return false;
#include "swift/AST/AccessorKinds.def"
    }
    llvm_unreachable("bad accessor kind");
  }

  /// \returns true if this is non-mutating due to applying a 'mutating'
  /// attribute. For example a "mutating set" accessor.
  bool isExplicitNonMutating() const;

  /// Is the accesor one of the kinds that's assumed nonmutating by default?
  bool isAssumedNonMutating() const;

  /// Is this accessor one of the kinds that's implicitly a coroutine?
  bool isCoroutine() const {
    switch (getAccessorKind()) {
#define COROUTINE_ACCESSOR(ID, KEYWORD) \
    case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
    case AccessorKind::ID: return false;
#include "swift/AST/AccessorKinds.def"
    }
    llvm_unreachable("bad accessor kind");
  }

  void setIsTransparent(bool transparent) {
    Bits.AccessorDecl.IsTransparent = transparent;
    Bits.AccessorDecl.IsTransparentComputed = 1;
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Accessor;
  }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }
};

inline AccessorDecl *
AbstractStorageDecl::AccessorRecord::getAccessor(AccessorKind kind) const {
  if (auto optIndex = AccessorIndices[unsigned(kind)]) {
    auto accessor = getAllAccessors()[optIndex - 1];
    assert(accessor && accessor->getAccessorKind() == kind);
    return accessor;
  }
  return nullptr;
}
  
/// This represents a 'case' declaration in an 'enum', which may declare
/// one or more individual comma-separated EnumElementDecls.
class EnumCaseDecl final
    : public Decl,
      private llvm::TrailingObjects<EnumCaseDecl, EnumElementDecl *> {
  friend TrailingObjects;
  friend class Decl;
  SourceLoc CaseLoc;
  
  EnumCaseDecl(SourceLoc CaseLoc,
               ArrayRef<EnumElementDecl *> Elements,
               DeclContext *DC)
    : Decl(DeclKind::EnumCase, DC),
      CaseLoc(CaseLoc)
  {
    Bits.EnumCaseDecl.NumElements = Elements.size();
    std::uninitialized_copy(Elements.begin(), Elements.end(),
                            getTrailingObjects<EnumElementDecl *>());
  }
  SourceLoc getLocFromSource() const { return CaseLoc; }

public:
  static EnumCaseDecl *create(SourceLoc CaseLoc,
                              ArrayRef<EnumElementDecl*> Elements,
                              DeclContext *DC);
  
  /// Get the list of elements declared in this case.
  ArrayRef<EnumElementDecl *> getElements() const {
    return {getTrailingObjects<EnumElementDecl *>(),
            Bits.EnumCaseDecl.NumElements};
  }
  SourceRange getSourceRange() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::EnumCase;
  }
};

/// This represents a single case of an 'enum' declaration.
///
/// For example, the X, Y, and Z in this enum:
///
/// \code
///   enum V {
///     case X(Int), Y(Int)
///     case Z
///   }
/// \endcode
///
/// The type of an EnumElementDecl is always the EnumType for the containing
/// enum. EnumElementDecls are represented in the AST as members of their
/// parent EnumDecl, although syntactically they are subordinate to the
/// EnumCaseDecl.
class EnumElementDecl : public DeclContext, public ValueDecl {
  friend class EnumRawValuesRequest;
  
  /// This is the type specified with the enum element, for
  /// example 'Int' in 'case Y(Int)'.  This is null if there is no type
  /// associated with this element, as in 'case Z' or in all elements of enum
  /// definitions.
  ParameterList *Params;
  
  SourceLoc EqualsLoc;
  
  /// The raw value literal for the enum element, or null.
  LiteralExpr *RawValueExpr;

public:
  EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name,
                  ParameterList *Params,
                  SourceLoc EqualsLoc,
                  LiteralExpr *RawValueExpr,
                  DeclContext *DC);

  Identifier getName() const { return getFullName().getBaseIdentifier(); }

  /// Returns the string for the base name, or "_" if this is unnamed.
  StringRef getNameStr() const {
    assert(!getFullName().isSpecial() && "Cannot get string for special names");
    return hasName() ? getBaseName().getIdentifier().str() : "_";
  }

  Type getArgumentInterfaceType() const;

  void setParameterList(ParameterList *params);
  ParameterList *getParameterList() const { return Params; }

  /// Retrieves a fully typechecked raw value expression associated
  /// with this enum element, if it exists.
  LiteralExpr *getRawValueExpr() const;
  
  /// Retrieves a "structurally" checked raw value expression associated
  /// with this enum element, if it exists.
  ///
  /// The structural raw value may or may not have a type set, but it is
  /// guaranteed to be suitable for retrieving any non-semantic information
  /// like digit text for an integral raw value or user text for a string raw value.
  LiteralExpr *getStructuralRawValueExpr() const;
  
  /// Reset the raw value expression.
  void setRawValueExpr(LiteralExpr *e);

  /// Return the containing EnumDecl.
  EnumDecl *getParentEnum() const {
    return cast<EnumDecl>(getDeclContext());
  }
  
  /// Return the containing EnumCaseDecl.
  EnumCaseDecl *getParentCase() const;

  SourceLoc getStartLoc() const {
    return getNameLoc();
  }
  SourceRange getSourceRange() const;
  
  bool hasAssociatedValues() const {
    return getParameterList() != nullptr;
  }

  /// True if the case is marked 'indirect'.
  bool isIndirect() const {
    return getAttrs().hasAttribute<IndirectAttr>();
  }
  
  /// Do not call this!
  /// It exists to let the AST walkers get the raw value without forcing a request.
  LiteralExpr *getRawValueUnchecked() const { return RawValueExpr; }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::EnumElement;
  }

  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }

  using DeclContext::operator new;
  using Decl::getASTContext;
};
  
inline SourceRange EnumCaseDecl::getSourceRange() const {
  auto subRange = getElements().back()->getSourceRange();
  if (subRange.isValid())
    return {CaseLoc, subRange.End};
  return {};
}

/// Describes the kind of initializer.
enum class CtorInitializerKind {
  /// A designated initializer is an initializer responsible for initializing
  /// the stored properties of the current class and chaining to a superclass's
  /// designated initializer (for non-root classes).
  ///
  /// Designated initializers are never inherited.
  Designated,

  /// A convenience initializer is an initializer that initializes a complete
  /// object by delegating to another initializer (eventually reaching a
  /// designated initializer).
  ///
  /// Convenience initializers are inherited into subclasses that override
  /// all of their superclass's designated initializers.
  Convenience,

  /// A convenience factory initializer is a convenience initializer introduced
  /// by an imported Objective-C factory method.
  ///
  /// Convenience factory initializers cannot be expressed directly in
  /// Swift; rather, they are produced by the Clang importer when importing
  /// an instancetype factory method from Objective-C.
  ConvenienceFactory,

  /// A factory initializer is an initializer that is neither designated nor
  /// convenience: it can be used to create an object of the given type, but
  /// cannot be chained to via "super.init" nor is it inherited.
  ///
  /// A factory initializer is written with a return type of the class name
  /// itself. FIXME: However, this is only a presentation form, and at present
  /// the only factory initializers are produced by importing an Objective-C
  /// factory method that does not return instancetype.
  ///
  /// FIXME: Arguably, structs and enums only have factory initializers, and
  /// using designated initializers for them is a misnomer.
  Factory
};

/// ConstructorDecl - Declares a constructor for a type.  For example:
///
/// \code
/// struct X {
///   var x : Int
///   init(i : Int) {
///      x = i
///   }
/// }
/// \endcode
class ConstructorDecl : public AbstractFunctionDecl {
  /// The location of the '!' or '?' for a failable initializer.
  SourceLoc FailabilityLoc;

  ParamDecl *SelfDecl;

  /// The interface type of the initializing constructor.
  Type InitializerInterfaceType;

  /// The typechecked call to super.init expression, which needs to be
  /// inserted at the end of the initializer by SILGen.
  Expr *CallToSuperInit = nullptr;

public:
  ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc, 
                  bool Failable, SourceLoc FailabilityLoc,
                  bool Throws, SourceLoc ThrowsLoc,
                  ParameterList *BodyParams,
                  GenericParamList *GenericParams, 
                  DeclContext *Parent);

  SourceLoc getConstructorLoc() const { return getNameLoc(); }
  SourceLoc getStartLoc() const { return getConstructorLoc(); }
  SourceRange getSourceRange() const;

  /// Get the interface type of the constructed object.
  Type getResultInterfaceType() const;

  /// Get the interface type of the initializing constructor.
  Type getInitializerInterfaceType();

  /// Get the typechecked call to super.init expression, which needs to be
  /// inserted at the end of the initializer by SILGen.
  Expr *getSuperInitCall() { return CallToSuperInit; }
  void setSuperInitCall(Expr *CallExpr) { CallToSuperInit = CallExpr; }

  ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }

  /// Specifies the kind of initialization call performed within the body
  /// of the constructor, e.g., self.init or super.init.
  enum class BodyInitKind {
    /// There are no calls to self.init or super.init.
    None,
    /// There is a call to self.init, which delegates to another (peer)
    /// initializer.
    Delegating,
    /// There is a call to super.init, which chains to a superclass initializer.
    Chained,
    /// There are no calls to self.init or super.init explicitly in the body of
    /// the constructor, but a 'super.init' call will be implicitly added
    /// by semantic analysis.
    ImplicitChained
  };

  /// Determine whether the body of this constructor contains any delegating
  /// or superclass initializations (\c self.init or \c super.init,
  /// respectively) within its body.
  ///
  /// \param diags If non-null, this check will ensure that the constructor
  /// body is consistent in its use of delegation vs. chaining and emit any
  /// diagnostics through the given diagnostic engine.
  ///
  /// \param init If non-null and there is an explicit \c self.init or
  /// \c super.init within the body, will be set to point at that
  /// initializer.
  BodyInitKind getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
                                              ApplyExpr **init = nullptr) const;

  /// Whether this constructor is required.
  bool isRequired() const {
    return getAttrs().hasAttribute<RequiredAttr>();
  }

  /// Determine the kind of initializer this is.
  CtorInitializerKind getInitKind() const;

  /// Whether this is a designated initializer.
  bool isDesignatedInit() const {
    return getInitKind() == CtorInitializerKind::Designated;
  }

  /// Whether this is a convenience initializer.
  bool isConvenienceInit() const {
    return getInitKind() == CtorInitializerKind::Convenience ||
           getInitKind() == CtorInitializerKind::ConvenienceFactory;
  }

  /// Whether this is a factory initializer.
  bool isFactoryInit() const {
    switch (getInitKind()) {
    case CtorInitializerKind::Designated:
    case CtorInitializerKind::Convenience:
      return false;
        
    case CtorInitializerKind::Factory:
    case CtorInitializerKind::ConvenienceFactory:
      return true;
    }
    llvm_unreachable("bad CtorInitializerKind");
  }

  /// Determine whether this initializer is inheritable.
  bool isInheritable() const {
    switch (getInitKind()) {
    case CtorInitializerKind::Designated:
    case CtorInitializerKind::Factory:
      return false;

    case CtorInitializerKind::Convenience:
    case CtorInitializerKind::ConvenienceFactory:
      return true;
    }
    llvm_unreachable("bad CtorInitializerKind");
  }

  /// Determine if this is a failable initializer.
  bool isFailable() const {
    return Bits.ConstructorDecl.Failable;
  }

  /// Retrieve the location of the '!' or '?' in a failable initializer.
  SourceLoc getFailabilityLoc() const { return FailabilityLoc; }

  /// Whether the implementation of this method is a stub that traps at runtime.
  bool hasStubImplementation() const {
    return Bits.ConstructorDecl.HasStubImplementation;
  }

  /// Set whether the implementation of this method is a stub that
  /// traps at runtime.
  void setStubImplementation(bool stub) {
    Bits.ConstructorDecl.HasStubImplementation = stub;
  }

  ConstructorDecl *getOverriddenDecl() const {
    return cast_or_null<ConstructorDecl>(
        AbstractFunctionDecl::getOverriddenDecl());
  }

  /// Determine whether this initializer falls into the special case for
  /// Objective-C initializers with selectors longer than "init", e.g.,
  /// \c initForMemory.
  ///
  /// In such cases, one can write the Swift initializer
  /// with a single parameter of type '()', e.g,
  ///
  /// \code
  /// @objc init(forMemory: ())
  /// \endcode
  bool isObjCZeroParameterWithLongSelector() const;

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Constructor;
  }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }
};

/// DestructorDecl - Declares a destructor for a type.  For example:
///
/// \code
/// struct X {
///   var fd : Int
///   deinit {
///      close(fd)
///   }
/// }
/// \endcode
class DestructorDecl : public AbstractFunctionDecl {
  ParamDecl *SelfDecl;

public:
  DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent);

  ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }

  SourceLoc getDestructorLoc() const { return getNameLoc(); }
  SourceLoc getStartLoc() const { return getDestructorLoc(); }
  SourceRange getSourceRange() const;

  /// Retrieve the Objective-C selector for destructors.
  ObjCSelector getObjCSelector() const;

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Destructor;
  }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto D = DC->getAsDecl())
      return classof(D);
    return false;
  }
};

/// Declares a precedence group.  For example:
///
/// \code
/// precedencegroup MultiplicativePrecedence {
///   associativity: right
///   higherThan: AdditivePrecedence
/// }
/// \endcode
class PrecedenceGroupDecl : public Decl {
public:
  struct Relation {
    SourceLoc NameLoc;
    Identifier Name;
    PrecedenceGroupDecl *Group;
  };

private:
  SourceLoc PrecedenceGroupLoc, NameLoc, LBraceLoc, RBraceLoc;
  SourceLoc AssociativityKeywordLoc, AssociativityValueLoc;
  SourceLoc AssignmentKeywordLoc, AssignmentValueLoc;
  SourceLoc HigherThanLoc, LowerThanLoc;
  Identifier Name;
  unsigned NumHigherThan, NumLowerThan;
  // Tail-allocated array of Relations

  Relation *getHigherThanBuffer() {
    return reinterpret_cast<Relation*>(this + 1);
  }
  const Relation *getHigherThanBuffer() const {
    return reinterpret_cast<const Relation*>(this + 1);
  }
  Relation *getLowerThanBuffer() {
    return getHigherThanBuffer() + NumHigherThan;
  }
  const Relation *getLowerThanBuffer() const {
    return getHigherThanBuffer() + NumHigherThan;
  }

  PrecedenceGroupDecl(DeclContext *DC,
                      SourceLoc precedenceGroupLoc,
                      SourceLoc nameLoc, Identifier name,
                      SourceLoc lbraceLoc,
                      SourceLoc associativityKeywordLoc,
                      SourceLoc associativityValueLoc,
                      Associativity associativity,
                      SourceLoc assignmentKeywordLoc,
                      SourceLoc assignmentValueLoc,
                      bool isAssignment,
                      SourceLoc higherThanLoc, ArrayRef<Relation> higherThan,
                      SourceLoc lowerThanLoc, ArrayRef<Relation> lowerThan,
                      SourceLoc rbraceLoc);
  friend class Decl;
  SourceLoc getLocFromSource() const { return NameLoc; }
public:
  static PrecedenceGroupDecl *create(DeclContext *dc,
                                     SourceLoc precedenceGroupLoc,
                                     SourceLoc nameLoc,
                                     Identifier name,
                                     SourceLoc lbraceLoc,
                                     SourceLoc associativityKeywordLoc,
                                     SourceLoc associativityValueLoc,
                                     Associativity associativity,
                                     SourceLoc assignmentKeywordLoc,
                                     SourceLoc assignmentValueLoc,
                                     bool isAssignment,
                                     SourceLoc higherThanLoc,
                                     ArrayRef<Relation> higherThan,
                                     SourceLoc lowerThanLoc,
                                     ArrayRef<Relation> lowerThan,
                                     SourceLoc rbraceLoc);


  SourceRange getSourceRange() const {
    return { PrecedenceGroupLoc, RBraceLoc };
  }

  /// Return the location of 'precedencegroup' in:
  ///   precedencegroup MultiplicativePrecedence { ... }
  SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; }

  /// Return the location of 'MultiplicativePrecedence' in:
  ///   precedencegroup MultiplicativePrecedence { ... }
  SourceLoc getNameLoc() const {
    return NameLoc;
  }

  Identifier getName() const {
    return Name;
  }

  SourceLoc getLBraceLoc() const { return LBraceLoc; }
  SourceLoc getRBraceLoc() const { return RBraceLoc; }

  bool isAssociativityImplicit() const {
    return AssociativityKeywordLoc.isInvalid();
  }

  /// Return the location of 'associativity' in:
  ///   associativity: left
  SourceLoc getAssociativityKeywordLoc() const {
    return AssociativityKeywordLoc;
  }

  /// Return the location of 'right' in:
  ///   associativity: right
  SourceLoc getAssociativityValueLoc() const {
    return AssociativityValueLoc;
  }

  Associativity getAssociativity() const {
    return Associativity(Bits.PrecedenceGroupDecl.Associativity);
  }
  bool isLeftAssociative() const {
    return getAssociativity() == Associativity::Left;
  }
  bool isRightAssociative() const {
    return getAssociativity() == Associativity::Right;
  }
  bool isNonAssociative() const {
    return getAssociativity() == Associativity::None;
  }

  bool isAssignmentImplicit() const {
    return AssignmentKeywordLoc.isInvalid();
  }

  /// Return the location of 'assignment' in:
  ///   assignment: true
  SourceLoc getAssignmentKeywordLoc() const {
    return AssignmentKeywordLoc;
  }

  /// Return the location of 'assignment' in:
  ///   assignment: true
  SourceLoc getAssignmentValueLoc() const {
    return AssignmentValueLoc;
  }

  bool isAssignment() const {
    return Bits.PrecedenceGroupDecl.IsAssignment;
  }

  bool isHigherThanImplicit() const {
    return HigherThanLoc.isInvalid();
  }

  /// Return the location of 'higherThan' in:
  ///   higherThan: AdditivePrecedence
  SourceLoc getHigherThanLoc() const {
    return HigherThanLoc;
  }

  ArrayRef<Relation> getHigherThan() const {
    return { getHigherThanBuffer(), NumHigherThan };
  }
  MutableArrayRef<Relation> getMutableHigherThan() {
    return { getHigherThanBuffer(), NumHigherThan };
  }

  bool isLowerThanImplicit() const {
    return LowerThanLoc.isInvalid();
  }

  /// Return the location of 'lowerThan' in:
  ///   lowerThan: MultiplicativePrecedence
  SourceLoc getLowerThanLoc() const {
    return LowerThanLoc;
  }

  ArrayRef<Relation> getLowerThan() const {
    return { getLowerThanBuffer(), NumLowerThan };
  }
  MutableArrayRef<Relation> getMutableLowerThan() {
    return { getLowerThanBuffer(), NumLowerThan };
  }

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PrecedenceGroup;
  }
};

/// Abstract base class of operator declarations.
class OperatorDecl : public Decl {
  SourceLoc OperatorLoc, NameLoc;
  
  Identifier name;

  ArrayRef<Identifier> Identifiers;
  ArrayRef<SourceLoc> IdentifierLocs;
  ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
  SourceLoc getLocFromSource() const { return NameLoc; }
  friend class Decl;
public:
  OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
               Identifier Name, SourceLoc NameLoc,
               ArrayRef<Identifier> Identifiers,
               ArrayRef<SourceLoc> IdentifierLocs)
      : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
        Identifiers(Identifiers), IdentifierLocs(IdentifierLocs) {}

  OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
               Identifier Name, SourceLoc NameLoc,
               ArrayRef<NominalTypeDecl *> DesignatedNominalTypes)
      : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
        DesignatedNominalTypes(DesignatedNominalTypes) {}


  SourceLoc getOperatorLoc() const { return OperatorLoc; }
  SourceLoc getNameLoc() const { return NameLoc; }
  Identifier getName() const { return name; }

  ArrayRef<Identifier> getIdentifiers() const {
    return Identifiers;
  }

  ArrayRef<SourceLoc> getIdentifierLocs() const {
    return IdentifierLocs;
  }

  ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
    return DesignatedNominalTypes;
  }

  void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) {
    DesignatedNominalTypes = nominalTypes;
  }

  static bool classof(const Decl *D) {
    // Workaround: http://llvm.org/PR35906
    if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
      return D->getKind() >= DeclKind::First_OperatorDecl;
    return D->getKind() >= DeclKind::First_OperatorDecl
        && D->getKind() <= DeclKind::Last_OperatorDecl;
  }
};

/// Declares the behavior of an infix operator. For example:
///
/// \code
/// infix operator /+/ : AdditionPrecedence, Numeric
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
  SourceLoc ColonLoc;

public:
  InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
                    SourceLoc nameLoc, SourceLoc colonLoc,
                    ArrayRef<Identifier> identifiers,
                    ArrayRef<SourceLoc> identifierLocs)
      : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
                     identifiers, identifierLocs),
        ColonLoc(colonLoc) {}

  SourceLoc getEndLoc() const {
    auto identifierLocs = getIdentifierLocs();
    if (identifierLocs.empty())
      return getNameLoc();

    return identifierLocs.back();
  }

  SourceRange getSourceRange() const {
    return { getOperatorLoc(), getEndLoc() };
  }

  SourceLoc getColonLoc() const { return ColonLoc; }

  PrecedenceGroupDecl *getPrecedenceGroup() const;

  /// True if this decl's attributes conflict with those declared by another
  /// operator.
  bool conflictsWith(InfixOperatorDecl *other) {
    return getPrecedenceGroup() != other->getPrecedenceGroup();
  }
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::InfixOperator;
  }
};
  
/// Declares the behavior of a prefix operator. For example:
///
/// \code
/// prefix operator /+/ {}
/// \endcode
class PrefixOperatorDecl : public OperatorDecl {
public:
  PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                     SourceLoc NameLoc,
                     ArrayRef<Identifier> Identifiers,
                     ArrayRef<SourceLoc> IdentifierLocs)
      : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
                     Identifiers, IdentifierLocs) {}

  PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                     SourceLoc NameLoc,
                     ArrayRef<NominalTypeDecl *> designatedNominalTypes)
      : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
                     designatedNominalTypes) {}

  SourceRange getSourceRange() const {
    return { getOperatorLoc(), getNameLoc() };
  }

  /// True if this decl's attributes conflict with those declared by another
  /// PrefixOperatorDecl.
  bool conflictsWith(PrefixOperatorDecl *other) {
    return false;
  }
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PrefixOperator;
  }
};
  
/// Declares the behavior of a postfix operator. For example:
///
/// \code
/// postfix operator /+/ {}
/// \endcode
class PostfixOperatorDecl : public OperatorDecl {
public:
  PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                      SourceLoc NameLoc,
                      ArrayRef<Identifier> Identifiers,
                      ArrayRef<SourceLoc> IdentifierLocs)
      : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
                     Identifiers, IdentifierLocs) {}

  PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                      SourceLoc NameLoc,
                      ArrayRef<NominalTypeDecl *> designatedNominalTypes)
      : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
                     designatedNominalTypes) {}

  SourceRange getSourceRange() const {
    return { getOperatorLoc(), getNameLoc() };
  }

  /// True if this decl's attributes conflict with those declared by another
  /// PostfixOperatorDecl.
  bool conflictsWith(PostfixOperatorDecl *other) {
    return false;
  }
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PostfixOperator;
  }
};

/// Represents a hole where a declaration should have been.
///
/// Among other things, these are used to keep vtable layout consistent.
class MissingMemberDecl : public Decl {
  DeclName Name;

  MissingMemberDecl(DeclContext *DC, DeclName name,
                    unsigned vtableEntries,
                    unsigned fieldOffsetVectorEntries)
      : Decl(DeclKind::MissingMember, DC), Name(name) {
    Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries;
    assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
    Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries =
      fieldOffsetVectorEntries;
    assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries
           && "not enough bits");
    setImplicit();
  }
  friend class Decl;
  SourceLoc getLocFromSource() const {
    return SourceLoc();
  }
public:
  static MissingMemberDecl *
  create(ASTContext &ctx, DeclContext *DC, DeclName name,
         unsigned numVTableEntries, bool hasStorage) {
    assert(!numVTableEntries || isa<ProtocolDecl>(DC) || isa<ClassDecl>(DC) &&
           "Only classes and protocols have vtable/witness table entries");
    assert(!hasStorage || !isa<ProtocolDecl>(DC) &&
           "Protocols cannot have missing stored properties");

    return new (ctx) MissingMemberDecl(DC, name, numVTableEntries, hasStorage);
  }

  DeclName getFullName() const {
    return Name;
  }

  unsigned getNumberOfVTableEntries() const {
    return Bits.MissingMemberDecl.NumberOfVTableEntries;
  }

  unsigned getNumberOfFieldOffsetVectorEntries() const {
    return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries;
  }

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

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::MissingMember;
  }
};

inline bool AbstractStorageDecl::isSettable(const DeclContext *UseDC,
                                            const DeclRefExpr *base) const {
  if (auto vd = dyn_cast<VarDecl>(this))
    return vd->isSettable(UseDC, base);

  auto sd = cast<SubscriptDecl>(this);
  return sd->supportsMutation();
}

inline void
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
  Accessors.setInt(accessLevel);
  if (auto setter = getAccessor(AccessorKind::Set))
    setter->overwriteAccess(accessLevel);
  if (auto modify = getAccessor(AccessorKind::Modify))
    modify->overwriteAccess(accessLevel);
  if (auto mutableAddressor = getAccessor(AccessorKind::MutableAddress))
    mutableAddressor->overwriteAccess(accessLevel);
}

/// Constructors and destructors always have a 'self' parameter,
/// which is stored in an instance member. Functions only have a
/// 'self' if they are declared inside of a nominal type or extension,
/// in which case we tail-allocate storage for it.
inline ParamDecl **AbstractFunctionDecl::getImplicitSelfDeclStorage() {
  switch (getKind()) {
  default: llvm_unreachable("Unknown AbstractFunctionDecl!");
  case DeclKind::Constructor:
    return cast<ConstructorDecl>(this)->getImplicitSelfDeclStorage();
  case DeclKind::Destructor:
    return cast<DestructorDecl>(this)->getImplicitSelfDeclStorage();
  case DeclKind::Func:
  case DeclKind::Accessor:
    return cast<FuncDecl>(this)->getImplicitSelfDeclStorage();
  }
}

inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() {
  if (!hasImplicitSelfDecl())
    return nullptr;

  if (!isa<AccessorDecl>(this)) {
    assert(getKind() == DeclKind::Func && "no new kinds of functions");
    return reinterpret_cast<ParamDecl **>(this+1);
  }
  return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl*>(this)+1);
}

inline DeclIterator &DeclIterator::operator++() {
  Current = Current->NextDecl;
  return *this;
}

inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const {
  if (auto func = dyn_cast<FuncDecl>(this))
    return func->hasForcedStaticDispatch();
  return false;
}

inline bool ValueDecl::isStatic() const {
  // Currently, only storage and function decls can be static/class.
  if (auto storage = dyn_cast<AbstractStorageDecl>(this))
    return storage->isStatic();
  if (auto func = dyn_cast<FuncDecl>(this))
    return func->isStatic();
  return false;
}

inline bool ValueDecl::isImportAsMember() const {
  if (auto func = dyn_cast<AbstractFunctionDecl>(this))
    return func->isImportAsMember();
  return false;
}

inline bool ValueDecl::hasCurriedSelf() const {
  if (auto *afd = dyn_cast<AbstractFunctionDecl>(this))
    return afd->hasImplicitSelfDecl();
  if (isa<EnumElementDecl>(this))
    return true;
  return false;
}

inline bool ValueDecl::hasParameterList() const {
  if (auto *eed = dyn_cast<EnumElementDecl>(this))
    return eed->hasAssociatedValues();
  return isa<AbstractFunctionDecl>(this) || isa<SubscriptDecl>(this);
}

inline unsigned ValueDecl::getNumCurryLevels() const {
  unsigned curryLevels = 0;
  if (hasParameterList())
    curryLevels++;
  if (hasCurriedSelf())
    curryLevels++;
  return curryLevels;
}

inline bool Decl::isPotentiallyOverridable() const {
  if (isa<VarDecl>(this) ||
      isa<SubscriptDecl>(this) ||
      isa<FuncDecl>(this) ||
      isa<DestructorDecl>(this)) {
    return getDeclContext()->getSelfClassDecl();
  } else {
    return false;
  }
}

inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
  : Depth(d->getDepth()), Index(d->getIndex()) { }

inline const GenericContext *Decl::getAsGenericContext() const {
  switch (getKind()) {
  default: return nullptr;
#define DECL(Id, Parent) // See previous line
#define GENERIC_DECL(Id, Parent) \
  case DeclKind::Id: \
    return static_cast<const Id##Decl*>(this);
#include "swift/AST/DeclNodes.def"
  }
}

inline bool DeclContext::classof(const Decl *D) {
  switch (D->getKind()) { //
  default: return false;
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
  case DeclKind::ID: return true;
#include "swift/AST/DeclNodes.def"
  }
}

inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
  // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
  // preface decls in memory, any DeclContext type will due.
  const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
  switch (D->getKind()) {
  default: llvm_unreachable("Not a DeclContext");
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
  case DeclKind::ID:
#include "swift/AST/DeclNodes.def"
    return const_cast<DeclContext *>(DC);
  }
}

inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
  EnumElementDecl *result = nullptr;
  bool found = false;
  for (auto elt : getAllElements()) {
    if (elt->hasAssociatedValues() == hasValue) {
      if (found)
        return nullptr;
      found = true;
      result = elt;
    }
  }
  return result;
}

/// Retrieve parameter declaration from the given source at given index.
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);

/// Display Decl subclasses.
void simple_display(llvm::raw_ostream &out, const Decl *decl);

/// Display ValueDecl subclasses.
void simple_display(llvm::raw_ostream &out, const ValueDecl *decl);

/// Display ExtensionDecls.
inline void simple_display(llvm::raw_ostream &out, const ExtensionDecl *decl) {
  simple_display(out, static_cast<const Decl *>(decl));
}

/// Display NominalTypeDecls.
inline void simple_display(llvm::raw_ostream &out,
                           const NominalTypeDecl *decl) {
  simple_display(out, static_cast<const Decl *>(decl));
}

/// Display GenericContext.
///
/// The template keeps this sorted down in the overload set relative to the
/// more concrete overloads with Decl pointers thereby breaking a potential ambiguity.
template <typename T>
inline typename std::enable_if<std::is_same<T, GenericContext>::value>::type
simple_display(llvm::raw_ostream &out, const T *GC) {
  simple_display(out, GC->getAsDecl());
}

/// Display GenericParamList.
void simple_display(llvm::raw_ostream &out, const GenericParamList *GPL);

/// Extract the source location from the given declaration.
SourceLoc extractNearestSourceLoc(const Decl *decl);

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const ExtensionDecl *ext) {
  return extractNearestSourceLoc(static_cast<const Decl *>(ext));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) {
  return extractNearestSourceLoc(static_cast<const Decl *>(type));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) {
  return extractNearestSourceLoc(static_cast<const Decl *>(type));
}

/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) {
  return extractNearestSourceLoc(static_cast<const Decl *>(func));
}

} // end namespace swift

#endif
