//===--- 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/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/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 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 FuncDecl;
  class BraceStmt;
  class DeclAttributes;
  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 DECL_RANGE(Id, FirstId, LastId) \
  First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "swift/AST/DeclNodes.def"
};

/// Fine-grained declaration kind that provides a description of the
/// kind of entity a declaration represents, as it would be used in
/// diagnostics.
///
/// For example, \c FuncDecl is a single declaration class, but it has
/// several descriptive entries depending on whether it is an
/// operator, global function, local function, method, (observing)
/// accessor, etc.
enum class DescriptiveDeclKind : uint8_t {
  Import,
  Extension,
  EnumCase,
  TopLevelCode,
  IfConfig,
  PatternBinding,
  Var,
  Param,
  Let,
  StaticVar,
  StaticLet,
  ClassVar,
  ClassLet,
  InfixOperator,
  PrefixOperator,
  PostfixOperator,
  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 interface type of the declaration, when relevant to the
  /// overload signature.
  CanType InterfaceType;

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

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

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

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

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

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

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

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

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

    /// \brief Whether we've already performed early attribute validation.
    /// FIXME: This is ugly.
    unsigned EarlyAttrValidation : 1;

    /// \brief Whether this declaration is currently being validated.
    unsigned BeingValidated : 1;

    /// \brief Whether we have started validating the declaration; this *isn't*
    /// reset after finishing it.
    unsigned ValidationStarted : 1;

    /// \brief Whether this declaration was added to the surrounding
    /// DeclContext of an active #if config clause.
    unsigned EscapedFromIfConfig : 1;
  };
  enum { NumDeclBits = 13 };
  static_assert(NumDeclBits <= 32, "fits in an unsigned");

  class PatternBindingDeclBitfields {
    friend class PatternBindingDecl;
    unsigned : NumDeclBits;
    
    /// \brief Whether this pattern binding declares static variables.
    unsigned IsStatic : 1;

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

    /// \brief The number of pattern binding declarations.
    unsigned NumPatternEntries : 16;
  };
  enum { NumPatternBindingDeclBits = NumDeclBits + 19 };
  static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned");
  
  class ValueDeclBitfields {
    friend class ValueDecl;
    friend class MemberLookupTable;
    unsigned : NumDeclBits;
    unsigned AlreadyInLookupTable : 1;

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

    /// Whether the decl can be accessed by swift users; for instance,
    /// a.storage for lazy var a is a decl that cannot be accessed.
    unsigned IsUserAccessible : 1;
  };
  enum { NumValueDeclBits = NumDeclBits + 3 };
  static_assert(NumValueDeclBits <= 32, "fits in an unsigned");

  class AbstractStorageDeclBitfields {
    friend class AbstractStorageDecl;
    unsigned : NumValueDeclBits;

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

    /// Whether the getter is mutating.
    unsigned IsGetterMutating : 1;

    /// Whether the setter is mutating.
    unsigned IsSetterMutating : 1;

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

  class VarDeclBitfields {
    friend class VarDecl;
    unsigned : NumAbstractStorageDeclBits;

    /// \brief Whether this property is a type property (currently unfortunately
    /// called 'static').
    unsigned IsStatic : 1;

    /// \brief The specifier associated with this variable or parameter.  This
    /// determines the storage semantics of the value e.g. mutability.
    unsigned Specifier : 2;

    /// \brief Whether this declaration was an element of a capture list.
    unsigned 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.
    unsigned HasNonPatternBindingInit : 1;

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

  };
  enum { NumVarDeclBits = NumAbstractStorageDeclBits + 6 };
  static_assert(NumVarDeclBits <= 32, "fits in an unsigned");

  class EnumElementDeclBitfields {
    friend class EnumElementDecl;
    unsigned : NumValueDeclBits;
    
    /// \brief Whether or not this element directly or indirectly references
    /// the enum type.
    unsigned Recursiveness : 2;

    /// \brief Whether or not this element has an associated value.
    unsigned HasArgumentType : 1;
  };
  enum { NumEnumElementDeclBits = NumValueDeclBits + 3 };
  static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned");
  
  class AbstractFunctionDeclBitfields {
    friend class AbstractFunctionDecl;
    unsigned : NumValueDeclBits;

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

    /// Number of curried parameter lists.
    unsigned NumParameterLists : 5;

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

    /// Whether the function body throws.
    unsigned Throws : 1;

    /// Whether this function requires a new vtable entry.
    unsigned NeedsNewVTableEntry : 1;

    /// Whether NeedsNewVTableEntry is valid.
    unsigned HasComputedNeedsNewVTableEntry : 1;

    /// The ResilienceExpansion to use for default arguments.
    unsigned DefaultArgumentResilienceExpansion : 1;
  };
  enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 13 };
  static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");

  class FuncDeclBitfields {
    friend class FuncDecl;
    unsigned : NumAbstractFunctionDeclBits;

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

    /// \brief Whether 'static' or 'class' was used.
    unsigned StaticSpelling : 2;
  };
  enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 3 };
  static_assert(NumFuncDeclBits <= 32, "fits in an unsigned");

  class ConstructorDeclBitfields {
    friend class ConstructorDecl;
    unsigned : NumAbstractFunctionDeclBits;

    /// The body initialization kind (+1), or zero if not yet computed.
    ///
    /// This value is cached but is not serialized, because it is a property
    /// of the definition of the constructor that is useful only to semantic
    /// analysis and SIL generation.
    unsigned ComputedBodyInitKind : 3;
  };
  enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 3 };
  static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned");

  class TypeDeclBitfields {
    friend class TypeDecl;
    unsigned : NumValueDeclBits;

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

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

  class GenericTypeDeclBitfields {
    friend class GenericTypeDecl;
    unsigned : NumTypeDeclBits;
  };

  enum { NumGenericTypeDeclBits = NumTypeDeclBits };
  static_assert(NumGenericTypeDeclBits <= 32, "fits in an unsigned");

  class TypeAliasDeclBitfields {
    friend class TypeAliasDecl;
    unsigned : NumGenericTypeDeclBits;

    /// Whether the typealias forwards perfectly to its underlying type.
    unsigned IsCompatibilityAlias : 1;
  };
  enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits + 1 };
  static_assert(NumTypeAliasDeclBits <= 32, "fits in an unsigned");

  class NominalTypeDeclBitFields {
    friend class NominalTypeDecl;
    unsigned : NumGenericTypeDeclBits;
    
    /// Whether or not the nominal type decl has delayed protocol or member
    /// declarations.
    unsigned HasDelayedMembers : 1;

    /// Whether we have already added implicitly-defined initializers
    /// to this declaration.
    unsigned AddedImplicitInitializers : 1;

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

    /// Whether we have already validated all members of the type that
    /// affect layout.
    unsigned HasValidatedLayout : 1;
  };
  enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 4 };
  static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");

  class ProtocolDeclBitfields {
    friend class ProtocolDecl;
    unsigned : NumNominalTypeDeclBits;

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

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

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

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

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

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

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

  class ClassDeclBitfields {
    friend class ClassDecl;
    unsigned : NumNominalTypeDeclBits;

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

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

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

    /// \see ClassDecl::ForeignKind
    unsigned 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.
    unsigned HasDestructorDecl : 1;

  };
  enum { NumClassDeclBits = NumNominalTypeDeclBits + 8 };
  static_assert(NumClassDeclBits <= 32, "fits in an unsigned");

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

    /// True if the enum has cases and at least one case has associated values.
    mutable unsigned HasAssociatedValues : 2;
  };
  enum { NumEnumDeclBits = NumNominalTypeDeclBits + 4 };
  static_assert(NumEnumDeclBits <= 32, "fits in an unsigned");
  
  class PrecedenceGroupDeclBitfields {
    friend class PrecedenceGroupDecl;
    unsigned : NumDeclBits;

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

    /// Is this an assignment operator?
    unsigned IsAssignment : 1;
  };
  enum { NumPrecedenceGroupDeclBits = NumDeclBits + 11 };
  static_assert(NumPrecedenceGroupDeclBits <= 32, "fits in an unsigned");

  class AssociatedTypeDeclBitfields {
    friend class AssociatedTypeDecl;
    unsigned : NumTypeDeclBits;
    unsigned ComputedOverridden : 1;
    unsigned HasOverridden : 1;
  };
  enum { NumAssociatedTypeDeclBits = NumTypeDeclBits + 2 };
  static_assert(NumAssociatedTypeDeclBits <= 32, "fits in an unsigned");

  class ImportDeclBitfields {
    friend class ImportDecl;
    unsigned : NumDeclBits;

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

  class ExtensionDeclBitfields {
    friend class ExtensionDecl;
    unsigned : NumDeclBits;

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

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

    /// Whether there is are lazily-loaded conformances for this extension.
    unsigned HasLazyConformances : 1;
  };
  enum { NumExtensionDeclBits = NumDeclBits + 5 };
  static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned");

  class IfConfigDeclBitfields {
    friend class IfConfigDecl;
    unsigned : NumDeclBits;

    /// Whether this decl is missing its closing '#endif'.
    unsigned HadMissingEnd : 1;
  };
  enum { NumIfConfigDeclBits = NumDeclBits + 1 };
  static_assert(NumIfConfigDeclBits <= 32, "fits in an unsigned");

  class MissingMemberDeclBitfields {
    friend class MissingMemberDecl;
    unsigned : NumDeclBits;

    unsigned NumberOfVTableEntries : 2;
    unsigned NumberOfFieldOffsetVectorEntries : 1;
  };
  enum { NumMissingMemberDeclBits = NumDeclBits + 3 };
  static_assert(NumMissingMemberDeclBits <= 32, "fits in an unsigned");

protected:
  union {
    DeclBitfields DeclBits;
    PatternBindingDeclBitfields PatternBindingDeclBits;
    ValueDeclBitfields ValueDeclBits;
    AbstractStorageDeclBitfields AbstractStorageDeclBits;
    AbstractFunctionDeclBitfields AbstractFunctionDeclBits;
    VarDeclBitfields VarDeclBits;
    EnumElementDeclBitfields EnumElementDeclBits;
    FuncDeclBitfields FuncDeclBits;
    ConstructorDeclBitfields ConstructorDeclBits;
    TypeDeclBitfields TypeDeclBits;
    GenericTypeDeclBitfields GenericTypeDeclBits;
    TypeAliasDeclBitfields TypeAliasDeclBits;
    NominalTypeDeclBitFields NominalTypeDeclBits;
    ProtocolDeclBitfields ProtocolDeclBits;
    ClassDeclBitfields ClassDeclBits;
    StructDeclBitfields StructDeclBits;
    EnumDeclBitfields EnumDeclBits;
    AssociatedTypeDeclBitfields AssociatedTypeDeclBits;
    PrecedenceGroupDeclBitfields PrecedenceGroupDeclBits;
    ImportDeclBitfields ImportDeclBits;
    ExtensionDeclBitfields ExtensionDeclBits;
    IfConfigDeclBitfields IfConfigDeclBits;
    MissingMemberDeclBitfields MissingMemberDeclBits;
    uint32_t OpaqueBits;
  };

  // FIXME: Unused padding here.

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

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

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

protected:

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

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

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

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

  DeclContext *getDeclContextForModule() const;

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

  /// \brief Retrieve the name of the given declaration kind.
  ///
  /// This name should only be used for debugging dumps and other
  /// developer aids, and should never be part of a diagnostic or exposed
  /// to the user of the compiler in any way.
  static StringRef getKindName(DeclKind K);

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

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

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

  /// 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");
  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 DeclBits.Invalid; }
  
  /// \brief Mark this declaration invalid.
  void setInvalid(bool isInvalid = true) { DeclBits.Invalid = isInvalid; }

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

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

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

  /// Set whether we've performed early attribute validation.
  void setEarlyAttrValidation(bool validated = true) {
    DeclBits.EarlyAttrValidation = validated;
  }
  
  /// Whether the declaration has a valid interface type and
  /// generic signature.
  bool isBeingValidated() const {
    return DeclBits.BeingValidated;
  }

  /// Toggle whether or not the declaration is being validated.
  void setIsBeingValidated(bool ibv = true) {
    assert(DeclBits.BeingValidated != ibv);
    DeclBits.BeingValidated = ibv;
    if (ibv) {
      DeclBits.ValidationStarted = true;
    }
  }

  bool hasValidationStarted() const { return DeclBits.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() { DeclBits.ValidationStarted = true; }

  bool escapedFromIfConfig() const {
    return DeclBits.EscapedFromIfConfig;
  }

  void setEscapedFromIfConfig(bool Escaped) {
    DeclBits.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 DeclBits.FromClang;
  }

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

    return getClangNodeImpl();
  }

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

    return getClangNodeImpl().getAsDecl();
  }

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

    return getClangNodeImpl().getAsMacro();
  }

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

class GenericContext : public DeclContext {
private:
  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;

  /// Lazily populate the generic environment.
  GenericEnvironment *getLazyGenericEnvironmentSlow() const;

protected:
  GenericContext(DeclContextKind Kind, DeclContext *Parent)
    : 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.
  ArrayRef<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);
};

/// 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 number of elements in this path.
  unsigned NumPathElements;

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

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

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

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

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

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

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

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

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

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

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

/// ExtensionDecl - This represents a type extension containing methods
/// associated with the type.  This is not a ValueDecl and has no Type because
/// there are no runtime values of the Extension's type.  
class ExtensionDecl final : public Decl, public GenericContext,
                            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 (!ExtensionDeclBits.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 ExtensionDeclBits.CheckedInheritanceClause;
  }

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

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

  AccessLevel getDefaultAccessLevel() const {
    assert(hasDefaultAccessLevel() && "not computed yet");
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << (static_cast<unsigned>(AccessLevel::FilePrivate) - 1)))
      return AccessLevel::FilePrivate;
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << (static_cast<unsigned>(AccessLevel::Internal) - 1)))
      return AccessLevel::Internal;
    return AccessLevel::Public;
  }

  AccessLevel getMaxAccessLevel() const {
    assert(hasDefaultAccessLevel() && "not computed yet");
    if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
        (1 << (static_cast<unsigned>(AccessLevel::Public) - 1)))
      return AccessLevel::Public;
    if (ExtensionDeclBits.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");
    ExtensionDeclBits.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;

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

  using DeclContext::operator new;
};

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

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

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

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

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

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

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

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

public:

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

  typedef ExtensionIterator iterator;
  iterator begin() const { return first; }
  iterator end() const { return last; }
};
  
  
/// This represents one entry in a PatternBindingDecl, which are pairs of
/// Pattern and Initialization expression.  The pattern is always present, but
/// the initializer can be null if there is none.
class PatternBindingEntry {
  Pattern *ThePattern;

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

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::PatternBinding;
  }
  
private:
  MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
    // Pattern entries are tail allocated.
    return {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 Decl, public DeclContext {
  BraceStmt *Body;

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

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

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

  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::TopLevelCode;
  }
  static bool classof(const DeclContext *C) {
    return C->getContextKind() == DeclContextKind::TopLevelCodeDecl;
  }
  
  using DeclContext::operator new;
};

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

/// 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)
  {
    IfConfigDeclBits.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 IfConfigDeclBits.HadMissingEnd; }
  
  SourceRange getSourceRange() const;
  
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::IfConfig;
  }
};

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

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

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 ValueDeclBits.CheckedRedeclaration; 
  }

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

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

  bool isUserAccessible() const {
    return ValueDeclBits.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 {
    return hasInterfaceType() && !isBeingValidated();
  }

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

  /// needsCapture - Check whether referring to this decl from a nested
  /// function requires capturing it.
  bool needsCapture() const;

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

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

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

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

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

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

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

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

  /// Determines the kind of access that should be performed by a
  /// DeclRefExpr or MemberRefExpr use of this value in the specified
  /// context.
  AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC) const;

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

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

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

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

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

  static bool classof(const Decl *D) {
    return D->getKind() >= DeclKind::First_ValueDecl &&
           D->getKind() <= DeclKind::Last_ValueDecl;
  }
  
  /// 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)
  {
    TypeDeclBits.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 TypeDeclBits.CheckedInheritanceClause;
  }

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

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

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

  /// 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 TypeDecl, public GenericContext {
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) {
    return C->getContextKind() == DeclContextKind::GenericTypeDecl;
  }
  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 TypeAliasDeclBits.IsCompatibilityAlias;
  }

  void markAsCompatibilityAlias(bool newValue = true) {
    TypeAliasDeclBits.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) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(GTD);
  }
};

/// 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 {
  unsigned Depth : 16;
  unsigned Index : 16;

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

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

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

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

  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 AssociatedTypeDeclBits.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 (!NominalTypeDeclBits.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);
    NominalTypeDeclBits.HasDelayedMembers = false;
    NominalTypeDeclBits.AddedImplicitInitializers = false;
    ExtensionGeneration = 0;
    NominalTypeDeclBits.HasLazyConformances = false;
    NominalTypeDeclBits.HasValidatedLayout = false;
  }

  friend class ProtocolType;

public:
  using GenericTypeDecl::getASTContext;

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

  /// \brief Does this declaration expose a fixed layout to all resilience
  /// domains?
  ///
  /// For structs, this means clients can assume the number and order of
  /// stored properties will not change.
  ///
  /// For enums, this means clients can assume the number and order of
  /// cases will not change.
  bool hasFixedLayout() const;

  /// \brief Does this declaration expose a fixed layout to the given
  /// module?
  bool hasFixedLayout(ModuleDecl *M, ResilienceExpansion expansion) const;

  /// \brief Returns true if this decl contains delayed value or protocol
  /// declarations.
  bool hasDelayedMembers() const {
    return NominalTypeDeclBits.HasDelayedMembers;
  }
  
  /// \brief Mark this declaration as having delayed members or not.
  void setHasDelayedMembers(bool hasDelayedMembers = true) {
    NominalTypeDeclBits.HasDelayedMembers = hasDelayedMembers;
  }

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

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

  /// Determine whether we have already validated any members
  /// which affect layout.
  bool hasValidatedLayout() const {
    return NominalTypeDeclBits.HasValidatedLayout;
  }

  /// Note that we have attempted to validate any members
  /// which affect layout.
  void setHasValidatedLayout() {
    NominalTypeDeclBits.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);

  /// classifyAsOptionalType - Decide whether this declaration is one
  /// of the library-intrinsic Optional<T> or ImplicitlyUnwrappedOptional<T> types.
  OptionalTypeKind classifyAsOptionalType() const;
  
private:
  /// Predicate used to filter StoredPropertyRange.
  struct ToStoredProperty {
    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) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(GTD);
  }
  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;
  }

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

  /// Insert all of the 'case' element declarations into a DenseSet.
  void getAllElements(llvm::DenseSet<EnumElementDecl*> &elements) const {
    for (auto elt : getAllElements())
      elements.insert(elt);
  }
  
  /// Retrieve the status of circularity checking for class inheritance.
  CircularityCheck getCircularityCheck() const {
    return static_cast<CircularityCheck>(EnumDeclBits.Circularity);
  }
  
  /// Record the current stage of circularity checking.
  void setCircularityCheck(CircularityCheck circularity) {
    EnumDeclBits.Circularity = static_cast<unsigned>(circularity);
  }
  
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const GenericTypeDecl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const NominalTypeDecl *D) {
    return D->getKind() == DeclKind::Enum;
  }
  static bool classof(const DeclContext *C) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(static_cast<const Decl*>(GTD));
  }
  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) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(static_cast<const Decl*>(GTD));
  }
  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 StructDeclBits.HasUnreferenceableStorage;
  }

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

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

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

/// ClassDecl - This is the declaration of a class, for example:
///
///    class Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class ClassDecl 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;

  /// Whether the class has @objc ancestry.
  unsigned ObjCKind : 3;

  unsigned HasMissingDesignatedInitializers : 1;
  unsigned HasMissingVTableEntries : 1;

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

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

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

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

  /// \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>(ClassDeclBits.RawForeignKind);
  }
  void setForeignClassKind(ForeignKind kind) {
    ClassDeclBits.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) {
    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) {
    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 ClassDeclBits.HasDestructorDecl; }

  /// Set the 'has destructor' flag.
  void setHasDestructor() { ClassDeclBits.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) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(static_cast<const Decl*>(GTD));
  }
  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;

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

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

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

  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 (ProtocolDeclBits.RequiresClassValid)
      return ProtocolDeclBits.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) {
    ProtocolDeclBits.RequiresClassValid = true;
    ProtocolDeclBits.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 (ProtocolDeclBits.ExistentialConformsToSelfValid)
      return ProtocolDeclBits.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 (ProtocolDeclBits.ExistentialTypeSupportedValid)
      return ProtocolDeclBits.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) {
    ProtocolDeclBits.ExistentialTypeSupported = supported;
    ProtocolDeclBits.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 (KnownProtocol == 0)
      return None;
    return static_cast<KnownProtocolKind>(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");
    KnownProtocol = static_cast<unsigned>(kind) + 1;
    assert(getKnownProtocolKind() && *getKnownProtocolKind() == kind &&
           "not enough bits");
  }

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

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

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

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

  /// 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, 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) {
    auto GTD = dyn_cast<GenericTypeDecl>(C);
    return GTD && classof(static_cast<const Decl*>(GTD));
  }
  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 not a property accessor.
  NotAccessor = -1,
  /// \brief This is a getter for a property or subscript.
  IsGetter = 0,
  /// \brief This is a setter for a property or subscript.
  IsSetter = 1,
  /// \brief This is a willSet specifier for a property.
  IsWillSet = 2,
  /// \brief This is a didSet specifier for a property.
  IsDidSet = 3,
  /// \brief This is a materializeForSet accessor for a property.
  IsMaterializeForSet = 4,
  /// \brief This is an address-family accessor for a property or
  /// subscript.  It also has an addressor kind.
  IsAddressor = 5,
  /// \brief This is a mutableAddress-family accessor for a property
  /// or subscript.  It also has an addressor kind.
  IsMutableAddressor = 6,
};

/// The safety semantics of this addressor.
enum class AddressorKind : unsigned char {
  /// \brief This is not an addressor.
  NotAddressor,
  /// \brief This is an unsafe addressor; it simply returns an address.
  Unsafe,
  /// \brief This is an owning addressor; it returns 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 {
    FuncDecl *Address = nullptr;        // User-defined address accessor
    FuncDecl *MutableAddress = nullptr; // User-defined mutableAddress accessor

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

  struct alignas(1 << 3) GetSetRecord {
    SourceRange Braces;
    FuncDecl *Get = nullptr;       // User-defined getter
    FuncDecl *Set = nullptr;       // User-defined setter
    FuncDecl *MaterializeForSet = nullptr; // optional materializeForSet accessor

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

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

  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) {
    AbstractStorageDeclBits.StorageKind = unsigned(K);
  }

protected:
  AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
                      SourceLoc NameLoc)
    : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
    AbstractStorageDeclBits.StorageKind = Stored;
    AbstractStorageDeclBits.IsGetterMutating = false;
    AbstractStorageDeclBits.IsSetterMutating = true;
    AbstractStorageDeclBits.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) AbstractStorageDeclBits.StorageKind;
  }

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

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

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

  /// \brief Return true if this object has either an addressor or a
  /// mutable addressor.
  ///
  /// It's generally not appropriate to use this predicate directly in
  /// a condition; instead, you should be switching on the storage
  /// kind.  Only use this for diagnostic, AST exploration, or
  /// assertion purposes.
  bool hasAddressors() const {
    switch (getStorageKind()) {
    case Stored:
    case StoredWithTrivialAccessors:
    case StoredWithObservers:
    case InheritedWithObservers:
    case Computed:
      return false;
    case ComputedWithMutableAddress:
    case Addressed:
    case AddressedWithTrivialAccessors:
    case AddressedWithObservers:
      return true;
    }
    llvm_unreachable("bad storage kind");
  }
  
  /// \brief Return true if reading this storage requires the ability to
  /// modify the base value.
  bool isGetterMutating() const {
    return AbstractStorageDeclBits.IsGetterMutating;
  }
  void setIsGetterMutating(bool isMutating) {
    AbstractStorageDeclBits.IsGetterMutating = isMutating;
  }
  
  /// \brief Return true if modifying this storage requires the ability to
  /// modify the base value.
  bool isSetterMutating() const {
    return AbstractStorageDeclBits.IsSetterMutating;
  }
  void setIsSetterMutating(bool isMutating) {
    AbstractStorageDeclBits.IsSetterMutating = isMutating;
  }

  FuncDecl *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, FuncDecl *Get, FuncDecl *Set,
                    FuncDecl *MaterializeForSet, SourceLoc RBraceLoc);

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

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

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

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

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

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

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

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

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

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

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

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

  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.
  FuncDecl *getMaterializeForSetFunc() const {
    if (auto info = GetSetInfo.getPointer())
      return info->MaterializeForSet;
    return nullptr;
  }

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

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

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

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

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

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

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

  /// Given that this is an Objective-C property or subscript declaration,
  /// produce its setter selector.
  ObjCSelector getObjCSetterSelector(LazyResolver *resolver = nullptr,
                                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() {
    AbstractStorageDeclBits.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 AbstractStorageDeclBits.Overridden; }

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

  /// Returns true if this declaration has a setter accessible from the given
  /// context.
  ///
  /// If \p DC is null, returns true only if the setter is public.
  bool isSetterAccessibleFrom(const DeclContext *DC) const;

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

  /// \brief Does this declaration expose a fixed layout to all resilience
  /// domains?
  ///
  /// Roughly speaking, this means we can make assumptions about whether
  /// the storage is stored or computed, and if stored, the precise access
  /// pattern to be used.
  bool hasFixedLayout() const;

  /// \brief Does this declaration expose a fixed layout to the given
  /// module?
  bool hasFixedLayout(ModuleDecl *M, ResilienceExpansion expansion) 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)
  {
    VarDeclBits.IsStatic = IsStatic;
    VarDeclBits.Specifier = static_cast<unsigned>(Sp);
    VarDeclBits.IsCaptureList = IsCaptureList;
    VarDeclBits.IsDebuggerVar = false;
    VarDeclBits.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>(VarDeclBits.Specifier);
  }
  void setSpecifier(Specifier Spec) {
    VarDeclBits.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 VarDeclBits.IsStatic; }
  void setStatic(bool IsStatic) { VarDeclBits.IsStatic = IsStatic; }

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

  /// Is this an immutable 'let' property?
  bool isLet() const { return getSpecifier() == Specifier::Let; }
  /// Is this an immutable 'shared' property?
  bool isShared() const { return getSpecifier() == Specifier::Shared; }
  
  /// Is this an element in a capture list?
  bool isCaptureList() const { return VarDeclBits.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 VarDeclBits.HasNonPatternBindingInit;
  }
  void setHasNonPatternBindingInit(bool V = true) {
    VarDeclBits.HasNonPatternBindingInit = V;
  }
  
  /// Is this a special debugger variable?
  bool isDebuggerVar() const { return VarDeclBits.IsDebuggerVar; }
  void setDebuggerVar(bool IsDebuggerVar) {
    VarDeclBits.IsDebuggerVar = IsDebuggerVar;
  }

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

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

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

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

  /// Returns true if the name is the self identifier and is implicit.
  bool 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;
  
  /// 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.
  bool IsTypeLocImplicit = false;
  
  /// Information about a symbolic default argument, like #file.
  DefaultArgumentKind defaultArgumentKind = DefaultArgumentKind::None;
  
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 IsTypeLocImplicit; }
  void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
  
  bool isDefaultArgument() const {
    return defaultArgumentKind != DefaultArgumentKind::None;
  }
  DefaultArgumentKind getDefaultArgumentKind() const {
    return defaultArgumentKind;
  }
  void setDefaultArgumentKind(DefaultArgumentKind K) {
    defaultArgumentKind = 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 AbstractStorageDecl, public GenericContext {
  SourceLoc ArrowLoc;
  ParameterList *Indices;
  TypeLoc ElementTy;

public:
  SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices,
                SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                GenericParamList *GenericParams)
    : AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
      GenericContext(DeclContextKind::SubscriptDecl, Parent),
      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(LazyResolver *resolver) 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) {
    return DC->getContextKind() == DeclContextKind::SubscriptDecl;
  }

  using DeclContext::operator new;
  using Decl::getASTContext;
};

/// Encodes imported-as-member status for C functions that get imported
/// as methods.
struct ImportAsMemberStatus {
  // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
  // index of n
  uint8_t rawValue = 0;

  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 ValueDecl, public GenericContext {
public:
  enum class BodyKind {
    /// The function did not have a body in the source code file.
    None,

    /// Function body is delayed, to be parsed later.
    Unparsed,

    /// Function body is parsed and available as an AST subtree.
    Parsed,

    /// Function body is not available, although it was written in the source.
    Skipped,

    /// Function body will be synthesized on demand.
    Synthesize,

    /// Function body is present and type-checked.
    TypeChecked,

    /// This is a memberwise initializer that will be synthesized by SILGen.
    MemberwiseInitializer

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

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

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

protected:
  // If a function has a body at all, we have either a parsed body AST node or
  // we have saved the end location of the unparsed body.
  union {
    /// This enum member is active if getBodyKind() is BodyKind::Parsed or
    /// BodyKind::TypeChecked.
    BraceStmt *Body;

    /// This enum member is active if getBodyKind() == BodyKind::Synthesize.
    BodySynthesizer Synthesizer;

    /// The location of the function body when the body is delayed or skipped.
    ///
    /// This enum member is active if getBodyKind() is BodyKind::Unparsed or
    /// BodyKind::Skipped.
    SourceRange BodyRange;
  };

  CaptureInfo Captures;

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

  ImportAsMemberStatus IAMStatus;

  AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                       SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                       unsigned NumParameterLists,
                       GenericParamList *GenericParams)
      : ValueDecl(Kind, Parent, Name, NameLoc),
        GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
        Body(nullptr), ThrowsLoc(ThrowsLoc) {
    setBodyKind(BodyKind::None);
    setGenericParams(GenericParams);
    AbstractFunctionDeclBits.NumParameterLists = NumParameterLists;
    AbstractFunctionDeclBits.Overridden = false;
    AbstractFunctionDeclBits.Throws = Throws;
    AbstractFunctionDeclBits.NeedsNewVTableEntry = false;
    AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = false;
    AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion =
        unsigned(ResilienceExpansion::Maximal);

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

  void setBodyKind(BodyKind K) {
    AbstractFunctionDeclBits.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
  bool isImportAsMember() const { return IAMStatus.isImportAsMember(); }
  bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); }
  bool isImportAsStaticMember() const { return IAMStatus.isStatic(); }
  uint8_t getSelfIndex() const { return IAMStatus.getSelfIndex(); }
  ImportAsMemberStatus getImportAsMemberStatus() const { return IAMStatus; }

  void setImportAsStaticMember() { IAMStatus.setStatic(); }
  void setSelfIndex(uint8_t idx) { return IAMStatus.setSelfIndex(idx); }

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 AbstractFunctionDeclBits.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) {
    AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = true;
    AbstractFunctionDeclBits.NeedsNewVTableEntry = value;
  }

  bool needsNewVTableEntry() const {
    if (!AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry)
      const_cast<AbstractFunctionDecl *>(this)->computeNeedsNewVTableEntry();
    return AbstractFunctionDeclBits.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(LazyResolver *resolver = nullptr,
                               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 AbstractFunctionDeclBits.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 AbstractFunctionDeclBits.Overridden; }

  /// The declaration has been overridden in the module
  ///
  /// Resolved during type checking
  void setIsOverridden() { AbstractFunctionDeclBits.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(
        AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion);
  }

  /// Set the ResilienceExpansion for default arguments.
  void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) {
    AbstractFunctionDeclBits.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) {
    return DC->getContextKind() == DeclContextKind::AbstractFunctionDecl;
  }
  
  /// 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 final : public AbstractFunctionDecl,
    private llvm::TrailingObjects<FuncDecl, ParameterList *> {
  friend class AbstractFunctionDecl;
  friend TrailingObjects;

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

  TypeLoc FnRetType;

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

  /// Whether this function has a dynamic Self return type.
  unsigned HasDynamicSelf : 1;

  /// Backing bits for 'self' access kind.
  unsigned SelfAccess : 2;
      
  /// \brief If this FuncDecl is an accessor for a property, this indicates
  /// which property and what kind of accessor.
  llvm::PointerIntPair<AbstractStorageDecl*, 3, AccessorKind> AccessorDecl;
  llvm::PointerUnion<FuncDecl *, BehaviorRecord *>
    OverriddenOrBehaviorParamDecl;
  llvm::PointerIntPair<OperatorDecl *, 3,
                       AddressorKind> OperatorAndAddressorKind;

  FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
           SourceLoc FuncLoc,
           DeclName Name, SourceLoc NameLoc,
           bool Throws, SourceLoc ThrowsLoc,
           SourceLoc AccessorKeywordLoc,
           unsigned NumParameterLists,
           GenericParamList *GenericParams, DeclContext *Parent)
    : AbstractFunctionDecl(DeclKind::Func, Parent,
                           Name, NameLoc,
                           Throws, ThrowsLoc,
                           NumParameterLists, GenericParams),
      StaticLoc(StaticLoc), FuncLoc(FuncLoc),
      AccessorKeywordLoc(AccessorKeywordLoc),
      OverriddenOrBehaviorParamDecl(),
      OperatorAndAddressorKind(nullptr, AddressorKind::NotAddressor) {
    FuncDeclBits.IsStatic =
      StaticLoc.isValid() || StaticSpelling != StaticSpellingKind::None;
    FuncDeclBits.StaticSpelling = static_cast<unsigned>(StaticSpelling);
    assert(NumParameterLists > 0 && "Must have at least an empty tuple arg");

    HasDynamicSelf = false;
    ForcedStaticDispatch = false;
    SelfAccess = static_cast<unsigned>(SelfAccessKind::NonMutating);
  }

  static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
                              StaticSpellingKind StaticSpelling,
                              SourceLoc FuncLoc,
                              DeclName Name, SourceLoc NameLoc,
                              bool Throws, SourceLoc ThrowsLoc,
                              SourceLoc AccessorKeywordLoc,
                              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,
                                      SourceLoc AccessorKeywordLoc,
                                      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,
                          SourceLoc AccessorKeywordLoc,
                          GenericParamList *GenericParams,
                          ArrayRef<ParameterList *> ParameterLists,
                          TypeLoc FnRetType, DeclContext *Parent,
                          ClangNode ClangN = ClangNode());

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

  bool isStatic() const {
    return FuncDeclBits.IsStatic;
  }
  /// \returns the way 'static'/'class' was spelled in the source.
  StaticSpellingKind getStaticSpelling() const {
    return static_cast<StaticSpellingKind>(FuncDeclBits.StaticSpelling);
  }
  /// \returns the way 'static'/'class' should be spelled for this declaration.
  StaticSpellingKind getCorrectStaticSpelling() const;
  void setStatic(bool IsStatic = true) {
    FuncDeclBits.IsStatic = IsStatic;
  }
      
  bool isMutating() const {
    return 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>(SelfAccess);
  }
  void setSelfAccessKind(SelfAccessKind mod) {
    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 {getTrailingObjects<ParameterList *>(), getNumParameterLists()};
  }
  ArrayRef<const ParameterList *> getParameterLists() const {
    return {getTrailingObjects<ParameterList *>(), 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 getAccessorKeywordLoc() const {return AccessorKeywordLoc; }

  SourceLoc getStartLoc() const {
    return StaticLoc.isValid() && !isAccessor() ? 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;
  
  /// makeAccessor - Note that this function is an accessor for the given
  /// VarDecl or SubscriptDecl.
  void makeAccessor(AbstractStorageDecl *D, AccessorKind Kind) {
    assert(Kind != AccessorKind::NotAccessor && "Must specify an accessor kind");
    AccessorDecl.setPointerAndInt(D, Kind);
  }

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

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

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

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

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

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

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

  /// Set whether this function has a dynamic \c Self return or not.
  void setDynamicSelf(bool hasDynamicSelf) { 
    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 OperatorAndAddressorKind.getPointer();
  }
  void setOperatorDecl(OperatorDecl *o) {
    assert(isOperator() && "can't set an OperatorDecl for a non-operator");
    OperatorAndAddressorKind.setPointer(o);
  }
  
  /// Returns true if the function is forced to be statically dispatched.
  bool hasForcedStaticDispatch() const {
    return ForcedStaticDispatch;
  }
  void setForcedStaticDispatch(bool flag) {
    ForcedStaticDispatch = flag;
  }

  static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func; }
  static bool classof(const AbstractFunctionDecl *D) {
    return classof(static_cast<const Decl*>(D));
  }
  static bool classof(const DeclContext *DC) {
    if (auto fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    return false;
  }

  /// True if the function is a defer body.
  bool isDeferBody() const;

  /// Perform basic checking to determine whether the @IBAction attribute can
  /// be applied to this function.
  bool isPotentialIBActionTarget() const;
};
  
/// \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;
  
  /// The number of tail-allocated element pointers.
  unsigned NumElements;
  
  EnumCaseDecl(SourceLoc CaseLoc,
               ArrayRef<EnumElementDecl *> Elements,
               DeclContext *DC)
    : Decl(DeclKind::EnumCase, DC),
      CaseLoc(CaseLoc), NumElements(Elements.size())
  {
    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 *>(), 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)
  {
    EnumElementDeclBits.Recursiveness =
        static_cast<unsigned>(ElementRecursiveness::NotRecursive);
    EnumElementDeclBits.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>(EnumElementDeclBits.Recursiveness);
  }
  
  void setRecursiveness(ElementRecursiveness recursiveness) {
    EnumElementDeclBits.Recursiveness = static_cast<unsigned>(recursiveness);
  }

  bool hasAssociatedValues() const {
    return EnumElementDeclBits.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 kind of initializer we have.
  unsigned InitKind : 2;

  /// The failability of this initializer, which is an OptionalTypeKind.
  unsigned 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.
  unsigned HasStubImplementation : 1;

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

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

  /// Whether this is a designated initializer.
  bool isDesignatedInit() const {
    return getInitKind() == CtorInitializerKind::Designated;
  }

  /// Whether this is a convenience initializer.
  bool isConvenienceInit() const {
    return getInitKind() == CtorInitializerKind::Convenience ||
           getInitKind() == CtorInitializerKind::ConvenienceFactory;
  }

  /// Whether this is a factory initializer.
  bool isFactoryInit() const {
    switch (getInitKind()) {
    case CtorInitializerKind::Designated:
    case CtorInitializerKind::Convenience:
      return false;
        
    case CtorInitializerKind::Factory:
    case CtorInitializerKind::ConvenienceFactory:
      return true;
    }
    llvm_unreachable("bad CtorInitializerKind");
  }

  /// Determine whether this initializer is inheritable.
  bool isInheritable() const {
    switch (getInitKind()) {
    case CtorInitializerKind::Designated:
    case CtorInitializerKind::Factory:
      return false;

    case CtorInitializerKind::Convenience:
    case CtorInitializerKind::ConvenienceFactory:
      return true;
    }
    llvm_unreachable("bad CtorInitializerKind");
  }

  /// Determine the failability of the initializer.
  OptionalTypeKind getFailability() const {
    return static_cast<OptionalTypeKind>(Failability);
  }

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

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

  /// Set whether the implementation of this method is a stub that
  /// traps at runtime.
  void setStubImplementation(bool stub) {
    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 fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    return false;
  }
};

/// DestructorDecl - Declares a destructor for a type.  For example:
///
/// \code
/// struct X {
///   var fd : Int
///   deinit {
///      close(fd)
///   }
/// }
/// \endcode
class DestructorDecl : public AbstractFunctionDecl {
  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 fn = dyn_cast<AbstractFunctionDecl>(DC))
      return classof(fn);
    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(PrecedenceGroupDeclBits.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 PrecedenceGroupDeclBits.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) {
    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) {
    MissingMemberDeclBits.NumberOfVTableEntries = vtableEntries;
    assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
    MissingMemberDeclBits.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 MissingMemberDeclBits.NumberOfVTableEntries;
  }

  unsigned getNumberOfFieldOffsetVectorEntries() const {
    return MissingMemberDeclBits.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:
    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()) { }

} // end namespace swift

#endif
