jansvoboda11 updated this revision to Diff 399981.
jansvoboda11 added a comment.
This revision is now accepted and ready to land.

Replace external uses of `const DirectoryLookup *` by an optional iterator. 
That's how they get treated by callers.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116750/new/

https://reviews.llvm.org/D116750

Files:
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/lib/Lex/Pragma.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===================================================================
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -23,6 +23,12 @@
 namespace clang {
 namespace {
 
+static std::shared_ptr<TargetOptions> createTargetOptions() {
+  auto TargetOpts = std::make_shared<TargetOptions>();
+  TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
+  return TargetOpts;
+}
+
 // The test fixture.
 class HeaderSearchTest : public ::testing::Test {
 protected:
@@ -30,12 +36,10 @@
       : VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS),
         DiagID(new DiagnosticIDs()),
         Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
-        SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions),
+        SourceMgr(Diags, FileMgr), TargetOpts(createTargetOptions()),
+        Target(TargetInfo::CreateTargetInfo(Diags, TargetOpts)),
         Search(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags,
-               LangOpts, Target.get()) {
-    TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
-    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
-  }
+               LangOpts, Target.get()) {}
 
   void addSearchDir(llvm::StringRef Dir) {
     VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/None,
@@ -55,6 +59,27 @@
     Search.AddSystemSearchPath(DL);
   }
 
+  void setSearchDirs(llvm::ArrayRef<llvm::StringRef> QuotedDirs,
+                     llvm::ArrayRef<llvm::StringRef> AngledDirs) {
+    auto AddPath = [&](StringRef Dir, bool IsAngled) {
+      VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/None,
+                   /*Group=*/None, llvm::sys::fs::file_type::directory_file);
+      auto Group = IsAngled ? frontend::IncludeDirGroup::Angled
+                            : frontend::IncludeDirGroup::Quoted;
+      Search.getHeaderSearchOpts().AddPath(Dir, Group,
+                                           /*IsFramework=*/false,
+                                           /*IgnoreSysRoot=*/true);
+    };
+
+    for (llvm::StringRef Dir : QuotedDirs)
+      AddPath(Dir, /*IsAngled=*/false);
+    for (llvm::StringRef Dir : AngledDirs)
+      AddPath(Dir, /*IsAngled=*/true);
+
+    clang::ApplyHeaderSearchOptions(Search, Search.getHeaderSearchOpts(),
+                                    LangOpts, Target->getTriple());
+  }
+
   void addHeaderMap(llvm::StringRef Filename,
                     std::unique_ptr<llvm::MemoryBuffer> Buf,
                     bool isAngled = false) {
@@ -71,6 +96,17 @@
     Search.AddSearchPath(DL, isAngled);
   }
 
+  void createModule(StringRef Mod) {
+    std::string ModDir = ("/" + Mod).str();
+    std::string ModHeader = (Mod + ".h").str();
+    VFS->addFile(
+        ModDir + "/module.modulemap", 0,
+        llvm::MemoryBuffer::getMemBufferCopy(
+            ("module " + Mod + " { header \"" + ModHeader + "\" }").str()));
+    VFS->addFile(ModDir + "/" + ModHeader, 0,
+                 llvm::MemoryBuffer::getMemBuffer(""));
+  }
+
   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
   FileSystemOptions FileMgrOpts;
   FileManager FileMgr;
@@ -239,7 +275,7 @@
 
   bool IsMapped = false;
   auto FoundFile = Search.LookupFile(
-      "Foo/Foo.h", SourceLocation(), /*isAngled=*/true, /*FromDir=*/nullptr,
+      "Foo/Foo.h", SourceLocation(), /*isAngled=*/true, /*FromDir=*/None,
       /*CurDir=*/nullptr, /*Includers=*/{}, /*SearchPath=*/nullptr,
       /*RelativePath=*/nullptr, /*RequestingModule=*/nullptr,
       /*SuggestedModule=*/nullptr, &IsMapped,
@@ -254,5 +290,31 @@
   EXPECT_EQ(FI->Framework.str(), "Foo");
 }
 
+TEST_F(HeaderSearchTest, SearchPathUsage) {
+  Search.getHeaderSearchOpts().ImplicitModuleMaps = true;
+
+  setSearchDirs(/*QuotedDirs=*/{"/M0"}, /*AngledDirs=*/{"/M2", "/M3"});
+  createModule("M0");
+  createModule("M2");
+  createModule("M3");
+
+  {
+    Module *M2 = Search.lookupModule("M2");
+    EXPECT_NE(M2, nullptr);
+    EXPECT_EQ(Search.getSearchDirUsage(), (std::vector<bool>{0, 1, 0}));
+    EXPECT_EQ(Search.computeUserEntryUsage(), (std::vector<bool>{0, 1, 0}));
+  }
+
+  addSearchDir("/M1");
+  createModule("M1");
+
+  {
+    Module *M1 = Search.lookupModule("M1");
+    EXPECT_NE(M1, nullptr);
+    EXPECT_EQ(Search.getSearchDirUsage(), (std::vector<bool>{0, 1, 1, 0}));
+    EXPECT_EQ(Search.computeUserEntryUsage(), (std::vector<bool>{0, 1, 0}));
+  }
+}
+
 } // namespace
 } // namespace clang
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -538,7 +538,7 @@
   // a main file.
   if (!SourceMgr.isLoadedFileID(MainFileID)) {
     // Enter the main file source buffer.
-    EnterSourceFile(MainFileID, nullptr, SourceLocation());
+    EnterSourceFile(MainFileID, None, SourceLocation());
 
     // If we've been asked to skip bytes in the main file (e.g., as part of a
     // precompiled preamble), do so now.
@@ -561,14 +561,14 @@
   setPredefinesFileID(FID);
 
   // Start parsing the predefines.
-  EnterSourceFile(FID, nullptr, SourceLocation());
+  EnterSourceFile(FID, None, SourceLocation());
 
   if (!PPOpts->PCHThroughHeader.empty()) {
     // Lookup and save the FileID for the through header. If it isn't found
     // in the search path, it's a fatal error.
     Optional<FileEntryRef> File = LookupFile(
         SourceLocation(), PPOpts->PCHThroughHeader,
-        /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr,
+        /*isAngled=*/false, /*FromDir=*/None, /*FromFile=*/nullptr,
         /*CurDir=*/nullptr, /*SearchPath=*/nullptr, /*RelativePath=*/nullptr,
         /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr,
         /*IsFrameworkFound=*/nullptr);
Index: clang/lib/Lex/Pragma.cpp
===================================================================
--- clang/lib/Lex/Pragma.cpp
+++ clang/lib/Lex/Pragma.cpp
@@ -330,7 +330,7 @@
   Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
                                         StrVal.size(), *this);
 
-  EnterSourceFileWithLexer(TL, nullptr);
+  EnterSourceFileWithLexer(TL, None);
 
   // With everything set up, lex this as a #pragma directive.
   HandlePragmaDirective({PIK__Pragma, PragmaLoc});
@@ -526,7 +526,7 @@
     return llvm::None;
 
   // Search include directories for this file.
-  File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
+  File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, None,
                        nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                        nullptr);
   if (!File) {
Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -1157,10 +1157,10 @@
 /// EvaluateHasIncludeCommon - Process a '__has_include("path")'
 /// or '__has_include_next("path")' expression.
 /// Returns true if successful.
-static bool EvaluateHasIncludeCommon(Token &Tok,
-                                     IdentifierInfo *II, Preprocessor &PP,
-                                     const DirectoryLookup *LookupFrom,
-                                     const FileEntry *LookupFromFile) {
+static bool
+EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, Preprocessor &PP,
+                         HeaderSearch::maybe_search_dir_iterator LookupFrom,
+                         const FileEntry *LookupFromFile) {
   // Save the location of the current token.  If a '(' is later found, use
   // that location.  If not, use the end of this location instead.
   SourceLocation LParenLoc = Tok.getLocation();
@@ -1248,7 +1248,7 @@
 /// Returns true if successful.
 static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II,
                                Preprocessor &PP) {
-  return EvaluateHasIncludeCommon(Tok, II, PP, nullptr, nullptr);
+  return EvaluateHasIncludeCommon(Tok, II, PP, None, nullptr);
 }
 
 /// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
@@ -1260,26 +1260,26 @@
   // issue a diagnostic.
   // FIXME: Factor out duplication with
   // Preprocessor::HandleIncludeNextDirective.
-  const DirectoryLookup *Lookup = PP.GetCurDirLookup();
+  HeaderSearch::maybe_search_dir_iterator Lookup = PP.GetCurDirLookup();
   const FileEntry *LookupFromFile = nullptr;
   if (PP.isInPrimaryFile() && PP.getLangOpts().IsHeaderFile) {
     // If the main file is a header, then it's either for PCH/AST generation,
     // or libclang opened it. Either way, handle it as a normal include below
     // and do not complain about __has_include_next.
   } else if (PP.isInPrimaryFile()) {
-    Lookup = nullptr;
+    Lookup.reset();
     PP.Diag(Tok, diag::pp_include_next_in_primary);
   } else if (PP.getCurrentLexerSubmodule()) {
     // Start looking up in the directory *after* the one in which the current
     // file would be found, if any.
     assert(PP.getCurrentLexer() && "#include_next directive in macro?");
     LookupFromFile = PP.getCurrentLexer()->getFileEntry();
-    Lookup = nullptr;
+    Lookup.reset();
   } else if (!Lookup) {
     PP.Diag(Tok, diag::pp_include_next_absolute_path);
   } else {
     // Start looking up in the next directory.
-    ++Lookup;
+    ++*Lookup;
   }
 
   return EvaluateHasIncludeCommon(Tok, II, PP, Lookup, LookupFromFile);
Index: clang/lib/Lex/PPLexerChange.cpp
===================================================================
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -66,9 +66,9 @@
 
 /// EnterSourceFile - Add a source file to the top of the include stack and
 /// start lexing tokens from it instead of the current buffer.
-bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir,
-                                   SourceLocation Loc,
-                                   bool IsFirstIncludeOfFile) {
+bool Preprocessor::EnterSourceFile(
+    FileID FID, HeaderSearch::maybe_search_dir_iterator CurDir,
+    SourceLocation Loc, bool IsFirstIncludeOfFile) {
   assert(!CurTokenLexer && "Cannot #include a file inside a macro!");
   ++NumEnteredSourceFiles;
 
@@ -99,8 +99,8 @@
 
 /// EnterSourceFileWithLexer - Add a source file to the top of the include stack
 ///  and start lexing tokens from it instead of the current buffer.
-void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
-                                            const DirectoryLookup *CurDir) {
+void Preprocessor::EnterSourceFileWithLexer(
+    Lexer *TheLexer, HeaderSearch::maybe_search_dir_iterator CurDir) {
 
   // Add the current lexer to the include stack.
   if (CurPPLexer || CurTokenLexer)
@@ -136,7 +136,7 @@
   }
 
   PushIncludeMacroStack();
-  CurDirLookup = nullptr;
+  CurDirLookup.reset();
   CurTokenLexer = std::move(TokLexer);
   if (CurLexerKind != CLK_LexAfterModuleImport)
     CurLexerKind = CLK_TokenLexer;
@@ -191,7 +191,7 @@
 
   // Save our current state.
   PushIncludeMacroStack();
-  CurDirLookup = nullptr;
+  CurDirLookup.reset();
   CurTokenLexer = std::move(TokLexer);
   if (CurLexerKind != CLK_LexAfterModuleImport)
     CurLexerKind = CLK_TokenLexer;
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -817,13 +817,13 @@
 
 Optional<FileEntryRef> Preprocessor::LookupFile(
     SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
-    const DirectoryLookup *FromDir, const FileEntry *FromFile,
-    const DirectoryLookup **CurDirArg, SmallVectorImpl<char> *SearchPath,
-    SmallVectorImpl<char> *RelativePath,
+    HeaderSearch::maybe_search_dir_iterator FromDir, const FileEntry *FromFile,
+    HeaderSearch::maybe_search_dir_iterator *CurDirArg,
+    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
     bool *IsFrameworkFound, bool SkipCache) {
-  const DirectoryLookup *CurDirLocal = nullptr;
-  const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
+  HeaderSearch::maybe_search_dir_iterator CurDirLocal;
+  auto &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
 
   Module *RequestingModule = getModuleForLocation(FilenameLoc);
   bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc);
@@ -877,8 +877,8 @@
   if (FromFile) {
     // We're supposed to start looking from after a particular file. Search
     // the include path until we find that file or run out of files.
-    const DirectoryLookup *TmpCurDir = CurDir;
-    const DirectoryLookup *TmpFromDir = nullptr;
+    HeaderSearch::maybe_search_dir_iterator TmpCurDir = CurDir;
+    HeaderSearch::maybe_search_dir_iterator TmpFromDir;
     while (Optional<FileEntryRef> FE = HeaderInfo.LookupFile(
                Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
                Includers, SearchPath, RelativePath, RequestingModule,
@@ -886,7 +886,7 @@
                /*IsFrameworkFound=*/nullptr, SkipCache)) {
       // Keep looking as if this file did a #include_next.
       TmpFromDir = TmpCurDir;
-      ++TmpFromDir;
+      ++*TmpFromDir;
       if (&FE->getFileEntry() == FromFile) {
         // Found it.
         FromDir = TmpFromDir;
@@ -1783,10 +1783,10 @@
 /// routine with functionality shared between \#include, \#include_next and
 /// \#import.  LookupFrom is set when this is a \#include_next directive, it
 /// specifies the file to start searching from.
-void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
-                                          Token &IncludeTok,
-                                          const DirectoryLookup *LookupFrom,
-                                          const FileEntry *LookupFromFile) {
+void Preprocessor::HandleIncludeDirective(
+    SourceLocation HashLoc, Token &IncludeTok,
+    HeaderSearch::maybe_search_dir_iterator LookupFrom,
+    const FileEntry *LookupFromFile) {
   Token FilenameTok;
   if (LexHeaderName(FilenameTok))
     return;
@@ -1830,10 +1830,10 @@
 }
 
 Optional<FileEntryRef> Preprocessor::LookupHeaderIncludeOrImport(
-    const DirectoryLookup **CurDir, StringRef& Filename,
+    HeaderSearch::maybe_search_dir_iterator *CurDir, StringRef& Filename,
     SourceLocation FilenameLoc, CharSourceRange FilenameRange,
     const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
-    bool &IsMapped, const DirectoryLookup *LookupFrom,
+    bool &IsMapped, HeaderSearch::maybe_search_dir_iterator LookupFrom,
     const FileEntry *LookupFromFile, StringRef& LookupFilename,
     SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
     ModuleMap::KnownHeader &SuggestedModule, bool isAngled) {
@@ -1960,7 +1960,7 @@
 ///        lookup.
 Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
     SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok,
-    SourceLocation EndLoc, const DirectoryLookup *LookupFrom,
+    SourceLocation EndLoc, HeaderSearch::maybe_search_dir_iterator LookupFrom,
     const FileEntry *LookupFromFile) {
   SmallString<128> FilenameBuffer;
   StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
@@ -2010,7 +2010,7 @@
   // Search include directories.
   bool IsMapped = false;
   bool IsFrameworkFound = false;
-  const DirectoryLookup *CurDir;
+  HeaderSearch::maybe_search_dir_iterator CurDir;
   SmallString<1024> SearchPath;
   SmallString<1024> RelativePath;
   // We get the raw path only if we have 'Callbacks' to which we later pass
@@ -2400,21 +2400,21 @@
   // #include_next is like #include, except that we start searching after
   // the current found directory.  If we can't do this, issue a
   // diagnostic.
-  const DirectoryLookup *Lookup = CurDirLookup;
+  HeaderSearch::maybe_search_dir_iterator Lookup = CurDirLookup;
   const FileEntry *LookupFromFile = nullptr;
   if (isInPrimaryFile() && LangOpts.IsHeaderFile) {
     // If the main file is a header, then it's either for PCH/AST generation,
     // or libclang opened it. Either way, handle it as a normal include below
     // and do not complain about include_next.
   } else if (isInPrimaryFile()) {
-    Lookup = nullptr;
+    Lookup.reset();
     Diag(IncludeNextTok, diag::pp_include_next_in_primary);
   } else if (CurLexerSubmodule) {
     // Start looking up in the directory *after* the one in which the current
     // file would be found, if any.
     assert(CurPPLexer && "#include_next directive in macro?");
     LookupFromFile = CurPPLexer->getFileEntry();
-    Lookup = nullptr;
+    Lookup.reset();
   } else if (!Lookup) {
     // The current file was not found by walking the include path. Either it
     // is the primary file (handled above), or it was found by absolute path,
@@ -2423,7 +2423,7 @@
     Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
   } else {
     // Start looking up in the next directory.
-    ++Lookup;
+    ++*Lookup;
   }
 
   return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -115,19 +115,24 @@
     llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
   assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
          "Directory indices are unordered");
-  SearchDirs = std::move(dirs);
-  SearchDirsUsage.assign(SearchDirs.size(), false);
+  SearchDirsAlloc.DestroyAll();
+  SearchDirs.clear();
+  for (const DirectoryLookup &Dir : dirs)
+    SearchDirs.push_back(storeSearchDir(Dir));
+  UsedSearchDirs.clear();
+  SearchDirToHSEntry.clear();
+  for (const auto &Entry : searchDirToHSEntry)
+    SearchDirToHSEntry.insert({SearchDirs[Entry.first], Entry.second});
+
   AngledDirIdx = angledDirIdx;
   SystemDirIdx = systemDirIdx;
   NoCurDirSearch = noCurDirSearch;
-  SearchDirToHSEntry = std::move(searchDirToHSEntry);
   //LookupFileCache.clear();
 }
 
 void HeaderSearch::AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
   unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
-  SearchDirs.insert(SearchDirs.begin() + idx, dir);
-  SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);
+  SearchDirs.insert(SearchDirs.begin() + idx, storeSearchDir(dir));
   if (!isAngled)
     AngledDirIdx++;
   SystemDirIdx++;
@@ -135,10 +140,9 @@
 
 std::vector<bool> HeaderSearch::computeUserEntryUsage() const {
   std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
-  for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
-    // Check whether this DirectoryLookup has been successfully used.
-    if (SearchDirsUsage[I]) {
-      auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
+  for (const DirectoryLookup *SearchDir : UsedSearchDirs) {
+    if (UsedSearchDirs.contains(SearchDir)) {
+      auto UserEntryIdxIt = SearchDirToHSEntry.find(SearchDir);
       // Check whether this DirectoryLookup maps to a HeaderSearch::UserEntry.
       if (UserEntryIdxIt != SearchDirToHSEntry.end())
         UserEntryUsage[UserEntryIdxIt->second] = true;
@@ -147,6 +151,14 @@
   return UserEntryUsage;
 }
 
+std::vector<bool> HeaderSearch::getSearchDirUsage() const {
+  std::vector<bool> SearchDirUsage(SearchDirs.size());
+  for (unsigned I = 0, E = SearchDirs.size(); I < E; ++I)
+    if (UsedSearchDirs.contains(SearchDirs[I]))
+      SearchDirUsage[I] = true;
+  return SearchDirUsage;
+}
+
 /// CreateHeaderMap - This method returns a HeaderMap for the specified
 /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
 const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
@@ -301,21 +313,23 @@
                                    SourceLocation ImportLoc,
                                    bool AllowExtraModuleMapSearch) {
   Module *Module = nullptr;
-  unsigned Idx;
+  DirectoryLookup *SearchDir = nullptr;
 
   // Look through the various header search paths to load any available module
   // maps, searching for a module map that describes this module.
-  for (Idx = 0; Idx != SearchDirs.size(); ++Idx) {
-    if (SearchDirs[Idx].isFramework()) {
+  for (unsigned Idx = 0; Idx != SearchDirs.size(); ++Idx) {
+    SearchDir = SearchDirs[Idx];
+
+    if (SearchDirs[Idx]->isFramework()) {
       // Search for or infer a module map for a framework. Here we use
       // SearchName rather than ModuleName, to permit finding private modules
       // named FooPrivate in buggy frameworks named Foo.
       SmallString<128> FrameworkDirName;
-      FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
+      FrameworkDirName += SearchDirs[Idx]->getFrameworkDir()->getName();
       llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
       if (auto FrameworkDir = FileMgr.getDirectory(FrameworkDirName)) {
         bool IsSystem
-          = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
+          = SearchDirs[Idx]->getDirCharacteristic() != SrcMgr::C_User;
         Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
         if (Module)
           break;
@@ -325,12 +339,12 @@
     // FIXME: Figure out how header maps and module maps will work together.
 
     // Only deal with normal search directories.
-    if (!SearchDirs[Idx].isNormalDir())
+    if (!SearchDirs[Idx]->isNormalDir())
       continue;
 
-    bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
+    bool IsSystem = SearchDirs[Idx]->isSystemHeaderDirectory();
     // Search for a module map file in this directory.
-    if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
+    if (loadModuleMapFile(SearchDirs[Idx]->getDir(), IsSystem,
                           /*IsFramework*/false) == LMM_NewlyLoaded) {
       // We just loaded a module map file; check whether the module is
       // available now.
@@ -342,7 +356,7 @@
     // Search for a module map in a subdirectory with the same name as the
     // module.
     SmallString<128> NestedModuleMapDirName;
-    NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName();
+    NestedModuleMapDirName = SearchDirs[Idx]->getDir()->getName();
     llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
     if (loadModuleMapFile(NestedModuleMapDirName, IsSystem,
                           /*IsFramework*/false) == LMM_NewlyLoaded){
@@ -354,13 +368,13 @@
 
     // If we've already performed the exhaustive search for module maps in this
     // search directory, don't do it again.
-    if (SearchDirs[Idx].haveSearchedAllModuleMaps())
+    if (SearchDirs[Idx]->haveSearchedAllModuleMaps())
       continue;
 
     // Load all module maps in the immediate subdirectories of this search
     // directory if ModuleName was from @import.
     if (AllowExtraModuleMapSearch)
-      loadSubdirectoryModuleMaps(SearchDirs[Idx]);
+      loadSubdirectoryModuleMaps(*SearchDirs[Idx]);
 
     // Look again for the module.
     Module = ModMap.findModule(ModuleName);
@@ -369,7 +383,7 @@
   }
 
   if (Module)
-    noteLookupUsage(Idx, ImportLoc);
+    noteLookupUsage(SearchDir, ImportLoc);
 
   return Module;
 }
@@ -495,7 +509,7 @@
   // The case where the target file **exists** is handled by callee of this
   // function as part of the regular logic that applies to include search paths.
   // The case where the target file **does not exist** is handled here:
-  HS.noteLookupUsage(*HS.searchDirIdx(*this), IncludeLoc);
+  HS.noteLookupUsage(this, IncludeLoc);
   return None;
 }
 
@@ -703,13 +717,14 @@
 void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
                                       unsigned HitIdx, SourceLocation Loc) {
   CacheLookup.HitIdx = HitIdx;
-  noteLookupUsage(HitIdx, Loc);
+  noteLookupUsage(SearchDirs[HitIdx], Loc);
 }
 
-void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
-  SearchDirsUsage[HitIdx] = true;
+void HeaderSearch::noteLookupUsage(const DirectoryLookup *SearchDir,
+                                   SourceLocation Loc) {
+  UsedSearchDirs.insert(SearchDir);
 
-  auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
+  auto UserEntryIdxIt = SearchDirToHSEntry.find(SearchDir);
   if (UserEntryIdxIt != SearchDirToHSEntry.end())
     Diags.Report(Loc, diag::remark_pp_search_path_usage)
         << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
@@ -831,14 +846,15 @@
 /// search is needed. Microsoft mode will pass all \#including files.
 Optional<FileEntryRef> HeaderSearch::LookupFile(
     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
-    const DirectoryLookup *FromDir, const DirectoryLookup **CurDirArg,
+    HeaderSearch::maybe_search_dir_iterator FromDir,
+    HeaderSearch::maybe_search_dir_iterator *CurDirArg,
     ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
     bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
     bool BuildSystemModule) {
-  const DirectoryLookup *CurDirLocal = nullptr;
-  const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
+  HeaderSearch::maybe_search_dir_iterator CurDirLocal;
+  auto &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
 
   if (IsMapped)
     *IsMapped = false;
@@ -851,7 +867,7 @@
 
   // If 'Filename' is absolute, check to see if it exists and no searching.
   if (llvm::sys::path::is_absolute(Filename)) {
-    CurDir = nullptr;
+    CurDir.reset();
 
     // If this was an #include_next "/absolute/file", fail.
     if (FromDir)
@@ -958,7 +974,7 @@
     }
   }
 
-  CurDir = nullptr;
+  CurDir.reset();
 
   // If this is a system #include, ignore the user #include locs.
   unsigned i = isAngled ? AngledDirIdx : 0;
@@ -966,7 +982,7 @@
   // If this is a #include_next request, start searching after the directory the
   // file was found in.
   if (FromDir)
-    i = FromDir-&SearchDirs[0];
+    i = *FromDir - SearchDirs.begin();
 
   // Cache all of the lookups performed by this method.  Many headers are
   // multiply included, and the "pragma once" optimization prevents them from
@@ -999,7 +1015,7 @@
     bool InUserSpecifiedSystemFramework = false;
     bool IsInHeaderMap = false;
     bool IsFrameworkFoundInDir = false;
-    Optional<FileEntryRef> File = SearchDirs[i].LookupFile(
+    Optional<FileEntryRef> File = SearchDirs[i]->LookupFile(
         Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
         SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
         IsInHeaderMap, MappedName);
@@ -1021,11 +1037,11 @@
     if (!File)
       continue;
 
-    CurDir = &SearchDirs[i];
+    CurDir = SearchDirs.begin() + i;
 
     // This file is a system header or C++ unfriendly if the dir is.
     HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry());
-    HFI.DirInfo = CurDir->getDirCharacteristic();
+    HFI.DirInfo = (*CurDir)->getDirCharacteristic();
 
     // If the directory characteristic is User but this framework was
     // user-specified to be treated as a system framework, promote the
@@ -1045,12 +1061,12 @@
 
     // If this file is found in a header map and uses the framework style of
     // includes, then this header is part of a framework we're building.
-    if (CurDir->isHeaderMap() && isAngled) {
+    if ((*CurDir)->isHeaderMap() && isAngled) {
       size_t SlashPos = Filename.find('/');
       if (SlashPos != StringRef::npos)
         HFI.Framework =
             getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
-      if (CurDir->isIndexHeaderMap())
+      if ((*CurDir)->isIndexHeaderMap())
         HFI.IndexHeaderMapHeader = 1;
     }
 
@@ -1443,13 +1459,6 @@
     + FrameworkMap.getAllocator().getTotalMemory();
 }
 
-Optional<unsigned> HeaderSearch::searchDirIdx(const DirectoryLookup &DL) const {
-  for (unsigned I = 0; I < SearchDirs.size(); ++I)
-    if (&SearchDirs[I] == &DL)
-      return I;
-  return None;
-}
-
 StringRef HeaderSearch::getUniqueFrameworkName(StringRef Framework) {
   return FrameworkNames.insert(Framework).first->first();
 }
@@ -1777,11 +1786,11 @@
   if (HSOpts->ImplicitModuleMaps) {
     // Load module maps for each of the header search directories.
     for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
-      bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory();
-      if (SearchDirs[Idx].isFramework()) {
+      bool IsSystem = SearchDirs[Idx]->isSystemHeaderDirectory();
+      if (SearchDirs[Idx]->isFramework()) {
         std::error_code EC;
         SmallString<128> DirNative;
-        llvm::sys::path::native(SearchDirs[Idx].getFrameworkDir()->getName(),
+        llvm::sys::path::native(SearchDirs[Idx]->getFrameworkDir()->getName(),
                                 DirNative);
 
         // Search each of the ".framework" directories to load them as modules.
@@ -1805,16 +1814,16 @@
       }
 
       // FIXME: Deal with header maps.
-      if (SearchDirs[Idx].isHeaderMap())
+      if (SearchDirs[Idx]->isHeaderMap())
         continue;
 
       // Try to load a module map file for the search directory.
-      loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem,
+      loadModuleMapFile(SearchDirs[Idx]->getDir(), IsSystem,
                         /*IsFramework*/ false);
 
       // Try to load module map files for immediate subdirectories of this
       // search directory.
-      loadSubdirectoryModuleMaps(SearchDirs[Idx]);
+      loadSubdirectoryModuleMaps(*SearchDirs[Idx]);
     }
   }
 
@@ -1830,14 +1839,13 @@
   // Load module maps for each of the header search directories.
   for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
     // We only care about normal header directories.
-    if (!SearchDirs[Idx].isNormalDir()) {
+    if (!SearchDirs[Idx]->isNormalDir())
       continue;
-    }
 
     // Try to load a module map file for the search directory.
-    loadModuleMapFile(SearchDirs[Idx].getDir(),
-                      SearchDirs[Idx].isSystemHeaderDirectory(),
-                      SearchDirs[Idx].isFramework());
+    loadModuleMapFile(SearchDirs[Idx]->getDir(),
+                      SearchDirs[Idx]->isSystemHeaderDirectory(),
+                      SearchDirs[Idx]->isFramework());
   }
 }
 
@@ -1935,15 +1943,15 @@
 
   bool BestPrefixIsFramework = false;
   for (unsigned I = 0; I != SearchDirs.size(); ++I) {
-    if (SearchDirs[I].isNormalDir()) {
-      StringRef Dir = SearchDirs[I].getDir()->getName();
+    if (SearchDirs[I]->isNormalDir()) {
+      StringRef Dir = SearchDirs[I]->getDir()->getName();
       if (CheckDir(Dir)) {
         if (IsSystem)
           *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
         BestPrefixIsFramework = false;
       }
-    } else if (SearchDirs[I].isFramework()) {
-      StringRef Dir = SearchDirs[I].getFrameworkDir()->getName();
+    } else if (SearchDirs[I]->isFramework()) {
+      StringRef Dir = SearchDirs[I]->getFrameworkDir()->getName();
       if (CheckDir(Dir)) {
         if (IsSystem)
           *IsSystem = BestPrefixLength ? I >= SystemDirIdx : false;
@@ -1964,11 +1972,11 @@
   // key from header name is user prefered name for the include file.
   StringRef Filename = File.drop_front(BestPrefixLength);
   for (unsigned I = 0; I != SearchDirs.size(); ++I) {
-    if (!SearchDirs[I].isHeaderMap())
+    if (!SearchDirs[I]->isHeaderMap())
       continue;
 
     StringRef SpelledFilename =
-        SearchDirs[I].getHeaderMap()->reverseLookupFilename(Filename);
+        SearchDirs[I]->getHeaderMap()->reverseLookupFilename(Filename);
     if (!SpelledFilename.empty()) {
       Filename = SpelledFilename;
       BestPrefixIsFramework = false;
Index: clang/lib/Interpreter/IncrementalParser.cpp
===================================================================
--- clang/lib/Interpreter/IncrementalParser.cpp
+++ clang/lib/Interpreter/IncrementalParser.cpp
@@ -256,7 +256,7 @@
                                /*LoadedOffset=*/0, NewLoc);
 
   // NewLoc only used for diags.
-  if (PP.EnterSourceFile(FID, /*DirLookup=*/nullptr, NewLoc))
+  if (PP.EnterSourceFile(FID, /*DirLookup=*/None, NewLoc))
     return llvm::make_error<llvm::StringError>("Parsing failed. "
                                                "Cannot enter source file.",
                                                std::error_code());
Index: clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -542,7 +542,7 @@
         } else {
           // Lookup file via Preprocessor, like a #include.
           Optional<FileEntryRef> File =
-              PP->LookupFile(Pos, Filename, false, nullptr, nullptr, nullptr,
+              PP->LookupFile(Pos, Filename, false, None, nullptr, nullptr,
                              nullptr, nullptr, nullptr, nullptr, nullptr);
           if (!File) {
             Diags.Report(Pos.getLocWithOffset(PH.C - PH.Begin),
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -311,7 +311,7 @@
   SmallVector<Module::Header, 16> Headers;
   for (StringRef Name : ModuleHeaders) {
     Optional<FileEntryRef> FE = HS.LookupFile(
-        Name, SourceLocation(), /*Angled*/ false, nullptr, nullptr, None,
+        Name, SourceLocation(), /*Angled*/ false, None, nullptr, None,
         nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
     if (!FE) {
       CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -515,7 +515,7 @@
   ///
   /// This allows us to implement \#include_next and find directory-specific
   /// properties.
-  const DirectoryLookup *CurDirLookup = nullptr;
+  HeaderSearch::maybe_search_dir_iterator CurDirLookup = None;
 
   /// The current macro we are expanding, if we are expanding a macro.
   ///
@@ -543,7 +543,7 @@
     std::unique_ptr<Lexer>      TheLexer;
     PreprocessorLexer          *ThePPLexer;
     std::unique_ptr<TokenLexer> TheTokenLexer;
-    const DirectoryLookup      *TheDirLookup;
+    HeaderSearch::maybe_search_dir_iterator TheDirLookup;
 
     // The following constructors are completely useless copies of the default
     // versions, only needed to pacify MSVC.
@@ -551,7 +551,7 @@
                      std::unique_ptr<Lexer> &&TheLexer,
                      PreprocessorLexer *ThePPLexer,
                      std::unique_ptr<TokenLexer> &&TheTokenLexer,
-                     const DirectoryLookup *TheDirLookup)
+                     HeaderSearch::maybe_search_dir_iterator TheDirLookup)
         : CurLexerKind(std::move(CurLexerKind)),
           TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
           ThePPLexer(std::move(ThePPLexer)),
@@ -1367,7 +1367,7 @@
   /// start lexing tokens from it instead of the current buffer.
   ///
   /// Emits a diagnostic, doesn't enter the file, and returns true on error.
-  bool EnterSourceFile(FileID FID, const DirectoryLookup *Dir,
+  bool EnterSourceFile(FileID FID, HeaderSearch::maybe_search_dir_iterator Dir,
                        SourceLocation Loc, bool IsFirstIncludeOfFile = true);
 
   /// Add a Macro to the top of the include stack and start lexing
@@ -2050,8 +2050,10 @@
   /// reference is for system \#include's or not (i.e. using <> instead of "").
   Optional<FileEntryRef>
   LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
-             const DirectoryLookup *FromDir, const FileEntry *FromFile,
-             const DirectoryLookup **CurDir, SmallVectorImpl<char> *SearchPath,
+             HeaderSearch::maybe_search_dir_iterator FromDir,
+             const FileEntry *FromFile,
+             HeaderSearch::maybe_search_dir_iterator *CurDir,
+             SmallVectorImpl<char> *SearchPath,
              SmallVectorImpl<char> *RelativePath,
              ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
              bool *IsFrameworkFound, bool SkipCache = false);
@@ -2061,7 +2063,9 @@
   ///
   /// This allows us to implement \#include_next and find directory-specific
   /// properties.
-  const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
+  HeaderSearch::maybe_search_dir_iterator GetCurDirLookup() {
+    return CurDirLookup;
+  }
 
   /// Return true if we're in the top-level file, not in a \#include.
   bool isInPrimaryFile() const;
@@ -2223,7 +2227,8 @@
 
   /// Add a lexer to the top of the include stack and
   /// start lexing tokens from it instead of the current buffer.
-  void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
+  void EnterSourceFileWithLexer(Lexer *TheLexer,
+                                HeaderSearch::maybe_search_dir_iterator Dir);
 
   /// Set the FileID for the preprocessor predefines.
   void setPredefinesFileID(FileID FID) {
@@ -2300,23 +2305,24 @@
   };
 
   Optional<FileEntryRef> LookupHeaderIncludeOrImport(
-      const DirectoryLookup **CurDir, StringRef &Filename,
+      HeaderSearch::maybe_search_dir_iterator *CurDir, StringRef &Filename,
       SourceLocation FilenameLoc, CharSourceRange FilenameRange,
       const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
-      bool &IsMapped, const DirectoryLookup *LookupFrom,
+      bool &IsMapped, HeaderSearch::maybe_search_dir_iterator LookupFrom,
       const FileEntry *LookupFromFile, StringRef &LookupFilename,
       SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
       ModuleMap::KnownHeader &SuggestedModule, bool isAngled);
 
   // File inclusion.
-  void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok,
-                              const DirectoryLookup *LookupFrom = nullptr,
-                              const FileEntry *LookupFromFile = nullptr);
-  ImportAction
-  HandleHeaderIncludeOrImport(SourceLocation HashLoc, Token &IncludeTok,
-                              Token &FilenameTok, SourceLocation EndLoc,
-                              const DirectoryLookup *LookupFrom = nullptr,
-                              const FileEntry *LookupFromFile = nullptr);
+  void HandleIncludeDirective(
+      SourceLocation HashLoc, Token &Tok,
+      HeaderSearch::maybe_search_dir_iterator LookupFrom = None,
+      const FileEntry *LookupFromFile = nullptr);
+  ImportAction HandleHeaderIncludeOrImport(
+      SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok,
+      SourceLocation EndLoc,
+      HeaderSearch::maybe_search_dir_iterator LookupFrom = None,
+      const FileEntry *LookupFromFile = nullptr);
   void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
   void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
   void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
Index: clang/include/clang/Lex/HeaderSearch.h
===================================================================
--- clang/include/clang/Lex/HeaderSearch.h
+++ clang/include/clang/Lex/HeaderSearch.h
@@ -171,22 +171,23 @@
   /// Header-search options used to initialize this header search.
   std::shared_ptr<HeaderSearchOptions> HSOpts;
 
-  /// Mapping from SearchDir to HeaderSearchOptions::UserEntries indices.
-  llvm::DenseMap<unsigned, unsigned> SearchDirToHSEntry;
-
   DiagnosticsEngine &Diags;
   FileManager &FileMgr;
 
+  /// The allocator owning search directories.
+  llvm::SpecificBumpPtrAllocator<DirectoryLookup> SearchDirsAlloc;
   /// \#include search path information.  Requests for \#include "x" search the
   /// directory of the \#including file first, then each directory in SearchDirs
   /// consecutively. Requests for <x> search the current dir first, then each
   /// directory in SearchDirs, starting at AngledDirIdx, consecutively.  If
   /// NoCurDirSearch is true, then the check for the file in the current
   /// directory is suppressed.
-  std::vector<DirectoryLookup> SearchDirs;
-  /// Whether the DirectoryLookup at the corresponding index in SearchDirs has
-  /// been successfully used to lookup a file.
-  std::vector<bool> SearchDirsUsage;
+  std::vector<DirectoryLookup *> SearchDirs;
+  /// Set of SearchDirs that have been successfully used to lookup a file.
+  llvm::DenseSet<const DirectoryLookup *> UsedSearchDirs;
+  /// Mapping from SearchDir to HeaderSearchOptions::UserEntries indices.
+  llvm::DenseMap<const DirectoryLookup *, unsigned> SearchDirToHSEntry;
+
   unsigned AngledDirIdx = 0;
   unsigned SystemDirIdx = 0;
   bool NoCurDirSearch = false;
@@ -294,8 +295,7 @@
 
   /// Add an additional system search path.
   void AddSystemSearchPath(const DirectoryLookup &dir) {
-    SearchDirs.push_back(dir);
-    SearchDirsUsage.push_back(false);
+    SearchDirs.push_back(storeSearchDir(dir));
   }
 
   /// Set the list of system header prefixes.
@@ -371,6 +371,10 @@
   /// already known.
   void setTarget(const TargetInfo &Target);
 
+  using search_dir_iterator =
+      llvm::pointee_iterator<decltype(SearchDirs)::const_iterator>;
+  using maybe_search_dir_iterator = llvm::Optional<search_dir_iterator>;
+
   /// Given a "foo" or \<foo> reference, look up the indicated file,
   /// return null on failure.
   ///
@@ -408,7 +412,7 @@
   /// found.
   Optional<FileEntryRef> LookupFile(
       StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
-      const DirectoryLookup *FromDir, const DirectoryLookup **CurDir,
+      maybe_search_dir_iterator FromDir, maybe_search_dir_iterator *CurDir,
       ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
       SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
       Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
@@ -499,7 +503,11 @@
 
   /// Determine which HeaderSearchOptions::UserEntries have been successfully
   /// used so far and mark their index with 'true' in the resulting bit vector.
+  // TODO: Use llvm::BitVector instead.
   std::vector<bool> computeUserEntryUsage() const;
+  /// Return a bit vector of length \c SearchDirs.size() that indicates for each
+  /// search directory whether it was used.
+  std::vector<bool> getSearchDirUsage() const;
 
   /// This method returns a HeaderMap for the specified
   /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
@@ -629,6 +637,11 @@
   void loadTopLevelSystemModules();
 
 private:
+  /// Stores the given search directory and returns a stable pointer.
+  DirectoryLookup *storeSearchDir(const DirectoryLookup &Dir) {
+    return new (SearchDirsAlloc.Allocate()) DirectoryLookup(Dir);
+  }
+
   /// Lookup a module with the given module name and search-name.
   ///
   /// \param ModuleName The name of the module we're looking for.
@@ -715,8 +728,9 @@
   void cacheLookupSuccess(LookupFileCacheInfo &CacheLookup, unsigned HitIdx,
                           SourceLocation IncludeLoc);
   /// Note that a lookup at the given include location was successful using the
-  /// search path at index `HitIdx`.
-  void noteLookupUsage(unsigned HitIdx, SourceLocation IncludeLoc);
+  /// given search path.
+  void noteLookupUsage(const DirectoryLookup *SearchDir,
+                       SourceLocation IncludeLoc);
 
 public:
   /// Retrieve the module map.
@@ -738,9 +752,6 @@
   const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
                                             bool WantExternal = true) const;
 
-  // Used by external tools
-  using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator;
-
   search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
   search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
   unsigned search_dir_size() const { return SearchDirs.size(); }
@@ -767,9 +778,6 @@
 
   search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
 
-  /// Get the index of the given search directory.
-  Optional<unsigned> searchDirIdx(const DirectoryLookup &DL) const;
-
   /// Retrieve a uniqued framework name.
   StringRef getUniqueFrameworkName(StringRef Framework);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to