//===--- DeclContext.cpp - DeclContext implementation ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/AST/DeclContext.h"
#include "swift/AST/AccessScope.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/Types.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
using namespace swift;

#define DEBUG_TYPE "Name lookup"

STATISTIC(NumLazyIterableDeclContexts,
          "# of serialized iterable declaration contexts");
STATISTIC(NumUnloadedLazyIterableDeclContexts,
          "# of serialized iterable declaration contexts never loaded");

// Only allow allocation of DeclContext using the allocator in ASTContext.
void *DeclContext::operator new(size_t Bytes, ASTContext &C,
                                unsigned Alignment) {
  return C.Allocate(Bytes, Alignment);
}

ASTContext &DeclContext::getASTContext() const {
  return getParentModule()->getASTContext();
}

GenericTypeDecl *DeclContext::getSelfTypeDecl() const {
  auto decl = const_cast<Decl*>(getAsDecl());
  if (!decl) return nullptr;

  auto ext = dyn_cast<ExtensionDecl>(decl);
  if (!ext) return dyn_cast<GenericTypeDecl>(decl);

  return ext->getExtendedNominal();
}

/// If this DeclContext is a NominalType declaration or an
/// extension thereof, return the NominalTypeDecl.
NominalTypeDecl *DeclContext::getSelfNominalTypeDecl() const {
  return dyn_cast_or_null<NominalTypeDecl>(getSelfTypeDecl());
}


ClassDecl *DeclContext::getSelfClassDecl() const {
  return dyn_cast_or_null<ClassDecl>(getSelfTypeDecl());
}

EnumDecl *DeclContext::getSelfEnumDecl() const {
  return dyn_cast_or_null<EnumDecl>(getSelfTypeDecl());
}

StructDecl *DeclContext::getSelfStructDecl() const {
  return dyn_cast_or_null<StructDecl>(getSelfTypeDecl());
}

ProtocolDecl *DeclContext::getSelfProtocolDecl() const {
  return dyn_cast_or_null<ProtocolDecl>(getSelfTypeDecl());
}

ProtocolDecl *DeclContext::getExtendedProtocolDecl() const {
  if (auto decl = const_cast<Decl*>(getAsDecl()))
    if (auto ED = dyn_cast<ExtensionDecl>(decl))
      return dyn_cast_or_null<ProtocolDecl>(ED->getExtendedNominal());
  return nullptr;
}

GenericTypeParamType *DeclContext::getProtocolSelfType() const {
  assert(getSelfProtocolDecl() && "not a protocol");

  GenericParamList *genericParams;
  if (auto proto = dyn_cast<ProtocolDecl>(this)) {
    genericParams = proto->getGenericParams();
  } else {
    genericParams = cast<ExtensionDecl>(this)->getGenericParams();
  }

  if (genericParams == nullptr)
    return nullptr;

  return genericParams->getParams().front()
      ->getDeclaredInterfaceType()
      ->castTo<GenericTypeParamType>();
}

Type DeclContext::getDeclaredTypeInContext() const {
  if (auto *ED = dyn_cast<ExtensionDecl>(this))
    return ED->mapTypeIntoContext(getDeclaredInterfaceType());
  if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
    return NTD->getDeclaredTypeInContext();
  return Type();
}

Type DeclContext::getDeclaredInterfaceType() const {
  if (auto *ED = dyn_cast<ExtensionDecl>(this)) {
    auto *NTD = ED->getExtendedNominal();
    if (NTD == nullptr)
      return ErrorType::get(ED->getASTContext());
    return NTD->getDeclaredInterfaceType();
  }
  if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
    return NTD->getDeclaredInterfaceType();
  return Type();
}

void DeclContext::forEachGenericContext(
    llvm::function_ref<void (GenericParamList *)> fn) const {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl()) {
      // Extensions do not capture outer generic parameters.
      if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
        for (auto *gpList = ext->getGenericParams();
             gpList != nullptr;
             gpList = gpList->getOuterParameters()) {
          fn(gpList);
        }

        return;
      }

      if (auto genericCtx = decl->getAsGenericContext())
        if (auto *gpList = genericCtx->getGenericParams())
          fn(gpList);
    }
  } while ((dc = dc->getParent()));
}

unsigned DeclContext::getGenericContextDepth() const {
  unsigned depth = -1;
  forEachGenericContext([&](GenericParamList *) { ++depth; });
  return depth;
}

GenericSignature *DeclContext::getGenericSignatureOfContext() const {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl())
      if (auto GC = decl->getAsGenericContext())
        return GC->getGenericSignature();
  } while ((dc = dc->getParent()));

  return nullptr;
}

GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl())
      if (auto GC = decl->getAsGenericContext())
        return GC->getGenericEnvironment();
  } while ((dc = dc->getParent()));

  return nullptr;
}

bool DeclContext::contextHasLazyGenericEnvironment() const {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl())
      if (auto GC = decl->getAsGenericContext())
        return GC->hasLazyGenericEnvironment();
  } while ((dc = dc->getParent()));

  return false;
}

Type DeclContext::mapTypeIntoContext(Type type) const {
  return GenericEnvironment::mapTypeIntoContext(
      getGenericEnvironmentOfContext(), type);
}

DeclContext *DeclContext::getLocalContext() {
  if (isLocalContext())
    return this;
  if (isModuleContext())
    return nullptr;
  return getParent()->getLocalContext();
}

AbstractFunctionDecl *DeclContext::getInnermostMethodContext() {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl()) {
      auto func = dyn_cast<AbstractFunctionDecl>(decl);
      // If we found a non-func decl, we're done.
      if (func == nullptr)
        return nullptr;
      if (func->getDeclContext()->isTypeContext())
        return func;
    }
  } while ((dc = dc->getParent()));

  return nullptr;
}

bool DeclContext::isTypeContext() const {
  if (auto decl = getAsDecl())
    return isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl);
  return false;
}

DeclContext *DeclContext::getInnermostTypeContext() {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl())
      if (isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl))
        return dc;
  } while ((dc = dc->getParent()));

  return nullptr;
}

Decl *DeclContext::getInnermostDeclarationDeclContext() {
  auto DC = this;
  do {
    if (auto decl = DC->getAsDecl())
      return isa<ModuleDecl>(decl) ? nullptr : decl;
  } while ((DC = DC->getParent()));

  return nullptr;
}

DeclContext *DeclContext::getParentForLookup() const {
  if (isa<ProtocolDecl>(this) || isa<ExtensionDecl>(this)) {
    // If we are inside a protocol or an extension, skip directly
    // to the module scope context, without looking at any (invalid)
    // outer types.
    return getModuleScopeContext();
  }
  if (isa<NominalTypeDecl>(this)) {
    // If we are inside a nominal type that is inside a protocol,
    // skip the protocol.
    if (isa<ProtocolDecl>(getParent()))
      return getModuleScopeContext();
  }
  return getParent();
}

ModuleDecl *DeclContext::getParentModule() const {
  const DeclContext *DC = this;
  while (!DC->isModuleContext())
    DC = DC->getParent();
  return const_cast<ModuleDecl *>(cast<ModuleDecl>(DC));
}

SourceFile *DeclContext::getParentSourceFile() const {
  const DeclContext *DC = this;
  while (!DC->isModuleScopeContext())
    DC = DC->getParent();
  return const_cast<SourceFile *>(dyn_cast<SourceFile>(DC));
}

DeclContext *DeclContext::getModuleScopeContext() const {
  auto DC = const_cast<DeclContext*>(this);

  while (true) {
    if (DC->ParentAndKind.getInt() == ASTHierarchy::FileUnit)
      return DC;
    if (auto NextDC = DC->getParent()) {
      DC = NextDC;
    } else {
      assert(isa<ModuleDecl>(DC->getAsDecl()));
      return DC;
    }
  }
}

/// Determine whether the given context is generic at any level.
bool DeclContext::isGenericContext() const {
  auto dc = this;
  do {
    if (auto decl = dc->getAsDecl()) {
      if (auto GC = decl->getAsGenericContext()) {
        if (GC->getGenericParams())
          return true;

        // Extensions do not capture outer generic parameters.
        if (isa<ExtensionDecl>(decl))
          break;
      }
    }
  } while ((dc = dc->getParent()));

  return false;
}

/// Get the most optimal resilience expansion for the body of this function.
/// If the body is able to be inlined into functions in other resilience
/// domains, this ensures that only sufficiently-conservative access patterns
/// are used.
ResilienceExpansion DeclContext::getResilienceExpansion() const {
  for (const auto *dc = this; dc->isLocalContext(); dc = dc->getParent()) {
    // Default argument initializer contexts have their resilience expansion
    // set when they're type checked.
    if (isa<DefaultArgumentInitializer>(dc)) {
      return cast<AbstractFunctionDecl>(dc->getParent())
          ->getDefaultArgumentResilienceExpansion();
    }

    // Stored property initializer contexts use minimal resilience expansion
    // if the type is formally fixed layout.
    if (isa<PatternBindingInitializer>(dc)) {
      if (auto *NTD = dyn_cast<NominalTypeDecl>(dc->getParent())) {
        auto nominalAccess =
          NTD->getFormalAccessScope(/*useDC=*/nullptr,
                                    /*treatUsableFromInlineAsPublic=*/true);
        if (!nominalAccess.isPublic())
          return ResilienceExpansion::Maximal;

        if (NTD->isFormallyResilient())
          return ResilienceExpansion::Maximal;

        return ResilienceExpansion::Minimal;
      }
    }

    if (auto *AFD = dyn_cast<AbstractFunctionDecl>(dc)) {
      // If the function is a nested function, we will serialize its body if
      // we serialize the parent's body.
      if (AFD->getDeclContext()->isLocalContext())
        continue;

      auto funcAccess =
        AFD->getFormalAccessScope(/*useDC=*/nullptr,
                                  /*treatUsableFromInlineAsPublic=*/true);

      // If the function is not externally visible, we will not be serializing
      // its body.
      if (!funcAccess.isPublic())
        break;

      // If the function is public, @_transparent implies @inlinable.
      if (AFD->isTransparent())
        return ResilienceExpansion::Minimal;

      if (AFD->getAttrs().hasAttribute<InlinableAttr>())
        return ResilienceExpansion::Minimal;

      // If a property or subscript is @inlinable, the accessors are
      // @inlinable also.
      if (auto accessor = dyn_cast<AccessorDecl>(AFD))
        if (accessor->getStorage()->getAttrs().getAttribute<InlinableAttr>())
          return ResilienceExpansion::Minimal;
    }
  }

  return ResilienceExpansion::Maximal;
}

/// Determine whether the innermost context is generic.
bool DeclContext::isInnermostContextGeneric() const {
  if (auto Decl = getAsDecl())
    if (auto GC = Decl->getAsGenericContext())
      return GC->isGeneric();
  return false;
}

bool
DeclContext::isCascadingContextForLookup(bool functionsAreNonCascading) const {
  // FIXME: This is explicitly checking for attributes in some cases because
  // it can be called before access control is computed.
  switch (getContextKind()) {
  case DeclContextKind::AbstractClosureExpr:
    break;

  case DeclContextKind::SerializedLocal:
    llvm_unreachable("should not perform lookups in deserialized contexts");

  case DeclContextKind::Initializer:
    // Default arguments still require a type.
    if (isa<DefaultArgumentInitializer>(this))
      return false;
    break;

  case DeclContextKind::TopLevelCodeDecl:
    // FIXME: Pattern initializers at top-level scope end up here.
    return true;

  case DeclContextKind::AbstractFunctionDecl:
    if (functionsAreNonCascading)
      return false;
    break;

  case DeclContextKind::SubscriptDecl:
    break;

  case DeclContextKind::EnumElementDecl:
    break;

  case DeclContextKind::Module:
  case DeclContextKind::FileUnit:
    return true;

  case DeclContextKind::GenericTypeDecl:
    break;

  case DeclContextKind::ExtensionDecl:
    return true;
  }

  return getParent()->isCascadingContextForLookup(true);
}

unsigned DeclContext::getSyntacticDepth() const {
  // Module scope == depth 0.
  if (isModuleScopeContext())
    return 0;

  return 1 + getParent()->getSyntacticDepth();
}

unsigned DeclContext::getSemanticDepth() const {
  // For extensions, count the depth of the nominal type being extended.
  if (isa<ExtensionDecl>(this)) {
    if (auto nominal = getSelfNominalTypeDecl())
      return nominal->getSemanticDepth();

    return 1;
  }

  // Module scope == depth 0.
  if (isModuleScopeContext())
    return 0;

  return 1 + getParent()->getSemanticDepth();
}

bool DeclContext::walkContext(ASTWalker &Walker) {
  switch (getContextKind()) {
  case DeclContextKind::Module:
    return cast<ModuleDecl>(this)->walk(Walker);
  case DeclContextKind::FileUnit:
    return cast<FileUnit>(this)->walk(Walker);
  case DeclContextKind::AbstractClosureExpr:
    return cast<AbstractClosureExpr>(this)->walk(Walker);
  case DeclContextKind::GenericTypeDecl:
    return cast<GenericTypeDecl>(this)->walk(Walker);
  case DeclContextKind::ExtensionDecl:
    return cast<ExtensionDecl>(this)->walk(Walker);
  case DeclContextKind::TopLevelCodeDecl:
    return cast<TopLevelCodeDecl>(this)->walk(Walker);
  case DeclContextKind::AbstractFunctionDecl:
    return cast<AbstractFunctionDecl>(this)->walk(Walker);
  case DeclContextKind::SubscriptDecl:
    return cast<SubscriptDecl>(this)->walk(Walker);
  case DeclContextKind::EnumElementDecl:
    return cast<EnumElementDecl>(this)->walk(Walker);
  case DeclContextKind::SerializedLocal:
    llvm_unreachable("walk is unimplemented for deserialized contexts");
  case DeclContextKind::Initializer:
    // Is there any point in trying to walk the expression?
    return false;
  }
  llvm_unreachable("bad DeclContextKind");
}

void DeclContext::dumpContext() const {
  printContext(llvm::errs());
}

void AccessScope::dump() const {
  llvm::errs() << getAccessLevelSpelling(accessLevelForDiagnostics()) << ": ";

  if (isPublic()) {
    llvm::errs() << "(null)\n";
    return;
  }

  if (auto *file = dyn_cast<SourceFile>(getDeclContext())) {
    llvm::errs() << "file '" << file->getFilename() << "'\n";
    return;
  }

  if (auto *decl = getDeclContext()->getAsDecl()) {
    llvm::errs() << Decl::getKindName(decl->getKind()) << " ";
    if (auto *ext = dyn_cast<ExtensionDecl>(decl))
      llvm::errs() << ext->getExtendedNominal()->getName();
    else if (auto *named = dyn_cast<ValueDecl>(decl))
      llvm::errs() << named->getFullName();
    else
      llvm::errs() << (const void *)decl;

    SourceLoc loc = decl->getLoc();
    if (loc.isValid()) {
      llvm::errs() << " at ";
      loc.print(llvm::errs(), decl->getASTContext().SourceMgr);
    }
    llvm::errs() << "\n";

    return;
  }

  // If all else fails, dump the DeclContext tree.
  getDeclContext()->printContext(llvm::errs());
}

template <typename DCType>
static unsigned getLineNumber(DCType *DC) {
  SourceLoc loc = DC->getLoc();
  if (loc.isInvalid())
    return 0;

  const ASTContext &ctx = static_cast<const DeclContext *>(DC)->getASTContext();
  return ctx.SourceMgr.getLineAndColumn(loc).first;
}

unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
  unsigned Depth = 0;
  if (auto *P = getParent())
    Depth = P->printContext(OS, indent);

  const char *Kind;
  switch (getContextKind()) {
  case DeclContextKind::Module:           Kind = "Module"; break;
  case DeclContextKind::FileUnit:         Kind = "FileUnit"; break;
  case DeclContextKind::SerializedLocal:  Kind = "Serialized Local"; break;
  case DeclContextKind::AbstractClosureExpr:
    Kind = "AbstractClosureExpr";
    break;
  case DeclContextKind::GenericTypeDecl:
    switch (cast<GenericTypeDecl>(this)->getKind()) {
#define DECL(ID, PARENT) \
    case DeclKind::ID: Kind = #ID "Decl"; break;
#include "swift/AST/DeclNodes.def"
    }
    break;
  case DeclContextKind::ExtensionDecl:    Kind = "ExtensionDecl"; break;
  case DeclContextKind::TopLevelCodeDecl: Kind = "TopLevelCodeDecl"; break;
  case DeclContextKind::Initializer:      Kind = "Initializer"; break;
  case DeclContextKind::AbstractFunctionDecl:
    Kind = "AbstractFunctionDecl";
    break;
  case DeclContextKind::SubscriptDecl:    Kind = "SubscriptDecl"; break;
  case DeclContextKind::EnumElementDecl:  Kind = "EnumElementDecl"; break;
  }
  OS.indent(Depth*2 + indent) << (void*)this << " " << Kind;

  switch (getContextKind()) {
  case DeclContextKind::Module:
    OS << " name=" << cast<ModuleDecl>(this)->getName();
    break;
  case DeclContextKind::FileUnit:
    switch (cast<FileUnit>(this)->getKind()) {
    case FileUnitKind::Builtin:
      OS << " Builtin";
      break;
    case FileUnitKind::Source:
      OS << " file=\"" << cast<SourceFile>(this)->getFilename() << "\"";
      break;
    case FileUnitKind::SerializedAST:
    case FileUnitKind::ClangModule:
    case FileUnitKind::DWARFModule:
      OS << " file=\"" << cast<LoadedFile>(this)->getFilename() << "\"";
      break;
    }
    break;
  case DeclContextKind::AbstractClosureExpr:
    OS << " line=" << getLineNumber(cast<AbstractClosureExpr>(this));
    OS << " : " << cast<AbstractClosureExpr>(this)->getType();
    break;
  case DeclContextKind::GenericTypeDecl:
    OS << " name=" << cast<GenericTypeDecl>(this)->getName();
    break;
  case DeclContextKind::ExtensionDecl:
    OS << " line=" << getLineNumber(cast<ExtensionDecl>(this));
    OS << " base=" << cast<ExtensionDecl>(this)->getExtendedType();
    break;
  case DeclContextKind::TopLevelCodeDecl:
    OS << " line=" << getLineNumber(cast<TopLevelCodeDecl>(this));
    break;
  case DeclContextKind::AbstractFunctionDecl: {
    auto *AFD = cast<AbstractFunctionDecl>(this);
    OS << " name=" << AFD->getFullName();
    if (AFD->hasInterfaceType())
      OS << " : " << AFD->getInterfaceType();
    else
      OS << " : (no type set)";
    break;
  }
  case DeclContextKind::SubscriptDecl: {
    auto *SD = cast<SubscriptDecl>(this);
    OS << " name=" << SD->getBaseName();
    if (SD->hasInterfaceType())
      OS << " : " << SD->getInterfaceType();
    else
      OS << " : (no type set)";
    break;
  }
  case DeclContextKind::EnumElementDecl: {
    auto *EED = cast<EnumElementDecl>(this);
    OS << " name=" << EED->getBaseName();
    if (EED->hasInterfaceType())
      OS << " : " << EED->getInterfaceType();
    else
      OS << " : (no type set)";
    break;
  }
  case DeclContextKind::Initializer:
    switch (cast<Initializer>(this)->getInitializerKind()) {
    case InitializerKind::PatternBinding: {
      auto init = cast<PatternBindingInitializer>(this);
      OS << " PatternBinding 0x" << (void*) init->getBinding()
         << " #" << init->getBindingIndex();
      break;
    }
    case InitializerKind::DefaultArgument: {
      auto init = cast<DefaultArgumentInitializer>(this);
      OS << " DefaultArgument index=" << init->getIndex();
      break;
    }
    }
    break;

  case DeclContextKind::SerializedLocal: {
    auto local = cast<SerializedLocalDeclContext>(this);
    switch (local->getLocalDeclContextKind()) {
    case LocalDeclContextKind::AbstractClosure: {
      auto serializedClosure = cast<SerializedAbstractClosureExpr>(local);
      OS << " closure : " << serializedClosure->getType();
      break;
    }
    case LocalDeclContextKind::DefaultArgumentInitializer: {
      auto init = cast<SerializedDefaultArgumentInitializer>(local);
      OS << "DefaultArgument index=" << init->getIndex();
      break;
    }
    case LocalDeclContextKind::PatternBindingInitializer: {
      auto init = cast<SerializedPatternBindingInitializer>(local);
      OS << " PatternBinding 0x" << (void*) init->getBinding()
         << " #" << init->getBindingIndex();
      break;
    }
    case LocalDeclContextKind::TopLevelCodeDecl:
      OS << " TopLevelCode";
      break;
    }
  }
  }

  OS << "\n";
  return Depth + 1;
}

const Decl *
IterableDeclContext::getDecl() const {
  switch (getIterableContextKind()) {
  case IterableDeclContextKind::NominalTypeDecl:
    return cast<NominalTypeDecl>(this);
    break;

  case IterableDeclContextKind::ExtensionDecl:
    return cast<ExtensionDecl>(this);
    break;
  }
  llvm_unreachable("Unhandled IterableDeclContextKind in switch.");
}

ASTContext &IterableDeclContext::getASTContext() const {
  return getDecl()->getASTContext();
}

DeclRange IterableDeclContext::getCurrentMembersWithoutLoading() const {
  return DeclRange(FirstDeclAndLazyMembers.getPointer(), nullptr);
}

DeclRange IterableDeclContext::getMembers() const {
  loadAllMembers();

  return getCurrentMembersWithoutLoading();
}

/// Add a member to this context.
void IterableDeclContext::addMember(Decl *member, Decl *Hint) {
  // Add the member to the list of declarations without notification.
  addMemberSilently(member, Hint);

  // Notify our parent declaration that we have added the member, which can
  // be used to update the lookup tables.
  switch (getIterableContextKind()) {
  case IterableDeclContextKind::NominalTypeDecl: {
    auto nominal = cast<NominalTypeDecl>(this);
    nominal->addedMember(member);
    assert(member->getDeclContext() == nominal &&
           "Added member to the wrong context");
    break;
  }

  case IterableDeclContextKind::ExtensionDecl: {
    auto ext = cast<ExtensionDecl>(this);
    ext->addedMember(member);
    assert(member->getDeclContext() == ext &&
           "Added member to the wrong context");
    break;
  }
  }
}

void IterableDeclContext::addMemberSilently(Decl *member, Decl *hint) const {
  assert(!member->NextDecl && "Already added to a container");

  // If there is a hint decl that specifies where to add this, just
  // link into the chain immediately following it.
  if (hint) {
    member->NextDecl = hint->NextDecl;
    hint->NextDecl = member;

    // If the hint was the last in the parent context's chain, update it.
    if (LastDeclAndKind.getPointer() == hint)
      LastDeclAndKind.setPointer(member);
    return;
  }

  if (auto last = LastDeclAndKind.getPointer()) {
    last->NextDecl = member;
    assert(last != member && "Simple cycle in decl list");
  } else {
    FirstDeclAndLazyMembers.setPointer(member);
  }
  LastDeclAndKind.setPointer(member);
}

void IterableDeclContext::setMemberLoader(LazyMemberLoader *loader,
                                          uint64_t contextData) {
  assert(!hasLazyMembers() && "already have lazy members");

  ASTContext &ctx = getASTContext();
  auto contextInfo = ctx.getOrCreateLazyIterableContextData(this, loader);
  auto lazyMembers = FirstDeclAndLazyMembers.getInt() | LazyMembers::Present;
  FirstDeclAndLazyMembers.setInt(LazyMembers(lazyMembers));
  contextInfo->memberData = contextData;

  ++NumLazyIterableDeclContexts;
  ++NumUnloadedLazyIterableDeclContexts;
  // FIXME: (transitional) increment the redundant "always-on" counter.
  if (auto s = ctx.Stats) {
    ++s->getFrontendCounters().NumLazyIterableDeclContexts;
    ++s->getFrontendCounters().NumUnloadedLazyIterableDeclContexts;
  }
}

void IterableDeclContext::loadAllMembers() const {
  // Lazily parse members.
  getASTContext().parseMembers(const_cast<IterableDeclContext*>(this));
  if (!hasLazyMembers())
    return;

  // Don't try to load all members re-entrant-ly.
  ASTContext &ctx = getASTContext();
  auto contextInfo = ctx.getOrCreateLazyIterableContextData(this,
    /*lazyLoader=*/nullptr);
  auto lazyMembers = FirstDeclAndLazyMembers.getInt() & ~LazyMembers::Present;
  FirstDeclAndLazyMembers.setInt(LazyMembers(lazyMembers));

  const Decl *container = getDecl();
  contextInfo->loader->loadAllMembers(const_cast<Decl *>(container),
                                      contextInfo->memberData);

  --NumUnloadedLazyIterableDeclContexts;
  // FIXME: (transitional) decrement the redundant "always-on" counter.
  if (auto s = ctx.Stats)
    s->getFrontendCounters().NumUnloadedLazyIterableDeclContexts--;
}

bool IterableDeclContext::wasDeserialized() const {
  const DeclContext *DC = cast<DeclContext>(getDecl());
  if (auto F = dyn_cast<FileUnit>(DC->getModuleScopeContext())) {
    return F->getKind() == FileUnitKind::SerializedAST;
  }
  return false;
}

bool IterableDeclContext::classof(const Decl *D) {
  switch (D->getKind()) {
  default: return false;
#define DECL(ID, PARENT) // See previous line
#define ITERABLE_DECL(ID, PARENT) \
  case DeclKind::ID: return true;
#include "swift/AST/DeclNodes.def"
  }
}

IterableDeclContext *
IterableDeclContext::castDeclToIterableDeclContext(const Decl *D) {
  switch (D->getKind()) {
  default: llvm_unreachable("Decl is not a IterableDeclContext.");
#define DECL(ID, PARENT) // See previous line
#define ITERABLE_DECL(ID, PARENT) \
  case DeclKind::ID: \
    return const_cast<IterableDeclContext *>( \
        static_cast<const IterableDeclContext*>(cast<ID##Decl>(D)));
#include "swift/AST/DeclNodes.def"
  }
}

/// Return the DeclContext to compare when checking private access in
/// Swift 4 mode. The context returned is the type declaration if the context
/// and the type declaration are in the same file, otherwise it is the types
/// last extension in the source file. If the context does not refer to a
/// declaration or extension, the supplied context is returned.
static const DeclContext *
getPrivateDeclContext(const DeclContext *DC, const SourceFile *useSF) {
  auto NTD = DC->getSelfNominalTypeDecl();
  if (!NTD)
    return DC;

  // use the type declaration as the private scope if it is in the same
  // file as useSF. This occurs for both extensions and declarations.
  if (NTD->getParentSourceFile() == useSF)
    return NTD;

  // Otherwise use the last extension declaration in the same file.
  const DeclContext *lastExtension = nullptr;
  for (ExtensionDecl *ED : NTD->getExtensions())
    if (ED->getParentSourceFile() == useSF)
      lastExtension = ED;

  // If there's no last extension, return the supplied context.
  return lastExtension ? lastExtension : DC;
}

AccessScope::AccessScope(const DeclContext *DC, bool isPrivate)
    : Value(DC, isPrivate) {
  if (isPrivate) {
    DC = getPrivateDeclContext(DC, DC->getParentSourceFile());
    Value.setPointer(DC);
  }
  if (!DC || isa<ModuleDecl>(DC))
    assert(!isPrivate && "public or internal scope can't be private");
}

bool AccessScope::isFileScope() const {
  auto DC = getDeclContext();
  return DC && isa<FileUnit>(DC);
}

bool AccessScope::isInternal() const {
  auto DC = getDeclContext();
  return DC && isa<ModuleDecl>(DC);
}

AccessLevel AccessScope::accessLevelForDiagnostics() const {
  if (isPublic())
    return AccessLevel::Public;
  if (isa<ModuleDecl>(getDeclContext()))
    return AccessLevel::Internal;
  if (getDeclContext()->isModuleScopeContext()) {
    return isPrivate() ? AccessLevel::Private : AccessLevel::FilePrivate;
  }

  return AccessLevel::Private;
}

bool AccessScope::allowsPrivateAccess(const DeclContext *useDC, const DeclContext *sourceDC) {
  // Check the lexical scope.
  if (useDC->isChildContextOf(sourceDC))
    return true;

  // Do not allow access if the sourceDC is in a different file
  auto useSF = useDC->getParentSourceFile();
  if (useSF != sourceDC->getParentSourceFile())
    return false;

  // Do not allow access if the sourceDC does not represent a type.
  auto sourceNTD = sourceDC->getSelfNominalTypeDecl();
  if (!sourceNTD)
    return false;

  // Compare the private scopes and iterate over the parent types.
  sourceDC = getPrivateDeclContext(sourceDC, useSF);
  while (!useDC->isModuleContext()) {
    useDC = getPrivateDeclContext(useDC, useSF);
    if (useDC == sourceDC)
      return true;

    // Get the parent type. If the context represents a type, look at the types
    // declaring context instead of the contexts parent. This will crawl up
    // the type hierarchy in nested extensions correctly.
    if (auto NTD = useDC->getSelfNominalTypeDecl())
      useDC = NTD->getDeclContext();
    else
      useDC = useDC->getParent();
  }

  return false;
}

DeclContext *Decl::getDeclContextForModule() const {
  if (auto module = dyn_cast<ModuleDecl>(this))
    return const_cast<ModuleDecl *>(module);

  return nullptr;
}

DeclContextKind DeclContext::getContextKind() const {
  switch (ParentAndKind.getInt()) {
  case ASTHierarchy::Expr:
    return DeclContextKind::AbstractClosureExpr;
  case ASTHierarchy::Initializer:
    return DeclContextKind::Initializer;
  case ASTHierarchy::SerializedLocal:
    return DeclContextKind::SerializedLocal;
  case ASTHierarchy::FileUnit:
    return DeclContextKind::FileUnit;
  case ASTHierarchy::Decl: {
    auto decl = reinterpret_cast<const Decl*>(this + 1);
    if (isa<AbstractFunctionDecl>(decl))
      return DeclContextKind::AbstractFunctionDecl;
    if (isa<GenericTypeDecl>(decl))
      return DeclContextKind::GenericTypeDecl;
    switch (decl->getKind()) {
    case DeclKind::Module:
      return DeclContextKind::Module;
    case DeclKind::TopLevelCode:
      return DeclContextKind::TopLevelCodeDecl;
    case DeclKind::Subscript:
      return DeclContextKind::SubscriptDecl;
    case DeclKind::EnumElement:
      return DeclContextKind::EnumElementDecl;
    case DeclKind::Extension:
      return DeclContextKind::ExtensionDecl;
    default:
      llvm_unreachable("Unhandled Decl kind");
    }
  }
  }
  llvm_unreachable("Unhandled DeclContext ASTHierarchy");
}

#define DECL(Id, Parent) \
  static_assert(!std::is_base_of<DeclContext, Id##Decl>::value, \
                "Non-context Decl node has context?");
#define CONTEXT_DECL(Id, Parent) \
  static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
  static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
                "CONTEXT_DECL nodes must inherit from DeclContext");
#define CONTEXT_VALUE_DECL(Id, Parent) \
  static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
  static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
                "CONTEXT_VALUE_DECL nodes must inherit from DeclContext");
#include "swift/AST/DeclNodes.def"

#define EXPR(Id, Parent) \
  static_assert(!std::is_base_of<DeclContext, Id##Expr>::value, \
                "Non-context Expr node has context?");
#define CONTEXT_EXPR(Id, Parent) \
  static_assert(alignof(DeclContext) == alignof(Id##Expr), "Alignment error"); \
  static_assert(std::is_base_of<DeclContext, Id##Expr>::value, \
                "CONTEXT_EXPR nodes must inherit from DeclContext");
#include "swift/AST/ExprNodes.def"

#ifndef NDEBUG
// XXX -- static_cast is not static enough for use with static_assert().
// DO verify this by temporarily breaking a Decl or Expr.
// DO NOT assume that the compiler will emit this code blindly.
SWIFT_CONSTRUCTOR
static void verify_DeclContext_is_start_of_node() {
  auto decl = reinterpret_cast<Decl*>(0x1000 + sizeof(DeclContext));
#define DECL(Id, Parent)
#define CONTEXT_DECL(Id, Parent) \
  assert(reinterpret_cast<DeclContext*>(0x1000) == \
         static_cast<Id##Decl*>(decl));
#define CONTEXT_VALUE_DECL(Id, Parent) \
  assert(reinterpret_cast<DeclContext*>(0x1000) == \
         static_cast<Id##Decl*>(decl));
#include "swift/AST/DeclNodes.def"

  auto expr = reinterpret_cast<Expr*>(0x1000 + sizeof(DeclContext));
#define EXPR(Id, Parent)
#define CONTEXT_EXPR(Id, Parent) \
  assert(reinterpret_cast<DeclContext*>(0x1000) == \
         static_cast<Id##Expr*>(expr));
#include "swift/AST/ExprNodes.def"
}
#endif
