diff options
Diffstat (limited to 'lib/Lex/HeaderSearch.cpp')
| -rw-r--r-- | lib/Lex/HeaderSearch.cpp | 348 | 
1 files changed, 203 insertions, 145 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 108630cc26f6..f0c5900c8ce4 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -27,9 +27,11 @@  #include "llvm/ADT/Hashing.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" @@ -45,6 +47,16 @@  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 (ControllingMacro) { @@ -75,8 +87,8 @@ HeaderSearch::HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,        ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}  void HeaderSearch::PrintStats() { -  fprintf(stderr, "\n*** HeaderSearch Stats:\n"); -  fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size()); +  llvm::errs() << "\n*** HeaderSearch Stats:\n" +               << FileInfo.size() << " files tracked.\n";    unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0;    for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) {      NumOnceOnlyFiles += FileInfo[i].isImport; @@ -84,16 +96,16 @@ void HeaderSearch::PrintStats() {        MaxNumIncludes = FileInfo[i].NumIncludes;      NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1;    } -  fprintf(stderr, "  %d #import/#pragma once files.\n", NumOnceOnlyFiles); -  fprintf(stderr, "  %d included exactly once.\n", NumSingleIncludedFiles); -  fprintf(stderr, "  %d max times a file is included.\n", MaxNumIncludes); +  llvm::errs() << "  " << NumOnceOnlyFiles << " #import/#pragma once files.\n" +               << "  " << NumSingleIncludedFiles << " included exactly once.\n" +               << "  " << MaxNumIncludes << " max times a file is included.\n"; -  fprintf(stderr, "  %d #include/#include_next/#import.\n", NumIncluded); -  fprintf(stderr, "    %d #includes skipped due to" -          " the multi-include optimization.\n", NumMultiIncludeFileOptzn); +  llvm::errs() << "  " << NumIncluded << " #include/#include_next/#import.\n" +               << "    " << NumMultiIncludeFileOptzn +               << " #includes skipped due to the multi-include optimization.\n"; -  fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups); -  fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups); +  llvm::errs() << NumFrameworkLookups << " framework lookups.\n" +               << NumSubFrameworkLookups << " subframework lookups.\n";  }  /// CreateHeaderMap - This method returns a HeaderMap for the specified @@ -175,10 +187,10 @@ std::string HeaderSearch::getCachedModuleFileName(StringRef ModuleName,      std::string Parent = llvm::sys::path::parent_path(ModuleMapPath);      if (Parent.empty())        Parent = "."; -    auto *Dir = FileMgr.getDirectory(Parent); +    auto Dir = FileMgr.getDirectory(Parent);      if (!Dir)        return {}; -    auto DirName = FileMgr.getCanonicalName(Dir); +    auto DirName = FileMgr.getCanonicalName(*Dir);      auto FileName = llvm::sys::path::filename(ModuleMapPath);      llvm::hash_code Hash = @@ -230,11 +242,10 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,        SmallString<128> FrameworkDirName;        FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();        llvm::sys::path::append(FrameworkDirName, SearchName + ".framework"); -      if (const DirectoryEntry *FrameworkDir -            = FileMgr.getDirectory(FrameworkDirName)) { +      if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) {          bool IsSystem            = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User; -        Module = loadFrameworkModule(ModuleName, FrameworkDir, IsSystem); +        Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);          if (Module)            break;        } @@ -296,6 +307,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName,  /// getName - Return the directory or filename corresponding to this lookup  /// object.  StringRef DirectoryLookup::getName() const { +  // FIXME: Use the name from \c DirectoryEntryRef.    if (isNormalDir())      return getDir()->getName();    if (isFramework()) @@ -304,41 +316,46 @@ StringRef DirectoryLookup::getName() const {    return getHeaderMap()->getFileName();  } -const FileEntry *HeaderSearch::getFileAndSuggestModule( +Optional<FileEntryRef> HeaderSearch::getFileAndSuggestModule(      StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,      bool IsSystemHeaderDir, Module *RequestingModule,      ModuleMap::KnownHeader *SuggestedModule) {    // If we have a module map that might map this header, load it and    // check whether we'll have a suggestion for a module. -  const FileEntry *File = getFileMgr().getFile(FileName, /*OpenFile=*/true); -  if (!File) -    return nullptr; +  auto File = getFileMgr().getFileRef(FileName, /*OpenFile=*/true); +  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 None; +  }    // If there is a module that corresponds to this header, suggest it. -  if (!findUsableModuleForHeader(File, Dir ? Dir : File->getDir(), -                                 RequestingModule, SuggestedModule, -                                 IsSystemHeaderDir)) -    return nullptr; +  if (!findUsableModuleForHeader( +          &File->getFileEntry(), Dir ? Dir : File->getFileEntry().getDir(), +          RequestingModule, SuggestedModule, IsSystemHeaderDir)) +    return None; -  return File; +  return *File;  }  /// LookupFile - Lookup the specified file in this search path, returning it  /// if it exists or returning null if not. -const FileEntry *DirectoryLookup::LookupFile( -    StringRef &Filename, -    HeaderSearch &HS, -    SourceLocation IncludeLoc, -    SmallVectorImpl<char> *SearchPath, -    SmallVectorImpl<char> *RelativePath, -    Module *RequestingModule, -    ModuleMap::KnownHeader *SuggestedModule, -    bool &InUserSpecifiedSystemFramework, -    bool &IsFrameworkFound, -    bool &HasBeenMapped, -    SmallVectorImpl<char> &MappedName) const { +Optional<FileEntryRef> 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) const {    InUserSpecifiedSystemFramework = false; -  HasBeenMapped = false; +  IsInHeaderMap = false; +  MappedName.clear();    SmallString<1024> TmpDir;    if (isNormalDir()) { @@ -370,24 +387,11 @@ const FileEntry *DirectoryLookup::LookupFile(    SmallString<1024> Path;    StringRef Dest = HM->lookupFilename(Filename, Path);    if (Dest.empty()) -    return nullptr; +    return None; -  const FileEntry *Result; - -  // 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.clear(); -    MappedName.append(Dest.begin(), Dest.end()); -    Filename = StringRef(MappedName.begin(), MappedName.size()); -    HasBeenMapped = true; -    Result = HM->LookupFile(Filename, HS.getFileMgr()); -  } else { -    Result = HS.getFileMgr().getFile(Dest); -  } +  IsInHeaderMap = true; -  if (Result) { +  auto FixupSearchPath = [&]() {      if (SearchPath) {        StringRef SearchPathRef(getName());        SearchPath->clear(); @@ -397,8 +401,25 @@ const FileEntry *DirectoryLookup::LookupFile(        RelativePath->clear();        RelativePath->append(Filename.begin(), Filename.end());      } +  }; + +  // 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()); +    Optional<FileEntryRef> Result = HM->LookupFile(Filename, HS.getFileMgr()); +    if (Result) { +      FixupSearchPath(); +      return *Result; +    } +  } else if (auto Res = HS.getFileMgr().getOptionalFileRef(Dest)) { +    FixupSearchPath(); +    return *Res;    } -  return Result; + +  return None;  }  /// Given a framework directory, find the top-most framework directory. @@ -427,8 +448,12 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,    //    // Similar issues occur when a top-level framework has moved into an    // embedded framework. -  const DirectoryEntry *TopFrameworkDir = FileMgr.getDirectory(DirName); -  DirName = FileMgr.getCanonicalName(TopFrameworkDir); +  const DirectoryEntry *TopFrameworkDir = nullptr; +  if (auto TopFrameworkDirOrErr = FileMgr.getDirectory(DirName)) +    TopFrameworkDir = *TopFrameworkDirOrErr; + +  if (TopFrameworkDir) +    DirName = FileMgr.getCanonicalName(TopFrameworkDir);    do {      // Get the parent directory name.      DirName = llvm::sys::path::parent_path(DirName); @@ -436,7 +461,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,        break;      // Determine whether this directory exists. -    const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); +    auto Dir = FileMgr.getDirectory(DirName);      if (!Dir)        break; @@ -444,7 +469,7 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,      // framework.      if (llvm::sys::path::extension(DirName) == ".framework") {        SubmodulePath.push_back(llvm::sys::path::stem(DirName)); -      TopFrameworkDir = Dir; +      TopFrameworkDir = *Dir;      }    } while (true); @@ -459,7 +484,7 @@ static bool needModuleLookup(Module *RequestingModule,  /// DoFrameworkLookup - Do a lookup of the specified file in the current  /// DirectoryLookup, which is a framework directory. -const FileEntry *DirectoryLookup::DoFrameworkLookup( +Optional<FileEntryRef> DirectoryLookup::DoFrameworkLookup(      StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,      SmallVectorImpl<char> *RelativePath, Module *RequestingModule,      ModuleMap::KnownHeader *SuggestedModule, @@ -468,7 +493,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(    // Framework names must have a '/' in the filename.    size_t SlashPos = Filename.find('/'); -  if (SlashPos == StringRef::npos) return nullptr; +  if (SlashPos == StringRef::npos) +    return None;    // Find out if this is the home for the specified framework, by checking    // HeaderSearch.  Possible answers are yes/no and unknown. @@ -477,13 +503,13 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(    // If it is known and in some other directory, fail.    if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) -    return nullptr; +    return None;    // Otherwise, construct the path to this framework dir.    // FrameworkName = "/System/Library/Frameworks/"    SmallString<1024> FrameworkName; -  FrameworkName += getFrameworkDir()->getName(); +  FrameworkName += getFrameworkDirRef()->getName();    if (FrameworkName.empty() || FrameworkName.back() != '/')      FrameworkName.push_back('/'); @@ -496,11 +522,12 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(    // If the cache entry was unresolved, populate it now.    if (!CacheEntry.Directory) { -    HS.IncrementFrameworkLookupCount(); +    ++NumFrameworkLookups;      // If the framework dir doesn't exist, we fail. -    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); -    if (!Dir) return nullptr; +    auto Dir = FileMgr.getDirectory(FrameworkName); +    if (!Dir) +      return None;      // Otherwise, if it does, remember that this is the right direntry for this      // framework. @@ -538,9 +565,10 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(    }    FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); -  const FileEntry *FE = FileMgr.getFile(FrameworkName, -                                        /*OpenFile=*/!SuggestedModule); -  if (!FE) { + +  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, @@ -549,17 +577,18 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(        SearchPath->insert(SearchPath->begin()+OrigSize, Private,                           Private+strlen(Private)); -    FE = FileMgr.getFile(FrameworkName, /*OpenFile=*/!SuggestedModule); +    File = FileMgr.getOptionalFileRef(FrameworkName, +                                      /*OpenFile=*/!SuggestedModule);    }    // If we found the header and are allowed to suggest a module, do so now. -  if (FE && needModuleLookup(RequestingModule, SuggestedModule)) { +  if (File && needModuleLookup(RequestingModule, SuggestedModule)) {      // Find the framework in which this header occurs. -    StringRef FrameworkPath = FE->getDir()->getName(); +    StringRef FrameworkPath = File->getFileEntry().getDir()->getName();      bool FoundFramework = false;      do {        // Determine whether this directory exists. -      const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); +      auto Dir = FileMgr.getDirectory(FrameworkPath);        if (!Dir)          break; @@ -579,15 +608,19 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(      bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;      if (FoundFramework) {        if (!HS.findUsableModuleForFrameworkHeader( -              FE, FrameworkPath, RequestingModule, SuggestedModule, IsSystem)) -        return nullptr; +              &File->getFileEntry(), FrameworkPath, RequestingModule, +              SuggestedModule, IsSystem)) +        return None;      } else { -      if (!HS.findUsableModuleForHeader(FE, getDir(), RequestingModule, -                                        SuggestedModule, IsSystem)) -        return nullptr; +      if (!HS.findUsableModuleForHeader(&File->getFileEntry(), getDir(), +                                        RequestingModule, SuggestedModule, +                                        IsSystem)) +        return None;      }    } -  return FE; +  if (File) +    return *File; +  return None;  }  void HeaderSearch::setTarget(const TargetInfo &Target) { @@ -692,7 +725,7 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,  /// 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. -const FileEntry *HeaderSearch::LookupFile( +Optional<FileEntryRef> HeaderSearch::LookupFile(      StringRef Filename, SourceLocation IncludeLoc, bool isAngled,      const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,      ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, @@ -714,7 +747,8 @@ const FileEntry *HeaderSearch::LookupFile(      CurDir = nullptr;      // If this was an #include_next "/absolute/file", fail. -    if (FromDir) return nullptr; +    if (FromDir) +      return None;      if (SearchPath)        SearchPath->clear(); @@ -729,8 +763,9 @@ const FileEntry *HeaderSearch::LookupFile(    }    // This is the header that MSVC's header search would have found. -  const FileEntry *MSFE = nullptr;    ModuleMap::KnownHeader MSSuggestedModule; +  const FileEntry *MSFE_FE = nullptr; +  StringRef MSFE_Name;    // Unless disabled, check to see if the file is in the #includer's    // directory.  This cannot be based on CurDir, because each includer could be @@ -759,7 +794,7 @@ const FileEntry *HeaderSearch::LookupFile(        bool IncluderIsSystemHeader =            Includer ? getFileInfo(Includer).DirInfo != SrcMgr::C_User :            BuildSystemModule; -      if (const FileEntry *FE = getFileAndSuggestModule( +      if (Optional<FileEntryRef> FE = getFileAndSuggestModule(                TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,                RequestingModule, SuggestedModule)) {          if (!Includer) { @@ -778,7 +813,7 @@ const FileEntry *HeaderSearch::LookupFile(          bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;          StringRef Framework = FromHFI.Framework; -        HeaderFileInfo &ToHFI = getFileInfo(FE); +        HeaderFileInfo &ToHFI = getFileInfo(&FE->getFileEntry());          ToHFI.DirInfo = DirInfo;          ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;          ToHFI.Framework = Framework; @@ -795,7 +830,7 @@ const FileEntry *HeaderSearch::LookupFile(          if (First) {            diagnoseFrameworkInclude(Diags, IncludeLoc,                                     IncluderAndDir.second->getName(), Filename, -                                   FE); +                                   &FE->getFileEntry());            return FE;          } @@ -805,7 +840,8 @@ const FileEntry *HeaderSearch::LookupFile(          if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {            return FE;          } else { -          MSFE = FE; +          MSFE_FE = &FE->getFileEntry(); +          MSFE_Name = FE->getName();            if (SuggestedModule) {              MSSuggestedModule = *SuggestedModule;              *SuggestedModule = ModuleMap::KnownHeader(); @@ -817,6 +853,9 @@ const FileEntry *HeaderSearch::LookupFile(      }    } +  Optional<FileEntryRef> MSFE(MSFE_FE ? FileEntryRef(MSFE_Name, *MSFE_FE) +                                      : Optional<FileEntryRef>()); +    CurDir = nullptr;    // If this is a system #include, ignore the user #include locs. @@ -856,29 +895,34 @@ const FileEntry *HeaderSearch::LookupFile(    // Check each directory in sequence to see if it contains this file.    for (; i != SearchDirs.size(); ++i) {      bool InUserSpecifiedSystemFramework = false; -    bool HasBeenMapped = false; +    bool IsInHeaderMap = false;      bool IsFrameworkFoundInDir = false; -    const FileEntry *FE = SearchDirs[i].LookupFile( +    Optional<FileEntryRef> File = SearchDirs[i].LookupFile(          Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,          SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, -        HasBeenMapped, MappedName); -    if (HasBeenMapped) { +        IsInHeaderMap, MappedName); +    if (!MappedName.empty()) { +      assert(IsInHeaderMap && "MappedName should come from a header map");        CacheLookup.MappedName = -          copyString(Filename, LookupFileCache.getAllocator()); -      if (IsMapped) -        *IsMapped = true; +          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 (!FE) continue; +    if (!File) +      continue;      CurDir = &SearchDirs[i];      // This file is a system header or C++ unfriendly if the dir is. -    HeaderFileInfo &HFI = getFileInfo(FE); +    HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry());      HFI.DirInfo = CurDir->getDirCharacteristic();      // If the directory characteristic is User but this framework was @@ -908,7 +952,8 @@ const FileEntry *HeaderSearch::LookupFile(        }      } -    if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { +    if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, +                              &File->getFileEntry(), IncludeLoc)) {        if (SuggestedModule)          *SuggestedModule = MSSuggestedModule;        return MSFE; @@ -916,13 +961,13 @@ const FileEntry *HeaderSearch::LookupFile(      bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;      if (!Includers.empty()) -      diagnoseFrameworkInclude(Diags, IncludeLoc, -                               Includers.front().second->getName(), Filename, -                               FE, isAngled, FoundByHeaderMap); +      diagnoseFrameworkInclude( +          Diags, IncludeLoc, Includers.front().second->getName(), Filename, +          &File->getFileEntry(), isAngled, FoundByHeaderMap);      // Remember this location for the next lookup we do.      CacheLookup.HitIdx = i; -    return FE; +    return File;    }    // If we are including a file with a quoted include "foo.h" from inside @@ -938,12 +983,14 @@ const FileEntry *HeaderSearch::LookupFile(        ScratchFilename += '/';        ScratchFilename += Filename; -      const FileEntry *FE = LookupFile( +      Optional<FileEntryRef> File = LookupFile(            ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,            Includers.front(), SearchPath, RelativePath, RequestingModule,            SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr); -      if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { +      if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, +                                File ? &File->getFileEntry() : nullptr, +                                IncludeLoc)) {          if (SuggestedModule)            *SuggestedModule = MSSuggestedModule;          return MSFE; @@ -952,11 +999,12 @@ const FileEntry *HeaderSearch::LookupFile(        LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];        CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx;        // FIXME: SuggestedModule. -      return FE; +      return File;      }    } -  if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { +  if (checkMSVCHeaderSearch(Diags, MSFE ? &MSFE->getFileEntry() : nullptr, +                            nullptr, IncludeLoc)) {      if (SuggestedModule)        *SuggestedModule = MSSuggestedModule;      return MSFE; @@ -964,7 +1012,7 @@ const FileEntry *HeaderSearch::LookupFile(    // Otherwise, didn't find it. Remember we didn't find this.    CacheLookup.HitIdx = SearchDirs.size(); -  return nullptr; +  return None;  }  /// LookupSubframeworkHeader - Look up a subframework for the specified @@ -972,19 +1020,17 @@ const FileEntry *HeaderSearch::LookupFile(  /// 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. -const FileEntry *HeaderSearch:: -LookupSubframeworkHeader(StringRef Filename, -                         const FileEntry *ContextFileEnt, -                         SmallVectorImpl<char> *SearchPath, -                         SmallVectorImpl<char> *RelativePath, -                         Module *RequestingModule, -                         ModuleMap::KnownHeader *SuggestedModule) { +Optional<FileEntryRef> HeaderSearch::LookupSubframeworkHeader( +    StringRef Filename, const FileEntry *ContextFileEnt, +    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, +    Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule) {    assert(ContextFileEnt && "No context file?");    // 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 nullptr; +  if (SlashPos == StringRef::npos) +    return None;    // Look up the base framework name of the ContextFileEnt.    StringRef ContextName = ContextFileEnt->getName(); @@ -995,7 +1041,7 @@ LookupSubframeworkHeader(StringRef Filename,    if (FrameworkPos == StringRef::npos ||        (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&         ContextName[FrameworkPos + DotFrameworkLen] != '\\')) -    return nullptr; +    return None;    SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +                                                            FrameworkPos + @@ -1015,22 +1061,22 @@ LookupSubframeworkHeader(StringRef Filename,        CacheLookup.first().size() == FrameworkName.size() &&        memcmp(CacheLookup.first().data(), &FrameworkName[0],               CacheLookup.first().size()) != 0) -    return nullptr; +    return None;    // Cache subframework.    if (!CacheLookup.second.Directory) {      ++NumSubFrameworkLookups;      // If the framework dir doesn't exist, we fail. -    const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); -    if (!Dir) return nullptr; +    auto Dir = FileMgr.getDirectory(FrameworkName); +    if (!Dir) +      return None;      // Otherwise, if it does, remember that this is the right direntry for this      // framework. -    CacheLookup.second.Directory = Dir; +    CacheLookup.second.Directory = *Dir;    } -  const FileEntry *FE = nullptr;    if (RelativePath) {      RelativePath->clear(); @@ -1047,7 +1093,8 @@ LookupSubframeworkHeader(StringRef Filename,    }    HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); -  if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) { +  auto File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); +  if (!File) {      // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"      HeadersFilename = FrameworkName;      HeadersFilename += "PrivateHeaders/"; @@ -1058,8 +1105,10 @@ LookupSubframeworkHeader(StringRef Filename,      }      HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); -    if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) -      return nullptr; +    File = FileMgr.getOptionalFileRef(HeadersFilename, /*OpenFile=*/true); + +    if (!File) +      return None;    }    // This file is a system header or C++ unfriendly if the old file is. @@ -1068,14 +1117,15 @@ LookupSubframeworkHeader(StringRef Filename,    // getFileInfo could resize the vector and we don't want to rely on order    // of evaluation.    unsigned DirInfo = getFileInfo(ContextFileEnt).DirInfo; -  getFileInfo(FE).DirInfo = DirInfo; +  getFileInfo(&File->getFileEntry()).DirInfo = DirInfo;    FrameworkName.pop_back(); // remove the trailing '/' -  if (!findUsableModuleForFrameworkHeader(FE, FrameworkName, RequestingModule, -                                          SuggestedModule, /*IsSystem*/ false)) -    return nullptr; +  if (!findUsableModuleForFrameworkHeader(&File->getFileEntry(), FrameworkName, +                                          RequestingModule, SuggestedModule, +                                          /*IsSystem*/ false)) +    return None; -  return FE; +  return *File;  }  //===----------------------------------------------------------------------===// @@ -1306,13 +1356,13 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,        return false;      // Determine whether this directory exists. -    const DirectoryEntry *Dir = FileMgr.getDirectory(DirName); +    auto Dir = FileMgr.getDirectory(DirName);      if (!Dir)        return false;      // Try to load the module map file in this directory. -    switch (loadModuleMapFile(Dir, IsSystem, -                              llvm::sys::path::extension(Dir->getName()) == +    switch (loadModuleMapFile(*Dir, IsSystem, +                              llvm::sys::path::extension((*Dir)->getName()) ==                                    ".framework")) {      case LMM_NewlyLoaded:      case LMM_AlreadyLoaded: @@ -1328,12 +1378,12 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,      }      // If we hit the top of our search, we're done. -    if (Dir == Root) +    if (*Dir == Root)        return false;      // Keep track of all of the directories we checked, so we can mark them as      // having module maps if we eventually do find a module map. -    FixUpDirectories.push_back(Dir); +    FixUpDirectories.push_back(*Dir);    } while (true);  } @@ -1417,7 +1467,9 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File,      llvm::sys::path::append(PrivateFilename, "module.private.modulemap");    else      return nullptr; -  return FileMgr.getFile(PrivateFilename); +  if (auto File = FileMgr.getFile(PrivateFilename)) +    return *File; +  return nullptr;  }  bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem, @@ -1426,15 +1478,18 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem,    // Find the directory for the module. For frameworks, that may require going    // up from the 'Modules' directory.    const DirectoryEntry *Dir = nullptr; -  if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) -    Dir = FileMgr.getDirectory("."); -  else { +  if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd) { +    if (auto DirOrErr = FileMgr.getDirectory(".")) +      Dir = *DirOrErr; +  } else {      if (!OriginalModuleMapFile.empty()) {        // We're building a preprocessed module map. Find or invent the directory        // that it originally occupied. -      Dir = FileMgr.getDirectory( +      auto DirOrErr = FileMgr.getDirectory(            llvm::sys::path::parent_path(OriginalModuleMapFile)); -      if (!Dir) { +      if (DirOrErr) { +        Dir = *DirOrErr; +      } else {          auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0);          Dir = FakeFile->getDir();        } @@ -1446,7 +1501,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem,      if (llvm::sys::path::filename(DirName) == "Modules") {        DirName = llvm::sys::path::parent_path(DirName);        if (DirName.endswith(".framework")) -        Dir = FileMgr.getDirectory(DirName); +        if (auto DirOrErr = FileMgr.getDirectory(DirName)) +          Dir = *DirOrErr;        // 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"); @@ -1503,13 +1559,15 @@ HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) {    if (IsFramework)      llvm::sys::path::append(ModuleMapFileName, "Modules");    llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); -  if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) -    return F; +  if (auto F = FileMgr.getFile(ModuleMapFileName)) +    return *F;    // Continue to allow module.map    ModuleMapFileName = Dir->getName();    llvm::sys::path::append(ModuleMapFileName, "module.map"); -  return FileMgr.getFile(ModuleMapFileName); +  if (auto F = FileMgr.getFile(ModuleMapFileName)) +    return *F; +  return nullptr;  }  Module *HeaderSearch::loadFrameworkModule(StringRef Name, @@ -1540,8 +1598,8 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name,  HeaderSearch::LoadModuleMapResult  HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem,                                  bool IsFramework) { -  if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) -    return loadModuleMapFile(Dir, IsSystem, IsFramework); +  if (auto Dir = FileMgr.getDirectory(DirName)) +    return loadModuleMapFile(*Dir, IsSystem, IsFramework);    return LMM_NoDirectory;  } @@ -1589,13 +1647,13 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {            if (llvm::sys::path::extension(Dir->path()) != ".framework")              continue; -          const DirectoryEntry *FrameworkDir = +          auto FrameworkDir =                FileMgr.getDirectory(Dir->path());            if (!FrameworkDir)              continue;            // Load this framework module. -          loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir, +          loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,                                IsSystem);          }          continue;  | 
