//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://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/Attr.h"
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/DefaultArgumentKind.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/KnownProtocols.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Requirement.h"
#include "swift/AST/Substitution.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Basic/OptionalEnum.h"
#include "swift/Basic/Range.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Basic/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <cstddef>

namespace clang {
  class Decl;
  class MacroInfo;
  class Module;
  class SourceLocation;
  class SourceRange;
}

namespace swift {
  enum class AccessSemantics : unsigned char;
  class ApplyExpr;
  class ArchetypeBuilder;
  class ArchetypeType;
  class ASTContext;
  class ASTPrinter;
  class ASTWalker;
  class ConstructorDecl;
  class DestructorDecl;
  class DiagnosticEngine;
  class DynamicSelfType;
  class Type;
  class Expr;
  class DeclRefExpr;
  class ForeignErrorConvention;
  class LiteralExpr;
  class FuncDecl;
  class BraceStmt;
  class DeclAttributes;
  class GenericSignature;
  class GenericTypeParamDecl;
  class GenericTypeParamType;
  class ModuleDecl;
  class NameAliasType;
  class EnumCaseDecl;
  class EnumElementDecl;
  class Pattern;
  struct PrintOptions;
  class ProtocolDecl;
  class ProtocolType;
  struct RawComment;
  enum class Resilience : unsigned char;
  class TypeAliasDecl;
  class Stmt;
  class SubscriptDecl;
  class ValueDecl;
  class VarDecl;

/// Represents a clang declaration, macro, or module.
class ClangNode {
  llvm::PointerUnion3<const clang::Decl *, const clang::MacroInfo *,
                      const clang::Module *> Ptr;

public:
  ClangNode() = default;
  ClangNode(const clang::Decl *D) : Ptr(D) {}
  ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {}
  ClangNode(const clang::Module *Mod) : Ptr(Mod) {}

  bool isNull() const { return Ptr.isNull(); }
  explicit operator bool() const { return !isNull(); }

  const clang::Decl *getAsDecl() const {
    return Ptr.dyn_cast<const clang::Decl *>();
  }
  const clang::MacroInfo *getAsMacro() const {
    return Ptr.dyn_cast<const clang::MacroInfo *>();
  }
  const clang::Module *getAsModule() const {
    return Ptr.dyn_cast<const clang::Module *>();
  }

  const clang::Decl *castAsDecl() const {
    return Ptr.get<const clang::Decl *>();
  }
  const clang::MacroInfo *castAsMacro() const {
    return Ptr.get<const clang::MacroInfo *>();
  }
  const clang::Module *castAsModule() const {
    return Ptr.get<const clang::Module *>();
  }

  /// Returns the module either the one wrapped directly, the one from a
  /// clang::ImportDecl or null if it's neither.
  const clang::Module *getClangModule() const;

  clang::SourceLocation getLocation() const;
  clang::SourceRange getSourceRange() const;

  void *getOpaqueValue() const { return Ptr.getOpaqueValue(); }
  static inline ClangNode getFromOpaqueValue(void *VP) {
    ClangNode N;
    N.Ptr = decltype(Ptr)::getFromOpaqueValue(VP);
    return N;
  }
};
  
enum class DeclKind : uint8_t {
#define DECL(Id, Parent) Id,
#define DECL_RANGE(Id, FirstId, LastId) \
  First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "swift/AST/DeclNodes.def"
};

/// 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,
  PatternBinding,
  Var,
  Param,
  Let,
  StaticVar,
  StaticLet,
  ClassVar,
  ClassLet,
  InfixOperator,
  PrefixOperator,
  PostfixOperator,
  TypeAlias,
  GenericTypeParam,
  AssociatedType,  
  Enum,
  Struct,
  Class,
  Protocol,
  GenericEnum,
  GenericStruct,
  GenericClass,
  Subscript,
  Constructor,
  Destructor,
  LocalFunction,
  GlobalFunction,
  OperatorFunction,
  Method,
  StaticMethod,
  ClassMethod,
  Getter,
  Setter,
  MaterializeForSet,
  Addressor,
  MutableAddressor,
  WillSet,
  DidSet,
  EnumElement,
  Module,
};

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

/// Keeps track of whrther a given class inherits initializers from its
/// superclass.
enum class StoredInheritsSuperclassInits {
  /// We have not yet checked.
  Unchecked,
  /// Superclass initializers are not inherited.
  NotInherited,
  /// Convenience initializers in the superclass are inherited.
  Inherited
};

/// Describes which spelling was used in the source for the 'static' or 'class'
/// keyword.
enum class StaticSpellingKind : uint8_t {
  None,
  KeywordStatic,
  KeywordClass,
};
  
/// Describes if an enum element constructor directly or indirectly references
/// its enclosing type.
enum class ElementRecursiveness {
  /// The element does not reference its enclosing type.
  NotRecursive,
  /// The element is currently being validated, and may references its enclosing
  /// type.
  PotentiallyRecursive,
  /// The element does not reference its enclosing type.
  Recursive
};

/// 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 interface type of the declaration, when relevant to the
  /// overload signature.
  CanType InterfaceType;

  /// The kind of unary operator.
  UnaryOperatorKind UnaryOperator = UnaryOperatorKind::None;

  /// Whether this is an instance member.
  bool IsInstanceMember = false;

  /// Whether this is a property.
  bool IsProperty = false;

  /// Whether this signature is part of a protocol extension.
  bool InProtocolExtension = false;
};

/// Determine whether two overload signatures conflict.
bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2);

/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
  class DeclBitfields {
    friend class Decl;
    unsigned Kind : 8;

    /// \brief Whether this declaration is invalid.
    unsigned Invalid : 1;

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

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

    /// \brief Whether we've already performed early attribute validation.
    /// FIXME: This is ugly.
    unsigned EarlyAttrValidation : 1;
    
    /// \brief Whether or not this declaration is currently being type-checked.
    unsigned BeingTypeChecked : 1;
  };
  enum { NumDeclBits = 13 };
  static_assert(NumDeclBits <= 32, "fits in an unsigned");
  
  class PatternBindingDeclBitfields {
    friend class PatternBindingDecl;
    unsigned : NumDeclBits;
    
    /// \brief Whether this pattern binding declares static variables.
    unsigned IsStatic : 1;

    /// \brief Whether 'static' or 'class' was used.
    unsigned StaticSpelling : 2;
  };
  enum { NumPatternBindingDeclBits = NumDeclBits + 3 };
  static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned");
  
  class ValueDeclBitfields {
    friend class ValueDecl;
    friend class MemberLookupTable;
    unsigned : NumDeclBits;
    unsigned AlreadyInLookupTable : 1;

    /// Whether we have already checked whether this declaration is a 
    /// redeclaration.
    unsigned CheckedRedeclaration : 1;
  };
  enum { NumValueDeclBits = NumDeclBits + 2 };
  static_assert(NumValueDeclBits <= 32, "fits in an unsigned");

  class AbstractStorageDeclBitfields {
    friend class AbstractStorageDecl;
    unsigned : NumValueDeclBits;

    /// Whether we are overridden later
    unsigned Overridden : 1;

    /// The storage kind.
    unsigned StorageKind : 4;
  };
  enum { NumAbstractStorageDeclBits = NumValueDeclBits + 5 };
  static_assert(NumAbstractStorageDeclBits <= 32, "fits in an unsigned");

  class VarDeclBitfields {
    friend class VarDecl;
    unsigned : NumAbstractStorageDeclBits;
    
    /// \brief Whether this property is a type property (currently unfortunately
    /// called 'static').
    unsigned IsStatic : 1;

    /// \brief Whether this is a 'let' property, which can only be initialized
    /// once (either in its declaration, or once later), making it immutable.
    unsigned IsLet : 1;

    /// \brief 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.
    unsigned HasNonPatternBindingInit : 1;
    
    /// \brief 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.
    unsigned IsDebuggerVar : 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.
    unsigned IsUserAccessible : 1;
  };
  enum { NumVarDeclBits = NumAbstractStorageDeclBits + 5 };
  static_assert(NumVarDeclBits <= 32, "fits in an unsigned");
  
  class EnumElementDeclBitfields {
    friend class EnumElementDecl;
    unsigned : NumValueDeclBits;
    
    /// \brief Whether or not this element directly or indirectly references
    /// the enum type.
    unsigned Recursiveness : 2;
  };
  enum { NumEnumElementDeclBits = NumValueDeclBits + 2 };
  static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned");
  
  class AbstractFunctionDeclBitfields {
    friend class AbstractFunctionDecl;
    unsigned : NumValueDeclBits;

    /// \see AbstractFunctionDecl::BodyKind
    unsigned BodyKind : 3;

    /// Number of curried parameter patterns (tuples).
    unsigned NumParamPatterns : 6;

    /// Whether we are overridden later.
    unsigned Overridden : 1;
  };
  enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 10 };
  static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");

  class FuncDeclBitfields {
    friend class FuncDecl;
    unsigned : NumAbstractFunctionDeclBits;

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

    /// \brief Whether 'static' or 'class' was used.
    unsigned StaticSpelling : 2;

    /// Whether this function is a 'mutating' method.
    unsigned Mutating : 1;

    /// Whether this function has a dynamic Self return type.
    unsigned HasDynamicSelf : 1;
    
    /// Whether we are statically dispatched even if overridable
    unsigned ForcedStaticDispatch : 1;
  };
  enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 6 };
  static_assert(NumFuncDeclBits <= 32, "fits in an unsigned");

  class ConstructorDeclBitfields {
    friend class ConstructorDecl;
    unsigned : NumAbstractFunctionDeclBits;

    /// 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.
    unsigned ComputedBodyInitKind : 3;

    /// The kind of initializer we have.
    unsigned InitKind : 2;

    /// 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.
    unsigned HasStubImplementation : 1;
  };
  enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 6 };
  static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned");

  class TypeDeclBitfields {
    friend class TypeDecl;
    unsigned : NumValueDeclBits;

    /// Whether we have already checked the inheritance clause.
    ///
    /// FIXME: Is this too fine-grained?
    unsigned CheckedInheritanceClause : 1;
  };

  enum { NumTypeDeclBits = NumValueDeclBits + 1 };
  static_assert(NumTypeDeclBits <= 32, "fits in an unsigned");
  
  class NominalTypeDeclBitFields {
    friend class NominalTypeDecl;
    unsigned : NumTypeDeclBits;
    
    /// Whether or not the nominal type decl has delayed protocol or member
    /// declarations.
    unsigned HasDelayedMembers : 1;

    /// Whether we have already added implicitly-defined initializers
    /// to this declaration.
    unsigned AddedImplicitInitializers : 1;
  };
  enum { NumNominalTypeDeclBits = NumTypeDeclBits + 2 };
  static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");

  class ProtocolDeclBitfields {
    friend class ProtocolDecl;
    unsigned : NumNominalTypeDeclBits;

    /// Whether the \c RequiresClass bit is valid.
    unsigned RequiresClassValid : 1;

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

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

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

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

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

    /// If this is a compiler-known protocol, this will be a KnownProtocolKind
    /// value, plus one. Otherwise, it will be 0.
    unsigned KnownProtocol : 6;

    /// The stage of the circularity check for this protocol.
    unsigned Circularity : 2;
  };
  enum { NumProtocolDeclBits = NumNominalTypeDeclBits + 14 };
  static_assert(NumProtocolDeclBits <= 32, "fits in an unsigned");

  class ClassDeclBitfields {
    friend class ClassDecl;
    unsigned : NumNominalTypeDeclBits;

    /// The stage of the inheritance circularity check for this class.
    unsigned Circularity : 2;

    /// Whether this class requires all of its instance variables to
    /// have in-class initializers.
    unsigned RequiresStoredPropertyInits : 1;

    /// Whether this class inherits its superclass's convenience
    /// initializers.
    ///
    /// This is a value of \c StoredInheritsSuperclassInits.
    unsigned InheritsSuperclassInits : 2;

    /// Whether this class is "foreign".
    unsigned Foreign : 1;
    
    /// Whether this class contains a destructor decl.
    ///
    /// A fully type-checked class always contains a destructor member, even if
    /// it is implicit. This bit is used during parsing and type-checking to
    /// control inserting the implicit destructor.
    unsigned HasDestructorDecl : 1;
  };
  enum { NumClassDeclBits = NumNominalTypeDeclBits + 7 };
  static_assert(NumClassDeclBits <= 32, "fits in an unsigned");

  class StructDeclBitfields {
    friend class StructDecl;
    unsigned : NumNominalTypeDeclBits;
    
    /// True if this struct has storage for fields that aren't accessible in
    /// Swift.
    unsigned HasUnreferenceableStorage : 1;
  };
  enum { NumStructDeclBits = NumNominalTypeDeclBits + 1 };
  static_assert(NumStructDeclBits <= 32, "fits in an unsigned");
  
  class EnumDeclBitfields {
    friend class EnumDecl;
    unsigned : NumNominalTypeDeclBits;
    
    /// The stage of the raw type circularity check for this class.
    unsigned Circularity : 2;
  };
  enum { NumEnumDeclBits = NumNominalTypeDeclBits + 2 };
  static_assert(NumEnumDeclBits <= 32, "fits in an unsigned");
  
  class InfixOperatorDeclBitfields {
    friend class InfixOperatorDecl;
    unsigned : NumDeclBits;

    unsigned Associativity : 2;
    unsigned Precedence : 8;
    unsigned Assignment : 1;
    unsigned IsAssocImplicit : 1;
    unsigned IsPrecedenceImplicit : 1;
    unsigned IsAssignmentImplicit : 1;
  };
  enum { NumInfixOperatorDeclBits = NumDeclBits + 14 };
  static_assert(NumInfixOperatorDeclBits <= 32, "fits in an unsigned");

  class AssociatedTypeDeclBitfields {
    friend class AssociatedTypeDecl;
    unsigned : NumTypeDeclBits;

    unsigned Recursive : 1;
  };
  enum { NumAssociatedTypeDeclBits = NumTypeDeclBits + 1 };
  static_assert(NumAssociatedTypeDeclBits <= 32, "fits in an unsigned");

  class ImportDeclBitfields {
    friend class ImportDecl;
    unsigned : NumDeclBits;

    unsigned ImportKind : 3;
  };
  enum { NumImportDeclBits = NumDeclBits + 3 };
  static_assert(NumImportDeclBits <= 32, "fits in an unsigned");

  class ExtensionDeclBitfields {
    friend class ExtensionDecl;
    unsigned : NumDeclBits;

    /// Whether we have already checked the inheritance clause.
    ///
    /// FIXME: Is this too fine-grained?
    unsigned CheckedInheritanceClause : 1;

    /// Whether this extension has already been validated.
    unsigned Validated : 1;

    /// An encoding of the default and maximum access level for this extension.
    ///
    /// This is encoded as (1 << maxAccess) | (1 << defaultAccess), which
    /// works because the maximum is always greater than or equal to the
    /// default. 0 represents an uncomputed value.
    unsigned DefaultAndMaxAccessLevel : 3;

    /// Whether there is an active conformance loader for this
    /// extension.
    unsigned HaveConformanceLoader : 1;
  };
  enum { NumExtensionDeclBits = NumDeclBits + 5 };
  static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned");

protected:
  union {
    DeclBitfields DeclBits;
    PatternBindingDeclBitfields PatternBindingDeclBits;
    ValueDeclBitfields ValueDeclBits;
    AbstractStorageDeclBitfields AbstractStorageDeclBits;
    AbstractFunctionDeclBitfields AbstractFunctionDeclBits;
    VarDeclBitfields VarDeclBits;
    EnumElementDeclBitfields EnumElementDeclBits;
    FuncDeclBitfields FuncDeclBits;
    ConstructorDeclBitfields ConstructorDeclBits;
    TypeDeclBitfields TypeDeclBits;
    NominalTypeDeclBitFields NominalTypeDeclBits;
    ProtocolDeclBitfields ProtocolDeclBits;
    ClassDeclBitfields ClassDeclBits;
    StructDeclBitfields StructDeclBits;
    EnumDeclBitfields EnumDeclBits;
    AssociatedTypeDeclBitfields AssociatedTypeDeclBits;
    InfixOperatorDeclBitfields InfixOperatorDeclBits;
    ImportDeclBitfields ImportDeclBits;
    ExtensionDeclBitfields ExtensionDeclBits;
    uint32_t OpaqueBits;
  };

  // FIXME: Unused padding here.

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

protected:

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

  ClangNode getClangNodeImpl() const {
    assert(DeclBits.FromClang);
    return ClangNode::getFromOpaqueValue(
        *(reinterpret_cast<void * const*>(this) - 1));
  }

  /// \brief Set the Clang node associated with this declaration.
  void setClangNode(ClangNode Node) {
    DeclBits.FromClang = true;
    // Extra memory is allocated for this.
    *(reinterpret_cast<void **>(this) - 1) = Node.getOpaqueValue();
  }

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

  DeclContext *getDeclContextForModule() const;

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

  /// \brief 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;

  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();

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

  /// getASTContext - Return the ASTContext that this decl lives in.
  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;

  SourceLoc TrailingSemiLoc;

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

  /// \brief 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;

  /// \brief 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;

  /// \brief 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);

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

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

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

  /// \brief Mark this declaration as implicit.
  void setImplicit(bool implicit = true) { DeclBits.Implicit = implicit; }

  /// Whether we have already done early attribute validation.
  bool didEarlyAttrValidation() const { return DeclBits.EarlyAttrValidation; }

  /// Set whether we've performed early attribute validation.
  void setEarlyAttrValidation(bool validated = true) {
    DeclBits.EarlyAttrValidation = validated;
  }
  
  /// Whether the declaration is currently being validated.
  bool isBeingTypeChecked();
  
  /// Toggle whether or not the declaration is being validated.
  void setIsBeingTypeChecked(bool ibt = true) {
    DeclBits.BeingTypeChecked = ibt;
  }

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

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

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

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

    return getClangNodeImpl();
  }

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

    return getClangNodeImpl().getAsDecl();
  }

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

    return getClangNodeImpl().getAsMacro();
  }

  bool isPrivateStdlibDecl(bool whitelistProtocols=true) const;

  /// Whether this declaration is weak-imported.
  bool isWeakImported(ModuleDecl *fromModule) const;

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

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

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

/// \brief 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;
  RequirementKind Kind : 2;
  bool Invalid : 1;
  TypeLoc Types[2];
  /// Set during deserialization; used to print out the requirements accurately
  /// for the generated interface.
  StringRef AsWrittenString;

  RequirementRepr(SourceLoc SeparatorLoc, RequirementKind Kind,
                  TypeLoc FirstType, TypeLoc SecondType)
    : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
      Types{FirstType, SecondType} { }
  
  void printImpl(raw_ostream &OS, bool AsWritten) const;

public:
  /// \brief Construct a new conformance 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 getConformance(TypeLoc Subject,
                                    SourceLoc ColonLoc,
                                    TypeLoc Constraint) {
    return { ColonLoc, RequirementKind::Conformance, Subject, Constraint };
  }

  /// \brief 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, RequirementKind::SameType, FirstType, SecondType };
  }

  /// \brief Determine the kind of requirement
  RequirementKind getKind() const { return Kind; }

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

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

  /// \brief For a conformance requirement, return the subject of the
  /// conformance relationship.
  Type getSubject() const {
    assert(getKind() == RequirementKind::Conformance);
    return Types[0].getType();
  }

  TypeRepr *getSubjectRepr() const {
    assert(getKind() == RequirementKind::Conformance);
    return Types[0].getTypeRepr();
  }

  TypeLoc &getSubjectLoc() {
    assert(getKind() == RequirementKind::Conformance);
    return Types[0];
  }

  const TypeLoc &getSubjectLoc() const {
    assert(getKind() == RequirementKind::Conformance);
    return Types[0];
  }

  /// \brief For a conformance requirement, return the protocol or to which
  /// the subject conforms or superclass it inherits.
  Type getConstraint() const {
    assert(getKind() == RequirementKind::Conformance);
    return Types[1].getType();
  }

  TypeLoc &getConstraintLoc() {
    assert(getKind() == RequirementKind::Conformance);
    return Types[1];
  }

  const TypeLoc &getConstraintLoc() const {
    assert(getKind() == RequirementKind::Conformance);
    return Types[1];
  }

  /// \brief Retrieve the location of the ':' in an explicitly-written
  /// conformance requirement.
  SourceLoc getColonLoc() const {
    assert(getKind() == RequirementKind::Conformance);
    return SeparatorLoc;
  }

  /// \brief Retrieve the first type of a same-type requirement.
  Type getFirstType() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[0].getType();
  }

  TypeRepr *getFirstTypeRepr() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[0].getTypeRepr();
  }

  TypeLoc &getFirstTypeLoc() {
    assert(getKind() == RequirementKind::SameType);
    return Types[0];
  }

  const TypeLoc &getFirstTypeLoc() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[0];
  }

  /// \brief Retrieve the second type of a same-type requirement.
  Type getSecondType() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[1].getType();
  }

  TypeRepr *getSecondTypeRepr() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[1].getTypeRepr();
  }

  TypeLoc &getSecondTypeLoc() {
    assert(getKind() == RequirementKind::SameType);
    return Types[1];
  }

  const TypeLoc &getSecondTypeLoc() const {
    assert(getKind() == RequirementKind::SameType);
    return Types[1];
  }

  /// \brief Retrieve the location of the '==' in an explicitly-written
  /// same-type requirement.
  SourceLoc getEqualLoc() const {
    assert(getKind() == RequirementKind::SameType);
    return SeparatorLoc;
  }

  /// Set during deserialization; used to print out the requirements accurately
  /// for the generated interface.
  StringRef getAsWrittenString() const {
    return AsWrittenString;
  }
  void setAsWrittenString(StringRef Str) {
    AsWrittenString = Str;
  }

  SourceRange getSourceRange() const {
    return SourceRange(Types[0].getSourceRange().Start,
                       Types[1].getSourceRange().End);
  }

  LLVM_ATTRIBUTE_DEPRECATED(
      void dump() const LLVM_ATTRIBUTE_USED,
      "only for use within the debugger");
  void print(raw_ostream &OS) const;
  void printAsWritten(raw_ostream &OS) const;
};
  
template<typename T, ArrayRef<T> (GenericParamList::*accessor)() const>
class NestedGenericParamListIterator;
  
/// 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 {
  SourceRange Brackets;
  unsigned NumParams;
  SourceLoc WhereLoc;
  MutableArrayRef<RequirementRepr> Requirements;
  ArrayRef<ArchetypeType *> AllArchetypes;

  GenericParamList *OuterParameters;

  SourceLoc TrailingWhereLoc;
  unsigned FirstTrailingWhereArg;

  /// The builder used to build archetypes for this list.
  ArchetypeBuilder *Builder;

  GenericParamList(SourceLoc LAngleLoc,
                   ArrayRef<GenericTypeParamDecl *> Params,
                   SourceLoc WhereLoc,
                   MutableArrayRef<RequirementRepr> Requirements,
                   SourceLoc RAngleLoc);
  
  void getAsGenericSignatureElements(ASTContext &C,
                         llvm::DenseMap<ArchetypeType*, Type> &archetypeMap,
                         SmallVectorImpl<GenericTypeParamType*> &genericParams,
                         SmallVectorImpl<Requirement> &requirements) const;
  
  // 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,
                                  MutableArrayRef<RequirementRepr> Requirements,
                                  SourceLoc RAngleLoc);

  /// Create a new generic parameter list with the same parameters and
  /// requirements as this one, but parented to a different outer parameter
  /// list.
  GenericParamList *cloneWithOuterParameters(const ASTContext &Context,
                                             GenericParamList *Outer) {
    auto clone = create(Context,
                        SourceLoc(),
                        getParams(),
                        SourceLoc(),
                        getRequirements(),
                        SourceLoc());
    clone->setAllArchetypes(getAllArchetypes());
    clone->setOuterParameters(Outer);
    return clone;
  }
  
  /// Create an empty generic parameter list.
  static GenericParamList *getEmpty(ASTContext &Context) {
    // TODO: Could probably unique this in the AST context.
    return create(Context, SourceLoc(), {}, SourceLoc(), {}, SourceLoc());
  }
  
  MutableArrayRef<GenericTypeParamDecl *> getParams() {
    return { reinterpret_cast<GenericTypeParamDecl **>(this + 1), NumParams };
  }

  ArrayRef<GenericTypeParamDecl *> getParams() const {
    return const_cast<GenericParamList *>(this)->getParams();
  }

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

  /// Get the total number of parameters, including those from parent generic
  /// parameter lists.
  unsigned totalSize() const {
    return NumParams + (OuterParameters ? OuterParameters->totalSize() : 0);
  }
  
  /// \brief Retrieve the location of the 'where' keyword, or an invalid
  /// location if 'where' was not present.
  SourceLoc getWhereLoc() const { return WhereLoc; }

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

  /// \brief 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 that are written within the brackets,
  /// which does not include any 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);

  /// \brief Retrieves the list containing all archetypes described by this
  /// generic parameter clause.
  ///
  /// In this list of archetypes, the primary archetypes come first followed by
  /// any non-primary archetypes (i.e., those archetypes that encode associated
  /// types of another archetype).
  ///
  /// This does not include archetypes from the outer generic parameter list(s).
  ArrayRef<ArchetypeType *> getAllArchetypes() const { return AllArchetypes; }

  /// \brief Return the number of primary archetypes.
  unsigned getNumPrimaryArchetypes() const {
    return size();
  }
  
  /// \brief Retrieves the list containing only the primary archetypes described
  /// by this generic parameter clause. This excludes archetypes for associated
  /// types of the primary archetypes.
  ArrayRef<ArchetypeType *> getPrimaryArchetypes() const {
    return getAllArchetypes().slice(0, getNumPrimaryArchetypes());
  }
  
  /// \brief Retrieves the list containing only the associated archetypes.
  ArrayRef<ArchetypeType *> getAssociatedArchetypes() const {
    return getAllArchetypes().slice(getNumPrimaryArchetypes());
  }

  /// \brief Sets all archetypes *without* copying the source array.
  void setAllArchetypes(ArrayRef<ArchetypeType *> AA) {
    assert(AA.size() >= size()
           && "allArchetypes is smaller than number of generic params?!");
    AllArchetypes = AA;
  }

  using NestedArchetypeIterator
    = NestedGenericParamListIterator<ArchetypeType*,
                                     &GenericParamList::getAllArchetypes>;
  using NestedGenericParamIterator
    = NestedGenericParamListIterator<GenericTypeParamDecl*,
                                     &GenericParamList::getParams>;
  
  /// \brief Retrieves a list containing all archetypes from this generic
  /// parameter clause and all outer generic parameter clauses in outer-to-
  /// inner order.
  iterator_range<NestedArchetypeIterator> getAllNestedArchetypes() const;
  
  /// \brief Retrieves a list containing all generic parameter records from
  /// this generic parameter clause and all outer generic parameter clauses in
  /// outer-to-inner order.
  iterator_range<NestedGenericParamIterator> getNestedGenericParams() const;
  
  /// \brief Retrieve the outer generic parameter list, which provides the
  /// generic parameters of the context in which this generic parameter list
  /// exists.
  ///
  /// Consider the following generic class:
  ///
  /// \code
  /// class Vector<T> {
  ///   constructor<R : Range where R.Element == T>(range : R) { }
  /// }
  /// \endcode
  ///
  /// The generic parameter list <T> has no outer parameters, because it is
  /// the outermost generic parameter list. The generic parameter list
  /// <R : Range...> for the constructor has the generic parameter list <T> as
  /// its outer generic parameter list.
  GenericParamList *getOuterParameters() const { return OuterParameters; }

  /// \brief 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();

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

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

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

  /// Retrieve the depth of this generic parameter list.
  unsigned getDepth() const {
    unsigned depth = 0;
    for (auto gp = getOuterParameters(); gp; gp = gp->getOuterParameters())
      ++depth;
    return depth;
  }
  
  /// Get the generic parameter list as a GenericSignature in which the generic
  /// parameters have been canonicalized.
  ///
  /// \param archetypeMap   This DenseMap is populated with a mapping of
  ///                       context primary archetypes to dependent generic
  ///                       types.
  GenericSignature *getAsCanonicalGenericSignature(
                           llvm::DenseMap<ArchetypeType*, Type> &archetypeMap,
                           ASTContext &C) const;
  
  /// Derive a type substitution map for this generic parameter list from a
  /// matching substitution vector.
  TypeSubstitutionMap getSubstitutionMap(ArrayRef<Substitution> Subs) const;

  /// Derive the all-archetypes list for the given list of generic
  /// parameters.
  static ArrayRef<ArchetypeType*>
  deriveAllArchetypes(ArrayRef<GenericTypeParamDecl*> params,
                      SmallVectorImpl<ArchetypeType*> &archetypes);

  ArrayRef<Substitution> getForwardingSubstitutions(ASTContext &C);

  void setBuilder(ArchetypeBuilder *builder) {
    Builder = builder;
  }

  ArchetypeBuilder *getBuilder() const {
    return Builder;
  }

  /// Collect the nested archetypes of an archetype into the given
  /// collection.
  ///
  /// \param known - the set of archetypes already present in `all`
  /// \param all - the output list of archetypes
  static void addNestedArchetypes(ArchetypeType *archetype,
                                  SmallPtrSetImpl<ArchetypeType*> &known,
                                  SmallVectorImpl<ArchetypeType*> &all);
  
  void print(raw_ostream &OS);
  void dump();
};
  
/// An iterator template for lazily walking a nested generic parameter list.
template<typename T, ArrayRef<T> (GenericParamList::*accessor)() const>
class NestedGenericParamListIterator {
  SmallVector<const GenericParamList*, 2> stack;
  ArrayRef<T> elements;

  void refreshElements() {
    while (elements.empty()) {
      stack.pop_back();
      if (stack.empty()) break;
      elements = (stack.back()->*accessor)();
    }
  }
public:
  // Create a 'begin' iterator for a generic param list.
  NestedGenericParamListIterator(const GenericParamList *params) {
    // Walk up to the outermost list to create a stack of lists to walk.
    while (params) {
      stack.push_back(params);
      params = params->getOuterParameters();
    }
    // If the stack is empty, be like the 'end' iterator.
    if (stack.empty())
      return;

    elements = (stack.back()->*accessor)();
    refreshElements();
  }
  
  // Create an 'end' iterator.
  NestedGenericParamListIterator() {}
  
  // Iterator dereference.
  const T &operator*() const {
    return elements[0];
  }
  const T *operator->() const {
    return &elements[0];
  }
  
  // Iterator advancement.
  NestedGenericParamListIterator &operator++() {
    elements = elements.slice(1);
    refreshElements();
    return *this;
  }
  NestedGenericParamListIterator operator++(int) {
    auto copy = *this;
    ++(*this);
    return copy;
  }
  
  // Ghetto comparison. Only true if end() == end().
  bool operator==(const NestedGenericParamListIterator &o) const {
    return stack.empty() && o.stack.empty();
  }
  bool operator!=(const NestedGenericParamListIterator &o) const {
    return !stack.empty() || !o.stack.empty();
  }
  
  // An empty range of nested archetypes.
  static iterator_range<NestedGenericParamListIterator> emptyRange() {
    return {{}, {}};
  }
};
  
using NestedArchetypeIterator = GenericParamList::NestedArchetypeIterator;
using NestedGenericParamIterator = GenericParamList::NestedGenericParamIterator;

inline iterator_range<NestedArchetypeIterator>
GenericParamList::getAllNestedArchetypes() const {
  return {NestedArchetypeIterator(this), NestedArchetypeIterator()};
}
  
inline iterator_range<NestedGenericParamIterator>
GenericParamList::getNestedGenericParams() const {
  return {NestedGenericParamIterator(this), NestedGenericParamIterator()};
}

/// A trailing where clause.
class TrailingWhereClause {
  SourceLoc WhereLoc;

  /// The number of requirements. The actual requirements are tail-allocated.
  /// FIXME: uintptr_t is larger than we need, but makes sure that we get the
  /// right alignment for the requirement for the requirements that follow.
  uintptr_t 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 { reinterpret_cast<RequirementRepr *>(this + 1), NumRequirements };
  }

  /// Retrieve the set of requirements.
  ArrayRef<RequirementRepr> getRequirements() const {
    return { reinterpret_cast<const RequirementRepr *>(this + 1),
             NumRequirements };
  }

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

/// 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 : public Decl {
public:
  typedef std::pair<Identifier, SourceLoc> AccessPathElement;

private:
  SourceLoc ImportLoc;
  SourceLoc KindLoc;

  /// The number of elements in this path.
  unsigned NumPathElements;

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

  AccessPathElement *getPathBuffer() {
    return reinterpret_cast<AccessPathElement*>(this+1);
  }
  const AccessPathElement *getPathBuffer() const {
    return reinterpret_cast<const AccessPathElement*>(this+1);
  }
  
  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-homogenous, 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 ArrayRef<AccessPathElement>(getPathBuffer(), 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>(ImportDeclBits.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 getLoc() 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 Decl, public DeclContext,
                            public IterableDeclContext {
  SourceLoc ExtensionLoc;  // Location of 'extension' keyword.
  SourceRange Braces;

  /// The type being extended.
  TypeLoc ExtendedType;
  
  /// The generic parameters of the extension.
  GenericParamList *GenericParams = nullptr;

  /// \brief The generic signature of this extension.
  ///
  /// This is the semantic representation of a generic parameters and the
  /// requirements placed on them.
  ///
  /// FIXME: The generic parameters here are also derivable from
  /// \c GenericParams. However, we likely want to make \c GenericParams
  /// the parsed representation, and not part of the module file.
  GenericSignature *GenericSig = nullptr;

  MutableArrayRef<TypeLoc> Inherited;

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

  /// \brief 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, TypeLoc 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 (!ExtensionDeclBits.HaveConformanceLoader)
      return { nullptr, 0 };

    return takeConformanceLoaderSlow();
  }

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

public:
  using Decl::getASTContext;

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

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

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

  /// Retrieve the innermost generic parameter list.
  GenericParamList *getGenericParams() const {
    return GenericParams;
  }

  void setGenericParams(GenericParamList *params);

  /// 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 extension.
  GenericSignature *getGenericSignature() const { return GenericSig; }

  /// Set the generic signature of this extension.
  void setGenericSignature(GenericSignature *sig);

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

  /// Retrieve the type being extended.
  Type getExtendedType() const { return ExtendedType.getType(); }

  /// Retrieve the extended type location.
  TypeLoc &getExtendedTypeLoc() { return ExtendedType; }

  /// Retrieve the extended type location.
  const TypeLoc &getExtendedTypeLoc() const { return ExtendedType; }

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

  /// Whether we already validated this extension.
  bool validated() const {
    return ExtensionDeclBits.Validated;
  }

  /// Set whether we have validated this extension.
  void setValidated(bool validated = true) {
    ExtensionDeclBits.Validated = validated;
  }

  /// Whether we already type-checked the inheritance clause.
  bool checkedInheritanceClause() const {
    return ExtensionDeclBits.CheckedInheritanceClause;
  }

  /// Note that we have already type-checked the inheritance clause.
  void setCheckedInheritanceClause(bool checked = true) {
    ExtensionDeclBits.CheckedInheritanceClause = checked;
  }

  bool hasDefaultAccessibility() const {
    return ExtensionDeclBits.DefaultAndMaxAccessLevel != 0;
  }

  Accessibility getDefaultAccessibility() const {
    assert(hasDefaultAccessibility() && "not computed yet");
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << static_cast<unsigned>(Accessibility::Private)))
      return Accessibility::Private;
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << static_cast<unsigned>(Accessibility::Internal)))
      return Accessibility::Internal;
    return Accessibility::Public;
  }

  Accessibility getMaxAccessibility() const {
    assert(hasDefaultAccessibility() && "not computed yet");
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << static_cast<unsigned>(Accessibility::Public)))
      return Accessibility::Public;
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << static_cast<unsigned>(Accessibility::Internal)))
      return Accessibility::Internal;
    return Accessibility::Private;
  }

  void setDefaultAndMaxAccessibility(Accessibility defaultAccess,
                                     Accessibility maxAccess) {
    assert(!hasDefaultAccessibility() && "default accessibility already set");
    assert(maxAccess >= defaultAccess);
    ExtensionDeclBits.DefaultAndMaxAccessLevel =
        (1 << static_cast<unsigned>(defaultAccess)) |
        (1 << static_cast<unsigned>(maxAccess));
    assert(getDefaultAccessibility() == defaultAccess && "not enough bits");
    assert(getMaxAccessibility() == maxAccess && "not enough bits");
  }

  void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

  DeclRange getMembers(bool forceDelayedMembers = true) const;
  void setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData);
  bool hasLazyMembers() const {
    return IterableDeclContext::isLazy();
  }

  /// Determine whether this is a constrained extension, which adds additional
  /// requirements beyond those of the nominal type.
  bool isConstrainedExtension() const;

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

  using DeclContext::operator new;
};

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

/// \brief 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 {
  Pattern *ThePattern;
  llvm::PointerIntPair<Expr *, 1, bool> InitAndChecked;
  
public:
  PatternBindingEntry(Pattern *P, Expr *E)
    : ThePattern(P), InitAndChecked(E, false) {}

  Pattern *getPattern() const { return ThePattern; }
  void setPattern(Pattern *P) { ThePattern = P; }
  Expr *getInit() const { return InitAndChecked.getPointer(); }
  void setInit(Expr *E) { InitAndChecked.setPointer(E); }
  bool isInitializerChecked() const { return InitAndChecked.getInt(); }
  void setInitializerChecked() { InitAndChecked.setInt(true); }
};

/// \brief 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 : public Decl {
  SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
  SourceLoc VarLoc;    ///< Location of the 'var' keyword.

  unsigned numPatternEntries;

  friend class Decl;
  
  PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                     SourceLoc VarLoc, unsigned NumPatternEntries,
                     DeclContext *Parent);

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, Expr *E,
                                    DeclContext *Parent) {
    return create(Ctx, StaticLoc, StaticSpelling, VarLoc,
                  PatternBindingEntry(Pat, E), Parent);
  }


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

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

  Expr *getInit(unsigned i) const {
    return getPatternList()[i].getInit();
  }
  
  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);

  /// 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.
  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();
  }
  
  /// Does this binding declare something that requires storage?
  bool hasStorage() const;
  
  /// When the pattern binding contains only a single variable with no
  /// destructuring, retrieve that variable.
  VarDecl *getSingleVar() const;

  bool isStatic() const { return PatternBindingDeclBits.IsStatic; }
  void setStatic(bool s) { PatternBindingDeclBits.IsStatic = s; }
  SourceLoc getStaticLoc() const { return StaticLoc; }
  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(
        PatternBindingDeclBits.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 {
      reinterpret_cast<PatternBindingEntry*>(this + 1),
      numPatternEntries
    };
  }
};
  
/// 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 Decl, public DeclContext {
  BraceStmt *Body;

public:
  TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
    : Decl(DeclKind::TopLevelCode, Parent),
      DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
      Body(Body) {}

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

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

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::TopLevelCode;
  }
  static bool classof(const DeclContext *C) {
    return C->getContextKind() == DeclContextKind::TopLevelCodeDecl;
  }
  
  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;
  }
};

/// This represents one part of a #if block.  If the condition field is
/// non-null, then this represents a #if or a #elseif, otherwise it represents
/// an #else block.
struct IfConfigDeclClause {
  /// The location of the #if, #elseif, or #else keyword.
  SourceLoc Loc;
  
  /// The condition guarding this #if or #elseif block.  If this is null, this
  /// is a #else clause.
  Expr *Cond;

  ArrayRef<Decl*> Members;

  /// True if this is the active clause of the #if block.  Since this is
  /// evaluated at parse time, this is always known.
  bool isActive;

  IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef<Decl*> Members,
                     bool isActive)
    : Loc(Loc), Cond(Cond), Members(Members), isActive(isActive) {
  }
};
  
  
/// IfConfigDecl - This class represents the declaration-side representation of
/// #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 declaration.
class IfConfigDecl : public Decl {
  /// An array of clauses controlling each of the #if/#elseif/#else conditions.
  /// The array is ASTContext allocated.
  ArrayRef<IfConfigDeclClause> Clauses;
  SourceLoc EndLoc;
  bool HadMissingEnd;
public:
  
  IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigDeclClause> Clauses,
               SourceLoc EndLoc, bool HadMissingEnd)
    : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc),
      HadMissingEnd(HadMissingEnd) {
  }

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

  /// Return the active clause, or null if there is no active one.
  const IfConfigDeclClause *getActiveClause() const {
    for (auto &Clause : Clauses)
      if (Clause.isActive) return &Clause;
    return nullptr;
  }
  const ArrayRef<Decl*> getActiveMembers() const {
    if (auto *Clause = getActiveClause())
      return Clause->Members;
    return {};
  }
  
  SourceLoc getEndLoc() const { return EndLoc; }
  SourceLoc getLoc() const { return Clauses[0].Loc; }

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

/// 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, 2, OptionalEnum<Accessibility>> TypeAndAccess;

protected:
  ValueDecl(DeclKind K,
            llvm::PointerUnion<DeclContext *, ASTContext *> context,
            DeclName name, SourceLoc NameLoc)
    : Decl(K, context), Name(name), NameLoc(NameLoc) {
    ValueDeclBits.AlreadyInLookupTable = false;
    ValueDeclBits.CheckedRedeclaration = false;
  }

  /// The interface type, mutable because some subclasses compute this lazily.
  mutable Type InterfaceTy;

public:
  /// \brief Return true if this is a definition of a decl, not a forward
  /// declaration (e.g. of a function) that is implemented outside of the
  /// swift code.
  bool isDefinition() const;

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

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

  bool hasName() const { return bool(Name); }
  /// TODO: Rename to getSimpleName?
  Identifier getName() const { return Name.getBaseName(); }
  bool isOperator() const { return Name.isOperator(); }

  /// Returns the string for the base name, or "_" if this is unnamed.
  StringRef getNameStr() const {
    return hasName() ? getName().str() : "_";
  }

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

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

  SourceLoc getNameLoc() const { return NameLoc; }
  SourceLoc getLoc() const { return NameLoc; }

  bool hasType() const { return !TypeAndAccess.getPointer().isNull(); }
  Type getType() const {
    assert(hasType() && "declaration has no type set yet");
    return TypeAndAccess.getPointer();
  }

  /// Set the type of this declaration for the first time.
  void setType(Type T);

  /// Overwrite the type of this declaration.
  void overwriteType(Type T);

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

  /// Returns the access level specified explicitly by the user, or provided by
  /// default according to language rules.
  ///
  /// This is the access used when calculating if access control is being used
  /// consistently.
  Accessibility getFormalAccess() const {
    assert(hasAccessibility() && "accessibility not computed yet");
    return TypeAndAccess.getInt().getValue();
  }

  /// 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.
  Accessibility getEffectiveAccess() const;

  void setAccessibility(Accessibility access) {
    assert(!hasAccessibility() && "accessibility already set");
    overwriteAccessibility(access);
  }

  /// Overwrite the accessibility of this declaration.
  // This is needed in the LLDB REPL.
  void overwriteAccessibility(Accessibility 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.
  bool isAccessibleFrom(const DeclContext *DC) const;

  /// Get the innermost declaration context that can provide generic
  /// parameters used within this declaration.
  DeclContext *getPotentialGenericDeclContext();

  /// Get the innermost declaration context that can provide generic
  /// parameters used within this declaration.
  const DeclContext *getPotentialGenericDeclContext() const {
    return const_cast<ValueDecl *>(this)->getPotentialGenericDeclContext();
  }

  /// Retrieve the "interface" type of this value, which is the type used when
  /// the declaration is viewed from the outside. For a generic function,
  /// this will have generic function type using generic parameters rather than
  /// archetypes, while a generic nominal type's interface type will be the
  /// generic type specialized with its generic parameters.
  ///
  /// FIXME: Eventually, this will simply become the type of the value, and
  /// we will substitute in the appropriate archetypes within a particular
  /// context.
  Type getInterfaceType() const;
  bool hasInterfaceType() const { return !!InterfaceTy; }

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

  /// needsCapture - Check whether referring to this decl from a nested
  /// function requires capturing it.
  bool needsCapture() 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;

  /// Compute the overload signature for this declaration.
  OverloadSignature getOverloadSignature() 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 {
    return getAttrs().hasAttribute<ObjCAttr>();
  }

  void setIsObjC(bool Value);

  /// Is this declaration marked with 'final'?
  bool isFinal() const {
    return getAttrs().hasAttribute<FinalAttr>();
  }

  /// Is this declaration marked with 'dynamic'?
  bool isDynamic() const {
    return getAttrs().hasAttribute<DynamicAttr>();
  }

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

  /// 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.
  AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC) 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;
  }  
};

/// 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)
  {
    TypeDeclBits.CheckedInheritanceClause = false;
  }

public:
  Type getDeclaredType() const;

  Type getDeclaredInterfaceType() const;

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

  /// Whether we already type-checked the inheritance clause.
  bool checkedInheritanceClause() const {
    return TypeDeclBits.CheckedInheritanceClause;
  }

  /// Note that we have already type-checked the inheritance clause.
  void setCheckedInheritanceClause(bool checked = true) {
    TypeDeclBits.CheckedInheritanceClause = checked;
  }

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

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

/// TypeAliasDecl - This is a declaration of a typealias, for example:
///
///    typealias foo = int
///
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public TypeDecl {
  /// The type that represents this (sugared) name alias.
  mutable NameAliasType *AliasTy;

  SourceLoc TypeAliasLoc; // The location of the 'typalias' keyword
  TypeLoc UnderlyingTy;

public:
  TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name,
                SourceLoc NameLoc, TypeLoc UnderlyingTy,
                DeclContext *DC);

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

  /// getUnderlyingType - Returns the underlying type, which is
  /// assumed to have been set.
  Type getUnderlyingType() const {
    assert(!UnderlyingTy.getType().isNull() &&
           "getting invalid underlying type");
    return UnderlyingTy.getType();
  }

  /// computeType - Compute the type (and declared type) of this type alias;
  /// can only be called after the alias type has been resolved.
  void computeType();

  /// \brief Determine whether this type alias has an underlying type.
  bool hasUnderlyingType() const { return !UnderlyingTy.getType().isNull(); }

  TypeLoc &getUnderlyingTypeLoc() { return UnderlyingTy; }
  const TypeLoc &getUnderlyingTypeLoc() const { return UnderlyingTy; }

  /// getAliasType - Return the sugared version of this decl as a Type.
  NameAliasType *getAliasType() const { return AliasTy; }

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

/// 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 {
  /// The archetype describing this abstract type parameter within its scope.
  ArchetypeType *Archetype;

protected:
  AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name,
                        SourceLoc NameLoc)
    : TypeDecl(kind, dc, name, NameLoc, { }), Archetype(nullptr) { }

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

  /// Retrieve the archetype that describes this abstract type parameter
  /// within its scope.
  ArchetypeType *getArchetype() const { return Archetype; }

  /// Set the archetype used to describe this abstract type parameter within
  /// its scope.
  void setArchetype(ArchetypeType *archetype) { Archetype = archetype; }

  /// Retrieve the set of protocols to which this abstract type
  /// parameter conforms.
  ArrayRef<ProtocolDecl *> getConformingProtocols(LazyResolver *resolver) 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 {
  unsigned Depth : 16;
  unsigned Index : 16;

public:
  /// 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 Depth; }

  /// Set the depth of this generic type parameter.
  ///
  /// \sa getDepth
  void setDepth(unsigned depth) { Depth = depth; }

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

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

  /// Determine whether this is the implicit 'Self' type parameter of
  /// a protocol.
  bool isProtocolSelf() 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
///
/// Every protocol has an implicitly-created associated type 'Self' that
/// describes a type that conforms to the protocol.
class AssociatedTypeDecl : public AbstractTypeParamDecl {
  /// The location of the initial keyword.
  SourceLoc KeywordLoc;

  /// The default definition.
  TypeLoc DefaultDefinition;

  LazyMemberLoader *Resolver = nullptr;
  uint64_t ResolverContextData;

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

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

  /// Retrieve the default definition type.
  Type getDefaultDefinitionType() const {
    return getDefaultDefinitionLoc().getType();
  }

  TypeLoc &getDefaultDefinitionLoc();
  const TypeLoc &getDefaultDefinitionLoc() const {
    return const_cast<AssociatedTypeDecl *>(this)->getDefaultDefinitionLoc();
  }

  /// computeType - Compute the type (and declared type) of this associated
  /// type; can only be called after the alias type has been resolved.
  void computeType();

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

  void setIsRecursive() { AssociatedTypeDeclBits.Recursive = true; }
  bool isRecursive() { return AssociatedTypeDeclBits.Recursive; }

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

class MemberLookupTable;
class ConformanceLookupTable;

/// Kinds of optional types.
enum OptionalTypeKind : unsigned {
  /// The type is not an optional type.
  OTK_None = 0,

  /// The type is Optional<T>.
  OTK_Optional,

  /// The type is ImplicitlyUnwrappedOptional<T>.
  OTK_ImplicitlyUnwrappedOptional
};
enum { NumOptionalTypeKinds = 2 };
  
// Kinds of pointer types.
enum PointerTypeKind : unsigned {
  PTK_UnsafeMutablePointer,
  PTK_UnsafePointer,
  PTK_AutoreleasingUnsafeMutablePointer,
};

/// An implicitly created member decl, used when importing a Clang enum type.
/// These are not added to their enclosing type unless forced.
typedef std::function<void(SmallVectorImpl<Decl *> &)> DelayedDecl;

/// NominalTypeDecl - a declaration of a nominal type, like a struct.  This
/// decl is always a DeclContext.
class NominalTypeDecl : public TypeDecl, public DeclContext,
                        public IterableDeclContext {
  SourceRange Braces;

  /// \brief The set of implicit members and protocols added to imported enum
  /// types.  These members and protocols are added to the NominalDecl only if
  /// the nominal type is directly or indirectly referenced.
  std::unique_ptr<DelayedDecl> DelayedMembers;

  GenericParamList *GenericParams;

  /// \brief The generic signature of this type.
  ///
  /// This is the semantic representation of a generic parameters and the
  /// requirements placed on them.
  ///
  /// FIXME: The generic parameters here are also derivable from
  /// \c GenericParams. However, we likely want to make \c GenericParams
  /// the parsed representation, and not part of the module file.
  GenericSignature *GenericSig = nullptr;

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

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

  /// \brief The generation at which we last loaded extensions.
  unsigned ExtensionGeneration: 28;
                          
  /// \brief Whether or not the generic signature of the type declaration is
  /// currently being validated.
  unsigned ValidatingGenericSignature: 1;
  
  /// \brief Whether or not this declaration has a failable initializer member,
  /// and whether or not we've actually searched for one.
  unsigned HasFailableInits : 1;
  unsigned SearchedForFailableInits : 1;

  /// Whether there is an active conformance loader for this
  /// nominal type.
  unsigned HaveConformanceLoader : 1;

  /// 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 (!HaveConformanceLoader)
      return { nullptr, 0 };

    return takeConformanceLoaderSlow();
  }

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

  /// \brief 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.
  llvm::PointerIntPair<MemberLookupTable *, 1, bool> LookupTable;

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

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

  /// \brief 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) const;

protected:
  Type DeclaredTy;
  Type DeclaredTyInContext;

  void setDeclaredType(Type declaredTy) {
    assert(DeclaredTy.isNull() && "Already set declared type");
    DeclaredTy = declaredTy;
  }

  NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
                  SourceLoc NameLoc,
                  MutableArrayRef<TypeLoc> inherited,
                  GenericParamList *GenericParams) :
    TypeDecl(K, DC, name, NameLoc, inherited),
    DeclContext(DeclContextKind::NominalTypeDecl, DC),
    IterableDeclContext(IterableDeclContextKind::NominalTypeDecl),
    GenericParams(nullptr), DeclaredTy(nullptr)
  {
    setGenericParams(GenericParams);
    NominalTypeDeclBits.HasDelayedMembers = false;
    NominalTypeDeclBits.AddedImplicitInitializers = false;
    ExtensionGeneration = 0;
    ValidatingGenericSignature = false;
    SearchedForFailableInits = false;
    HasFailableInits = false;
    HaveConformanceLoader = false;
  }

  friend class ProtocolType;

public:
  using TypeDecl::getASTContext;

  DeclRange getMembers(bool forceDelayedMembers = true) const;
  SourceRange getBraces() const { return Braces; }
  
  void setBraces(SourceRange braces) { Braces = braces; }

  /// \brief Does this declaration expose a fixed layout to all resilience
  /// domains?
  bool hasFixedLayout() const;

  /// \brief Does this declaration expose a fixed layout to the given
  /// module?
  bool hasFixedLayout(ModuleDecl *M) const {
    return (hasFixedLayout() || M == getModuleContext());
  }

  void setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData);
  bool hasLazyMembers() const {
    return IterableDeclContext::isLazy();
  }
  
  void setIsValidatingGenericSignature(bool ivgs = true) {
    ValidatingGenericSignature = ivgs;
  }
  
  bool IsValidatingGenericSignature() {
    return ValidatingGenericSignature;
  }
  
  /// \brief Returns true if this this decl contains delayed value or protocol
  /// declarations.
  bool hasDelayedMembers() const {
    return NominalTypeDeclBits.HasDelayedMembers;
  }
  
  /// \brief Mark this declaration as having delayed members or not.
  void setHasDelayedMembers(bool hasDelayedMembers = true) {
    NominalTypeDeclBits.HasDelayedMembers = hasDelayedMembers;
  }

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

  /// Note that we have attempted to
  void setAddedImplicitInitializers() {
    NominalTypeDeclBits.AddedImplicitInitializers = true;
  }
              
  bool getHasFailableInits() { return HasFailableInits; }
  void setHasFailableInits(bool failable = true) {
    HasFailableInits = failable;
  }
  void setSearchedForFailableInits(bool searched = true) {
    SearchedForFailableInits = searched;
  }
  bool getSearchedForFailableInits() {
    return SearchedForFailableInits;
  }

  GenericParamList *getGenericParams() const { return GenericParams; }

  /// Provide the set of parameters to a generic type, or null if
  /// this function is not generic.
  void setGenericParams(GenericParamList *params);
  
  /// Set the generic signature of this type.
  void setGenericSignature(GenericSignature *sig);

  /// Retrieve the generic parameter types.
  ArrayRef<GenericTypeParamType *> getGenericParamTypes() const {
    if (!GenericSig)
      return { };

    return GenericSig->getGenericParams();
  }

  /// Retrieve the generic requirements.
  ArrayRef<Requirement> getGenericRequirements() const {
    if (!GenericSig)
      return { };

    return GenericSig->getRequirements();
  }
  
  /// Retrieve the generic signature.
  GenericSignature *getGenericSignature() const {
    return GenericSig;
  }

  /// Mark generic type signature as invalid.
  void markInvalidGenericSignature();

  /// getDeclaredType - Retrieve the type declared by this entity.
  Type getDeclaredType() const { return DeclaredTy; }

  /// Compute the type (and declared type) of this nominal type.
  void computeType();

  Type getDeclaredTypeInContext() const;

  /// Get the "interface" type of the given nominal type, which is the
  /// type used to refer to the nominal type externally.
  ///
  /// For a generic type, or a member thereof, this is the a specialization
  /// of the type using its own generic parameters.
  Type computeInterfaceType() const;

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

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

  /// Make a member of this nominal type, or one of its extensions,
  /// immediately visible in the lookup table.
  ///
  /// A member of a nominal type or extension thereof will become
  /// visible to name lookup as soon as it is added. However, if the
  /// addition of a member is delayed---for example, because it's
  /// being introduced in response to name lookup---this method can be
  /// called to make it immediately visible.
  void makeMemberVisible(ValueDecl *member);

  /// 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.
  ///
  /// \param ignoreNewExtensions Whether to avoid loading any new extension.
  /// Used by the module loader to break recursion.
  ArrayRef<ValueDecl *> lookupDirect(DeclName name,
                                     bool ignoreNewExtensions = false);

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

  /// \brief True if the type can implicitly derive a conformance for the given
  /// protocol.
  ///
  /// If true, explicit conformance checking will synthesize implicit
  /// declarations for requirements of the protocol that are not satisfied by
  /// the type's explicit members.
  bool derivesProtocolConformance(ProtocolDecl *protocol) const;

  void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);

  using TypeDecl::getDeclaredInterfaceType;

  /// classifyAsOptionalType - Decide whether this declaration is one
  /// of the library-intrinsic Optional<T> or ImplicitlyUnwrappedOptional<T> types.
  OptionalTypeKind classifyAsOptionalType() const;
  
private:
  /// Predicate used to filter StoredPropertyRange.
  struct ToStoredProperty {
    Optional<VarDecl *> operator()(Decl *decl) const;
  };

  /// Force delayed implicit member declarations to be added to the type
  /// declaration.
  void forceDelayedMemberDecls();
  
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.
  StoredPropertyRange getStoredProperties() const {
    return StoredPropertyRange(getMembers(), ToStoredProperty());
  }

  bool hasDelayedMemberDecls() { return DelayedMembers.get(); }

  void setDelayedMemberDecls(const DelayedDecl &delayedMembers);

  /// Force delayed implicit member and protocol declarations to be added to the
  /// type declaration.
  void forceDelayed() {
    forceDelayedMemberDecls();
  }
  
  // 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 DeclContext *C) {
    return C->getContextKind() == DeclContextKind::NominalTypeDecl;
  }
  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; }

  using DeclContext::operator new;
};

/// \brief 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 : public NominalTypeDecl {
  SourceLoc EnumLoc;

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

  friend class IterativeTypeChecker;

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

  EnumElementDecl *getElement(Identifier Name) const;
  
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());
  }
  
  /// 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>(EnumDeclBits.Circularity);
  }
  
  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    EnumDeclBits.Circularity = static_cast<unsigned>(circularity);
  }
  
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const DeclContext *C) {
    return isa<NominalTypeDecl>(C) && classof(cast<NominalTypeDecl>(C));
  }
  static bool classof(const IterableDeclContext *C) {
    return isa<NominalTypeDecl>(C) && classof(cast<NominalTypeDecl>(C));
  }
  
  /// Determine whether this enum declares a raw type in its inheritance clause.
  bool hasRawType() const {
    return (bool)LazySemanticInfo.RawType.getPointer();
  }
  /// Retrieve the declared raw type of the enum from its inheritance clause,
  /// or null if it has none.
  Type getRawType() const {
    return LazySemanticInfo.RawType.getPointer();
  }

  /// Set the raw type of the enum from its inheritance clause.
  void setRawType(Type rawType) {
    LazySemanticInfo.RawType.setPointerAndInt(rawType, true);
  }
  
  /// True if the enum has cases, and none of those cases have associated values.
  ///
  /// Note that this is false for enums with absolutely no cases.
  bool hasOnlyCasesWithoutAssociatedValues() const;

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

/// 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 : 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 NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Struct;
  }
  static bool classof(const DeclContext *C) {
    return isa<NominalTypeDecl>(C) && classof(cast<NominalTypeDecl>(C));
  }
  static bool classof(const IterableDeclContext *C) {
    return isa<NominalTypeDecl>(C) && classof(cast<NominalTypeDecl>(C));
  }

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

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

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

enum class ObjCClassKind : uint8_t {
  /// Neither the class nor any of its superclasses are @objc.
  NonObjC,
  /// One of the superclasses is @objc but another superclass or the
  /// class itself has generic parameters, so while it cannot be
  /// directly represented in Objective-C, it has implicitly @objc
  /// members.
  ObjCMembers,
  /// The top-level ancestor of this class is not @objc, but the
  /// class itself is.
  ObjCWithSwiftRoot,
  /// The class is bona-fide @objc.
  ObjC,
};

/// 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 : public NominalTypeDecl {
  class ObjCMethodLookupTable;

  SourceLoc ClassLoc;
  ObjCMethodLookupTable *ObjCMethodLookup = nullptr;

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

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

  friend class IterativeTypeChecker;

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 this class has a superclass.
  bool hasSuperclass() const { return (bool)getSuperclass(); }

  /// Retrieve the superclass of this class, or null if there is no superclass.
  Type getSuperclass() const { return LazySemanticInfo.Superclass.getPointer(); }

  /// Set the superclass of this class.
  void setSuperclass(Type superclass) {
    LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
  }

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

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

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

  /// Set whether this class requires all of its stored properties to
  /// have initializers in the class definition.
  void setRequiresStoredPropertyInits(bool requiresInits) {
    ClassDeclBits.RequiresStoredPropertyInits = requiresInits;
  }

  /// 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.
  bool isForeign() const {
    return ClassDeclBits.Foreign;
  }
  void setForeign(bool isForeign = true) {
    ClassDeclBits.Foreign = true;
  }

  /// Find a method of a class that overrides a given method.
  /// Return nullptr, if no such method exists.
  FuncDecl *findOverridingDecl(const FuncDecl *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.
  FuncDecl *findImplementingMethod(const FuncDecl *method) const;

  /// True if the class has a destructor.
  ///
  /// Fully type-checked classes always contain destructors, but during parsing
  /// or type-checking, the implicit destructor may not have been synthesized
  /// yet if one was not explicitly declared.
  bool hasDestructor() const { return ClassDeclBits.HasDestructorDecl; }

  /// Set the 'has destructor' flag.
  void setHasDestructor() { ClassDeclBits.HasDestructorDecl = 1; }
  
  /// Retrieve the destructor for this class.
  DestructorDecl *getDestructor();

  /// Determine whether this class inherits the convenience initializers
  /// from its superclass.
  ///
  /// \param resolver Used to resolve the signatures of initializers, which is
  /// required for name lookup.
  bool inheritsSuperclassInitializers(LazyResolver *resolver);

  /// Figure out if this class has any @objc ancestors, in which case it should
  /// have implicitly @objc members. Note that a class with generic ancestry
  /// might have implicitly @objc members, but will never itself be @objc.
  ObjCClassKind checkObjCAncestry() 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 whose Objective-C name has been
  /// finalized.
  void recordObjCMethod(AbstractFunctionDecl *method);

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


/// ProtocolDecl - A declaration of a protocol, for example:
///
///   protocol Drawable {
///     func draw()
///   }
class ProtocolDecl : public NominalTypeDecl {
  SourceLoc ProtocolLoc;

  ArrayRef<ProtocolDecl *> InheritedProtocols;

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

  /// Whether we have already set the list of inherited protocols.
  unsigned InheritedProtocolsSet : 1;

  bool requiresClassSlow();

  bool existentialConformsToSelfSlow();

  bool existentialTypeSupportedSlow(LazyResolver *resolver);

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

  /// Retrieve the set of protocols inherited from this protocol.
  ArrayRef<ProtocolDecl *> getInheritedProtocols(LazyResolver *resolver) const;

  /// \brief Determine whether this protocol inherits from the given ("super")
  /// protocol.
  bool inheritsFrom(const ProtocolDecl *Super) const;
  
  ProtocolType *getDeclaredType() const {
    return reinterpret_cast<ProtocolType *>(DeclaredTy.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() {
    if (ProtocolDeclBits.RequiresClassValid)
      return ProtocolDeclBits.RequiresClass;

    return requiresClassSlow();
  }

  /// Specify that this protocol is class-bounded, e.g., because it was
  /// annotated with the 'class' keyword.
  void setRequiresClass() {
    ProtocolDeclBits.RequiresClassValid = true;
    ProtocolDeclBits.RequiresClass = true;
  }

  /// 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 {
    if (ProtocolDeclBits.ExistentialConformsToSelfValid)
      return ProtocolDeclBits.ExistentialConformsToSelf;

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

  /// 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 are rank-1, that is, do not have Self or associated
  /// type requirements that may depend on the existential's opened type.
  bool existentialTypeSupported(LazyResolver *resolver) const {
    if (ProtocolDeclBits.ExistentialTypeSupportedValid)
      return ProtocolDeclBits.ExistentialTypeSupported;

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

  /// If this is known to be a compiler-known protocol, returns the kind.
  /// Otherwise returns None.
  ///
  /// Note that this is only valid after type-checking.
  Optional<KnownProtocolKind> getKnownProtocolKind() const {
    if (ProtocolDeclBits.KnownProtocol == 0)
      return None;
    return static_cast<KnownProtocolKind>(ProtocolDeclBits.KnownProtocol - 1);
  }

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

  /// Records that this is a compiler-known protocol.
  void setKnownProtocolKind(KnownProtocolKind kind) {
    assert((!getKnownProtocolKind() || *getKnownProtocolKind() == kind) &&
           "can't reset known protocol kind");
    ProtocolDeclBits.KnownProtocol = static_cast<unsigned>(kind) + 1;
    assert(getKnownProtocolKind() && *getKnownProtocolKind() == kind &&
           "not enough bits");
  }

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

  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    ProtocolDeclBits.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 HasMissingRequirements;
  }

  void setHasMissingRequirements(bool newValue) {
    HasMissingRequirements = newValue;
  }

  /// Set the list of inherited protocols.
  void setInheritedProtocols(ArrayRef<ProtocolDecl *> protocols) {
    assert(!InheritedProtocolsSet && "protocols already set");
    InheritedProtocolsSet = true;
    InheritedProtocols = protocols;
  }

  void clearInheritedProtocols() {
    InheritedProtocolsSet = true;
    InheritedProtocols = { };
  }

  bool isInheritedProtocolsValid() const {
    return InheritedProtocolsSet;
  }

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

  /// Create the implicit generic parameter list for a protocol or
  /// extension thereof.
  ///
  /// FIXME: protocol extensions will introduce a where clause here as well.
  GenericParamList *createGenericParams(DeclContext *dc);

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

// Note that the values of these enums line up with %select values in
// diagnostics.
enum class AccessorKind {
  /// \brief This is not a property accessor.
  NotAccessor = -1,
  /// \brief This is a getter for a property or subscript.
  IsGetter = 0,
  /// \brief This is a setter for a property or subscript.
  IsSetter = 1,
  /// \brief This is a willSet specifier for a property.
  IsWillSet = 2,
  /// \brief This is a didSet specifier for a property.
  IsDidSet = 3,
  /// \brief This is a materializeForSet accessor for a property.
  IsMaterializeForSet = 4,
  /// \brief This is an address-family accessor for a property or
  /// subscript.  It also has an addressor kind.
  IsAddressor = 5,
  /// \brief This is a mutableAddress-family accessor for a property
  /// or subscript.  It also has an addressor kind.
  IsMutableAddressor = 6,
};

/// The safety semantics of this addressor.
enum class AddressorKind : unsigned char {
  /// \brief This is not an addressor.
  NotAddressor,
  /// \brief This is an unsafe addressor; it simply returns an address.
  Unsafe,
  /// \brief This is an owning addressor; it returns a Builtin.UnknownObject
  /// which should be released when the caller is done with the object.
  Owning,
  /// \brief This is an owning addressor; it returns a Builtin.NativeObject
  /// which should be released when the caller is done with the object.
  NativeOwning,
  /// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
  /// which should be unpinned when the caller is done with the object.
  NativePinning,
};

/// Whether an access to storage is for reading, writing, or both.
enum class AccessKind : unsigned char {
  /// The access is just to read the current value.
  Read,

  /// The access is just to overwrite the current value.
  Write,

  /// The access may require either reading or writing the current value.
  ReadWrite
};

/// The way to actually evaluate an access to storage.
enum class AccessStrategy : unsigned char {
  /// The decl is a VarDecl with its own backing storage; evaluate its
  /// address directly.
  Storage,

  /// The decl has addressors; call the appropriate addressor for the
  /// access kind.  These calls are currently always direct.
  Addressor,

  /// Directly call the getter, setter, or materializeForSet accessor.
  DirectToAccessor,

  /// Indirectly call the getter, setter, or materializeForSet accessor.
  DispatchToAccessor,
};

/// AbstractStorageDecl - This is the common superclass for VarDecl and
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
public:
  enum StorageKindTy {
    /// There are bits stored in memory for this object, and they are accessed
    /// directly.  This is not valid for a SubscriptDecl.
    Stored,
    
    /// This is a stored property with trivial accessors which simply get and
    /// set the underlying storage.  This is not valid for a SubscriptDecl.
    ///
    /// These accessors are used for several different purposes:
    ///   1) In an @objc variable, these accessors are dynamically dispatched
    ///      to and may be overridden.
    ///   2) When a stored property satisfies a protocol requirement, these
    ///      accessors end up as entries in the witness table.
    ///   3) Perhaps someday these will be used by accesses outside of this
    ///      resilience domain, when the owning type is resilient.
    ///
    StoredWithTrivialAccessors,

    /// This is a stored property with either a didSet specifier or a
    /// willSet specifier (or both).  Sema synthesizes a setter which
    /// calls them at the appropriate points.
    StoredWithObservers,

    /// There are bits stored in memory for this object, but they are
    /// not allocated directly within the container; instead, there
    /// are accessors which return the address of the memory.  The
    /// value is accessed directly through the returned address.
    ///
    /// This is legal on both VarDecls and SubscriptDecls.
    ///
    /// There is always at least an 'address' accessor; if the object
    /// is mutable, there will also be a 'mutableAddress' accessor.
    Addressed,
    
    /// Like Addressed, this object has address accessors.  Like
    /// StoredWithTrivialAccessors, accessors have been synthesized
    /// which simply read and write through the addresses returned by
    /// the addressors.
    AddressedWithTrivialAccessors,

    /// Like Addressed, this object has address accessors.  Like
    /// StoredWithObservers, it also has either a willSet specifier or
    /// a didSet specifier.  Accessors have been synthesized, like
    /// with StoredWithObservers but using the address returned from
    /// the appropriate accessor instead.
    AddressedWithObservers,

    /// This is an override of an object which adds either a didSet
    /// specifier or a willSet specifier (or both).  Sema synthesizes
    /// a setter which calls them at the appropriate points around
    /// delegating to the superclass's setter.
    InheritedWithObservers,

    /// There is no memory associated with this decl anywhere.  It is
    /// accessed by calling a getter and setter.  If the setter is
    /// absent, then the value is only loadable, but not storable.
    Computed,

    /// This object was specified with non-trivial getter and
    /// mutableAddress accessors.  If it is accessed in a read-only
    /// manner, the getter is called; otherwise, mutableAddress is
    /// called.
    ///
    /// This turns out to the be the right thing for certain core data
    /// structures which, when they store a bridged object, cannot
    /// return the address at which the object is stored.
    ComputedWithMutableAddress,
  };
private:
  AbstractStorageDecl *OverriddenDecl;

  struct GetSetRecord;

  /// This is stored immediately before the GetSetRecord.
  struct AddressorRecord {
    FuncDecl *Address = nullptr;        // User-defined address accessor
    FuncDecl *MutableAddress = nullptr; // User-defined mutableAddress accessor

    GetSetRecord *getGetSet() {
      // Relies on not-strictly-portable ABI layout assumptions.
      return reinterpret_cast<GetSetRecord*>(this+1);
    }
  };
  void configureAddressorRecord(AddressorRecord *record,
                                FuncDecl *addressor, FuncDecl *mutableAddressor);

  struct GetSetRecord {
    SourceRange Braces;
    FuncDecl *Get = nullptr;       // User-defined getter
    FuncDecl *Set = nullptr;       // User-defined setter
    FuncDecl *MaterializeForSet = nullptr; // optional materializeForSet accessor

    AddressorRecord *getAddressors() {
      // Relies on not-strictly-portable ABI layout assumptions.
      return reinterpret_cast<AddressorRecord*>(this) - 1;
    }
  };
  void configureGetSetRecord(GetSetRecord *getSetRecord,
                             FuncDecl *getter, FuncDecl *setter,
                             FuncDecl *materializeForSet);
  void configureSetRecord(GetSetRecord *getSetInfo,
                          FuncDecl *setter,
                          FuncDecl *materializeForSet);

  struct ObservingRecord : GetSetRecord {
    FuncDecl *WillSet = nullptr;   // willSet(value):
    FuncDecl *DidSet = nullptr;    // didSet:
  };
  void configureObservingRecord(ObservingRecord *record,
                                FuncDecl *willSet, FuncDecl *didSet);

  struct GetSetRecordWithAddressors : AddressorRecord, GetSetRecord {};
  struct ObservingRecordWithAddressors : AddressorRecord, ObservingRecord {};

  llvm::PointerIntPair<GetSetRecord*, 2, OptionalEnum<Accessibility>> GetSetInfo;

  ObservingRecord &getDidSetInfo() const {
    assert(hasObservers());
    return *static_cast<ObservingRecord*>(GetSetInfo.getPointer());
  }
  AddressorRecord &getAddressorInfo() const {
    assert(hasAddressors());
    return *GetSetInfo.getPointer()->getAddressors();
  }

  void setStorageKind(StorageKindTy K) {
    AbstractStorageDeclBits.StorageKind = unsigned(K);
  }

protected:
  AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
                      SourceLoc NameLoc)
    : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
    AbstractStorageDeclBits.StorageKind = Stored;
    AbstractStorageDeclBits.Overridden = false;
  }
public:

  /// \brief Determine whether this storage is a static member, if it
  /// is a member.  Currently only variables can be static.
  inline bool isStatic() const; // defined in this header

  /// \brief Determine whether this variable is computed, which means it
  /// has no storage but does have a user-defined getter or setter.
  ///
  StorageKindTy getStorageKind() const {
    return (StorageKindTy) AbstractStorageDeclBits.StorageKind;
  }

  /// \brief Return true if this is a VarDecl that has storage associated with
  /// it.
  bool hasStorage() const {
    switch (getStorageKind()) {
    case Stored:
    case StoredWithTrivialAccessors:
    case StoredWithObservers:
      return true;
    case InheritedWithObservers:
    case Computed:
    case ComputedWithMutableAddress:
    case Addressed:
    case AddressedWithTrivialAccessors:
    case AddressedWithObservers:
      return false;
    }
    llvm_unreachable("bad storage kind");
  }

  /// \brief Return true if this object has a getter (and, if mutable,
  /// a setter and a materializeForSet).
  bool hasAccessorFunctions() const {
    switch (getStorageKind()) {
    case Addressed:
    case Stored:
      return false;
    case StoredWithTrivialAccessors:
    case StoredWithObservers:
    case InheritedWithObservers:
    case Computed:
    case ComputedWithMutableAddress:
    case AddressedWithTrivialAccessors:
    case AddressedWithObservers:
      return true;
    }
    llvm_unreachable("bad storage kind");
  }

  /// \brief Return true if this object has observing accessors.
  ///
  /// It's generally not appropriate to use this predicate directly in
  /// a condition; instead, you should be switching on the storage kind.
  bool hasObservers() const {
    switch (getStorageKind()) {
    case Stored:
    case StoredWithTrivialAccessors:
    case Computed:
    case ComputedWithMutableAddress:
    case Addressed:
    case AddressedWithTrivialAccessors:
      return false;
    case StoredWithObservers:
    case InheritedWithObservers:
    case AddressedWithObservers:
      return true;
    }
    llvm_unreachable("bad storage kind");
  }

  /// \brief Return true if this object has either an addressor or a
  /// mutable addressor.
  ///
  /// It's generally not appropriate to use this predicate directly in
  /// a condition; instead, you should be switching on the storage
  /// kind.  Only use this for diagnostic, AST exploration, or
  /// assertion purposes.
  bool hasAddressors() const {
    switch (getStorageKind()) {
    case Stored:
    case StoredWithTrivialAccessors:
    case StoredWithObservers:
    case InheritedWithObservers:
    case Computed:
      return false;
    case ComputedWithMutableAddress:
    case Addressed:
    case AddressedWithTrivialAccessors:
    case AddressedWithObservers:
      return true;
    }
    llvm_unreachable("bad storage kind");
  }
  
  /// \brief Return true if the 'getter' is 'mutating', i.e. that it requires an
  /// lvalue base to be accessed.
  bool isGetterMutating() const;
  
  /// \brief Return true if the 'setter' is 'nonmutating', i.e. that it can be
  /// called even on an immutable base value.
  bool isSetterNonMutating() const;

  FuncDecl *getAccessorFunction(AccessorKind accessor) const;

  /// \brief Turn this into a computed variable, providing a getter and setter.
  void makeComputed(SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set,
                    FuncDecl *MaterializeForSet, SourceLoc RBraceLoc);

  /// \brief Turn this into a computed object, providing a getter and a mutable
  /// addressor.
  void makeComputedWithMutableAddress(SourceLoc lbraceLoc,
                                      FuncDecl *getter, FuncDecl *setter,
                                      FuncDecl *materializeForSet,
                                      FuncDecl *mutableAddressor,
                                      SourceLoc rbraceLoc);

  /// \brief Add trivial accessors to this Stored or Addressed object.
  void addTrivialAccessors(FuncDecl *Get, FuncDecl *Set,
                           FuncDecl *MaterializeForSet);

  /// \brief Turn this into a stored-with-observers var, providing the
  /// didSet/willSet specifiers.
  void makeStoredWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet,
                               FuncDecl *DidSet, SourceLoc RBraceLoc);

  /// \brief Turn this into an inherited-with-observers var, providing
  /// the didSet/willSet specifiers.
  void makeInheritedWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet,
                                  FuncDecl *DidSet, SourceLoc RBraceLoc);

  /// \brief Turn this into an addressed var.
  void makeAddressed(SourceLoc LBraceLoc, FuncDecl *Addressor,
                     FuncDecl *MutableAddressor,
                     SourceLoc RBraceLoc);

  /// \brief Turn this into an addressed var with observing accessors.
  void makeAddressedWithObservers(SourceLoc LBraceLoc, FuncDecl *Addressor,
                                  FuncDecl *MutableAddressor,
                                  FuncDecl *WillSet, FuncDecl *DidSet,
                                  SourceLoc RBraceLoc);

  /// \brief Specify the synthesized get/set functions for a
  /// StoredWithObservers or AddressedWithObservers var.  This is used by Sema.
  void setObservingAccessors(FuncDecl *Get, FuncDecl *Set,
                             FuncDecl *MaterializeForSet);

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

  /// \brief Set a materializeForSet accessor for this declaration.
  ///
  /// This should only be used by Sema.
  void setMaterializeForSetFunc(FuncDecl *materializeForSet);

  /// \brief Specify the braces range without adding accessors.
  ///
  /// This is used to record the braces range if the accessors were rejected.
  void setInvalidBracesRange(SourceRange BracesRange);

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

  /// \brief Retrieve the getter used to access the value of this variable.
  FuncDecl *getGetter() const {
    if (auto info = GetSetInfo.getPointer())
      return info->Get;
    return nullptr;
  }
  
  /// \brief Retrieve the setter used to mutate the value of this variable.
  FuncDecl *getSetter() const {
    if (auto info = GetSetInfo.getPointer())
      return info->Set;
    return nullptr;
  }

  Accessibility getSetterAccessibility() const {
    assert(hasAccessibility());
    assert(GetSetInfo.getInt().hasValue());
    return GetSetInfo.getInt().getValue();
  }

  void setSetterAccessibility(Accessibility accessLevel) {
    assert(!GetSetInfo.getInt().hasValue());
    overwriteSetterAccessibility(accessLevel);
  }

  void overwriteSetterAccessibility(Accessibility accessLevel);

  /// \brief Retrieve the materializeForSet function, if this
  /// declaration has one.
  FuncDecl *getMaterializeForSetFunc() const {
    if (auto info = GetSetInfo.getPointer())
      return info->MaterializeForSet;
    return nullptr;
  }

  /// \brief Return the funcdecl for the 'address' accessor if it
  /// exists; this is only valid on a declaration with addressors.
  FuncDecl *getAddressor() const { return getAddressorInfo().Address; }

  /// \brief Return the funcdecl for the 'mutableAddress' accessors if
  /// it exists; this is only valid on a declaration with addressors.
  FuncDecl *getMutableAddressor() const {
    return getAddressorInfo().MutableAddress;
  }

  /// \brief Return the approproiate addressor for the given access kind.
  FuncDecl *getAddressorForAccess(AccessKind accessKind) const {
    if (accessKind == AccessKind::Read)
      return getAddressor();
    return getMutableAddressor();
  }
  
  /// \brief Return the funcdecl for the willSet specifier if it exists, this is
  /// only valid on a declaration with Observing storage.
  FuncDecl *getWillSetFunc() const { return getDidSetInfo().WillSet; }

  /// \brief Return the funcdecl for the didSet specifier if it exists, this is
  /// only valid on a declaration with Observing storage.
  FuncDecl *getDidSetFunc() const { return getDidSetInfo().DidSet; }

  /// Return true if this storage can (but doesn't have to) be accessed with
  /// Objective-C-compatible getters and setters.
  bool hasObjCGetterAndSetter() const;

  /// Return true if this storage *must* be accessed with Objective-C-compatible
  /// getters and setters.
  bool requiresObjCGetterAndSetter() const;

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

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

  AbstractStorageDecl *getOverriddenDecl() const {
    return OverriddenDecl;
  }
  void setOverriddenDecl(AbstractStorageDecl *over) {
    OverriddenDecl = over;
    over->setIsOverridden();
  }

  /// The declaration has been overridden in the module
  ///
  /// Resolved during type checking
  void setIsOverridden() {
    AbstractStorageDeclBits.Overridden = true;
  }

  /// Whether the declaration is later overridden in the module
  ///
  /// Overriddes are resolved during type checking; only query this field after
  /// the whole module has been checked
  bool isOverridden() const { return AbstractStorageDeclBits.Overridden; }

  /// 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.
  bool isSetterAccessibleFrom(const DeclContext *DC) const;

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

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

/// VarDecl - 'var' and 'let' declarations.
class VarDecl : public AbstractStorageDecl {
protected:
  llvm::PointerUnion3<PatternBindingDecl*, Pattern*, Stmt*> ParentPattern;

  VarDecl(DeclKind Kind, bool IsStatic, bool IsLet, SourceLoc NameLoc,
          Identifier Name, Type Ty, DeclContext *DC)
    : AbstractStorageDecl(Kind, DC, Name, NameLoc) 
  {
    VarDeclBits.IsUserAccessible = true;
    VarDeclBits.IsStatic = IsStatic;
    VarDeclBits.IsLet = IsLet;
    VarDeclBits.IsDebuggerVar = false;
    VarDeclBits.HasNonPatternBindingInit = false;
    setType(Ty);
  }

public:
  VarDecl(bool IsStatic, bool IsLet, SourceLoc NameLoc, Identifier Name,
          Type Ty, DeclContext *DC)
    : VarDecl(DeclKind::Var, IsStatic, IsLet, NameLoc, Name, Ty, DC) { }

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

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

  bool isUserAccessible() const {
    return VarDeclBits.IsUserAccessible;
  }

  /// \brief Retrieve the source range of the variable type.
  ///
  /// 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;

  /// \brief 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 {
    return ParentPattern.dyn_cast<PatternBindingDecl *>();
  }
  void setParentPatternBinding(PatternBindingDecl *PBD) {
    ParentPattern = PBD;
  }
  
  /// Return the Pattern involved in initializing this VarDecl.  Recall that the
  /// Pattern 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 or statement associated, it
  /// returns null.
  ///
  Pattern *getParentPattern() const;
  
  /// Return the statement that owns the pattern associated with this VarDecl,
  /// if one exists.
  Stmt *getParentPatternStmt() const {
    return ParentPattern.dyn_cast<Stmt*>();
  }
  void setParentPatternStmt(Stmt *S) {
    ParentPattern = S;
  }

  /// Return the initializer involved in this VarDecl.  However, 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;
  }
  
  VarDecl *getOverriddenDecl() const {
    return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
  }

  /// Determine whether this declaration is an anonymous closure parameter.
  bool isAnonClosureParam() const;

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

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

  /// Is this an immutable 'let' property?
  bool isLet() const { return VarDeclBits.IsLet; }
  void setLet(bool IsLet) { VarDeclBits.IsLet = IsLet; }

  /// 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 VarDeclBits.HasNonPatternBindingInit;
  }
  void setHasNonPatternBindingInit(bool V = true) {
    VarDeclBits.HasNonPatternBindingInit = V;
  }
  
  /// Is this a special debugger variable?
  bool isDebuggerVar() const { return VarDeclBits.IsDebuggerVar; }
  void setDebuggerVar(bool IsDebuggerVar) {
    VarDeclBits.IsDebuggerVar = IsDebuggerVar;
  }

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

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

public:
  ParamDecl(bool isLet, SourceLoc argumentNameLoc, 
            Identifier argumentName, SourceLoc parameterNameLoc,
            Identifier parameterName, Type ty, DeclContext *dc)
    : VarDecl(DeclKind::Param, /*IsState=*/false, isLet, parameterNameLoc, 
              parameterName, ty, dc),
      ArgumentName(argumentName), ArgumentNameLoc(argumentNameLoc) { }

  /// Retrieve the argument (API) name for this function parameter.
  Identifier getArgumentName() const { return ArgumentName; }

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

  SourceRange getSourceRange() const {
    if (ArgumentNameLoc.isValid() && getNameLoc().isInvalid())
      return ArgumentNameLoc;
    if (ArgumentNameLoc.isInvalid() && getNameLoc().isValid())
      return getNameLoc();
    return SourceRange(ArgumentNameLoc, getNameLoc());
  }

  Pattern *getParamParentPattern() const {
    return ParentPattern.dyn_cast<Pattern *>();
  }
  void setParamParentPattern(Pattern *Pat) {
    ParentPattern = Pat;
  }

  // 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 {
  /// Not an Objective-C subscripting kind.
  None,
  /// 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
};

/// \brief 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 AbstractStorageDecl {
  SourceLoc ArrowLoc;
  Pattern *Indices;
  TypeLoc ElementTy;

public:
  SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, Pattern *Indices,
                SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent)
    : AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
      ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
    setIndices(Indices);
  }
  
  SourceLoc getSubscriptLoc() const { return getNameLoc(); }
  SourceLoc getStartLoc() const { return getSubscriptLoc(); }
  SourceRange getSourceRange() const;

  /// \brief Retrieve the indices for this subscript operation.
  Pattern *getIndices() { return Indices; }
  const Pattern *getIndices() const { return Indices; }
  void setIndices(Pattern *p);

  /// Retrieve the type of the indices.
  Type getIndicesType() const;

  /// Retrieve the interface type of the indices.
  Type getIndicesInterfaceType() const;

  /// \brief Retrieve the type of the element referenced by a subscript
  /// operation.
  Type getElementType() const { return ElementTy.getType(); }
  TypeLoc &getElementTypeLoc() { return ElementTy; }
  const TypeLoc &getElementTypeLoc() const { return ElementTy; }

  /// \brief Returns whether the result of the subscript operation can be set.
  bool isSettable() const;

  /// Determine the kind of Objective-C subscripting this declaration
  /// implies.
  ObjCSubscriptKind getObjCSubscriptKind(LazyResolver *resolver) const;

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

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

/// \brief Base class for function-like declarations.
class AbstractFunctionDecl : public ValueDecl, public DeclContext {
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

    // This enum currently needs to fit in a 3-bit bitfield.
  };

  BodyKind getBodyKind() const {
    return BodyKind(AbstractFunctionDeclBits.BodyKind);
  }

  using BodySynthesizer = void (*)(AbstractFunctionDecl *);

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() == 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;
  };

  GenericParamList *GenericParams;

  CaptureInfo Captures;

  AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                       SourceLoc NameLoc, unsigned NumParamPatterns,
                       GenericParamList *GenericParams)
      : ValueDecl(Kind, Parent, Name, NameLoc),
        DeclContext(DeclContextKind::AbstractFunctionDecl, Parent),
        Body(nullptr), GenericParams(nullptr) {
    setBodyKind(BodyKind::None);
    setGenericParams(GenericParams);
    AbstractFunctionDeclBits.NumParamPatterns = NumParamPatterns;
    AbstractFunctionDeclBits.Overridden = false;

    // Verify no bitfield truncation.
    assert(AbstractFunctionDeclBits.NumParamPatterns == NumParamPatterns);
  }

  MutableArrayRef<Pattern *> getBodyParamBuffer();

  void setBodyKind(BodyKind K) {
    AbstractFunctionDeclBits.BodyKind = unsigned(K);
  }

  void setGenericParams(GenericParamList *GenericParams);
public:
  // FIXME: Hack that provides names with keyword arguments for accessors.
  DeclName getEffectiveFullName() const;

  /// \brief If this is a method in a type extension for some type,
  /// return that type, otherwise return Type().
  Type getExtensionType() 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;
  }

  /// 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 {
    if (canSynthesize && getBodyKind() == BodyKind::Synthesize) {
      const_cast<AbstractFunctionDecl *>(this)->setBodyKind(BodyKind::None);
      (*Synthesizer)(const_cast<AbstractFunctionDecl *>(this));
    }
    if (getBodyKind() == BodyKind::Parsed ||
        getBodyKind() == BodyKind::TypeChecked) {
      return Body;
    }
    return nullptr;
  }
  void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
    assert(getBodyKind() != BodyKind::Skipped &&
           "can not set a body if it was skipped");

    Body = S;
    setBodyKind(NewBodyKind);
  }

  /// \brief Note that the body was skipped for this function.  Function body
  /// can not be attached after this call.
  void setBodySkipped(SourceRange bodyRange) {
    assert(getBodyKind() == BodyKind::None);
    BodyRange = bodyRange;
    setBodyKind(BodyKind::Skipped);
  }

  /// \brief Note that parsing for the body was delayed.
  void setBodyDelayed(SourceRange bodyRange) {
    assert(getBodyKind() == BodyKind::None);
    BodyRange = bodyRange;
    setBodyKind(BodyKind::Unparsed);
  }

  /// Note that parsing for the body was delayed.
  void setBodySynthesizer(BodySynthesizer synthesizer) {
    assert(getBodyKind() == BodyKind::None);
    Synthesizer = synthesizer;
    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);
  }

  /// If a body has been loaded, flag that it's been type-checked.
  /// This is kindof a hacky operation, but it avoids some unnecessary
  /// duplication of work.
  void setBodyTypeCheckedIfPresent() {
    if (getBodyKind() == BodyKind::Parsed)
      setBodyKind(BodyKind::TypeChecked);
  }

  bool isBodyTypeChecked() const {
    return getBodyKind() == BodyKind::TypeChecked;
  }

  bool isMemberwiseInitializer() const {
    return getBodyKind() == BodyKind::MemberwiseInitializer;
  }

  /// Retrieve the source range of the function body.
  SourceRange getBodySourceRange() const;

  /// Retrieve the source range of the function declaration name + patterns.
  SourceRange getSignatureSourceRange() const;

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

  /// Retrieve the Objective-C selector that names this method.
  ObjCSelector getObjCSelector(LazyResolver *resolver = nullptr) const;

  /// Determine whether the given method would produce an Objective-C
  /// instance method.
  bool isObjCInstanceMethod() const;

  /// Determine the default argument kind and type for the given argument index
  /// in this declaration, which must be a function or constructor.
  ///
  /// \param Index The index of the argument for which we are querying the
  /// default argument.
  ///
  /// \returns the default argument kind and, if there is a default argument,
  /// the type of the corresponding parameter.
  std::pair<DefaultArgumentKind, Type> getDefaultArg(unsigned Index) const;

  /// Determine whether the name of the ith argument is an API name by default.
  bool argumentNameIsAPIByDefault(unsigned i) const;

  unsigned getNumParamPatterns() const {
    return AbstractFunctionDeclBits.NumParamPatterns;
  }

  /// \brief Returns the "natural" number of argument clauses taken by this
  /// function.  This value is always at least one, and it may be more if the
  /// function is implicitly or explicitly curried.
  ///
  /// For example, this function:
  /// \code
  ///   func negate(x : Int) -> Int { return -x }
  /// \endcode
  /// has a natural argument count of 1 if it is freestanding.  If it is
  /// a method, it has a natural argument count of 2, as does this
  /// curried function:
  /// \code
  ///   func add(x : Int)(y : Int) -> Int { return x + y }
  /// \endcode
  ///
  /// This value never exceeds the number of chained function types
  /// in the function's type, but it can be less for functions which
  /// return a value of function type:
  /// \code
  ///   func const(x : Int) -> () -> Int { return { x } } // NAC==1
  /// \endcode
  unsigned getNaturalArgumentCount() const {
    return getNumParamPatterns();
  }

  /// \brief Returns the parameter pattern(s) for the function definition that
  /// determine the parameter names bound in the function body.
  ///
  /// The number of "top-level" elements in this pattern will match the number
  /// of argument names in the compound name of the function or constructor.
  MutableArrayRef<Pattern *> getBodyParamPatterns() {
    return getBodyParamBuffer();
  }
  ArrayRef<const Pattern *> getBodyParamPatterns() const {
    auto Patterns =
        const_cast<AbstractFunctionDecl *>(this)->getBodyParamBuffer();
    return ArrayRef<const Pattern *>(Patterns.data(), Patterns.size());
  }

  /// \brief If this is a method in a type or extension thereof, compute
  /// and return the type to be used for the 'self' argument of the type, or an
  /// empty Type() if no 'self' argument should exist.  This can
  /// only be used after name binding has resolved types.
  ///
  /// \param outerGenericParams If non-NULL, and this function is an instance
  /// of a generic type, will be set to the generic parameter list of that
  /// generic type.
  Type computeSelfType(GenericParamList **outerGenericParams = nullptr);

  /// \brief If this is a method in a type or extension thereof, compute
  /// and return the type to be used for the 'self' argument of the interface
  /// type, or an empty Type() if no 'self' argument should exist.  This can
  /// only be used after name binding has resolved types.
  ///
  /// \param isInitializingCtor Specifies whether we're computing the 'self'
  /// type of an initializing constructor, which accepts an instance 'self'
  /// rather than a metatype 'self'.
  Type computeInterfaceSelfType(bool isInitializingCtor);

  /// \brief This method returns the implicit 'self' decl.
  ///
  /// Note that some functions don't have an implicit 'self' decl, for example,
  /// free functions.  In this case nullptr is returned.
  VarDecl *getImplicitSelfDecl() const;

  /// \brief Retrieve the set of parameters to a generic function, or null if
  /// this function is not generic.
  GenericParamList *getGenericParams() const { return GenericParams; }

  /// \brief Determine whether this is a generic function, which can only be
  /// used when each of the archetypes is bound to a particular concrete type.
  bool isGeneric() const { return GenericParams != nullptr; }

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

  /// Whether the declaration is later overridden in the module
  ///
  /// Overriddes are resolved during type checking; only query this field after
  /// the whole module has been checked
  bool isOverridden() const { return AbstractFunctionDeclBits.Overridden; }

  /// The declaration has been overridden in the module
  ///
  /// Resolved during type checking
  void setIsOverridden() { AbstractFunctionDeclBits.Overridden = true; }

  /// Whether the function body is 'throws'.
  bool isBodyThrowing() const;

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

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

  static bool classof(const DeclContext *DC) {
    return DC->getContextKind() == DeclContextKind::AbstractFunctionDecl;
  }
  
  /// True if the declaration is forced to be statically dispatched.
  bool hasForcedStaticDispatch() const;
  
  using DeclContext::operator new;
  using Decl::getASTContext;
};

class OperatorDecl;


/// FuncDecl - 'func' declaration.
class FuncDecl : public AbstractFunctionDecl {
  friend class AbstractFunctionDecl;

  SourceLoc StaticLoc;  // Location of the 'static' token or invalid.
  SourceLoc FuncLoc;    // Location of the 'func' token.
  SourceLoc ThrowsLoc;  // Location of the 'throws' token.
  SourceLoc AccessorKeywordLoc; // Location of the accessor keyword token, e,g. 'set'.

  TypeLoc FnRetType;

  /// The result type as seen from the body of the function.
  ///
  /// \sa getBodyResultType()
  Type BodyResultType;
  
  /// If this declaration is part of an overload set, determine if we've
  /// searched for a common overload amongst all overloads, or if we've found
  /// one.
  unsigned HaveSearchedForCommonOverloadReturnType : 1;
  unsigned HaveFoundCommonOverloadReturnType : 1;

  /// \brief If this FuncDecl is an accessor for a property, this indicates
  /// which property and what kind of accessor.
  llvm::PointerIntPair<AbstractStorageDecl*, 3, AccessorKind> AccessorDecl;
  llvm::PointerUnion<FuncDecl *, NominalTypeDecl*> OverriddenOrDerivedForDecl;
  llvm::PointerIntPair<OperatorDecl *, 3, AddressorKind> OperatorAndAddressorKind;

  FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
           SourceLoc FuncLoc, DeclName Name,
           SourceLoc NameLoc, SourceLoc ThrowsLoc,
           SourceLoc AccessorKeywordLoc,
           unsigned NumParamPatterns,
           GenericParamList *GenericParams, Type Ty, DeclContext *Parent)
    : AbstractFunctionDecl(DeclKind::Func, Parent, Name, NameLoc,
                           NumParamPatterns, GenericParams),
      StaticLoc(StaticLoc), FuncLoc(FuncLoc), ThrowsLoc(ThrowsLoc),
      AccessorKeywordLoc(AccessorKeywordLoc),
      OverriddenOrDerivedForDecl(),
      OperatorAndAddressorKind(nullptr, AddressorKind::NotAddressor) {
    FuncDeclBits.IsStatic = StaticLoc.isValid() || getName().isOperator();
    FuncDeclBits.StaticSpelling = static_cast<unsigned>(StaticSpelling);
    assert(NumParamPatterns > 0 && "Must have at least an empty tuple arg");
    setType(Ty);
    FuncDeclBits.Mutating = false;
    FuncDeclBits.HasDynamicSelf = false;
    FuncDeclBits.ForcedStaticDispatch = false;
        
    HaveSearchedForCommonOverloadReturnType = false;
    HaveFoundCommonOverloadReturnType = false;
  }

  static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
                              StaticSpellingKind StaticSpelling,
                              SourceLoc FuncLoc, DeclName Name,
                              SourceLoc NameLoc, SourceLoc ThrowsLoc,
                              SourceLoc AccessorKeywordLoc,
                              GenericParamList *GenericParams, Type Ty,
                              unsigned NumParamPatterns,
                              DeclContext *Parent,
                              ClangNode ClangN);

public:
  /// Factory function only for use by deserialization.
  static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc,
                                      StaticSpellingKind StaticSpelling,
                                      SourceLoc FuncLoc, DeclName Name,
                                      SourceLoc NameLoc, SourceLoc ThrowsLoc,
                                      SourceLoc AccessorKeywordLoc,
                                      GenericParamList *GenericParams, Type Ty,
                                      unsigned NumParamPatterns,
                                      DeclContext *Parent);

  static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
                          StaticSpellingKind StaticSpelling,
                          SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc,
                          SourceLoc ThrowsLoc, SourceLoc AccessorKeywordLoc,
                          GenericParamList *GenericParams,
                          Type Ty, ArrayRef<Pattern *> BodyParams,
                          TypeLoc FnRetType, DeclContext *Parent,
                          ClangNode ClangN = ClangNode());

  bool isStatic() const {
    return FuncDeclBits.IsStatic;
  }
  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(FuncDeclBits.StaticSpelling);
  }
  /// \returns the way 'static'/'class' should be spelled for this declaration.
  StaticSpellingKind getCorrectStaticSpelling() const;
  void setStatic(bool IsStatic = true) {
    FuncDeclBits.IsStatic = IsStatic;
  }
  bool isMutating() const {
    return FuncDeclBits.Mutating;
  }
  void setMutating(bool Mutating = true) {
    FuncDeclBits.Mutating = Mutating;
  }
  
  bool getHaveSearchedForCommonOverloadReturnType() {
    return HaveSearchedForCommonOverloadReturnType;
  }
  void setHaveSearchedForCommonOverloadReturnType(bool b = true) {
    HaveSearchedForCommonOverloadReturnType = b;
  }
  bool getHaveFoundCommonOverloadReturnType() {
    return HaveFoundCommonOverloadReturnType;
  }
  void setHaveFoundCommonOverloadReturnType(bool b = true) {
    HaveFoundCommonOverloadReturnType = b;
  }

  /// \returns true if this is non-mutating due to applying a 'mutating'
  /// attribute. For example a "mutating set" accessor.
  bool isExplicitNonMutating() const;

  void setDeserializedSignature(ArrayRef<Pattern *> BodyParams,
                                TypeLoc FnRetType);

  SourceLoc getStaticLoc() const { return StaticLoc; }
  SourceLoc getFuncLoc() const { return FuncLoc; }
  SourceLoc getThrowsLoc() const { return ThrowsLoc; }
  SourceLoc getAccessorKeywordLoc() const {return AccessorKeywordLoc; }

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

  TypeLoc &getBodyResultTypeLoc() { return FnRetType; }
  const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; }

  /// Retrieve the result type of this function.
  ///
  /// \sa getBodyResultType
  Type getResultType() const;

  /// Retrieve the result type of this function for use within the function
  /// definition.
  ///
  /// FIXME: The statement below is a wish, not reality.
  /// The "body" result type will only differ from the result type within the
  /// interface to the function for a polymorphic function, where the interface
  /// may contain generic parameters while the definition will contain
  /// the corresponding archetypes.
  Type getBodyResultType() const { return BodyResultType; }

  /// Set the result type as viewed from the function body.
  ///
  /// \sa getBodyResultType
  void setBodyResultType(Type bodyResultType) {
    assert(BodyResultType.isNull() && "Already set body result type");
    BodyResultType = bodyResultType;
  }

  /// Revert to an empty type.
  void revertType() {
    BodyResultType = Type();
    overwriteType(Type());
  }

  /// isUnaryOperator - Determine whether this is a unary operator
  /// implementation, in other words, the name of the function is an operator,
  /// and the argument list consists syntactically of a single-element tuple
  /// pattern. This check is syntactic rather than type-based in order to allow
  /// for the definition of unary operators on tuples, as in:
  ///   func [prefix] + (_:(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, in other words, the name of the function is an operator,
  /// and the argument list consists syntactically of a two-element tuple
  /// pattern. This check is syntactic rather than type-based in order to
  /// distinguish a binary operator from a unary operator on tuples, as in:
  ///   func [prefix] + (_:(a:Int, b:Int)) // unary operator +(1,2)
  ///   func [infix]  + (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;
  
  /// makeAccessor - Note that this function is an accessor for the given
  /// VarDecl or SubscriptDecl.
  void makeAccessor(AbstractStorageDecl *D, AccessorKind Kind) {
    assert(Kind != AccessorKind::NotAccessor && "Must specify an accessor kind");
    AccessorDecl.setPointerAndInt(D, Kind);
  }

  /// Set the addressor kind of this address or mutableAddress declaration.
  void setAddressorKind(AddressorKind kind) {
    assert(kind != AddressorKind::NotAddressor);
    OperatorAndAddressorKind.setInt(kind);
  }

  AbstractStorageDecl *getAccessorStorageDecl() const {
    return AccessorDecl.getPointer();
  }

  AccessorKind getAccessorKind() const {
    if (AccessorDecl.getPointer() == nullptr)
      return AccessorKind::NotAccessor;
    return AccessorDecl.getInt();
  }

  AddressorKind getAddressorKind() const {
    return OperatorAndAddressorKind.getInt();
  }

  bool isGetter() const { return getAccessorKind() == AccessorKind::IsGetter; }
  bool isSetter() const { return getAccessorKind() == AccessorKind::IsSetter; }

  /// isGetterOrSetter - Determine whether this is a getter or a setter vs.
  /// a normal function.
  bool isGetterOrSetter() const { return isGetter() || isSetter(); }
  bool isObservingAccessor() const {
    return getAccessorKind() == AccessorKind::IsDidSet ||
           getAccessorKind() == AccessorKind::IsWillSet;
  }
  bool isAccessor() const {
    return getAccessorKind() != AccessorKind::NotAccessor;
  }

  /// Determine whether this function has a dynamic \c Self return
  /// type.
  bool hasDynamicSelf() const { return FuncDeclBits.HasDynamicSelf; }

  /// Set whether this function has a dynamic \c Self return or not.
  void setDynamicSelf(bool hasDynamicSelf) { 
    FuncDeclBits.HasDynamicSelf = hasDynamicSelf;
  }
  
  /// Retrieve the dynamic \c Self type for this method, or a null type if
  /// this method does not have a dynamic \c Self return type.
  DynamicSelfType *getDynamicSelf() const;

  /// Retrieve the dynamic \c Self interface type for this method, or
  /// a null type if this method does not have a dynamic \c Self
  /// return type.
  DynamicSelfType *getDynamicSelfInterface() const;

  /// Determine whether this method has an archetype \c Self return
  /// type. This is when a method defined in a protocol extension
  /// returns Self. In this case, the type is not quite as constrained
  /// as a dynamic Self, because it is bound to the conforming type,
  /// not the dynamic type of the value.
  bool hasArchetypeSelf() const;

  void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
    return getCaptureInfo().getLocalCaptures(Result);
  }
  
  /// Get the supertype method this method overrides, if any.
  FuncDecl *getOverriddenDecl() const {
    return OverriddenOrDerivedForDecl.dyn_cast<FuncDecl *>();
  }
  void setOverriddenDecl(FuncDecl *over) {
    // A function cannot be an override if it is also a derived global decl
    // (since derived decls are at global scope).
    assert((!OverriddenOrDerivedForDecl
            || !OverriddenOrDerivedForDecl.is<FuncDecl*>())
           && "function cannot be both override and derived global");
    OverriddenOrDerivedForDecl = over;
    over->setIsOverridden();
  }
  
  /// Get the type this function was implicitly generated on the behalf of for
  /// a derived protocol conformance, if any.
  NominalTypeDecl *getDerivedForTypeDecl() const {
    return OverriddenOrDerivedForDecl.dyn_cast<NominalTypeDecl *>();
  }
  void setDerivedForTypeDecl(NominalTypeDecl *ntd) {
    // A function cannot be an override if it is also a derived global decl
    // (since derived decls are at global scope).
    assert((!OverriddenOrDerivedForDecl
            || !OverriddenOrDerivedForDecl.is<NominalTypeDecl *>())
           && "function cannot be both override and derived global");
    OverriddenOrDerivedForDecl = ntd;
  }
  
  OperatorDecl *getOperatorDecl() const {
    return OperatorAndAddressorKind.getPointer();
  }
  void setOperatorDecl(OperatorDecl *o) {
    assert(isOperator() && "can't set an OperatorDecl for a non-operator");
    OperatorAndAddressorKind.setPointer(o);
  }
  
  /// Returns true if the function is forced to be statically dispatched.
  bool hasForcedStaticDispatch() const {
    return FuncDeclBits.ForcedStaticDispatch;
  }
  void setForcedStaticDispatch(bool flag) {
    FuncDeclBits.ForcedStaticDispatch = flag;
  }

  /// Returns true if a function declaration overrides a given
  /// method from its direct or indirect superclass.
  bool isOverridingDecl(const FuncDecl *method) const;
  
  static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func; }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    return false;
  }

  /// True if the function is a defer body.
  bool isDeferBody() const;
};
  
/// \brief This represents a 'case' declaration in an 'enum', which may declare
/// one or more individual comma-separated EnumElementDecls.
class EnumCaseDecl : public Decl {
  SourceLoc CaseLoc;
  
  /// The number of tail-allocated element pointers.
  unsigned NumElements;
  
  EnumCaseDecl(SourceLoc CaseLoc,
               ArrayRef<EnumElementDecl *> Elements,
               DeclContext *DC)
    : Decl(DeclKind::EnumCase, DC),
      CaseLoc(CaseLoc), NumElements(Elements.size())
  {
    memcpy(this + 1, Elements.begin(), NumElements * sizeof(EnumElementDecl*));
  }
  
  EnumElementDecl * const *getElementsBuf() const {
    return reinterpret_cast<EnumElementDecl * const*>(this + 1);
  }
  
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 {getElementsBuf(), NumElements};
  }
  
  SourceLoc getLoc() const {
    return CaseLoc;
  }
  
  SourceRange getSourceRange() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::EnumCase;
  }
};

/// \brief 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 ValueDecl {
  /// 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.
  TypeLoc ArgumentType;
  
  SourceLoc EqualsLoc;
  
  /// The raw value literal for the enum element, or null.
  LiteralExpr *RawValueExpr;
  /// The type-checked raw value expression.
  Expr *TypeCheckedRawValueExpr = nullptr;
  
public:
  EnumElementDecl(SourceLoc IdentifierLoc, Identifier Name,
                  TypeLoc ArgumentType,
                  SourceLoc EqualsLoc,
                  LiteralExpr *RawValueExpr,
                  DeclContext *DC)
  : ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
    ArgumentType(ArgumentType),
    EqualsLoc(EqualsLoc),
    RawValueExpr(RawValueExpr)
  {
    EnumElementDeclBits.Recursiveness =
        static_cast<unsigned>(ElementRecursiveness::NotRecursive);
  }

  void computeType();

  bool hasArgumentType() const { return !ArgumentType.getType().isNull(); }
  Type getArgumentType() const { return ArgumentType.getType(); }
  Type getArgumentInterfaceType() const;

  TypeLoc &getArgumentTypeLoc() { return ArgumentType; }
  const TypeLoc &getArgumentTypeLoc() const { return ArgumentType; }

  bool hasRawValueExpr() const { return RawValueExpr; }
  LiteralExpr *getRawValueExpr() const { return RawValueExpr; }
  void setRawValueExpr(LiteralExpr *e) { RawValueExpr = e; }
  
  Expr *getTypeCheckedRawValueExpr() const {
    return TypeCheckedRawValueExpr;
  }
  void setTypeCheckedRawValueExpr(Expr *e) {
    TypeCheckedRawValueExpr = 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;
  
  ElementRecursiveness getRecursiveness() const {
    return
      static_cast<ElementRecursiveness>(EnumElementDeclBits.Recursiveness);
  }
  
  void setRecursiveness(ElementRecursiveness recursiveness) {
    EnumElementDeclBits.Recursiveness = static_cast<unsigned>(recursiveness);
  }

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

  /// True if the case is marked 'indirect'.
  bool isIndirect() const {
    return getAttrs().hasAttribute<IndirectAttr>();
  }
};
  
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).
  ///
  /// A convenience initializer is written with a return type of "Self" in
  /// source code.
  ///
  /// 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 {
  friend class AbstractFunctionDecl;

  /// The failability of this initializer, which is an OptionalTypeKind.
  unsigned Failability : 2;

  /// The location of the '!' or '?' for a failable initializer.
  SourceLoc FailabilityLoc;

  // Location of the 'throws' token.
  SourceLoc ThrowsLoc;

  Pattern *BodyParams[2];

  /// The type of the initializing constructor.
  Type InitializerType;

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

  /// The constructor this overrides, which only makes sense when
  /// both the overriding and the overridden constructors are abstract.
  ConstructorDecl *OverriddenDecl = nullptr;

public:
  ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc, 
                  OptionalTypeKind Failability, SourceLoc FailabilityLoc,
                  Pattern *SelfBodyParam, Pattern *BodyParams,
                  GenericParamList *GenericParams, 
                  SourceLoc throwsLoc, DeclContext *Parent);

  void setBodyParams(Pattern *selfPattern, Pattern *bodyParams);

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

  /// getArgumentType - get the type of the argument tuple
  Type getArgumentType() const;

  /// \brief Get the type of the constructed object.
  Type getResultType() const;

  /// Get the type of the initializing constructor.
  Type getInitializerType() const { return InitializerType; }
  void setInitializerType(Type t) { InitializerType = t; }

  /// Get the interface type of the initializing constructor.
  Type getInitializerInterfaceType();
  void setInitializerInterfaceType(Type t);

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

  /// 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 {
    return static_cast<CtorInitializerKind>(ConstructorDeclBits.InitKind);
  }

  /// Set whether this is a convenience initializer.
  void setInitKind(CtorInitializerKind kind) {
    ConstructorDeclBits.InitKind = static_cast<unsigned>(kind);
  }

  /// 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 the failability of the initializer.
  OptionalTypeKind getFailability() const {
    return static_cast<OptionalTypeKind>(Failability);
  }

  /// Retrieve the location of the '!' or '?' in a failable initializer.
  SourceLoc getFailabilityLoc() const { return FailabilityLoc; }

  /// Retrieve the location of the 'throws' keyword, if present.
  SourceLoc getThrowsLoc() const { return ThrowsLoc; }

  /// Whether the implementation of this method is a stub that traps at runtime.
  bool hasStubImplementation() const {
    return ConstructorDeclBits.HasStubImplementation;
  }

  /// Set whether the implementation of this method is a stub that
  /// traps at runtime.
  void setStubImplementation(bool stub) {
    ConstructorDeclBits.HasStubImplementation = stub;
  }

  ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; }
  void setOverriddenDecl(ConstructorDecl *over) {
    OverriddenDecl = over;
    over->setIsOverridden();
  }

  /// 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 fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    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 {
  friend class AbstractFunctionDecl;
  Pattern *SelfPattern;
public:
  DestructorDecl(Identifier NameHack, SourceLoc DestructorLoc,
                 Pattern *SelfPattern, DeclContext *Parent);
  
  void setSelfPattern(Pattern *selfPattern);

  SourceLoc getDestructorLoc() const { return getNameLoc(); }
  SourceLoc getStartLoc() const { return getDestructorLoc(); }
  SourceRange getSourceRange() 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 fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    return false;
  }
};

/// Abstract base class of operator declarations.
class OperatorDecl : public Decl {
  SourceLoc OperatorLoc, NameLoc, LBraceLoc, RBraceLoc;
  
  Identifier name;

public:
  OperatorDecl(DeclKind kind,
               DeclContext *DC,
               SourceLoc OperatorLoc,
               Identifier Name,
               SourceLoc NameLoc,
               SourceLoc LBraceLoc,
               SourceLoc RBraceLoc)
    : Decl(kind, DC),
      OperatorLoc(OperatorLoc), NameLoc(NameLoc),
      LBraceLoc(LBraceLoc), RBraceLoc(RBraceLoc),
      name(Name) {}
  
  SourceLoc getLoc() const { return NameLoc; }
  SourceRange getSourceRange() const { return {OperatorLoc, RBraceLoc}; }

  SourceLoc getOperatorLoc() const { return OperatorLoc; }
  SourceLoc getLBraceLoc() const { return LBraceLoc; }
  SourceLoc getRBraceLoc() const { return RBraceLoc; }
  Identifier getName() const { return name; }
  
  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_OperatorDecl
      && D->getKind() <= DeclKind::Last_OperatorDecl;
  }
};

/// Declares the behavior of an infix operator. For example:
///
/// \code
/// infix operator /+/ {
///   associativity left
///   precedence 123
/// }
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
  SourceLoc AssociativityLoc, AssociativityValueLoc,
    PrecedenceLoc, PrecedenceValueLoc,
    AssignmentLoc;

public:
  InfixOperatorDecl(DeclContext *DC,
                    SourceLoc OperatorLoc,
                    Identifier Name,
                    SourceLoc NameLoc,
                    SourceLoc LBraceLoc,
                    bool IsAssocImplicit,
                    SourceLoc AssociativityLoc,
                    SourceLoc AssociativityValueLoc,
                    bool IsPrecedenceImplicit,
                    SourceLoc PrecedenceLoc,
                    SourceLoc PrecedenceValueLoc,
                    bool IsAssignmentImplicit,
                    SourceLoc AssignmentLoc,
                    SourceLoc RBraceLoc,
                    InfixData InfixData)
    : OperatorDecl(DeclKind::InfixOperator, DC,
                   OperatorLoc,
                   Name,
                   NameLoc,
                   LBraceLoc,
                   RBraceLoc),
      AssociativityLoc(AssociativityLoc),
      AssociativityValueLoc(AssociativityValueLoc),
      PrecedenceLoc(PrecedenceLoc),
      PrecedenceValueLoc(PrecedenceValueLoc),
      AssignmentLoc(AssignmentLoc) {
    if (!InfixData.isValid()) {
      setInvalid();
    } else {
      assert((AssociativityLoc.isInvalid() || !IsAssocImplicit) &&
             "Associativity cannot be implicit if it came from user source");
      assert((PrecedenceLoc.isInvalid() || !IsPrecedenceImplicit) &&
             "Precedence cannot be implicit if it came from user source");
      InfixOperatorDeclBits.Precedence = InfixData.getPrecedence();
      InfixOperatorDeclBits.Associativity =
        static_cast<unsigned>(InfixData.getAssociativity());
      InfixOperatorDeclBits.Assignment =
         unsigned(InfixData.isAssignment());
      InfixOperatorDeclBits.IsPrecedenceImplicit = IsPrecedenceImplicit;
      InfixOperatorDeclBits.IsAssocImplicit = IsAssocImplicit;
      InfixOperatorDeclBits.IsAssignmentImplicit = IsAssignmentImplicit;
    }
  }
  
  SourceLoc getAssociativityLoc() const { return AssociativityLoc; }
  SourceLoc getAssociativityValueLoc() const { return AssociativityValueLoc; }
  SourceLoc getPrecedenceLoc() const { return PrecedenceLoc; }
  SourceLoc getPrecedenceValueLoc() const { return PrecedenceValueLoc; }
  SourceLoc getAssignmentLoc() const { return AssignmentLoc; }

  unsigned getPrecedence() const {
    return InfixOperatorDeclBits.Precedence;
  }

  Associativity getAssociativity() const {
    return Associativity(InfixOperatorDeclBits.Associativity);
  }
  
  bool isAssignment() const {
    return InfixOperatorDeclBits.Assignment;
  }

  InfixData getInfixData() const {
    if (isInvalid())
      return InfixData();
    return InfixData(getPrecedence(), getAssociativity(), isAssignment());
  }

  bool isAssociativityImplicit() const {
    return InfixOperatorDeclBits.IsAssocImplicit;
  }
  bool isPrecedenceImplicit() const {
    return InfixOperatorDeclBits.IsPrecedenceImplicit;
  }
  bool isAssignmentImplicit() const {
    return InfixOperatorDeclBits.IsAssignmentImplicit;
  }

  void collectOperatorKeywordRanges(SmallVectorImpl<CharSourceRange> &Ranges);

  /// True if this decl's attributes conflict with those declared by another
  /// operator.
  bool conflictsWith(InfixOperatorDecl *other) {
    return getInfixData() != other->getInfixData();
  }
  
  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, SourceLoc LBraceLoc,
                     SourceLoc RBraceLoc)
    : OperatorDecl(DeclKind::PrefixOperator, DC,
                   OperatorLoc, Name, NameLoc, LBraceLoc, RBraceLoc) {}

  /// 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, SourceLoc LBraceLoc,
                     SourceLoc RBraceLoc)
    : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name,
                   NameLoc, LBraceLoc, RBraceLoc) {}
  
  /// 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;
  }
};

inline bool ValueDecl::isSettable(const DeclContext *UseDC,
                                  const DeclRefExpr *base) const {
  if (auto vd = dyn_cast<VarDecl>(this)) {
    return vd->isSettable(UseDC, base);
  } else if (auto sd = dyn_cast<SubscriptDecl>(this)) {
    return sd->isSettable();
  } else
    return false;
}

namespace impl {
  bool isTestingEnabled(const ValueDecl *VD);
}

inline Accessibility ValueDecl::getEffectiveAccess() const {
  switch (getFormalAccess()) {
  case Accessibility::Public:
    return Accessibility::Public;
  case Accessibility::Internal:
    if (impl::isTestingEnabled(this))
      return Accessibility::Public;
    return Accessibility::Internal;
  case Accessibility::Private:
    return Accessibility::Private;
  }
}

inline Optional<VarDecl *>
NominalTypeDecl::ToStoredProperty::operator()(Decl *decl) const {
  if (auto var = dyn_cast<VarDecl>(decl)) {
    if (!var->isStatic() && var->hasStorage())
      return var;
  }

  return None;
}

inline void
AbstractStorageDecl::overwriteSetterAccessibility(Accessibility accessLevel) {
  GetSetInfo.setInt(accessLevel);
  if (auto setter = getSetter())
    setter->overwriteAccessibility(accessLevel);
  if (auto materializeForSet = getMaterializeForSetFunc())
    materializeForSet->overwriteAccessibility(accessLevel);
}

inline bool AbstractStorageDecl::isStatic() const {
  if (auto var = dyn_cast<VarDecl>(this)) {
    return var->isStatic();
  }

  // Currently, subscripts are never static.
  return false;
}

inline MutableArrayRef<Pattern *> AbstractFunctionDecl::getBodyParamBuffer() {
  unsigned NumPatterns = AbstractFunctionDeclBits.NumParamPatterns;
  Pattern **Ptr;
  switch (getKind()) {
  default: llvm_unreachable("Unknown AbstractFunctionDecl!");
  case DeclKind::Constructor:
    Ptr = cast<ConstructorDecl>(this)->BodyParams;
    break;

  case DeclKind::Destructor:
    Ptr = &cast<DestructorDecl>(this)->SelfPattern;
    break;

  case DeclKind::Func:
    // Body patterns are tail allocated.
    Ptr = reinterpret_cast<Pattern **>(cast<FuncDecl>(this) + 1);
    break;
  }
  return MutableArrayRef<Pattern *>(Ptr, NumPatterns);
}

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 ArrayRef<Requirement> ExtensionDecl::getGenericRequirements() const {
  if (!GenericSig)
    return { };

  return GenericSig->getRequirements();
}

} // end namespace swift

#endif
