//===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements the DirectoryLookup and HeaderSearch interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/HeaderSearch.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <string>
#include <system_error>
#include <utility>

using namespace clang;

#define DEBUG_TYPE "file-search"

ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes.");
ALWAYS_ENABLED_STATISTIC(
    NumMultiIncludeFileOptzn,
    "Number of #includes skipped due to the multi-include optimization.");
ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups.");
ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups,
                         "Number of subframework lookups.");

const IdentifierInfo *
HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
  if (LazyControllingMacro.isID()) {
    if (!External)
      return nullptr;

    LazyControllingMacro =
        External->GetIdentifier(LazyControllingMacro.getID());
    return LazyControllingMacro.getPtr();
  }

  IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr();
  if (ControllingMacro && ControllingMacro->isOutOfDate()) {
    assert(External && "We must have an external source if we have a "
                       "controlling macro that is out of date.");
    External->updateOutOfDateIdentifier(*ControllingMacro);
  }
  return ControllingMacro;
}

ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;

HeaderSearch::HeaderSearch(const HeaderSearchOptions &HSOpts,
                           SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                           const LangOptions &LangOpts,
                           const TargetInfo *Target)
    : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
      FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}

void HeaderSearch::PrintStats() {
  llvm::errs() << "\n*** HeaderSearch Stats:\n"
               << FileInfo.size() << " files tracked.\n";
  unsigned NumOnceOnlyFiles = 0;
  for (const auto &[FE, HFI] : FileInfo)
    NumOnceOnlyFiles += (HFI.isPragmaOnce || HFI.isImport);
  llvm::errs() << "  " << NumOnceOnlyFiles << " #import/#pragma once files.\n";

  llvm::errs() << "  " << NumIncluded << " #include/#include_next/#import.\n"
               << "    " << NumMultiIncludeFileOptzn
               << " #includes skipped due to the multi-include optimization.\n";

  llvm::errs() << NumFrameworkLookups << " framework lookups.\n"
               << NumSubFrameworkLookups << " subframework lookups.\n";
}

void HeaderSearch::SetSearchPaths(
    std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx,
    unsigned int systemDirIdx,
    llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
  assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
         "Directory indices are unordered");
  SearchDirs = std::move(dirs);
  SearchDirsUsage.assign(SearchDirs.size(), false);
  AngledDirIdx = angledDirIdx;
  SystemDirIdx = systemDirIdx;
  SearchDirToHSEntry = std::move(searchDirToHSEntry);
  //LookupFileCache.clear();
  indexInitialHeaderMaps();
}

void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
  unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
  SearchDirs.insert(SearchDirs.begin() + idx, dir);
  SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);
  if (!isAngled)
    AngledDirIdx++;
  SystemDirIdx++;
}

std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
  std::vector<bool> UserEntryUsage(HSOpts.UserEntries.size());
  for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
    // Check whether this DirectoryLookup has been successfully used.
    if (SearchDirsUsage[I]) {
      auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
      // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
      if (UserEntryIdxIt != SearchDirToHSEntry.end())
        UserEntryUsage[UserEntryIdxIt->second] = true;
    }
  }
  return UserEntryUsage;
}

std::vector<bool> HeaderSearch::collectVFSUsageAndClear() const {
  std::vector<bool> VFSUsage;
  if (!getHeaderSearchOpts().ModulesIncludeVFSUsage)
    return VFSUsage;

  llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
  // TODO: This only works if the `RedirectingFileSystem`s were all created by
  //       `createVFSFromOverlayFiles`. But at least exclude the ones with null
  //       OverlayFileDir.
  RootFS.visit([&](llvm::vfs::FileSystem &FS) {
    if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {
      // Skip a `RedirectingFileSystem` with null OverlayFileDir which indicates
      // that they aren't created by createVFSFromOverlayFiles from the overlays
      // in HeaderSearchOption::VFSOverlayFiles.
      if (!RFS->getOverlayFileDir().empty()) {
        VFSUsage.push_back(RFS->hasBeenUsed());
        RFS->clearHasBeenUsed();
      }
    }
  });
  assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() &&
         "A different number of RedirectingFileSystem's were present than "
         "-ivfsoverlay options passed to Clang!");
  // VFS visit order is the opposite of VFSOverlayFiles order.
  std::reverse(VFSUsage.begin(), VFSUsage.end());
  return VFSUsage;
}

/// CreateHeaderMap - This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *HeaderSearch::CreateHeaderMap(FileEntryRef FE) {
  // We expect the number of headermaps to be small, and almost always empty.
  // If it ever grows, use of a linear search should be re-evaluated.
  if (!HeaderMaps.empty()) {
    for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
      // Pointer equality comparison of FileEntries works because they are
      // already uniqued by inode.
      if (HeaderMaps[i].first == FE)
        return HeaderMaps[i].second.get();
  }

  if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) {
    HeaderMaps.emplace_back(FE, std::move(HM));
    return HeaderMaps.back().second.get();
  }

  return nullptr;
}

/// Get filenames for all registered header maps.
void HeaderSearch::getHeaderMapFileNames(
    SmallVectorImpl<std::string> &Names) const {
  for (auto &HM : HeaderMaps)
    Names.push_back(std::string(HM.first.getName()));
}

ModuleFileName HeaderSearch::getCachedModuleFileName(Module *Module) {
  OptionalFileEntryRef ModuleMap =
      getModuleMap().getModuleMapFileForUniquing(Module);
  // The ModuleMap maybe a nullptr, when we load a cached C++ module without
  // *.modulemap file. In this case, just return an empty string.
  if (!ModuleMap)
    return {};
  return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested());
}

ModuleFileName HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
                                                       bool FileMapOnly) {
  // First check the module name to pcm file map.
  auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));
  if (i != HSOpts.PrebuiltModuleFiles.end())
    return ModuleFileName::makeExplicit(i->second);

  if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())
    return {};

  // Then go through each prebuilt module directory and try to find the pcm
  // file.
  for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
    SmallString<256> Result(Dir);
    FileMgr.makeAbsolutePath(Result);
    if (ModuleName.contains(':'))
      // The separator of C++20 modules partitions (':') is not good for file
      // systems, here clang and gcc choose '-' by default since it is not a
      // valid character of C++ indentifiers. So we could avoid conflicts.
      llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +
                                          ModuleName.split(':').second +
                                          ".pcm");
    else
      llvm::sys::path::append(Result, ModuleName + ".pcm");
    if (getFileMgr().getOptionalFileRef(Result))
      return ModuleFileName::makeExplicit(Result);
  }

  return {};
}

ModuleFileName HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {
  OptionalFileEntryRef ModuleMap =
      getModuleMap().getModuleMapFileForUniquing(Module);
  StringRef ModuleName = Module->Name;
  StringRef ModuleMapPath = ModuleMap->getName();
  for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
    SmallString<256> CachePath(Dir);
    FileMgr.makeAbsolutePath(CachePath);
    ModuleFileName FileName =
        getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
    if (!FileName.empty() && getFileMgr().getOptionalFileRef(FileName))
      return ModuleFileName::makeExplicit(FileName);
  }
  return {};
}

ModuleFileName HeaderSearch::getCachedModuleFileName(StringRef ModuleName,
                                                     StringRef ModuleMapPath) {
  return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
                                     getNormalizedModuleCachePath());
}

ModuleFileName HeaderSearch::getCachedModuleFileNameImpl(
    StringRef ModuleName, StringRef ModuleMapPath, StringRef CachePath) {
  // If we don't have a module cache path or aren't supposed to use one, we
  // can't do anything.
  if (CachePath.empty())
    return {};

  // Note: This re-implements part of createSpecificModuleCachePathImpl() in
  // order to be able to correctly construct ModuleFileName.

  SmallString<256> Result(CachePath);
  unsigned SuffixBegin = Result.size();

  if (HSOpts.DisableModuleHash) {
    llvm::sys::path::append(Result, ModuleName + ".pcm");
  } else {
    llvm::sys::path::append(Result, ContextHash);

    // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should
    // ideally be globally unique to this particular module. Name collisions
    // in the hash are safe (because any translation unit can only import one
    // module with each name), but result in a loss of caching.
    //
    // To avoid false-negatives, we form as canonical a path as we can, and map
    // to lower-case in case we're on a case-insensitive file system.
    SmallString<128> CanonicalPath(ModuleMapPath);
    if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
      return {};

    auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());

    SmallString<128> HashStr;
    llvm::APInt(64, Hash).toStringUnsigned(HashStr, /*Radix*/36);
    llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");
  }
  return ModuleFileName::makeImplicit(Result, Result.size() - SuffixBegin);
}

Module *HeaderSearch::lookupModule(StringRef ModuleName,
                                   SourceLocation ImportLoc, bool AllowSearch,
                                   bool AllowExtraModuleMapSearch) {
  // Look in the module map to determine if there is a module by this name.
  Module *Module = ModMap.findOrLoadModule(ModuleName);
  if (Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
    return Module;

  StringRef SearchName = ModuleName;
  Module = lookupModule(ModuleName, SearchName, ImportLoc,
                        AllowExtraModuleMapSearch);

  // The facility for "private modules" -- adjacent, optional module maps named
  // module.private.modulemap that are supposed to define private submodules --
  // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.
  //
  // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate
  // should also rename to Foo_Private. Representing private as submodules
  // could force building unwanted dependencies into the parent module and cause
  // dependency cycles.
  if (!Module && SearchName.consume_back("_Private"))
    Module = lookupModule(ModuleName, SearchName, ImportLoc,
                          AllowExtraModuleMapSearch);
  if (!Module && SearchName.consume_back("Private"))
    Module = lookupModule(ModuleName, SearchName, ImportLoc,
                          AllowExtraModuleMapSearch);
  return Module;
}

Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,
                                   SourceLocation ImportLoc,
                                   bool AllowExtraModuleMapSearch) {
  Module *Module = nullptr;

  // Look through the various header search paths to load any available module
  // maps, searching for a module map that describes this module.
  for (DirectoryLookup &Dir : search_dir_range()) {
    if (Dir.isFramework()) {
      // Search for or infer a module map for a framework. Here we use
      // SearchName rather than ModuleName, to permit finding private modules
      // named FooPrivate in buggy frameworks named Foo.
      SmallString<128> FrameworkDirName;
      FrameworkDirName += Dir.getFrameworkDirRef()->getName();
      llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
      if (auto FrameworkDir =
              FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
        bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;
        Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem,
                                     /*ImplicitlyDiscovered=*/true);
        if (Module)
          break;
      }
    }

    // FIXME: Figure out how header maps and module maps will work together.

    // Only deal with normal search directories.
    if (!Dir.isNormalDir())
      continue;

    bool IsSystem = Dir.isSystemHeaderDirectory();
    // Only returns std::nullopt if not a normal directory, which we just
    // checked
    DirectoryEntryRef NormalDir = *Dir.getDirRef();
    // Search for a module map file in this directory.
    if (parseModuleMapFile(NormalDir, IsSystem, /*ImplicitlyDiscovered=*/true,
                           /*IsFramework*/ false) == MMR_NewlyProcessed) {
      // We just parsed a module map file; check whether the module can be
      // loaded now.
      Module = ModMap.findOrLoadModule(ModuleName);
      if (Module)
        break;
    }

    // Search for a module map in a subdirectory with the same name as the
    // module.
    SmallString<128> NestedModuleMapDirName;
    NestedModuleMapDirName = Dir.getDirRef()->getName();
    llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
    if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,
                           /*ImplicitlyDiscovered=*/true,
                           /*IsFramework*/ false) == MMR_NewlyProcessed) {
      // If we just parsed a module map file, look for the module again.
      Module = ModMap.findOrLoadModule(ModuleName);
      if (Module)
        break;
    }

    if (HSOpts.AllowModuleMapSubdirectorySearch) {
      // If we've already performed the exhaustive search for module maps in
      // this search directory, don't do it again.
      if (Dir.haveSearchedAllModuleMaps())
        continue;

      // Load all module maps in the immediate subdirectories of this search
      // directory if ModuleName was from @import.
      if (AllowExtraModuleMapSearch)
        loadSubdirectoryModuleMaps(Dir);

      // Look again for the module.
      Module = ModMap.findOrLoadModule(ModuleName);
      if (Module)
        break;
    }
  }

  return Module;
}

void HeaderSearch::indexInitialHeaderMaps() {
  llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());

  // Iterate over all filename keys and associate them with the index i.
  for (unsigned i = 0; i != SearchDirs.size(); ++i) {
    auto &Dir = SearchDirs[i];

    // We're concerned with only the initial contiguous run of header
    // maps within SearchDirs, which can be 99% of SearchDirs when
    // SearchDirs.size() is ~10000.
    if (!Dir.isHeaderMap()) {
      SearchDirHeaderMapIndex = std::move(Index);
      FirstNonHeaderMapSearchDirIdx = i;
      break;
    }

    // Give earlier keys precedence over identical later keys.
    auto Callback = [&](StringRef Filename) {
      Index.try_emplace(Filename.lower(), i);
    };
    Dir.getHeaderMap()->forEachKey(Callback);
  }
}

//===----------------------------------------------------------------------===//
// File lookup within a DirectoryLookup scope
//===----------------------------------------------------------------------===//

/// getName - Return the directory or filename corresponding to this lookup
/// object.
StringRef DirectoryLookup::getName() const {
  if (isNormalDir())
    return getDirRef()->getName();
  if (isFramework())
    return getFrameworkDirRef()->getName();
  assert(isHeaderMap() && "Unknown DirectoryLookup");
  return getHeaderMap()->getFileName();
}

OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule(
    StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,
    bool IsSystemHeaderDir, Module *RequestingModule,
    ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/,
    bool CacheFailures /*=true*/) {
  // If we have a module map that might map this header, load it and
  // check whether we'll have a suggestion for a module.
  auto File = getFileMgr().getFileRef(FileName, OpenFile, CacheFailures);
  if (!File) {
    // For rare, surprising errors (e.g. "out of file handles"), diag the EC
    // message.
    std::error_code EC = llvm::errorToErrorCode(File.takeError());
    if (EC != llvm::errc::no_such_file_or_directory &&
        EC != llvm::errc::invalid_argument &&
        EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
      Diags.Report(IncludeLoc, diag::err_cannot_open_file)
          << FileName << EC.message();
    }
    return std::nullopt;
  }

  // If there is a module that corresponds to this header, suggest it.
  if (!findUsableModuleForHeader(
          *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,
          SuggestedModule, IsSystemHeaderDir))
    return std::nullopt;

  return *File;
}

/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
OptionalFileEntryRef DirectoryLookup::LookupFile(
    StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,
    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
    bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
    bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName,
    bool OpenFile) const {
  InUserSpecifiedSystemFramework = false;
  IsInHeaderMap = false;
  MappedName.clear();

  SmallString<1024> TmpDir;
  if (isNormalDir()) {
    // Concatenate the requested file onto the directory.
    TmpDir = getDirRef()->getName();
    llvm::sys::path::append(TmpDir, Filename);
    if (SearchPath) {
      StringRef SearchPathRef(getDirRef()->getName());
      SearchPath->clear();
      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
    }
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }

    return HS.getFileAndSuggestModule(
        TmpDir, IncludeLoc, getDir(), isSystemHeaderDirectory(),
        RequestingModule, SuggestedModule, OpenFile);
  }

  if (isFramework())
    return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
                             RequestingModule, SuggestedModule,
                             InUserSpecifiedSystemFramework, IsFrameworkFound);

  assert(isHeaderMap() && "Unknown directory lookup");
  const HeaderMap *HM = getHeaderMap();
  SmallString<1024> Path;
  StringRef Dest = HM->lookupFilename(Filename, Path);
  if (Dest.empty())
    return std::nullopt;

  IsInHeaderMap = true;

  auto FixupSearchPathAndFindUsableModule =
      [&](FileEntryRef File) -> OptionalFileEntryRef {
    if (SearchPath) {
      StringRef SearchPathRef(getName());
      SearchPath->clear();
      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
    }
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
    if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(),
                                      RequestingModule, SuggestedModule,
                                      isSystemHeaderDirectory())) {
      return std::nullopt;
    }
    return File;
  };

  // Check if the headermap maps the filename to a framework include
  // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
  // framework include.
  if (llvm::sys::path::is_relative(Dest)) {
    MappedName.append(Dest.begin(), Dest.end());
    Filename = StringRef(MappedName.begin(), MappedName.size());
    Dest = HM->lookupFilename(Filename, Path);
  }

  if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) {
    return FixupSearchPathAndFindUsableModule(*Res);
  }

  // Header maps need to be marked as used whenever the filename matches.
  // The case where the target file **exists** is handled by callee of this
  // function as part of the regular logic that applies to include search paths.
  // The case where the target file **does not exist** is handled here:
  HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);
  return std::nullopt;
}

/// Given a framework directory, find the top-most framework directory.
///
/// \param FileMgr The file manager to use for directory lookups.
/// \param DirName The name of the framework directory.
/// \param SubmodulePath Will be populated with the submodule path from the
/// returned top-level module to the originally named framework.
static OptionalDirectoryEntryRef
getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
                   SmallVectorImpl<std::string> &SubmodulePath) {
  assert(llvm::sys::path::extension(DirName) == ".framework" &&
         "Not a framework directory");

  // Note: as an egregious but useful hack we use the real path here, because
  // frameworks moving between top-level frameworks to embedded frameworks tend
  // to be symlinked, and we base the logical structure of modules on the
  // physical layout. In particular, we need to deal with crazy includes like
  //
  //   #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>
  //
  // where 'Bar' used to be embedded in 'Foo', is now a top-level framework
  // which one should access with, e.g.,
  //
  //   #include <Bar/Wibble.h>
  //
  // Similar issues occur when a top-level framework has moved into an
  // embedded framework.
  auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);

  if (TopFrameworkDir)
    DirName = FileMgr.getCanonicalName(*TopFrameworkDir);
  do {
    // Get the parent directory name.
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.empty())
      break;

    // Determine whether this directory exists.
    auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
    if (!Dir)
      break;

    // If this is a framework directory, then we're a subframework of this
    // framework.
    if (llvm::sys::path::extension(DirName) == ".framework") {
      SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
      TopFrameworkDir = *Dir;
    }
  } while (true);

  return TopFrameworkDir;
}

static bool needModuleLookup(Module *RequestingModule,
                             bool HasSuggestedModule) {
  return HasSuggestedModule ||
         (RequestingModule && RequestingModule->NoUndeclaredIncludes);
}

/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup(
    StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
    SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
    ModuleMap::KnownHeader *SuggestedModule,
    bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
  FileManager &FileMgr = HS.getFileMgr();

  // Framework names must have a '/' in the filename.
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos)
    return std::nullopt;

  // Find out if this is the home for the specified framework, by checking
  // HeaderSearch.  Possible answers are yes/no and unknown.
  FrameworkCacheEntry &CacheEntry =
    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));

  // If it is known and in some other directory, fail.
  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef())
    return std::nullopt;

  // Otherwise, construct the path to this framework dir.

  // FrameworkName = "/System/Library/Frameworks/"
  SmallString<1024> FrameworkName;
  FrameworkName += getFrameworkDirRef()->getName();
  if (FrameworkName.empty() || FrameworkName.back() != '/')
    FrameworkName.push_back('/');

  // FrameworkName = "/System/Library/Frameworks/Cocoa"
  StringRef ModuleName(Filename.begin(), SlashPos);
  FrameworkName += ModuleName;

  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"
  FrameworkName += ".framework/";

  // If the cache entry was unresolved, populate it now.
  if (!CacheEntry.Directory) {
    ++NumFrameworkLookups;

    // If the framework dir doesn't exist, we fail.
    auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
    if (!Dir)
      return std::nullopt;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheEntry.Directory = getFrameworkDirRef();

    // If this is a user search directory, check if the framework has been
    // user-specified as a system framework.
    if (getDirCharacteristic() == SrcMgr::C_User) {
      SmallString<1024> SystemFrameworkMarker(FrameworkName);
      SystemFrameworkMarker += ".system_framework";
      if (FileMgr.getOptionalFileRef(SystemFrameworkMarker))
        CacheEntry.IsUserSpecifiedSystemFramework = true;
    }
  }

  // Set out flags.
  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
  IsFrameworkFound = CacheEntry.Directory.has_value();

  if (RelativePath) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
  unsigned OrigSize = FrameworkName.size();

  FrameworkName += "Headers/";

  if (SearchPath) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
  }

  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());

  auto File =
      FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);
  if (!File) {
    // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
    const char *Private = "Private";
    FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
                         Private+strlen(Private));
    if (SearchPath)
      SearchPath->insert(SearchPath->begin()+OrigSize, Private,
                         Private+strlen(Private));

    File = FileMgr.getOptionalFileRef(FrameworkName,
                                      /*OpenFile=*/!SuggestedModule);
  }

  // If we found the header and are allowed to suggest a module, do so now.
  if (File && needModuleLookup(RequestingModule, SuggestedModule)) {
    // Find the framework in which this header occurs.
    StringRef FrameworkPath = File->getDir().getName();
    bool FoundFramework = false;
    do {
      // Determine whether this directory exists.
      auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkPath);
      if (!Dir)
        break;

      // If this is a framework directory, then we're a subframework of this
      // framework.
      if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
        FoundFramework = true;
        break;
      }

      // Get the parent directory name.
      FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
      if (FrameworkPath.empty())
        break;
    } while (true);

    bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
    if (FoundFramework) {
      if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath,
                                                 RequestingModule,
                                                 SuggestedModule, IsSystem))
        return std::nullopt;
    } else {
      if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule,
                                        SuggestedModule, IsSystem))
        return std::nullopt;
    }
  }
  if (File)
    return *File;
  return std::nullopt;
}

void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
                                      ConstSearchDirIterator HitIt,
                                      SourceLocation Loc) {
  CacheLookup.HitIt = HitIt;
  noteLookupUsage(HitIt.Idx, Loc);
}

void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
  SearchDirsUsage[HitIdx] = true;

  auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
  if (UserEntryIdxIt != SearchDirToHSEntry.end())
    Diags.Report(Loc, diag::remark_pp_search_path_usage)
        << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
}

void HeaderSearch::setTarget(const TargetInfo &Target) {
  ModMap.setTarget(Target);
}

//===----------------------------------------------------------------------===//
// Header File Location.
//===----------------------------------------------------------------------===//

/// Return true with a diagnostic if the file that MSVC would have found
/// fails to match the one that Clang would have found with MSVC header search
/// disabled.
static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,
                                  OptionalFileEntryRef MSFE,
                                  const FileEntry *FE,
                                  SourceLocation IncludeLoc) {
  if (MSFE && FE != *MSFE) {
    Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();
    return true;
  }
  return false;
}

static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
  assert(!Str.empty());
  char *CopyStr = Alloc.Allocate<char>(Str.size()+1);
  std::copy(Str.begin(), Str.end(), CopyStr);
  CopyStr[Str.size()] = '\0';
  return CopyStr;
}

static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,
                                 SmallVectorImpl<char> &FrameworkName,
                                 SmallVectorImpl<char> &IncludeSpelling) {
  using namespace llvm::sys;
  path::const_iterator I = path::begin(Path);
  path::const_iterator E = path::end(Path);
  IsPrivateHeader = false;

  // Detect different types of framework style paths:
  //
  //   ...Foo.framework/{Headers,PrivateHeaders}
  //   ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}
  //   ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}
  //   ...<other variations with 'Versions' like in the above path>
  //
  // and some other variations among these lines.
  int FoundComp = 0;
  while (I != E) {
    if (*I == "Headers") {
      ++FoundComp;
    } else if (*I == "PrivateHeaders") {
      ++FoundComp;
      IsPrivateHeader = true;
    } else if (I->ends_with(".framework")) {
      StringRef Name = I->drop_back(10); // Drop .framework
      // Need to reset the strings and counter to support nested frameworks.
      FrameworkName.clear();
      FrameworkName.append(Name.begin(), Name.end());
      IncludeSpelling.clear();
      IncludeSpelling.append(Name.begin(), Name.end());
      FoundComp = 1;
    } else if (FoundComp >= 2) {
      IncludeSpelling.push_back('/');
      IncludeSpelling.append(I->begin(), I->end());
    }
    ++I;
  }

  return !FrameworkName.empty() && FoundComp >= 2;
}

static void
diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
                         StringRef Includer, StringRef IncludeFilename,
                         FileEntryRef IncludeFE, bool isAngled = false,
                         bool FoundByHeaderMap = false) {
  bool IsIncluderPrivateHeader = false;
  SmallString<128> FromFramework, ToFramework;
  SmallString<128> FromIncludeSpelling, ToIncludeSpelling;
  if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework,
                            FromIncludeSpelling))
    return;
  bool IsIncludeePrivateHeader = false;
  bool IsIncludeeInFramework =
      isFrameworkStylePath(IncludeFE.getName(), IsIncludeePrivateHeader,
                           ToFramework, ToIncludeSpelling);

  if (!isAngled && !FoundByHeaderMap) {
    SmallString<128> NewInclude("<");
    if (IsIncludeeInFramework) {
      NewInclude += ToIncludeSpelling;
      NewInclude += ">";
    } else {
      NewInclude += IncludeFilename;
      NewInclude += ">";
    }
    Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
        << IncludeFilename
        << FixItHint::CreateReplacement(IncludeLoc, NewInclude);
  }

  // Headers in Foo.framework/Headers should not include headers
  // from Foo.framework/PrivateHeaders, since this violates public/private
  // API boundaries and can cause modular dependency cycles.
  if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
      IsIncludeePrivateHeader && FromFramework == ToFramework)
    Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)
        << IncludeFilename;
}

void HeaderSearch::diagnoseHeaderShadowing(
    StringRef Filename, OptionalFileEntryRef FE, bool &DiagnosedShadowing,
    SourceLocation IncludeLoc, ConstSearchDirIterator FromDir,
    ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
    bool isAngled, int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {

  if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc) ||
      DiagnosedShadowing)
    return;
  // Ignore diagnostics from system headers.
  if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
    return;

  DiagnosedShadowing = true;

  // Indicates that file is first found in the includer's directory
  if (!MainLoopIt) {
    for (size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
      const auto &IncluderAndDir = Includers[i];
      SmallString<1024> TmpDir = IncluderAndDir.second.getName();
      llvm::sys::path::append(TmpDir, Filename);
      if (auto File = getFileMgr().getOptionalFileRef(TmpDir, false, false)) {
        if (&File->getFileEntry() == *FE)
          continue;
        Diags.Report(IncludeLoc, diag::warn_header_shadowing)
            << Filename << (*FE).getDir().getName()
            << IncluderAndDir.second.getName();
        return;
      }
    }
  }

  // Continue searching in the regular search paths
  ConstSearchDirIterator It =
      isAngled ? angled_dir_begin() : search_dir_begin();
  if (MainLoopIt) {
    It = std::next(MainLoopIt);
  } else if (FromDir) {
    It = FromDir;
  }
  for (; It != search_dir_end(); ++It) {
    // Suppress check for system headers, as duplicates are often intentional.
    if (It->getDirCharacteristic() != SrcMgr::C_User)
      continue;
    SmallString<1024> TmpPath = It->getName();
    llvm::sys::path::append(TmpPath, Filename);
    if (auto File = getFileMgr().getOptionalFileRef(TmpPath, false, false)) {
      if (&File->getFileEntry() == *FE)
        continue;
      Diags.Report(IncludeLoc, diag::warn_header_shadowing)
          << Filename << (*FE).getDir().getName() << It->getName();
      return;
    }
  }
}

/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
/// return null on failure.  isAngled indicates whether the file reference is
/// for system \#include's or not (i.e. using <> instead of ""). Includers, if
/// non-empty, indicates where the \#including file(s) are, in case a relative
/// search is needed. Microsoft mode will pass all \#including files.
OptionalFileEntryRef HeaderSearch::LookupFile(
    StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
    ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
    ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
    bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
    bool BuildSystemModule, bool OpenFile, bool CacheFailures) {
  ConstSearchDirIterator CurDirLocal = nullptr;
  ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;

  if (IsMapped)
    *IsMapped = false;

  if (IsFrameworkFound)
    *IsFrameworkFound = false;

  if (SuggestedModule)
    *SuggestedModule = ModuleMap::KnownHeader();

  // If 'Filename' is absolute, check to see if it exists and no searching.
  if (llvm::sys::path::is_absolute(Filename)) {
    CurDir = nullptr;

    // If this was an #include_next "/absolute/file", fail.
    if (FromDir)
      return std::nullopt;

    if (SearchPath)
      SearchPath->clear();
    if (RelativePath) {
      RelativePath->clear();
      RelativePath->append(Filename.begin(), Filename.end());
    }
    // Otherwise, just return the file.
    return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,
                                   /*IsSystemHeaderDir*/ false,
                                   RequestingModule, SuggestedModule, OpenFile,
                                   CacheFailures);
  }

  // This is the header that MSVC's header search would have found.
  ModuleMap::KnownHeader MSSuggestedModule;
  OptionalFileEntryRef MSFE;
  bool DiagnosedShadowing = false;

  // Check to see if the file is in the #includer's directory. This cannot be
  // based on CurDir, because each includer could be a #include of a
  // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h"
  // should resolve to "whatever/foo/baz.h". This search is not done for <>
  // headers.
  if (!Includers.empty() && !isAngled) {
    SmallString<1024> TmpDir;
    bool First = true;
    for (const auto &IncluderAndDir : Includers) {
      OptionalFileEntryRef Includer = IncluderAndDir.first;

      // Concatenate the requested file onto the directory.
      TmpDir = IncluderAndDir.second.getName();
      llvm::sys::path::append(TmpDir, Filename);

      // FIXME: We don't cache the result of getFileInfo across the call to
      // getFileAndSuggestModule, because it's a reference to an element of
      // a container that could be reallocated across this call.
      //
      // If we have no includer, that means we're processing a #include
      // from a module build. We should treat this as a system header if we're
      // building a [system] module.
      bool IncluderIsSystemHeader = [&]() {
        if (!Includer)
          return BuildSystemModule;
        const HeaderFileInfo *HFI = getExistingFileInfo(*Includer);
        assert(HFI && "includer without file info");
        return HFI->DirInfo != SrcMgr::C_User;
      }();
      if (OptionalFileEntryRef FE = getFileAndSuggestModule(
              TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
              RequestingModule, SuggestedModule)) {
        diagnoseHeaderShadowing(Filename, FE, DiagnosedShadowing, IncludeLoc,
                                FromDir, Includers, isAngled,
                                &IncluderAndDir - Includers.begin(), nullptr);
        if (!Includer) {
          assert(First && "only first includer can have no file");
          return FE;
        }

        // Leave CurDir unset.
        // This file is a system header or C++ unfriendly if the old file is.
        //
        // Note that we only use one of FromHFI/ToHFI at once, due to potential
        // reallocation of the underlying vector potentially making the first
        // reference binding dangling.
        const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer);
        assert(FromHFI && "includer without file info");
        unsigned DirInfo = FromHFI->DirInfo;

        HeaderFileInfo &ToHFI = getFileInfo(*FE);
        ToHFI.DirInfo = DirInfo;

        if (SearchPath) {
          StringRef SearchPathRef(IncluderAndDir.second.getName());
          SearchPath->clear();
          SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
        }
        if (RelativePath) {
          RelativePath->clear();
          RelativePath->append(Filename.begin(), Filename.end());
        }
        if (First) {
          diagnoseFrameworkInclude(Diags, IncludeLoc,
                                   IncluderAndDir.second.getName(), Filename,
                                   *FE);
          return FE;
        }

        // Otherwise, we found the path via MSVC header search rules.  If
        // -Wmsvc-include is enabled, we have to keep searching to see if we
        // would've found this header in -I or -isystem directories.
        if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
          return FE;
        } else {
          MSFE = FE;
          if (SuggestedModule) {
            MSSuggestedModule = *SuggestedModule;
            *SuggestedModule = ModuleMap::KnownHeader();
          }
          break;
        }
      }
      First = false;
    }
  }

  CurDir = nullptr;

  // If this is a system #include, ignore the user #include locs.
  ConstSearchDirIterator It =
      isAngled ? angled_dir_begin() : search_dir_begin();

  // If this is a #include_next request, start searching after the directory the
  // file was found in.
  if (FromDir)
    It = FromDir;

  // Cache all of the lookups performed by this method.  Many headers are
  // multiply included, and the "pragma once" optimization prevents them from
  // being relex/pp'd, but they would still have to search through a
  // (potentially huge) series of SearchDirs to find it.
  LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];

  ConstSearchDirIterator NextIt = std::next(It);

  if (!SkipCache) {
    if (CacheLookup.StartIt == NextIt &&
        CacheLookup.RequestingModule == RequestingModule) {
      // HIT: Skip querying potentially lots of directories for this lookup.
      if (CacheLookup.HitIt)
        It = CacheLookup.HitIt;
      if (CacheLookup.MappedName) {
        Filename = CacheLookup.MappedName;
        if (IsMapped)
          *IsMapped = true;
      }
    } else {
      // MISS: This is the first query, or the previous query didn't match
      // our search start.  We will fill in our found location below, so prime
      // the start point value.
      CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);

      if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {
        // Handle cold misses of user includes in the presence of many header
        // maps.  We avoid searching perhaps thousands of header maps by
        // jumping directly to the correct one or jumping beyond all of them.
        auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
        if (Iter == SearchDirHeaderMapIndex.end())
          // Not in index => Skip to first SearchDir after initial header maps
          It = search_dir_nth(FirstNonHeaderMapSearchDirIdx);
        else
          // In index => Start with a specific header map
          It = search_dir_nth(Iter->second);
      }
    }
  } else {
    CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);
  }

  SmallString<64> MappedName;

  // Check each directory in sequence to see if it contains this file.
  for (; It != search_dir_end(); ++It) {
    bool InUserSpecifiedSystemFramework = false;
    bool IsInHeaderMap = false;
    bool IsFrameworkFoundInDir = false;
    OptionalFileEntryRef File = It->LookupFile(
        Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
        SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
        IsInHeaderMap, MappedName, OpenFile);
    if (!MappedName.empty()) {
      assert(IsInHeaderMap && "MappedName should come from a header map");
      CacheLookup.MappedName =
          copyString(MappedName, LookupFileCache.getAllocator());
    }
    if (IsMapped)
      // A filename is mapped when a header map remapped it to a relative path
      // used in subsequent header search or to an absolute path pointing to an
      // existing file.
      *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));
    if (IsFrameworkFound)
      // Because we keep a filename remapped for subsequent search directory
      // lookups, ignore IsFrameworkFoundInDir after the first remapping and not
      // just for remapping in a current search directory.
      *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
    if (!File)
      continue;

    diagnoseHeaderShadowing(Filename, File, DiagnosedShadowing, IncludeLoc,
                            FromDir, Includers, isAngled, -1, It);

    CurDir = It;

    IncludeNames[*File] = Filename;

    // This file is a system header or C++ unfriendly if the dir is.
    HeaderFileInfo &HFI = getFileInfo(*File);
    HFI.DirInfo = CurDir->getDirCharacteristic();

    // If the directory characteristic is User but this framework was
    // user-specified to be treated as a system framework, promote the
    // characteristic.
    if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
      HFI.DirInfo = SrcMgr::C_System;

    // If the filename matches a known system header prefix, override
    // whether the file is a system header.
    for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
      if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
        HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System
                                                       : SrcMgr::C_User;
        break;
      }
    }

    if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) {
      if (SuggestedModule)
        *SuggestedModule = MSSuggestedModule;
      return MSFE;
    }

    bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
    if (!Includers.empty())
      diagnoseFrameworkInclude(Diags, IncludeLoc,
                               Includers.front().second.getName(), Filename,
                               *File, isAngled, FoundByHeaderMap);

    // Remember this location for the next lookup we do.
    cacheLookupSuccess(CacheLookup, It, IncludeLoc);
    return File;
  }

  if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
    if (SuggestedModule)
      *SuggestedModule = MSSuggestedModule;
    return MSFE;
  }

  // Otherwise, didn't find it. Remember we didn't find this.
  CacheLookup.HitIt = search_dir_end();
  return std::nullopt;
}

/// LookupSubframeworkHeader - Look up a subframework for the specified
/// \#include file.  For example, if \#include'ing <HIToolbox/HIToolbox.h> from
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
/// is a subframework within Carbon.framework.  If so, return the FileEntry
/// for the designated file, otherwise return null.
OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
    StringRef Filename, FileEntryRef ContextFileEnt,
    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {
  // Framework names must have a '/' in the filename.  Find it.
  // FIXME: Should we permit '\' on Windows?
  size_t SlashPos = Filename.find('/');
  if (SlashPos == StringRef::npos)
    return std::nullopt;

  // Look up the base framework name of the ContextFileEnt.
  StringRef ContextName = ContextFileEnt.getName();

  // If the context info wasn't a framework, couldn't be a subframework.
  const unsigned DotFrameworkLen = 10;
  auto FrameworkPos = ContextName.find(".framework");
  if (FrameworkPos == StringRef::npos ||
      (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&
       ContextName[FrameworkPos + DotFrameworkLen] != '\\'))
    return std::nullopt;

  SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +
                                                          FrameworkPos +
                                                          DotFrameworkLen + 1);

  // Append Frameworks/HIToolbox.framework/
  FrameworkName += "Frameworks/";
  FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
  FrameworkName += ".framework/";

  auto &CacheLookup =
      *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
                                          FrameworkCacheEntry())).first;

  // Some other location?
  if (CacheLookup.second.Directory &&
      CacheLookup.first().size() == FrameworkName.size() &&
      memcmp(CacheLookup.first().data(), &FrameworkName[0],
             CacheLookup.first().size()) != 0)
    return std::nullopt;

  // Cache subframework.
  if (!CacheLookup.second.Directory) {
    ++NumSubFrameworkLookups;

    // If the framework dir doesn't exist, we fail.
    auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
    if (!Dir)
      return std::nullopt;

    // Otherwise, if it does, remember that this is the right direntry for this
    // framework.
    CacheLookup.second.Directory = Dir;
  }


  if (RelativePath) {
    RelativePath->clear();
    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
  }

  // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"
  SmallString<1024> HeadersFilename(FrameworkName);
  HeadersFilename += "Headers/";
  if (SearchPath) {
    SearchPath->clear();
    // Without trailing '/'.
    SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
  }

  HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
  auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);
  if (!File) {
    // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
    HeadersFilename = FrameworkName;
    HeadersFilename += "PrivateHeaders/";
    if (SearchPath) {
      SearchPath->clear();
      // Without trailing '/'.
      SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
    }

    HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
    File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);

    if (!File)
      return std::nullopt;
  }

  // This file is a system header or C++ unfriendly if the old file is.
  const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt);
  assert(ContextHFI && "context file without file info");
  // Note that the temporary 'DirInfo' is required here, as the call to
  // getFileInfo could resize the vector and might invalidate 'ContextHFI'.
  unsigned DirInfo = ContextHFI->DirInfo;
  getFileInfo(*File).DirInfo = DirInfo;

  FrameworkName.pop_back(); // remove the trailing '/'
  if (!findUsableModuleForFrameworkHeader(*File, FrameworkName,
                                          RequestingModule, SuggestedModule,
                                          /*IsSystem*/ false))
    return std::nullopt;

  return *File;
}

//===----------------------------------------------------------------------===//
// File Info Management.
//===----------------------------------------------------------------------===//

static bool moduleMembershipNeedsMerge(const HeaderFileInfo *HFI,
                                       ModuleMap::ModuleHeaderRole Role) {
  if (ModuleMap::isModular(Role))
    return !HFI->isModuleHeader || HFI->isTextualModuleHeader;
  if (!HFI->isModuleHeader && (Role & ModuleMap::TextualHeader))
    return !HFI->isTextualModuleHeader;
  return false;
}

static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,
                                          bool isModuleHeader,
                                          bool isTextualModuleHeader) {
  HFI.isModuleHeader |= isModuleHeader;
  if (HFI.isModuleHeader)
    HFI.isTextualModuleHeader = false;
  else
    HFI.isTextualModuleHeader |= isTextualModuleHeader;
}

void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) {
  mergeHeaderFileInfoModuleBits(*this, ModuleMap::isModular(Role),
                                (Role & ModuleMap::TextualHeader));
}

/// Merge the header file info provided by \p OtherHFI into the current
/// header file info (\p HFI)
static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
                                const HeaderFileInfo &OtherHFI) {
  assert(OtherHFI.External && "expected to merge external HFI");

  HFI.isImport |= OtherHFI.isImport;
  HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;
  mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,
                                OtherHFI.isTextualModuleHeader);

  if (!HFI.LazyControllingMacro.isValid())
    HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;

  HFI.DirInfo = OtherHFI.DirInfo;
  HFI.External = (!HFI.IsValid || HFI.External);
  HFI.IsValid = true;
}

HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {
  HeaderFileInfo *HFI = &FileInfo[FE];
  // FIXME: Use a generation count to check whether this is really up to date.
  if (ExternalSource && !HFI->Resolved) {
    auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
    if (ExternalHFI.IsValid) {
      HFI->Resolved = true;
      if (ExternalHFI.External)
        mergeHeaderFileInfo(*HFI, ExternalHFI);
    }
  }

  HFI->IsValid = true;
  // We assume the caller has local information about this header file, so it's
  // no longer strictly external.
  HFI->External = false;
  return *HFI;
}

const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const {
  HeaderFileInfo *HFI;
  if (ExternalSource) {
    HFI = &FileInfo[FE];
    // FIXME: Use a generation count to check whether this is really up to date.
    if (!HFI->Resolved) {
      auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
      if (ExternalHFI.IsValid) {
        HFI->Resolved = true;
        if (ExternalHFI.External)
          mergeHeaderFileInfo(*HFI, ExternalHFI);
      }
    }
  } else if (auto It = FileInfo.find(FE); It != FileInfo.end()) {
    HFI = &It->second;
  } else {
    HFI = nullptr;
  }

  return (HFI && HFI->IsValid) ? HFI : nullptr;
}

void HeaderSearch::forEachExistingLocalFileInfo(
    llvm::function_ref<void(FileEntryRef, const HeaderFileInfo &)> Fn) const {
  for (const auto &[FE, HFI] : FileInfo)
    if (HFI.IsValid && !HFI.External)
      Fn(FE, HFI);
}

bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
  // Check if we've entered this file and found an include guard or #pragma
  // once. Note that we dor't check for #import, because that's not a property
  // of the file itself.
  if (auto *HFI = getExistingFileInfo(File))
    return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
  return false;
}

void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,
                                        ModuleMap::ModuleHeaderRole Role,
                                        bool isCompilingModuleHeader) {
  // Don't mark the file info as non-external if there's nothing to change.
  if (!isCompilingModuleHeader) {
    if ((Role & ModuleMap::ExcludedHeader))
      return;
    auto *HFI = getExistingFileInfo(FE);
    if (HFI && !moduleMembershipNeedsMerge(HFI, Role))
      return;
  }

  auto &HFI = getFileInfo(FE);
  HFI.mergeModuleMembership(Role);
  HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
}

bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
                                          FileEntryRef File, bool isImport,
                                          bool ModulesEnabled, Module *M,
                                          bool &IsFirstIncludeOfFile) {
  // An include file should be entered if either:
  // 1. This is the first include of the file.
  // 2. This file can be included multiple times, that is it's not an
  //    "include-once" file.
  //
  // Include-once is controlled by these preprocessor directives.
  //
  // #pragma once
  // This directive is in the include file, and marks it as an include-once
  // file.
  //
  // #import <file>
  // This directive is in the includer, and indicates that the include file
  // should only be entered if this is the first include.
  ++NumIncluded;
  IsFirstIncludeOfFile = false;
  HeaderFileInfo &FileInfo = getFileInfo(File);

  auto MaybeReenterImportedFile = [&]() -> bool {
    // Modules add a wrinkle though: what's included isn't necessarily visible.
    // Consider this module.
    // module Example {
    //   module A { header "a.h" export * }
    //   module B { header "b.h" export * }
    // }
    // b.h includes c.h. The main file includes a.h, which will trigger a module
    // build of Example, and c.h will be included. However, c.h isn't visible to
    // the main file. Normally this is fine, the main file can just include c.h
    // if it needs it. If c.h is in a module, the include will translate into a
    // module import, this function will be skipped, and everything will work as
    // expected. However, if c.h is not in a module (or is `textual`), then this
    // function will run. If c.h is include-once, it will not be entered from
    // the main file and it will still not be visible.

    // If modules aren't enabled then there's no visibility issue. Always
    // respect `#pragma once`.
    if (!ModulesEnabled || FileInfo.isPragmaOnce)
      return false;

    // Ensure FileInfo bits are up to date.
    ModMap.resolveHeaderDirectives(File);

    // This brings up a subtlety of #import - it's not a very good indicator of
    // include-once. Developers are often unaware of the difference between
    // #include and #import, and tend to use one or the other indiscrimiately.
    // In order to support #include on include-once headers that lack macro
    // guards and `#pragma once` (which is the vast majority of Objective-C
    // headers), if a file is ever included with #import, it's marked as
    // isImport in the HeaderFileInfo and treated as include-once. This allows
    // #include to work in Objective-C.
    // #include <Foundation/Foundation.h>
    // #include <Foundation/NSString.h>
    // Foundation.h has an #import of NSString.h, and so the second #include is
    // skipped even though NSString.h has no `#pragma once` and no macro guard.
    //
    // However, this helpfulness causes problems with modules. If c.h is not an
    // include-once file, but something included it with #import anyway (as is
    // typical in Objective-C code), this include will be skipped and c.h will
    // not be visible. Consider it not include-once if it is a `textual` header
    // in a module.
    if (FileInfo.isTextualModuleHeader)
      return true;

    if (FileInfo.isCompilingModuleHeader) {
      // It's safer to re-enter a file whose module is being built because its
      // declarations will still be scoped to a single module.
      if (FileInfo.isModuleHeader) {
        // Headers marked as "builtin" are covered by the system module maps
        // rather than the builtin ones. Some versions of the Darwin module fail
        // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these
        // files while building their module to allow them to function properly.
        if (ModMap.isBuiltinHeader(File))
          return true;
      } else {
        // Files that are excluded from their module can potentially be
        // re-entered from their own module. This might cause redeclaration
        // errors if another module saw this file first, but there's a
        // reasonable chance that its module will build first. However if
        // there's no controlling macro, then trust the #import and assume this
        // really is an include-once file.
        if (FileInfo.getControllingMacro(ExternalLookup))
          return true;
      }
    }
    // If the include file has a macro guard, then it might still not be
    // re-entered if the controlling macro is visibly defined. e.g. another
    // header in the module being built included this file and local submodule
    // visibility is not enabled.

    // It might be tempting to re-enter the include-once file if it's not
    // visible in an attempt to make it visible. However this will still cause
    // redeclaration errors against the known-but-not-visible declarations. The
    // include file not being visible will most likely cause "undefined x"
    // errors, but at least there's a slim chance of compilation succeeding.
    return false;
  };

  if (isImport) {
    // As discussed above, record that this file was ever `#import`ed, and treat
    // it as an include-once file from here out.
    FileInfo.isImport = true;
    if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile())
      return false;
  } else {
    // isPragmaOnce and isImport are only set after the file has been included
    // at least once. If either are set then this is a repeat #include of an
    // include-once file.
    if (FileInfo.isPragmaOnce ||
        (FileInfo.isImport && !MaybeReenterImportedFile()))
      return false;
  }

  // As a final optimization, check for a macro guard and skip entering the file
  // if the controlling macro is defined. The macro guard will effectively erase
  // the file's contents, and the include would have no effect other than to
  // waste time opening and reading a file.
  if (const IdentifierInfo *ControllingMacro =
          FileInfo.getControllingMacro(ExternalLookup)) {
    // If the header corresponds to a module, check whether the macro is already
    // defined in that module rather than checking all visible modules. This is
    // mainly to cover corner cases where the same controlling macro is used in
    // different files in multiple modules.
    if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)
          : PP.isMacroDefined(ControllingMacro)) {
      ++NumMultiIncludeFileOptzn;
      return false;
    }
  }

  IsFirstIncludeOfFile = PP.markIncluded(File);
  return true;
}

size_t HeaderSearch::getTotalMemory() const {
  return SearchDirs.capacity()
    + llvm::capacity_in_bytes(FileInfo)
    + llvm::capacity_in_bytes(HeaderMaps)
    + LookupFileCache.getAllocator().getTotalMemory()
    + FrameworkMap.getAllocator().getTotalMemory();
}

unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
  return &DL - &*SearchDirs.begin();
}

StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
  return FrameworkNames.insert(Framework).first->first();
}

StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const {
  auto It = IncludeNames.find(File);
  if (It == IncludeNames.end())
    return {};
  return It->second;
}

void HeaderSearch::buildModuleMapIndex(DirectoryEntryRef Dir,
                                       ModuleMapDirectoryState &MMState) {
  if (!MMState.ModuleMapFile)
    return;
  const modulemap::ModuleMapFile *ParsedMM =
      ModMap.getParsedModuleMap(*MMState.ModuleMapFile);
  if (!ParsedMM)
    return;
  const modulemap::ModuleMapFile *ParsedPrivateMM = nullptr;
  if (MMState.PrivateModuleMapFile)
    ParsedPrivateMM = ModMap.getParsedModuleMap(*MMState.PrivateModuleMapFile);

  processModuleMapForIndex(*ParsedMM, Dir, "", MMState);
  if (ParsedPrivateMM)
    processModuleMapForIndex(*ParsedPrivateMM, Dir, "", MMState);
}

void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
                                       StringRef PathPrefix,
                                       ModuleMapDirectoryState &MMState) {
  SmallString<128> RelFromRootPath(PathPrefix);
  llvm::sys::path::append(RelFromRootPath, RelPath);
  llvm::sys::path::native(RelFromRootPath);
  MMState.HeaderToModules[RelFromRootPath].push_back(ModuleName);
}

void HeaderSearch::processExternModuleDeclForIndex(
    const modulemap::ExternModuleDecl &EMD, DirectoryEntryRef MMDir,
    StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
  StringRef FileNameRef = EMD.Path;
  SmallString<128> ModuleMapFileName;
  if (llvm::sys::path::is_relative(FileNameRef)) {
    ModuleMapFileName = MMDir.getName();
    llvm::sys::path::append(ModuleMapFileName, EMD.Path);
    FileNameRef = ModuleMapFileName;
  }
  if (auto EFile = FileMgr.getOptionalFileRef(FileNameRef)) {
    if (auto *ExtMMF = ModMap.getParsedModuleMap(*EFile)) {
      // Compute the new prefix by appending the extern module's directory
      // (from the extern declaration path) to the current prefix.
      SmallString<128> NewPrefix(PathPrefix);
      StringRef ExternDir = llvm::sys::path::parent_path(EMD.Path);
      if (!ExternDir.empty()) {
        llvm::sys::path::append(NewPrefix, ExternDir);
        llvm::sys::path::native(NewPrefix);
      }
      processModuleMapForIndex(*ExtMMF, EFile->getDir(), NewPrefix, MMState);
    }
  }
}

void HeaderSearch::processModuleDeclForIndex(const modulemap::ModuleDecl &MD,
                                             StringRef ModuleName,
                                             DirectoryEntryRef MMDir,
                                             StringRef PathPrefix,
                                             ModuleMapDirectoryState &MMState) {
  // Skip inferred submodules (module *)
  if (MD.Id.front().first == "*")
    return;

  auto ProcessDecl = llvm::makeVisitor(
      [&](const modulemap::HeaderDecl &HD) {
        if (HD.Umbrella) {
          MMState.UmbrellaHeaderModules.push_back(ModuleName);
        } else {
          addToModuleMapIndex(HD.Path, ModuleName, PathPrefix, MMState);
        }
      },
      [&](const modulemap::UmbrellaDirDecl &UDD) {
        SmallString<128> FullPath(PathPrefix);
        llvm::sys::path::append(FullPath, UDD.Path);
        llvm::sys::path::native(FullPath);
        MMState.UmbrellaDirModules.push_back(
            std::make_pair(std::string(FullPath), ModuleName));
      },
      [&](const modulemap::ModuleDecl &SubMD) {
        processModuleDeclForIndex(SubMD, ModuleName, MMDir, PathPrefix,
                                  MMState);
      },
      [&](const modulemap::ExternModuleDecl &EMD) {
        processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
      },
      [](const auto &) {
        // Ignore other decls.
      });

  for (const auto &Decl : MD.Decls) {
    std::visit(ProcessDecl, Decl);
  }
}

void HeaderSearch::processModuleMapForIndex(const modulemap::ModuleMapFile &MMF,
                                            DirectoryEntryRef MMDir,
                                            StringRef PathPrefix,
                                            ModuleMapDirectoryState &MMState) {
  for (const auto &Decl : MMF.Decls) {
    std::visit(llvm::makeVisitor(
                   [&](const modulemap::ModuleDecl &MD) {
                     processModuleDeclForIndex(MD, MD.Id.front().first, MMDir,
                                               PathPrefix, MMState);
                   },
                   [&](const modulemap::ExternModuleDecl &EMD) {
                     processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
                                                     MMState);
                   }),
               Decl);
  }
}

/// Compute relative path from DirPath to FileName by stripping the DirPath
/// prefix. DirPath should be derived from FileName (e.g. via parent_path) to
/// ensure consistent path separators. Returns empty if FileName doesn't start
/// with DirPath.
static StringRef computeRelativePath(StringRef FileName, StringRef DirPath) {
  if (!FileName.starts_with(DirPath))
    return {};
  StringRef RelativePath = FileName.substr(DirPath.size());
  while (!RelativePath.empty() &&
         llvm::sys::path::is_separator(RelativePath.front()))
    RelativePath = RelativePath.substr(1);
  return RelativePath;
}

SmallVector<StringRef, 1> HeaderSearch::findMatchingModulesInIndex(
    StringRef RelativePath, const ModuleMapDirectoryState &MMState) const {
  SmallVector<StringRef, 1> Modules;

  // Check for exact matches in cache.
  auto CachedMods = MMState.HeaderToModules.find(RelativePath);
  if (CachedMods != MMState.HeaderToModules.end())
    Modules.append(CachedMods->second.begin(), CachedMods->second.end());

  // Check umbrella directories.
  for (const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
    if (RelativePath.starts_with(UmbrellaDir.first) || UmbrellaDir.first == ".")
      Modules.push_back(UmbrellaDir.second);
  }

  // Add all modules corresponding to an umbrella header. We don't know which
  // other headers these umbrella headers include, so it's possible any one of
  // them includes the file. `ModuleMap::findModuleForHeader` will select the
  // correct module, accounting for any already known headers from other module
  // maps or loaded PCMs.
  //
  // TODO: Clang should strictly enforce that umbrella headers include the
  //       other headers in their directory, or that they are referenced in
  //       the module map. The current behavior can be order of include/import
  //       dependent. This would allow treating umbrella headers the same as
  //       umbrella directories here.
  Modules.append(MMState.UmbrellaHeaderModules.begin(),
                 MMState.UmbrellaHeaderModules.end());

  return Modules;
}

bool HeaderSearch::hasModuleMap(StringRef FileName,
                                const DirectoryEntry *Root,
                                bool IsSystem) {
  if (!HSOpts.ImplicitModuleMaps)
    return false;

  StringRef DirName = FileName;
  const DirectoryEntry *CurDir = nullptr;
  do {
    // Get the parent directory name.
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.empty())
      return false;

    // Determine whether this directory exists.
    auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
    if (!Dir)
      return false;
    CurDir = *Dir;

    bool IsFramework =
        llvm::sys::path::extension(Dir->getName()) == ".framework";

    // Check if it's possible that the module map for this directory can resolve
    // this header.
    parseModuleMapFile(*Dir, IsSystem, /*ImplicitlyDiscovered=*/true,
                       IsFramework);
    auto DirState = DirectoryModuleMap.find(*Dir);
    if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
      continue;

    if (!HSOpts.LazyLoadModuleMaps &&
        Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
                        SourceLocation()))
      return true;

    auto &MMState = DirState->second;

    // Build index if not already built
    if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
        MMState.UmbrellaHeaderModules.empty()) {
      buildModuleMapIndex(*Dir, MMState);
    }

    // The header cache is needed for the symlink diagnostic.
    if (!HSOpts.LazyLoadModuleMaps)
      return true;

    // Compute relative path from directory to the file. Use DirName (which
    // we computed via parent_path) rather than Dir->getName() to ensure
    // consistent path separators.
    StringRef RelativePath = computeRelativePath(FileName, DirName);
    SmallString<128> RelativePathNative(RelativePath);
    llvm::sys::path::native(RelativePathNative);

    auto ModulesToLoad =
        findMatchingModulesInIndex(RelativePathNative, MMState);

    // Load all matching modules.
    bool LoadedAny = false;
    for (StringRef ModName : ModulesToLoad) {
      if (ModMap.findOrLoadModule(ModName)) {
        LoadedAny = true;
      }
    }

    if (LoadedAny)
      return true;

    // If we hit the top of our search, we're done.
  } while (CurDir != Root);
  return false;
}

ModuleMap::KnownHeader
HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual,
                                  bool AllowExcluded) const {
  if (ExternalSource) {
    // Make sure the external source has handled header info about this file,
    // which includes whether the file is part of a module.
    (void)getExistingFileInfo(File);
  }
  return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded);
}

ArrayRef<ModuleMap::KnownHeader>
HeaderSearch::findAllModulesForHeader(FileEntryRef File) const {
  if (ExternalSource) {
    // Make sure the external source has handled header info about this file,
    // which includes whether the file is part of a module.
    (void)getExistingFileInfo(File);
  }
  return ModMap.findAllModulesForHeader(File);
}

ArrayRef<ModuleMap::KnownHeader>
HeaderSearch::findResolvedModulesForHeader(FileEntryRef File) const {
  if (ExternalSource) {
    // Make sure the external source has handled header info about this file,
    // which includes whether the file is part of a module.
    (void)getExistingFileInfo(File);
  }
  return ModMap.findResolvedModulesForHeader(File);
}

static bool suggestModule(HeaderSearch &HS, ModuleMap::KnownHeader Module,
                          FileEntryRef File, clang::Module *RequestingModule,
                          ModuleMap::KnownHeader *SuggestedModule) {
  // If this module specifies [no_undeclared_includes], we cannot find any
  // file that's in a non-dependency module.
  if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {
    HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false);
    if (!RequestingModule->directlyUses(Module.getModule())) {
      // Builtin headers are a special case. Multiple modules can use the same
      // builtin as a modular header (see also comment in
      // ShouldEnterIncludeFile()), so the builtin header may have been
      // "claimed" by an unrelated module. This shouldn't prevent us from
      // including the builtin header textually in this module.
      if (HS.getModuleMap().isBuiltinHeader(File)) {
        if (SuggestedModule)
          *SuggestedModule = ModuleMap::KnownHeader();
        return true;
      }
      // TODO: Add this module (or just its module map file) into something like
      // `RequestingModule->AffectingClangModules`.
      return false;
    }
  }

  if (SuggestedModule)
    *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)
                           ? ModuleMap::KnownHeader()
                           : Module;

  return true;
}

void HeaderSearch::diagnoseUncoveredSymlink(FileEntryRef File,
                                            ModuleMap::KnownHeader &Module,
                                            const DirectoryEntry *Root) {
  if (!Module)
    return;

  if (!HSOpts.ImplicitModuleMaps || Module.getModule()->isPartOfFramework() ||
      !Module.getModule()->isModuleMapModule())
    return;

  if (Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
                      Module.getModule()->DefinitionLoc))
    return;

  if (File.isDeviceFile() || File.isNamedPipe())
    return;

  llvm::SmallString<128> AbsPath(File.getName());
  FileMgr.makeAbsolutePath(AbsPath);
  llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);

  // NOTE: This path may be redirected, LLVM's VFS does not model symlinks, so
  //       it's possible this fails. The diagnostic is worded as such.
  llvm::SmallString<128> LinkTarget;
  if (llvm::sys::fs::readlink(AbsPath, LinkTarget))
    return;

  // We know this file is a symlink and resolved to a module. Check that there's
  // a module map that would be discoverable that covers this header. This uses
  // VFS paths as that's how module map search works.
  StringRef FileName = File.getNameAsRequested();
  StringRef DirName = FileName;
  const DirectoryEntry *CurDir = nullptr;

  // Walk up the directory tree looking for a module map that covers this path.
  do {
    DirName = llvm::sys::path::parent_path(DirName);
    if (DirName.empty())
      break;

    auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
    if (!Dir)
      break;
    CurDir = *Dir;

    auto DirState = DirectoryModuleMap.find(*Dir);
    if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
      continue;

    // Use DirName (from parent_path) rather than Dir->getName() to ensure
    // consistent path separators.
    StringRef RelativePath = computeRelativePath(FileName, DirName);
    if (RelativePath.empty())
      continue;
    SmallString<128> RelativePathNative(RelativePath);
    llvm::sys::path::native(RelativePathNative);

    auto MatchingModules =
        findMatchingModulesInIndex(RelativePathNative, DirState->second);
    if (!MatchingModules.empty())
      return; // Symlink path is covered, no diagnostic needed.
  } while (CurDir != Root);

  // The symlink path is not covered by any module map.
  Diags.Report(diag::warn_mmap_deprecated_symlink_to_modular_header)
      << File.getName() << LinkTarget
      << Module.getModule()->getFullModuleName();
  Diags.Report(Module.getModule()->DefinitionLoc,
               diag::note_mmap_module_defined_here);
}

bool HeaderSearch::findUsableModuleForHeader(
    FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule,
    ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
  if (needModuleLookup(RequestingModule, SuggestedModule)) {
    if (!HSOpts.LazyLoadModuleMaps) {
      // NOTE: This is required for `shadowed-submodule.m` to pass as it relies
      //       on A1/module.modulemap being loaded even though we already know
      //       which module the header belongs to. We will remove this behavior
      //       as part of lazy module map loading.
      hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);
      ModuleMap::KnownHeader Module =
          findModuleForHeader(File, /*AllowTextual=*/true);
      diagnoseUncoveredSymlink(File, Module, Root);
      return suggestModule(*this, Module, File, RequestingModule,
                           SuggestedModule);
    }

    // First check if we already know about this header
    ModuleMap::KnownHeader Module =
        findModuleForHeader(File, /*AllowTextual=*/true);

    // If we don't have a module yet, try to find/load module maps
    if (!Module) {
      hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);
      // Try again after loading module maps, this time bypassing loading module
      // map data from PCMs.
      Module = ModMap.findModuleForHeader(File, /*AllowTextual=*/true);
    }
    diagnoseUncoveredSymlink(File, Module, Root);
    return suggestModule(*this, Module, File, RequestingModule,
                         SuggestedModule);
  }
  return true;
}

bool HeaderSearch::findUsableModuleForFrameworkHeader(
    FileEntryRef File, StringRef FrameworkName, Module *RequestingModule,
    ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
  // If we're supposed to suggest a module, look for one now.
  if (needModuleLookup(RequestingModule, SuggestedModule)) {
    // Find the top-level framework based on this framework.
    SmallVector<std::string, 4> SubmodulePath;
    OptionalDirectoryEntryRef TopFrameworkDir =
        ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);
    assert(TopFrameworkDir && "Could not find the top-most framework dir");

    // Determine the name of the top-level framework.
    StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());

    // Load this framework module. If that succeeds, find the suggested module
    // for this header, if any.
    loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework,
                        /*ImplicitlyDiscovered=*/true);

    // FIXME: This can find a module not part of ModuleName, which is
    // important so that we're consistent about whether this header
    // corresponds to a module. Possibly we should lock down framework modules
    // so that this is not possible.
    ModuleMap::KnownHeader Module =
        findModuleForHeader(File, /*AllowTextual=*/true);
    return suggestModule(*this, Module, File, RequestingModule,
                         SuggestedModule);
  }
  return true;
}

static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File,
                                                FileManager &FileMgr,
                                                DiagnosticsEngine &Diags,
                                                bool Diagnose = true) {
  StringRef Filename = llvm::sys::path::filename(File.getName());
  SmallString<128>  PrivateFilename(File.getDir().getName());
  if (Filename == "module.map")
    llvm::sys::path::append(PrivateFilename, "module_private.map");
  else if (Filename == "module.modulemap")
    llvm::sys::path::append(PrivateFilename, "module.private.modulemap");
  else
    return std::nullopt;
  auto PMMFile = FileMgr.getOptionalFileRef(PrivateFilename);
  if (PMMFile) {
    if (Diagnose && Filename == "module.map")
      Diags.Report(diag::warn_deprecated_module_dot_map)
          << PrivateFilename << 1
          << File.getDir().getName().ends_with(".framework");
  }
  return PMMFile;
}

bool HeaderSearch::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,
                                             bool ImplicitlyDiscovered,
                                             FileID ID, unsigned *Offset,
                                             StringRef OriginalModuleMapFile) {
  // Find the directory for the module. For frameworks, that may require going
  // up from the 'Modules' directory.
  OptionalDirectoryEntryRef Dir;
  if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) {
    Dir = FileMgr.getOptionalDirectoryRef(".");
  } else {
    if (!OriginalModuleMapFile.empty()) {
      // We're building a preprocessed module map. Find or invent the directory
      // that it originally occupied.
      Dir = FileMgr.getOptionalDirectoryRef(
          llvm::sys::path::parent_path(OriginalModuleMapFile));
      if (!Dir) {
        auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
        Dir = FakeFile.getDir();
      }
    } else {
      Dir = File.getDir();
    }

    assert(Dir && "parent must exist");
    StringRef DirName(Dir->getName());
    if (llvm::sys::path::filename(DirName) == "Modules") {
      DirName = llvm::sys::path::parent_path(DirName);
      if (DirName.ends_with(".framework"))
        if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
          Dir = *MaybeDir;
      // FIXME: This assert can fail if there's a race between the above check
      // and the removal of the directory.
      assert(Dir && "parent must exist");
    }
  }

  assert(Dir && "module map home directory must exist");
  switch (parseAndLoadModuleMapFileImpl(File, IsSystem, ImplicitlyDiscovered,
                                        *Dir, ID, Offset,
                                        /*DiagnosePrivMMap=*/true)) {
  case MMR_AlreadyProcessed:
  case MMR_NewlyProcessed:
    return false;
  case MMR_NoDirectory:
  case MMR_InvalidModuleMap:
    return true;
  }
  llvm_unreachable("Unknown load module map result");
}

HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
    FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered,
    DirectoryEntryRef Dir, FileID ID, unsigned *Offset, bool DiagnosePrivMMap) {
  // Check whether we've already loaded this module map, and mark it as being
  // loaded in case we recursively try to load it from itself.
  auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));
  if (!AddResult.second)
    return AddResult.first->second ? MMR_AlreadyProcessed
                                   : MMR_InvalidModuleMap;

  if (ModMap.parseAndLoadModuleMapFile(File, IsSystem, ImplicitlyDiscovered,
                                       Dir, ID, Offset)) {
    LoadedModuleMaps[File] = false;
    return MMR_InvalidModuleMap;
  }

  // Try to load a corresponding private module map.
  if (OptionalFileEntryRef PMMFile =
          getPrivateModuleMap(File, FileMgr, Diags, DiagnosePrivMMap)) {
    if (ModMap.parseAndLoadModuleMapFile(*PMMFile, IsSystem,
                                         ImplicitlyDiscovered, Dir)) {
      LoadedModuleMaps[File] = false;
      return MMR_InvalidModuleMap;
    }
  }

  // This directory has a module map.
  return MMR_NewlyProcessed;
}

HeaderSearch::ModuleMapResult
HeaderSearch::parseModuleMapFileImpl(FileEntryRef File, bool IsSystem,
                                     bool ImplicitlyDiscovered,
                                     DirectoryEntryRef Dir, FileID ID) {
  // Check whether we've already parsed this module map, and mark it as being
  // parsed in case we recursively try to parse it from itself.
  auto AddResult = ParsedModuleMaps.insert(std::make_pair(File, true));
  if (!AddResult.second)
    return AddResult.first->second ? MMR_AlreadyProcessed
                                   : MMR_InvalidModuleMap;

  if (ModMap.parseModuleMapFile(File, IsSystem, ImplicitlyDiscovered, Dir,
                                ID)) {
    ParsedModuleMaps[File] = false;
    return MMR_InvalidModuleMap;
  }

  // Try to parse a corresponding private module map.
  if (OptionalFileEntryRef PMMFile =
          getPrivateModuleMap(File, FileMgr, Diags, /*Diagnose=*/false)) {
    if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, ImplicitlyDiscovered,
                                  Dir)) {
      ParsedModuleMaps[File] = false;
      return MMR_InvalidModuleMap;
    }
  }

  // This directory has a module map.
  return MMR_NewlyProcessed;
}

OptionalFileEntryRef
HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) {
  if (!HSOpts.ImplicitModuleMaps)
    return std::nullopt;
  // For frameworks, the preferred spelling is Modules/module.modulemap, but
  // module.map at the framework root is also accepted.
  SmallString<128> ModuleMapFileName(Dir.getName());
  if (IsFramework)
    llvm::sys::path::append(ModuleMapFileName, "Modules");
  llvm::sys::path::append(ModuleMapFileName, "module.modulemap");
  if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
    return *F;

  // Continue to allow module.map, but warn it's deprecated.
  ModuleMapFileName = Dir.getName();
  llvm::sys::path::append(ModuleMapFileName, "module.map");
  if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
    Diags.Report(diag::warn_deprecated_module_dot_map)
        << ModuleMapFileName << 0 << IsFramework;
    return *F;
  }

  // For frameworks, allow to have a private module map with a preferred
  // spelling when a public module map is absent.
  if (IsFramework) {
    ModuleMapFileName = Dir.getName();
    llvm::sys::path::append(ModuleMapFileName, "Modules",
                            "module.private.modulemap");
    if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
      return *F;
  }
  return std::nullopt;
}

Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,
                                          bool IsSystem,
                                          bool ImplicitlyDiscovered) {
  // Try to load a module map file.
  switch (parseAndLoadModuleMapFile(Dir, IsSystem, ImplicitlyDiscovered,
                                    /*IsFramework*/ true)) {
  case MMR_InvalidModuleMap:
    // Try to infer a module map from the framework directory.
    if (HSOpts.ImplicitModuleMaps)
      ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);
    break;

  case MMR_NoDirectory:
    return nullptr;

  case MMR_AlreadyProcessed:
  case MMR_NewlyProcessed:
    break;
  }

  return ModMap.findOrLoadModule(Name);
}

HeaderSearch::ModuleMapResult
HeaderSearch::parseAndLoadModuleMapFile(StringRef DirName, bool IsSystem,
                                        bool ImplicitlyDiscovered,
                                        bool IsFramework) {
  if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
    return parseAndLoadModuleMapFile(*Dir, IsSystem, ImplicitlyDiscovered,
                                     IsFramework);

  return MMR_NoDirectory;
}

HeaderSearch::ModuleMapResult
HeaderSearch::parseAndLoadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
                                        bool ImplicitlyDiscovered,
                                        bool IsFramework) {
  auto InsertRes = DirectoryModuleMap.insert(std::pair{
      Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
  ModuleMapDirectoryState &MMState = InsertRes.first->second;
  if (!InsertRes.second) {
    switch (MMState.Status) {
    case ModuleMapDirectoryState::Parsed:
      break;
    case ModuleMapDirectoryState::Loaded:
      return MMR_AlreadyProcessed;
    case ModuleMapDirectoryState::Invalid:
      return MMR_InvalidModuleMap;
    };
  }

  if (!MMState.ModuleMapFile) {
    MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);
    if (MMState.ModuleMapFile)
      MMState.PrivateModuleMapFile =
          getPrivateModuleMap(*MMState.ModuleMapFile, FileMgr, Diags);
  }

  if (MMState.ModuleMapFile) {
    ModuleMapResult Result = parseAndLoadModuleMapFileImpl(
        *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
    // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
    // E.g. Foo.framework/Modules/module.modulemap
    //      ^Dir                  ^ModuleMapFile
    if (Result == MMR_NewlyProcessed)
      MMState.Status = ModuleMapDirectoryState::Loaded;
    else if (Result == MMR_InvalidModuleMap)
      MMState.Status = ModuleMapDirectoryState::Invalid;
    return Result;
  }
  return MMR_InvalidModuleMap;
}

HeaderSearch::ModuleMapResult
HeaderSearch::parseModuleMapFile(StringRef DirName, bool IsSystem,
                                 bool ImplicitlyDiscovered, bool IsFramework) {
  if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
    return parseModuleMapFile(*Dir, IsSystem, ImplicitlyDiscovered,
                              IsFramework);

  return MMR_NoDirectory;
}

HeaderSearch::ModuleMapResult
HeaderSearch::parseModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
                                 bool ImplicitlyDiscovered, bool IsFramework) {
  if (!HSOpts.LazyLoadModuleMaps)
    return parseAndLoadModuleMapFile(Dir, IsSystem, ImplicitlyDiscovered,
                                     IsFramework);

  auto InsertRes = DirectoryModuleMap.insert(std::pair{
      Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
  ModuleMapDirectoryState &MMState = InsertRes.first->second;
  if (!InsertRes.second) {
    switch (MMState.Status) {
    case ModuleMapDirectoryState::Parsed:
    case ModuleMapDirectoryState::Loaded:
      return MMR_AlreadyProcessed;
    case ModuleMapDirectoryState::Invalid:
      return MMR_InvalidModuleMap;
    };
  }

  if (!MMState.ModuleMapFile) {
    MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);
    if (MMState.ModuleMapFile)
      MMState.PrivateModuleMapFile =
          getPrivateModuleMap(*MMState.ModuleMapFile, FileMgr, Diags);
  }

  if (MMState.ModuleMapFile) {
    ModuleMapResult Result = parseModuleMapFileImpl(
        *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
    // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
    // E.g. Foo.framework/Modules/module.modulemap
    //      ^Dir                  ^ModuleMapFile
    if (Result == MMR_NewlyProcessed)
      MMState.Status = ModuleMapDirectoryState::Parsed;
    else if (Result == MMR_InvalidModuleMap)
      MMState.Status = ModuleMapDirectoryState::Invalid;
    return Result;
  }
  return MMR_InvalidModuleMap;
}

void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
  Modules.clear();

  if (HSOpts.ImplicitModuleMaps) {
    // Load module maps for each of the header search directories.
    for (DirectoryLookup &DL : search_dir_range()) {
      bool IsSystem = DL.isSystemHeaderDirectory();
      if (DL.isFramework()) {
        std::error_code EC;
        SmallString<128> DirNative;
        llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);

        // Search each of the ".framework" directories to load them as modules.
        llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
        for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
                                           DirEnd;
             Dir != DirEnd && !EC; Dir.increment(EC)) {
          if (llvm::sys::path::extension(Dir->path()) != ".framework")
            continue;

          auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
          if (!FrameworkDir)
            continue;

          // Load this framework module.
          loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
                              IsSystem, /*ImplicitlyDiscovered=*/true);
        }
        continue;
      }

      // FIXME: Deal with header maps.
      if (DL.isHeaderMap())
        continue;

      // Try to load a module map file for the search directory.
      parseAndLoadModuleMapFile(*DL.getDirRef(), IsSystem,
                                /*ImplicitlyDiscovered=*/true,
                                /*IsFramework*/ false);

      // Try to load module map files for immediate subdirectories of this
      // search directory.
      loadSubdirectoryModuleMaps(DL);
    }
  }

  // Populate the list of modules.
  llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
}

void HeaderSearch::loadTopLevelSystemModules() {
  if (!HSOpts.ImplicitModuleMaps)
    return;

  // Load module maps for each of the header search directories.
  for (const DirectoryLookup &DL : search_dir_range()) {
    // We only care about normal header directories.
    if (!DL.isNormalDir())
      continue;

    // Try to load a module map file for the search directory.
    parseAndLoadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(),
                              /*ImplicitlyDiscovered=*/true, DL.isFramework());
  }
}

void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
  assert(HSOpts.ImplicitModuleMaps &&
         "Should not be loading subdirectory module maps");

  if (SearchDir.haveSearchedAllModuleMaps())
    return;

  std::error_code EC;
  SmallString<128> Dir = SearchDir.getDirRef()->getName();
  FileMgr.makeAbsolutePath(Dir);
  SmallString<128> DirNative;
  llvm::sys::path::native(Dir, DirNative);
  llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
  for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
       Dir != DirEnd && !EC; Dir.increment(EC)) {
    if (Dir->type() == llvm::sys::fs::file_type::regular_file)
      continue;
    bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
    if (IsFramework == SearchDir.isFramework())
      parseAndLoadModuleMapFile(
          Dir->path(), SearchDir.isSystemHeaderDirectory(),
          /*ImplicitlyDiscovered=*/true, SearchDir.isFramework());
  }

  SearchDir.setSearchedAllModuleMaps(true);
}

std::string HeaderSearch::suggestPathToFileForDiagnostics(
    FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {
  return suggestPathToFileForDiagnostics(File.getName(), /*WorkingDir=*/"",
                                         MainFile, IsAngled);
}

std::string HeaderSearch::suggestPathToFileForDiagnostics(
    llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
    bool *IsAngled) const {
  using namespace llvm::sys;

  llvm::SmallString<32> FilePath = File;
  if (!WorkingDir.empty() && !path::is_absolute(FilePath))
    path::make_absolute(WorkingDir, FilePath);
  // remove_dots switches to backslashes on windows as a side-effect!
  // We always want to suggest forward slashes for includes.
  // (not remove_dots(..., posix) as that misparses windows paths).
  path::remove_dots(FilePath, /*remove_dot_dot=*/true);
  path::native(FilePath, path::Style::posix);
  File = FilePath;

  unsigned BestPrefixLength = 0;
  // Checks whether `Dir` is a strict path prefix of `File`. If so and that's
  // the longest prefix we've seen so for it, returns true and updates the
  // `BestPrefixLength` accordingly.
  auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool {
    if (!WorkingDir.empty() && !path::is_absolute(Dir))
      path::make_absolute(WorkingDir, Dir);
    path::remove_dots(Dir, /*remove_dot_dot=*/true);
    for (auto NI = path::begin(File), NE = path::end(File),
              DI = path::begin(Dir), DE = path::end(Dir);
         NI != NE; ++NI, ++DI) {
      if (DI == DE) {
        // Dir is a prefix of File, up to choice of path separators.
        unsigned PrefixLength = NI - path::begin(File);
        if (PrefixLength > BestPrefixLength) {
          BestPrefixLength = PrefixLength;
          return true;
        }
        break;
      }

      // Consider all path separators equal.
      if (NI->size() == 1 && DI->size() == 1 &&
          path::is_separator(NI->front()) && path::is_separator(DI->front()))
        continue;

      // Special case Apple .sdk folders since the search path is typically a
      // symlink like `iPhoneSimulator14.5.sdk` while the file is instead
      // located in `iPhoneSimulator.sdk` (the real folder).
      if (NI->ends_with(".sdk") && DI->ends_with(".sdk")) {
        StringRef NBasename = path::stem(*NI);
        StringRef DBasename = path::stem(*DI);
        if (DBasename.starts_with(NBasename))
          continue;
      }

      if (*NI != *DI)
        break;
    }
    return false;
  };

  bool BestPrefixIsFramework = false;
  for (const DirectoryLookup &DL : search_dir_range()) {
    if (DL.isNormalDir()) {
      StringRef Dir = DL.getDirRef()->getName();
      if (CheckDir(Dir)) {
        if (IsAngled)
          *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
        BestPrefixIsFramework = false;
      }
    } else if (DL.isFramework()) {
      StringRef Dir = DL.getFrameworkDirRef()->getName();
      if (CheckDir(Dir)) {
        // Framework includes by convention use <>.
        if (IsAngled)
          *IsAngled = BestPrefixLength;
        BestPrefixIsFramework = true;
      }
    }
  }

  // Try to shorten include path using TUs directory, if we couldn't find any
  // suitable prefix in include search paths.
  if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
    if (IsAngled)
      *IsAngled = false;
    BestPrefixIsFramework = false;
  }

  // Try resolving resulting filename via reverse search in header maps,
  // key from header name is user preferred name for the include file.
  StringRef Filename = File.drop_front(BestPrefixLength);
  for (const DirectoryLookup &DL : search_dir_range()) {
    if (!DL.isHeaderMap())
      continue;

    StringRef SpelledFilename =
        DL.getHeaderMap()->reverseLookupFilename(Filename);
    if (!SpelledFilename.empty()) {
      Filename = SpelledFilename;
      BestPrefixIsFramework = false;
      break;
    }
  }

  // If the best prefix is a framework path, we need to compute the proper
  // include spelling for the framework header.
  bool IsPrivateHeader;
  SmallString<128> FrameworkName, IncludeSpelling;
  if (BestPrefixIsFramework &&
      isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName,
                           IncludeSpelling)) {
    Filename = IncludeSpelling;
  }
  return path::convert_to_slash(Filename);
}

void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path,
                                     SmallVectorImpl<char> &NormalizedPath) {
  NormalizedPath.assign(Path.begin(), Path.end());
  if (!NormalizedPath.empty()) {
    FileMgr.makeAbsolutePath(NormalizedPath);
    llvm::sys::path::remove_dots(NormalizedPath);
  }
}

static std::string createSpecificModuleCachePathImpl(
    FileManager &FileMgr, StringRef ModuleCachePath, bool DisableModuleHash,
    std::string ContextHash, size_t &NormalizedModuleCachePathLen) {
  SmallString<256> SpecificModuleCachePath;
  normalizeModuleCachePath(FileMgr, ModuleCachePath, SpecificModuleCachePath);
  NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
  if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
    llvm::sys::path::append(SpecificModuleCachePath, ContextHash);
  return std::string(SpecificModuleCachePath);
}

void HeaderSearch::initializeModuleCachePath(std::string NewContextHash) {
  ContextHash = std::move(NewContextHash);
  SpecificModuleCachePath = createSpecificModuleCachePathImpl(
      FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash,
      NormalizedModuleCachePathLen);
}

std::string clang::createSpecificModuleCachePath(FileManager &FileMgr,
                                                 StringRef ModuleCachePath,
                                                 bool DisableModuleHash,
                                                 std::string ContextHash) {
  size_t NormalizedModuleCachePathLen;
  return createSpecificModuleCachePathImpl(
      FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash),
      NormalizedModuleCachePathLen);
}
