//===- ModuleMap.cpp - Describe the layout of 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 defines the ModuleMap implementation, which describes the layout
// of a module as it relates to headers.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/ModuleMap.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/ModuleMapFile.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstring>
#include <optional>
#include <string>
#include <system_error>
#include <utility>

using namespace clang;

static constexpr llvm::StringRef kPrivateModuleSuffix = "_Private";

void ModuleMapCallbacks::anchor() {}

void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
  auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
  if (PendingLinkAs != PendingLinkAsModule.end()) {
    for (auto &Name : PendingLinkAs->second) {
      auto *M = findModule(Name.getKey());
      if (M)
        M->UseExportAsModuleLinkName = true;
    }
  }
}

void ModuleMap::addLinkAsDependency(Module *Mod) {
  if (findModule(Mod->ExportAsModule))
    Mod->UseExportAsModuleLinkName = true;
  else
    PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
}

Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
  switch ((int)Role) {
  case NormalHeader:
    return Module::HK_Normal;
  case PrivateHeader:
    return Module::HK_Private;
  case TextualHeader:
    return Module::HK_Textual;
  case PrivateHeader | TextualHeader:
    return Module::HK_PrivateTextual;
  case ExcludedHeader:
    return Module::HK_Excluded;
  }
  llvm_unreachable("unknown header role");
}

ModuleMap::ModuleHeaderRole
ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
  switch ((int)Kind) {
  case Module::HK_Normal:
    return NormalHeader;
  case Module::HK_Private:
    return PrivateHeader;
  case Module::HK_Textual:
    return TextualHeader;
  case Module::HK_PrivateTextual:
    return ModuleHeaderRole(PrivateHeader | TextualHeader);
  case Module::HK_Excluded:
    return ExcludedHeader;
  }
  llvm_unreachable("unknown header kind");
}

bool ModuleMap::isModular(ModuleHeaderRole Role) {
  return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
}

Module::ExportDecl
ModuleMap::resolveExport(Module *Mod,
                         const Module::UnresolvedExportDecl &Unresolved,
                         bool Complain) const {
  // We may have just a wildcard.
  if (Unresolved.Id.empty()) {
    assert(Unresolved.Wildcard && "Invalid unresolved export");
    return Module::ExportDecl(nullptr, true);
  }

  // Resolve the module-id.
  Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
  if (!Context)
    return {};

  return Module::ExportDecl(Context, Unresolved.Wildcard);
}

Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
                                   bool Complain) const {
  // Find the starting module.
  Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
  if (!Context) {
    if (Complain)
      Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
      << Id[0].first << Mod->getFullModuleName();

    return nullptr;
  }

  // Dig into the module path.
  for (unsigned I = 1, N = Id.size(); I != N; ++I) {
    Module *Sub = lookupModuleQualified(Id[I].first, Context);
    if (!Sub) {
      if (Complain)
        Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
        << Id[I].first << Context->getFullModuleName()
        << SourceRange(Id[0].second, Id[I-1].second);

      return nullptr;
    }

    Context = Sub;
  }

  return Context;
}

/// Append to \p Paths the set of paths needed to get to the
/// subframework in which the given module lives.
static void appendSubframeworkPaths(Module *Mod,
                                    SmallVectorImpl<char> &Path) {
  // Collect the framework names from the given module to the top-level module.
  SmallVector<StringRef, 2> Paths;
  for (; Mod; Mod = Mod->Parent) {
    if (Mod->IsFramework)
      Paths.push_back(Mod->Name);
  }

  if (Paths.empty())
    return;

  // Add Frameworks/Name.framework for each subframework.
  for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
    llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
}

OptionalFileEntryRef ModuleMap::findHeader(
    Module *M, const Module::UnresolvedHeaderDirective &Header,
    SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
  // Search for the header file within the module's home directory.
  auto Directory = M->Directory;
  SmallString<128> FullPathName(Directory->getName());

  auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
    auto File = SourceMgr.getFileManager().getOptionalFileRef(Filename);
    if (!File || (Header.Size && File->getSize() != *Header.Size) ||
        (Header.ModTime && File->getModificationTime() != *Header.ModTime))
      return std::nullopt;
    return *File;
  };

  auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
    unsigned FullPathLength = FullPathName.size();
    appendSubframeworkPaths(M, RelativePathName);
    unsigned RelativePathLength = RelativePathName.size();

    // Check whether this file is in the public headers.
    llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
    llvm::sys::path::append(FullPathName, RelativePathName);
    if (auto File = GetFile(FullPathName))
      return File;

    // Check whether this file is in the private headers.
    // Ideally, private modules in the form 'FrameworkName.Private' should
    // be defined as 'module FrameworkName.Private', and not as
    // 'framework module FrameworkName.Private', since a 'Private.Framework'
    // does not usually exist. However, since both are currently widely used
    // for private modules, make sure we find the right path in both cases.
    if (M->IsFramework && M->Name == "Private")
      RelativePathName.clear();
    else
      RelativePathName.resize(RelativePathLength);
    FullPathName.resize(FullPathLength);
    llvm::sys::path::append(RelativePathName, "PrivateHeaders",
                            Header.FileName);
    llvm::sys::path::append(FullPathName, RelativePathName);
    return GetFile(FullPathName);
  };

  if (llvm::sys::path::is_absolute(Header.FileName)) {
    RelativePathName.clear();
    RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
    return GetFile(Header.FileName);
  }

  if (M->isPartOfFramework())
    return GetFrameworkFile();

  // Lookup for normal headers.
  llvm::sys::path::append(RelativePathName, Header.FileName);
  llvm::sys::path::append(FullPathName, RelativePathName);
  auto NormalHdrFile = GetFile(FullPathName);

  if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {
    // The lack of 'framework' keyword in a module declaration it's a simple
    // mistake we can diagnose when the header exists within the proper
    // framework style path.
    FullPathName.assign(Directory->getName());
    RelativePathName.clear();
    if (GetFrameworkFile()) {
      Diags.Report(Header.FileNameLoc,
                   diag::warn_mmap_incomplete_framework_module_declaration)
          << Header.FileName << M->getFullModuleName();
      NeedsFramework = true;
    }
    return std::nullopt;
  }

  return NormalHdrFile;
}

/// Determine whether the given file name is the name of a builtin
/// header, supplied by Clang to replace, override, or augment existing system
/// headers.
static bool isBuiltinHeaderName(StringRef FileName) {
  return llvm::StringSwitch<bool>(FileName)
           .Case("float.h", true)
           .Case("iso646.h", true)
           .Case("limits.h", true)
           .Case("stdalign.h", true)
           .Case("stdarg.h", true)
           .Case("stdatomic.h", true)
           .Case("stdbool.h", true)
           .Case("stdckdint.h", true)
           .Case("stdcountof.h", true)
           .Case("stddef.h", true)
           .Case("stdint.h", true)
           .Case("tgmath.h", true)
           .Case("unwind.h", true)
           .Default(false);
}

/// Determine whether the given module name is the name of a builtin
/// module that is cyclic with a system module  on some platforms.
static bool isBuiltInModuleName(StringRef ModuleName) {
  return llvm::StringSwitch<bool>(ModuleName)
           .Case("_Builtin_float", true)
           .Case("_Builtin_inttypes", true)
           .Case("_Builtin_iso646", true)
           .Case("_Builtin_limits", true)
           .Case("_Builtin_stdalign", true)
           .Case("_Builtin_stdarg", true)
           .Case("_Builtin_stdatomic", true)
           .Case("_Builtin_stdbool", true)
           .Case("_Builtin_stddef", true)
           .Case("_Builtin_stdint", true)
           .Case("_Builtin_stdnoreturn", true)
           .Case("_Builtin_tgmath", true)
           .Case("_Builtin_unwind", true)
           .Default(false);
}

void ModuleMap::resolveHeader(Module *Mod,
                              const Module::UnresolvedHeaderDirective &Header,
                              bool &NeedsFramework) {
  SmallString<128> RelativePathName;
  if (OptionalFileEntryRef File =
          findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
    if (Header.IsUmbrella) {
      const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
      if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
        Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
          << UmbrellaMod->getFullModuleName();
      else
        // Record this umbrella header.
        setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
                                   RelativePathName.str(), Header.FileNameLoc);
    } else {
      Module::Header H = {Header.FileName, std::string(RelativePathName),
                          *File};
      addHeader(Mod, H, headerKindToRole(Header.Kind), /*Imported=*/false,
                Header.FileNameLoc);
    }
  } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
    // There's a builtin header but no corresponding on-disk header. Assume
    // this was supposed to modularize the builtin header alone.
  } else if (Header.Kind == Module::HK_Excluded) {
    // Ignore missing excluded header files. They're optional anyway.
  } else {
    // If we find a module that has a missing header, we mark this module as
    // unavailable and store the header directive for displaying diagnostics.
    Mod->MissingHeaders.push_back(Header);
    // A missing header with stat information doesn't make the module
    // unavailable; this keeps our behavior consistent as headers are lazily
    // resolved. (Such a module still can't be built though, except from
    // preprocessed source.)
    if (!Header.Size && !Header.ModTime)
      Mod->markUnavailable(/*Unimportable=*/false);
  }
}

bool ModuleMap::resolveAsBuiltinHeader(
    Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
  if (Header.Kind == Module::HK_Excluded ||
      llvm::sys::path::is_absolute(Header.FileName) ||
      Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
      !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
      !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
    return false;

  // This is a system module with a top-level header. This header
  // may have a counterpart (or replacement) in the set of headers
  // supplied by Clang. Find that builtin header.
  SmallString<128> Path;
  llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
  auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
  if (!File)
    return false;

  Module::Header H = {Header.FileName, Header.FileName, *File};
  auto Role = headerKindToRole(Header.Kind);
  addHeader(Mod, H, Role);
  return true;
}

ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                     const LangOptions &LangOpts, const TargetInfo *Target,
                     HeaderSearch &HeaderInfo)
    : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
      HeaderInfo(HeaderInfo) {
}

ModuleMap::~ModuleMap() = default;

void ModuleMap::setTarget(const TargetInfo &Target) {
  assert((!this->Target || this->Target == &Target) &&
         "Improper target override");
  this->Target = &Target;
}

/// "Sanitize" a filename so that it can be used as an identifier.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
                                              SmallVectorImpl<char> &Buffer) {
  if (Name.empty())
    return Name;

  if (!isValidAsciiIdentifier(Name)) {
    // If we don't already have something with the form of an identifier,
    // create a buffer with the sanitized name.
    Buffer.clear();
    if (isDigit(Name[0]))
      Buffer.push_back('_');
    Buffer.reserve(Buffer.size() + Name.size());
    for (unsigned I = 0, N = Name.size(); I != N; ++I) {
      if (isAsciiIdentifierContinue(Name[I]))
        Buffer.push_back(Name[I]);
      else
        Buffer.push_back('_');
    }

    Name = StringRef(Buffer.data(), Buffer.size());
  }

  while (llvm::StringSwitch<bool>(Name)
#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
#include "clang/Basic/TokenKinds.def"
           .Default(false)) {
    if (Name.data() != Buffer.data())
      Buffer.append(Name.begin(), Name.end());
    Buffer.push_back('_');
    Name = StringRef(Buffer.data(), Buffer.size());
  }

  return Name;
}

bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
  return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
         isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
}

bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
                                                        Module *Module) const {
  return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
         Module->IsSystem && !Module->isPartOfFramework() &&
         isBuiltinHeaderName(FileName);
}

ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {
  resolveHeaderDirectives(File);
  HeadersMap::iterator Known = Headers.find(File);
  if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
      Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
    HeaderInfo.loadTopLevelSystemModules();
    return Headers.find(File);
  }
  return Known;
}

ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
    FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
  if (UmbrellaDirs.empty())
    return {};

  OptionalDirectoryEntryRef Dir = File.getDir();

  // Note: as an egregious but useful hack we use the real path here, because
  // frameworks moving from top-level frameworks to embedded frameworks tend
  // to be symlinked from the top-level location to the embedded location,
  // and we need to resolve lookups as if we had found the embedded location.
  StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);

  // Keep walking up the directory hierarchy, looking for a directory with
  // an umbrella header.
  do {
    auto KnownDir = UmbrellaDirs.find(*Dir);
    if (KnownDir != UmbrellaDirs.end())
      return KnownHeader(KnownDir->second, NormalHeader);

    IntermediateDirs.push_back(*Dir);

    // Retrieve our parent path.
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.empty())
      break;

    // Resolve the parent path to a directory entry.
    Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
  } while (Dir);
  return {};
}

static bool violatesPrivateInclude(Module *RequestingModule,
                                   const FileEntry *IncFileEnt,
                                   ModuleMap::KnownHeader Header) {
#ifndef NDEBUG
  if (Header.getRole() & ModuleMap::PrivateHeader) {
    // Check for consistency between the module header role
    // as obtained from the lookup and as obtained from the module.
    // This check is not cheap, so enable it only for debugging.
    bool IsPrivate = false;
    ArrayRef<Module::Header> HeaderList[] = {
        Header.getModule()->getHeaders(Module::HK_Private),
        Header.getModule()->getHeaders(Module::HK_PrivateTextual)};
    for (auto Hs : HeaderList)
      IsPrivate |= llvm::any_of(
          Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
    assert(IsPrivate && "inconsistent headers and roles");
  }
#endif
  return !Header.isAccessibleFrom(RequestingModule);
}

static Module *getTopLevelOrNull(Module *M) {
  return M ? M->getTopLevelModule() : nullptr;
}

void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
                                        bool RequestingModuleIsModuleInterface,
                                        SourceLocation FilenameLoc,
                                        StringRef Filename, FileEntryRef File) {
  if (RequestingModule) {
    resolveUses(RequestingModule, /*Complain=*/false);
    resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
  }

  HeadersMap::iterator Known = findKnownHeader(File);

  diagnoseDuplicateHeaderOwnership(FilenameLoc, Filename, File, Known);

  // No errors for indirect modules. This may be a bit of a problem for modules
  // with no source files.
  Module *TopLevelRequestingModule = getTopLevelOrNull(RequestingModule);
  Module *TopLevelSourceModule = getTopLevelOrNull(SourceModule);
  bool IsPublicForMainPrivateModule = false;
  if (TopLevelRequestingModule != TopLevelSourceModule) {
    // Suppose we have a pair of files foo.cpp / foo.h.
    // Our build system may want to verify that foo.cpp only uses things
    // declared in the implementation_deps of foo, while foo.h only uses things
    // declared in interface_deps. This requires them to be two seperate
    // modules, foo_Private and foo. This check is required to ensure that foo.h
    // is still checked. Otherwise, foo.h would never be checked, since it will
    // never be the top-level module.
    if (TopLevelRequestingModule && TopLevelSourceModule &&
        llvm::StringRef(TopLevelSourceModule->Name)
            .ends_with(kPrivateModuleSuffix) &&
        llvm::StringRef(TopLevelSourceModule->Name)
                .drop_back(kPrivateModuleSuffix.size()) ==
            TopLevelRequestingModule->Name) {
      IsPublicForMainPrivateModule = true;
    } else {
      return;
    }
  }

  bool Excluded = false;
  bool UsedByPrivateModule = false;
  Module *Private = nullptr;
  Module *NotUsed = nullptr;

  if (Known != Headers.end()) {
    for (const KnownHeader &Header : Known->second) {
      // Excluded headers don't really belong to a module.
      if (Header.getRole() == ModuleMap::ExcludedHeader) {
        Excluded = true;
        continue;
      }

      // Remember private headers for later printing of a diagnostic.
      if (violatesPrivateInclude(RequestingModule, File, Header)) {
        Private = Header.getModule();
        continue;
      }

      // If uses need to be specified explicitly, we are only allowed to return
      // modules that are explicitly used by the requesting module.
      if (RequestingModule && LangOpts.ModulesDeclUse &&
          !RequestingModule->directlyUses(Header.getModule())) {
        NotUsed = Header.getModule();
        if (IsPublicForMainPrivateModule) {
          UsedByPrivateModule = SourceModule->directlyUses(Header.getModule());
        }
        continue;
      }

      // We have found a module that we can happily use.
      return;
    }

    Excluded = true;
  }

  // We have found a header, but it is private.
  if (Private) {
    Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
        << Filename;
    return;
  }

  // We have found a module, but we don't use it.
  if (NotUsed) {
    if (UsedByPrivateModule) {
      Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_private)
          << RequestingModule->getTopLevelModule()->Name << Filename
          << NotUsed->Name;
    } else {
      Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
          << RequestingModule->getTopLevelModule()->Name << Filename
          << NotUsed->Name;
    }
    return;
  }

  if (Excluded || isHeaderInUmbrellaDirs(File))
    return;

  // At this point, only non-modular includes remain.

  if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
    Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
        << RequestingModule->getTopLevelModule()->Name << Filename;
  } else if (RequestingModule && RequestingModuleIsModuleInterface &&
             LangOpts.isCompilingModule()) {
    // Do not diagnose when we are not compiling a module.
    diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
        diag::warn_non_modular_include_in_framework_module :
        diag::warn_non_modular_include_in_module;
    Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
        << File.getName();
  }
}

void ModuleMap::diagnoseDuplicateHeaderOwnership(SourceLocation FilenameLoc,
                                                 StringRef Filename,
                                                 FileEntryRef File,
                                                 HeadersMap::iterator Known) {
  if (Known == Headers.end())
    return;

  if (Diags.isIgnored(diag::warn_mmap_duplicate_header_ownership, FilenameLoc))
    return;

  // Only diagnose each header once.
  if (!DiagnosedDuplicateHeaders.insert(&File.getFileEntry()).second)
    return;

  struct OwnerInfo {
    Module *Mod;
    SourceLocation Loc;
    bool IsUmbrella;
  };

  // Collect distinct top-level modules that explicitly own this header with
  // a modular (non-textual, non-excluded) role.
  SmallVector<OwnerInfo, 2> OwningModules;
  llvm::SmallPtrSet<Module *, 2> SeenTopLevel;
  for (const KnownHeader &H : Known->second) {
    if (!isModular(H.getRole()))
      continue;
    Module *TopLevel = H.getModule()->getTopLevelModule();
    if (!SeenTopLevel.insert(TopLevel).second)
      continue;
    auto It = HeaderOwnerLocs.find({&File.getFileEntry(), H.getModule()});
    SourceLocation OwnerLoc =
        It != HeaderOwnerLocs.end() ? It->second : SourceLocation();
    OwningModules.push_back({TopLevel, OwnerLoc, /*IsUmbrella=*/false});
  }

  // Need at least one explicit owner for there to be a conflict, since
  // umbrella coverage can only add one more.
  if (OwningModules.empty())
    return;

  // Also check umbrella directory coverage for additional owners from different
  // top-level modules — but only if the header isn't excluded from the umbrella
  // module. Explicit headers take precedence over umbrella dirs in module
  // resolution, but a header owned by one module that another module's umbrella
  // covers can still create problems.
  SmallVector<DirectoryEntryRef, 2> IntermediateDirs;
  if (KnownHeader UmbrellaOwner =
          findHeaderInUmbrellaDirs(File, IntermediateDirs)) {
    Module *TopLevel = UmbrellaOwner.getModule()->getTopLevelModule();
    // Only add if it's a different top-level module and the header isn't
    // excluded from the umbrella module.
    if (SeenTopLevel.insert(TopLevel).second) {
      // Check that the header isn't excluded in the umbrella module.
      bool IsExcluded =
          llvm::any_of(Known->second, [TopLevel](const KnownHeader &H) {
            return H.getModule()->getTopLevelModule() == TopLevel &&
                   H.getRole() == ExcludedHeader;
          });
      if (!IsExcluded) {
        OwningModules.push_back({TopLevel,
                                 UmbrellaOwner.getModule()->UmbrellaDeclLoc,
                                 /*IsUmbrella=*/true});
      }
    }
  }

  if (OwningModules.size() < 2)
    return;

  Diags.Report(FilenameLoc, diag::warn_mmap_duplicate_header_ownership)
      << Filename;
  for (const auto &Owner : OwningModules) {
    unsigned NoteID = Owner.IsUmbrella
                          ? diag::note_mmap_header_covered_by_umbrella
                          : diag::note_mmap_header_owned_by;
    Diags.Report(Owner.Loc, NoteID) << Owner.Mod->getFullModuleName();
  }
}

static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
                                const ModuleMap::KnownHeader &Old) {
  // Prefer available modules.
  // FIXME: Considering whether the module is available rather than merely
  // importable is non-hermetic and can result in surprising behavior for
  // prebuilt modules. Consider only checking for importability here.
  if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
    return true;

  // Prefer a public header over a private header.
  if ((New.getRole() & ModuleMap::PrivateHeader) !=
      (Old.getRole() & ModuleMap::PrivateHeader))
    return !(New.getRole() & ModuleMap::PrivateHeader);

  // Prefer a non-textual header over a textual header.
  if ((New.getRole() & ModuleMap::TextualHeader) !=
      (Old.getRole() & ModuleMap::TextualHeader))
    return !(New.getRole() & ModuleMap::TextualHeader);

  // Prefer a non-excluded header over an excluded header.
  if ((New.getRole() == ModuleMap::ExcludedHeader) !=
      (Old.getRole() == ModuleMap::ExcludedHeader))
    return New.getRole() != ModuleMap::ExcludedHeader;

  // Don't have a reason to choose between these. Just keep the first one.
  return false;
}

ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,
                                                      bool AllowTextual,
                                                      bool AllowExcluded) {
  auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
    if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
      return {};
    return R;
  };

  HeadersMap::iterator Known = findKnownHeader(File);
  if (Known != Headers.end()) {
    ModuleMap::KnownHeader Result;
    // Iterate over all modules that 'File' is part of to find the best fit.
    for (KnownHeader &H : Known->second) {
      // Cannot use a module if the header is excluded in it.
      if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
        continue;
      // Prefer a header from the source module over all others.
      if (H.getModule()->getTopLevelModule() == SourceModule)
        return MakeResult(H);
      if (!Result || isBetterKnownHeader(H, Result))
        Result = H;
    }
    return MakeResult(Result);
  }

  return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
}

OptionalFileEntryRef ModuleMap::findUmbrellaHeaderForModule(
    Module *M, std::string NameAsWritten,
    SmallVectorImpl<char> &RelativePathName) {
  Module::UnresolvedHeaderDirective Header;
  Header.FileName = std::move(NameAsWritten);
  Header.IsUmbrella = true;
  bool NeedsFramework;
  return findHeader(M, Header, RelativePathName, NeedsFramework);
}

ModuleMap::KnownHeader
ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
  assert(!Headers.count(File) && "already have a module for this header");

  SmallVector<DirectoryEntryRef, 2> SkippedDirs;
  KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
  if (H) {
    Module *Result = H.getModule();

    // Search up the module stack until we find a module with an umbrella
    // directory.
    Module *UmbrellaModule = Result;
    while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
      UmbrellaModule = UmbrellaModule->Parent;

    if (UmbrellaModule->InferSubmodules) {
      FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);

      // Infer submodules for each of the directories we found between
      // the directory of the umbrella header and the directory where
      // the actual header is located.
      bool Explicit = UmbrellaModule->InferExplicitSubmodules;

      for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
        // Find or create the module that corresponds to this directory name.
        SmallString<32> NameBuf;
        StringRef Name = sanitizeFilenameAsIdentifier(
            llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
        Result = findOrCreateModuleFirst(Name, Result, /*IsFramework=*/false,
                                         Explicit);
        setInferredModuleAllowedBy(Result, UmbrellaModuleMap);

        // Associate the module and the directory.
        UmbrellaDirs[SkippedDir] = Result;

        // If inferred submodules export everything they import, add a
        // wildcard to the set of exports.
        if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
          Result->Exports.push_back(Module::ExportDecl(nullptr, true));
      }

      // Infer a submodule with the same name as this header file.
      SmallString<32> NameBuf;
      StringRef Name = sanitizeFilenameAsIdentifier(
                         llvm::sys::path::stem(File.getName()), NameBuf);
      Result = findOrCreateModuleFirst(Name, Result, /*IsFramework=*/false,
                                       Explicit);
      setInferredModuleAllowedBy(Result, UmbrellaModuleMap);
      Result->addTopHeader(File);

      // If inferred submodules export everything they import, add a
      // wildcard to the set of exports.
      if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
        Result->Exports.push_back(Module::ExportDecl(nullptr, true));
    } else {
      // Record each of the directories we stepped through as being part of
      // the module we found, since the umbrella header covers them all.
      for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
        UmbrellaDirs[SkippedDirs[I]] = Result;
    }

    KnownHeader Header(Result, NormalHeader);
    Headers[File].push_back(Header);
    return Header;
  }

  return {};
}

ArrayRef<ModuleMap::KnownHeader>
ModuleMap::findAllModulesForHeader(FileEntryRef File) {
  HeadersMap::iterator Known = findKnownHeader(File);
  if (Known != Headers.end())
    return Known->second;

  if (findOrCreateModuleForHeaderInUmbrellaDir(File))
    return Headers.find(File)->second;

  return {};
}

ArrayRef<ModuleMap::KnownHeader>
ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
  // FIXME: Is this necessary?
  resolveHeaderDirectives(File);
  auto It = Headers.find(File);
  if (It == Headers.end())
    return {};
  return It->second;
}

bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
  return isHeaderUnavailableInModule(Header, nullptr);
}

bool ModuleMap::isHeaderUnavailableInModule(
    FileEntryRef Header, const Module *RequestingModule) const {
  resolveHeaderDirectives(Header);
  HeadersMap::const_iterator Known = Headers.find(Header);
  if (Known != Headers.end()) {
    for (SmallVectorImpl<KnownHeader>::const_iterator
             I = Known->second.begin(),
             E = Known->second.end();
         I != E; ++I) {

      if (I->getRole() == ModuleMap::ExcludedHeader)
        continue;

      if (I->isAvailable() &&
          (!RequestingModule ||
           I->getModule()->isSubModuleOf(RequestingModule))) {
        // When no requesting module is available, the caller is looking if a
        // header is part a module by only looking into the module map. This is
        // done by warn_uncovered_module_header checks; don't consider textual
        // headers part of it in this mode, otherwise we get misleading warnings
        // that a umbrella header is not including a textual header.
        if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
          continue;
        return false;
      }
    }
    return true;
  }

  OptionalDirectoryEntryRef Dir = Header.getDir();
  SmallVector<DirectoryEntryRef, 2> SkippedDirs;
  StringRef DirName = Dir->getName();

  auto IsUnavailable = [&](const Module *M) {
    return !M->isAvailable() && (!RequestingModule ||
                                 M->isSubModuleOf(RequestingModule));
  };

  // Keep walking up the directory hierarchy, looking for a directory with
  // an umbrella header.
  do {
    auto KnownDir = UmbrellaDirs.find(*Dir);
    if (KnownDir != UmbrellaDirs.end()) {
      Module *Found = KnownDir->second;
      if (IsUnavailable(Found))
        return true;

      // Search up the module stack until we find a module with an umbrella
      // directory.
      Module *UmbrellaModule = Found;
      while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
             UmbrellaModule->Parent)
        UmbrellaModule = UmbrellaModule->Parent;

      if (UmbrellaModule->InferSubmodules) {
        for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
          // Find or create the module that corresponds to this directory name.
          SmallString<32> NameBuf;
          StringRef Name = sanitizeFilenameAsIdentifier(
              llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
          Found = lookupModuleQualified(Name, Found);
          if (!Found)
            return false;
          if (IsUnavailable(Found))
            return true;
        }

        // Infer a submodule with the same name as this header file.
        SmallString<32> NameBuf;
        StringRef Name = sanitizeFilenameAsIdentifier(
                           llvm::sys::path::stem(Header.getName()),
                           NameBuf);
        Found = lookupModuleQualified(Name, Found);
        if (!Found)
          return false;
      }

      return IsUnavailable(Found);
    }

    SkippedDirs.push_back(*Dir);

    // Retrieve our parent path.
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.empty())
      break;

    // Resolve the parent path to a directory entry.
    Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
  } while (Dir);

  return false;
}

Module *ModuleMap::findModule(StringRef Name) const {
  llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
  if (Known != Modules.end())
    return Known->getValue();

  return nullptr;
}

Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
  if (Module *SubM = Parent->findSubmodule(Name))
    return SubM;
  if (!Parent->InferSubmodules)
    return nullptr;
  Module *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
             Parent->InferExplicitSubmodules, 0);
  Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
  Result->InferSubmodules = Parent->InferSubmodules;
  Result->InferExportWildcard = Parent->InferExportWildcard;
  if (Result->InferExportWildcard)
    Result->Exports.push_back(Module::ExportDecl(nullptr, true));
  return Result;
}

Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
                                           Module *Context) const {
  for(; Context; Context = Context->Parent) {
    if (Module *Sub = lookupModuleQualified(Name, Context))
      return Sub;
  }

  return findModule(Name);
}

ModuleRef ModuleMap::lookupModuleQualified(StringRef Name,
                                           Module *Context) const {
  if (!Context)
    return findModule(Name);

  return Context->findSubmodule(Name);
}

std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
                                                        Module *Parent,
                                                        bool IsFramework,
                                                        bool IsExplicit) {
  // Try to find an existing module with this name.
  if (ModuleRef Sub = lookupModuleQualified(Name, Parent); Sub.getExisting())
    return std::make_pair(Sub.getExisting(), false);

  // Create a new module with this name.
  Module *M = createModule(Name, Parent, IsFramework, IsExplicit);
  return std::make_pair(M, true);
}

Module *ModuleMap::createModule(StringRef Name, Module *Parent,
                                bool IsFramework, bool IsExplicit) {
  assert(!lookupModuleQualified(Name, Parent).getExisting() &&
         "Creating duplicate submodule");

  Module *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
             IsFramework, IsExplicit, NumCreatedModules++);
  if (!Parent) {
    if (LangOpts.CurrentModule == Name)
      SourceModule = Result;
    Modules[Name] = Result;
    ModuleScopeIDs[Result] = CurrentModuleScopeID;
  }
  return Result;
}

Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
                                                           Module *Parent) {
  auto *Result = new (ModulesAlloc.Allocate()) Module(
      ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
      /*IsExplicit=*/true, NumCreatedModules++);
  Result->Kind = Module::ExplicitGlobalModuleFragment;
  // If the created module isn't owned by a parent, send it to PendingSubmodules
  // to wait for its parent.
  if (!Result->Parent)
    PendingSubmodules.emplace_back(Result);
  return Result;
}

Module *
ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
                                                           Module *Parent) {
  assert(Parent && "We should only create an implicit global module fragment "
                   "in a module purview");
  // Note: Here the `IsExplicit` parameter refers to the semantics in clang
  // modules. All the non-explicit submodules in clang modules will be exported
  // too. Here we simplify the implementation by using the concept.
  auto *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
             /*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
  Result->Kind = Module::ImplicitGlobalModuleFragment;
  return Result;
}

Module *
ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
                                                       SourceLocation Loc) {
  auto *Result = new (ModulesAlloc.Allocate()) Module(
      ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
      /*IsExplicit=*/true, NumCreatedModules++);
  Result->Kind = Module::PrivateModuleFragment;
  return Result;
}

Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
                                            Module::ModuleKind Kind) {
  auto *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
             /*IsExplicit=*/false, NumCreatedModules++);
  Result->Kind = Kind;

  // Reparent any current global module fragment as a submodule of this module.
  for (auto &Submodule : PendingSubmodules)
    Submodule->setParent(Result);
  PendingSubmodules.clear();
  return Result;
}

Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
                                                StringRef Name) {
  assert(LangOpts.CurrentModule == Name && "module name mismatch");
  assert(!Modules[Name] && "redefining existing module");

  auto *Result =
      createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
  Modules[Name] = SourceModule = Result;

  // Mark the main source file as being within the newly-created module so that
  // declarations and macros are properly visibility-restricted to it.
  auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
  assert(MainFile && "no input file for module interface");
  Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));

  return Result;
}

Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
                                                     StringRef Name) {
  assert(LangOpts.CurrentModule == Name && "module name mismatch");
  // The interface for this implementation must exist and be loaded.
  assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
         "creating implementation module without an interface");

  // Create an entry in the modules map to own the implementation unit module.
  // User module names must not start with a period (so that this cannot clash
  // with any legal user-defined module name).
  StringRef IName = ".ImplementationUnit";
  assert(!Modules[IName] && "multiple implementation units?");

  auto *Result =
      createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
  Modules[IName] = SourceModule = Result;

  // Check that the main file is present.
  assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
         "no input file for module implementation");

  return Result;
}

Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
                                    Module::Header H) {
  assert(LangOpts.CurrentModule == Name && "module name mismatch");
  assert(!Modules[Name] && "redefining existing module");

  auto *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
             /*IsExplicit=*/false, NumCreatedModules++);
  Result->Kind = Module::ModuleHeaderUnit;
  Modules[Name] = SourceModule = Result;
  addHeader(Result, H, NormalHeader);
  return Result;
}

/// For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod) {
  assert(Mod->IsFramework && "Can only infer linking for framework modules");
  assert(!Mod->isSubFramework() &&
         "Can only infer linking for top-level frameworks");

  StringRef FrameworkName(Mod->Name);
  FrameworkName.consume_back("_Private");
  Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
                                                   /*IsFramework=*/true));
}

Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
                                        bool IsSystem, Module *Parent) {
  Attributes Attrs;
  Attrs.IsSystem = IsSystem;
  return inferFrameworkModule(FrameworkDir, Attrs, Parent);
}

Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
                                        Attributes Attrs, Module *Parent) {
  // Note: as an egregious but useful hack we use the real path here, because
  // we might be looking at an embedded framework that symlinks out to a
  // top-level framework, and we need to infer as if we were naming the
  // top-level framework.
  StringRef FrameworkDirName =
      SourceMgr.getFileManager().getCanonicalName(FrameworkDir);

  // In case this is a case-insensitive filesystem, use the canonical
  // directory name as the ModuleName, since modules are case-sensitive.
  // FIXME: we should be able to give a fix-it hint for the correct spelling.
  SmallString<32> ModuleNameStorage;
  StringRef ModuleName = sanitizeFilenameAsIdentifier(
      llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);

  // Check whether we've already found this module.
  if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
    return Mod;

  FileManager &FileMgr = SourceMgr.getFileManager();

  // If the framework has a parent path from which we're allowed to infer
  // a framework module, do so.
  FileID ModuleMapFID;
  if (!Parent) {
    // Determine whether we're allowed to infer a module map.
    bool canInfer = false;
    if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
      // Figure out the parent path.
      StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
      if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
        // Check whether we have already looked into the parent directory
        // for a module map.
        llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
          inferred = InferredDirectories.find(*ParentDir);
        if (inferred == InferredDirectories.end()) {
          // We haven't looked here before. Load a module map, if there is
          // one.
          bool IsFrameworkDir = Parent.ends_with(".framework");
          if (OptionalFileEntryRef ModMapFile =
                  HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
            // TODO: Parsing a module map should populate `InferredDirectories`
            //       so we don't need to do a full load here.
            parseAndLoadModuleMapFile(*ModMapFile, Attrs.IsSystem,
                                      /*ImplicitlyDiscovered=*/true,
                                      *ParentDir);
            inferred = InferredDirectories.find(*ParentDir);
          }

          if (inferred == InferredDirectories.end())
            inferred = InferredDirectories.insert(
                         std::make_pair(*ParentDir, InferredDirectory())).first;
        }

        if (inferred->second.InferModules) {
          // We're allowed to infer for this directory, but make sure it's okay
          // to infer this particular module.
          StringRef Name = llvm::sys::path::stem(FrameworkDirName);
          canInfer =
              !llvm::is_contained(inferred->second.ExcludedModules, Name);

          Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
          Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
          Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
          Attrs.NoUndeclaredIncludes |=
              inferred->second.Attrs.NoUndeclaredIncludes;
          ModuleMapFID = inferred->second.ModuleMapFID;
        }
      }
    }

    // If we're not allowed to infer a framework module, don't.
    if (!canInfer)
      return nullptr;
  } else {
    ModuleMapFID = getModuleMapFileIDForUniquing(Parent);
  }

  // Look for an umbrella header.
  SmallString<128> UmbrellaName = FrameworkDir.getName();
  llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
  auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);

  // FIXME: If there's no umbrella header, we could probably scan the
  // framework to load *everything*. But, it's not clear that this is a good
  // idea.
  if (!UmbrellaHeader)
    return nullptr;

  Module *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
             /*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
  setInferredModuleAllowedBy(Result, ModuleMapFID);
  if (!Parent) {
    if (LangOpts.CurrentModule == ModuleName)
      SourceModule = Result;
    Modules[ModuleName] = Result;
    ModuleScopeIDs[Result] = CurrentModuleScopeID;
  }

  Result->IsSystem |= Attrs.IsSystem;
  Result->IsExternC |= Attrs.IsExternC;
  Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
  Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
  Result->Directory = FrameworkDir;

  // Chop off the first framework bit, as that is implied.
  StringRef RelativePath = UmbrellaName.str().substr(
      Result->getTopLevelModule()->Directory->getName().size());
  RelativePath = llvm::sys::path::relative_path(RelativePath);

  // umbrella header "umbrella-header-name"
  setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
                             RelativePath);

  // export *
  Result->Exports.push_back(Module::ExportDecl(nullptr, true));

  // module * { export * }
  Result->InferSubmodules = true;
  Result->InferExportWildcard = true;

  // Look for subframeworks.
  std::error_code EC;
  SmallString<128> SubframeworksDirName = FrameworkDir.getName();
  llvm::sys::path::append(SubframeworksDirName, "Frameworks");
  llvm::sys::path::native(SubframeworksDirName);
  llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
  for (llvm::vfs::directory_iterator
           Dir = FS.dir_begin(SubframeworksDirName, EC),
           DirEnd;
       Dir != DirEnd && !EC; Dir.increment(EC)) {
    if (!StringRef(Dir->path()).ends_with(".framework"))
      continue;

    if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
      // Note: as an egregious but useful hack, we use the real path here and
      // check whether it is actually a subdirectory of the parent directory.
      // This will not be the case if the 'subframework' is actually a symlink
      // out to a top-level framework.
      StringRef SubframeworkDirName =
          FileMgr.getCanonicalName(*SubframeworkDir);
      bool FoundParent = false;
      do {
        // Get the parent directory name.
        SubframeworkDirName
          = llvm::sys::path::parent_path(SubframeworkDirName);
        if (SubframeworkDirName.empty())
          break;

        if (auto SubDir =
                FileMgr.getOptionalDirectoryRef(SubframeworkDirName)) {
          if (*SubDir == FrameworkDir) {
            FoundParent = true;
            break;
          }
        }
      } while (true);

      if (!FoundParent)
        continue;

      // FIXME: Do we want to warn about subframeworks without umbrella headers?
      inferFrameworkModule(*SubframeworkDir, Attrs, Result);
    }
  }

  // If the module is a top-level framework, automatically link against the
  // framework.
  if (!Result->isSubFramework())
    inferFrameworkLink(Result);

  return Result;
}

Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
                                        Module *ShadowingModule) {

  // Create a new module with this name.
  Module *Result = new (ModulesAlloc.Allocate())
      Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
             IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
  Result->ShadowingModule = ShadowingModule;
  Result->markUnavailable(/*Unimportable*/true);
  ModuleScopeIDs[Result] = CurrentModuleScopeID;
  ShadowModules.push_back(Result);

  return Result;
}

void ModuleMap::setUmbrellaHeaderAsWritten(
    Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
    const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc) {
  Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
  if (Loc.isValid())
    HeaderOwnerLocs[{&UmbrellaHeader.getFileEntry(), Mod}] = Loc;
  Mod->Umbrella = UmbrellaHeader;
  Mod->UmbrellaDeclLoc = Loc;
  Mod->UmbrellaAsWritten = NameAsWritten.str();
  Mod->UmbrellaRelativeToRootModuleDirectory =
      PathRelativeToRootModuleDirectory.str();
  UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;

  // Notify callbacks that we just added a new header.
  for (const auto &Cb : Callbacks)
    Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
}

void ModuleMap::setUmbrellaDirAsWritten(
    Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
    const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc) {
  Mod->Umbrella = UmbrellaDir;
  Mod->UmbrellaDeclLoc = Loc;
  Mod->UmbrellaAsWritten = NameAsWritten.str();
  Mod->UmbrellaRelativeToRootModuleDirectory =
      PathRelativeToRootModuleDirectory.str();
  UmbrellaDirs[UmbrellaDir] = Mod;
}

void ModuleMap::addUnresolvedHeader(Module *Mod,
                                    Module::UnresolvedHeaderDirective Header,
                                    bool &NeedsFramework) {
  // If there is a builtin counterpart to this file, add it now so it can
  // wrap the system header.
  if (resolveAsBuiltinHeader(Mod, Header)) {
    // If we have both a builtin and system version of the file, the
    // builtin version may want to inject macros into the system header, so
    // force the system header to be treated as a textual header in this
    // case.
    Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
        headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
    Header.HasBuiltinHeader = true;
  }

  // If possible, don't stat the header until we need to. This requires the
  // user to have provided us with some stat information about the file.
  // FIXME: Add support for lazily stat'ing umbrella headers and excluded
  // headers.
  if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
      Header.Kind != Module::HK_Excluded) {
    // We expect more variation in mtime than size, so if we're given both,
    // use the mtime as the key.
    if (Header.ModTime)
      LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
    else
      LazyHeadersBySize[*Header.Size].push_back(Mod);
    Mod->UnresolvedHeaders.push_back(Header);
    return;
  }

  // We don't have stat information or can't defer looking this file up.
  // Perform the lookup now.
  resolveHeader(Mod, Header, NeedsFramework);
}

void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
  auto BySize = LazyHeadersBySize.find(File->getSize());
  if (BySize != LazyHeadersBySize.end()) {
    for (auto *M : BySize->second)
      resolveHeaderDirectives(M, File);
    LazyHeadersBySize.erase(BySize);
  }

  auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
  if (ByModTime != LazyHeadersByModTime.end()) {
    for (auto *M : ByModTime->second)
      resolveHeaderDirectives(M, File);
    LazyHeadersByModTime.erase(ByModTime);
  }
}

void ModuleMap::resolveHeaderDirectives(
    Module *Mod, std::optional<const FileEntry *> File) const {
  bool NeedsFramework = false;
  SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
  const auto Size = File ? (*File)->getSize() : 0;
  const auto ModTime = File ? (*File)->getModificationTime() : 0;

  for (auto &Header : Mod->UnresolvedHeaders) {
    if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
                 (Header.Size && Header.Size != Size)))
      NewHeaders.push_back(Header);
    else
      // This operation is logically const; we're just changing how we represent
      // the header information for this file.
      const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
  }
  Mod->UnresolvedHeaders.swap(NewHeaders);
}

void ModuleMap::addHeader(Module *Mod, Module::Header Header,
                          ModuleHeaderRole Role, bool Imported,
                          SourceLocation Loc) {
  KnownHeader KH(Mod, Role);

  FileEntryRef HeaderEntry = Header.Entry;

  // Only add each header to the headers list once.
  // FIXME: Should we diagnose if a header is listed twice in the
  // same module definition?
  auto &HeaderList = Headers[HeaderEntry];
  if (llvm::is_contained(HeaderList, KH))
    return;

  if (Loc.isValid())
    HeaderOwnerLocs[{&HeaderEntry.getFileEntry(), Mod}] = Loc;

  HeaderList.push_back(KH);
  Mod->addHeader(headerRoleToKind(Role), std::move(Header));

  bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
  if (!Imported || isCompilingModuleHeader) {
    // When we import HeaderFileInfo, the external source is expected to
    // set the isModuleHeader flag itself.
    HeaderInfo.MarkFileModuleHeader(HeaderEntry, Role, isCompilingModuleHeader);
  }

  // Notify callbacks that we just added a new header.
  for (const auto &Cb : Callbacks)
    Cb->moduleMapAddHeader(HeaderEntry.getName());
}

bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
                                   bool ImplicitlyDiscovered,
                                   DirectoryEntryRef Dir, FileID ID,
                                   SourceLocation ExternModuleLoc) {
  llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
      Known = ParsedModuleMap.find(File);
  if (Known != ParsedModuleMap.end())
    return Known->second == nullptr;

  // If the module map file wasn't already entered, do so now.
  if (ID.isInvalid()) {
    FileID &LocalFID = ModuleMapLocalFileID[File];
    if (LocalFID.isInvalid()) {
      auto FileCharacter =
          IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
      LocalFID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
    }
    ID = LocalFID;
  }

  std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
  if (!Buffer) {
    ParsedModuleMap[File] = nullptr;
    return true;
  }

  Diags.Report(diag::remark_mmap_parse) << File.getName();
  std::optional<modulemap::ModuleMapFile> MaybeMMF = modulemap::parseModuleMap(
      ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, nullptr);

  if (!MaybeMMF) {
    ParsedModuleMap[File] = nullptr;
    return true;
  }

  ParsedModuleMaps.push_back(
      std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
  const modulemap::ModuleMapFile &MMF = *ParsedModuleMaps.back();
  std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
  std::function<void(const modulemap::ModuleDecl &)> CollectExternDecls =
      [&](const modulemap::ModuleDecl &MD) {
        for (const auto &Decl : MD.Decls) {
          std::visit(llvm::makeVisitor(
                         [&](const modulemap::ModuleDecl &SubMD) {
                           // Skip inferred submodules (module *)
                           if (SubMD.Id.front().first == "*")
                             return;
                           CollectExternDecls(SubMD);
                         },
                         [&](const modulemap::ExternModuleDecl &EMD) {
                           PendingExternalModuleMaps.push_back(&EMD);
                         },
                         [&](const auto &) {
                           // Ignore other decls
                         }),
                     Decl);
        }
      };

  for (const auto &Decl : MMF.Decls) {
    std::visit(llvm::makeVisitor(
                   [&](const modulemap::ModuleDecl &MD) {
                     // Only use the first part of the name even for submodules.
                     // This will correctly load the submodule declarations when
                     // the module is loaded.
                     auto &ModuleDecls =
                         ParsedModules[StringRef(MD.Id.front().first)];
                     ModuleDecls.push_back(std::pair(&MMF, &MD));
                     CollectExternDecls(MD);
                   },
                   [&](const modulemap::ExternModuleDecl &EMD) {
                     PendingExternalModuleMaps.push_back(&EMD);
                   }),
               Decl);
  }

  for (const modulemap::ExternModuleDecl *EMD : PendingExternalModuleMaps) {
    StringRef FileNameRef = EMD->Path;
    SmallString<128> ModuleMapFileName;
    if (llvm::sys::path::is_relative(FileNameRef)) {
      ModuleMapFileName += Dir.getName();
      llvm::sys::path::append(ModuleMapFileName, EMD->Path);
      FileNameRef = ModuleMapFileName;
    }

    if (auto EFile =
            SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
      parseModuleMapFile(*EFile, IsSystem, ImplicitlyDiscovered,
                         EFile->getDir(), FileID(), ExternModuleLoc);
    }
  }

  ParsedModuleMap[File] = &MMF;

  for (const auto &Cb : Callbacks)
    Cb->moduleMapFileRead(SourceLocation(), File, IsSystem);

  return false;
}

void ModuleMap::loadAllParsedModules() {
  for (const auto &Entry : ParsedModules)
    findOrLoadModule(Entry.first());
}

FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {
  if (Module->DefinitionLoc.isInvalid())
    return {};

  return SourceMgr.getFileID(Module->DefinitionLoc);
}

OptionalFileEntryRef
ModuleMap::getContainingModuleMapFile(const Module *Module) const {
  return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module));
}

FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
  if (M->IsInferred) {
    assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
    return InferredModuleAllowedBy.find(M)->second;
  }
  return getContainingModuleMapFileID(M);
}

OptionalFileEntryRef
ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
  return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M));
}

void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
  M->IsInferred = true;
  InferredModuleAllowedBy[M] = ModMapFID;
}

std::error_code
ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
  StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});

  // Do not canonicalize within the framework; the module map loader expects
  // Modules/ not Versions/A/Modules.
  if (llvm::sys::path::filename(Dir) == "Modules") {
    StringRef Parent = llvm::sys::path::parent_path(Dir);
    if (Parent.ends_with(".framework"))
      Dir = Parent;
  }

  FileManager &FM = SourceMgr.getFileManager();
  auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
  if (!DirEntry)
    return llvm::errorToErrorCode(DirEntry.takeError());

  // Canonicalize the directory.
  StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
  if (CanonicalDir != Dir)
    llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);

  // In theory, the filename component should also be canonicalized if it
  // on a case-insensitive filesystem. However, the extra canonicalization is
  // expensive and if clang looked up the filename it will always be lowercase.

  // Remove ., remove redundant separators, and switch to native separators.
  // This is needed for separators between CanonicalDir and the filename.
  llvm::sys::path::remove_dots(Path);

  return std::error_code();
}

void ModuleMap::addAdditionalModuleMapFile(const Module *M,
                                           FileEntryRef ModuleMap) {
  AdditionalModMaps[M].insert(ModuleMap);
}

LLVM_DUMP_METHOD void ModuleMap::dump() {
  llvm::errs() << "Modules:";
  for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
                                        MEnd = Modules.end();
       M != MEnd; ++M)
    M->getValue()->print(llvm::errs(), 2);

  llvm::errs() << "Headers:";
  for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
       H != HEnd; ++H) {
    llvm::errs() << "  \"" << H->first.getName() << "\" -> ";
    for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
                                                      E = H->second.end();
         I != E; ++I) {
      if (I != H->second.begin())
        llvm::errs() << ",";
      llvm::errs() << I->getModule()->getFullModuleName();
    }
    llvm::errs() << "\n";
  }
}

bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
  auto Unresolved = std::move(Mod->UnresolvedExports);
  Mod->UnresolvedExports.clear();
  for (auto &UE : Unresolved) {
    Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
    if (Export.first || Export.second)
      Mod->Exports.push_back(Export);
    else
      Mod->UnresolvedExports.push_back(UE);
  }
  return !Mod->UnresolvedExports.empty();
}

bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
  auto *Top = Mod->getTopLevelModule();
  auto Unresolved = std::move(Top->UnresolvedDirectUses);
  Top->UnresolvedDirectUses.clear();
  for (auto &UDU : Unresolved) {
    Module *DirectUse = resolveModuleId(UDU, Top, Complain);
    if (DirectUse)
      Top->DirectUses.push_back(DirectUse);
    else
      Top->UnresolvedDirectUses.push_back(UDU);
  }
  return !Top->UnresolvedDirectUses.empty();
}

bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
  auto Unresolved = std::move(Mod->UnresolvedConflicts);
  Mod->UnresolvedConflicts.clear();
  for (auto &UC : Unresolved) {
    if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
      Module::Conflict Conflict;
      Conflict.Other = OtherMod;
      Conflict.Message = UC.Message;
      Mod->Conflicts.push_back(Conflict);
    } else
      Mod->UnresolvedConflicts.push_back(UC);
  }
  return !Mod->UnresolvedConflicts.empty();
}

//----------------------------------------------------------------------------//
// Module map file loader
//----------------------------------------------------------------------------//

namespace clang {
class ModuleMapLoader {
  SourceManager &SourceMgr;

  DiagnosticsEngine &Diags;
  ModuleMap &Map;

  /// The current module map file.
  FileID ModuleMapFID;

  /// Source location of most recent loaded module declaration
  SourceLocation CurrModuleDeclLoc;

  /// The directory that file names in this module map file should
  /// be resolved relative to.
  DirectoryEntryRef Directory;

  /// Whether this module map is in a system header directory.
  bool IsSystem;

  bool ImplicitlyDiscovered;

  /// Whether an error occurred.
  bool HadError = false;

  /// The active module.
  Module *ActiveModule = nullptr;

  /// Whether a module uses the 'requires excluded' hack to mark its
  /// contents as 'textual'.
  ///
  /// On older Darwin SDK versions, 'requires excluded' is used to mark the
  /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
  /// non-modular headers.  For backwards compatibility, we continue to
  /// support this idiom for just these modules, and map the headers to
  /// 'textual' to match the original intent.
  llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;

  void handleModuleDecl(const modulemap::ModuleDecl &MD);
  void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
  void handleRequiresDecl(const modulemap::RequiresDecl &RD);
  void handleHeaderDecl(const modulemap::HeaderDecl &HD);
  void handleUmbrellaDirDecl(const modulemap::UmbrellaDirDecl &UDD);
  void handleExportDecl(const modulemap::ExportDecl &ED);
  void handleExportAsDecl(const modulemap::ExportAsDecl &EAD);
  void handleUseDecl(const modulemap::UseDecl &UD);
  void handleLinkDecl(const modulemap::LinkDecl &LD);
  void handleConfigMacros(const modulemap::ConfigMacrosDecl &CMD);
  void handleConflict(const modulemap::ConflictDecl &CD);
  void handleInferredModuleDecl(const modulemap::ModuleDecl &MD);

  /// Private modules are canonicalized as Foo_Private. Clang provides extra
  /// module map search logic to find the appropriate private module when PCH
  /// is used with implicit module maps. Warn when private modules are written
  /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
  void diagnosePrivateModules(SourceLocation StartLoc);

  using Attributes = ModuleMap::Attributes;

public:
  ModuleMapLoader(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                  ModuleMap &Map, FileID ModuleMapFID,
                  DirectoryEntryRef Directory, bool IsSystem,
                  bool ImplicitlyDiscovered)
      : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
        ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
        ImplicitlyDiscovered(ImplicitlyDiscovered) {}

  bool loadModuleDecl(const modulemap::ModuleDecl &MD);
  bool loadExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
  bool parseAndLoadModuleMapFile(const modulemap::ModuleMapFile &MMF);
};

} // namespace clang

/// Private modules are canonicalized as Foo_Private. Clang provides extra
/// module map search logic to find the appropriate private module when PCH
/// is used with implicit module maps. Warn when private modules are written
/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
void ModuleMapLoader::diagnosePrivateModules(SourceLocation StartLoc) {
  auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
                             const Module *M, SourceRange ReplLoc) {
    auto D = Diags.Report(ActiveModule->DefinitionLoc,
                          diag::note_mmap_rename_top_level_private_module);
    D << BadName << M->Name;
    D << FixItHint::CreateReplacement(ReplLoc, Canonical);
  };

  for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
    auto const *M = E->getValue();
    if (M->Directory != ActiveModule->Directory)
      continue;

    SmallString<128> FullName(ActiveModule->getFullModuleName());
    if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
      continue;
    SmallString<128> FixedPrivModDecl;
    SmallString<128> Canonical(M->Name);
    Canonical.append("_Private");

    // Foo.Private -> Foo_Private
    if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
        M->Name == ActiveModule->Parent->Name) {
      Diags.Report(ActiveModule->DefinitionLoc,
                   diag::warn_mmap_mismatched_private_submodule)
          << FullName;

      SourceLocation FixItInitBegin = CurrModuleDeclLoc;
      if (StartLoc.isValid())
        FixItInitBegin = StartLoc;

      if (ActiveModule->Parent->IsFramework)
        FixedPrivModDecl.append("framework ");
      FixedPrivModDecl.append("module ");
      FixedPrivModDecl.append(Canonical);

      GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
                      SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
      continue;
    }

    // FooPrivate and whatnots -> Foo_Private
    if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
        ActiveModule->Name != Canonical) {
      Diags.Report(ActiveModule->DefinitionLoc,
                   diag::warn_mmap_mismatched_private_module_name)
          << ActiveModule->Name;
      GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
                      SourceRange(ActiveModule->DefinitionLoc));
    }
  }
}

void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
  if (MD.Id.front().first == "*")
    return handleInferredModuleDecl(MD);

  CurrModuleDeclLoc = MD.Location;

  Module *PreviousActiveModule = ActiveModule;
  if (MD.Id.size() > 1) {
    // This module map defines a submodule. Go find the module of which it
    // is a submodule.
    ActiveModule = nullptr;
    const Module *TopLevelModule = nullptr;
    for (unsigned I = 0, N = MD.Id.size() - 1; I != N; ++I) {
      if (Module *Next =
              Map.lookupModuleQualified(MD.Id[I].first, ActiveModule)) {
        if (I == 0)
          TopLevelModule = Next;
        ActiveModule = Next;
        continue;
      }

      Diags.Report(MD.Id[I].second, diag::err_mmap_missing_parent_module)
          << MD.Id[I].first << (ActiveModule != nullptr)
          << (ActiveModule
                  ? ActiveModule->getTopLevelModule()->getFullModuleName()
                  : "");
      HadError = true;
    }

    if (TopLevelModule &&
        ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
      assert(ModuleMapFID !=
                 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
             "submodule defined in same file as 'module *' that allowed its "
             "top-level module");
      Map.addAdditionalModuleMapFile(
          TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
    }
  }

  StringRef ModuleName = MD.Id.back().first;
  SourceLocation ModuleNameLoc = MD.Id.back().second;

  // Determine whether this (sub)module has already been defined.
  Module *ShadowingModule = nullptr;
  if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
    // We might see a (re)definition of a module that we already have a
    // definition for in four cases:
    //  - If the Existing module was loaded from an AST file and we've found its
    //    original source module map, or we cannot determine Existing's
    //    definition location.
    bool LoadedFromASTFile = Existing->IsFromModuleFile;
    if (LoadedFromASTFile) {
      OptionalFileEntryRef ExistingModMapFile =
          Map.getContainingModuleMapFile(Existing);
      OptionalFileEntryRef CurrentModMapFile =
          SourceMgr.getFileEntryRefForID(ModuleMapFID);
      if ((ExistingModMapFile && CurrentModMapFile &&
           *ExistingModMapFile == *CurrentModMapFile) ||
          Existing->DefinitionLoc.isInvalid()) {
        // If we do not know Existing's definition location, we have
        // no way of checking against it, and hence we stay conservative and do
        // not check for duplicating module definitions.
        LoadedFromASTFile = true;
      } else
        LoadedFromASTFile = false;
    }
    //  - If we previously inferred this module from different module map file.
    bool Inferred = Existing->IsInferred;
    //  - If we're building a framework that vends a module map, we might've
    //    previously seen the one in intermediate products and now the system
    //    one.
    // FIXME: If we're parsing module map file that looks like this:
    //          framework module FW { ... }
    //          module FW.Sub { ... }
    //        We can't check the framework qualifier, since it's not attached to
    //        the definition of Sub. Checking that qualifier on \c Existing is
    //        not correct either, since we might've previously seen:
    //          module FW { ... }
    //          module FW.Sub { ... }
    //        We should enforce consistency of redefinitions so that we can rely
    //        that \c Existing is part of a framework iff the redefinition of FW
    //        we have just skipped had it too. Once we do that, stop checking
    //        the local framework qualifier and only rely on \c Existing.
    bool PartOfFramework = MD.Framework || Existing->isPartOfFramework();
    //  - If we're building a (preprocessed) module and we've just loaded the
    //    module map file from which it was created.
    bool ParsedAsMainInput =
        Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
        Map.LangOpts.CurrentModule == ModuleName &&
        SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
            SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
    // TODO: Remove this check when we can avoid loading module maps multiple
    //       times.
    bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
    if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
        SameModuleDecl) {
      ActiveModule = PreviousActiveModule;
      // Skip the module definition.
      return;
    }

    if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
      ShadowingModule = Existing;
    } else {
      // This is not a shawdowed module decl, it is an illegal redefinition.
      Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
          << ModuleName;
      Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
      HadError = true;
      return;
    }
  }

  // Start defining this module.
  if (ShadowingModule) {
    ActiveModule =
        Map.createShadowedModule(ModuleName, MD.Framework, ShadowingModule);
  } else {
    ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
                                               MD.Framework, MD.Explicit);
  }

  ActiveModule->DefinitionLoc = ModuleNameLoc;
  if (MD.Attrs.IsSystem || IsSystem)
    ActiveModule->IsSystem = true;
  if (MD.Attrs.IsExternC)
    ActiveModule->IsExternC = true;
  if (MD.Attrs.NoUndeclaredIncludes)
    ActiveModule->NoUndeclaredIncludes = true;
  ActiveModule->Directory = Directory;

  StringRef MapFileName(
      SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
  if (MapFileName.ends_with("module.private.modulemap") ||
      MapFileName.ends_with("module_private.map")) {
    ActiveModule->ModuleMapIsPrivate = true;
  }

  // Private modules named as FooPrivate, Foo.Private or similar are likely a
  // user error; provide warnings, notes and fixits to direct users to use
  // Foo_Private instead.
  SourceLocation StartLoc =
      SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
  if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
      !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
                       StartLoc) &&
      !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
                       StartLoc) &&
      ActiveModule->ModuleMapIsPrivate)
    diagnosePrivateModules(MD.Location);

  for (const modulemap::Decl &Decl : MD.Decls) {
    std::visit(
        llvm::makeVisitor(
            [&](const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
            [&](const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
            [&](const modulemap::UmbrellaDirDecl &UDD) {
              handleUmbrellaDirDecl(UDD);
            },
            [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
            [&](const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
            [&](const modulemap::ExportAsDecl &EAD) {
              handleExportAsDecl(EAD);
            },
            [&](const modulemap::ExternModuleDecl &EMD) {
              handleExternModuleDecl(EMD);
            },
            [&](const modulemap::UseDecl &UD) { handleUseDecl(UD); },
            [&](const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
            [&](const modulemap::ConfigMacrosDecl &CMD) {
              handleConfigMacros(CMD);
            },
            [&](const modulemap::ConflictDecl &CD) { handleConflict(CD); },
            [&](const modulemap::ExcludeDecl &ED) {
              Diags.Report(ED.Location, diag::err_mmap_expected_member);
            }),
        Decl);
  }

  // If the active module is a top-level framework, and there are no link
  // libraries, automatically link against the framework.
  if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
      ActiveModule->LinkLibraries.empty())
    inferFrameworkLink(ActiveModule);

  // If the module meets all requirements but is still unavailable, mark the
  // whole tree as unavailable to prevent it from building.
  if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
      ActiveModule->Parent) {
    ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
    ActiveModule->getTopLevelModule()->MissingHeaders.append(
      ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
  }

  // We're done parsing this module. Pop back to the previous module.
  ActiveModule = PreviousActiveModule;
}

void ModuleMapLoader::handleExternModuleDecl(
    const modulemap::ExternModuleDecl &EMD) {
  StringRef FileNameRef = EMD.Path;
  SmallString<128> ModuleMapFileName;
  if (llvm::sys::path::is_relative(FileNameRef)) {
    ModuleMapFileName += Directory.getName();
    llvm::sys::path::append(ModuleMapFileName, EMD.Path);
    // As extern module declarations are parsed recursively, relative paths
    // to those modules can become arbitrarily long.
    // If the OS name length limit is exceeded when trying to get the file ref
    // we can silently fail to find an extern module that exists.
    // To mitigate this, collapse relative paths containing '../' for when
    // constructing the name of each module file referenced as an extern module.
    llvm::sys::path::remove_dots(ModuleMapFileName, /*remove_dot_dot=*/true);
    FileNameRef = ModuleMapFileName;
  }
  if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
    Map.parseAndLoadModuleMapFile(
        *File, IsSystem, ImplicitlyDiscovered,
        Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
            ? Directory
            : File->getDir(),
        FileID(), nullptr, EMD.Location);
}

/// Whether to add the requirement \p Feature to the module \p M.
///
/// This preserves backwards compatibility for two hacks in the Darwin system
/// module map files:
///
/// 1. The use of 'requires excluded' to make headers non-modular, which
///    should really be mapped to 'textual' now that we have this feature.  We
///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
///    true.  Later, this bit will be used to map all the headers inside this
///    module to 'textual'.
///
///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
///
/// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
///    was never correct and causes issues now that we check it, so drop it.
static bool shouldAddRequirement(Module *M, StringRef Feature,
                                 bool &IsRequiresExcludedHack) {
  if (Feature == "excluded" &&
      (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
       M->fullModuleNameIs({"Tcl", "Private"}))) {
    IsRequiresExcludedHack = true;
    return false;
  } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
    return false;
  }

  return true;
}

void ModuleMapLoader::handleRequiresDecl(const modulemap::RequiresDecl &RD) {

  for (const modulemap::RequiresFeature &RF : RD.Features) {
    bool IsRequiresExcludedHack = false;
    bool ShouldAddRequirement =
        shouldAddRequirement(ActiveModule, RF.Feature, IsRequiresExcludedHack);

    if (IsRequiresExcludedHack)
      UsesRequiresExcludedHack.insert(ActiveModule);

    if (ShouldAddRequirement) {
      // Add this feature.
      ActiveModule->addRequirement(RF.Feature, RF.RequiredState, Map.LangOpts,
                                   *Map.Target);
    }
  }
}

void ModuleMapLoader::handleHeaderDecl(const modulemap::HeaderDecl &HD) {
  // We've already consumed the first token.
  ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;

  if (HD.Private) {
    Role = ModuleMap::PrivateHeader;
  } else if (HD.Excluded) {
    Role = ModuleMap::ExcludedHeader;
  }

  if (HD.Textual)
    Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);

  if (UsesRequiresExcludedHack.count(ActiveModule)) {
    // Mark this header 'textual' (see doc comment for
    // Module::UsesRequiresExcludedHack).
    Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
  }

  Module::UnresolvedHeaderDirective Header;
  Header.FileName = HD.Path;
  Header.FileNameLoc = HD.PathLoc;
  Header.IsUmbrella = HD.Umbrella;
  Header.Kind = Map.headerRoleToKind(Role);

  // Check whether we already have an umbrella.
  if (Header.IsUmbrella &&
      !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
    Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
      << ActiveModule->getFullModuleName();
    HadError = true;
    return;
  }

  if (ImplicitlyDiscovered) {
    SmallString<128> NormalizedPath(HD.Path);
    llvm::sys::path::remove_dots(NormalizedPath, /*remove_dot_dot=*/true);
    if (NormalizedPath.starts_with(".."))
      Diags.Report(HD.PathLoc, diag::warn_mmap_path_outside_directory);
  }

  if (HD.Size)
    Header.Size = HD.Size;
  if (HD.MTime)
    Header.ModTime = HD.MTime;

  bool NeedsFramework = false;
  // Don't add headers to the builtin modules if the builtin headers belong to
  // the system modules, with the exception of __stddef_max_align_t.h which
  // always had its own module.
  if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
      !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
      ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
    Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);

  if (NeedsFramework)
    Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
      << ActiveModule->getFullModuleName()
      << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
}

static bool compareModuleHeaders(const Module::Header &A,
                                 const Module::Header &B) {
  return A.NameAsWritten < B.NameAsWritten;
}

void ModuleMapLoader::handleUmbrellaDirDecl(
    const modulemap::UmbrellaDirDecl &UDD) {
  std::string DirName = std::string(UDD.Path);
  std::string DirNameAsWritten = DirName;

  // Check whether we already have an umbrella.
  if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
    Diags.Report(UDD.Location, diag::err_mmap_umbrella_clash)
        << ActiveModule->getFullModuleName();
    HadError = true;
    return;
  }

  if (ImplicitlyDiscovered) {
    SmallString<128> NormalizedPath(UDD.Path);
    llvm::sys::path::remove_dots(NormalizedPath, /*remove_dot_dot=*/true);
    if (NormalizedPath.starts_with(".."))
      Diags.Report(UDD.Location, diag::warn_mmap_path_outside_directory);
  }

  // Look for this file.
  OptionalDirectoryEntryRef Dir;
  if (llvm::sys::path::is_absolute(DirName)) {
    Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
  } else {
    SmallString<128> PathName;
    PathName = Directory.getName();
    llvm::sys::path::append(PathName, DirName);
    Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
  }

  if (!Dir) {
    Diags.Report(UDD.Location, diag::warn_mmap_umbrella_dir_not_found)
        << DirName;
    return;
  }

  if (UsesRequiresExcludedHack.count(ActiveModule)) {
    // Mark this header 'textual' (see doc comment for
    // ModuleMapLoader::UsesRequiresExcludedHack). Although iterating over the
    // directory is relatively expensive, in practice this only applies to the
    // uncommonly used Tcl module on Darwin platforms.
    std::error_code EC;
    SmallVector<Module::Header, 6> Headers;
    llvm::vfs::FileSystem &FS =
        SourceMgr.getFileManager().getVirtualFileSystem();
    for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
         I != E && !EC; I.increment(EC)) {
      if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
        Module::Header Header = {"", std::string(I->path()), *FE};
        Headers.push_back(std::move(Header));
      }
    }

    // Sort header paths so that the pcm doesn't depend on iteration order.
    llvm::stable_sort(Headers, compareModuleHeaders);

    for (auto &Header : Headers)
      Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
    return;
  }

  if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
    Diags.Report(UDD.Location, diag::err_mmap_umbrella_clash)
        << OwningModule->getFullModuleName();
    HadError = true;
    return;
  }

  // Record this umbrella directory.
  Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName,
                              UDD.Location);
}

void ModuleMapLoader::handleExportDecl(const modulemap::ExportDecl &ED) {
  Module::UnresolvedExportDecl Unresolved = {ED.Location, ED.Id, ED.Wildcard};
  ActiveModule->UnresolvedExports.push_back(Unresolved);
}

void ModuleMapLoader::handleExportAsDecl(const modulemap::ExportAsDecl &EAD) {
  const auto &ModName = EAD.Id.front();

  if (!ActiveModule->ExportAsModule.empty()) {
    if (ActiveModule->ExportAsModule == ModName.first) {
      Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
          << ActiveModule->Name << ModName.first;
    } else {
      Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
          << ActiveModule->Name << ActiveModule->ExportAsModule
          << ModName.first;
    }
  }

  ActiveModule->ExportAsModule = ModName.first;
  Map.addLinkAsDependency(ActiveModule);
}

void ModuleMapLoader::handleUseDecl(const modulemap::UseDecl &UD) {
  if (ActiveModule->Parent)
    Diags.Report(UD.Location, diag::err_mmap_use_decl_submodule);
  else
    ActiveModule->UnresolvedDirectUses.push_back(UD.Id);
}

void ModuleMapLoader::handleLinkDecl(const modulemap::LinkDecl &LD) {
  ActiveModule->LinkLibraries.push_back(
      Module::LinkLibrary(std::string{LD.Library}, LD.Framework));
}

void ModuleMapLoader::handleConfigMacros(
    const modulemap::ConfigMacrosDecl &CMD) {
  if (ActiveModule->Parent) {
    Diags.Report(CMD.Location, diag::err_mmap_config_macro_submodule);
    return;
  }

  // TODO: Is this really the behavior we want for multiple config_macros
  //       declarations? If any of them are exhaustive then all of them are.
  if (CMD.Exhaustive) {
    ActiveModule->ConfigMacrosExhaustive = true;
  }
  ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
                                    CMD.Macros.begin(), CMD.Macros.end());
}

void ModuleMapLoader::handleConflict(const modulemap::ConflictDecl &CD) {
  Module::UnresolvedConflict Conflict;

  Conflict.Id = CD.Id;
  Conflict.Message = CD.Message;

  // FIXME: when we move to C++20 we should consider using emplace_back
  ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
}

void ModuleMapLoader::handleInferredModuleDecl(
    const modulemap::ModuleDecl &MD) {
  SourceLocation StarLoc = MD.Id.front().second;

  // Inferred modules must be submodules.
  if (!ActiveModule && !MD.Framework) {
    Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
    return;
  }

  if (ActiveModule) {
    // Inferred modules must have umbrella directories.
    if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
      Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
      return;
    }

    // Check for redefinition of an inferred module.
    if (ActiveModule->InferSubmodules) {
      Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
      if (ActiveModule->InferredSubmoduleLoc.isValid())
        Diags.Report(ActiveModule->InferredSubmoduleLoc,
                     diag::note_mmap_prev_definition);
      return;
    }

    // Check for the 'framework' keyword, which is not permitted here.
    if (MD.Framework) {
      Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
      return;
    }
  } else if (MD.Explicit) {
    Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
    return;
  }

  if (ActiveModule) {
    // Note that we have an inferred submodule.
    ActiveModule->InferSubmodules = true;
    ActiveModule->InferredSubmoduleLoc = StarLoc;
    ActiveModule->InferExplicitSubmodules = MD.Explicit;
  } else {
    // We'll be inferring framework modules for this directory.
    auto &InfDir = Map.InferredDirectories[Directory];
    InfDir.InferModules = true;
    InfDir.Attrs = MD.Attrs;
    InfDir.ModuleMapFID = ModuleMapFID;
    // FIXME: Handle the 'framework' keyword.
  }

  for (const modulemap::Decl &Decl : MD.Decls) {
    std::visit(
        llvm::makeVisitor(
            [&](const auto &Other) {
              Diags.Report(Other.Location,
                           diag::err_mmap_expected_inferred_member)
                  << (ActiveModule != nullptr);
            },
            [&](const modulemap::ExcludeDecl &ED) {
              // Only inferred frameworks can have exclude decls
              if (ActiveModule) {
                Diags.Report(ED.Location,
                             diag::err_mmap_expected_inferred_member)
                    << (ActiveModule != nullptr);
                HadError = true;
                return;
              }
              Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
                  ED.Module);
            },
            [&](const modulemap::ExportDecl &ED) {
              // Only inferred submodules can have export decls
              if (!ActiveModule) {
                Diags.Report(ED.Location,
                             diag::err_mmap_expected_inferred_member)
                    << (ActiveModule != nullptr);
                HadError = true;
                return;
              }

              if (ED.Wildcard && ED.Id.size() == 0)
                ActiveModule->InferExportWildcard = true;
              else
                Diags.Report(ED.Id.front().second,
                             diag::err_mmap_expected_export_wildcard);
            }),
        Decl);
  }
}

bool ModuleMapLoader::loadModuleDecl(const modulemap::ModuleDecl &MD) {
  handleModuleDecl(MD);
  return HadError;
}

bool ModuleMapLoader::loadExternModuleDecl(
    const modulemap::ExternModuleDecl &EMD) {
  handleExternModuleDecl(EMD);
  return HadError;
}

bool ModuleMapLoader::parseAndLoadModuleMapFile(
    const modulemap::ModuleMapFile &MMF) {
  for (const auto &Decl : MMF.Decls) {
    std::visit(
        llvm::makeVisitor(
            [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
            [&](const modulemap::ExternModuleDecl &EMD) {
              handleExternModuleDecl(EMD);
            }),
        Decl);
  }
  return HadError;
}

Module *ModuleMap::findOrLoadModule(StringRef Name) {
  llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
  if (Known != Modules.end())
    return Known->getValue();

  auto ParsedMod = ParsedModules.find(Name);
  if (ParsedMod == ParsedModules.end())
    return nullptr;

  Diags.Report(diag::remark_mmap_load_module) << Name;

  for (const auto &ModuleDecl : ParsedMod->second) {
    const modulemap::ModuleMapFile &MMF = *ModuleDecl.first;
    ModuleMapLoader Loader(SourceMgr, Diags, const_cast<ModuleMap &>(*this),
                           MMF.ID, *MMF.Dir, MMF.IsSystem,
                           MMF.ImplicitlyDiscovered);
    if (Loader.loadModuleDecl(*ModuleDecl.second))
      return nullptr;
  }

  return findModule(Name);
}

bool ModuleMap::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,
                                          bool ImplicitlyDiscovered,
                                          DirectoryEntryRef Dir, FileID ID,
                                          unsigned *Offset,
                                          SourceLocation ExternModuleLoc) {
  assert(Target && "Missing target information");
  llvm::DenseMap<const FileEntry *, bool>::iterator Known =
      LoadedModuleMap.find(File);
  if (Known != LoadedModuleMap.end())
    return Known->second;

  // If the module map file wasn't already entered, do so now.
  if (ID.isInvalid()) {
    // TODO: The way we compute affecting module maps requires this to be a
    //       local FileID. This should be changed to reuse loaded FileIDs when
    //       available, and change the way that affecting module maps are
    //       computed to not require this.
    FileID &LocalFID = ModuleMapLocalFileID[File];
    if (LocalFID.isInvalid()) {
      auto FileCharacter =
          IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
      LocalFID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
    }
    ID = LocalFID;
  }

  assert(Target && "Missing target information");
  std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
  if (!Buffer)
    return LoadedModuleMap[File] = true;
  assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
         "invalid buffer offset");

  std::optional<modulemap::ModuleMapFile> MMF = modulemap::parseModuleMap(
      ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
  bool Result = false;
  if (MMF) {
    Diags.Report(diag::remark_mmap_load) << File.getName();
    ModuleMapLoader Loader(SourceMgr, Diags, *this, ID, Dir, IsSystem,
                           ImplicitlyDiscovered);
    Result = Loader.parseAndLoadModuleMapFile(*MMF);

    // Also record that this was parsed if it wasn't previously. This is used
    // for diagnostics.
    llvm::DenseMap<const FileEntry *,
                   const modulemap::ModuleMapFile *>::iterator PKnown =
        ParsedModuleMap.find(File);
    if (PKnown == ParsedModuleMap.end()) {
      ParsedModuleMaps.push_back(
          std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
      ParsedModuleMap[File] = &*ParsedModuleMaps.back();
    }
  }
  LoadedModuleMap[File] = Result;

  // Notify callbacks that we observed it.
  // FIXME: We should only report module maps that were actually used.
  for (const auto &Cb : Callbacks)
    Cb->moduleMapFileRead(MMF ? MMF->Start : SourceLocation(), File, IsSystem);

  return Result;
}
