brintos

brintos / llvm-project-archived public Read only

0
0
Text · 83.4 KiB · f05c28f Raw
2194 lines · cpp
1//===- HeaderSearch.cpp - Resolve Header File Locations -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements the DirectoryLookup and HeaderSearch interfaces.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Lex/HeaderSearch.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/FileManager.h"16#include "clang/Basic/IdentifierTable.h"17#include "clang/Basic/Module.h"18#include "clang/Basic/SourceManager.h"19#include "clang/Lex/DirectoryLookup.h"20#include "clang/Lex/ExternalPreprocessorSource.h"21#include "clang/Lex/HeaderMap.h"22#include "clang/Lex/HeaderSearchOptions.h"23#include "clang/Lex/LexDiagnostic.h"24#include "clang/Lex/ModuleMap.h"25#include "clang/Lex/Preprocessor.h"26#include "llvm/ADT/APInt.h"27#include "llvm/ADT/STLExtras.h"28#include "llvm/ADT/SmallString.h"29#include "llvm/ADT/SmallVector.h"30#include "llvm/ADT/Statistic.h"31#include "llvm/ADT/StringRef.h"32#include "llvm/Support/Allocator.h"33#include "llvm/Support/Capacity.h"34#include "llvm/Support/Errc.h"35#include "llvm/Support/ErrorHandling.h"36#include "llvm/Support/FileSystem.h"37#include "llvm/Support/Path.h"38#include "llvm/Support/VirtualFileSystem.h"39#include "llvm/Support/xxhash.h"40#include <algorithm>41#include <cassert>42#include <cstddef>43#include <cstdio>44#include <cstring>45#include <string>46#include <system_error>47#include <utility>48 49using namespace clang;50 51#define DEBUG_TYPE "file-search"52 53ALWAYS_ENABLED_STATISTIC(NumIncluded, "Number of attempted #includes.");54ALWAYS_ENABLED_STATISTIC(55    NumMultiIncludeFileOptzn,56    "Number of #includes skipped due to the multi-include optimization.");57ALWAYS_ENABLED_STATISTIC(NumFrameworkLookups, "Number of framework lookups.");58ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups,59                         "Number of subframework lookups.");60 61const IdentifierInfo *62HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {63  if (LazyControllingMacro.isID()) {64    if (!External)65      return nullptr;66 67    LazyControllingMacro =68        External->GetIdentifier(LazyControllingMacro.getID());69    return LazyControllingMacro.getPtr();70  }71 72  IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr();73  if (ControllingMacro && ControllingMacro->isOutOfDate()) {74    assert(External && "We must have an external source if we have a "75                       "controlling macro that is out of date.");76    External->updateOutOfDateIdentifier(*ControllingMacro);77  }78  return ControllingMacro;79}80 81ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() = default;82 83HeaderSearch::HeaderSearch(const HeaderSearchOptions &HSOpts,84                           SourceManager &SourceMgr, DiagnosticsEngine &Diags,85                           const LangOptions &LangOpts,86                           const TargetInfo *Target)87    : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),88      FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}89 90void HeaderSearch::PrintStats() {91  llvm::errs() << "\n*** HeaderSearch Stats:\n"92               << FileInfo.size() << " files tracked.\n";93  unsigned NumOnceOnlyFiles = 0;94  for (unsigned i = 0, e = FileInfo.size(); i != e; ++i)95    NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);96  llvm::errs() << "  " << NumOnceOnlyFiles << " #import/#pragma once files.\n";97 98  llvm::errs() << "  " << NumIncluded << " #include/#include_next/#import.\n"99               << "    " << NumMultiIncludeFileOptzn100               << " #includes skipped due to the multi-include optimization.\n";101 102  llvm::errs() << NumFrameworkLookups << " framework lookups.\n"103               << NumSubFrameworkLookups << " subframework lookups.\n";104}105 106void HeaderSearch::SetSearchPaths(107    std::vector<DirectoryLookup> dirs, unsigned int angledDirIdx,108    unsigned int systemDirIdx,109    llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {110  assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&111         "Directory indices are unordered");112  SearchDirs = std::move(dirs);113  SearchDirsUsage.assign(SearchDirs.size(), false);114  AngledDirIdx = angledDirIdx;115  SystemDirIdx = systemDirIdx;116  SearchDirToHSEntry = std::move(searchDirToHSEntry);117  //LookupFileCache.clear();118  indexInitialHeaderMaps();119}120 121void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {122  unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;123  SearchDirs.insert(SearchDirs.begin() + idx, dir);124  SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);125  if (!isAngled)126    AngledDirIdx++;127  SystemDirIdx++;128}129 130std::vector<bool> HeaderSearch::computeUserEntryUsage() const {131  std::vector<bool> UserEntryUsage(HSOpts.UserEntries.size());132  for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {133    // Check whether this DirectoryLookup has been successfully used.134    if (SearchDirsUsage[I]) {135      auto UserEntryIdxIt = SearchDirToHSEntry.find(I);136      // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.137      if (UserEntryIdxIt != SearchDirToHSEntry.end())138        UserEntryUsage[UserEntryIdxIt->second] = true;139    }140  }141  return UserEntryUsage;142}143 144std::vector<bool> HeaderSearch::collectVFSUsageAndClear() const {145  std::vector<bool> VFSUsage;146  if (!getHeaderSearchOpts().ModulesIncludeVFSUsage)147    return VFSUsage;148 149  llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();150  // TODO: This only works if the `RedirectingFileSystem`s were all created by151  //       `createVFSFromOverlayFiles`. But at least exclude the ones with null152  //       OverlayFileDir.153  RootFS.visit([&](llvm::vfs::FileSystem &FS) {154    if (auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {155      // Skip a `RedirectingFileSystem` with null OverlayFileDir which indicates156      // that they aren't created by createVFSFromOverlayFiles from the overlays157      // in HeaderSearchOption::VFSOverlayFiles.158      if (!RFS->getOverlayFileDir().empty()) {159        VFSUsage.push_back(RFS->hasBeenUsed());160        RFS->clearHasBeenUsed();161      }162    }163  });164  assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() &&165         "A different number of RedirectingFileSystem's were present than "166         "-ivfsoverlay options passed to Clang!");167  // VFS visit order is the opposite of VFSOverlayFiles order.168  std::reverse(VFSUsage.begin(), VFSUsage.end());169  return VFSUsage;170}171 172/// CreateHeaderMap - This method returns a HeaderMap for the specified173/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.174const HeaderMap *HeaderSearch::CreateHeaderMap(FileEntryRef FE) {175  // We expect the number of headermaps to be small, and almost always empty.176  // If it ever grows, use of a linear search should be re-evaluated.177  if (!HeaderMaps.empty()) {178    for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)179      // Pointer equality comparison of FileEntries works because they are180      // already uniqued by inode.181      if (HeaderMaps[i].first == FE)182        return HeaderMaps[i].second.get();183  }184 185  if (std::unique_ptr<HeaderMap> HM = HeaderMap::Create(FE, FileMgr)) {186    HeaderMaps.emplace_back(FE, std::move(HM));187    return HeaderMaps.back().second.get();188  }189 190  return nullptr;191}192 193/// Get filenames for all registered header maps.194void HeaderSearch::getHeaderMapFileNames(195    SmallVectorImpl<std::string> &Names) const {196  for (auto &HM : HeaderMaps)197    Names.push_back(std::string(HM.first.getName()));198}199 200std::string HeaderSearch::getCachedModuleFileName(Module *Module) {201  OptionalFileEntryRef ModuleMap =202      getModuleMap().getModuleMapFileForUniquing(Module);203  // The ModuleMap maybe a nullptr, when we load a cached C++ module without204  // *.modulemap file. In this case, just return an empty string.205  if (!ModuleMap)206    return {};207  return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested());208}209 210std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,211                                                    bool FileMapOnly) {212  // First check the module name to pcm file map.213  auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));214  if (i != HSOpts.PrebuiltModuleFiles.end())215    return i->second;216 217  if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())218    return {};219 220  // Then go through each prebuilt module directory and try to find the pcm221  // file.222  for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {223    SmallString<256> Result(Dir);224    FileMgr.makeAbsolutePath(Result);225    if (ModuleName.contains(':'))226      // The separator of C++20 modules partitions (':') is not good for file227      // systems, here clang and gcc choose '-' by default since it is not a228      // valid character of C++ indentifiers. So we could avoid conflicts.229      llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +230                                          ModuleName.split(':').second +231                                          ".pcm");232    else233      llvm::sys::path::append(Result, ModuleName + ".pcm");234    if (getFileMgr().getOptionalFileRef(Result))235      return std::string(Result);236  }237 238  return {};239}240 241std::string HeaderSearch::getPrebuiltImplicitModuleFileName(Module *Module) {242  OptionalFileEntryRef ModuleMap =243      getModuleMap().getModuleMapFileForUniquing(Module);244  StringRef ModuleName = Module->Name;245  StringRef ModuleMapPath = ModuleMap->getName();246  StringRef ModuleCacheHash = HSOpts.DisableModuleHash ? "" : getModuleHash();247  for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {248    SmallString<256> CachePath(Dir);249    FileMgr.makeAbsolutePath(CachePath);250    llvm::sys::path::append(CachePath, ModuleCacheHash);251    std::string FileName =252        getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);253    if (!FileName.empty() && getFileMgr().getOptionalFileRef(FileName))254      return FileName;255  }256  return {};257}258 259std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,260                                                  StringRef ModuleMapPath) {261  return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,262                                     getModuleCachePath());263}264 265std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,266                                                      StringRef ModuleMapPath,267                                                      StringRef CachePath) {268  // If we don't have a module cache path or aren't supposed to use one, we269  // can't do anything.270  if (CachePath.empty())271    return {};272 273  SmallString<256> Result(CachePath);274 275  if (HSOpts.DisableModuleHash) {276    llvm::sys::path::append(Result, ModuleName + ".pcm");277  } else {278    // Construct the name <ModuleName>-<hash of ModuleMapPath>.pcm which should279    // ideally be globally unique to this particular module. Name collisions280    // in the hash are safe (because any translation unit can only import one281    // module with each name), but result in a loss of caching.282    //283    // To avoid false-negatives, we form as canonical a path as we can, and map284    // to lower-case in case we're on a case-insensitive file system.285    SmallString<128> CanonicalPath(ModuleMapPath);286    if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath))287      return {};288 289    auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());290 291    SmallString<128> HashStr;292    llvm::APInt(64, Hash).toStringUnsigned(HashStr, /*Radix*/36);293    llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");294  }295  return Result.str().str();296}297 298Module *HeaderSearch::lookupModule(StringRef ModuleName,299                                   SourceLocation ImportLoc, bool AllowSearch,300                                   bool AllowExtraModuleMapSearch) {301  // Look in the module map to determine if there is a module by this name.302  Module *Module = ModMap.findOrLoadModule(ModuleName);303  if (Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)304    return Module;305 306  StringRef SearchName = ModuleName;307  Module = lookupModule(ModuleName, SearchName, ImportLoc,308                        AllowExtraModuleMapSearch);309 310  // The facility for "private modules" -- adjacent, optional module maps named311  // module.private.modulemap that are supposed to define private submodules --312  // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private.313  //314  // Foo.Private is now deprecated in favor of Foo_Private. Users of FooPrivate315  // should also rename to Foo_Private. Representing private as submodules316  // could force building unwanted dependencies into the parent module and cause317  // dependency cycles.318  if (!Module && SearchName.consume_back("_Private"))319    Module = lookupModule(ModuleName, SearchName, ImportLoc,320                          AllowExtraModuleMapSearch);321  if (!Module && SearchName.consume_back("Private"))322    Module = lookupModule(ModuleName, SearchName, ImportLoc,323                          AllowExtraModuleMapSearch);324  return Module;325}326 327Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,328                                   SourceLocation ImportLoc,329                                   bool AllowExtraModuleMapSearch) {330  Module *Module = nullptr;331 332  // Look through the various header search paths to load any available module333  // maps, searching for a module map that describes this module.334  for (DirectoryLookup &Dir : search_dir_range()) {335    if (Dir.isFramework()) {336      // Search for or infer a module map for a framework. Here we use337      // SearchName rather than ModuleName, to permit finding private modules338      // named FooPrivate in buggy frameworks named Foo.339      SmallString<128> FrameworkDirName;340      FrameworkDirName += Dir.getFrameworkDirRef()->getName();341      llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");342      if (auto FrameworkDir =343              FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {344        bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;345        Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);346        if (Module)347          break;348      }349    }350 351    // FIXME: Figure out how header maps and module maps will work together.352 353    // Only deal with normal search directories.354    if (!Dir.isNormalDir())355      continue;356 357    bool IsSystem = Dir.isSystemHeaderDirectory();358    // Only returns std::nullopt if not a normal directory, which we just359    // checked360    DirectoryEntryRef NormalDir = *Dir.getDirRef();361    // Search for a module map file in this directory.362    if (parseModuleMapFile(NormalDir, IsSystem,363                           /*IsFramework*/ false) == MMR_NewlyProcessed) {364      // We just parsed a module map file; check whether the module can be365      // loaded now.366      Module = ModMap.findOrLoadModule(ModuleName);367      if (Module)368        break;369    }370 371    // Search for a module map in a subdirectory with the same name as the372    // module.373    SmallString<128> NestedModuleMapDirName;374    NestedModuleMapDirName = Dir.getDirRef()->getName();375    llvm::sys::path::append(NestedModuleMapDirName, ModuleName);376    if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,377                           /*IsFramework*/ false) == MMR_NewlyProcessed) {378      // If we just parsed a module map file, look for the module again.379      Module = ModMap.findOrLoadModule(ModuleName);380      if (Module)381        break;382    }383 384    if (HSOpts.AllowModuleMapSubdirectorySearch) {385      // If we've already performed the exhaustive search for module maps in386      // this search directory, don't do it again.387      if (Dir.haveSearchedAllModuleMaps())388        continue;389 390      // Load all module maps in the immediate subdirectories of this search391      // directory if ModuleName was from @import.392      if (AllowExtraModuleMapSearch)393        loadSubdirectoryModuleMaps(Dir);394 395      // Look again for the module.396      Module = ModMap.findOrLoadModule(ModuleName);397      if (Module)398        break;399    }400  }401 402  return Module;403}404 405void HeaderSearch::indexInitialHeaderMaps() {406  llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());407 408  // Iterate over all filename keys and associate them with the index i.409  for (unsigned i = 0; i != SearchDirs.size(); ++i) {410    auto &Dir = SearchDirs[i];411 412    // We're concerned with only the initial contiguous run of header413    // maps within SearchDirs, which can be 99% of SearchDirs when414    // SearchDirs.size() is ~10000.415    if (!Dir.isHeaderMap()) {416      SearchDirHeaderMapIndex = std::move(Index);417      FirstNonHeaderMapSearchDirIdx = i;418      break;419    }420 421    // Give earlier keys precedence over identical later keys.422    auto Callback = [&](StringRef Filename) {423      Index.try_emplace(Filename.lower(), i);424    };425    Dir.getHeaderMap()->forEachKey(Callback);426  }427}428 429//===----------------------------------------------------------------------===//430// File lookup within a DirectoryLookup scope431//===----------------------------------------------------------------------===//432 433/// getName - Return the directory or filename corresponding to this lookup434/// object.435StringRef DirectoryLookup::getName() const {436  if (isNormalDir())437    return getDirRef()->getName();438  if (isFramework())439    return getFrameworkDirRef()->getName();440  assert(isHeaderMap() && "Unknown DirectoryLookup");441  return getHeaderMap()->getFileName();442}443 444OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule(445    StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,446    bool IsSystemHeaderDir, Module *RequestingModule,447    ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /*=true*/,448    bool CacheFailures /*=true*/) {449  // If we have a module map that might map this header, load it and450  // check whether we'll have a suggestion for a module.451  auto File = getFileMgr().getFileRef(FileName, OpenFile, CacheFailures);452  if (!File) {453    // For rare, surprising errors (e.g. "out of file handles"), diag the EC454    // message.455    std::error_code EC = llvm::errorToErrorCode(File.takeError());456    if (EC != llvm::errc::no_such_file_or_directory &&457        EC != llvm::errc::invalid_argument &&458        EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {459      Diags.Report(IncludeLoc, diag::err_cannot_open_file)460          << FileName << EC.message();461    }462    return std::nullopt;463  }464 465  // If there is a module that corresponds to this header, suggest it.466  if (!findUsableModuleForHeader(467          *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,468          SuggestedModule, IsSystemHeaderDir))469    return std::nullopt;470 471  return *File;472}473 474/// LookupFile - Lookup the specified file in this search path, returning it475/// if it exists or returning null if not.476OptionalFileEntryRef DirectoryLookup::LookupFile(477    StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,478    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,479    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,480    bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,481    bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName,482    bool OpenFile) const {483  InUserSpecifiedSystemFramework = false;484  IsInHeaderMap = false;485  MappedName.clear();486 487  SmallString<1024> TmpDir;488  if (isNormalDir()) {489    // Concatenate the requested file onto the directory.490    TmpDir = getDirRef()->getName();491    llvm::sys::path::append(TmpDir, Filename);492    if (SearchPath) {493      StringRef SearchPathRef(getDirRef()->getName());494      SearchPath->clear();495      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());496    }497    if (RelativePath) {498      RelativePath->clear();499      RelativePath->append(Filename.begin(), Filename.end());500    }501 502    return HS.getFileAndSuggestModule(503        TmpDir, IncludeLoc, getDir(), isSystemHeaderDirectory(),504        RequestingModule, SuggestedModule, OpenFile);505  }506 507  if (isFramework())508    return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,509                             RequestingModule, SuggestedModule,510                             InUserSpecifiedSystemFramework, IsFrameworkFound);511 512  assert(isHeaderMap() && "Unknown directory lookup");513  const HeaderMap *HM = getHeaderMap();514  SmallString<1024> Path;515  StringRef Dest = HM->lookupFilename(Filename, Path);516  if (Dest.empty())517    return std::nullopt;518 519  IsInHeaderMap = true;520 521  auto FixupSearchPathAndFindUsableModule =522      [&](FileEntryRef File) -> OptionalFileEntryRef {523    if (SearchPath) {524      StringRef SearchPathRef(getName());525      SearchPath->clear();526      SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());527    }528    if (RelativePath) {529      RelativePath->clear();530      RelativePath->append(Filename.begin(), Filename.end());531    }532    if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(),533                                      RequestingModule, SuggestedModule,534                                      isSystemHeaderDirectory())) {535      return std::nullopt;536    }537    return File;538  };539 540  // Check if the headermap maps the filename to a framework include541  // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the542  // framework include.543  if (llvm::sys::path::is_relative(Dest)) {544    MappedName.append(Dest.begin(), Dest.end());545    Filename = StringRef(MappedName.begin(), MappedName.size());546    Dest = HM->lookupFilename(Filename, Path);547  }548 549  if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest, OpenFile)) {550    return FixupSearchPathAndFindUsableModule(*Res);551  }552 553  // Header maps need to be marked as used whenever the filename matches.554  // The case where the target file **exists** is handled by callee of this555  // function as part of the regular logic that applies to include search paths.556  // The case where the target file **does not exist** is handled here:557  HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);558  return std::nullopt;559}560 561/// Given a framework directory, find the top-most framework directory.562///563/// \param FileMgr The file manager to use for directory lookups.564/// \param DirName The name of the framework directory.565/// \param SubmodulePath Will be populated with the submodule path from the566/// returned top-level module to the originally named framework.567static OptionalDirectoryEntryRef568getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,569                   SmallVectorImpl<std::string> &SubmodulePath) {570  assert(llvm::sys::path::extension(DirName) == ".framework" &&571         "Not a framework directory");572 573  // Note: as an egregious but useful hack we use the real path here, because574  // frameworks moving between top-level frameworks to embedded frameworks tend575  // to be symlinked, and we base the logical structure of modules on the576  // physical layout. In particular, we need to deal with crazy includes like577  //578  //   #include <Foo/Frameworks/Bar.framework/Headers/Wibble.h>579  //580  // where 'Bar' used to be embedded in 'Foo', is now a top-level framework581  // which one should access with, e.g.,582  //583  //   #include <Bar/Wibble.h>584  //585  // Similar issues occur when a top-level framework has moved into an586  // embedded framework.587  auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);588 589  if (TopFrameworkDir)590    DirName = FileMgr.getCanonicalName(*TopFrameworkDir);591  do {592    // Get the parent directory name.593    DirName = llvm::sys::path::parent_path(DirName);594    if (DirName.empty())595      break;596 597    // Determine whether this directory exists.598    auto Dir = FileMgr.getOptionalDirectoryRef(DirName);599    if (!Dir)600      break;601 602    // If this is a framework directory, then we're a subframework of this603    // framework.604    if (llvm::sys::path::extension(DirName) == ".framework") {605      SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));606      TopFrameworkDir = *Dir;607    }608  } while (true);609 610  return TopFrameworkDir;611}612 613static bool needModuleLookup(Module *RequestingModule,614                             bool HasSuggestedModule) {615  return HasSuggestedModule ||616         (RequestingModule && RequestingModule->NoUndeclaredIncludes);617}618 619/// DoFrameworkLookup - Do a lookup of the specified file in the current620/// DirectoryLookup, which is a framework directory.621OptionalFileEntryRef DirectoryLookup::DoFrameworkLookup(622    StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,623    SmallVectorImpl<char> *RelativePath, Module *RequestingModule,624    ModuleMap::KnownHeader *SuggestedModule,625    bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {626  FileManager &FileMgr = HS.getFileMgr();627 628  // Framework names must have a '/' in the filename.629  size_t SlashPos = Filename.find('/');630  if (SlashPos == StringRef::npos)631    return std::nullopt;632 633  // Find out if this is the home for the specified framework, by checking634  // HeaderSearch.  Possible answers are yes/no and unknown.635  FrameworkCacheEntry &CacheEntry =636    HS.LookupFrameworkCache(Filename.substr(0, SlashPos));637 638  // If it is known and in some other directory, fail.639  if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDirRef())640    return std::nullopt;641 642  // Otherwise, construct the path to this framework dir.643 644  // FrameworkName = "/System/Library/Frameworks/"645  SmallString<1024> FrameworkName;646  FrameworkName += getFrameworkDirRef()->getName();647  if (FrameworkName.empty() || FrameworkName.back() != '/')648    FrameworkName.push_back('/');649 650  // FrameworkName = "/System/Library/Frameworks/Cocoa"651  StringRef ModuleName(Filename.begin(), SlashPos);652  FrameworkName += ModuleName;653 654  // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/"655  FrameworkName += ".framework/";656 657  // If the cache entry was unresolved, populate it now.658  if (!CacheEntry.Directory) {659    ++NumFrameworkLookups;660 661    // If the framework dir doesn't exist, we fail.662    auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);663    if (!Dir)664      return std::nullopt;665 666    // Otherwise, if it does, remember that this is the right direntry for this667    // framework.668    CacheEntry.Directory = getFrameworkDirRef();669 670    // If this is a user search directory, check if the framework has been671    // user-specified as a system framework.672    if (getDirCharacteristic() == SrcMgr::C_User) {673      SmallString<1024> SystemFrameworkMarker(FrameworkName);674      SystemFrameworkMarker += ".system_framework";675      if (FileMgr.getOptionalFileRef(SystemFrameworkMarker))676        CacheEntry.IsUserSpecifiedSystemFramework = true;677    }678  }679 680  // Set out flags.681  InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;682  IsFrameworkFound = CacheEntry.Directory.has_value();683 684  if (RelativePath) {685    RelativePath->clear();686    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());687  }688 689  // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"690  unsigned OrigSize = FrameworkName.size();691 692  FrameworkName += "Headers/";693 694  if (SearchPath) {695    SearchPath->clear();696    // Without trailing '/'.697    SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);698  }699 700  FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());701 702  auto File =703      FileMgr.getOptionalFileRef(FrameworkName, /*OpenFile=*/!SuggestedModule);704  if (!File) {705    // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"706    const char *Private = "Private";707    FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,708                         Private+strlen(Private));709    if (SearchPath)710      SearchPath->insert(SearchPath->begin()+OrigSize, Private,711                         Private+strlen(Private));712 713    File = FileMgr.getOptionalFileRef(FrameworkName,714                                      /*OpenFile=*/!SuggestedModule);715  }716 717  // If we found the header and are allowed to suggest a module, do so now.718  if (File && needModuleLookup(RequestingModule, SuggestedModule)) {719    // Find the framework in which this header occurs.720    StringRef FrameworkPath = File->getDir().getName();721    bool FoundFramework = false;722    do {723      // Determine whether this directory exists.724      auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkPath);725      if (!Dir)726        break;727 728      // If this is a framework directory, then we're a subframework of this729      // framework.730      if (llvm::sys::path::extension(FrameworkPath) == ".framework") {731        FoundFramework = true;732        break;733      }734 735      // Get the parent directory name.736      FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);737      if (FrameworkPath.empty())738        break;739    } while (true);740 741    bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;742    if (FoundFramework) {743      if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath,744                                                 RequestingModule,745                                                 SuggestedModule, IsSystem))746        return std::nullopt;747    } else {748      if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule,749                                        SuggestedModule, IsSystem))750        return std::nullopt;751    }752  }753  if (File)754    return *File;755  return std::nullopt;756}757 758void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,759                                      ConstSearchDirIterator HitIt,760                                      SourceLocation Loc) {761  CacheLookup.HitIt = HitIt;762  noteLookupUsage(HitIt.Idx, Loc);763}764 765void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {766  SearchDirsUsage[HitIdx] = true;767 768  auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);769  if (UserEntryIdxIt != SearchDirToHSEntry.end())770    Diags.Report(Loc, diag::remark_pp_search_path_usage)771        << HSOpts.UserEntries[UserEntryIdxIt->second].Path;772}773 774void HeaderSearch::setTarget(const TargetInfo &Target) {775  ModMap.setTarget(Target);776}777 778//===----------------------------------------------------------------------===//779// Header File Location.780//===----------------------------------------------------------------------===//781 782/// Return true with a diagnostic if the file that MSVC would have found783/// fails to match the one that Clang would have found with MSVC header search784/// disabled.785static bool checkMSVCHeaderSearch(DiagnosticsEngine &Diags,786                                  OptionalFileEntryRef MSFE,787                                  const FileEntry *FE,788                                  SourceLocation IncludeLoc) {789  if (MSFE && FE != *MSFE) {790    Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();791    return true;792  }793  return false;794}795 796static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {797  assert(!Str.empty());798  char *CopyStr = Alloc.Allocate<char>(Str.size()+1);799  std::copy(Str.begin(), Str.end(), CopyStr);800  CopyStr[Str.size()] = '\0';801  return CopyStr;802}803 804static bool isFrameworkStylePath(StringRef Path, bool &IsPrivateHeader,805                                 SmallVectorImpl<char> &FrameworkName,806                                 SmallVectorImpl<char> &IncludeSpelling) {807  using namespace llvm::sys;808  path::const_iterator I = path::begin(Path);809  path::const_iterator E = path::end(Path);810  IsPrivateHeader = false;811 812  // Detect different types of framework style paths:813  //814  //   ...Foo.framework/{Headers,PrivateHeaders}815  //   ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders}816  //   ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders}817  //   ...<other variations with 'Versions' like in the above path>818  //819  // and some other variations among these lines.820  int FoundComp = 0;821  while (I != E) {822    if (*I == "Headers") {823      ++FoundComp;824    } else if (*I == "PrivateHeaders") {825      ++FoundComp;826      IsPrivateHeader = true;827    } else if (I->ends_with(".framework")) {828      StringRef Name = I->drop_back(10); // Drop .framework829      // Need to reset the strings and counter to support nested frameworks.830      FrameworkName.clear();831      FrameworkName.append(Name.begin(), Name.end());832      IncludeSpelling.clear();833      IncludeSpelling.append(Name.begin(), Name.end());834      FoundComp = 1;835    } else if (FoundComp >= 2) {836      IncludeSpelling.push_back('/');837      IncludeSpelling.append(I->begin(), I->end());838    }839    ++I;840  }841 842  return !FrameworkName.empty() && FoundComp >= 2;843}844 845static void846diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,847                         StringRef Includer, StringRef IncludeFilename,848                         FileEntryRef IncludeFE, bool isAngled = false,849                         bool FoundByHeaderMap = false) {850  bool IsIncluderPrivateHeader = false;851  SmallString<128> FromFramework, ToFramework;852  SmallString<128> FromIncludeSpelling, ToIncludeSpelling;853  if (!isFrameworkStylePath(Includer, IsIncluderPrivateHeader, FromFramework,854                            FromIncludeSpelling))855    return;856  bool IsIncludeePrivateHeader = false;857  bool IsIncludeeInFramework =858      isFrameworkStylePath(IncludeFE.getName(), IsIncludeePrivateHeader,859                           ToFramework, ToIncludeSpelling);860 861  if (!isAngled && !FoundByHeaderMap) {862    SmallString<128> NewInclude("<");863    if (IsIncludeeInFramework) {864      NewInclude += ToIncludeSpelling;865      NewInclude += ">";866    } else {867      NewInclude += IncludeFilename;868      NewInclude += ">";869    }870    Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)871        << IncludeFilename872        << FixItHint::CreateReplacement(IncludeLoc, NewInclude);873  }874 875  // Headers in Foo.framework/Headers should not include headers876  // from Foo.framework/PrivateHeaders, since this violates public/private877  // API boundaries and can cause modular dependency cycles.878  if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&879      IsIncludeePrivateHeader && FromFramework == ToFramework)880    Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)881        << IncludeFilename;882}883 884/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,885/// return null on failure.  isAngled indicates whether the file reference is886/// for system \#include's or not (i.e. using <> instead of ""). Includers, if887/// non-empty, indicates where the \#including file(s) are, in case a relative888/// search is needed. Microsoft mode will pass all \#including files.889OptionalFileEntryRef HeaderSearch::LookupFile(890    StringRef Filename, SourceLocation IncludeLoc, bool isAngled,891    ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,892    ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,893    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,894    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,895    bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,896    bool BuildSystemModule, bool OpenFile, bool CacheFailures) {897  ConstSearchDirIterator CurDirLocal = nullptr;898  ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;899 900  if (IsMapped)901    *IsMapped = false;902 903  if (IsFrameworkFound)904    *IsFrameworkFound = false;905 906  if (SuggestedModule)907    *SuggestedModule = ModuleMap::KnownHeader();908 909  // If 'Filename' is absolute, check to see if it exists and no searching.910  if (llvm::sys::path::is_absolute(Filename)) {911    CurDir = nullptr;912 913    // If this was an #include_next "/absolute/file", fail.914    if (FromDir)915      return std::nullopt;916 917    if (SearchPath)918      SearchPath->clear();919    if (RelativePath) {920      RelativePath->clear();921      RelativePath->append(Filename.begin(), Filename.end());922    }923    // Otherwise, just return the file.924    return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,925                                   /*IsSystemHeaderDir*/ false,926                                   RequestingModule, SuggestedModule, OpenFile,927                                   CacheFailures);928  }929 930  // This is the header that MSVC's header search would have found.931  ModuleMap::KnownHeader MSSuggestedModule;932  OptionalFileEntryRef MSFE;933 934  // Check to see if the file is in the #includer's directory. This cannot be935  // based on CurDir, because each includer could be a #include of a936  // subdirectory (#include "foo/bar.h") and a subsequent include of "baz.h"937  // should resolve to "whatever/foo/baz.h". This search is not done for <>938  // headers.939  if (!Includers.empty() && !isAngled) {940    SmallString<1024> TmpDir;941    bool First = true;942    for (const auto &IncluderAndDir : Includers) {943      OptionalFileEntryRef Includer = IncluderAndDir.first;944 945      // Concatenate the requested file onto the directory.946      TmpDir = IncluderAndDir.second.getName();947      llvm::sys::path::append(TmpDir, Filename);948 949      // FIXME: We don't cache the result of getFileInfo across the call to950      // getFileAndSuggestModule, because it's a reference to an element of951      // a container that could be reallocated across this call.952      //953      // If we have no includer, that means we're processing a #include954      // from a module build. We should treat this as a system header if we're955      // building a [system] module.956      bool IncluderIsSystemHeader = [&]() {957        if (!Includer)958          return BuildSystemModule;959        const HeaderFileInfo *HFI = getExistingFileInfo(*Includer);960        assert(HFI && "includer without file info");961        return HFI->DirInfo != SrcMgr::C_User;962      }();963      if (OptionalFileEntryRef FE = getFileAndSuggestModule(964              TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,965              RequestingModule, SuggestedModule)) {966        if (!Includer) {967          assert(First && "only first includer can have no file");968          return FE;969        }970 971        // Leave CurDir unset.972        // This file is a system header or C++ unfriendly if the old file is.973        //974        // Note that we only use one of FromHFI/ToHFI at once, due to potential975        // reallocation of the underlying vector potentially making the first976        // reference binding dangling.977        const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer);978        assert(FromHFI && "includer without file info");979        unsigned DirInfo = FromHFI->DirInfo;980 981        HeaderFileInfo &ToHFI = getFileInfo(*FE);982        ToHFI.DirInfo = DirInfo;983 984        if (SearchPath) {985          StringRef SearchPathRef(IncluderAndDir.second.getName());986          SearchPath->clear();987          SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());988        }989        if (RelativePath) {990          RelativePath->clear();991          RelativePath->append(Filename.begin(), Filename.end());992        }993        if (First) {994          diagnoseFrameworkInclude(Diags, IncludeLoc,995                                   IncluderAndDir.second.getName(), Filename,996                                   *FE);997          return FE;998        }999 1000        // Otherwise, we found the path via MSVC header search rules.  If1001        // -Wmsvc-include is enabled, we have to keep searching to see if we1002        // would've found this header in -I or -isystem directories.1003        if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {1004          return FE;1005        } else {1006          MSFE = FE;1007          if (SuggestedModule) {1008            MSSuggestedModule = *SuggestedModule;1009            *SuggestedModule = ModuleMap::KnownHeader();1010          }1011          break;1012        }1013      }1014      First = false;1015    }1016  }1017 1018  CurDir = nullptr;1019 1020  // If this is a system #include, ignore the user #include locs.1021  ConstSearchDirIterator It =1022      isAngled ? angled_dir_begin() : search_dir_begin();1023 1024  // If this is a #include_next request, start searching after the directory the1025  // file was found in.1026  if (FromDir)1027    It = FromDir;1028 1029  // Cache all of the lookups performed by this method.  Many headers are1030  // multiply included, and the "pragma once" optimization prevents them from1031  // being relex/pp'd, but they would still have to search through a1032  // (potentially huge) series of SearchDirs to find it.1033  LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];1034 1035  ConstSearchDirIterator NextIt = std::next(It);1036 1037  if (!SkipCache) {1038    if (CacheLookup.StartIt == NextIt &&1039        CacheLookup.RequestingModule == RequestingModule) {1040      // HIT: Skip querying potentially lots of directories for this lookup.1041      if (CacheLookup.HitIt)1042        It = CacheLookup.HitIt;1043      if (CacheLookup.MappedName) {1044        Filename = CacheLookup.MappedName;1045        if (IsMapped)1046          *IsMapped = true;1047      }1048    } else {1049      // MISS: This is the first query, or the previous query didn't match1050      // our search start.  We will fill in our found location below, so prime1051      // the start point value.1052      CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);1053 1054      if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {1055        // Handle cold misses of user includes in the presence of many header1056        // maps.  We avoid searching perhaps thousands of header maps by1057        // jumping directly to the correct one or jumping beyond all of them.1058        auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());1059        if (Iter == SearchDirHeaderMapIndex.end())1060          // Not in index => Skip to first SearchDir after initial header maps1061          It = search_dir_nth(FirstNonHeaderMapSearchDirIdx);1062        else1063          // In index => Start with a specific header map1064          It = search_dir_nth(Iter->second);1065      }1066    }1067  } else {1068    CacheLookup.reset(RequestingModule, /*NewStartIt=*/NextIt);1069  }1070 1071  SmallString<64> MappedName;1072 1073  // Check each directory in sequence to see if it contains this file.1074  for (; It != search_dir_end(); ++It) {1075    bool InUserSpecifiedSystemFramework = false;1076    bool IsInHeaderMap = false;1077    bool IsFrameworkFoundInDir = false;1078    OptionalFileEntryRef File = It->LookupFile(1079        Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,1080        SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,1081        IsInHeaderMap, MappedName, OpenFile);1082    if (!MappedName.empty()) {1083      assert(IsInHeaderMap && "MappedName should come from a header map");1084      CacheLookup.MappedName =1085          copyString(MappedName, LookupFileCache.getAllocator());1086    }1087    if (IsMapped)1088      // A filename is mapped when a header map remapped it to a relative path1089      // used in subsequent header search or to an absolute path pointing to an1090      // existing file.1091      *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));1092    if (IsFrameworkFound)1093      // Because we keep a filename remapped for subsequent search directory1094      // lookups, ignore IsFrameworkFoundInDir after the first remapping and not1095      // just for remapping in a current search directory.1096      *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);1097    if (!File)1098      continue;1099 1100    CurDir = It;1101 1102    IncludeNames[*File] = Filename;1103 1104    // This file is a system header or C++ unfriendly if the dir is.1105    HeaderFileInfo &HFI = getFileInfo(*File);1106    HFI.DirInfo = CurDir->getDirCharacteristic();1107 1108    // If the directory characteristic is User but this framework was1109    // user-specified to be treated as a system framework, promote the1110    // characteristic.1111    if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)1112      HFI.DirInfo = SrcMgr::C_System;1113 1114    // If the filename matches a known system header prefix, override1115    // whether the file is a system header.1116    for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {1117      if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {1118        HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System1119                                                       : SrcMgr::C_User;1120        break;1121      }1122    }1123 1124    if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) {1125      if (SuggestedModule)1126        *SuggestedModule = MSSuggestedModule;1127      return MSFE;1128    }1129 1130    bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;1131    if (!Includers.empty())1132      diagnoseFrameworkInclude(Diags, IncludeLoc,1133                               Includers.front().second.getName(), Filename,1134                               *File, isAngled, FoundByHeaderMap);1135 1136    // Remember this location for the next lookup we do.1137    cacheLookupSuccess(CacheLookup, It, IncludeLoc);1138    return File;1139  }1140 1141  if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {1142    if (SuggestedModule)1143      *SuggestedModule = MSSuggestedModule;1144    return MSFE;1145  }1146 1147  // Otherwise, didn't find it. Remember we didn't find this.1148  CacheLookup.HitIt = search_dir_end();1149  return std::nullopt;1150}1151 1152/// LookupSubframeworkHeader - Look up a subframework for the specified1153/// \#include file.  For example, if \#include'ing <HIToolbox/HIToolbox.h> from1154/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox1155/// is a subframework within Carbon.framework.  If so, return the FileEntry1156/// for the designated file, otherwise return null.1157OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(1158    StringRef Filename, FileEntryRef ContextFileEnt,1159    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,1160    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {1161  // Framework names must have a '/' in the filename.  Find it.1162  // FIXME: Should we permit '\' on Windows?1163  size_t SlashPos = Filename.find('/');1164  if (SlashPos == StringRef::npos)1165    return std::nullopt;1166 1167  // Look up the base framework name of the ContextFileEnt.1168  StringRef ContextName = ContextFileEnt.getName();1169 1170  // If the context info wasn't a framework, couldn't be a subframework.1171  const unsigned DotFrameworkLen = 10;1172  auto FrameworkPos = ContextName.find(".framework");1173  if (FrameworkPos == StringRef::npos ||1174      (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&1175       ContextName[FrameworkPos + DotFrameworkLen] != '\\'))1176    return std::nullopt;1177 1178  SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +1179                                                          FrameworkPos +1180                                                          DotFrameworkLen + 1);1181 1182  // Append Frameworks/HIToolbox.framework/1183  FrameworkName += "Frameworks/";1184  FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);1185  FrameworkName += ".framework/";1186 1187  auto &CacheLookup =1188      *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),1189                                          FrameworkCacheEntry())).first;1190 1191  // Some other location?1192  if (CacheLookup.second.Directory &&1193      CacheLookup.first().size() == FrameworkName.size() &&1194      memcmp(CacheLookup.first().data(), &FrameworkName[0],1195             CacheLookup.first().size()) != 0)1196    return std::nullopt;1197 1198  // Cache subframework.1199  if (!CacheLookup.second.Directory) {1200    ++NumSubFrameworkLookups;1201 1202    // If the framework dir doesn't exist, we fail.1203    auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);1204    if (!Dir)1205      return std::nullopt;1206 1207    // Otherwise, if it does, remember that this is the right direntry for this1208    // framework.1209    CacheLookup.second.Directory = Dir;1210  }1211 1212 1213  if (RelativePath) {1214    RelativePath->clear();1215    RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());1216  }1217 1218  // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h"1219  SmallString<1024> HeadersFilename(FrameworkName);1220  HeadersFilename += "Headers/";1221  if (SearchPath) {1222    SearchPath->clear();1223    // Without trailing '/'.1224    SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);1225  }1226 1227  HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());1228  auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);1229  if (!File) {1230    // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"1231    HeadersFilename = FrameworkName;1232    HeadersFilename += "PrivateHeaders/";1233    if (SearchPath) {1234      SearchPath->clear();1235      // Without trailing '/'.1236      SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);1237    }1238 1239    HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());1240    File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true);1241 1242    if (!File)1243      return std::nullopt;1244  }1245 1246  // This file is a system header or C++ unfriendly if the old file is.1247  const HeaderFileInfo *ContextHFI = getExistingFileInfo(ContextFileEnt);1248  assert(ContextHFI && "context file without file info");1249  // Note that the temporary 'DirInfo' is required here, as the call to1250  // getFileInfo could resize the vector and might invalidate 'ContextHFI'.1251  unsigned DirInfo = ContextHFI->DirInfo;1252  getFileInfo(*File).DirInfo = DirInfo;1253 1254  FrameworkName.pop_back(); // remove the trailing '/'1255  if (!findUsableModuleForFrameworkHeader(*File, FrameworkName,1256                                          RequestingModule, SuggestedModule,1257                                          /*IsSystem*/ false))1258    return std::nullopt;1259 1260  return *File;1261}1262 1263//===----------------------------------------------------------------------===//1264// File Info Management.1265//===----------------------------------------------------------------------===//1266 1267static bool moduleMembershipNeedsMerge(const HeaderFileInfo *HFI,1268                                       ModuleMap::ModuleHeaderRole Role) {1269  if (ModuleMap::isModular(Role))1270    return !HFI->isModuleHeader || HFI->isTextualModuleHeader;1271  if (!HFI->isModuleHeader && (Role & ModuleMap::TextualHeader))1272    return !HFI->isTextualModuleHeader;1273  return false;1274}1275 1276static void mergeHeaderFileInfoModuleBits(HeaderFileInfo &HFI,1277                                          bool isModuleHeader,1278                                          bool isTextualModuleHeader) {1279  HFI.isModuleHeader |= isModuleHeader;1280  if (HFI.isModuleHeader)1281    HFI.isTextualModuleHeader = false;1282  else1283    HFI.isTextualModuleHeader |= isTextualModuleHeader;1284}1285 1286void HeaderFileInfo::mergeModuleMembership(ModuleMap::ModuleHeaderRole Role) {1287  mergeHeaderFileInfoModuleBits(*this, ModuleMap::isModular(Role),1288                                (Role & ModuleMap::TextualHeader));1289}1290 1291/// Merge the header file info provided by \p OtherHFI into the current1292/// header file info (\p HFI)1293static void mergeHeaderFileInfo(HeaderFileInfo &HFI,1294                                const HeaderFileInfo &OtherHFI) {1295  assert(OtherHFI.External && "expected to merge external HFI");1296 1297  HFI.isImport |= OtherHFI.isImport;1298  HFI.isPragmaOnce |= OtherHFI.isPragmaOnce;1299  mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,1300                                OtherHFI.isTextualModuleHeader);1301 1302  if (!HFI.LazyControllingMacro.isValid())1303    HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;1304 1305  HFI.DirInfo = OtherHFI.DirInfo;1306  HFI.External = (!HFI.IsValid || HFI.External);1307  HFI.IsValid = true;1308}1309 1310HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {1311  if (FE.getUID() >= FileInfo.size())1312    FileInfo.resize(FE.getUID() + 1);1313 1314  HeaderFileInfo *HFI = &FileInfo[FE.getUID()];1315  // FIXME: Use a generation count to check whether this is really up to date.1316  if (ExternalSource && !HFI->Resolved) {1317    auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);1318    if (ExternalHFI.IsValid) {1319      HFI->Resolved = true;1320      if (ExternalHFI.External)1321        mergeHeaderFileInfo(*HFI, ExternalHFI);1322    }1323  }1324 1325  HFI->IsValid = true;1326  // We assume the caller has local information about this header file, so it's1327  // no longer strictly external.1328  HFI->External = false;1329  return *HFI;1330}1331 1332const HeaderFileInfo *HeaderSearch::getExistingFileInfo(FileEntryRef FE) const {1333  HeaderFileInfo *HFI;1334  if (ExternalSource) {1335    if (FE.getUID() >= FileInfo.size())1336      FileInfo.resize(FE.getUID() + 1);1337 1338    HFI = &FileInfo[FE.getUID()];1339    // FIXME: Use a generation count to check whether this is really up to date.1340    if (!HFI->Resolved) {1341      auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);1342      if (ExternalHFI.IsValid) {1343        HFI->Resolved = true;1344        if (ExternalHFI.External)1345          mergeHeaderFileInfo(*HFI, ExternalHFI);1346      }1347    }1348  } else if (FE.getUID() < FileInfo.size()) {1349    HFI = &FileInfo[FE.getUID()];1350  } else {1351    HFI = nullptr;1352  }1353 1354  return (HFI && HFI->IsValid) ? HFI : nullptr;1355}1356 1357const HeaderFileInfo *1358HeaderSearch::getExistingLocalFileInfo(FileEntryRef FE) const {1359  HeaderFileInfo *HFI;1360  if (FE.getUID() < FileInfo.size()) {1361    HFI = &FileInfo[FE.getUID()];1362  } else {1363    HFI = nullptr;1364  }1365 1366  return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr;1367}1368 1369bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {1370  // Check if we've entered this file and found an include guard or #pragma1371  // once. Note that we dor't check for #import, because that's not a property1372  // of the file itself.1373  if (auto *HFI = getExistingFileInfo(File))1374    return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();1375  return false;1376}1377 1378void HeaderSearch::MarkFileModuleHeader(FileEntryRef FE,1379                                        ModuleMap::ModuleHeaderRole Role,1380                                        bool isCompilingModuleHeader) {1381  // Don't mark the file info as non-external if there's nothing to change.1382  if (!isCompilingModuleHeader) {1383    if ((Role & ModuleMap::ExcludedHeader))1384      return;1385    auto *HFI = getExistingFileInfo(FE);1386    if (HFI && !moduleMembershipNeedsMerge(HFI, Role))1387      return;1388  }1389 1390  auto &HFI = getFileInfo(FE);1391  HFI.mergeModuleMembership(Role);1392  HFI.isCompilingModuleHeader |= isCompilingModuleHeader;1393}1394 1395bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,1396                                          FileEntryRef File, bool isImport,1397                                          bool ModulesEnabled, Module *M,1398                                          bool &IsFirstIncludeOfFile) {1399  // An include file should be entered if either:1400  // 1. This is the first include of the file.1401  // 2. This file can be included multiple times, that is it's not an1402  //    "include-once" file.1403  //1404  // Include-once is controlled by these preprocessor directives.1405  //1406  // #pragma once1407  // This directive is in the include file, and marks it as an include-once1408  // file.1409  //1410  // #import <file>1411  // This directive is in the includer, and indicates that the include file1412  // should only be entered if this is the first include.1413  ++NumIncluded;1414  IsFirstIncludeOfFile = false;1415  HeaderFileInfo &FileInfo = getFileInfo(File);1416 1417  auto MaybeReenterImportedFile = [&]() -> bool {1418    // Modules add a wrinkle though: what's included isn't necessarily visible.1419    // Consider this module.1420    // module Example {1421    //   module A { header "a.h" export * }1422    //   module B { header "b.h" export * }1423    // }1424    // b.h includes c.h. The main file includes a.h, which will trigger a module1425    // build of Example, and c.h will be included. However, c.h isn't visible to1426    // the main file. Normally this is fine, the main file can just include c.h1427    // if it needs it. If c.h is in a module, the include will translate into a1428    // module import, this function will be skipped, and everything will work as1429    // expected. However, if c.h is not in a module (or is `textual`), then this1430    // function will run. If c.h is include-once, it will not be entered from1431    // the main file and it will still not be visible.1432 1433    // If modules aren't enabled then there's no visibility issue. Always1434    // respect `#pragma once`.1435    if (!ModulesEnabled || FileInfo.isPragmaOnce)1436      return false;1437 1438    // Ensure FileInfo bits are up to date.1439    ModMap.resolveHeaderDirectives(File);1440 1441    // This brings up a subtlety of #import - it's not a very good indicator of1442    // include-once. Developers are often unaware of the difference between1443    // #include and #import, and tend to use one or the other indiscrimiately.1444    // In order to support #include on include-once headers that lack macro1445    // guards and `#pragma once` (which is the vast majority of Objective-C1446    // headers), if a file is ever included with #import, it's marked as1447    // isImport in the HeaderFileInfo and treated as include-once. This allows1448    // #include to work in Objective-C.1449    // #include <Foundation/Foundation.h>1450    // #include <Foundation/NSString.h>1451    // Foundation.h has an #import of NSString.h, and so the second #include is1452    // skipped even though NSString.h has no `#pragma once` and no macro guard.1453    //1454    // However, this helpfulness causes problems with modules. If c.h is not an1455    // include-once file, but something included it with #import anyway (as is1456    // typical in Objective-C code), this include will be skipped and c.h will1457    // not be visible. Consider it not include-once if it is a `textual` header1458    // in a module.1459    if (FileInfo.isTextualModuleHeader)1460      return true;1461 1462    if (FileInfo.isCompilingModuleHeader) {1463      // It's safer to re-enter a file whose module is being built because its1464      // declarations will still be scoped to a single module.1465      if (FileInfo.isModuleHeader) {1466        // Headers marked as "builtin" are covered by the system module maps1467        // rather than the builtin ones. Some versions of the Darwin module fail1468        // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these1469        // files while building their module to allow them to function properly.1470        if (ModMap.isBuiltinHeader(File))1471          return true;1472      } else {1473        // Files that are excluded from their module can potentially be1474        // re-entered from their own module. This might cause redeclaration1475        // errors if another module saw this file first, but there's a1476        // reasonable chance that its module will build first. However if1477        // there's no controlling macro, then trust the #import and assume this1478        // really is an include-once file.1479        if (FileInfo.getControllingMacro(ExternalLookup))1480          return true;1481      }1482    }1483    // If the include file has a macro guard, then it might still not be1484    // re-entered if the controlling macro is visibly defined. e.g. another1485    // header in the module being built included this file and local submodule1486    // visibility is not enabled.1487 1488    // It might be tempting to re-enter the include-once file if it's not1489    // visible in an attempt to make it visible. However this will still cause1490    // redeclaration errors against the known-but-not-visible declarations. The1491    // include file not being visible will most likely cause "undefined x"1492    // errors, but at least there's a slim chance of compilation succeeding.1493    return false;1494  };1495 1496  if (isImport) {1497    // As discussed above, record that this file was ever `#import`ed, and treat1498    // it as an include-once file from here out.1499    FileInfo.isImport = true;1500    if (PP.alreadyIncluded(File) && !MaybeReenterImportedFile())1501      return false;1502  } else {1503    // isPragmaOnce and isImport are only set after the file has been included1504    // at least once. If either are set then this is a repeat #include of an1505    // include-once file.1506    if (FileInfo.isPragmaOnce ||1507        (FileInfo.isImport && !MaybeReenterImportedFile()))1508      return false;1509  }1510 1511  // As a final optimization, check for a macro guard and skip entering the file1512  // if the controlling macro is defined. The macro guard will effectively erase1513  // the file's contents, and the include would have no effect other than to1514  // waste time opening and reading a file.1515  if (const IdentifierInfo *ControllingMacro =1516          FileInfo.getControllingMacro(ExternalLookup)) {1517    // If the header corresponds to a module, check whether the macro is already1518    // defined in that module rather than checking all visible modules. This is1519    // mainly to cover corner cases where the same controlling macro is used in1520    // different files in multiple modules.1521    if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)1522          : PP.isMacroDefined(ControllingMacro)) {1523      ++NumMultiIncludeFileOptzn;1524      return false;1525    }1526  }1527 1528  IsFirstIncludeOfFile = PP.markIncluded(File);1529  return true;1530}1531 1532size_t HeaderSearch::getTotalMemory() const {1533  return SearchDirs.capacity()1534    + llvm::capacity_in_bytes(FileInfo)1535    + llvm::capacity_in_bytes(HeaderMaps)1536    + LookupFileCache.getAllocator().getTotalMemory()1537    + FrameworkMap.getAllocator().getTotalMemory();1538}1539 1540unsigned HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {1541  return &DL - &*SearchDirs.begin();1542}1543 1544StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {1545  return FrameworkNames.insert(Framework).first->first();1546}1547 1548StringRef HeaderSearch::getIncludeNameForHeader(const FileEntry *File) const {1549  auto It = IncludeNames.find(File);1550  if (It == IncludeNames.end())1551    return {};1552  return It->second;1553}1554 1555bool HeaderSearch::hasModuleMap(StringRef FileName,1556                                const DirectoryEntry *Root,1557                                bool IsSystem) {1558  if (!HSOpts.ImplicitModuleMaps)1559    return false;1560 1561  SmallVector<DirectoryEntryRef, 2> FixUpDirectories;1562 1563  StringRef DirName = FileName;1564  do {1565    // Get the parent directory name.1566    DirName = llvm::sys::path::parent_path(DirName);1567    if (DirName.empty())1568      return false;1569 1570    // Determine whether this directory exists.1571    auto Dir = FileMgr.getOptionalDirectoryRef(DirName);1572    if (!Dir)1573      return false;1574 1575    // Try to load the module map file in this directory.1576    switch (parseAndLoadModuleMapFile(1577        *Dir, IsSystem,1578        llvm::sys::path::extension(Dir->getName()) == ".framework")) {1579    case MMR_NewlyProcessed:1580    case MMR_AlreadyProcessed: {1581      // Success. All of the directories we stepped through inherit this module1582      // map file.1583      const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];1584      for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)1585        DirectoryModuleMap[FixUpDirectories[I]] = MMDS;1586      return true;1587    }1588    case MMR_NoDirectory:1589    case MMR_InvalidModuleMap:1590      break;1591    }1592 1593    // If we hit the top of our search, we're done.1594    if (*Dir == Root)1595      return false;1596 1597    // Keep track of all of the directories we checked, so we can mark them as1598    // having module maps if we eventually do find a module map.1599    FixUpDirectories.push_back(*Dir);1600  } while (true);1601}1602 1603ModuleMap::KnownHeader1604HeaderSearch::findModuleForHeader(FileEntryRef File, bool AllowTextual,1605                                  bool AllowExcluded) const {1606  if (ExternalSource) {1607    // Make sure the external source has handled header info about this file,1608    // which includes whether the file is part of a module.1609    (void)getExistingFileInfo(File);1610  }1611  return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded);1612}1613 1614ArrayRef<ModuleMap::KnownHeader>1615HeaderSearch::findAllModulesForHeader(FileEntryRef File) const {1616  if (ExternalSource) {1617    // Make sure the external source has handled header info about this file,1618    // which includes whether the file is part of a module.1619    (void)getExistingFileInfo(File);1620  }1621  return ModMap.findAllModulesForHeader(File);1622}1623 1624ArrayRef<ModuleMap::KnownHeader>1625HeaderSearch::findResolvedModulesForHeader(FileEntryRef File) const {1626  if (ExternalSource) {1627    // Make sure the external source has handled header info about this file,1628    // which includes whether the file is part of a module.1629    (void)getExistingFileInfo(File);1630  }1631  return ModMap.findResolvedModulesForHeader(File);1632}1633 1634static bool suggestModule(HeaderSearch &HS, FileEntryRef File,1635                          Module *RequestingModule,1636                          ModuleMap::KnownHeader *SuggestedModule) {1637  ModuleMap::KnownHeader Module =1638      HS.findModuleForHeader(File, /*AllowTextual*/true);1639 1640  // If this module specifies [no_undeclared_includes], we cannot find any1641  // file that's in a non-dependency module.1642  if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {1643    HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/ false);1644    if (!RequestingModule->directlyUses(Module.getModule())) {1645      // Builtin headers are a special case. Multiple modules can use the same1646      // builtin as a modular header (see also comment in1647      // ShouldEnterIncludeFile()), so the builtin header may have been1648      // "claimed" by an unrelated module. This shouldn't prevent us from1649      // including the builtin header textually in this module.1650      if (HS.getModuleMap().isBuiltinHeader(File)) {1651        if (SuggestedModule)1652          *SuggestedModule = ModuleMap::KnownHeader();1653        return true;1654      }1655      // TODO: Add this module (or just its module map file) into something like1656      // `RequestingModule->AffectingClangModules`.1657      return false;1658    }1659  }1660 1661  if (SuggestedModule)1662    *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)1663                           ? ModuleMap::KnownHeader()1664                           : Module;1665 1666  return true;1667}1668 1669bool HeaderSearch::findUsableModuleForHeader(1670    FileEntryRef File, const DirectoryEntry *Root, Module *RequestingModule,1671    ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {1672  if (needModuleLookup(RequestingModule, SuggestedModule)) {1673    // If there is a module that corresponds to this header, suggest it.1674    hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);1675    return suggestModule(*this, File, RequestingModule, SuggestedModule);1676  }1677  return true;1678}1679 1680bool HeaderSearch::findUsableModuleForFrameworkHeader(1681    FileEntryRef File, StringRef FrameworkName, Module *RequestingModule,1682    ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {1683  // If we're supposed to suggest a module, look for one now.1684  if (needModuleLookup(RequestingModule, SuggestedModule)) {1685    // Find the top-level framework based on this framework.1686    SmallVector<std::string, 4> SubmodulePath;1687    OptionalDirectoryEntryRef TopFrameworkDir =1688        ::getTopFrameworkDir(FileMgr, FrameworkName, SubmodulePath);1689    assert(TopFrameworkDir && "Could not find the top-most framework dir");1690 1691    // Determine the name of the top-level framework.1692    StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());1693 1694    // Load this framework module. If that succeeds, find the suggested module1695    // for this header, if any.1696    loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);1697 1698    // FIXME: This can find a module not part of ModuleName, which is1699    // important so that we're consistent about whether this header1700    // corresponds to a module. Possibly we should lock down framework modules1701    // so that this is not possible.1702    return suggestModule(*this, File, RequestingModule, SuggestedModule);1703  }1704  return true;1705}1706 1707static OptionalFileEntryRef getPrivateModuleMap(FileEntryRef File,1708                                                FileManager &FileMgr,1709                                                DiagnosticsEngine &Diags,1710                                                bool Diagnose = true) {1711  StringRef Filename = llvm::sys::path::filename(File.getName());1712  SmallString<128>  PrivateFilename(File.getDir().getName());1713  if (Filename == "module.map")1714    llvm::sys::path::append(PrivateFilename, "module_private.map");1715  else if (Filename == "module.modulemap")1716    llvm::sys::path::append(PrivateFilename, "module.private.modulemap");1717  else1718    return std::nullopt;1719  auto PMMFile = FileMgr.getOptionalFileRef(PrivateFilename);1720  if (PMMFile) {1721    if (Diagnose && Filename == "module.map")1722      Diags.Report(diag::warn_deprecated_module_dot_map)1723          << PrivateFilename << 11724          << File.getDir().getName().ends_with(".framework");1725  }1726  return PMMFile;1727}1728 1729bool HeaderSearch::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,1730                                             FileID ID, unsigned *Offset,1731                                             StringRef OriginalModuleMapFile) {1732  // Find the directory for the module. For frameworks, that may require going1733  // up from the 'Modules' directory.1734  OptionalDirectoryEntryRef Dir;1735  if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) {1736    Dir = FileMgr.getOptionalDirectoryRef(".");1737  } else {1738    if (!OriginalModuleMapFile.empty()) {1739      // We're building a preprocessed module map. Find or invent the directory1740      // that it originally occupied.1741      Dir = FileMgr.getOptionalDirectoryRef(1742          llvm::sys::path::parent_path(OriginalModuleMapFile));1743      if (!Dir) {1744        auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);1745        Dir = FakeFile.getDir();1746      }1747    } else {1748      Dir = File.getDir();1749    }1750 1751    assert(Dir && "parent must exist");1752    StringRef DirName(Dir->getName());1753    if (llvm::sys::path::filename(DirName) == "Modules") {1754      DirName = llvm::sys::path::parent_path(DirName);1755      if (DirName.ends_with(".framework"))1756        if (auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))1757          Dir = *MaybeDir;1758      // FIXME: This assert can fail if there's a race between the above check1759      // and the removal of the directory.1760      assert(Dir && "parent must exist");1761    }1762  }1763 1764  assert(Dir && "module map home directory must exist");1765  switch (parseAndLoadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) {1766  case MMR_AlreadyProcessed:1767  case MMR_NewlyProcessed:1768    return false;1769  case MMR_NoDirectory:1770  case MMR_InvalidModuleMap:1771    return true;1772  }1773  llvm_unreachable("Unknown load module map result");1774}1775 1776HeaderSearch::ModuleMapResult1777HeaderSearch::parseAndLoadModuleMapFileImpl(FileEntryRef File, bool IsSystem,1778                                            DirectoryEntryRef Dir, FileID ID,1779                                            unsigned *Offset) {1780  // Check whether we've already loaded this module map, and mark it as being1781  // loaded in case we recursively try to load it from itself.1782  auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));1783  if (!AddResult.second)1784    return AddResult.first->second ? MMR_AlreadyProcessed1785                                   : MMR_InvalidModuleMap;1786 1787  if (ModMap.parseAndLoadModuleMapFile(File, IsSystem, Dir, ID, Offset)) {1788    LoadedModuleMaps[File] = false;1789    return MMR_InvalidModuleMap;1790  }1791 1792  // Try to load a corresponding private module map.1793  if (OptionalFileEntryRef PMMFile =1794          getPrivateModuleMap(File, FileMgr, Diags, !ParsedModuleMaps[File])) {1795    if (ModMap.parseAndLoadModuleMapFile(*PMMFile, IsSystem, Dir)) {1796      LoadedModuleMaps[File] = false;1797      return MMR_InvalidModuleMap;1798    }1799  }1800 1801  // This directory has a module map.1802  return MMR_NewlyProcessed;1803}1804 1805HeaderSearch::ModuleMapResult1806HeaderSearch::parseModuleMapFileImpl(FileEntryRef File, bool IsSystem,1807                                     DirectoryEntryRef Dir, FileID ID) {1808  // Check whether we've already parsed this module map, and mark it as being1809  // parsed in case we recursively try to parse it from itself.1810  auto AddResult = ParsedModuleMaps.insert(std::make_pair(File, true));1811  if (!AddResult.second)1812    return AddResult.first->second ? MMR_AlreadyProcessed1813                                   : MMR_InvalidModuleMap;1814 1815  if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID)) {1816    ParsedModuleMaps[File] = false;1817    return MMR_InvalidModuleMap;1818  }1819 1820  // Try to parse a corresponding private module map.1821  if (OptionalFileEntryRef PMMFile =1822          getPrivateModuleMap(File, FileMgr, Diags)) {1823    if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {1824      ParsedModuleMaps[File] = false;1825      return MMR_InvalidModuleMap;1826    }1827  }1828 1829  // This directory has a module map.1830  return MMR_NewlyProcessed;1831}1832 1833OptionalFileEntryRef1834HeaderSearch::lookupModuleMapFile(DirectoryEntryRef Dir, bool IsFramework) {1835  if (!HSOpts.ImplicitModuleMaps)1836    return std::nullopt;1837  // For frameworks, the preferred spelling is Modules/module.modulemap, but1838  // module.map at the framework root is also accepted.1839  SmallString<128> ModuleMapFileName(Dir.getName());1840  if (IsFramework)1841    llvm::sys::path::append(ModuleMapFileName, "Modules");1842  llvm::sys::path::append(ModuleMapFileName, "module.modulemap");1843  if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))1844    return *F;1845 1846  // Continue to allow module.map, but warn it's deprecated.1847  ModuleMapFileName = Dir.getName();1848  llvm::sys::path::append(ModuleMapFileName, "module.map");1849  if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {1850    Diags.Report(diag::warn_deprecated_module_dot_map)1851        << ModuleMapFileName << 0 << IsFramework;1852    return *F;1853  }1854 1855  // For frameworks, allow to have a private module map with a preferred1856  // spelling when a public module map is absent.1857  if (IsFramework) {1858    ModuleMapFileName = Dir.getName();1859    llvm::sys::path::append(ModuleMapFileName, "Modules",1860                            "module.private.modulemap");1861    if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))1862      return *F;1863  }1864  return std::nullopt;1865}1866 1867Module *HeaderSearch::loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,1868                                          bool IsSystem) {1869  // Try to load a module map file.1870  switch (parseAndLoadModuleMapFile(Dir, IsSystem, /*IsFramework*/ true)) {1871  case MMR_InvalidModuleMap:1872    // Try to infer a module map from the framework directory.1873    if (HSOpts.ImplicitModuleMaps)1874      ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);1875    break;1876 1877  case MMR_NoDirectory:1878    return nullptr;1879 1880  case MMR_AlreadyProcessed:1881  case MMR_NewlyProcessed:1882    break;1883  }1884 1885  return ModMap.findOrLoadModule(Name);1886}1887 1888HeaderSearch::ModuleMapResult1889HeaderSearch::parseAndLoadModuleMapFile(StringRef DirName, bool IsSystem,1890                                        bool IsFramework) {1891  if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))1892    return parseAndLoadModuleMapFile(*Dir, IsSystem, IsFramework);1893 1894  return MMR_NoDirectory;1895}1896 1897HeaderSearch::ModuleMapResult1898HeaderSearch::parseAndLoadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,1899                                        bool IsFramework) {1900  auto InsertRes = DirectoryModuleMap.insert(std::pair{1901      Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});1902  ModuleMapDirectoryState &MMState = InsertRes.first->second;1903  if (!InsertRes.second) {1904    switch (MMState.Status) {1905    case ModuleMapDirectoryState::Parsed:1906      break;1907    case ModuleMapDirectoryState::Loaded:1908      return MMR_AlreadyProcessed;1909    case ModuleMapDirectoryState::Invalid:1910      return MMR_InvalidModuleMap;1911    };1912  }1913 1914  if (!MMState.ModuleMapFile)1915    MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);1916 1917  if (MMState.ModuleMapFile) {1918    ModuleMapResult Result =1919        parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);1920    // Add Dir explicitly in case ModuleMapFile is in a subdirectory.1921    // E.g. Foo.framework/Modules/module.modulemap1922    //      ^Dir                  ^ModuleMapFile1923    if (Result == MMR_NewlyProcessed)1924      MMState.Status = ModuleMapDirectoryState::Loaded;1925    else if (Result == MMR_InvalidModuleMap)1926      MMState.Status = ModuleMapDirectoryState::Invalid;1927    return Result;1928  }1929  return MMR_InvalidModuleMap;1930}1931 1932HeaderSearch::ModuleMapResult1933HeaderSearch::parseModuleMapFile(StringRef DirName, bool IsSystem,1934                                 bool IsFramework) {1935  if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))1936    return parseModuleMapFile(*Dir, IsSystem, IsFramework);1937 1938  return MMR_NoDirectory;1939}1940 1941HeaderSearch::ModuleMapResult1942HeaderSearch::parseModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,1943                                 bool IsFramework) {1944  auto InsertRes = DirectoryModuleMap.insert(std::pair{1945      Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});1946  ModuleMapDirectoryState &MMState = InsertRes.first->second;1947  if (!InsertRes.second) {1948    switch (MMState.Status) {1949    case ModuleMapDirectoryState::Parsed:1950    case ModuleMapDirectoryState::Loaded:1951      return MMR_AlreadyProcessed;1952    case ModuleMapDirectoryState::Invalid:1953      return MMR_InvalidModuleMap;1954    };1955  }1956 1957  if (!MMState.ModuleMapFile)1958    MMState.ModuleMapFile = lookupModuleMapFile(Dir, IsFramework);1959 1960  if (MMState.ModuleMapFile) {1961    ModuleMapResult Result =1962        parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);1963    // Add Dir explicitly in case ModuleMapFile is in a subdirectory.1964    // E.g. Foo.framework/Modules/module.modulemap1965    //      ^Dir                  ^ModuleMapFile1966    if (Result == MMR_NewlyProcessed)1967      MMState.Status = ModuleMapDirectoryState::Parsed;1968    else if (Result == MMR_InvalidModuleMap)1969      MMState.Status = ModuleMapDirectoryState::Invalid;1970    return Result;1971  }1972  return MMR_InvalidModuleMap;1973}1974 1975void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {1976  Modules.clear();1977 1978  if (HSOpts.ImplicitModuleMaps) {1979    // Load module maps for each of the header search directories.1980    for (DirectoryLookup &DL : search_dir_range()) {1981      bool IsSystem = DL.isSystemHeaderDirectory();1982      if (DL.isFramework()) {1983        std::error_code EC;1984        SmallString<128> DirNative;1985        llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);1986 1987        // Search each of the ".framework" directories to load them as modules.1988        llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();1989        for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),1990                                           DirEnd;1991             Dir != DirEnd && !EC; Dir.increment(EC)) {1992          if (llvm::sys::path::extension(Dir->path()) != ".framework")1993            continue;1994 1995          auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());1996          if (!FrameworkDir)1997            continue;1998 1999          // Load this framework module.2000          loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,2001                              IsSystem);2002        }2003        continue;2004      }2005 2006      // FIXME: Deal with header maps.2007      if (DL.isHeaderMap())2008        continue;2009 2010      // Try to load a module map file for the search directory.2011      parseAndLoadModuleMapFile(*DL.getDirRef(), IsSystem,2012                                /*IsFramework*/ false);2013 2014      // Try to load module map files for immediate subdirectories of this2015      // search directory.2016      loadSubdirectoryModuleMaps(DL);2017    }2018  }2019 2020  // Populate the list of modules.2021  llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));2022}2023 2024void HeaderSearch::loadTopLevelSystemModules() {2025  if (!HSOpts.ImplicitModuleMaps)2026    return;2027 2028  // Load module maps for each of the header search directories.2029  for (const DirectoryLookup &DL : search_dir_range()) {2030    // We only care about normal header directories.2031    if (!DL.isNormalDir())2032      continue;2033 2034    // Try to load a module map file for the search directory.2035    parseAndLoadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(),2036                              DL.isFramework());2037  }2038}2039 2040void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {2041  assert(HSOpts.ImplicitModuleMaps &&2042         "Should not be loading subdirectory module maps");2043 2044  if (SearchDir.haveSearchedAllModuleMaps())2045    return;2046 2047  std::error_code EC;2048  SmallString<128> Dir = SearchDir.getDirRef()->getName();2049  FileMgr.makeAbsolutePath(Dir);2050  SmallString<128> DirNative;2051  llvm::sys::path::native(Dir, DirNative);2052  llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();2053  for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;2054       Dir != DirEnd && !EC; Dir.increment(EC)) {2055    if (Dir->type() == llvm::sys::fs::file_type::regular_file)2056      continue;2057    bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";2058    if (IsFramework == SearchDir.isFramework())2059      parseAndLoadModuleMapFile(Dir->path(),2060                                SearchDir.isSystemHeaderDirectory(),2061                                SearchDir.isFramework());2062  }2063 2064  SearchDir.setSearchedAllModuleMaps(true);2065}2066 2067std::string HeaderSearch::suggestPathToFileForDiagnostics(2068    FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {2069  return suggestPathToFileForDiagnostics(File.getName(), /*WorkingDir=*/"",2070                                         MainFile, IsAngled);2071}2072 2073std::string HeaderSearch::suggestPathToFileForDiagnostics(2074    llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,2075    bool *IsAngled) const {2076  using namespace llvm::sys;2077 2078  llvm::SmallString<32> FilePath = File;2079  if (!WorkingDir.empty() && !path::is_absolute(FilePath))2080    path::make_absolute(WorkingDir, FilePath);2081  // remove_dots switches to backslashes on windows as a side-effect!2082  // We always want to suggest forward slashes for includes.2083  // (not remove_dots(..., posix) as that misparses windows paths).2084  path::remove_dots(FilePath, /*remove_dot_dot=*/true);2085  path::native(FilePath, path::Style::posix);2086  File = FilePath;2087 2088  unsigned BestPrefixLength = 0;2089  // Checks whether `Dir` is a strict path prefix of `File`. If so and that's2090  // the longest prefix we've seen so for it, returns true and updates the2091  // `BestPrefixLength` accordingly.2092  auto CheckDir = [&](llvm::SmallString<32> Dir) -> bool {2093    if (!WorkingDir.empty() && !path::is_absolute(Dir))2094      path::make_absolute(WorkingDir, Dir);2095    path::remove_dots(Dir, /*remove_dot_dot=*/true);2096    for (auto NI = path::begin(File), NE = path::end(File),2097              DI = path::begin(Dir), DE = path::end(Dir);2098         NI != NE; ++NI, ++DI) {2099      if (DI == DE) {2100        // Dir is a prefix of File, up to choice of path separators.2101        unsigned PrefixLength = NI - path::begin(File);2102        if (PrefixLength > BestPrefixLength) {2103          BestPrefixLength = PrefixLength;2104          return true;2105        }2106        break;2107      }2108 2109      // Consider all path separators equal.2110      if (NI->size() == 1 && DI->size() == 1 &&2111          path::is_separator(NI->front()) && path::is_separator(DI->front()))2112        continue;2113 2114      // Special case Apple .sdk folders since the search path is typically a2115      // symlink like `iPhoneSimulator14.5.sdk` while the file is instead2116      // located in `iPhoneSimulator.sdk` (the real folder).2117      if (NI->ends_with(".sdk") && DI->ends_with(".sdk")) {2118        StringRef NBasename = path::stem(*NI);2119        StringRef DBasename = path::stem(*DI);2120        if (DBasename.starts_with(NBasename))2121          continue;2122      }2123 2124      if (*NI != *DI)2125        break;2126    }2127    return false;2128  };2129 2130  bool BestPrefixIsFramework = false;2131  for (const DirectoryLookup &DL : search_dir_range()) {2132    if (DL.isNormalDir()) {2133      StringRef Dir = DL.getDirRef()->getName();2134      if (CheckDir(Dir)) {2135        if (IsAngled)2136          *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());2137        BestPrefixIsFramework = false;2138      }2139    } else if (DL.isFramework()) {2140      StringRef Dir = DL.getFrameworkDirRef()->getName();2141      if (CheckDir(Dir)) {2142        // Framework includes by convention use <>.2143        if (IsAngled)2144          *IsAngled = BestPrefixLength;2145        BestPrefixIsFramework = true;2146      }2147    }2148  }2149 2150  // Try to shorten include path using TUs directory, if we couldn't find any2151  // suitable prefix in include search paths.2152  if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {2153    if (IsAngled)2154      *IsAngled = false;2155    BestPrefixIsFramework = false;2156  }2157 2158  // Try resolving resulting filename via reverse search in header maps,2159  // key from header name is user preferred name for the include file.2160  StringRef Filename = File.drop_front(BestPrefixLength);2161  for (const DirectoryLookup &DL : search_dir_range()) {2162    if (!DL.isHeaderMap())2163      continue;2164 2165    StringRef SpelledFilename =2166        DL.getHeaderMap()->reverseLookupFilename(Filename);2167    if (!SpelledFilename.empty()) {2168      Filename = SpelledFilename;2169      BestPrefixIsFramework = false;2170      break;2171    }2172  }2173 2174  // If the best prefix is a framework path, we need to compute the proper2175  // include spelling for the framework header.2176  bool IsPrivateHeader;2177  SmallString<128> FrameworkName, IncludeSpelling;2178  if (BestPrefixIsFramework &&2179      isFrameworkStylePath(Filename, IsPrivateHeader, FrameworkName,2180                           IncludeSpelling)) {2181    Filename = IncludeSpelling;2182  }2183  return path::convert_to_slash(Filename);2184}2185 2186void clang::normalizeModuleCachePath(FileManager &FileMgr, StringRef Path,2187                                     SmallVectorImpl<char> &NormalizedPath) {2188  NormalizedPath.assign(Path.begin(), Path.end());2189  if (!NormalizedPath.empty()) {2190    FileMgr.makeAbsolutePath(NormalizedPath);2191    llvm::sys::path::remove_dots(NormalizedPath);2192  }2193}2194