//===--- SemaModule.cpp - Semantic Analysis for Modules -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for modules (C++ modules syntax,
//  Objective-C modules syntax, and Clang header modules).
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static void checkModuleImportContext(Sema &S, Module *M,
                                     SourceLocation ImportLoc, DeclContext *DC,
                                     bool FromInclude = false) {
  SourceLocation ExternCLoc;

  if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
    switch (LSD->getLanguage()) {
    case LinkageSpecLanguageIDs::C:
      if (ExternCLoc.isInvalid())
        ExternCLoc = LSD->getBeginLoc();
      break;
    case LinkageSpecLanguageIDs::CXX:
      break;
    }
    DC = LSD->getParent();
  }

  while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC))
    DC = DC->getParent();

  if (!isa<TranslationUnitDecl>(DC)) {
    S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M))
                          ? diag::ext_module_import_not_at_top_level_noop
                          : diag::err_module_import_not_at_top_level_fatal)
        << M->getFullModuleName() << DC;
    S.Diag(cast<Decl>(DC)->getBeginLoc(),
           diag::note_module_import_not_at_top_level)
        << DC;
  } else if (!M->IsExternC && ExternCLoc.isValid()) {
    S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
      << M->getFullModuleName();
    S.Diag(ExternCLoc, diag::note_extern_c_begins_here);
  }
}

/// Helper function for makeTransitiveImportsVisible to decide whether
/// the \param Imported module unit is in the same module with the \param
/// CurrentModule.
/// \param FoundPrimaryModuleInterface is a helper parameter to record the
/// primary module interface unit corresponding to the module \param
/// CurrentModule. Since currently it is expensive to decide whether two module
/// units come from the same module by comparing the module name.
static bool
isImportingModuleUnitFromSameModule(ASTContext &Ctx, Module *Imported,
                                    Module *CurrentModule,
                                    Module *&FoundPrimaryModuleInterface) {
  if (!Imported->isNamedModule())
    return false;

  // The a partition unit we're importing must be in the same module of the
  // current module.
  if (Imported->isModulePartition())
    return true;

  // If we found the primary module interface during the search process, we can
  // return quickly to avoid expensive string comparison.
  if (FoundPrimaryModuleInterface)
    return Imported == FoundPrimaryModuleInterface;

  if (!CurrentModule)
    return false;

  // Then the imported module must be a primary module interface unit.  It
  // is only allowed to import the primary module interface unit from the same
  // module in the implementation unit and the implementation partition unit.

  // Since we'll handle implementation unit above. We can only care
  // about the implementation partition unit here.
  if (!CurrentModule->isModulePartitionImplementation())
    return false;

  if (Ctx.isInSameModule(Imported, CurrentModule)) {
    assert(!FoundPrimaryModuleInterface ||
           FoundPrimaryModuleInterface == Imported);
    FoundPrimaryModuleInterface = Imported;
    return true;
  }

  return false;
}

/// [module.import]p7:
///   Additionally, when a module-import-declaration in a module unit of some
///   module M imports another module unit U of M, it also imports all
///   translation units imported by non-exported module-import-declarations in
///   the module unit purview of U. These rules can in turn lead to the
///   importation of yet more translation units.
static void
makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules,
                             Module *Imported, Module *CurrentModule,
                             SourceLocation ImportLoc,
                             bool IsImportingPrimaryModuleInterface = false) {
  assert(Imported->isNamedModule() &&
         "'makeTransitiveImportsVisible()' is intended for standard C++ named "
         "modules only.");

  llvm::SmallVector<Module *, 4> Worklist;
  llvm::SmallPtrSet<Module *, 16> Visited;
  Worklist.push_back(Imported);

  Module *FoundPrimaryModuleInterface =
      IsImportingPrimaryModuleInterface ? Imported : nullptr;

  while (!Worklist.empty()) {
    Module *Importing = Worklist.pop_back_val();

    if (Visited.count(Importing))
      continue;
    Visited.insert(Importing);

    // FIXME: The ImportLoc here is not meaningful. It may be problematic if we
    // use the sourcelocation loaded from the visible modules.
    VisibleModules.setVisible(Importing, ImportLoc);

    if (isImportingModuleUnitFromSameModule(Ctx, Importing, CurrentModule,
                                            FoundPrimaryModuleInterface)) {
      for (Module *TransImported : Importing->Imports)
        Worklist.push_back(TransImported);

      for (auto [Exports, _] : Importing->Exports)
        Worklist.push_back(Exports);
    }
  }
}

Sema::DeclGroupPtrTy
Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {
  // We start in the global module;
  Module *GlobalModule =
      PushGlobalModuleFragment(ModuleLoc);

  // All declarations created from now on are owned by the global module.
  auto *TU = Context.getTranslationUnitDecl();
  // [module.global.frag]p2
  // A global-module-fragment specifies the contents of the global module
  // fragment for a module unit. The global module fragment can be used to
  // provide declarations that are attached to the global module and usable
  // within the module unit.
  //
  // So the declations in the global module shouldn't be visible by default.
  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
  TU->setLocalOwningModule(GlobalModule);

  // FIXME: Consider creating an explicit representation of this declaration.
  return nullptr;
}

void Sema::HandleStartOfHeaderUnit() {
  assert(getLangOpts().CPlusPlusModules &&
         "Header units are only valid for C++20 modules");
  SourceLocation StartOfTU =
      SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());

  StringRef HUName = getLangOpts().CurrentModule;
  if (HUName.empty()) {
    HUName =
        SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID())->getName();
    const_cast<LangOptions &>(getLangOpts()).CurrentModule = HUName.str();
  }

  // TODO: Make the C++20 header lookup independent.
  // When the input is pre-processed source, we need a file ref to the original
  // file for the header map.
  auto F = SourceMgr.getFileManager().getOptionalFileRef(HUName);
  // For the sake of error recovery (if someone has moved the original header
  // after creating the pre-processed output) fall back to obtaining the file
  // ref for the input file, which must be present.
  if (!F)
    F = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
  assert(F && "failed to find the header unit source?");
  Module::Header H{HUName.str(), HUName.str(), *F};
  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
  Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
  assert(Mod && "module creation should not fail");
  ModuleScopes.push_back({}); // No GMF
  ModuleScopes.back().BeginLoc = StartOfTU;
  ModuleScopes.back().Module = Mod;
  VisibleModules.setVisible(Mod, StartOfTU);

  // From now on, we have an owning module for all declarations we see.
  // All of these are implicitly exported.
  auto *TU = Context.getTranslationUnitDecl();
  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
  TU->setLocalOwningModule(Mod);
}

/// Tests whether the given identifier is reserved as a module name and
/// diagnoses if it is. Returns true if a diagnostic is emitted and false
/// otherwise.
static bool DiagReservedModuleName(Sema &S, const IdentifierInfo *II,
                                   SourceLocation Loc) {
  enum {
    Valid = -1,
    Invalid = 0,
    Reserved = 1,
  } Reason = Valid;

  if (II->isStr("module") || II->isStr("import"))
    Reason = Invalid;
  else if (II->isReserved(S.getLangOpts()) !=
           ReservedIdentifierStatus::NotReserved)
    Reason = Reserved;

  // If the identifier is reserved (not invalid) but is in a system header,
  // we do not diagnose (because we expect system headers to use reserved
  // identifiers).
  if (Reason == Reserved && S.getSourceManager().isInSystemHeader(Loc))
    Reason = Valid;

  switch (Reason) {
  case Valid:
    return false;
  case Invalid:
    return S.Diag(Loc, diag::err_invalid_module_name) << II;
  case Reserved:
    S.Diag(Loc, diag::warn_reserved_module_name) << II;
    return false;
  }
  llvm_unreachable("fell off a fully covered switch");
}

Sema::DeclGroupPtrTy
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
                      ModuleDeclKind MDK, ModuleIdPath Path,
                      ModuleIdPath Partition, ModuleImportState &ImportState,
                      bool SeenNoTrivialPPDirective) {
  assert(getLangOpts().CPlusPlusModules &&
         "should only have module decl in standard C++ modules");

  bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
  bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
  // If any of the steps here fail, we count that as invalidating C++20
  // module state;
  ImportState = ModuleImportState::NotACXX20Module;

  bool IsPartition = !Partition.empty();
  if (IsPartition)
    switch (MDK) {
    case ModuleDeclKind::Implementation:
      MDK = ModuleDeclKind::PartitionImplementation;
      break;
    case ModuleDeclKind::Interface:
      MDK = ModuleDeclKind::PartitionInterface;
      break;
    default:
      llvm_unreachable("how did we get a partition type set?");
    }

  // A (non-partition) module implementation unit requires that we are not
  // compiling a module of any kind.  A partition implementation emits an
  // interface (and the AST for the implementation), which will subsequently
  // be consumed to emit a binary.
  // A module interface unit requires that we are not compiling a module map.
  switch (getLangOpts().getCompilingModule()) {
  case LangOptions::CMK_None:
    // It's OK to compile a module interface as a normal translation unit.
    break;

  case LangOptions::CMK_ModuleInterface:
    if (MDK != ModuleDeclKind::Implementation)
      break;

    // We were asked to compile a module interface unit but this is a module
    // implementation unit.
    Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
        << FixItHint::CreateInsertion(ModuleLoc, "export ");
    MDK = ModuleDeclKind::Interface;
    break;

  case LangOptions::CMK_ModuleMap:
    Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);
    return nullptr;

  case LangOptions::CMK_HeaderUnit:
    Diag(ModuleLoc, diag::err_module_decl_in_header_unit);
    return nullptr;
  }

  assert(ModuleScopes.size() <= 1 && "expected to be at global module scope");

  // FIXME: Most of this work should be done by the preprocessor rather than
  // here, in order to support macro import.

  // Only one module-declaration is permitted per source file.
  if (isCurrentModulePurview()) {
    Diag(ModuleLoc, diag::err_module_redeclaration);
    Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module),
         diag::note_prev_module_declaration);
    return nullptr;
  }

  assert((!getLangOpts().CPlusPlusModules ||
          SeenGMF == (bool)this->TheGlobalModuleFragment) &&
         "mismatched global module state");

  // In C++20, A module directive may only appear as the first preprocessing
  // tokens in a file (excluding the global module fragment.).
  if (getLangOpts().CPlusPlusModules &&
      (!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {
    Diag(ModuleLoc, diag::err_module_decl_not_at_start);
    SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();
    Diag(BeginLoc, diag::note_global_module_introducer_missing)
        << FixItHint::CreateInsertion(BeginLoc, "module;\n");
  }

  // C++23 [module.unit]p1: ... The identifiers module and import shall not
  // appear as identifiers in a module-name or module-partition. All
  // module-names either beginning with an identifier consisting of std
  // followed by zero or more digits or containing a reserved identifier
  // ([lex.name]) are reserved and shall not be specified in a
  // module-declaration; no diagnostic is required.

  // Test the first part of the path to see if it's std[0-9]+ but allow the
  // name in a system header.
  StringRef FirstComponentName = Path[0].getIdentifierInfo()->getName();
  if (!getSourceManager().isInSystemHeader(Path[0].getLoc()) &&
      (FirstComponentName == "std" ||
       (FirstComponentName.starts_with("std") &&
        llvm::all_of(FirstComponentName.drop_front(3), &llvm::isDigit))))
    Diag(Path[0].getLoc(), diag::warn_reserved_module_name)
        << Path[0].getIdentifierInfo();

  // Then test all of the components in the path to see if any of them are
  // using another kind of reserved or invalid identifier.
  for (auto Part : Path) {
    if (DiagReservedModuleName(*this, Part.getIdentifierInfo(), Part.getLoc()))
      return nullptr;
  }

  // Flatten the dots in a module name. Unlike Clang's hierarchical module map
  // modules, the dots here are just another character that can appear in a
  // module name.
  std::string ModuleName = ModuleLoader::getFlatNameFromPath(Path);
  if (IsPartition) {
    ModuleName += ":";
    ModuleName += ModuleLoader::getFlatNameFromPath(Partition);
  }
  // If a module name was explicitly specified on the command line, it must be
  // correct.
  if (!getLangOpts().CurrentModule.empty() &&
      getLangOpts().CurrentModule != ModuleName) {
    Diag(Path.front().getLoc(), diag::err_current_module_name_mismatch)
        << SourceRange(Path.front().getLoc(), IsPartition
                                                  ? Partition.back().getLoc()
                                                  : Path.back().getLoc())
        << getLangOpts().CurrentModule;
    return nullptr;
  }
  const_cast<LangOptions &>(getLangOpts()).CurrentModule = ModuleName;

  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
  Module *Mod;                 // The module we are creating.
  Module *Interface = nullptr; // The interface for an implementation.
  switch (MDK) {
  case ModuleDeclKind::Interface:
  case ModuleDeclKind::PartitionInterface: {
    // We can't have parsed or imported a definition of this module or parsed a
    // module map defining it already.
    if (auto *M = Map.findOrLoadModule(ModuleName)) {
      Diag(Path[0].getLoc(), diag::err_module_redefinition) << ModuleName;
      if (M->DefinitionLoc.isValid())
        Diag(M->DefinitionLoc, diag::note_prev_module_definition);
      else if (const ModuleFileName *FileName = M->getASTFileName())
        Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
            << *FileName;
      Mod = M;
      break;
    }

    // Create a Module for the module that we're defining.
    Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
    if (MDK == ModuleDeclKind::PartitionInterface)
      Mod->Kind = Module::ModulePartitionInterface;
    assert(Mod && "module creation should not fail");
    break;
  }

  case ModuleDeclKind::Implementation: {
    // C++20 A module-declaration that contains neither an export-
    // keyword nor a module-partition implicitly imports the primary
    // module interface unit of the module as if by a module-import-
    // declaration.
    IdentifierLoc ModuleNameLoc(Path[0].getLoc(),
                                PP.getIdentifierInfo(ModuleName));

    // The module loader will assume we're trying to import the module that
    // we're building if `LangOpts.CurrentModule` equals to 'ModuleName'.
    // Change the value for `LangOpts.CurrentModule` temporarily to make the
    // module loader work properly.
    const_cast<LangOptions &>(getLangOpts()).CurrentModule = "";
    Interface = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
                                             Module::AllVisible,
                                             /*IsInclusionDirective=*/false);
    const_cast<LangOptions &>(getLangOpts()).CurrentModule = ModuleName;

    if (!Interface) {
      Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
      // Create an empty module interface unit for error recovery.
      Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
    } else {
      Mod = Map.createModuleForImplementationUnit(ModuleLoc, ModuleName);
    }
  } break;

  case ModuleDeclKind::PartitionImplementation:
    // Create an interface, but note that it is an implementation
    // unit.
    Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
    Mod->Kind = Module::ModulePartitionImplementation;
    break;
  }

  if (!this->TheGlobalModuleFragment) {
    ModuleScopes.push_back({});
    if (getLangOpts().ModulesLocalVisibility)
      ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
  } else {
    // We're done with the global module fragment now.
    ActOnEndOfTranslationUnitFragment(TUFragmentKind::Global);
  }

  // Switch from the global module fragment (if any) to the named module.
  ModuleScopes.back().BeginLoc = StartLoc;
  ModuleScopes.back().Module = Mod;
  VisibleModules.setVisible(Mod, ModuleLoc);

  // From now on, we have an owning module for all declarations we see.
  // In C++20 modules, those declaration would be reachable when imported
  // unless explicitily exported.
  // Otherwise, those declarations are module-private unless explicitly
  // exported.
  auto *TU = Context.getTranslationUnitDecl();
  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
  TU->setLocalOwningModule(Mod);

  // We are in the module purview, but before any other (non import)
  // statements, so imports are allowed.
  ImportState = ModuleImportState::ImportAllowed;

  getASTContext().setCurrentNamedModule(Mod);

  // We already potentially made an implicit import (in the case of a module
  // implementation unit importing its interface).  Make this module visible
  // and return the import decl to be added to the current TU.
  if (Interface) {
    HadImportedNamedModules = true;

    makeTransitiveImportsVisible(getASTContext(), VisibleModules, Interface,
                                 Mod, ModuleLoc,
                                 /*IsImportingPrimaryModuleInterface=*/true);

    // Make the import decl for the interface in the impl module.
    ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,
                                            Interface, Path[0].getLoc());
    CurContext->addDecl(Import);

    // Sequence initialization of the imported module before that of the current
    // module, if any.
    Context.addModuleInitializer(ModuleScopes.back().Module, Import);
    Mod->Imports.push_back(Interface); // As if we imported it.
    // Also save this as a shortcut to checking for decls in the interface
    ThePrimaryInterface = Interface;
    // If we made an implicit import of the module interface, then return the
    // imported module decl.
    return ConvertDeclToDeclGroup(Import);
  }

  return nullptr;
}

Sema::DeclGroupPtrTy
Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
                                     SourceLocation PrivateLoc) {
  // C++20 [basic.link]/2:
  //   A private-module-fragment shall appear only in a primary module
  //   interface unit.
  switch (ModuleScopes.empty() ? Module::ExplicitGlobalModuleFragment
                               : ModuleScopes.back().Module->Kind) {
  case Module::ModuleMapModule:
  case Module::ExplicitGlobalModuleFragment:
  case Module::ImplicitGlobalModuleFragment:
  case Module::ModulePartitionImplementation:
  case Module::ModulePartitionInterface:
  case Module::ModuleHeaderUnit:
    Diag(PrivateLoc, diag::err_private_module_fragment_not_module);
    return nullptr;

  case Module::PrivateModuleFragment:
    Diag(PrivateLoc, diag::err_private_module_fragment_redefined);
    Diag(ModuleScopes.back().BeginLoc, diag::note_previous_definition);
    return nullptr;

  case Module::ModuleImplementationUnit:
    Diag(PrivateLoc, diag::err_private_module_fragment_not_module_interface);
    Diag(ModuleScopes.back().BeginLoc,
         diag::note_not_module_interface_add_export)
        << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");
    return nullptr;

  case Module::ModuleInterfaceUnit:
    break;
  }

  // FIXME: Check that this translation unit does not import any partitions;
  // such imports would violate [basic.link]/2's "shall be the only module unit"
  // restriction.

  // We've finished the public fragment of the translation unit.
  ActOnEndOfTranslationUnitFragment(TUFragmentKind::Normal);

  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
  Module *PrivateModuleFragment =
      Map.createPrivateModuleFragmentForInterfaceUnit(
          ModuleScopes.back().Module, PrivateLoc);
  assert(PrivateModuleFragment && "module creation should not fail");

  // Enter the scope of the private module fragment.
  ModuleScopes.push_back({});
  ModuleScopes.back().BeginLoc = ModuleLoc;
  ModuleScopes.back().Module = PrivateModuleFragment;
  VisibleModules.setVisible(PrivateModuleFragment, ModuleLoc);

  // All declarations created from now on are scoped to the private module
  // fragment (and are neither visible nor reachable in importers of the module
  // interface).
  auto *TU = Context.getTranslationUnitDecl();
  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
  TU->setLocalOwningModule(PrivateModuleFragment);

  // FIXME: Consider creating an explicit representation of this declaration.
  return nullptr;
}

DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
                                   SourceLocation ExportLoc,
                                   SourceLocation ImportLoc, ModuleIdPath Path,
                                   bool IsPartition) {
  assert((!IsPartition || getLangOpts().CPlusPlusModules) &&
         "partition seen in non-C++20 code?");

  // For a C++20 module name, flatten into a single identifier with the source
  // location of the first component.
  IdentifierLoc ModuleNameLoc;

  std::string ModuleName;
  if (IsPartition) {
    // We already checked that we are in a module purview in the parser.
    assert(!ModuleScopes.empty() && "in a module purview, but no module?");
    Module *NamedMod = ModuleScopes.back().Module;
    // If we are importing into a partition, find the owning named module,
    // otherwise, the name of the importing named module.
    ModuleName = NamedMod->getPrimaryModuleInterfaceName().str();
    ModuleName += ":";
    ModuleName += ModuleLoader::getFlatNameFromPath(Path);
    ModuleNameLoc =
        IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName));
    Path = ModuleIdPath(ModuleNameLoc);
  } else if (getLangOpts().CPlusPlusModules) {
    ModuleName = ModuleLoader::getFlatNameFromPath(Path);
    ModuleNameLoc =
        IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName));
    Path = ModuleIdPath(ModuleNameLoc);
  }

  // Diagnose self-import before attempting a load.
  // [module.import]/9
  // A module implementation unit of a module M that is not a module partition
  // shall not contain a module-import-declaration nominating M.
  // (for an implementation, the module interface is imported implicitly,
  //  but that's handled in the module decl code).

  if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&
      getCurrentModule()->Name == ModuleName) {
    Diag(ImportLoc, diag::err_module_self_import_cxx20)
        << ModuleName << currentModuleIsImplementation();
    return true;
  }

  Module *Mod = getModuleLoader().loadModule(
      ImportLoc, Path, Module::AllVisible, /*IsInclusionDirective=*/false);
  if (!Mod)
    return true;

  if (!Mod->isInterfaceOrPartition() && !ModuleName.empty() &&
      !getLangOpts().ObjC) {
    Diag(ImportLoc, diag::err_module_import_non_interface_nor_parition)
        << ModuleName;
    return true;
  }

  return ActOnModuleImport(StartLoc, ExportLoc, ImportLoc, Mod, Path);
}

/// Determine whether \p D is lexically within an export-declaration.
static const ExportDecl *getEnclosingExportDecl(const Decl *D) {
  for (auto *DC = D->getLexicalDeclContext(); DC; DC = DC->getLexicalParent())
    if (auto *ED = dyn_cast<ExportDecl>(DC))
      return ED;
  return nullptr;
}

DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
                                   SourceLocation ExportLoc,
                                   SourceLocation ImportLoc, Module *Mod,
                                   ModuleIdPath Path) {
  if (Mod->isHeaderUnit())
    Diag(ImportLoc, diag::warn_experimental_header_unit);

  if (Mod->isNamedModule())
    makeTransitiveImportsVisible(getASTContext(), VisibleModules, Mod,
                                 getCurrentModule(), ImportLoc);
  else
    VisibleModules.setVisible(Mod, ImportLoc);

  assert((!Mod->isModulePartitionImplementation() || getCurrentModule()) &&
         "We can only import a partition unit in a named module.");
  if (Mod->isModulePartitionImplementation() &&
      getCurrentModule()->isModuleInterfaceUnit())
    Diag(ImportLoc,
         diag::warn_import_implementation_partition_unit_in_interface_unit)
        << Mod->Name;

  checkModuleImportContext(*this, Mod, ImportLoc, CurContext);

  // FIXME: we should support importing a submodule within a different submodule
  // of the same top-level module. Until we do, make it an error rather than
  // silently ignoring the import.
  // FIXME: Should we warn on a redundant import of the current module?
  if (Mod->isForBuilding(getLangOpts())) {
    Diag(ImportLoc, getLangOpts().isCompilingModule()
                        ? diag::err_module_self_import
                        : diag::err_module_import_in_implementation)
        << Mod->getFullModuleName() << getLangOpts().CurrentModule;
  }

  SmallVector<SourceLocation, 2> IdentifierLocs;

  if (Path.empty()) {
    // If this was a header import, pad out with dummy locations.
    // FIXME: Pass in and use the location of the header-name token in this
    // case.
    for (Module *ModCheck = Mod; ModCheck; ModCheck = ModCheck->Parent)
      IdentifierLocs.push_back(SourceLocation());
  } else if (getLangOpts().CPlusPlusModules && !Mod->Parent) {
    // A single identifier for the whole name.
    IdentifierLocs.push_back(Path[0].getLoc());
  } else {
    Module *ModCheck = Mod;
    for (unsigned I = 0, N = Path.size(); I != N; ++I) {
      // If we've run out of module parents, just drop the remaining
      // identifiers.  We need the length to be consistent.
      if (!ModCheck)
        break;
      ModCheck = ModCheck->Parent;

      IdentifierLocs.push_back(Path[I].getLoc());
    }
  }

  ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc,
                                          Mod, IdentifierLocs);
  CurContext->addDecl(Import);

  // Sequence initialization of the imported module before that of the current
  // module, if any.
  if (!ModuleScopes.empty())
    Context.addModuleInitializer(ModuleScopes.back().Module, Import);

  // A module (partition) implementation unit shall not be exported.
  if (getLangOpts().CPlusPlusModules && ExportLoc.isValid() &&
      Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
    Diag(ExportLoc, diag::err_export_partition_impl)
        << SourceRange(ExportLoc, Path.back().getLoc());
  } else if (ExportLoc.isValid() &&
             (ModuleScopes.empty() || currentModuleIsImplementation())) {
    // [module.interface]p1:
    // An export-declaration shall inhabit a namespace scope and appear in the
    // purview of a module interface unit.
    Diag(ExportLoc, diag::err_export_not_in_module_interface);
  } else if (!ModuleScopes.empty()) {
    // Re-export the module if the imported module is exported.
    // Note that we don't need to add re-exported module to Imports field
    // since `Exports` implies the module is imported already.
    if (ExportLoc.isValid() || getEnclosingExportDecl(Import))
      getCurrentModule()->Exports.emplace_back(Mod, false);
    else
      getCurrentModule()->Imports.push_back(Mod);
  }

  HadImportedNamedModules = true;

  return Import;
}

void Sema::ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
  checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
  BuildModuleInclude(DirectiveLoc, Mod);
}

void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
  // Determine whether we're in the #include buffer for a module. The #includes
  // in that buffer do not qualify as module imports; they're just an
  // implementation detail of us building the module.
  //
  // FIXME: Should we even get ActOnAnnotModuleInclude calls for those?
  bool IsInModuleIncludes =
      TUKind == TU_ClangModule &&
      getSourceManager().isWrittenInMainFile(DirectiveLoc);

  // If we are really importing a module (not just checking layering) due to an
  // #include in the main file, synthesize an ImportDecl.
  if (getLangOpts().Modules && !IsInModuleIncludes) {
    TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
    ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
                                                     DirectiveLoc, Mod,
                                                     DirectiveLoc);
    if (!ModuleScopes.empty())
      Context.addModuleInitializer(ModuleScopes.back().Module, ImportD);
    TU->addDecl(ImportD);
    Consumer.HandleImplicitImportDecl(ImportD);
  }

  getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc);
  VisibleModules.setVisible(Mod, DirectiveLoc);

  if (getLangOpts().isCompilingModule()) {
    Module *ThisModule = PP.getHeaderSearchInfo().lookupModule(
        getLangOpts().CurrentModule, DirectiveLoc, false, false);
    (void)ThisModule;
    // For named modules, the current module name is not known while parsing the
    // global module fragment and lookupModule may return null.
    assert((getLangOpts().getCompilingModule() ==
                LangOptionsBase::CMK_ModuleInterface ||
            ThisModule) &&
           "was expecting a module if building a Clang module");
  }
}

void Sema::ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
  checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);

  ModuleScopes.push_back({});
  ModuleScopes.back().Module = Mod;
  if (getLangOpts().ModulesLocalVisibility)
    ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);

  VisibleModules.setVisible(Mod, DirectiveLoc);

  // The enclosing context is now part of this module.
  // FIXME: Consider creating a child DeclContext to hold the entities
  // lexically within the module.
  if (getLangOpts().trackLocalOwningModule()) {
    for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
      cast<Decl>(DC)->setModuleOwnershipKind(
          getLangOpts().ModulesLocalVisibility
              ? Decl::ModuleOwnershipKind::VisibleWhenImported
              : Decl::ModuleOwnershipKind::Visible);
      cast<Decl>(DC)->setLocalOwningModule(Mod);
    }
  }
}

void Sema::ActOnAnnotModuleEnd(SourceLocation EomLoc, Module *Mod) {
  if (getLangOpts().ModulesLocalVisibility) {
    VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules);
    // Leaving a module hides namespace names, so our visible namespace cache
    // is now out of date.
    VisibleNamespaceCache.clear();
  }

  assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&
         "left the wrong module scope");
  ModuleScopes.pop_back();

  // We got to the end of processing a local module. Create an
  // ImportDecl as we would for an imported module.
  FileID File = getSourceManager().getFileID(EomLoc);
  SourceLocation DirectiveLoc;
  if (EomLoc == getSourceManager().getLocForEndOfFile(File)) {
    // We reached the end of a #included module header. Use the #include loc.
    assert(File != getSourceManager().getMainFileID() &&
           "end of submodule in main source file");
    DirectiveLoc = getSourceManager().getIncludeLoc(File);
  } else {
    // We reached an EOM pragma. Use the pragma location.
    DirectiveLoc = EomLoc;
  }
  BuildModuleInclude(DirectiveLoc, Mod);

  // Any further declarations are in whatever module we returned to.
  if (getLangOpts().trackLocalOwningModule()) {
    // The parser guarantees that this is the same context that we entered
    // the module within.
    for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
      cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());
      if (!getCurrentModule())
        cast<Decl>(DC)->setModuleOwnershipKind(
            Decl::ModuleOwnershipKind::Unowned);
    }
  }
}

void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
                                                      Module *Mod) {
  // Bail if we're not allowed to implicitly import a module here.
  if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery ||
      VisibleModules.isVisible(Mod))
    return;

  // Create the implicit import declaration.
  TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
  ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
                                                   Loc, Mod, Loc);
  TU->addDecl(ImportD);
  Consumer.HandleImplicitImportDecl(ImportD);

  // Make the module visible.
  getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc);
  VisibleModules.setVisible(Mod, Loc);
}

Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
                                 SourceLocation LBraceLoc) {
  ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc);

  // Set this temporarily so we know the export-declaration was braced.
  D->setRBraceLoc(LBraceLoc);

  CurContext->addDecl(D);
  PushDeclContext(S, D);

  // C++2a [module.interface]p1:
  //   An export-declaration shall appear only [...] in the purview of a module
  //   interface unit. An export-declaration shall not appear directly or
  //   indirectly within [...] a private-module-fragment.
  if (!getLangOpts().HLSL) {
    if (!isCurrentModulePurview()) {
      Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;
      D->setInvalidDecl();
      return D;
    } else if (currentModuleIsImplementation()) {
      Diag(ExportLoc, diag::err_export_not_in_module_interface) << 1;
      Diag(ModuleScopes.back().BeginLoc,
          diag::note_not_module_interface_add_export)
          << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");
      D->setInvalidDecl();
      return D;
    } else if (ModuleScopes.back().Module->Kind ==
              Module::PrivateModuleFragment) {
      Diag(ExportLoc, diag::err_export_in_private_module_fragment);
      Diag(ModuleScopes.back().BeginLoc, diag::note_private_module_fragment);
      D->setInvalidDecl();
      return D;
    }
  }

  for (const DeclContext *DC = CurContext; DC; DC = DC->getLexicalParent()) {
    if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
      //   An export-declaration shall not appear directly or indirectly within
      //   an unnamed namespace [...]
      if (ND->isAnonymousNamespace()) {
        Diag(ExportLoc, diag::err_export_within_anonymous_namespace);
        Diag(ND->getLocation(), diag::note_anonymous_namespace);
        // Don't diagnose internal-linkage declarations in this region.
        D->setInvalidDecl();
        return D;
      }

      //   A declaration is exported if it is [...] a namespace-definition
      //   that contains an exported declaration.
      //
      // Defer exporting the namespace until after we leave it, in order to
      // avoid marking all subsequent declarations in the namespace as exported.
      if (!getLangOpts().HLSL && !DeferredExportedNamespaces.insert(ND).second)
        break;
    }
  }

  //   [...] its declaration or declaration-seq shall not contain an
  //   export-declaration.
  if (auto *ED = getEnclosingExportDecl(D)) {
    Diag(ExportLoc, diag::err_export_within_export);
    if (ED->hasBraces())
      Diag(ED->getLocation(), diag::note_export);
    D->setInvalidDecl();
    return D;
  }

  if (!getLangOpts().HLSL)
    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::VisibleWhenImported);

  return D;
}

static bool checkExportedDecl(Sema &, Decl *, SourceLocation);

/// Check that it's valid to export all the declarations in \p DC.
static bool checkExportedDeclContext(Sema &S, DeclContext *DC,
                                     SourceLocation BlockStart) {
  bool AllUnnamed = true;
  for (auto *D : DC->decls())
    AllUnnamed &= checkExportedDecl(S, D, BlockStart);
  return AllUnnamed;
}

/// Check that it's valid to export \p D.
static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) {

  // HLSL: export declaration is valid only on functions
  if (S.getLangOpts().HLSL) {
    // Export-within-export was already diagnosed in ActOnStartExportDecl
    if (!isa<FunctionDecl, ExportDecl, ExplicitInstantiationDecl>(D)) {
      S.Diag(D->getBeginLoc(), diag::err_hlsl_export_not_on_function);
      D->setInvalidDecl();
      return false;
    }

    if (isa<FunctionDecl>(D)) {
      FunctionDecl *FD = cast<FunctionDecl>(D);
      for (const ParmVarDecl *PVD : FD->parameters()) {
        if (PVD->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {
          S.Diag(D->getBeginLoc(), diag::err_hlsl_attr_incompatible)
              << "'export'" << "'groupshared' parameter";
          D->setInvalidDecl();
          return false;
        }
      }
    }
  }

  //  C++20 [module.interface]p3:
  //   [...] it shall not declare a name with internal linkage.
  bool HasName = false;
  if (auto *ND = dyn_cast<NamedDecl>(D)) {
    // Don't diagnose anonymous union objects; we'll diagnose their members
    // instead.
    HasName = (bool)ND->getDeclName();
    if (HasName && ND->getFormalLinkage() == Linkage::Internal) {
      S.Diag(ND->getLocation(), diag::err_export_internal) << ND;
      if (BlockStart.isValid())
        S.Diag(BlockStart, diag::note_export);
      return false;
    }
  }

  // C++2a [module.interface]p5:
  //   all entities to which all of the using-declarators ultimately refer
  //   shall have been introduced with a name having external linkage
  if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
    NamedDecl *Target = USD->getUnderlyingDecl();
    Linkage Lk = Target->getFormalLinkage();
    if (Lk == Linkage::Internal || Lk == Linkage::Module) {
      S.Diag(USD->getLocation(), diag::err_export_using_internal)
          << (Lk == Linkage::Internal ? 0 : 1) << Target;
      S.Diag(Target->getLocation(), diag::note_using_decl_target);
      if (BlockStart.isValid())
        S.Diag(BlockStart, diag::note_export);
      return false;
    }
  }

  // Recurse into namespace-scope DeclContexts. (Only namespace-scope
  // declarations are exported).
  if (auto *DC = dyn_cast<DeclContext>(D)) {
    if (!isa<NamespaceDecl>(D))
      return true;

    if (auto *ND = dyn_cast<NamedDecl>(D)) {
      if (!ND->getDeclName()) {
        S.Diag(ND->getLocation(), diag::err_export_anon_ns_internal);
        if (BlockStart.isValid())
          S.Diag(BlockStart, diag::note_export);
        return false;
      } else if (!DC->decls().empty() &&
                 DC->getRedeclContext()->isFileContext()) {
        return checkExportedDeclContext(S, DC, BlockStart);
      }
    }
  }
  return true;
}

Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {
  auto *ED = cast<ExportDecl>(D);
  if (RBraceLoc.isValid())
    ED->setRBraceLoc(RBraceLoc);

  PopDeclContext();

  if (!D->isInvalidDecl()) {
    SourceLocation BlockStart =
        ED->hasBraces() ? ED->getBeginLoc() : SourceLocation();
    for (auto *Child : ED->decls()) {
      checkExportedDecl(*this, Child, BlockStart);
      if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
        // [dcl.inline]/7
        // If an inline function or variable that is attached to a named module
        // is declared in a definition domain, it shall be defined in that
        // domain.
        // So, if the current declaration does not have a definition, we must
        // check at the end of the TU (or when the PMF starts) to see that we
        // have a definition at that point.
        if (FD->isInlineSpecified() && !FD->isDefined())
          PendingInlineFuncDecls.insert(FD);
      }
    }
  }

  // Anything exported from a module should never be considered unused.
  for (auto *Exported : ED->decls())
    Exported->markUsed(getASTContext());

  return D;
}

Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc) {
  // We shouldn't create new global module fragment if there is already
  // one.
  if (!TheGlobalModuleFragment) {
    ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
    TheGlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(
        BeginLoc, getCurrentModule());
  }

  assert(TheGlobalModuleFragment && "module creation should not fail");

  // Enter the scope of the global module.
  ModuleScopes.push_back({BeginLoc, TheGlobalModuleFragment,
                          /*OuterVisibleModules=*/{}});
  VisibleModules.setVisible(TheGlobalModuleFragment, BeginLoc);

  return TheGlobalModuleFragment;
}

void Sema::PopGlobalModuleFragment() {
  assert(!ModuleScopes.empty() &&
         getCurrentModule()->isExplicitGlobalModule() &&
         "left the wrong module scope, which is not global module fragment");
  ModuleScopes.pop_back();
}

Module *Sema::PushImplicitGlobalModuleFragment(SourceLocation BeginLoc) {
  if (!TheImplicitGlobalModuleFragment) {
    ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
    TheImplicitGlobalModuleFragment =
        Map.createImplicitGlobalModuleFragmentForModuleUnit(BeginLoc,
                                                            getCurrentModule());
  }
  assert(TheImplicitGlobalModuleFragment && "module creation should not fail");

  // Enter the scope of the global module.
  ModuleScopes.push_back({BeginLoc, TheImplicitGlobalModuleFragment,
                          /*OuterVisibleModules=*/{}});
  VisibleModules.setVisible(TheImplicitGlobalModuleFragment, BeginLoc);
  return TheImplicitGlobalModuleFragment;
}

void Sema::PopImplicitGlobalModuleFragment() {
  assert(!ModuleScopes.empty() &&
         getCurrentModule()->isImplicitGlobalModule() &&
         "left the wrong module scope, which is not global module fragment");
  ModuleScopes.pop_back();
}

bool Sema::isCurrentModulePurview() const {
  if (!getCurrentModule())
    return false;

  /// Does this Module scope describe part of the purview of a standard named
  /// C++ module?
  switch (getCurrentModule()->Kind) {
  case Module::ModuleInterfaceUnit:
  case Module::ModuleImplementationUnit:
  case Module::ModulePartitionInterface:
  case Module::ModulePartitionImplementation:
  case Module::PrivateModuleFragment:
  case Module::ImplicitGlobalModuleFragment:
    return true;
  default:
    return false;
  }
}

//===----------------------------------------------------------------------===//
// Checking Exposure in modules                                               //
//===----------------------------------------------------------------------===//

namespace {
class ExposureChecker {
public:
  ExposureChecker(Sema &S) : SemaRef(S) {}

  bool checkExposure(const VarDecl *D, bool Diag);
  bool checkExposure(const CXXRecordDecl *D, bool Diag);
  bool checkExposure(const Stmt *S, bool Diag);
  bool checkExposure(const FunctionDecl *D, bool Diag);
  bool checkExposure(const NamedDecl *D, bool Diag);
  void checkExposureInContext(const DeclContext *DC);
  bool isExposureCandidate(const NamedDecl *D);

  bool isTULocal(QualType Ty);
  bool isTULocal(const NamedDecl *ND);
  bool isTULocal(const Expr *E);

  Sema &SemaRef;

private:
  llvm::DenseSet<const NamedDecl *> ExposureSet;
  llvm::DenseSet<const NamedDecl *> KnownNonExposureSet;
  llvm::DenseSet<const NamedDecl *> CheckingDecls;
};

bool ExposureChecker::isTULocal(QualType Ty) {
  // [basic.link]p15:
  // An entity is TU-local if it is
  // - a type, type alias, namespace, namespace alias, function, variable, or
  // template that
  //   -- has internal linkage, or
  return Ty->getLinkage() == Linkage::Internal;

  // TODO:
  // [basic.link]p15.2:
  //   a type with no name that is defined outside a class-specifier, function
  //   body, or initializer or is introduced by a defining-type-specifier that
  //   is used to declare only TU-local entities,
}

bool ExposureChecker::isTULocal(const NamedDecl *D) {
  if (!D)
    return false;

  // [basic.link]p15:
  // An entity is TU-local if it is
  // - a type, type alias, namespace, namespace alias, function, variable, or
  // template that
  //   -- has internal linkage, or
  if (D->getLinkageInternal() == Linkage::Internal)
    return true;

  if (D->isInAnonymousNamespace())
    return true;

  // [basic.link]p15.1.2:
  // does not have a name with linkage and is declared, or introduced by a
  // lambda-expression, within the definition of a TU-local entity,
  if (D->getLinkageInternal() == Linkage::None)
    if (auto *ND = dyn_cast<NamedDecl>(D->getDeclContext());
        ND && isTULocal(ND))
      return true;

  // [basic.link]p15.3, p15.4:
  // - a specialization of a TU-local template,
  // - a specialization of a template with any TU-local template argument, or
  ArrayRef<TemplateArgument> TemplateArgs;
  NamedDecl *PrimaryTemplate = nullptr;
  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
    TemplateArgs = CTSD->getTemplateArgs().asArray();
    PrimaryTemplate = CTSD->getSpecializedTemplate();
    if (isTULocal(PrimaryTemplate))
      return true;
  } else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
    TemplateArgs = VTSD->getTemplateArgs().asArray();
    PrimaryTemplate = VTSD->getSpecializedTemplate();
    if (isTULocal(PrimaryTemplate))
      return true;
  } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
    if (auto *TAList = FD->getTemplateSpecializationArgs())
      TemplateArgs = TAList->asArray();

    PrimaryTemplate = FD->getPrimaryTemplate();
    if (isTULocal(PrimaryTemplate))
      return true;
  }

  if (!PrimaryTemplate)
    // Following off, we only check for specializations.
    return false;

  if (KnownNonExposureSet.count(D))
    return false;

  for (auto &TA : TemplateArgs) {
    switch (TA.getKind()) {
    case TemplateArgument::Type:
      if (isTULocal(TA.getAsType()))
        return true;
      break;
    case TemplateArgument::Declaration:
      if (isTULocal(TA.getAsDecl()))
        return true;
      break;
    default:
      break;
    }
  }

  // Avoid recursions.
  if (CheckingDecls.count(D))
    return false;
  CheckingDecls.insert(D);
  llvm::scope_exit RemoveCheckingDecls([&] { CheckingDecls.erase(D); });

  // [basic.link]p15.5
  // - a specialization of a template whose (possibly instantiated) declaration
  // is an exposure.
  if (ExposureSet.count(PrimaryTemplate) ||
      checkExposure(PrimaryTemplate, /*Diag=*/false))
    return true;

  // Avoid calling checkExposure again since it is expensive.
  KnownNonExposureSet.insert(D);
  return false;
}

bool ExposureChecker::isTULocal(const Expr *E) {
  if (!E)
    return false;

  // [basic.link]p16:
  //    A value or object is TU-local if either
  //    - it is of TU-local type,
  if (isTULocal(E->getType()))
    return true;

  E = E->IgnoreParenImpCasts();
  // [basic.link]p16.2:
  //   - it is, or is a pointer to, a TU-local function or the object associated
  //   with a TU-local variable,
  //  - it is an object of class or array type and any of its subobjects or any
  //  of the objects or functions to which its non-static data members of
  //  reference type refer is TU-local and is usable in constant expressions, or
  // FIXME: But how can we know the value of pointers or arrays at compile time?
  if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
    if (auto *FD = dyn_cast_or_null<FunctionDecl>(DRE->getFoundDecl()))
      return isTULocal(FD);
    else if (auto *VD = dyn_cast_or_null<VarDecl>(DRE->getFoundDecl()))
      return isTULocal(VD);
    else if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(DRE->getFoundDecl()))
      return isTULocal(RD);
  }

  // TODO:
  // [basic.link]p16.4:
  //  it is a reflection value that represents...

  return false;
}

bool ExposureChecker::isExposureCandidate(const NamedDecl *D) {
  if (!D)
    return false;

  // [basic.link]p17:
  //   If a (possibly instantiated) declaration of, or a deduction guide for,
  //   a non-TU-local entity in a module interface unit
  //   (outside the private-module-fragment, if any) or
  //   module partition is an exposure, the program is ill-formed.
  Module *M = D->getOwningModule();
  if (!M)
    return false;
  // If M is implicit global module, the declaration must be in the purview of
  // a module unit.
  if (M->isImplicitGlobalModule()) {
    M = M->Parent;
    assert(M && "Implicit global module must have a parent");
  }

  if (!M->isInterfaceOrPartition())
    return false;

  if (D->isImplicit())
    return false;

  // [basic.link]p14:
  //      A declaration is an exposure if it either names a TU-local entity
  //      (defined below), ignoring:
  //      ...
  //      - friend declarations in a class definition
  if (D->getFriendObjectKind() &&
      isa<CXXRecordDecl>(D->getLexicalDeclContext()))
    return false;

  return true;
}

bool ExposureChecker::checkExposure(const NamedDecl *D, bool Diag) {
  if (!isExposureCandidate(D))
    return false;

  if (auto *FD = dyn_cast<FunctionDecl>(D))
    return checkExposure(FD, Diag);
  if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
    return checkExposure(FTD->getTemplatedDecl(), Diag);

  if (auto *VD = dyn_cast<VarDecl>(D))
    return checkExposure(VD, Diag);
  if (auto *VTD = dyn_cast<VarTemplateDecl>(D))
    return checkExposure(VTD->getTemplatedDecl(), Diag);

  if (auto *RD = dyn_cast<CXXRecordDecl>(D))
    return checkExposure(RD, Diag);

  if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
    return checkExposure(CTD->getTemplatedDecl(), Diag);

  return false;
}

bool ExposureChecker::checkExposure(const FunctionDecl *FD, bool Diag) {
  bool IsExposure = false;
  if (isTULocal(FD->getReturnType())) {
    IsExposure = true;
    if (Diag)
      SemaRef.Diag(FD->getReturnTypeSourceRange().getBegin(),
                   diag::warn_exposure)
          << FD->getReturnType();
  }

  for (ParmVarDecl *Parms : FD->parameters())
    if (isTULocal(Parms->getType())) {
      IsExposure = true;
      if (Diag)
        SemaRef.Diag(Parms->getLocation(), diag::warn_exposure)
            << Parms->getType();
    }

  bool IsImplicitInstantiation =
      FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;

  // [basic.link]p14:
  //      A declaration is an exposure if it either names a TU-local entity
  //      (defined below), ignoring:
  //      - the function-body for a non-inline function or function template
  //      (but not the deduced return
  //        type for a (possibly instantiated) definition of a function with a
  //        declared return type that uses a placeholder type
  //        ([dcl.spec.auto])),
  Diag &=
      (FD->isInlined() || IsImplicitInstantiation) && !FD->isDependentContext();

  IsExposure |= checkExposure(FD->getBody(), Diag);
  if (IsExposure)
    ExposureSet.insert(FD);

  return IsExposure;
}

bool ExposureChecker::checkExposure(const VarDecl *VD, bool Diag) {
  bool IsExposure = false;
  // [basic.link]p14:
  //  A declaration is an exposure if it either names a TU-local entity (defined
  //  below), ignoring:
  //  ...
  //  or defines a constexpr variable initialized to a TU-local value (defined
  //  below).
  if (VD->isConstexpr() && isTULocal(VD->getInit())) {
    IsExposure = true;
    if (Diag)
      SemaRef.Diag(VD->getInit()->getExprLoc(), diag::warn_exposure)
          << VD->getInit();
  }

  if (isTULocal(VD->getType())) {
    IsExposure = true;
    if (Diag)
      SemaRef.Diag(VD->getLocation(), diag::warn_exposure) << VD->getType();
  }

  // [basic.link]p14:
  //   ..., ignoring:
  //   - the initializer for a variable or variable template (but not the
  //   variable's type),
  //
  // Note: although the spec says to ignore the initializer for all variable,
  // for the code we generated now for inline variables, it is dangerous if the
  // initializer of an inline variable is TULocal.
  Diag &= !VD->getDeclContext()->isDependentContext() && VD->isInline();
  IsExposure |= checkExposure(VD->getInit(), Diag);
  if (IsExposure)
    ExposureSet.insert(VD);

  return IsExposure;
}

bool ExposureChecker::checkExposure(const CXXRecordDecl *RD, bool Diag) {
  if (!RD->hasDefinition())
    return false;

  bool IsExposure = false;
  for (CXXMethodDecl *Method : RD->methods())
    IsExposure |= checkExposure(Method, Diag);

  for (FieldDecl *FD : RD->fields()) {
    if (isTULocal(FD->getType())) {
      IsExposure = true;
      if (Diag)
        SemaRef.Diag(FD->getLocation(), diag::warn_exposure) << FD->getType();
    }
  }

  for (const CXXBaseSpecifier &Base : RD->bases()) {
    if (isTULocal(Base.getType())) {
      IsExposure = true;
      if (Diag)
        SemaRef.Diag(Base.getBaseTypeLoc(), diag::warn_exposure)
            << Base.getType();
    }
  }

  if (IsExposure)
    ExposureSet.insert(RD);

  return IsExposure;
}

class ReferenceTULocalChecker : public DynamicRecursiveASTVisitor {
public:
  using CallbackTy = std::function<void(DeclRefExpr *, ValueDecl *)>;

  ReferenceTULocalChecker(ExposureChecker &C, CallbackTy &&Callback)
      : Checker(C), Callback(std::move(Callback)) {}

  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
    ValueDecl *Referenced = DRE->getDecl();
    if (!Referenced)
      return true;

    if (!Checker.isTULocal(Referenced))
      // We don't care if the referenced declaration is not TU-local.
      return true;

    Qualifiers Qual = DRE->getType().getQualifiers();
    // [basic.link]p14:
    //      A declaration is an exposure if it either names a TU-local entity
    //      (defined below), ignoring:
    //      ...
    //      - any reference to a non-volatile const object ...
    if (Qual.hasConst() && !Qual.hasVolatile())
      return true;

    // [basic.link]p14:
    // ..., ignoring:
    //   ...
    //   (p14.4) - ... or reference with internal or no linkage initialized with
    //   a constant expression that is not an odr-use
    ASTContext &Context = Referenced->getASTContext();
    Linkage L = Referenced->getLinkageInternal();
    if (DRE->isNonOdrUse() && (L == Linkage::Internal || L == Linkage::None))
      if (auto *VD = dyn_cast<VarDecl>(Referenced);
          VD && VD->getInit() && !VD->getInit()->isValueDependent() &&
          VD->getInit()->isConstantInitializer(Context))
        return true;

    Callback(DRE, Referenced);
    return true;
  }

  ExposureChecker &Checker;
  CallbackTy Callback;
};

bool ExposureChecker::checkExposure(const Stmt *S, bool Diag) {
  if (!S)
    return false;

  bool HasReferencedTULocals = false;
  ReferenceTULocalChecker Checker(
      *this, [this, &HasReferencedTULocals, Diag](DeclRefExpr *DRE,
                                                  ValueDecl *Referenced) {
        if (Diag) {
          SemaRef.Diag(DRE->getExprLoc(), diag::warn_exposure) << Referenced;
        }
        HasReferencedTULocals = true;
      });
  Checker.TraverseStmt(const_cast<Stmt *>(S));
  return HasReferencedTULocals;
}

void ExposureChecker::checkExposureInContext(const DeclContext *DC) {
  for (auto *TopD : DC->noload_decls()) {
    if (auto *Export = dyn_cast<ExportDecl>(TopD)) {
      checkExposureInContext(Export);
      continue;
    }

    if (auto *LinkageSpec = dyn_cast<LinkageSpecDecl>(TopD)) {
      checkExposureInContext(LinkageSpec);
      continue;
    }

    auto *TopND = dyn_cast<NamedDecl>(TopD);
    if (!TopND)
      continue;

    if (auto *Namespace = dyn_cast<NamespaceDecl>(TopND)) {
      checkExposureInContext(Namespace);
      continue;
    }

    // [basic.link]p17:
    //   If a (possibly instantiated) declaration of, or a deduction guide for,
    //   a non-TU-local entity in a module interface unit
    //   (outside the private-module-fragment, if any) or
    //   module partition is an exposure, the program is ill-formed.
    if (!TopND->isFromASTFile() && isExposureCandidate(TopND) &&
        !isTULocal(TopND))
      checkExposure(TopND, /*Diag=*/true);
  }
}

} // namespace

void Sema::checkExposure(const TranslationUnitDecl *TU) {
  if (!TU)
    return;

  ExposureChecker Checker(*this);

  Module *M = TU->getOwningModule();
  if (M && M->isInterfaceOrPartition())
    Checker.checkExposureInContext(TU);

  // [basic.link]p18:
  //   If a declaration that appears in one translation unit names a TU-local
  //   entity declared in another translation unit that is not a header unit,
  //   the program is ill-formed.
  for (auto FDAndInstantiationLocPair : PendingCheckReferenceForTULocal) {
    FunctionDecl *FD = FDAndInstantiationLocPair.first;
    SourceLocation PointOfInstantiation = FDAndInstantiationLocPair.second;

    if (!FD->hasBody())
      continue;

    ReferenceTULocalChecker(Checker, [&, this](DeclRefExpr *DRE,
                                               ValueDecl *Referenced) {
      // A "defect" in current implementation. Now an implicit instantiation of
      // a template, the instantiation is considered to be in the same module
      // unit as the template instead of the module unit where the instantiation
      // happens.
      //
      // See test/Modules/Exposre-2.cppm for example.
      if (!Referenced->isFromASTFile())
        return;

      if (!Referenced->isInAnotherModuleUnit())
        return;

      // This is not standard conforming. But given there are too many static
      // (inline) functions in headers in existing code, it is more user
      // friendly to ignore them temporarily now. maybe we can have another flag
      // for this.
      if (Referenced->getOwningModule()->isExplicitGlobalModule() &&
          isa<FunctionDecl>(Referenced))
        return;

      Diag(PointOfInstantiation,
           diag::warn_reference_tu_local_entity_in_other_tu)
          << FD << Referenced
          << Referenced->getOwningModule()->getTopLevelModuleName();
    }).TraverseStmt(FD->getBody());
  }
}

void Sema::checkReferenceToTULocalFromOtherTU(
    FunctionDecl *FD, SourceLocation PointOfInstantiation) {
  // Checking if a declaration have any reference to TU-local entities in other
  // TU is expensive. Try to avoid it as much as possible.
  if (!FD || !HadImportedNamedModules)
    return;

  PendingCheckReferenceForTULocal.push_back(
      std::make_pair(FD, PointOfInstantiation));
}
