//===--- 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+2+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 : 2,

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

  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 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 : unsigned char {
  /// \brief This is not an addressor.
  NotAddressor,
  /// \brief This is an unsafe addressor; it simply returns an address.
  Unsafe,
  /// \brief This is an owning addressor; it returns 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 : unsigned char {
  /// The access is just to read the current value.
  Read,

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

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

/// The way to actually evaluate an access to storage.
enum class AccessStrategy : unsigned char {
  /// The decl is a VarDecl with its own backing storage; evaluate its
  /// address directly.
  Storage,
  
  /// The decl 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
    
    Owned  = Let,
    InOut = 2,
    Shared = 3,
  };
  
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;

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

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

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