text: //===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines the Decl class and subclasses.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_DECL_H
  #define SWIFT_DECL_H
  
  #include "swift/AST/AccessScope.h"
  #include "swift/AST/Attr.h"
  #include "swift/AST/CaptureInfo.h"
  #include "swift/AST/ClangNode.h"
  #include "swift/AST/ConcreteDeclRef.h"
  #include "swift/AST/DefaultArgumentKind.h"
  #include "swift/AST/DiagnosticConsumer.h"
  #include "swift/AST/GenericParamKey.h"
  #include "swift/AST/IfConfigClause.h"
  #include "swift/AST/LayoutConstraint.h"
  #include "swift/AST/TypeAlignments.h"
  #include "swift/AST/TypeWalker.h"
  #include "swift/AST/Witness.h"
  #include "swift/Basic/Compiler.h"
  #include "swift/Basic/InlineBitfield.h"
  #include "swift/Basic/OptionalEnum.h"
  #include "swift/Basic/Range.h"
  #include "llvm/ADT/DenseMap.h"
  #include "llvm/ADT/DenseSet.h"
  #include "llvm/Support/TrailingObjects.h"
  
  namespace swift {
    enum class AccessSemantics : unsigned char;
    class AccessorDecl;
    class ApplyExpr;
    class GenericEnvironment;
    class ArchetypeType;
    class ASTContext;
    struct ASTNode;
    class ASTPrinter;
    class ASTWalker;
    class ConstructorDecl;
    class DestructorDecl;
    class DiagnosticEngine;
    class DynamicSelfType;
    class Type;
    class Expr;
    class DeclRefExpr;
    class ForeignErrorConvention;
    class LiteralExpr;
    class BraceStmt;
    class DeclAttributes;
    class GenericContext;
    class GenericSignature;
    class GenericTypeParamDecl;
    class GenericTypeParamType;
    class LazyResolver;
    class ModuleDecl;
    class NameAliasType;
    class EnumCaseDecl;
    class EnumElementDecl;
    class ParameterList;
    class ParameterTypeFlags;
    class Pattern;
    struct PrintOptions;
    class ProtocolDecl;
    class ProtocolType;
    struct RawComment;
    enum class ResilienceExpansion : unsigned;
    class TypeAliasDecl;
    class Stmt;
    class SubscriptDecl;
    class UnboundGenericType;
    class ValueDecl;
    class VarDecl;
  
  enum class DeclKind : uint8_t {
  #define DECL(Id, Parent) Id,
  #define LAST_DECL(Id) Last_Decl = Id,
  #define DECL_RANGE(Id, FirstId, LastId) \
    First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
  #include "swift/AST/DeclNodes.def"
  };
  enum : unsigned { NumDeclKindBits =
    countBitsUsed(static_cast<unsigned>(DeclKind::Last_Decl)) };
  
  
  /// Fine-grained declaration kind that provides a description of the
  /// kind of entity a declaration represents, as it would be used in
  /// diagnostics.
  ///
  /// For example, \c FuncDecl is a single declaration class, but it has
  /// several descriptive entries depending on whether it is an
  /// operator, global function, local function, method, (observing)
  /// accessor, etc.
  enum class DescriptiveDeclKind : uint8_t {
    Import,
    Extension,
    EnumCase,
    TopLevelCode,
    IfConfig,
    PoundDiagnostic,
    PatternBinding,
    Var,
    Param,
    Let,
    StaticVar,
    StaticLet,
    ClassVar,
    ClassLet,
    InfixOperator,
    PrefixOperator,
    PostfixOperator,
    PrecedenceGroup,
    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,
    MissingMember,
  };
  
  /// 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 whether 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,
  };
  
  /// Keeps track of whether an enum has cases that have associated values.
  enum class AssociatedValueCheck {
    /// We have not yet checked.
    Unchecked,
    /// The enum contains no cases or all cases contain no associated values.
    NoAssociatedValues,
    /// The enum contains at least one case with associated values.
    HasAssociatedValues,
  };
  
  /// 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 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,
                   bool skipProtocolExtensionCheck = false);
  
  
  /// Decl - Base class for all declarations in Swift.
  class alignas(1 << DeclAlignInBits) Decl {
  protected:
    union { uint64_t OpaqueBits;
  
    SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1,
      Kind : bitmax(NumDeclKindBits,8),
  
      /// \brief Whether this declaration is invalid.
      Invalid : 1,
  
      /// \brief Whether this declaration was implicitly created, e.g.,
      /// an implicit constructor in a struct.
      Implicit : 1,
  
      /// \brief Whether this declaration was mapped directly from a Clang AST.
      ///
      /// Use getClangNode() to retrieve the corresponding Clang AST.
      FromClang : 1,
  
      /// \brief Whether we've already performed early attribute validation.
      /// FIXME: This is ugly.
      EarlyAttrValidation : 1,
  
      /// \brief Whether this declaration is currently being validated.
      BeingValidated : 1,
  
      /// \brief Whether we have started validating the declaration; this *isn't*
      /// reset after finishing it.
      ValidationStarted : 1,
  
      /// \brief Whether this declaration was added to the surrounding
      /// DeclContext of an active #if config clause.
      EscapedFromIfConfig : 1
    );
  
    SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16,
      /// \brief Whether this pattern binding declares static variables.
      IsStatic : 1,
  
      /// \brief Whether 'static' or 'class' was used.
      StaticSpelling : 2,
  
      : NumPadBits,
  
      /// \brief The number of pattern binding declarations.
      NumPatternEntries : 16
    );
    
    SWIFT_INLINE_BITFIELD_FULL(EnumCaseDecl, Decl, 32,
      : NumPadBits,
  
      /// The number of tail-allocated element pointers.
      NumElements : 32
    );
  
    SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
      AlreadyInLookupTable : 1,
  
      /// Whether we have already checked whether this declaration is a 
      /// redeclaration.
      CheckedRedeclaration : 1,
  
      /// Whether the decl can be accessed by swift users; for instance,
      /// a.storage for lazy var a is a decl that cannot be accessed.
      IsUserAccessible : 1
    );
  
    SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+4,
      /// Whether we are overridden later
      Overridden : 1,
  
      /// Whether the getter is mutating.
      IsGetterMutating : 1,
  
      /// Whether the setter is mutating.
      IsSetterMutating : 1,
  
      /// The storage kind.
      StorageKind : 4
    );
  
    SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+4+1+1+1,
      /// \brief Whether this property is a type property (currently unfortunately
      /// called 'static').
      IsStatic : 1,
  
      /// \brief The specifier associated with this variable or parameter.  This
      /// determines the storage semantics of the value e.g. mutability.
      Specifier : 4,
  
      /// \brief Whether this declaration was an element of a capture list.
      IsCaptureList : 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.
      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.
      IsDebuggerVar : 1
    );
  
    SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1 + NumDefaultArgumentKindBits,
      /// True if the type is implicitly specified in the source, but this has an
      /// apparently valid typeRepr.  This is used in accessors, which look like:
      ///    set (value) {
      /// but need to get the typeRepr from the property as a whole so Sema can
      /// resolve the type.
      IsTypeLocImplicit : 1,
  
      /// Information about a symbolic default argument, like #file.
      defaultArgumentKind : NumDefaultArgumentKindBits
    );
  
    SWIFT_INLINE_BITFIELD(EnumElementDecl, ValueDecl, 3,
      /// \brief Whether or not this element has an associated value.
      HasArgumentType : 1,
  
      /// \brief Whether or not this element directly or indirectly references
      /// the enum type.
      Recursiveness : 2
    );
    
    SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1,
      /// \see AbstractFunctionDecl::BodyKind
      BodyKind : 3,
  
      /// Import as member status.
      IAMStatus : 8,
  
      /// Number of curried parameter lists.
      NumParameterLists : 5,
  
      /// Whether we are overridden later.
      Overridden : 1,
  
      /// Whether the function body throws.
      Throws : 1,
  
      /// Whether this function requires a new vtable entry.
      NeedsNewVTableEntry : 1,
  
      /// Whether NeedsNewVTableEntry is valid.
      HasComputedNeedsNewVTableEntry : 1,
  
      /// The ResilienceExpansion to use for default arguments.
      DefaultArgumentResilienceExpansion : 1
    );
  
    SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+2+1+1+2,
      /// Whether this function is a 'static' method.
      IsStatic : 1,
  
      /// \brief Whether 'static' or 'class' was used.
      StaticSpelling : 2,
  
      /// Whether we are statically dispatched even if overridable
      ForcedStaticDispatch : 1,
  
      /// Whether this function has a dynamic Self return type.
      HasDynamicSelf : 1,
  
      /// Backing bits for 'self' access kind.
      SelfAccess : 2
    );
  
    SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 3+3,
      /// The kind of accessor this is.
      AccessorKind : 3,
  
      /// The kind of addressor this is.
      AddressorKind : 3
    );
  
    SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+2+2+1,
      /// The body initialization kind (+1), or zero if not yet computed.
      ///
      /// This value is cached but is not serialized, because it is a property
      /// of the definition of the constructor that is useful only to semantic
      /// analysis and SIL generation.
      ComputedBodyInitKind : 3,
  
      /// The kind of initializer we have.
      InitKind : 2,
  
      /// The failability of this initializer, which is an OptionalTypeKind.
      Failability : 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.
      HasStubImplementation : 1
    );
  
    SWIFT_INLINE_BITFIELD(TypeDecl, ValueDecl, 1,
      /// Whether we have already checked the inheritance clause.
      ///
      /// FIXME: Is this too fine-grained?
      CheckedInheritanceClause : 1
    );
  
    SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);
  
    SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
      : NumPadBits,
  
      Depth : 16,
      Index : 16
    );
  
    SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);
  
    SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1,
      /// Whether the typealias forwards perfectly to its underlying type.
      IsCompatibilityAlias : 1
    );
  
    SWIFT_INLINE_BITFIELD(NominalTypeDecl, GenericTypeDecl, 1+1+1,
      /// Whether we have already added implicitly-defined initializers
      /// to this declaration.
      AddedImplicitInitializers : 1,
  
      /// Whether there is are lazily-loaded conformances for this nominal type.
      HasLazyConformances : 1,
  
      /// Whether we have already validated all members of the type that
      /// affect layout.
      HasValidatedLayout : 1
    );
  
    SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+8+16,
      /// Whether the \c RequiresClass bit is valid.
      RequiresClassValid : 1,
  
      /// Whether this is a class-bounded protocol.
      RequiresClass : 1,
  
      /// Whether the \c ExistentialConformsToSelf bit is valid.
      ExistentialConformsToSelfValid : 1,
  
      /// Whether the existential of this protocol conforms to itself.
      ExistentialConformsToSelf : 1,
  
      /// Whether the \c ExistentialTypeSupported bit is valid.
      ExistentialTypeSupportedValid : 1,
  
      /// Whether the existential of this protocol can be represented.
      ExistentialTypeSupported : 1,
  
      /// True if the protocol has requirements that cannot be satisfied (e.g.
      /// because they could not be imported from Objective-C).
      HasMissingRequirements : 1,
  
      /// The stage of the circularity check for this protocol.
      Circularity : 2,
  
      : NumPadBits,
  
      /// If this is a compiler-known protocol, this will be a KnownProtocolKind
      /// value, plus one. Otherwise, it will be 0.
      KnownProtocol : 8, // '8' for speed. This only needs 6.
  
      /// The number of requirements in the requirement signature.
      NumRequirementsInSignature : 16
    );
  
    SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+2+2+1+3+1+1,
      /// Whether this class requires all of its instance variables to
      /// have in-class initializers.
      RequiresStoredPropertyInits : 1,
  
      /// The stage of the inheritance circularity check for this class.
      Circularity : 2,
  
      /// Whether this class inherits its superclass's convenience
      /// initializers.
      ///
      /// This is a value of \c StoredInheritsSuperclassInits.
      InheritsSuperclassInits : 2,
  
      /// \see ClassDecl::ForeignKind
      RawForeignKind : 2,
      
      /// 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.
      HasDestructorDecl : 1,
  
      /// Whether the class has @objc ancestry.
      ObjCKind : 3,
  
      HasMissingDesignatedInitializers : 1,
      HasMissingVTableEntries : 1
    );
  
    SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1,
      /// True if this struct has storage for fields that aren't accessible in
      /// Swift.
      HasUnreferenceableStorage : 1
    );
    
    SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+2+1,
      /// The stage of the raw type circularity check for this class.
      Circularity : 2,
  
      /// True if the enum has cases and at least one case has associated values.
      HasAssociatedValues : 2,
      /// True if the enum has at least one case that has some availability
      /// attribute.  A single bit because it's lazily computed along with the
      /// HasAssociatedValues bit.
      HasAnyUnavailableValues : 1
    );
  
    SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
      /// Is this an assignment operator?
      IsAssignment : 1,
  
      /// The group's associativity.  A value of the Associativity enum.
      Associativity : 2
    );
  
    SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, TypeDecl, 1+1,
      ComputedOverridden : 1,
      HasOverridden : 1
    );
  
    SWIFT_INLINE_BITFIELD(ImportDecl, Decl, 3+8,
      ImportKind : 3,
  
      /// The number of elements in this path.
      NumPathElements : 8
    );
  
    SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1+1,
      /// An encoding of the default and maximum access level for this extension.
      ///
      /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
      /// which works because the maximum is always greater than or equal to the
      /// default, and 'private' is never used. 0 represents an uncomputed value.
      DefaultAndMaxAccessLevel : 3,
  
      /// Whether we have already checked the inheritance clause.
      ///
      /// FIXME: Is this too fine-grained?
      CheckedInheritanceClause : 1,
  
      /// Whether there is are lazily-loaded conformances for this extension.
      HasLazyConformances : 1
    );
  
    SWIFT_INLINE_BITFIELD(IfConfigDecl, Decl, 1,
      /// Whether this decl is missing its closing '#endif'.
      HadMissingEnd : 1
    );
  
    SWIFT_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1,
      /// `true` if the diagnostic is an error, `false` if it's a warning.
      IsError : 1,
  
      /// Whether this diagnostic has already been emitted.
      HasBeenEmitted : 1
    );
  
    SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2,
      NumberOfFieldOffsetVectorEntries : 1,
      NumberOfVTableEntries : 2
    );
  
    } Bits;
  
    // Storage for the declaration attributes.
    DeclAttributes Attrs;
    
    /// The next declaration in the list of declarations within this
    /// member context.
    Decl *NextDecl = nullptr;
    
    friend class DeclIterator;
    friend class IterableDeclContext;
    friend class MemberLookupTable;
  
  private:
    llvm::PointerUnion<DeclContext *, ASTContext *> Context;
  
    Decl(const Decl&) = delete;
    void operator=(const Decl&) = delete;
  
  protected:
  
    Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
      : Context(context) {
      Bits.OpaqueBits = 0;
      Bits.Decl.Kind = unsigned(kind);
      Bits.Decl.Invalid = false;
      Bits.Decl.Implicit = false;
      Bits.Decl.FromClang = false;
      Bits.Decl.EarlyAttrValidation = false;
      Bits.Decl.BeingValidated = false;
      Bits.Decl.ValidationStarted = false;
      Bits.Decl.EscapedFromIfConfig = false;
    }
  
    /// \brief Get the Clang node associated with this declaration.
    ClangNode getClangNodeImpl() const;
  
    /// \brief Set the Clang node associated with this declaration.
    void setClangNode(ClangNode Node);
  
    void updateClangNode(ClangNode node) {
      assert(hasClangNode());
      setClangNode(node);
    }
    friend class ClangImporter;
  
    DeclContext *getDeclContextForModule() const;
  
  public:
    DeclKind getKind() const { return DeclKind(Bits.Decl.Kind); }
  
    /// \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;
  
    /// Determine if the decl can have a comment.  If false, a comment will
    /// not be serialized.
    bool canHaveComment() 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() const;
  
    /// \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;
  
    /// Returns the source range of the declaration including its attributes.
    SourceRange getSourceRangeIncludingAttrs() const;
  
    SourceLoc TrailingSemiLoc;
  
    LLVM_ATTRIBUTE_DEPRECATED(
        void dump() const LLVM_ATTRIBUTE_USED,
        "only for use within the debugger");
    LLVM_ATTRIBUTE_DEPRECATED(
        void dump(const char *filename) const LLVM_ATTRIBUTE_USED,
        "only for use within the debugger");
    void dump(raw_ostream &OS, unsigned Indent = 0) const;
  
    /// \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 Return whether this declaration has been determined invalid.
    bool isInvalid() const { return Bits.Decl.Invalid; }
    
    /// \brief Mark this declaration invalid.
    void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; }
  
    /// \brief Determine whether this declaration was implicitly generated by the
    /// compiler (rather than explicitly written in source code).
    bool isImplicit() const { return Bits.Decl.Implicit; }
  
    /// \brief Mark this declaration as implicit.
    void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; }
  
    /// Whether we have already done early attribute validation.
    bool didEarlyAttrValidation() const { return Bits.Decl.EarlyAttrValidation; }
  
    /// Set whether we've performed early attribute validation.
    void setEarlyAttrValidation(bool validated = true) {
      Bits.Decl.EarlyAttrValidation = validated;
    }
    
    /// Whether the declaration has a valid interface type and
    /// generic signature.
    bool isBeingValidated() const {
      return Bits.Decl.BeingValidated;
    }
  
    /// Toggle whether or not the declaration is being validated.
    void setIsBeingValidated(bool ibv = true) {
      assert(Bits.Decl.BeingValidated != ibv);
      Bits.Decl.BeingValidated = ibv;
      if (ibv) {
        Bits.Decl.ValidationStarted = true;
      }
    }
  
    bool hasValidationStarted() const { return Bits.Decl.ValidationStarted; }
  
    /// Manually indicate that validation has started for the declaration.
    ///
    /// This is implied by setIsBeingValidated(true) (i.e. starting validation)
    /// and so rarely needs to be called directly.
    void setValidationStarted() { Bits.Decl.ValidationStarted = true; }
  
    bool escapedFromIfConfig() const {
      return Bits.Decl.EscapedFromIfConfig;
    }
  
    void setEscapedFromIfConfig(bool Escaped) {
      Bits.Decl.EscapedFromIfConfig = Escaped;
    }
  
    /// \returns the unparsed comment attached to this declaration.
    RawComment getRawComment() const;
  
    Optional<StringRef> getGroupName() const;
  
    Optional<StringRef> getSourceFileName() const;
  
    Optional<unsigned> getSourceOrder() const;
  
    /// \returns the brief comment attached to this declaration.
    StringRef getBriefComment() const;
  
    /// \brief Returns true if there is a Clang AST node associated
    /// with self.
    bool hasClangNode() const {
      return Bits.Decl.FromClang;
    }
  
    /// \brief Retrieve the Clang AST node from which this declaration was
    /// synthesized, if any.
    ClangNode getClangNode() const {
      if (!Bits.Decl.FromClang)
        return ClangNode();
  
      return getClangNodeImpl();
    }
  
    /// \brief Retrieve the Clang declaration from which this declaration was
    /// synthesized, if any.
    const clang::Decl *getClangDecl() const {
      if (!Bits.Decl.FromClang)
        return nullptr;
  
      return getClangNodeImpl().getAsDecl();
    }
  
    /// \brief Retrieve the Clang macro from which this declaration was
    /// synthesized, if any.
    const clang::MacroInfo *getClangMacro() {
      if (!Bits.Decl.FromClang)
        return nullptr;
  
      return getClangNodeImpl().getAsMacro();
    }
  
    /// \brief Return the GenericContext if the Decl has one.
    const GenericContext *getAsGenericContext() const;
  
    bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
  
    /// Whether this declaration is weak-imported.
    bool isWeakImported(ModuleDecl *fromModule) const;
  
    /// Returns true if the nature of this declaration allows overrides.
    /// Note that this does not consider whether it is final or whether
    /// the class it's on is final.
    ///
    /// If this returns true, the decl can be safely casted to ValueDecl.
    bool isPotentiallyOverridable() const;
  
    // Make vanilla new/delete illegal for Decls.
    void *operator new(size_t Bytes) = delete;
    void operator delete(void *Data) SWIFT_DELETE_OPERATOR_DELETED;
  
    // Only allow allocation of Decls using the allocator in ASTContext
    // or by doing a placement new.
    void *operator new(size_t Bytes, const ASTContext &C,
                       unsigned Alignment = alignof(Decl));
    void *operator new(size_t Bytes, void *Mem) { 
      assert(Mem); 
      return Mem; 
    }
  };
  
  /// \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;
  }
  
  enum class RequirementReprKind : unsigned {
    /// A type bound T : P, where T is a type that depends on a generic
    /// parameter and P is some type that should bound T, either as a concrete
    /// supertype or a protocol to which T must conform.
    TypeConstraint,
  
    /// A same-type requirement T == U, where T and U are types that shall be
    /// equivalent.
    SameType,
  
    /// A layout bound T : L, where T is a type that depends on a generic
    /// parameter and L is some layout specification that should bound T.
    LayoutConstraint,
  
    // Note: there is code that packs this enum in a 2-bit bitfield.  Audit users
    // when adding enumerators.
  };
  
  /// \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;
    RequirementReprKind Kind : 2;
    bool Invalid : 1;
    TypeLoc FirstType;
  
    /// The second element represents the right-hand side of the constraint.
    /// It can be e.g. a type or a layout constraint.
    union {
      TypeLoc SecondType;
      LayoutConstraintLoc SecondLayout;
    };
  
    /// Set during deserialization; used to print out the requirements accurately
    /// for the generated interface.
    StringRef AsWrittenString;
  
    RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                    TypeLoc FirstType, TypeLoc SecondType)
      : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
        FirstType(FirstType), SecondType(SecondType) { }
  
    RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
                    TypeLoc FirstType, LayoutConstraintLoc SecondLayout)
      : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
        FirstType(FirstType), SecondLayout(SecondLayout) { }
  
    void printImpl(ASTPrinter &OS, bool AsWritten) const;
  
  public:
    /// \brief Construct a new type-constraint requirement.
    ///
    /// \param Subject The type that must conform to the given protocol or
    /// composition, or be a subclass of the given class type.
    /// \param ColonLoc The location of the ':', or an invalid location if
    /// this requirement was implied.
    /// \param Constraint The protocol or protocol composition to which the
    /// subject must conform, or superclass from which the subject must inherit.
    static RequirementRepr getTypeConstraint(TypeLoc Subject,
                                             SourceLoc ColonLoc,
                                             TypeLoc Constraint) {
      return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
    }
  
    /// \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, RequirementReprKind::SameType, FirstType, SecondType };
    }
  
    /// \brief Construct a new layout-constraint requirement.
    ///
    /// \param Subject The type that must conform to the given layout 
    /// requirement.
    /// \param ColonLoc The location of the ':', or an invalid location if
    /// this requirement was implied.
    /// \param Layout The layout requirement to which the
    /// subject must conform.
    static RequirementRepr getLayoutConstraint(TypeLoc Subject,
                                               SourceLoc ColonLoc,
                                               LayoutConstraintLoc Layout) {
      return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
              Layout};
    }
  
    /// \brief Determine the kind of requirement
    RequirementReprKind 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 type-bound requirement, return the subject of the
    /// conformance relationship.
    Type getSubject() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType.getType();
    }
  
    TypeRepr *getSubjectRepr() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType.getTypeRepr();
    }
  
    TypeLoc &getSubjectLoc() {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType;
    }
  
    const TypeLoc &getSubjectLoc() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return FirstType;
    }
  
    /// \brief For a type-bound requirement, return the protocol or to which
    /// the subject conforms or superclass it inherits.
    Type getConstraint() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType.getType();
    }
  
    TypeRepr *getConstraintRepr() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType.getTypeRepr();
    }
  
    TypeLoc &getConstraintLoc() {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType;
    }
  
    const TypeLoc &getConstraintLoc() const {
      assert(getKind() == RequirementReprKind::TypeConstraint);
      return SecondType;
    }
  
    LayoutConstraint getLayoutConstraint() const {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout.getLayoutConstraint();
    }
  
    LayoutConstraintLoc &getLayoutConstraintLoc() {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout;
    }
  
    const LayoutConstraintLoc &getLayoutConstraintLoc() const {
      assert(getKind() == RequirementReprKind::LayoutConstraint);
      return SecondLayout;
    }
  
    /// \brief Retrieve the location of the ':' in an explicitly-written
    /// conformance requirement.
    SourceLoc getColonLoc() const {
      assert(getKind() == RequirementReprKind::TypeConstraint ||
             getKind() == RequirementReprKind::LayoutConstraint);
      return SeparatorLoc;
    }
  
    /// \brief Retrieve the first type of a same-type requirement.
    Type getFirstType() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType.getType();
    }
  
    TypeRepr *getFirstTypeRepr() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType.getTypeRepr();
    }
  
    TypeLoc &getFirstTypeLoc() {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType;
    }
  
    const TypeLoc &getFirstTypeLoc() const {
      assert(getKind() == RequirementReprKind::SameType);
      return FirstType;
    }
  
    /// \brief Retrieve the second type of a same-type requirement.
    Type getSecondType() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType.getType();
    }
  
    TypeRepr *getSecondTypeRepr() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType.getTypeRepr();
    }
  
    TypeLoc &getSecondTypeLoc() {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType;
    }
  
    const TypeLoc &getSecondTypeLoc() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SecondType;
    }
  
    /// \brief Retrieve the location of the '==' in an explicitly-written
    /// same-type requirement.
    SourceLoc getEqualLoc() const {
      assert(getKind() == RequirementReprKind::SameType);
      return SeparatorLoc;
    }
  
    SourceRange getSourceRange() const {
      if (getKind() == RequirementReprKind::LayoutConstraint)
        return SourceRange(FirstType.getSourceRange().Start,
                           SecondLayout.getSourceRange().End);
      return SourceRange(FirstType.getSourceRange().Start,
                         SecondType.getSourceRange().End);
    }
  
    LLVM_ATTRIBUTE_DEPRECATED(
        void dump() const LLVM_ATTRIBUTE_USED,
        "only for use within the debugger");
    void print(raw_ostream &OS) const;
    void print(ASTPrinter &Printer) const;
  };
    
  /// GenericParamList - A list of generic parameters that is part of a generic
  /// function or type, along with extra requirements placed on those generic
  /// parameters and types derived from them.
  class GenericParamList final :
      private llvm::TrailingObjects<GenericParamList, GenericTypeParamDecl *> {
    friend TrailingObjects;
  
    SourceRange Brackets;
    unsigned NumParams;
    SourceLoc WhereLoc;
    MutableArrayRef<RequirementRepr> Requirements;
  
    GenericParamList *OuterParameters;
  
    SourceLoc TrailingWhereLoc;
    unsigned FirstTrailingWhereArg;
  
    GenericParamList(SourceLoc LAngleLoc,
                     ArrayRef<GenericTypeParamDecl *> Params,
                     SourceLoc WhereLoc,
                     MutableArrayRef<RequirementRepr> Requirements,
                     SourceLoc RAngleLoc);
    
    // Don't copy.
    GenericParamList(const GenericParamList &) = delete;
    GenericParamList &operator=(const GenericParamList &) = delete;
    
  public:
    /// create - Create a new generic parameter list within the given AST context.
    ///
    /// \param Context The ASTContext in which the generic parameter list will
    /// be allocated.
    /// \param LAngleLoc The location of the opening angle bracket ('<')
    /// \param Params The list of generic parameters, which will be copied into
    /// ASTContext-allocated memory.
    /// \param RAngleLoc The location of the closing angle bracket ('>')
    static GenericParamList *create(ASTContext &Context,
                                    SourceLoc LAngleLoc,
                                    ArrayRef<GenericTypeParamDecl *> Params,
                                    SourceLoc RAngleLoc);
  
    /// create - Create a new generic parameter list and "where" clause within
    /// the given AST context.
    ///
    /// \param Context The ASTContext in which the generic parameter list will
    /// be allocated.
    /// \param LAngleLoc The location of the opening angle bracket ('<')
    /// \param Params The list of generic parameters, which will be copied into
    /// ASTContext-allocated memory.
    /// \param WhereLoc The location of the 'where' keyword, if any.
    /// \param Requirements The list of requirements, which will be copied into
    /// ASTContext-allocated memory.
    /// \param RAngleLoc The location of the closing angle bracket ('>')
    static GenericParamList *create(const ASTContext &Context,
                                    SourceLoc LAngleLoc,
                                    ArrayRef<GenericTypeParamDecl *> Params,
                                    SourceLoc WhereLoc,
                                    ArrayRef<RequirementRepr> Requirements,
                                    SourceLoc RAngleLoc);
  
    MutableArrayRef<GenericTypeParamDecl *> getParams() {
      return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
    }
  
    ArrayRef<GenericTypeParamDecl *> getParams() const {
      return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
    }
  
    using iterator = GenericTypeParamDecl **;
    using const_iterator = const GenericTypeParamDecl * const *;
  
    unsigned size() const { return NumParams; }
    iterator begin() { return getParams().begin(); }
    iterator end() { return getParams().end(); }
    const_iterator begin() const { return getParams().begin(); }
    const_iterator end() const { return getParams().end(); }
  
    /// \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 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 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> {
    ///   init<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();
  
      auto endLoc = Requirements[FirstTrailingWhereArg-1].getSourceRange().End;
      return SourceRange(WhereLoc, endLoc);
    }
  
    /// Retrieve the source range covering the trailing where clause.
    SourceRange getTrailingWhereClauseSourceRange() const {
      if (!hasTrailingWhereClause())
        return SourceRange();
  
      return SourceRange(TrailingWhereLoc,
                         Requirements.back().getSourceRange().End);
    }
  
    /// 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;
    }
  
    /// Create a copy of the generic parameter list and all of its generic
    /// parameter declarations. The copied generic parameters are re-parented
    /// to the given DeclContext.
    GenericParamList *clone(DeclContext *dc) const;
  
    void print(raw_ostream &OS);
    void dump();
  };
    
  /// A trailing where clause.
  class alignas(RequirementRepr) TrailingWhereClause final :
      private llvm::TrailingObjects<TrailingWhereClause, RequirementRepr> {
    friend TrailingObjects;
  
    SourceLoc WhereLoc;
  
    /// The number of requirements. The actual requirements are tail-allocated.
    unsigned NumRequirements;
  
    TrailingWhereClause(SourceLoc whereLoc,
                        ArrayRef<RequirementRepr> requirements);
  
  public:
    /// Create a new trailing where clause with the given set of requirements.
    static TrailingWhereClause *create(ASTContext &ctx, SourceLoc whereLoc,
                                       ArrayRef<RequirementRepr> requirements);
  
    /// Retrieve the location of the 'where' keyword.
    SourceLoc getWhereLoc() const { return WhereLoc; }
  
    /// Retrieve the set of requirements.
    MutableArrayRef<RequirementRepr> getRequirements() {
      return {getTrailingObjects<RequirementRepr>(), NumRequirements};
    }
  
    /// Retrieve the set of requirements.
    ArrayRef<RequirementRepr> getRequirements() const {
      return {getTrailingObjects<RequirementRepr>(), NumRequirements};
    }
  
    /// Compute the source range containing this trailing where clause.
    SourceRange getSourceRange() const {
      return SourceRange(WhereLoc,
                         getRequirements().back().getSourceRange().End);
    }
  };
  
  // A private class for forcing exact field layout.
  class _GenericContext {
  // Not really public. See GenericContext.
  public:
    GenericParamList *GenericParams = nullptr;
  
    /// The trailing where clause.
    ///
    /// Note that this is not currently serialized, because semantic analysis
    /// moves the trailing where clause into the generic parameter list.
    TrailingWhereClause *TrailingWhere = nullptr;
  
    /// The generic signature or environment of this declaration.
    ///
    /// When this declaration stores only a signature, the generic
    /// environment will be lazily loaded.
    mutable llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
      GenericSigOrEnv;
  };
  
  class GenericContext : private _GenericContext, public DeclContext {
    /// Lazily populate the generic environment.
    GenericEnvironment *getLazyGenericEnvironmentSlow() const;
  
  protected:
    GenericContext(DeclContextKind Kind, DeclContext *Parent)
      : _GenericContext(), DeclContext(Kind, Parent) { }
  
  public:
    /// \brief Retrieve the set of parameters to a generic context, or null if
    /// this context is not generic.
    GenericParamList *getGenericParams() const { return GenericParams; }
  
    void setGenericParams(GenericParamList *GenericParams);
  
    /// \brief Determine whether this context has generic parameters
    /// of its own.
    bool isGeneric() const { return GenericParams != nullptr; }
  
    /// Retrieve the trailing where clause for this extension, if any.
    TrailingWhereClause *getTrailingWhereClause() const {
      return TrailingWhere;
    }
  
    /// Set the trailing where clause for this extension.
    void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
      TrailingWhere = trailingWhereClause;
    }
  
    /// Retrieve the generic signature for this context.
    GenericSignature *getGenericSignature() const;
  
    /// Retrieve the generic context for this context.
    GenericEnvironment *getGenericEnvironment() const;
  
    /// Retrieve the innermost generic parameter types.
    TypeArrayView<GenericTypeParamType> getInnermostGenericParamTypes() const;
  
    /// Retrieve the generic requirements.
    ArrayRef<Requirement> getGenericRequirements() const;
  
    /// Set a lazy generic environment.
    void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader,
                                   GenericSignature *genericSig,
                                   uint64_t genericEnvData);
  
    /// Whether this generic context has a lazily-created generic environment
    /// that has not yet been constructed.
    bool hasLazyGenericEnvironment() const;
  
    /// Set the generic context of this context.
    void setGenericEnvironment(GenericEnvironment *genericEnv);
  };
  static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
                sizeof(GenericContext), "Please add fields to _GenericContext");
  
  /// Describes what kind of name is being imported.
  ///
  /// If the enumerators here are changed, make sure to update all diagnostics
  /// using ImportKind as a select index.
  enum class ImportKind : uint8_t {
    Module = 0,
    Type,
    Struct,
    Class,
    Enum,
    Protocol,
    Var,
    Func
  };
  
  /// ImportDecl - This represents a single import declaration, e.g.:
  ///   import Swift
  ///   import typealias Swift.Int
  class ImportDecl final : public Decl,
      private llvm::TrailingObjects<ImportDecl, std::pair<Identifier,SourceLoc>> {
    friend TrailingObjects;
  
  public:
    typedef std::pair<Identifier, SourceLoc> AccessPathElement;
  
  private:
    SourceLoc ImportLoc;
    SourceLoc KindLoc;
  
    /// The resolved module.
    ModuleDecl *Mod = nullptr;
    /// The resolved decls if this is a decl import.
    ArrayRef<ValueDecl *> Decls;
  
    ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
               SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);
  
  public:
    static ImportDecl *create(ASTContext &C, DeclContext *DC,
                              SourceLoc ImportLoc, ImportKind Kind,
                              SourceLoc KindLoc,
                              ArrayRef<AccessPathElement> Path,
                              ClangNode ClangN = ClangNode());
  
    /// Returns the import kind that is most appropriate for \p VD.
    ///
    /// Note that this will never return \c Type; an imported typealias will use
    /// the more specific kind from its underlying type.
    static ImportKind getBestImportKind(const ValueDecl *VD);
  
    /// Returns the most appropriate import kind for the given list of decls.
    ///
    /// If the list is non-homogeneous, or if there is more than one decl that
    /// cannot be overloaded, returns None.
    static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);
  
    ArrayRef<AccessPathElement> getFullAccessPath() const {
      return {getTrailingObjects<AccessPathElement>(),
              Bits.ImportDecl.NumPathElements};
    }
  
    ArrayRef<AccessPathElement> getModulePath() const {
      auto result = getFullAccessPath();
      if (getImportKind() != ImportKind::Module)
        result = result.slice(0, result.size()-1);
      return result;
    }
  
    ArrayRef<AccessPathElement> getDeclPath() const {
      if (getImportKind() == ImportKind::Module)
        return {};
      return getFullAccessPath().back();
    }
  
    ImportKind getImportKind() const {
      return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
    }
  
    bool isExported() const {
      return getAttrs().hasAttribute<ExportedAttr>();
    }
  
    ModuleDecl *getModule() const { return Mod; }
    void setModule(ModuleDecl *M) { Mod = M; }
  
    ArrayRef<ValueDecl *> getDecls() const { return Decls; }
    void setDecls(ArrayRef<ValueDecl *> Ds) { Decls = Ds; }
  
    const clang::Module *getClangModule() const {
      return getClangNode().getClangModule();
    }
  
    SourceLoc getStartLoc() const { return ImportLoc; }
    SourceLoc 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 GenericContext, public Decl,
                              public IterableDeclContext {
    SourceLoc ExtensionLoc;  // Location of 'extension' keyword.
    SourceRange Braces;
  
    /// The type being extended.
    TypeLoc ExtendedType;
    
    MutableArrayRef<TypeLoc> Inherited;
  
    /// \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 (!Bits.ExtensionDecl.HasLazyConformances)
        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 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 have fully checked the extension.
    bool hasValidSignature() const {
      return hasValidationStarted() && !isBeingValidated();
    }
  
    /// Whether we already type-checked the inheritance clause.
    bool checkedInheritanceClause() const {
      return Bits.ExtensionDecl.CheckedInheritanceClause;
    }
  
    /// Note that we have already type-checked the inheritance clause.
    void setCheckedInheritanceClause(bool checked = true) {
      Bits.ExtensionDecl.CheckedInheritanceClause = checked;
    }
  
    bool hasDefaultAccessLevel() const {
      return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
    }
  
    AccessLevel getDefaultAccessLevel() const {
      assert(hasDefaultAccessLevel() && "not computed yet");
      if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel &
          (1 << (static_cast<unsigned>(AccessLevel::FilePrivate) - 1)))
        return AccessLevel::FilePrivate;
      if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel &
          (1 << (static_cast<unsigned>(AccessLevel::Internal) - 1)))
        return AccessLevel::Internal;
      return AccessLevel::Public;
    }
  
    AccessLevel getMaxAccessLevel() const {
      assert(hasDefaultAccessLevel() && "not computed yet");
      if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel &
          (1 << (static_cast<unsigned>(AccessLevel::Public) - 1)))
        return AccessLevel::Public;
      if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel &
          (1 << (static_cast<unsigned>(AccessLevel::Internal) - 1)))
        return AccessLevel::Internal;
      return AccessLevel::FilePrivate;
    }
  
    void setDefaultAndMaxAccess(AccessLevel defaultAccess,
                                AccessLevel maxAccess) {
      assert(!hasDefaultAccessLevel() && "default access level already set");
      assert(maxAccess >= defaultAccess);
      assert(maxAccess != AccessLevel::Private && "private not valid");
      assert(defaultAccess != AccessLevel::Private && "private not valid");
      Bits.ExtensionDecl.DefaultAndMaxAccessLevel =
          (1 << (static_cast<unsigned>(defaultAccess) - 1)) |
          (1 << (static_cast<unsigned>(maxAccess) - 1));
      assert(getDefaultAccessLevel() == defaultAccess && "not enough bits");
      assert(getMaxAccessLevel() == maxAccess && "not enough bits");
    }
  
    void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);
  
    /// Determine whether this is a constrained extension, which adds additional
    /// requirements beyond those of the nominal type.
    bool isConstrainedExtension() const;
    
    /// Determine whether this extension context is interchangeable with the
    /// original nominal type context.
    ///
    /// False if any of the following properties hold:
    /// - the extension is defined in a different module from the original
    ///   nominal type decl,
    /// - the extension is constrained, or
    /// - the extension is to a protocol.
    /// FIXME: In a world where protocol extensions are dynamically dispatched,
    /// "extension is to a protocol" would no longer be a reason to use the
    /// extension mangling, because an extension method implementation could be
    /// resiliently moved into the original protocol itself.
    bool isEquivalentToExtendedContext() const;
  
    // Implement isa/cast/dyncast/etc.
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Extension;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    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;
  
    enum class Flags {
      Checked = 1 << 0,
      Removed = 1 << 1
    };
  
    // When the initializer is removed we don't actually clear the pointer
    // because we might need to get initializer's source range. Since the
    // initializer is ASTContext-allocated it is safe.
    llvm::PointerIntPair<Expr *, 2, OptionSet<Flags>> InitCheckedAndRemoved;
  
    /// The initializer context used for this pattern binding entry.
    DeclContext *InitContext = nullptr;
  
    friend class PatternBindingInitializer;
  
  public:
    PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext)
      : ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {}
  
    Pattern *getPattern() const { return ThePattern; }
    void setPattern(Pattern *P) { ThePattern = P; }
    Expr *getInit() const {
      return (InitCheckedAndRemoved.getInt().contains(Flags::Removed))
        ? nullptr : InitCheckedAndRemoved.getPointer();
    }
    SourceRange getOrigInitRange() const;
    void setInit(Expr *E);
  
    /// Retrieve the initializer as it was written in the source.
    Expr *getInitAsWritten() const { return InitCheckedAndRemoved.getPointer(); }
  
    bool isInitializerChecked() const {
      return InitCheckedAndRemoved.getInt().contains(Flags::Checked);
    }
    void setInitializerChecked() {
      InitCheckedAndRemoved.setInt(
        InitCheckedAndRemoved.getInt() | Flags::Checked);
    }
  
    // Return the first variable initialized by this pattern.
    VarDecl *getAnchoringVarDecl() const;
  
    // Retrieve the declaration context for the initializer.
    DeclContext *getInitContext() const { return InitContext; }
  
    /// Override the initializer context.
    void setInitContext(DeclContext *dc) { InitContext = dc; }
  
    /// Retrieve the source range covered by this pattern binding.
    ///
    /// \param omitAccessors Whether the computation should omit the accessors
    /// from the source range.
    SourceRange getSourceRange(bool omitAccessors = false) const;
  };
  
  /// \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 final : public Decl,
      private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
    friend TrailingObjects;
  
    SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
    SourceLoc VarLoc;    ///< Location of the 'var' keyword.
  
    friend class Decl;
    
    PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
                       SourceLoc VarLoc, unsigned NumPatternEntries,
                       DeclContext *Parent);
  
  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);
  
    static PatternBindingDecl *createDeserialized(
                                 ASTContext &Ctx, SourceLoc StaticLoc,
                                 StaticSpellingKind StaticSpelling,
                                 SourceLoc VarLoc,
                                 unsigned NumPatternEntries,
                                 DeclContext *Parent);
  
    SourceLoc getStartLoc() const {
      return StaticLoc.isValid() ? StaticLoc : VarLoc;
    }
    SourceLoc getLoc() const { return VarLoc; }
    SourceRange getSourceRange() const;
  
    unsigned getNumPatternEntries() const {
      return Bits.PatternBindingDecl.NumPatternEntries;
    }
    
    ArrayRef<PatternBindingEntry> getPatternList() const {
      return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
    }
  
    Expr *getInit(unsigned i) const {
      return getPatternList()[i].getInit();
    }
    
    SourceRange getOrigInitRange(unsigned i) const {
      return getPatternList()[i].getOrigInitRange();
    }
  
    void setInit(unsigned i, Expr *E) {
      getMutablePatternList()[i].setInit(E);
    }
  
    Pattern *getPattern(unsigned i) const {
      return getPatternList()[i].getPattern();
    }
    
    void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext);
  
    /// 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;
  
    /// Determines whether this binding either has an initializer expression, or is
    /// default initialized, without performing any type checking on it.
    ///
    /// This is only valid to check for bindings which have storage.
    bool isDefaultInitializable() const {
      assert(hasStorage());
  
      for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
        if (!isDefaultInitializable(i))
          return false;
  
      return true;
    }
  
    /// Can the pattern at index i be default initialized?
    bool isDefaultInitializable(unsigned i) const;
    
    /// When the pattern binding contains only a single variable with no
    /// destructuring, retrieve that variable.
    VarDecl *getSingleVar() const;
  
    bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; }
    void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; }
    SourceLoc getStaticLoc() const { return StaticLoc; }
    /// \returns the way 'static'/'class' was spelled in the source.
    StaticSpellingKind getStaticSpelling() const {
      return static_cast<StaticSpellingKind>(
          Bits.PatternBindingDecl.StaticSpelling);
    }
    /// \returns the way 'static'/'class' should be spelled for this declaration.
    StaticSpellingKind getCorrectStaticSpelling() const;
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PatternBinding;
    }
    
  private:
    MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
      // Pattern entries are tail allocated.
      return {getTrailingObjects<PatternBindingEntry>(), getNumPatternEntries()};
    }
  };
    
  /// TopLevelCodeDecl - This decl is used as a container for top-level
  /// expressions and statements in the main module.  It is always a direct
  /// child of a SourceFile.  The primary reason for building these is to give
  /// top-level statements a DeclContext which is distinct from the file itself.
  /// This, among other things, makes it easier to distinguish between local
  /// top-level variables (which are not live past the end of the statement) and
  /// global variables.
  class TopLevelCodeDecl : public DeclContext, public Decl {
    BraceStmt *Body;
  
  public:
    TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
      : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
        Decl(DeclKind::TopLevelCode, Parent),
        Body(Body) {}
  
    BraceStmt *getBody() const { return Body; }
    void setBody(BraceStmt *b) { Body = b; }
  
    SourceLoc getStartLoc() const;
    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) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    
    using DeclContext::operator new;
  };
  
  /// SerializedTopLevelCodeDeclContext - This represents what was originally a
  /// TopLevelCodeDecl during serialization. It is preserved only to maintain the
  /// correct AST structure and remangling after deserialization.
  class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext {
  public:
    SerializedTopLevelCodeDeclContext(DeclContext *Parent)
      : SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl,
                                   Parent) {}
    static bool classof(const DeclContext *DC) {
      if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
        return LDC->getLocalDeclContextKind() ==
          LocalDeclContextKind::TopLevelCodeDecl;
      return false;
    }
  };
  
  /// IfConfigDecl - This class represents #if/#else/#endif blocks.
  /// Active and inactive block members are stored separately, with the intention
  /// being that active members will be handed back to the enclosing context.
  class IfConfigDecl : public Decl {
    /// An array of clauses controlling each of the #if/#elseif/#else conditions.
    /// The array is ASTContext allocated.
    ArrayRef<IfConfigClause> Clauses;
    SourceLoc EndLoc;
  public:
    
    IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses,
                 SourceLoc EndLoc, bool HadMissingEnd)
      : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
    {
      Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd;
    }
  
    ArrayRef<IfConfigClause> getClauses() const { return Clauses; }
  
    /// Return the active clause, or null if there is no active one.
    const IfConfigClause *getActiveClause() const {
      for (auto &Clause : Clauses)
        if (Clause.isActive) return &Clause;
      return nullptr;
    }
  
    const ArrayRef<ASTNode> getActiveClauseElements() const {
      if (auto *Clause = getActiveClause())
        return Clause->Elements;
      return {};
    }
    
    SourceLoc getEndLoc() const { return EndLoc; }
    SourceLoc getLoc() const { return Clauses[0].Loc; }
  
    bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; }
    
    SourceRange getSourceRange() const;
    
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::IfConfig;
    }
  };
  
  class StringLiteralExpr;
  
  class PoundDiagnosticDecl : public Decl {
    SourceLoc StartLoc;
    SourceLoc EndLoc;
    StringLiteralExpr *Message;
  
  public:
    PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc,
                        SourceLoc EndLoc, StringLiteralExpr *Message)
      : Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc),
        EndLoc(EndLoc), Message(Message) {
        Bits.PoundDiagnosticDecl.IsError = IsError;
        Bits.PoundDiagnosticDecl.HasBeenEmitted = false; 
      }
  
    DiagnosticKind getKind() {
      return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning;
    }
  
    StringLiteralExpr *getMessage() { return Message; }
  
    bool isError() {
      return Bits.PoundDiagnosticDecl.IsError;
    }
  
    bool hasBeenEmitted() {
      return Bits.PoundDiagnosticDecl.HasBeenEmitted;
    }
  
    void markEmitted() {
      Bits.PoundDiagnosticDecl.HasBeenEmitted = true;
    }
    
    SourceLoc getEndLoc() const { return EndLoc; };
    SourceLoc getLoc() const { return StartLoc; }
    
    SourceRange getSourceRange() const {
      return SourceRange(StartLoc, EndLoc);
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PoundDiagnostic;
    }
  };
  
  /// ValueDecl - All named decls that are values in the language.  These can
  /// have a type, etc.
  class ValueDecl : public Decl {
    DeclName Name;
    SourceLoc NameLoc;
    llvm::PointerIntPair<Type, 3, OptionalEnum<AccessLevel>> TypeAndAccess;
  
  protected:
    ValueDecl(DeclKind K,
              llvm::PointerUnion<DeclContext *, ASTContext *> context,
              DeclName name, SourceLoc NameLoc)
      : Decl(K, context), Name(name), NameLoc(NameLoc) {
      Bits.ValueDecl.AlreadyInLookupTable = false;
      Bits.ValueDecl.CheckedRedeclaration = false;
      Bits.ValueDecl.IsUserAccessible = true;
    }
  
    // MemberLookupTable borrows a bit from this type
    friend class MemberLookupTable;
    bool isAlreadyInLookupTable() {
      return Bits.ValueDecl.AlreadyInLookupTable;
    }
    void setAlreadyInLookupTable(bool value = true) {
      Bits.ValueDecl.AlreadyInLookupTable = value;
    }
  
  public:
    /// \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;
  
    /// \brief Return true if this protocol member is a protocol requirement.
    ///
    /// Asserts if this is not a member of a protocol.
    bool isProtocolRequirement() const;
  
    /// Determine whether we have already checked whether this
    /// declaration is a redeclaration.
    bool alreadyCheckedRedeclaration() const { 
      return Bits.ValueDecl.CheckedRedeclaration; 
    }
  
    /// Set whether we have already checked this declaration as a
    /// redeclaration.
    void setCheckedRedeclaration(bool checked) {
      Bits.ValueDecl.CheckedRedeclaration = checked;
    }
  
    void setUserAccessible(bool Accessible) {
      Bits.ValueDecl.IsUserAccessible = Accessible;
    }
  
    bool isUserAccessible() const {
      return Bits.ValueDecl.IsUserAccessible;
    }
  
    bool hasName() const { return bool(Name); }
    bool isOperator() const { return Name.isOperator(); }
  
    /// Retrieve the full name of the declaration.
    /// TODO: Rename to getName?
    DeclName getFullName() const { return Name; }
    void setName(DeclName name) { Name = name; }
  
    /// Retrieve the base name of the declaration, ignoring any argument
    /// names.
    DeclBaseName getBaseName() const { return Name.getBaseName(); }
  
    /// Retrieve the name to use for this declaration when interoperating
    /// with the Objective-C runtime.
    ///
    /// \returns A "selector" containing the runtime name. For non-method
    /// entities (classes, protocols, properties), this operation will
    /// return a zero-parameter selector with the appropriate name in its
    /// first slot.
    Optional<ObjCSelector> getObjCRuntimeName() const;
  
    /// Determine whether the given declaration can infer @objc, or the
    /// Objective-C name, if used to satisfy the given requirement.
    bool canInferObjCFromRequirement(ValueDecl *requirement);
  
    SourceLoc getNameLoc() const { return NameLoc; }
    SourceLoc getLoc() const { return NameLoc; }
  
    bool hasAccess() const {
      return TypeAndAccess.getInt().hasValue();
    }
  
    /// \see getFormalAccess
    AccessLevel getFormalAccessImpl(const DeclContext *useDC) const;
  
    bool isVersionedInternalDecl() const;
  
    /// 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. If \p useDC is provided (the location where the value is
    /// being used), features that affect formal access such as \c \@testable are
    /// taken into account.
    ///
    /// \sa getFormalAccessScope
    AccessLevel getFormalAccess(const DeclContext *useDC = nullptr,
                                bool respectVersionedAttr = false) const {
      assert(hasAccess() && "access not computed yet");
      AccessLevel result = TypeAndAccess.getInt().getValue();
      if (respectVersionedAttr &&
          result == AccessLevel::Internal &&
          isVersionedInternalDecl()) {
        assert(!useDC);
        return AccessLevel::Public;
      }
      if (useDC && (result == AccessLevel::Internal ||
                    result == AccessLevel::Public))
        return getFormalAccessImpl(useDC);
      return result;
    }
  
    /// Determine whether this Decl has either Private or FilePrivate access.
    bool isOutermostPrivateOrFilePrivateScope() const;
  
    /// Returns the outermost DeclContext from which this declaration can be
    /// accessed, or null if the declaration is public.
    ///
    /// This is used when calculating if access control is being used
    /// consistently. If \p useDC is provided (the location where the value is
    /// being used), features that affect formal access such as \c \@testable are
    /// taken into account.
    ///
    /// \invariant
    /// <code>value.isAccessibleFrom(value.getFormalAccessScope())</code>
    ///
    /// \sa getFormalAccess
    /// \sa isAccessibleFrom
    AccessScope
    getFormalAccessScope(const DeclContext *useDC = nullptr,
                         bool respectVersionedAttr = false) const;
  
  
    /// Copy the formal access level and @_versioned attribute from source.
    void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source);
  
    /// Returns the access level that actually controls how a declaration should
    /// be emitted and may be used.
    ///
    /// This is the access used when making optimization and code generation
    /// decisions. It should not be used at the AST or semantic level.
    AccessLevel getEffectiveAccess() const;
  
    void setAccess(AccessLevel access) {
      assert(!hasAccess() && "access already set");
      overwriteAccess(access);
    }
  
    /// Overwrite the access of this declaration.
    ///
    /// This is needed in the LLDB REPL.
    void overwriteAccess(AccessLevel access) {
      TypeAndAccess.setInt(access);
    }
  
    /// Returns true if this declaration is accessible from the given context.
    ///
    /// A private declaration is accessible from any DeclContext within the same
    /// source file.
    ///
    /// An internal declaration is accessible from any DeclContext within the same
    /// module.
    ///
    /// A public declaration is accessible everywhere.
    ///
    /// If \p DC is null, returns true only if this declaration is public.
    bool isAccessibleFrom(const DeclContext *DC) const;
  
    /// Retrieve the "interface" type of this value, which uses
    /// GenericTypeParamType if the declaration is generic. For a generic
    /// function, this will have a GenericFunctionType with a
    /// GenericSignature inside the type.
    Type getInterfaceType() const;
    bool hasInterfaceType() const;
  
    /// Set the interface type for the given value.
    void setInterfaceType(Type type);
  
    bool hasValidSignature() const;
  
    /// 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 untyped overload signature for this declaration.
    OverloadSignature getOverloadSignature() const;
  
    /// Retrieve the type used to describe this entity for the purposes of
    /// overload resolution.
    CanType getOverloadSignatureType() const;
  
    /// Returns true if the decl requires Objective-C interop.
    ///
    /// This can be true even if there is no 'objc' attribute on the declaration.
    /// In that case it was inferred by the type checker and set with a call to
    /// markAsObjC().
    bool isObjC() const {
      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;
    }
    
    /// True if this is a C function that was imported as a member of a type in
    /// Swift.
    bool isImportAsMember() const;
  };
  
  /// This is a common base class for declarations which declare a type.
  class TypeDecl : public ValueDecl {
    MutableArrayRef<TypeLoc> Inherited;
  
  protected:
    TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
             Identifier name, SourceLoc NameLoc,
             MutableArrayRef<TypeLoc> inherited) :
      ValueDecl(K, context, name, NameLoc), Inherited(inherited)
    {
      Bits.TypeDecl.CheckedInheritanceClause = false;
    }
  
  public:
    Identifier getName() const { return getFullName().getBaseIdentifier(); }
  
    /// Returns the string for the base name, or "_" if this is unnamed.
    StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
    }
  
    /// The type of this declaration's values. For the type of the
    /// declaration itself, use getInterfaceType(), which returns a
    /// metatype.
    Type getDeclaredInterfaceType() const;
  
    /// \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 Bits.TypeDecl.CheckedInheritanceClause;
    }
  
    /// Note that we have already type-checked the inheritance clause.
    void setCheckedInheritanceClause(bool checked = true) {
      Bits.TypeDecl.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;
    }
  
    /// Compute an ordering between two type declarations that is ABI-stable.
    static int compare(const TypeDecl *type1, const TypeDecl *type2);
  };
  
  /// A type declaration that can have generic parameters attached to it.  Because
  /// it has these generic parameters, it is always a DeclContext.
  class GenericTypeDecl : public GenericContext, public TypeDecl {
  public:
    GenericTypeDecl(DeclKind K, DeclContext *DC,
                    Identifier name, SourceLoc nameLoc,
                    MutableArrayRef<TypeLoc> inherited,
                    GenericParamList *GenericParams);
  
    // Resolve ambiguity due to multiple base classes.
    using TypeDecl::getASTContext;
    using DeclContext::operator new;
    using TypeDecl::getDeclaredInterfaceType;
  
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_GenericTypeDecl &&
             D->getKind() <= DeclKind::Last_GenericTypeDecl;
    }
  };
  
  
  
  /// TypeAliasDecl - This is a declaration of a typealias, for example:
  ///
  ///    typealias Foo = Int
  ///
  /// TypeAliasDecl's always have 'MetatypeType' type.
  ///
  class TypeAliasDecl : public GenericTypeDecl {
    /// The location of the 'typealias' keyword
    SourceLoc TypeAliasLoc;
  
    /// The location of the equal '=' token
    SourceLoc EqualLoc;
  
    /// The location of the right-hand side of the typealias binding
    TypeLoc UnderlyingTy;
  
  public:
    TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name,
                  SourceLoc NameLoc, GenericParamList *GenericParams,
                  DeclContext *DC);
  
    SourceLoc getStartLoc() const { return TypeAliasLoc; }
    SourceRange getSourceRange() const;
  
    /// Returns the location of the equal '=' token
    SourceLoc getEqualLoc() const {
      return EqualLoc;
    }
  
    TypeLoc &getUnderlyingTypeLoc() {
      return UnderlyingTy;
    }
    const TypeLoc &getUnderlyingTypeLoc() const {
      return UnderlyingTy;
    }
  
    /// Set the underlying type, for deserialization and synthesized
    /// aliases.
    void setUnderlyingType(Type type);
  
    /// For generic typealiases, return the unbound generic type.
    UnboundGenericType *getUnboundGenericType() const;
  
    bool isCompatibilityAlias() const {
      return Bits.TypeAliasDecl.IsCompatibilityAlias;
    }
  
    void markAsCompatibilityAlias(bool newValue = true) {
      Bits.TypeAliasDecl.IsCompatibilityAlias = newValue;
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::TypeAlias;
    }
    static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::TypeAlias;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  };
  
  /// Abstract class describing generic type parameters and associated types,
  /// whose common purpose is to anchor the abstract type parameter and specify
  /// requirements for any corresponding type argument.
  class AbstractTypeParamDecl : public TypeDecl {
  protected:
    AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name,
                          SourceLoc NameLoc)
      : TypeDecl(kind, dc, name, NameLoc, { }) { }
  
  public:
    /// Return the superclass of the generic parameter.
    Type getSuperclass() const;
  
    /// Retrieve the set of protocols to which this abstract type
    /// parameter conforms.
    ArrayRef<ProtocolDecl *> getConformingProtocols() const;
  
    static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_AbstractTypeParamDecl &&
             D->getKind() <= DeclKind::Last_AbstractTypeParamDecl;
    }
  };
  
  /// A declaration of a generic type parameter.
  ///
  /// A generic type parameter introduces a new, named type parameter along
  /// with some set of requirements on any type argument used to realize this
  /// type parameter. The requirements involve conformances to specific
  /// protocols or inheritance from a specific class type.
  ///
  /// In the following example, 'T' is a generic type parameter with the
  /// requirement that the type argument conform to the 'Comparable' protocol.
  ///
  /// \code
  /// func min<T : Comparable>(x : T, y : T) -> T { ... }
  /// \endcode
  class GenericTypeParamDecl : public AbstractTypeParamDecl {
  public:
    static const unsigned InvalidDepth = 0xFFFF;
  
    /// Construct a new generic type parameter.
    ///
    /// \param dc The DeclContext in which the generic type parameter's owner
    /// occurs. This should later be overwritten with the actual declaration
    /// context that owns the type parameter.
    ///
    /// \param name The name of the generic parameter.
    /// \param nameLoc The location of the name.
    GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
                         unsigned depth, unsigned index);
  
    /// The depth of this generic type parameter, i.e., the number of outer
    /// levels of generic parameter lists that enclose this type parameter.
    ///
    /// \code
    /// struct X<T> {
    ///   func f<U>() { }
    /// }
    /// \endcode
    ///
    /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
    unsigned getDepth() const { return Bits.GenericTypeParamDecl.Depth; }
  
    /// Set the depth of this generic type parameter.
    ///
    /// \sa getDepth
    void setDepth(unsigned depth) {
      Bits.GenericTypeParamDecl.Depth = depth;
      assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation");
    }
  
    /// The index of this generic type parameter within its generic parameter
    /// list.
    ///
    /// \code
    /// struct X<T, U> {
    ///   func f<V>() { }
    /// }
    /// \endcode
    ///
    /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
    unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; }
  
    SourceLoc getStartLoc() const { return getNameLoc(); }
    SourceRange getSourceRange() const;
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::GenericTypeParam;
    }
  };
  
  /// A declaration of an associated type.
  ///
  /// An associated type introduces a new, named type in a protocol that
  /// can vary from one conforming type to the next. Associated types have a
  /// set of requirements to which the type that replaces it much realize,
  /// described via conformance to specific protocols, or inheritance from a
  /// specific class type.
  ///
  /// In the following example, 'Element' is an associated type with no
  /// requirements.
  ///
  /// \code
  /// protocol Enumerator {
  ///   typealias Element
  ///   func getNext() -> Element?
  /// }
  /// \endcode
  ///
  /// 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;
  
    /// The where clause attached to the associated type.
    TrailingWhereClause *TrailingWhere;
  
    LazyMemberLoader *Resolver = nullptr;
    uint64_t ResolverContextData;
  
  public:
    AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                       SourceLoc nameLoc, TypeLoc defaultDefinition,
                       TrailingWhereClause *trailingWhere);
    AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
                       SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
                       LazyMemberLoader *definitionResolver,
                       uint64_t resolverData);
  
    /// Get the protocol in which this associated type is declared.
    ProtocolDecl *getProtocol() const {
      return cast<ProtocolDecl>(getDeclContext());
    }
  
    /// Retrieve the default definition type.
    Type getDefaultDefinitionType() const {
      return getDefaultDefinitionLoc().getType();
    }
  
    TypeLoc &getDefaultDefinitionLoc();
    const TypeLoc &getDefaultDefinitionLoc() const {
      return const_cast<AssociatedTypeDecl *>(this)->getDefaultDefinitionLoc();
    }
  
    /// Retrieve the trailing where clause for this associated type, if any.
    TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; }
  
    /// Set the trailing where clause for this associated type.
    void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
      TrailingWhere = trailingWhereClause;
    }
  
    /// computeType - Compute the type (and declared type) of this associated
    /// type; can only be called after the alias type has been resolved.
    void computeType();
  
    /// Retrieve the associated type "anchor", which is the associated type
    /// declaration that will be used to describe this associated type in the
    /// ABI.
    ///
    /// The associated type "anchor" is an associated type that does not
    /// override any other associated type. There may be several such associated
    /// types; select one deterministically.
    AssociatedTypeDecl *getAssociatedTypeAnchor() const;
  
    /// Retrieve the (first) overridden associated type declaration, if any.
    AssociatedTypeDecl *getOverriddenDecl() const;
  
    /// Retrieve the set of associated types overridden by this associated
    /// type.
    ArrayRef<AssociatedTypeDecl *> getOverriddenDecls() const;
  
    /// Whether the overridden declarations have already been computed.
    bool overriddenDeclsComputed() const {
      return Bits.AssociatedTypeDecl.ComputedOverridden;
    }
  
    /// Record the set of overridden declarations.
    ///
    /// \returns the array recorded in the AST.
    ArrayRef<AssociatedTypeDecl *> setOverriddenDecls(
                                     ArrayRef<AssociatedTypeDecl *> overridden);
  
    SourceLoc getStartLoc() const { return KeywordLoc; }
    SourceRange getSourceRange() const;
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::AssociatedType;
    }
  };
  
  class MemberLookupTable;
  class ConformanceLookupTable;
  
  /// Kinds of 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_UnsafeMutableRawPointer,
    PTK_UnsafeRawPointer,
    PTK_UnsafeMutablePointer,
    PTK_UnsafePointer,
    PTK_AutoreleasingUnsafeMutablePointer,
  };
  
  static inline bool isRawPointerKind(PointerTypeKind PTK) {
    switch (PTK) {
    case PTK_UnsafeMutableRawPointer:
    case PTK_UnsafeRawPointer:
      return true;
    case PTK_UnsafeMutablePointer:
    case PTK_UnsafePointer:
    case PTK_AutoreleasingUnsafeMutablePointer:
      return false;
    }
  
    llvm_unreachable("Unhandled PointerTypeKind in switch.");
  }
  
  /// NominalTypeDecl - a declaration of a nominal type, like a struct.
  class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
    SourceRange Braces;
  
    /// \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;
    
    /// Prepare to traverse the list of extensions.
    void prepareExtensions();
  
    /// Retrieve the conformance loader (if any), and removing it in the
    /// same operation. The caller is responsible for loading the
    /// conformances.
    std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
      if (!Bits.NominalTypeDecl.HasLazyConformances)
        return { nullptr, 0 };
  
      return takeConformanceLoaderSlow();
    }
  
    /// Slow path for \c takeConformanceLoader().
    std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
  
    /// \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 Sorted) const;
  
  protected:
    Type DeclaredTy;
    Type DeclaredTyInContext;
    Type DeclaredInterfaceTy;
  
    NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
                    SourceLoc NameLoc,
                    MutableArrayRef<TypeLoc> inherited,
                    GenericParamList *GenericParams) :
      GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
      IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
    {
      setGenericParams(GenericParams);
      Bits.NominalTypeDecl.AddedImplicitInitializers = false;
      ExtensionGeneration = 0;
      Bits.NominalTypeDecl.HasLazyConformances = false;
      Bits.NominalTypeDecl.HasValidatedLayout = false;
    }
  
    friend class ProtocolType;
  
  public:
    using GenericTypeDecl::getASTContext;
  
    SourceRange getBraces() const { return Braces; }
    
    void setBraces(SourceRange braces) { Braces = braces; }
  
    /// \brief Should this declaration behave as if it must be accessed
    /// resiliently, even when we're building a non-resilient module?
    ///
    /// This is used for diagnostics, because we do not want a behavior
    /// change between builds with resilience enabled and disabled.
    bool isFormallyResilient() const;
  
    /// \brief Do we need to use resilient access patterns outside of this type's
    /// resilience domain?
    bool isResilient() const;
  
    /// \brief Do we need to use resilient access patterns when accessing this
    /// type from the given module?
    bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
  
    /// Determine whether we have already attempted to add any
    /// implicitly-defined initializers to this declaration.
    bool addedImplicitInitializers() const {
      return Bits.NominalTypeDecl.AddedImplicitInitializers;
    }
  
    /// Note that we have attempted to add implicit initializers.
    void setAddedImplicitInitializers() {
      Bits.NominalTypeDecl.AddedImplicitInitializers = true;
    }
  
    /// Determine whether we have already validated any members
    /// which affect layout.
    bool hasValidatedLayout() const {
      return Bits.NominalTypeDecl.HasValidatedLayout;
    }
  
    /// Note that we have attempted to validate any members
    /// which affect layout.
    void setHasValidatedLayout() {
      Bits.NominalTypeDecl.HasValidatedLayout = true;
    }
  
    /// Compute the type of this nominal type.
    void computeType();
  
    /// getDeclaredType - Retrieve the type declared by this entity, without
    /// any generic parameters bound if this is a generic type.
    Type getDeclaredType() const;
  
    /// getDeclaredTypeInContext - Retrieve the type declared by this entity, with
    /// context archetypes bound if this is a generic type.
    Type getDeclaredTypeInContext() const;
  
    /// getDeclaredInterfaceType - Retrieve the type declared by this entity, with
    /// generic parameters bound if this is a generic type.
    Type getDeclaredInterfaceType() 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.
    TinyPtrVector<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);
  
    void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);
  
    /// Is this the decl for Optional<T>?
    bool isOptionalDecl() const;
  
  private:
    /// Predicate used to filter StoredPropertyRange.
    struct ToStoredProperty {
      ToStoredProperty(bool skipInaccessible = false) :
          skipUserInaccessible(skipInaccessible) {}
      bool skipUserInaccessible;
      Optional<VarDecl *> operator()(Decl *decl) const;
    };
    
  public:
    /// A range for iterating the stored member variables of a structure.
    using StoredPropertyRange = OptionalTransformRange<DeclRange,
                                                       ToStoredProperty>;
  
    /// Return a collection of the stored member variables of this type.
    StoredPropertyRange getStoredProperties(bool skipInaccessible = false) const {
      return StoredPropertyRange(getMembers(),
                                 ToStoredProperty(skipInaccessible));
    }
  
  private:
    /// Predicate used to filter StoredPropertyRange.
    struct ToStoredPropertyOrMissingMemberPlaceholder {
      Optional<Decl *> operator()(Decl *decl) const;
    };
  
  public:
    /// A range for iterating the stored member variables of a structure.
    using StoredPropertyOrMissingMemberPlaceholderRange
      = OptionalTransformRange<DeclRange,
                               ToStoredPropertyOrMissingMemberPlaceholder>;
    
    /// Return a collection of the stored member variables of this type, along
    /// with placeholders for unimportable stored properties.
    StoredPropertyOrMissingMemberPlaceholderRange
    getStoredPropertiesAndMissingMemberPlaceholders() const {
      return StoredPropertyOrMissingMemberPlaceholderRange(getMembers(),
                               ToStoredPropertyOrMissingMemberPlaceholder());
    }
  
    // Implement isa/cast/dyncast/etc.
    static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_NominalTypeDecl &&
             D->getKind() <= DeclKind::Last_NominalTypeDecl;
    }
    static bool classof(const GenericTypeDecl *D) {
      return D->getKind() >= DeclKind::First_NominalTypeDecl &&
             D->getKind() <= DeclKind::Last_NominalTypeDecl;
    }
  
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const IterableDeclContext *C) {
      return C->getIterableContextKind()
               == IterableDeclContextKind::NominalTypeDecl;
    }
    static bool classof(const NominalTypeDecl *D) { return true; }
    static bool classof(const ExtensionDecl *D) { return false; }
  };
  
  /// \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 final : 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());
    }
  
    unsigned getNumElements() const {
      auto eltRange = getAllElements();
      return std::distance(eltRange.begin(), eltRange.end());
    }
  
    /// If this is an enum with two cases, return the other case. Otherwise,
    /// return nullptr.
    EnumElementDecl *getOppositeBinaryDecl(EnumElementDecl *decl) const {
      ElementRange range = getAllElements();
      auto iter = range.begin();
      if (iter == range.end())
        return nullptr;
      bool seenDecl = false;
      EnumElementDecl *result = nullptr;
      if (*iter == decl) {
        seenDecl = true;
      } else {
        result = *iter;
      }
  
      ++iter;
      if (iter == range.end())
        return nullptr;
      if (seenDecl) {
        assert(!result);
        result = *iter;
      } else {
        if (decl != *iter)
          return nullptr;
        seenDecl = true;
      }
      ++iter;
  
      // If we reach this point, we saw the decl we were looking for and one other
      // case. If we have any additional cases, then we do not have a binary enum.
      if (iter != range.end())
        return nullptr;
  
      // This is always true since we have already returned earlier nullptr if we
      // did not see the decl at all.
      assert(seenDecl);
      return result;
    }
  
    /// If this enum has a unique element, return it. A unique element can
    /// either hold a value or not, and the existence of one unique element does
    /// not imply the existence or non-existence of the opposite unique element.
    EnumElementDecl *getUniqueElement(bool hasValue) const;
  
    /// Return a range that iterates over all the cases of an enum.
    CaseRange getAllCases() const {
      return CaseRange(getMembers());
    }
  
    /// Insert all of the 'case' element declarations into a DenseSet.
    void getAllElements(llvm::DenseSet<EnumElementDecl*> &elements) const {
      for (auto elt : getAllElements())
        elements.insert(elt);
    }
    
    /// Retrieve the status of circularity checking for class inheritance.
    CircularityCheck getCircularityCheck() const {
      return static_cast<CircularityCheck>(Bits.EnumDecl.Circularity);
    }
    
    /// Record the current stage of circularity checking.
    void setCircularityCheck(CircularityCheck circularity) {
      Bits.EnumDecl.Circularity = static_cast<unsigned>(circularity);
    }
    
    // Implement isa/cast/dyncast/etc.
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Enum;
    }
    static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Enum;
    }
    static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Enum;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
    }
    
    /// Determine whether this enum declares a raw type in its inheritance clause.
    bool hasRawType() const {
      return (bool)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 none of the enum cases have associated values.
    ///
    /// Note that this is true for enums with absolutely no cases.
    bool hasOnlyCasesWithoutAssociatedValues() const;
  
    /// True if any of the enum cases have availability annotations.
    ///
    /// Note that this is false for enums with absolutely no cases.
    bool hasPotentiallyUnavailableCaseValue() const;
  
    /// True if the enum has cases.
    bool hasCases() const {
      return !getAllElements().empty();
    }
  
    /// True if the enum is marked 'indirect'.
    bool isIndirect() const {
      return getAttrs().hasAttribute<IndirectAttr>();
    }
  };
  
  /// StructDecl - This is the declaration of a struct, for example:
  ///
  ///    struct Complex { var R : Double, I : Double }
  ///
  /// The type of the decl itself is a MetatypeType; use getDeclaredType()
  /// to get the declared type ("Complex" in the above example).
  class StructDecl final : public NominalTypeDecl {
    SourceLoc StructLoc;
  
  public:
    StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
               MutableArrayRef<TypeLoc> Inherited,
               GenericParamList *GenericParams, DeclContext *DC);
  
    SourceLoc getStartLoc() const { return StructLoc; }
    SourceRange getSourceRange() const {
      return SourceRange(StructLoc, getBraces().End);
    }
  
    // Implement isa/cast/dyncast/etc.
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Struct;
    }
    static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Struct;
    }
    static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Struct;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
    }
  
    /// Does this struct contain unreferenceable storage, such as C fields that
    /// cannot be represented in Swift?
    bool hasUnreferenceableStorage() const {
      return Bits.StructDecl.HasUnreferenceableStorage;
    }
  
    void setHasUnreferenceableStorage(bool v) {
      Bits.StructDecl.HasUnreferenceableStorage = v;
    }
  };
  
  /// The kind of artificial main to generate for a class.
  enum class ArtificialMainKind : uint8_t {
    NSApplicationMain,
    UIApplicationMain,
  };
  
  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 final : 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(); }
  
    /// Retrieve the ClassDecl for the superclass of this class, or null if there
    /// is no superclass.
    ClassDecl *getSuperclassDecl() const;
  
    /// Set the superclass of this class.
    void setSuperclass(Type superclass);
  
    /// Retrieve the status of circularity checking for class inheritance.
    CircularityCheck getCircularityCheck() const {
      return static_cast<CircularityCheck>(Bits.ClassDecl.Circularity);
    }
  
    /// Record the current stage of circularity checking.
    void setCircularityCheck(CircularityCheck circularity) {
      Bits.ClassDecl.Circularity = static_cast<unsigned>(circularity);
    }
  
    //// Whether this class requires all of its stored properties to
    //// have initializers in the class definition.
    bool requiresStoredPropertyInits() const { 
      return Bits.ClassDecl.RequiresStoredPropertyInits;
    }
  
    /// Set whether this class requires all of its stored properties to
    /// have initializers in the class definition.
    void setRequiresStoredPropertyInits(bool requiresInits) {
      Bits.ClassDecl.RequiresStoredPropertyInits = requiresInits;
    }
  
    /// \see getForeignClassKind
    enum class ForeignKind : uint8_t {
      /// A normal Swift or Objective-C class.
      Normal = 0,
      /// An imported Core Foundation type. These are AnyObject-compatible but
      /// do not have runtime metadata.
      CFType,
      /// An imported Objective-C type whose class and metaclass symbols are not
      /// both available at link-time but can be accessed through the Objective-C
      /// runtime.
      RuntimeOnly
    };
  
    /// Whether this class is "foreign", meaning that it is implemented
    /// by a runtime that Swift does not have first-class integration
    /// with.  This generally means that:
    ///   - class data is either abstracted or cannot be made to
    ///     fit with Swift's metatype schema, and/or
    ///   - there is no facility for subclassing or adding polymorphic
    ///     methods to the class.
    ///
    /// We may find ourselves wanting to break this bit into more
    /// precise chunks later.
    ForeignKind getForeignClassKind() const {
      return static_cast<ForeignKind>(Bits.ClassDecl.RawForeignKind);
    }
    void setForeignClassKind(ForeignKind kind) {
      Bits.ClassDecl.RawForeignKind = static_cast<unsigned>(kind);
    }
  
    /// Returns true if this class is any kind of "foreign class".
    ///
    /// \see getForeignClassKind
    bool isForeign() const {
      return getForeignClassKind() != ForeignKind::Normal;
    }
  
    /// Returns true if the class has designated initializers that are not listed
    /// in its members.
    ///
    /// This can occur, for example, if the class is an Objective-C class with
    /// initializers that cannot be represented in Swift.
    bool hasMissingDesignatedInitializers() const;
  
    void setHasMissingDesignatedInitializers(bool newValue = true) {
      Bits.ClassDecl.HasMissingDesignatedInitializers = newValue;
    }
  
    /// Returns true if the class has missing members that require vtable entries.
    ///
    /// In this case, the class cannot be subclassed, because we cannot construct
    /// the vtable for the subclass.
    bool hasMissingVTableEntries() const;
  
    void setHasMissingVTableEntries(bool newValue = true) {
      Bits.ClassDecl.HasMissingVTableEntries = newValue;
    }
  
    /// Find a method of a class that overrides a given method.
    /// Return nullptr, if no such method exists.
    AbstractFunctionDecl *findOverridingDecl(
        const AbstractFunctionDecl *method) const;
  
    /// Find a method implementation which will be used when a given method
    /// is invoked on an instance of this class. This implementation may stem
    /// either from a class itself or its direct or indirect superclasses.
    AbstractFunctionDecl *findImplementingMethod(
        const AbstractFunctionDecl *method) const;
  
    /// 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 Bits.ClassDecl.HasDestructorDecl; }
  
    /// Set the 'has destructor' flag.
    void setHasDestructor() { Bits.ClassDecl.HasDestructorDecl = 1; }
    
    /// Retrieve the destructor for this class.
    DestructorDecl *getDestructor();
  
    /// Synthesize implicit, trivial destructor, add it to this ClassDecl
    /// and return it.
    void addImplicitDestructor();
  
    /// 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;
  
    /// The type of metaclass to use for a class.
    enum class MetaclassKind : uint8_t {
      ObjC,
      SwiftStub,
    };
  
    /// Determine which sort of metaclass to use for this class
    MetaclassKind getMetaclassKind() const;
  
    /// Retrieve the name to use for this class when interoperating with
    /// the Objective-C runtime.
    StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
  
    /// Returns the appropriate kind of entry point to generate for this class,
    /// based on its attributes.
    ///
    /// It is an error to call this on a class that does not have a
    /// *ApplicationMain attribute.
    ArtificialMainKind getArtificialMainKind() const;
  
    using NominalTypeDecl::lookupDirect;
  
    /// Look in this class and its extensions (but not any of its protocols or
    /// superclasses) for declarations with a given Objective-C selector.
    ///
    /// Note that this can find methods, initializers, deinitializers,
    /// getters, and setters.
    ///
    /// \param selector The Objective-C selector of the method we're
    /// looking for.
    ///
    /// \param isInstance Whether we are looking for an instance method
    /// (vs. a class method).
    MutableArrayRef<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
                                                         bool isInstance);
  
    /// Record the presence of an @objc method 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 GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Class;
    }
    static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Class;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
    }
    
    /// Returns true if the decl uses the Objective-C generics model.
    ///
    /// This is true of imported Objective-C classes.
    bool usesObjCGenericsModel() const {
      return isObjC() && hasClangNode() && isGenericContext();
    }
    
    /// True if the class is known to be implemented in Swift.
    bool hasKnownSwiftImplementation() const {
      return !hasClangNode();
    }
  };
  
  
  /// Describes whether a requirement refers to 'Self', for use in the
  /// is-inheritable and is-available-existential checks.
  struct SelfReferenceKind {
    bool result;
    bool parameter;
    bool requirement;
    bool other;
  
    /// The type does not refer to 'Self' at all.
    static SelfReferenceKind None() {
      return SelfReferenceKind(false, false, false, false);
    }
  
    /// The type refers to 'Self', but only as the result type of a method.
    static SelfReferenceKind Result() {
      return SelfReferenceKind(true, false, false, false);
    }
  
    /// The type refers to 'Self', but only as the parameter type of a method.
    static SelfReferenceKind Parameter() {
      return SelfReferenceKind(false, true, false, false);
    }
  
    /// The type refers to 'Self' within a same-type requiement.
    static SelfReferenceKind Requirement() {
      return SelfReferenceKind(false, false, true, false);
    }
  
    /// The type refers to 'Self' in a position that is invariant.
    static SelfReferenceKind Other() {
      return SelfReferenceKind(false, false, false, true);
    }
  
    SelfReferenceKind flip() const {
      return SelfReferenceKind(parameter, result, requirement, other);
    }
  
    SelfReferenceKind operator|=(SelfReferenceKind kind) {
      result |= kind.result;
      requirement |= kind.requirement;
      parameter |= kind.parameter;
      other |= kind.other;
      return *this;
    }
  
    operator bool() const {
      return result || parameter || requirement || other;
    }
  
  private:
    SelfReferenceKind(bool result, bool parameter, bool requirement, bool other)
      : result(result), parameter(parameter), requirement(requirement),
        other(other) { }
  };
  
  /// ProtocolDecl - A declaration of a protocol, for example:
  ///
  ///   protocol Drawable {
  ///     func draw()
  ///   }
  class ProtocolDecl final : public NominalTypeDecl {
    SourceLoc ProtocolLoc;
  
    /// The syntactic representation of the where clause in a protocol like
    /// `protocol ... where ... { ... }`.
    TrailingWhereClause *TrailingWhere;
  
    llvm::DenseMap<ValueDecl *, Witness> DefaultWitnesses;
  
    /// The generic signature representing exactly the new requirements introduced
    /// by this protocol.
    const Requirement *RequirementSignature = nullptr;
  
    bool requiresClassSlow();
  
    bool existentialConformsToSelfSlow();
  
    bool existentialTypeSupportedSlow(LazyResolver *resolver);
  
  public:
    ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
                 Identifier Name, MutableArrayRef<TypeLoc> Inherited,
                 TrailingWhereClause *TrailingWhere);
  
    using Decl::getASTContext;
  
    /// Retrieve the set of protocols inherited from this protocol.
    llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
  
    /// Retrieve the set of AssociatedTypeDecl members of this protocol; this
    /// saves loading the set of members in cases where there's no possibility of
    /// a protocol having nested types (ObjC protocols).
    llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() const;
  
    /// Walk all of the protocols inherited by this protocol, transitively,
    /// invoking the callback function for each protocol.
    ///
    /// \param fn The callback function that will be invoked for each inherited
    /// protocol. It can return \c Continue to continue the traversal,
    /// \c SkipChildren to avoid visiting the children of the given protocol
    /// but continue the search, and \c Stop to halt the search.
    ///
    /// \returns \c true if \c fn returned \c Stop for any protocol, \c false
    /// otherwise.
    bool walkInheritedProtocols(
                 llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const;
  
    /// \brief Determine whether this protocol inherits from the given ("super")
    /// protocol.
    bool inheritsFrom(const ProtocolDecl *Super) const;
    
    ProtocolType *getDeclaredType() const {
      return reinterpret_cast<ProtocolType *>(
        NominalTypeDecl::getDeclaredType().getPointer());
    }
    
    SourceLoc getStartLoc() const { return ProtocolLoc; }
    SourceRange getSourceRange() const {
      return SourceRange(ProtocolLoc, getBraces().End);
    }
  
    /// True if this protocol can only be conformed to by class types.
    bool requiresClass() const {
      if (Bits.ProtocolDecl.RequiresClassValid)
        return Bits.ProtocolDecl.RequiresClass;
  
      return const_cast<ProtocolDecl *>(this)->requiresClassSlow();
    }
  
    /// Specify that this protocol is class-bounded, e.g., because it was
    /// annotated with the 'class' keyword.
    void setRequiresClass(bool requiresClass = true) {
      Bits.ProtocolDecl.RequiresClassValid = true;
      Bits.ProtocolDecl.RequiresClass = requiresClass;
    }
  
    /// 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 (Bits.ProtocolDecl.ExistentialConformsToSelfValid)
        return Bits.ProtocolDecl.ExistentialConformsToSelf;
  
      return const_cast<ProtocolDecl *>(this)
               ->existentialConformsToSelfSlow();
    }
  
    /// Find direct Self references within the given requirement.
    ///
    /// \param allowCovariantParameters If true, 'Self' is assumed to be
    /// covariant anywhere; otherwise, only in the return type of the top-level
    /// function type.
    ///
    /// \param skipAssocTypes If true, associated types of 'Self' are ignored;
    /// otherwise, they count as an 'other' usage of 'Self'.
    SelfReferenceKind findProtocolSelfReferences(const ValueDecl *decl,
                                                 bool allowCovariantParameters,
                                                 bool skipAssocTypes) const;
  
    /// Determine whether we are allowed to refer to an existential type
    /// conforming to this protocol. This is only permitted if the type of
    /// the member does not contain any associated types, and does not
    /// contain 'Self' in 'parameter' or 'other' position.
    bool isAvailableInExistential(const ValueDecl *decl) const;
  
    /// Determine whether we are allowed to refer to an existential type
    /// conforming to this protocol. This is only permitted if the types of
    /// all the members do not contain any associated types, and do not
    /// contain 'Self' in 'parameter' or 'other' position.
    bool existentialTypeSupported(LazyResolver *resolver) const {
      if (Bits.ProtocolDecl.ExistentialTypeSupportedValid)
        return Bits.ProtocolDecl.ExistentialTypeSupported;
  
      return const_cast<ProtocolDecl *>(this)
               ->existentialTypeSupportedSlow(resolver);
    }
  
    /// Explicitly set the existentialTypeSupported flag, without computing
    /// it from members. Only called from deserialization, where the flag
    /// was stored in the serialized record.
    void setExistentialTypeSupported(bool supported) {
      Bits.ProtocolDecl.ExistentialTypeSupported = supported;
      Bits.ProtocolDecl.ExistentialTypeSupportedValid = true;
    }
  
    /// 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 (Bits.ProtocolDecl.KnownProtocol == 0)
        return None;
      return static_cast<KnownProtocolKind>(Bits.ProtocolDecl.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");
      Bits.ProtocolDecl.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>(Bits.ProtocolDecl.Circularity);
    }
  
    /// Record the current stage of circularity checking.
    void setCircularityCheck(CircularityCheck circularity) {
      Bits.ProtocolDecl.Circularity = static_cast<unsigned>(circularity);
    }
  
    /// Returns true if the protocol has requirements that are not listed in its
    /// members.
    ///
    /// This can occur, for example, if the protocol is an Objective-C protocol
    /// with requirements that cannot be represented in Swift.
    bool hasMissingRequirements() const {
      (void)getMembers();
      return Bits.ProtocolDecl.HasMissingRequirements;
    }
  
    void setHasMissingRequirements(bool newValue) {
      Bits.ProtocolDecl.HasMissingRequirements = newValue;
    }
  
    /// Returns the default witness for a requirement, or nullptr if there is
    /// no default.
    Witness getDefaultWitness(ValueDecl *requirement) const;
  
    /// Record the default witness for a requirement.
    void setDefaultWitness(ValueDecl *requirement, Witness witness);
  
    /// 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.
    GenericParamList *createGenericParams(DeclContext *dc);
  
    /// Create the generic parameters of this protocol if the haven't been
    /// created yet.
    void createGenericParamsIfMissing();
  
    /// Retrieve the trailing where clause on this protocol, if it exists.
    TrailingWhereClause *getTrailingWhereClause() const {
      return TrailingWhere;
    }
  
    /// Retrieve the requirements that describe this protocol.
    ///
    /// These are the requirements including any inherited protocols
    /// and conformances for associated types that are introduced in this
    /// protocol. Requirements implied via any other protocol (e.g., inherited
    /// protocols of the inherited protocols) are not mentioned. The conformance
    /// requirements listed here become entries in the witness table.
    ArrayRef<Requirement> getRequirementSignature() const {
      assert(isRequirementSignatureComputed() &&
             "getting requirement signature before computing it");
      return llvm::makeArrayRef(RequirementSignature,
                                Bits.ProtocolDecl.NumRequirementsInSignature);
    }
  
    /// Has the requirement signature been computed yet?
    bool isRequirementSignatureComputed() const {
      return RequirementSignature != nullptr;
    }
  
    void computeRequirementSignature();
  
    void setRequirementSignature(ArrayRef<Requirement> requirements);
  
    // Implement isa/cast/dyncast/etc.
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Protocol;
    }
    static bool classof(const GenericTypeDecl *D) {
      return D->getKind() == DeclKind::Protocol;
    }
    static bool classof(const NominalTypeDecl *D) {
      return D->getKind() == DeclKind::Protocol;
    }
    static bool classof(const DeclContext *C) {
      if (auto D = C->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    static bool classof(const IterableDeclContext *C) {
      auto NTD = dyn_cast<NominalTypeDecl>(C);
      return NTD && classof(NTD);
    }
  };
  
  // Note that the values of these enums line up with %select values in
  // diagnostics.
  enum class AccessorKind {
    /// \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 : uint8_t {
    /// \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 an AnyObject
    /// 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 : uint8_t {
    /// 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 : uint8_t {
    /// The decl is a VarDecl with its own backing storage; evaluate its
    /// address directly.
    Storage,
  
    /// The decl is a VarDecl with storage defined by a property behavior;
    /// this access may initialize or reassign the storage based on dataflow.
    BehaviorStorage,
  
    /// 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,
  };
  
  /// Information about a behavior instantiated by a storage declaration.
  ///
  /// TODO: Accessors, composed behaviors
  struct alignas(1 << 3) BehaviorRecord {
    // The behavior name.
    TypeRepr *ProtocolName;
    // The parameter expression, if any.
    Expr *Param;
    
    Optional<NormalProtocolConformance *> Conformance = None;
    // The 'value' property from the behavior protocol that provides the property
    // implementation.
    VarDecl *ValueDecl = nullptr;
    
    // Storage declaration and initializer for use by definite initialization.
    VarDecl *StorageDecl = nullptr;
    ConcreteDeclRef InitStorageDecl = nullptr;
    
    bool needsInitialization() const {
      assert((bool)StorageDecl == (bool)InitStorageDecl
             && "DI state not consistent");
      return StorageDecl != nullptr;
    }
    
    BehaviorRecord(TypeRepr *ProtocolName,
                   Expr *Param)
      : ProtocolName(ProtocolName), Param(Param)
    {}
    
    SourceLoc getLoc() const;
  };
  
  /// 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) When a stored property is accessed outside of the storage
      ///      declaration's resilience domain, when the owning type or
      ///      global variable 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 alignas(1 << 3) AddressorRecord {
      AccessorDecl *Address = nullptr;        // User-defined address accessor
      AccessorDecl *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,
                                 AccessorDecl *addressor, AccessorDecl *mutableAddressor);
  
    struct alignas(1 << 3) GetSetRecord {
      SourceRange Braces;
      AccessorDecl *Get = nullptr;       // User-defined getter
      AccessorDecl *Set = nullptr;       // User-defined setter
      AccessorDecl *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,
                               AccessorDecl *getter, AccessorDecl *setter,
                               AccessorDecl *materializeForSet);
    void configureSetRecord(GetSetRecord *getSetInfo,
                            AccessorDecl *setter,
                            AccessorDecl *materializeForSet);
  
    struct ObservingRecord : GetSetRecord {
      AccessorDecl *WillSet = nullptr;   // willSet(value):
      AccessorDecl *DidSet = nullptr;    // didSet:
    };
    void configureObservingRecord(ObservingRecord *record,
                                  AccessorDecl *willSet, AccessorDecl *didSet);
  
    llvm::PointerIntPair<GetSetRecord*, 3, OptionalEnum<AccessLevel>> GetSetInfo;
    llvm::PointerIntPair<BehaviorRecord*, 3, OptionalEnum<AccessLevel>>
      BehaviorInfo;
  
    ObservingRecord &getDidSetInfo() const {
      assert(hasObservers());
      return *static_cast<ObservingRecord*>(GetSetInfo.getPointer());
    }
    AddressorRecord &getAddressorInfo() const {
      assert(hasAddressors());
      return *GetSetInfo.getPointer()->getAddressors();
    }
  
    void setStorageKind(StorageKindTy K) {
      Bits.AbstractStorageDecl.StorageKind = unsigned(K);
    }
  
  protected:
    AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
                        SourceLoc NameLoc)
      : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
      Bits.AbstractStorageDecl.StorageKind = Stored;
      Bits.AbstractStorageDecl.IsGetterMutating = false;
      Bits.AbstractStorageDecl.IsSetterMutating = true;
      Bits.AbstractStorageDecl.Overridden = false;
    }
  public:
  
    /// \brief Should this declaration be treated as if annotated with transparent
    /// attribute.
    bool isTransparent() const;
  
    /// \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) Bits.AbstractStorageDecl.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 reading this storage requires the ability to
    /// modify the base value.
    bool isGetterMutating() const {
      return Bits.AbstractStorageDecl.IsGetterMutating;
    }
    void setIsGetterMutating(bool isMutating) {
      Bits.AbstractStorageDecl.IsGetterMutating = isMutating;
    }
    
    /// \brief Return true if modifying this storage requires the ability to
    /// modify the base value.
    bool isSetterMutating() const {
      return Bits.AbstractStorageDecl.IsSetterMutating;
    }
    void setIsSetterMutating(bool isMutating) {
      Bits.AbstractStorageDecl.IsSetterMutating = isMutating;
    }
  
    AccessorDecl *getAccessorFunction(AccessorKind accessor) const;
  
    /// \brief Push all of the accessor functions associated with this VarDecl
    /// onto `decls`.
    void getAllAccessorFunctions(SmallVectorImpl<Decl *> &decls) const;
  
    /// \brief Turn this into a computed variable, providing a getter and setter.
    void makeComputed(SourceLoc LBraceLoc, AccessorDecl *Get, AccessorDecl *Set,
                      AccessorDecl *MaterializeForSet, SourceLoc RBraceLoc);
  
    /// \brief Turn this into a computed object, providing a getter and a mutable
    /// addressor.
    void makeComputedWithMutableAddress(SourceLoc lbraceLoc,
                                        AccessorDecl *getter,
                                        AccessorDecl *setter,
                                        AccessorDecl *materializeForSet,
                                        AccessorDecl *mutableAddressor,
                                        SourceLoc rbraceLoc);
  
    /// \brief Add trivial accessors to this Stored or Addressed object.
    void addTrivialAccessors(AccessorDecl *Get, AccessorDecl *Set,
                             AccessorDecl *MaterializeForSet);
  
    /// \brief Turn this into a stored-with-observers var, providing the
    /// didSet/willSet specifiers.
    void makeStoredWithObservers(SourceLoc LBraceLoc, AccessorDecl *WillSet,
                                 AccessorDecl *DidSet, SourceLoc RBraceLoc);
  
    /// \brief Turn this into an inherited-with-observers var, providing
    /// the didSet/willSet specifiers.
    void makeInheritedWithObservers(SourceLoc LBraceLoc, AccessorDecl *WillSet,
                                    AccessorDecl *DidSet, SourceLoc RBraceLoc);
  
    /// \brief Turn this into an addressed var.
    void makeAddressed(SourceLoc LBraceLoc, AccessorDecl *Addressor,
                       AccessorDecl *MutableAddressor,
                       SourceLoc RBraceLoc);
  
    /// \brief Turn this into an addressed var with observing accessors.
    void makeAddressedWithObservers(SourceLoc LBraceLoc, AccessorDecl *Addressor,
                                    AccessorDecl *MutableAddressor,
                                    AccessorDecl *WillSet, AccessorDecl *DidSet,
                                    SourceLoc RBraceLoc);
  
    /// \brief Specify the synthesized get/set functions for a
    /// StoredWithObservers or AddressedWithObservers var.  This is used by Sema.
    void setObservingAccessors(AccessorDecl *Get, AccessorDecl *Set,
                               AccessorDecl *MaterializeForSet);
  
    /// \brief Add a setter to an existing Computed var.
    ///
    /// This should only be used by the ClangImporter.
    void setComputedSetter(AccessorDecl *Set);
  
    /// \brief Add a behavior to a property.
    void addBehavior(TypeRepr *Type, Expr *Param);
  
    /// \brief Set a materializeForSet accessor for this declaration.
    ///
    /// This should only be used by Sema.
    void setMaterializeForSetFunc(AccessorDecl *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.
    AccessorDecl *getGetter() const {
      if (auto info = GetSetInfo.getPointer())
        return info->Get;
      return nullptr;
    }
    
    /// \brief Retrieve the setter used to mutate the value of this variable.
    AccessorDecl *getSetter() const {
      if (auto info = GetSetInfo.getPointer())
        return info->Set;
      return nullptr;
    }
  
    AccessLevel getSetterFormalAccess() const {
      assert(hasAccess());
      assert(GetSetInfo.getInt().hasValue());
      return GetSetInfo.getInt().getValue();
    }
  
    void setSetterAccess(AccessLevel accessLevel) {
      assert(!GetSetInfo.getInt().hasValue());
      overwriteSetterAccess(accessLevel);
    }
  
    void overwriteSetterAccess(AccessLevel accessLevel);
  
    /// \brief Retrieve the materializeForSet function, if this
    /// declaration has one.
    AccessorDecl *getMaterializeForSetFunc() const {
      if (auto info = GetSetInfo.getPointer())
        return info->MaterializeForSet;
      return nullptr;
    }
  
    /// \brief Return the decl for the 'address' accessor if it
    /// exists; this is only valid on a declaration with addressors.
    AccessorDecl *getAddressor() const { return getAddressorInfo().Address; }
  
    /// \brief Return the decl for the 'mutableAddress' accessors if
    /// it exists; this is only valid on a declaration with addressors.
    AccessorDecl *getMutableAddressor() const {
      return getAddressorInfo().MutableAddress;
    }
  
    /// \brief Return the appropriate addressor for the given access kind.
    AccessorDecl *getAddressorForAccess(AccessKind accessKind) const {
      if (accessKind == AccessKind::Read)
        return getAddressor();
      return getMutableAddressor();
    }
    
    /// \brief Return the decl for the willSet specifier if it exists, this is
    /// only valid on a declaration with Observing storage.
    AccessorDecl *getWillSetFunc() const { return getDidSetInfo().WillSet; }
  
    /// \brief Return the decl for the didSet specifier if it exists, this is
    /// only valid on a declaration with Observing storage.
    AccessorDecl *getDidSetFunc() const { return getDidSetInfo().DidSet; }
  
    /// Given that this is an Objective-C property or subscript declaration,
    /// produce its getter selector.
    ObjCSelector
    getObjCGetterSelector(Identifier preferredName = Identifier()) const;
  
    /// Given that this is an Objective-C property or subscript declaration,
    /// produce its setter selector.
    ObjCSelector
    getObjCSetterSelector(Identifier preferredName = Identifier()) const;
  
    AbstractStorageDecl *getOverriddenDecl() const {
      return OverriddenDecl;
    }
    void setOverriddenDecl(AbstractStorageDecl *over) {
      // FIXME: Hack due to broken class circularity checking.
      if (over == this) return;
      OverriddenDecl = over;
      over->setIsOverridden();
    }
  
    /// The declaration has been overridden in the module
    ///
    /// Resolved during type checking
    void setIsOverridden() {
      Bits.AbstractStorageDecl.Overridden = true;
    }
  
    /// Whether the declaration is later overridden in the module
    ///
    /// Overrides are resolved during type checking; only query this field after
    /// the whole module has been checked
    bool isOverridden() const { return Bits.AbstractStorageDecl.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;
  
    /// \brief Should this declaration behave as if it must be accessed
    /// resiliently, even when we're building a non-resilient module?
    ///
    /// This is used for diagnostics, because we do not want a behavior
    /// change between builds with resilience enabled and disabled.
    bool isFormallyResilient() const;
  
    /// \brief Do we need to use resilient access patterns outside of this
    /// property's resilience domain?
    bool isResilient() const;
  
    /// \brief Do we need to use resilient access patterns when accessing this
    /// property from the given module?
    bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
  
    /// Returns the interface type of elements of storage represented by this
    /// declaration.
    ///
    /// For variables, this is the type of the variable itself.
    /// For subscripts, this is the type of the subscript element.
    Type getStorageInterfaceType() const;
  
    /// Does the storage use a behavior?
    bool hasBehavior() const {
      return BehaviorInfo.getPointer() != nullptr;
    }
    
    /// Does the storage use a behavior, and require definite initialization
    /// analysis.
    bool hasBehaviorNeedingInitialization() const {
      if (auto behavior = getBehavior()) {
        return behavior->needsInitialization();
      }
      return false;
    }
    
    /// Get the behavior info.
    const BehaviorRecord *getBehavior() const {
      return BehaviorInfo.getPointer();
    }
    BehaviorRecord *getMutableBehavior() {
      return BehaviorInfo.getPointer();
    }
  
    // 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 {
  public:
    enum class Specifier : uint8_t {
      // For Var Decls
  
      Let = 0,
      Var = 1,
  
      // For Param Decls
  
      Default = Let,
      InOut = 2,
      Shared = 3,
      Owned = 4,
    };
  
  protected:
    llvm::PointerUnion<PatternBindingDecl*, Stmt*> ParentPattern;
  
    VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
            SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC)
      : AbstractStorageDecl(Kind, DC, Name, NameLoc)
    {
      Bits.VarDecl.IsStatic = IsStatic;
      Bits.VarDecl.Specifier = static_cast<unsigned>(Sp);
      Bits.VarDecl.IsCaptureList = IsCaptureList;
      Bits.VarDecl.IsDebuggerVar = false;
      Bits.VarDecl.HasNonPatternBindingInit = false;
      setType(Ty);
    }
  
    /// This is the type specified, including location information.
    TypeLoc typeLoc;
  
    Type typeInContext;
  
  public:
    VarDecl(bool IsStatic, Specifier Sp, bool IsCaptureList, SourceLoc NameLoc,
            Identifier Name, Type Ty, DeclContext *DC)
      : VarDecl(DeclKind::Var, IsStatic, Sp, IsCaptureList, NameLoc, Name, Ty,
                DC) {}
  
    SourceRange getSourceRange() const;
  
    Identifier getName() const { return getFullName().getBaseIdentifier(); }
  
    /// Returns the string for the base name, or "_" if this is unnamed.
    StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
    }
  
    TypeLoc &getTypeLoc() { return typeLoc; }
    TypeLoc getTypeLoc() const { return typeLoc; }
  
    bool hasType() const {
      // We have a type if either the type has been computed already or if
      // this is a deserialized declaration with an interface type.
      return !typeInContext.isNull();
    }
  
    /// Get the type of the variable within its context. If the context is generic,
    /// this will use archetypes.
    Type getType() const;
  
    /// Set the type of the variable within its context.
    void setType(Type t);
  
    void markInvalid();
  
    /// Retrieve the source range of the variable type, or an invalid range if the
    /// variable's type is not explicitly written in the source.
    ///
    /// Only for use in diagnostics.  It is not always possible to always
    /// precisely point to the variable type because of type aliases.
    SourceRange getTypeSourceRangeForDiagnostics() const;
  
    /// \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.  However, recall
    /// that the Pattern may be involved in initializing more than just this one
    /// vardecl.  For example, if this is a VarDecl for "x", the pattern may be
    /// "(x, y)" and the initializer on the PatternBindingDecl may be "(1,2)" or
    /// "foo()".
    ///
    /// If this has no parent pattern binding decl or statement associated, it
    /// returns null.
    ///
    Pattern *getParentPattern() const;
    
    /// Return the statement that owns the pattern associated with this VarDecl,
    /// if one exists.
    Stmt *getParentPatternStmt() const {
      return ParentPattern.dyn_cast<Stmt*>();
    }
    void setParentPatternStmt(Stmt *S) {
      ParentPattern = S;
    }
  
    /// Return the initializer involved in this VarDecl.  Recall that the
    /// initializer may be involved in initializing more than just this one
    /// vardecl though.  For example, if this is a VarDecl for "x", the pattern
    /// may be "(x, y)" and the initializer on the PatternBindingDecl may be
    /// "(1,2)" or "foo()".
    ///
    /// If this has no parent pattern binding decl associated, or if that pattern
    /// binding has no initial value, this returns null.
    ///
    Expr *getParentInitializer() const {
      if (auto *PBD = getParentPatternBinding())
        return PBD->getPatternEntryForVarDecl(this).getInit();
      return nullptr;
    }
  
    VarDecl *getOverriddenDecl() const {
      return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
    }
  
    /// Determine whether this declaration is an anonymous closure parameter.
    bool isAnonClosureParam() const;
  
    /// Return the raw specifier value for this property or parameter.
    Specifier getSpecifier() const {
      return static_cast<Specifier>(Bits.VarDecl.Specifier);
    }
    void setSpecifier(Specifier Spec) {
      Bits.VarDecl.Specifier = static_cast<unsigned>(Spec);
    }
    
    /// Is the type of this parameter 'inout'?
    ///
    /// FIXME(Remove InOut): This is only valid on ParamDecls but multiple parts
    /// of the compiler check ParamDecls and VarDecls along the same paths.
    bool isInOut() const {
      // FIXME: Re-enable this assertion and fix callers.
  //    assert((getKind() == DeclKind::Param) && "querying 'inout' on var decl?");
      return getSpecifier() == Specifier::InOut;
    }
    
    
    /// Is this a type ('static') variable?
    bool isStatic() const { return Bits.VarDecl.IsStatic; }
    void setStatic(bool IsStatic) { Bits.VarDecl.IsStatic = IsStatic; }
  
    /// \returns the way 'static'/'class' should be spelled for this declaration.
    StaticSpellingKind getCorrectStaticSpelling() const;
  
    bool isImmutable() const {
      switch (getSpecifier()) {
      case Specifier::Let:
      case Specifier::Shared:
      case Specifier::Owned:
        return true;
      case Specifier::Var:
      case Specifier::InOut:
        return false;
      }
    }
    /// Is this an immutable 'let' property?
    bool isLet() const { return getSpecifier() == Specifier::Let; }
    /// Is this an immutable 'shared' property?
    bool isShared() const { return getSpecifier() == Specifier::Shared; }
    /// Is this an immutable 'owned' property?
    bool isOwned() const { return getSpecifier() == Specifier::Owned; }
  
    ValueOwnership getValueOwnership() const {
      switch (getSpecifier()) {
      case Specifier::Let:
        return ValueOwnership::Default;
      case Specifier::Var:
        return ValueOwnership::Default;
      case Specifier::InOut:
        return ValueOwnership::InOut;
      case Specifier::Shared:
        return ValueOwnership::Shared;
      case Specifier::Owned:
        return ValueOwnership::Owned;
      }
    }
  
    /// Is this an element in a capture list?
    bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
  
    /// Return true if this vardecl has an initial value bound to it in a way
    /// that isn't represented in the AST with an initializer in the pattern
    /// binding.  This happens in cases like "for i in ...", switch cases, etc.
    bool hasNonPatternBindingInit() const {
      return Bits.VarDecl.HasNonPatternBindingInit;
    }
    void setHasNonPatternBindingInit(bool V = true) {
      Bits.VarDecl.HasNonPatternBindingInit = V;
    }
    
    /// Is this a special debugger variable?
    bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
    void setDebuggerVar(bool IsDebuggerVar) {
      Bits.VarDecl.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 isSelfParameter() 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;
    SourceLoc SpecifierLoc;
  
    struct StoredDefaultArgument {
      Expr *DefaultArg = nullptr;
      Initializer *InitContext = nullptr;
    };
  
    /// The default value, if any, along with whether this is varargs.
    llvm::PointerIntPair<StoredDefaultArgument *, 1> DefaultValueAndIsVariadic;
    
  public:
    ParamDecl(VarDecl::Specifier specifier,
              SourceLoc specifierLoc, SourceLoc argumentNameLoc,
              Identifier argumentName, SourceLoc parameterNameLoc,
              Identifier parameterName, Type ty, DeclContext *dc);
  
    /// Clone constructor, allocates a new ParamDecl identical to the first.
    /// Intentionally not defined as a typical copy constructor to avoid
    /// accidental copies.
    ParamDecl(ParamDecl *PD, bool withTypes);
    
    /// 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; }
    
    /// Retrieve the parameter type flags corresponding to the declaration of
    /// this parameter's argument type.
    ParameterTypeFlags getParameterFlags() const;
    
    SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
      
    bool isTypeLocImplicit() const { return Bits.ParamDecl.IsTypeLocImplicit; }
    void setIsTypeLocImplicit(bool val) { Bits.ParamDecl.IsTypeLocImplicit = val; }
    
    DefaultArgumentKind getDefaultArgumentKind() const {
      return static_cast<DefaultArgumentKind>(Bits.ParamDecl.defaultArgumentKind);
    }
    bool isDefaultArgument() const {
      return getDefaultArgumentKind() != DefaultArgumentKind::None;
    }
    void setDefaultArgumentKind(DefaultArgumentKind K) {
      Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
    }
    
    Expr *getDefaultValue() const {
      if (auto stored = DefaultValueAndIsVariadic.getPointer())
        return stored->DefaultArg;
      return nullptr;
    }
  
    void setDefaultValue(Expr *E);
  
    Initializer *getDefaultArgumentInitContext() const {
      if (auto stored = DefaultValueAndIsVariadic.getPointer())
        return stored->InitContext;
      return nullptr;
    }
  
    void setDefaultArgumentInitContext(Initializer *initContext);
  
    /// Whether or not this parameter is varargs.
    bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); }
    void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);}
    
    /// Remove the type of this varargs element designator, without the array
    /// type wrapping it.  A parameter like "Int..." will have formal parameter
    /// type of "[Int]" and this returns "Int".
    static Type getVarargBaseTy(Type VarArgT);
    
    /// Remove the type of this varargs element designator, without the array
    /// type wrapping it.
    Type getVarargBaseTy() const {
      assert(isVariadic());
      return getVarargBaseTy(getInterfaceType());
    }
    
    SourceRange getSourceRange() const;
  
    /// Create an implicit 'self' decl for a method in the specified decl context.
    /// If 'static' is true, then this is self for a static method in the type.
    ///
    /// Note that this decl is created, but it is returned with an incorrect
    /// DeclContext that needs to be set correctly.  This is automatically handled
    /// when a function is created with this as part of its argument list.
    /// For a generic context, this also gives the parameter an unbound generic
    /// type with the expectation that type-checking will fill in the context
    /// generic parameters.
    static ParamDecl *createUnboundSelf(SourceLoc loc, DeclContext *DC);
  
    /// Create an implicit 'self' decl for a method in the specified decl context.
    /// If 'static' is true, then this is self for a static method in the type.
    ///
    /// Note that this decl is created, but it is returned with an incorrect
    /// DeclContext that needs to be set correctly.  This is automatically handled
    /// when a function is created with this as part of its argument list.
    static ParamDecl *createSelf(SourceLoc loc, DeclContext *DC,
                                 bool isStatic = false,
                                 bool isInOut = false);
  
    // 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 GenericContext, public AbstractStorageDecl {
    SourceLoc ArrowLoc;
    ParameterList *Indices;
    TypeLoc ElementTy;
  
  public:
    SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices,
                  SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                  GenericParamList *GenericParams)
      : GenericContext(DeclContextKind::SubscriptDecl, Parent),
        AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
        ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
      setIndices(Indices);
      setGenericParams(GenericParams);
    }
    
    SourceLoc getSubscriptLoc() const { return getNameLoc(); }
    SourceLoc getStartLoc() const { return getSubscriptLoc(); }
    SourceRange getSourceRange() const;
    SourceRange getSignatureSourceRange() const;
  
    /// \brief Retrieve the indices for this subscript operation.
    ParameterList *getIndices() { return Indices; }
    const ParameterList *getIndices() const { return Indices; }
    void setIndices(ParameterList *p);
  
    /// Retrieve the interface type of the indices.
    Type getIndicesInterfaceType() const;
  
    /// \brief Retrieve the type of the element referenced by a subscript
    /// operation.
    Type getElementInterfaceType() const;
    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() const;
  
    SubscriptDecl *getOverriddenDecl() const {
      return cast_or_null<SubscriptDecl>(
                                    AbstractStorageDecl::getOverriddenDecl());
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Subscript;
    }
    
    static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  
    using DeclContext::operator new;
    using Decl::getASTContext;
  };
  
  /// Encodes imported-as-member status for C functions that get imported
  /// as methods.
  class ImportAsMemberStatus {
    friend class AbstractFunctionDecl;
  
    // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
    // index of n
    uint8_t rawValue;
  
  public:
    ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {}
  
    uint8_t getRawValue() const { return rawValue; }
  
    bool isImportAsMember() const { return rawValue != 0; }
    bool isInstance() const { return rawValue >= 2; }
    bool isStatic() const { return rawValue == 1; }
    uint8_t getSelfIndex() const {
      assert(isInstance() && "not set");
      return rawValue - 2;
    }
    void setStatic() {
      assert(!isStatic() && "already set");
      rawValue = 1;
    }
    void setSelfIndex(uint8_t idx) {
      assert(!isImportAsMember() && "already set");
      assert(idx <= UINT8_MAX-2 && "out of bounds");
      rawValue = idx + 2;
    }
  };
  
  /// \brief Base class for function-like declarations.
  class AbstractFunctionDecl : public GenericContext, public ValueDecl {
  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(Bits.AbstractFunctionDecl.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;
    };
  
    CaptureInfo Captures;
  
    /// Location of the 'throws' token.
    SourceLoc ThrowsLoc;
  
    AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                         SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                         unsigned NumParameterLists,
                         GenericParamList *GenericParams)
        : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
          ValueDecl(Kind, Parent, Name, NameLoc),
          Body(nullptr), ThrowsLoc(ThrowsLoc) {
      setBodyKind(BodyKind::None);
      setGenericParams(GenericParams);
      Bits.AbstractFunctionDecl.NumParameterLists = NumParameterLists;
      Bits.AbstractFunctionDecl.Overridden = false;
      Bits.AbstractFunctionDecl.Throws = Throws;
      Bits.AbstractFunctionDecl.NeedsNewVTableEntry = false;
      Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = false;
      Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion =
          unsigned(ResilienceExpansion::Maximal);
  
      // Verify no bitfield truncation.
      assert(Bits.AbstractFunctionDecl.NumParameterLists == NumParameterLists);
    }
  
    void setBodyKind(BodyKind K) {
      Bits.AbstractFunctionDecl.BodyKind = unsigned(K);
    }
  
  public:
    /// Returns the string for the base name, or "_" if this is unnamed.
    StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
    }
  
    /// \brief Should this declaration be treated as if annotated with transparent
    /// attribute.
    bool isTransparent() const;
  
    // Expose our import as member status
    ImportAsMemberStatus getImportAsMemberStatus() const {
      return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus);
    }
    bool isImportAsMember() const {
      return getImportAsMemberStatus().isImportAsMember();
    }
    bool isImportAsInstanceMember() const {
      return getImportAsMemberStatus().isInstance();
    }
    bool isImportAsStaticMember() const {
      return getImportAsMemberStatus().isStatic();
    }
    uint8_t getSelfIndex() const {
      return getImportAsMemberStatus().getSelfIndex();
    }
  
    void setImportAsStaticMember() {
      auto newValue = getImportAsMemberStatus();
      newValue.setStatic();
      Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
    }
    void setSelfIndex(uint8_t idx) {
      auto newValue = getImportAsMemberStatus();
      newValue.setSelfIndex(idx);
      Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
    }
  
  public:
    /// Retrieve the location of the 'throws' keyword, if present.
    SourceLoc getThrowsLoc() const { return ThrowsLoc; }
  
    /// Returns true if the function body throws.
    bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }
  
    // FIXME: Hack that provides names with keyword arguments for accessors.
    DeclName getEffectiveFullName() const;
  
    /// Returns true if the function has a body written in the source file.
    ///
    /// Note that a true return value does not imply that the body was actually
    /// parsed.
    bool hasBody() const {
      return getBodyKind() != BodyKind::None;
    }
  
    /// 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 &&
             "cannot set a body if it was skipped");
  
      Body = S;
      setBodyKind(NewBodyKind);
    }
  
    /// \brief Note that the body was skipped for this function.  Function body
    /// cannot 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;
    }
  
    void setNeedsNewVTableEntry(bool value) {
      Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = true;
      Bits.AbstractFunctionDecl.NeedsNewVTableEntry = value;
    }
  
    bool needsNewVTableEntry() const {
      if (!Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry)
        const_cast<AbstractFunctionDecl *>(this)->computeNeedsNewVTableEntry();
      return Bits.AbstractFunctionDecl.NeedsNewVTableEntry;
    }
  
  private:
    void computeNeedsNewVTableEntry();
  
  public:
    /// 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(DeclName preferredName = DeclName()) 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 an argument is an API name by default
    /// depending on the function context.
    bool argumentNameIsAPIByDefault() const;
  
    /// \brief Returns the "natural" number of argument clauses taken by this
    /// function.  This value is one for free-standing functions, and two for
    /// methods.
    unsigned getNumParameterLists() const {
      return Bits.AbstractFunctionDecl.NumParameterLists;
    }
  
    /// \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<ParameterList *> getParameterLists();
    ArrayRef<const ParameterList *> getParameterLists() const {
      auto paramLists =
          const_cast<AbstractFunctionDecl *>(this)->getParameterLists();
      return ArrayRef<const ParameterList *>(paramLists.data(),paramLists.size());
    }
    ParameterList *getParameterList(unsigned i) {
      return getParameterLists()[i];
    }
    const ParameterList *getParameterList(unsigned i) const {
      return getParameterLists()[i];
    }
  
    /// \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.
    const ParamDecl *getImplicitSelfDecl() const {
      return const_cast<AbstractFunctionDecl*>(this)->getImplicitSelfDecl();
    }
    ParamDecl *getImplicitSelfDecl();
  
    /// Retrieve the declaration that this method overrides, if any.
    AbstractFunctionDecl *getOverriddenDecl() const;
  
    /// Returns true if a function declaration overrides a given
    /// method from its direct or indirect superclass.
    bool isOverridingDecl(const AbstractFunctionDecl *method) const;
  
    /// Whether the declaration is later overridden in the module
    ///
    /// Overrides are resolved during type checking; only query this field after
    /// the whole module has been checked
    bool isOverridden() const { return Bits.AbstractFunctionDecl.Overridden; }
  
    /// The declaration has been overridden in the module
    ///
    /// Resolved during type checking
    void setIsOverridden() { Bits.AbstractFunctionDecl.Overridden = true; }
  
    /// The ResilienceExpansion for default arguments.
    ///
    /// In Swift 4 mode, default argument expressions are serialized, and must
    /// obey the restrictions imposed upon inlineable function bodies.
    ResilienceExpansion getDefaultArgumentResilienceExpansion() const {
      return ResilienceExpansion(
          Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion);
    }
  
    /// Set the ResilienceExpansion for default arguments.
    void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) {
      Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion =
          unsigned(expansion);
    }
  
    /// Set information about the foreign error convention used by this
    /// declaration.
    void setForeignErrorConvention(const ForeignErrorConvention &convention);
  
    /// Get information about the foreign error convention used by this
    /// declaration, given that it is @objc and 'throws'.
    Optional<ForeignErrorConvention> getForeignErrorConvention() const;
  
    /// If this is a foreign C function imported as a method, get the index of
    /// the foreign parameter imported as `self`. If the function is imported
    /// as a static method, `-1` is returned to represent the `self` parameter
    /// being dropped altogether. `None` is returned for a normal function
    /// or method.
    Optional<int> getForeignFunctionAsMethodSelfParameterIndex() const;
    
    static bool classof(const Decl *D) {
      return D->getKind() >= DeclKind::First_AbstractFunctionDecl &&
             D->getKind() <= DeclKind::Last_AbstractFunctionDecl;
    }
  
    static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
    
    /// True if the declaration is forced to be statically dispatched.
    bool hasForcedStaticDispatch() const;
  
    /// Get the interface type of this decl and remove the Self context.
    Type getMethodInterfaceType() const;
  
    using DeclContext::operator new;
    using Decl::getASTContext;
  };
  
  class OperatorDecl;
  
  /// Note: These align with '%select's in diagnostics.
  enum class SelfAccessKind : uint8_t {
    NonMutating = 0,
    Mutating    = 1,
    __Consuming = 2,
  };
    
  /// 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.
  
    TypeLoc FnRetType;
  
    /// \brief If this FuncDecl is an accessor for a property, this indicates
    /// which property and what kind of accessor.
    llvm::PointerUnion<FuncDecl *, BehaviorRecord *>
      OverriddenOrBehaviorParamDecl;
    OperatorDecl *Operator;
  
  protected:
    ParameterList **getParameterListBuffer(); // defined inline below
    ParameterList * const *getParameterListBuffer() const {
      return const_cast<FuncDecl*>(this)->getParameterListBuffer();
    }
  
    FuncDecl(DeclKind Kind,
             SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
             SourceLoc FuncLoc,
             DeclName Name, SourceLoc NameLoc,
             bool Throws, SourceLoc ThrowsLoc,
             unsigned NumParameterLists,
             GenericParamList *GenericParams, DeclContext *Parent)
      : AbstractFunctionDecl(Kind, Parent,
                             Name, NameLoc,
                             Throws, ThrowsLoc,
                             NumParameterLists, GenericParams),
        StaticLoc(StaticLoc), FuncLoc(FuncLoc),
        OverriddenOrBehaviorParamDecl(),
        Operator(nullptr) {
      Bits.FuncDecl.IsStatic =
        StaticLoc.isValid() || StaticSpelling != StaticSpellingKind::None;
      Bits.FuncDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);
      assert(NumParameterLists > 0 && "Must have at least an empty tuple arg");
  
      Bits.FuncDecl.HasDynamicSelf = false;
      Bits.FuncDecl.ForcedStaticDispatch = false;
      Bits.FuncDecl.SelfAccess = static_cast<unsigned>(SelfAccessKind::NonMutating);
    }
  
  private:
    static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
                                StaticSpellingKind StaticSpelling,
                                SourceLoc FuncLoc,
                                DeclName Name, SourceLoc NameLoc,
                                bool Throws, SourceLoc ThrowsLoc,
                                GenericParamList *GenericParams,
                                unsigned NumParameterLists,
                                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,
                                        bool Throws, SourceLoc ThrowsLoc,
                                        GenericParamList *GenericParams,
                                        unsigned NumParameterLists,
                                        DeclContext *Parent);
  
    static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
                            StaticSpellingKind StaticSpelling,
                            SourceLoc FuncLoc,
                            DeclName Name, SourceLoc NameLoc,
                            bool Throws, SourceLoc ThrowsLoc,
                            GenericParamList *GenericParams,
                            ArrayRef<ParameterList *> ParameterLists,
                            TypeLoc FnRetType, DeclContext *Parent,
                            ClangNode ClangN = ClangNode());
  
    Identifier getName() const { return getFullName().getBaseIdentifier(); }
  
    bool isStatic() const {
      return Bits.FuncDecl.IsStatic;
    }
    /// \returns the way 'static'/'class' was spelled in the source.
    StaticSpellingKind getStaticSpelling() const {
      return static_cast<StaticSpellingKind>(Bits.FuncDecl.StaticSpelling);
    }
    /// \returns the way 'static'/'class' should be spelled for this declaration.
    StaticSpellingKind getCorrectStaticSpelling() const;
    void setStatic(bool IsStatic = true) {
      Bits.FuncDecl.IsStatic = IsStatic;
    }
        
    bool isMutating() const {
      return getSelfAccessKind() == SelfAccessKind::Mutating;
    }
    bool isNonMutating() const {
      return getSelfAccessKind() == SelfAccessKind::NonMutating;
    }
    bool isConsuming() const {
      return getSelfAccessKind() == SelfAccessKind::__Consuming;
    }
  
    TypeLoc getReturnTypeLoc() const {
      return FnRetType;
    }
    
    SelfAccessKind getSelfAccessKind() const {
      return static_cast<SelfAccessKind>(Bits.FuncDecl.SelfAccess);
    }
    void setSelfAccessKind(SelfAccessKind mod) {
      Bits.FuncDecl.SelfAccess = static_cast<unsigned>(mod);
    }
        
    /// \brief Returns the parameter lists(s) for the function definition.
    ///
    /// The number of "top-level" elements will match the number of argument names
    /// in the compound name of the function or constructor.
    MutableArrayRef<ParameterList *> getParameterLists() {
      return {getParameterListBuffer(), getNumParameterLists()};
    }
    ArrayRef<const ParameterList *> getParameterLists() const {
      return {getParameterListBuffer(), getNumParameterLists()};
    }
    ParameterList *getParameterList(unsigned i) {
      return getParameterLists()[i];
    }
    const ParameterList *getParameterList(unsigned i) const {
      return getParameterLists()[i];
    }
    
    /// \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<ParameterList *> ParameterLists,
                                  TypeLoc FnRetType);
  
    SourceLoc getStaticLoc() const { return StaticLoc; }
    SourceLoc getFuncLoc() const { return FuncLoc; }
  
    SourceLoc getStartLoc() const {
      return StaticLoc.isValid() && !isa<AccessorDecl>(this)
                ? StaticLoc : FuncLoc;
    }
    SourceRange getSourceRange() const;
  
    TypeLoc &getBodyResultTypeLoc() { return FnRetType; }
    const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; }
  
    /// Retrieve the result interface type of this function.
    Type getResultInterfaceType() const;
  
    /// isUnaryOperator - Determine whether this is a unary operator
    /// implementation.  This check is a syntactic rather than type-based check,
    /// which looks at the number of parameters specified, in order to allow
    /// for the definition of unary operators on tuples, as in:
    ///
    ///   prefix func + (param : (a:Int, b:Int))
    ///
    /// This also allows the unary-operator-ness of a func decl to be determined
    /// prior to type checking.
    bool isUnaryOperator() const;
    
    /// isBinaryOperator - Determine whether this is a binary operator
    /// implementation.  This check is a syntactic rather than type-based check,
    /// which looks at the number of parameters specified, in order to allow
    /// distinguishing a binary operator from a unary operator on tuples, as in:
    ///
    ///   prefix func + (_:(a:Int, b:Int)) // unary operator +(1,2)
    ///   infix func  + (a:Int, b:Int)     // binary operator 1 + 2
    ///
    /// This also allows the binary-operator-ness of a func decl to be determined
    /// prior to type checking.
    bool isBinaryOperator() const;
    
    /// Determine whether this function has a dynamic \c Self return
    /// type.
    bool hasDynamicSelf() const { return Bits.FuncDecl.HasDynamicSelf; }
  
    /// Set whether this function has a dynamic \c Self return or not.
    void setDynamicSelf(bool hasDynamicSelf) { 
      Bits.FuncDecl.HasDynamicSelf = hasDynamicSelf;
    }
  
    void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
      return getCaptureInfo().getLocalCaptures(Result);
    }
    
    /// Get the supertype method this method overrides, if any.
    FuncDecl *getOverriddenDecl() const {
      return OverriddenOrBehaviorParamDecl.dyn_cast<FuncDecl *>();
    }
    void setOverriddenDecl(FuncDecl *over) {
      // FIXME: Hack due to broken class circularity checking.
      if (over == this) return;
  
      // A function cannot be an override if it is also a derived global decl
      // (since derived decls are at global scope).
      assert((!OverriddenOrBehaviorParamDecl
              || OverriddenOrBehaviorParamDecl.get<FuncDecl*>() == over)
           && "function can only be one of override, derived, or behavior param");
      OverriddenOrBehaviorParamDecl = over;
      over->setIsOverridden();
    }
    
    /// Get the property behavior this function serves as a parameter for, if
    /// any.
    BehaviorRecord *getParamBehavior() const {
      return OverriddenOrBehaviorParamDecl
        .dyn_cast<BehaviorRecord *>();
    }
    
    void setParamBehavior(BehaviorRecord *behavior) {
      // Behavior param blocks cannot be overrides or derived.
      assert((!OverriddenOrBehaviorParamDecl
              || OverriddenOrBehaviorParamDecl.is<BehaviorRecord *>())
           && "function can only be one of override, derived, or behavior param");
      OverriddenOrBehaviorParamDecl = behavior;
    }
    
    OperatorDecl *getOperatorDecl() const {
      return Operator;
    }
    void setOperatorDecl(OperatorDecl *o) {
      assert(isOperator() && "can't set an OperatorDecl for a non-operator");
      Operator = o;
    }
    
    /// Returns true if the function is forced to be statically dispatched.
    bool hasForcedStaticDispatch() const {
      return Bits.FuncDecl.ForcedStaticDispatch;
    }
    void setForcedStaticDispatch(bool flag) {
      Bits.FuncDecl.ForcedStaticDispatch = flag;
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Func ||
             D->getKind() == DeclKind::Accessor;
    }
    static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
    }
    static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  
    /// True if the function is a defer body.
    bool isDeferBody() const;
  
    /// Perform basic checking to determine whether the @IBAction attribute can
    /// be applied to this function.
    bool isPotentialIBActionTarget() const;
  };
  
  /// \brief This represents an accessor function, such as a getter or setter.
  class AccessorDecl final : public FuncDecl {
    /// Location of the accessor keyword, e.g. 'set'.
    SourceLoc AccessorKeywordLoc;
  
    AbstractStorageDecl *Storage;
  
    AccessorDecl(SourceLoc declLoc, SourceLoc accessorKeywordLoc,
                 AccessorKind accessorKind, AddressorKind addressorKind,
                 AbstractStorageDecl *storage,
                 SourceLoc staticLoc, StaticSpellingKind staticSpelling,
                 bool throws, SourceLoc throwsLoc,
                 unsigned numParameterLists, GenericParamList *genericParams,
                 DeclContext *parent)
      : FuncDecl(DeclKind::Accessor,
                 staticLoc, staticSpelling, /*func loc*/ declLoc,
                 /*name*/ Identifier(), /*name loc*/ declLoc,
                 throws, throwsLoc, numParameterLists, genericParams, parent),
        AccessorKeywordLoc(accessorKeywordLoc),
        Storage(storage) {
      Bits.AccessorDecl.AccessorKind = unsigned(accessorKind);
      Bits.AccessorDecl.AddressorKind = unsigned(addressorKind);
    }
  
    static AccessorDecl *createImpl(ASTContext &ctx,
                                    SourceLoc declLoc,
                                    SourceLoc accessorKeywordLoc,
                                    AccessorKind accessorKind,
                                    AddressorKind addressorKind,
                                    AbstractStorageDecl *storage,
                                    SourceLoc staticLoc,
                                    StaticSpellingKind staticSpelling,
                                    bool throws, SourceLoc throwsLoc,
                                    unsigned numParameterLists,
                                    GenericParamList *genericParams,
                                    DeclContext *parent,
                                    ClangNode clangNode);
  
  public:
    static AccessorDecl *createDeserialized(ASTContext &ctx,
                                SourceLoc declLoc,
                                SourceLoc accessorKeywordLoc,
                                AccessorKind accessorKind,
                                AddressorKind addressorKind,
                                AbstractStorageDecl *storage,
                                SourceLoc staticLoc,
                                StaticSpellingKind staticSpelling,
                                bool throws, SourceLoc throwsLoc,
                                GenericParamList *genericParams,
                                unsigned numParameterLists,
                                DeclContext *parent);
  
    static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc,
                                SourceLoc accessorKeywordLoc,
                                AccessorKind accessorKind,
                                AddressorKind addressorKind,
                                AbstractStorageDecl *storage,
                                SourceLoc staticLoc,
                                StaticSpellingKind staticSpelling,
                                bool throws, SourceLoc throwsLoc,
                                GenericParamList *genericParams,
                                ArrayRef<ParameterList *> parameterLists,
                                TypeLoc fnRetType, DeclContext *parent,
                                ClangNode clangNode = ClangNode());
  
    SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }
  
    AbstractStorageDecl *getStorage() const {
      return Storage;
    }
  
    AccessorKind getAccessorKind() const {
      return AccessorKind(Bits.AccessorDecl.AccessorKind);
    }
  
    AddressorKind getAddressorKind() const {
      return AddressorKind(Bits.AccessorDecl.AddressorKind);
    }
  
    bool isGetter() const { return getAccessorKind() == AccessorKind::IsGetter; }
    bool isSetter() const { return getAccessorKind() == AccessorKind::IsSetter; }
    bool isMaterializeForSet() const {
      return getAccessorKind() == AccessorKind::IsMaterializeForSet;
    }
    bool isAnyAddressor() const {
      auto kind = getAccessorKind();
      return kind == AccessorKind::IsAddressor
          || kind == AccessorKind::IsMutableAddressor;
    }
  
    /// isGetterOrSetter - Determine whether this is specifically a getter or
    /// a setter, as opposed to some other kind of accessor.
    ///
    /// For example, only getters and setters can be exposed to Objective-C.
    bool isGetterOrSetter() const { return isGetter() || isSetter(); }
  
    bool isObservingAccessor() const {
      return getAccessorKind() == AccessorKind::IsDidSet ||
             getAccessorKind() == AccessorKind::IsWillSet;
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::Accessor;
    }
    static bool classof(const AbstractFunctionDecl *D) {
      return classof(static_cast<const Decl*>(D));
    }
    static bool classof(const DeclContext *DC) {
      if (auto D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  };
  
  inline ParameterList **FuncDecl::getParameterListBuffer() {
    if (!isa<AccessorDecl>(this)) {
      assert(getKind() == DeclKind::Func && "no new kinds of functions");
      return reinterpret_cast<ParameterList**>(this+1);
    }
    return reinterpret_cast<ParameterList**>(static_cast<AccessorDecl*>(this)+1);
  }
    
  /// \brief This represents a 'case' declaration in an 'enum', which may declare
  /// one or more individual comma-separated EnumElementDecls.
  class EnumCaseDecl final : public Decl,
      private llvm::TrailingObjects<EnumCaseDecl, EnumElementDecl *> {
    friend TrailingObjects;
    SourceLoc CaseLoc;
    
    EnumCaseDecl(SourceLoc CaseLoc,
                 ArrayRef<EnumElementDecl *> Elements,
                 DeclContext *DC)
      : Decl(DeclKind::EnumCase, DC),
        CaseLoc(CaseLoc)
    {
      Bits.EnumCaseDecl.NumElements = Elements.size();
      std::uninitialized_copy(Elements.begin(), Elements.end(),
                              getTrailingObjects<EnumElementDecl *>());
    }
  
  public:
    static EnumCaseDecl *create(SourceLoc CaseLoc,
                                ArrayRef<EnumElementDecl*> Elements,
                                DeclContext *DC);
    
    /// Get the list of elements declared in this case.
    ArrayRef<EnumElementDecl *> getElements() const {
      return {getTrailingObjects<EnumElementDecl *>(),
              Bits.EnumCaseDecl.NumElements};
    }
    
    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,
                    bool HasArgumentType,
                    SourceLoc EqualsLoc,
                    LiteralExpr *RawValueExpr,
                    DeclContext *DC)
    : ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
      ArgumentType(ArgumentType),
      EqualsLoc(EqualsLoc),
      RawValueExpr(RawValueExpr)
    {
      Bits.EnumElementDecl.Recursiveness =
          static_cast<unsigned>(ElementRecursiveness::NotRecursive);
      Bits.EnumElementDecl.HasArgumentType = HasArgumentType;
    }
  
    Identifier getName() const { return getFullName().getBaseIdentifier(); }
  
    /// Returns the string for the base name, or "_" if this is unnamed.
    StringRef getNameStr() const {
      assert(!getFullName().isSpecial() && "Cannot get string for special names");
      return hasName() ? getBaseName().getIdentifier().str() : "_";
    }
  
    /// \returns false if there was an error during the computation rendering the
    /// EnumElementDecl invalid, true otherwise.
    bool computeType();
  
    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>(Bits.EnumElementDecl.Recursiveness);
    }
    
    void setRecursiveness(ElementRecursiveness recursiveness) {
      Bits.EnumElementDecl.Recursiveness = static_cast<unsigned>(recursiveness);
    }
  
    bool hasAssociatedValues() const {
      return Bits.EnumElementDecl.HasArgumentType;
    }
  
    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).
    ///
    /// Convenience initializers are inherited into subclasses that override
    /// all of their superclass's designated initializers.
    Convenience,
  
    /// A convenience factory initializer is a convenience initializer introduced
    /// by an imported Objective-C factory method.
    ///
    /// Convenience factory initializers cannot be expressed directly in
    /// Swift; rather, they are produced by the Clang importer when importing
    /// an instancetype factory method from Objective-C.
    ConvenienceFactory,
  
    /// A factory initializer is an initializer that is neither designated nor
    /// convenience: it can be used to create an object of the given type, but
    /// cannot be chained to via "super.init" nor is it inherited.
    ///
    /// A factory initializer is written with a return type of the class name
    /// itself. FIXME: However, this is only a presentation form, and at present
    /// the only factory initializers are produced by importing an Objective-C
    /// factory method that does not return instancetype.
    ///
    /// FIXME: Arguably, structs and enums only have factory initializers, and
    /// using designated initializers for them is a misnomer.
    Factory
  };
  
  /// ConstructorDecl - Declares a constructor for a type.  For example:
  ///
  /// \code
  /// struct X {
  ///   var x : Int
  ///   init(i : Int) {
  ///      x = i
  ///   }
  /// }
  /// \endcode
  class ConstructorDecl : public AbstractFunctionDecl {
    /// The location of the '!' or '?' for a failable initializer.
    SourceLoc FailabilityLoc;
  
    ParameterList *ParameterLists[2];
  
    /// 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,
                    bool Throws, SourceLoc ThrowsLoc,
                    ParamDecl *SelfParam, ParameterList *BodyParams,
                    GenericParamList *GenericParams, 
                    DeclContext *Parent);
  
    Identifier getName() const { return getFullName().getBaseIdentifier(); }
  
    void setParameterLists(ParamDecl *selfParam, ParameterList *bodyParams);
  
    SourceLoc getConstructorLoc() const { return getNameLoc(); }
    SourceLoc getStartLoc() const { return getConstructorLoc(); }
    SourceRange getSourceRange() const;
  
    /// getArgumentInterfaceType - get the interface type of the argument tuple
    Type getArgumentInterfaceType() const;
  
    /// \brief Get the interface type of the constructed object.
    Type getResultInterfaceType() const;
  
    /// 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; }
  
    MutableArrayRef<ParameterList *> getParameterLists() {
      return { ParameterLists, 2 };
    }
    ArrayRef<const ParameterList *> getParameterLists() const {
      return AbstractFunctionDecl::getParameterLists();
    }
    ParameterList *getParameterList(unsigned i) {
      return getParameterLists()[i];
    }
    const ParameterList *getParameterList(unsigned i) const {
      return getParameterLists()[i];
    }
    
    /// Returns the normal parameters to the initializer, not including self.
    ParameterList *getParameters() { return ParameterLists[1]; }
  
    /// Returns the normal parameters to the initializer, not including self.
    const ParameterList *getParameters() const { return ParameterLists[1]; }
  
  
    /// 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>(Bits.ConstructorDecl.InitKind);
    }
  
    /// Set whether this is a convenience initializer.
    void setInitKind(CtorInitializerKind kind) {
      Bits.ConstructorDecl.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>(Bits.ConstructorDecl.Failability);
    }
  
    /// Retrieve the location of the '!' or '?' in a failable initializer.
    SourceLoc getFailabilityLoc() const { return FailabilityLoc; }
  
    /// Whether the implementation of this method is a stub that traps at runtime.
    bool hasStubImplementation() const {
      return Bits.ConstructorDecl.HasStubImplementation;
    }
  
    /// Set whether the implementation of this method is a stub that
    /// traps at runtime.
    void setStubImplementation(bool stub) {
      Bits.ConstructorDecl.HasStubImplementation = stub;
    }
  
    ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; }
    void setOverriddenDecl(ConstructorDecl *over) {
      // FIXME: Hack due to broken class circularity checking.
      if (over == this) return;
  
      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 D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  };
  
  /// DestructorDecl - Declares a destructor for a type.  For example:
  ///
  /// \code
  /// struct X {
  ///   var fd : Int
  ///   deinit {
  ///      close(fd)
  ///   }
  /// }
  /// \endcode
  class DestructorDecl : public AbstractFunctionDecl {
    ParameterList *SelfParameter;
  public:
    DestructorDecl(SourceLoc DestructorLoc, ParamDecl *selfDecl,
                   DeclContext *Parent);
    
    void setSelfDecl(ParamDecl *selfDecl);
  
    MutableArrayRef<ParameterList *> getParameterLists() {
      return { &SelfParameter, 1 };
    }
    ArrayRef<const ParameterList *> getParameterLists() const {
      return { &SelfParameter, 1 };
    }
  
  
    
    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 D = DC->getAsDeclOrDeclExtensionContext())
        return classof(D);
      return false;
    }
  };
  
  /// Declares a precedence group.  For example:
  ///
  /// \code
  /// precedencegroup MultiplicativePrecedence {
  ///   associativity: right
  ///   higherThan: AdditivePrecedence
  /// }
  /// \endcode
  class PrecedenceGroupDecl : public Decl {
  public:
    struct Relation {
      SourceLoc NameLoc;
      Identifier Name;
      PrecedenceGroupDecl *Group;
    };
  
  private:
    SourceLoc PrecedenceGroupLoc, NameLoc, LBraceLoc, RBraceLoc;
    SourceLoc AssociativityKeywordLoc, AssociativityValueLoc;
    SourceLoc AssignmentKeywordLoc, AssignmentValueLoc;
    SourceLoc HigherThanLoc, LowerThanLoc;
    Identifier Name;
    unsigned NumHigherThan, NumLowerThan;
    // Tail-allocated array of Relations
  
    Relation *getHigherThanBuffer() {
      return reinterpret_cast<Relation*>(this + 1);
    }
    const Relation *getHigherThanBuffer() const {
      return reinterpret_cast<const Relation*>(this + 1);
    }
    Relation *getLowerThanBuffer() {
      return getHigherThanBuffer() + NumHigherThan;
    }
    const Relation *getLowerThanBuffer() const {
      return getHigherThanBuffer() + NumHigherThan;
    }
  
    PrecedenceGroupDecl(DeclContext *DC,
                        SourceLoc precedenceGroupLoc,
                        SourceLoc nameLoc, Identifier name,
                        SourceLoc lbraceLoc,
                        SourceLoc associativityKeywordLoc,
                        SourceLoc associativityValueLoc,
                        Associativity associativity,
                        SourceLoc assignmentKeywordLoc,
                        SourceLoc assignmentValueLoc,
                        bool isAssignment,
                        SourceLoc higherThanLoc, ArrayRef<Relation> higherThan,
                        SourceLoc lowerThanLoc, ArrayRef<Relation> lowerThan,
                        SourceLoc rbraceLoc);
  
  public:
    static PrecedenceGroupDecl *create(DeclContext *dc,
                                       SourceLoc precedenceGroupLoc,
                                       SourceLoc nameLoc,
                                       Identifier name,
                                       SourceLoc lbraceLoc,
                                       SourceLoc associativityKeywordLoc,
                                       SourceLoc associativityValueLoc,
                                       Associativity associativity,
                                       SourceLoc assignmentKeywordLoc,
                                       SourceLoc assignmentValueLoc,
                                       bool isAssignment,
                                       SourceLoc higherThanLoc,
                                       ArrayRef<Relation> higherThan,
                                       SourceLoc lowerThanLoc,
                                       ArrayRef<Relation> lowerThan,
                                       SourceLoc rbraceLoc);
  
  
    SourceLoc getLoc() const { return NameLoc; }
    SourceRange getSourceRange() const {
      return { PrecedenceGroupLoc, RBraceLoc };
    }
  
    /// Return the location of 'precedencegroup' in:
    ///   precedencegroup MultiplicativePrecedence { ... }
    SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; }
  
    /// Return the location of 'MultiplicativePrecedence' in:
    ///   precedencegroup MultiplicativePrecedence { ... }
    SourceLoc getNameLoc() const {
      return NameLoc;
    }
  
    Identifier getName() const {
      return Name;
    }
  
    SourceLoc getLBraceLoc() const { return LBraceLoc; }
    SourceLoc getRBraceLoc() const { return RBraceLoc; }
  
    bool isAssociativityImplicit() const {
      return AssociativityKeywordLoc.isInvalid();
    }
  
    /// Return the location of 'associativity' in:
    ///   associativity: left
    SourceLoc getAssociativityKeywordLoc() const {
      return AssociativityKeywordLoc;
    }
  
    /// Return the location of 'right' in:
    ///   associativity: right
    SourceLoc getAssociativityValueLoc() const {
      return AssociativityValueLoc;
    }
  
    Associativity getAssociativity() const {
      return Associativity(Bits.PrecedenceGroupDecl.Associativity);
    }
    bool isLeftAssociative() const {
      return getAssociativity() == Associativity::Left;
    }
    bool isRightAssociative() const {
      return getAssociativity() == Associativity::Right;
    }
    bool isNonAssociative() const {
      return getAssociativity() == Associativity::None;
    }
  
    bool isAssignmentImplicit() const {
      return AssignmentKeywordLoc.isInvalid();
    }
  
    /// Return the location of 'assignment' in:
    ///   assignment: true
    SourceLoc getAssignmentKeywordLoc() const {
      return AssignmentKeywordLoc;
    }
  
    /// Return the location of 'assignment' in:
    ///   assignment: true
    SourceLoc getAssignmentValueLoc() const {
      return AssignmentValueLoc;
    }
  
    bool isAssignment() const {
      return Bits.PrecedenceGroupDecl.IsAssignment;
    }
  
    bool isHigherThanImplicit() const {
      return HigherThanLoc.isInvalid();
    }
  
    /// Return the location of 'higherThan' in:
    ///   higherThan: AdditivePrecedence
    SourceLoc getHigherThanLoc() const {
      return HigherThanLoc;
    }
  
    ArrayRef<Relation> getHigherThan() const {
      return { getHigherThanBuffer(), NumHigherThan };
    }
    MutableArrayRef<Relation> getMutableHigherThan() {
      return { getHigherThanBuffer(), NumHigherThan };
    }
  
    bool isLowerThanImplicit() const {
      return LowerThanLoc.isInvalid();
    }
  
    /// Return the location of 'lowerThan' in:
    ///   lowerThan: MultiplicativePrecedence
    SourceLoc getLowerThanLoc() const {
      return LowerThanLoc;
    }
  
    ArrayRef<Relation> getLowerThan() const {
      return { getLowerThanBuffer(), NumLowerThan };
    }
    MutableArrayRef<Relation> getMutableLowerThan() {
      return { getLowerThanBuffer(), NumLowerThan };
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PrecedenceGroup;
    }
  };
  
  /// Abstract base class of operator declarations.
  class OperatorDecl : public Decl {
    SourceLoc OperatorLoc, NameLoc;
    
    Identifier name;
  
  public:
    OperatorDecl(DeclKind kind,
                 DeclContext *DC,
                 SourceLoc OperatorLoc,
                 Identifier Name,
                 SourceLoc NameLoc)
      : Decl(kind, DC),
        OperatorLoc(OperatorLoc), NameLoc(NameLoc),
        name(Name) {}
    
    SourceLoc getLoc() const { return NameLoc; }
  
    SourceLoc getOperatorLoc() const { return OperatorLoc; }
    SourceLoc getNameLoc() const { return NameLoc; }
    Identifier getName() const { return name; }
    
    static bool classof(const Decl *D) {
      // Workaround: http://llvm.org/PR35906
      if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
        return D->getKind() >= DeclKind::First_OperatorDecl;
      return D->getKind() >= DeclKind::First_OperatorDecl
          && D->getKind() <= DeclKind::Last_OperatorDecl;
    }
  };
  
  /// Declares the behavior of an infix operator. For example:
  ///
  /// \code
  /// infix operator /+/ : AdditivePrecedence
  /// \endcode
  class InfixOperatorDecl : public OperatorDecl {
    SourceLoc ColonLoc, PrecedenceGroupNameLoc;
    Identifier PrecedenceGroupName;
    PrecedenceGroupDecl *PrecedenceGroup = nullptr;
  
  public:
    InfixOperatorDecl(DeclContext *DC,
                      SourceLoc operatorLoc,
                      Identifier name,
                      SourceLoc nameLoc,
                      SourceLoc colonLoc,
                      Identifier precedenceGroupName,
                      SourceLoc precedenceGroupNameLoc)
      : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc),
        ColonLoc(colonLoc), PrecedenceGroupNameLoc(precedenceGroupNameLoc),
        PrecedenceGroupName(precedenceGroupName) {
    }
  
    SourceLoc getEndLoc() const {
      if (PrecedenceGroupName.empty())
        return getNameLoc();
      return PrecedenceGroupNameLoc;
    }
    SourceRange getSourceRange() const {
      return { getOperatorLoc(), getEndLoc() };
    }
    
    SourceLoc getColonLoc() const { return ColonLoc; }
    SourceLoc getPrecedenceGroupNameLoc() const { return PrecedenceGroupNameLoc; }
  
    Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; }
    PrecedenceGroupDecl *getPrecedenceGroup() const { return PrecedenceGroup; }
    void setPrecedenceGroup(PrecedenceGroupDecl *PGD) {
      PrecedenceGroup = PGD;
    }
  
    /// True if this decl's attributes conflict with those declared by another
    /// operator.
    bool conflictsWith(InfixOperatorDecl *other) {
      return getPrecedenceGroup() != other->getPrecedenceGroup();
    }
    
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::InfixOperator;
    }
  };
    
  /// Declares the behavior of a prefix operator. For example:
  ///
  /// \code
  /// prefix operator /+/ {}
  /// \endcode
  class PrefixOperatorDecl : public OperatorDecl {
  public:
    PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                       SourceLoc NameLoc)
      : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc) {}
  
    SourceRange getSourceRange() const {
      return { getOperatorLoc(), getNameLoc() };
    }
  
    /// True if this decl's attributes conflict with those declared by another
    /// PrefixOperatorDecl.
    bool conflictsWith(PrefixOperatorDecl *other) {
      return false;
    }
    
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PrefixOperator;
    }
  };
    
  /// Declares the behavior of a postfix operator. For example:
  ///
  /// \code
  /// postfix operator /+/ {}
  /// \endcode
  class PostfixOperatorDecl : public OperatorDecl {
  public:
    PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
                       SourceLoc NameLoc)
      : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc) {}
    
    SourceRange getSourceRange() const {
      return { getOperatorLoc(), getNameLoc() };
    }
  
    /// True if this decl's attributes conflict with those declared by another
    /// PostfixOperatorDecl.
    bool conflictsWith(PostfixOperatorDecl *other) {
      return false;
    }
    
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::PostfixOperator;
    }
  };
  
  /// Represents a hole where a declaration should have been.
  ///
  /// Among other things, these are used to keep vtable layout consistent.
  class MissingMemberDecl : public Decl {
    DeclName Name;
  
    MissingMemberDecl(DeclContext *DC, DeclName name,
                      unsigned vtableEntries,
                      unsigned fieldOffsetVectorEntries)
        : Decl(DeclKind::MissingMember, DC), Name(name) {
      Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries;
      assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
      Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries =
        fieldOffsetVectorEntries;
      assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries
             && "not enough bits");
      setImplicit();
    }
  public:
    static MissingMemberDecl *
    forMethod(ASTContext &ctx, DeclContext *DC, DeclName name,
              bool hasNormalVTableEntry) {
      assert(!name || name.isCompoundName());
      return new (ctx) MissingMemberDecl(DC, name, hasNormalVTableEntry, 0);
    }
  
    static MissingMemberDecl *
    forInitializer(ASTContext &ctx, DeclContext *DC, DeclName name,
                   bool hasNormalVTableEntry,
                   bool hasAllocatingVTableEntry) {
      unsigned entries = hasNormalVTableEntry + hasAllocatingVTableEntry;
      return new (ctx) MissingMemberDecl(DC, name, entries, 0);
    }
    
    static MissingMemberDecl *
    forStoredProperty(ASTContext &ctx, DeclContext *DC, DeclName name) {
      return new (ctx) MissingMemberDecl(DC, name, 0, 1);
    }
  
    DeclName getFullName() const {
      return Name;
    }
  
    unsigned getNumberOfVTableEntries() const {
      return Bits.MissingMemberDecl.NumberOfVTableEntries;
    }
  
    unsigned getNumberOfFieldOffsetVectorEntries() const {
      return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries;
    }
  
    SourceLoc getLoc() const {
      return SourceLoc();
    }
  
    SourceRange getSourceRange() const {
      return SourceRange();
    }
  
    static bool classof(const Decl *D) {
      return D->getKind() == DeclKind::MissingMember;
    }
  };
  
  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;
  }
  
  inline Optional<VarDecl *>
  NominalTypeDecl::ToStoredProperty::operator()(Decl *decl) const {
    if (auto var = dyn_cast<VarDecl>(decl)) {
      if (!var->isStatic() && var->hasStorage() &&
          (!skipUserInaccessible || var->isUserAccessible()))
        return var;
    }
  
    return None;
  }
  
  inline Optional<Decl *>
  NominalTypeDecl::ToStoredPropertyOrMissingMemberPlaceholder
  ::operator()(Decl *decl) const {
    if (auto var = dyn_cast<VarDecl>(decl)) {
      if (!var->isStatic() && var->hasStorage())
        return var;
    }
    if (auto missing = dyn_cast<MissingMemberDecl>(decl)) {
      if (missing->getNumberOfFieldOffsetVectorEntries() > 0)
        return missing;
    }
  
    return None;
  }
  
  inline void
  AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
    GetSetInfo.setInt(accessLevel);
    if (auto setter = getSetter())
      setter->overwriteAccess(accessLevel);
    if (auto materializeForSet = getMaterializeForSetFunc())
      materializeForSet->overwriteAccess(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<ParameterList *>
  AbstractFunctionDecl::getParameterLists() {
    switch (getKind()) {
    default: llvm_unreachable("Unknown AbstractFunctionDecl!");
    case DeclKind::Constructor:
      return cast<ConstructorDecl>(this)->getParameterLists();
    case DeclKind::Destructor:
      return cast<DestructorDecl>(this)->getParameterLists();
    case DeclKind::Func:
    case DeclKind::Accessor:
      return cast<FuncDecl>(this)->getParameterLists();
    }
  }
  
  inline DeclIterator &DeclIterator::operator++() {
    Current = Current->NextDecl;
    return *this;
  }
  
  inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const {
    if (auto func = dyn_cast<FuncDecl>(this))
      return func->hasForcedStaticDispatch();
    return false;
  }
  
  inline bool ValueDecl::isStatic() const {
    // Currently, only storage and function decls can be static/class.
    if (auto storage = dyn_cast<AbstractStorageDecl>(this))
      return storage->isStatic();
    if (auto func = dyn_cast<FuncDecl>(this))
      return func->isStatic();
    return false;
  }
  
  inline bool ValueDecl::isImportAsMember() const {
    if (auto func = dyn_cast<AbstractFunctionDecl>(this))
      return func->isImportAsMember();
    return false;
  }
  
  inline bool Decl::isPotentiallyOverridable() const {
    if (isa<VarDecl>(this) ||
        isa<SubscriptDecl>(this) ||
        isa<FuncDecl>(this)) {
      return getDeclContext()->getAsClassOrClassExtensionContext();
    } else {
      return false;
    }
  }
  
  inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
    : Depth(d->getDepth()), Index(d->getIndex()) { }
  
  inline const GenericContext *Decl::getAsGenericContext() const {
    switch (getKind()) {
    default: return nullptr;
  #define DECL(Id, Parent) // See previous line
  #define GENERIC_DECL(Id, Parent) \
    case DeclKind::Id: \
      return static_cast<const Id##Decl*>(this);
  #include "swift/AST/DeclNodes.def"
    }
  }
  
  inline bool DeclContext::isExtensionContext() const {
    if (auto D = getAsDeclOrDeclExtensionContext())
      return ExtensionDecl::classof(D);
    return false;
  }
  
  inline bool DeclContext::classof(const Decl *D) {
    switch (D->getKind()) { //
    default: return false;
  #define DECL(ID, PARENT) // See previous line
  #define CONTEXT_DECL(ID, PARENT) \
    case DeclKind::ID: return true;
  #include "swift/AST/DeclNodes.def"
    }
  }
  
  inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
    // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
    // preface decls in memory, any DeclContext type will due.
    const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
    switch (D->getKind()) {
    default: llvm_unreachable("Not a DeclContext");
  #define DECL(ID, PARENT) // See previous line
  #define CONTEXT_DECL(ID, PARENT) \
    case DeclKind::ID:
  #include "swift/AST/DeclNodes.def"
      return const_cast<DeclContext *>(DC);
    }
  }
  
  inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
    EnumElementDecl *result = nullptr;
    bool found = false;
    for (auto elt : getAllElements()) {
      if (elt->hasAssociatedValues() == hasValue) {
        if (found)
          return nullptr;
        found = true;
        result = elt;
      }
    }
    return result;
  }
  
  } // end namespace swift
  
  #endif
  