https://github.com/jansvoboda11 updated 
https://github.com/llvm/llvm-project/pull/136178

>From 51449e05b19f3b0f237305159ae150bc92588fd9 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Fri, 11 Apr 2025 14:11:36 -0700
Subject: [PATCH 1/3] [clang][deps] Make dependency directives getter
 thread-safe

---
 .../include/clang/Frontend/CompilerInstance.h |  8 +++
 .../clang/Lex/DependencyDirectivesScanner.h   |  6 ++
 clang/include/clang/Lex/Preprocessor.h        | 10 +++
 clang/include/clang/Lex/PreprocessorOptions.h | 13 ----
 .../DependencyScanningFilesystem.h            | 10 +++
 clang/lib/Frontend/CompilerInstance.cpp       |  5 ++
 clang/lib/Lex/PPLexerChange.cpp               | 14 ++---
 .../DependencyScanningWorker.cpp              | 61 ++++++++++++++++---
 .../Lex/PPDependencyDirectivesTest.cpp        | 12 ++--
 9 files changed, 100 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index 41dc7f1fef461..ecd1f5cabc79e 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -16,6 +16,7 @@
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/PCHContainerOperations.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Lex/DependencyDirectivesScanner.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -99,6 +100,9 @@ class CompilerInstance : public ModuleLoader {
   /// The cache of PCM files.
   IntrusiveRefCntPtr<ModuleCache> ModCache;
 
+  /// Function for getting the dependency preprocessor directives of a file.
+  GetDependencyDirectivesFn GetDependencyDirectives;
+
   /// The preprocessor.
   std::shared_ptr<Preprocessor> PP;
 
@@ -697,6 +701,10 @@ class CompilerInstance : public ModuleLoader {
   /// and replace any existing one with it.
   void createPreprocessor(TranslationUnitKind TUKind);
 
+  void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
+    GetDependencyDirectives = Fn;
+  }
+
   std::string getSpecificModuleCachePath(StringRef ModuleHash);
   std::string getSpecificModuleCachePath() {
     return getSpecificModuleCachePath(getInvocation().getModuleHash());
diff --git a/clang/include/clang/Lex/DependencyDirectivesScanner.h 
b/clang/include/clang/Lex/DependencyDirectivesScanner.h
index 0e115906fbfe5..c975311f8bf33 100644
--- a/clang/include/clang/Lex/DependencyDirectivesScanner.h
+++ b/clang/include/clang/Lex/DependencyDirectivesScanner.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/ArrayRef.h"
 
 namespace clang {
+class FileManager;
 
 namespace tok {
 enum TokenKind : unsigned short;
@@ -135,6 +136,11 @@ void printDependencyDirectivesAsSource(
     ArrayRef<dependency_directives_scan::Directive> Directives,
     llvm::raw_ostream &OS);
 
+// FIXME: Allow returning an error.
+using GetDependencyDirectivesFn = std::function<
+    std::optional<ArrayRef<dependency_directives_scan::Directive>>(
+        FileManager &, FileEntryRef)>;
+
 } // end namespace clang
 
 #endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index 24bb524783e93..8554068b19607 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -140,6 +140,12 @@ class Preprocessor {
   friend class VariadicMacroScopeGuard;
 
   llvm::unique_function<void(const clang::Token &)> OnToken;
+  /// Function for getting the dependency preprocessor directives of a file.
+  ///
+  /// These are directives derived from a special form of lexing where the
+  /// source input is scanned for the preprocessor directives that might have 
an
+  /// effect on the dependencies for a compilation unit.
+  GetDependencyDirectivesFn GetDependencyDirectives;
   const PreprocessorOptions &PPOpts;
   DiagnosticsEngine        *Diags;
   const LangOptions &LangOpts;
@@ -1326,6 +1332,10 @@ class Preprocessor {
     OnToken = std::move(F);
   }
 
+  void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
+    GetDependencyDirectives = Fn;
+  }
+
   void setPreprocessToken(bool Preprocess) { PreprocessToken = Preprocess; }
 
   bool isMacroDefined(StringRef Id) {
diff --git a/clang/include/clang/Lex/PreprocessorOptions.h 
b/clang/include/clang/Lex/PreprocessorOptions.h
index c2e3d68333024..d4c4e1ccbf2c4 100644
--- a/clang/include/clang/Lex/PreprocessorOptions.h
+++ b/clang/include/clang/Lex/PreprocessorOptions.h
@@ -189,19 +189,6 @@ class PreprocessorOptions {
   /// with support for lifetime-qualified pointers.
   ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib;
 
-  /// Function for getting the dependency preprocessor directives of a file.
-  ///
-  /// These are directives derived from a special form of lexing where the
-  /// source input is scanned for the preprocessor directives that might have 
an
-  /// effect on the dependencies for a compilation unit.
-  ///
-  /// Enables a client to cache the directives for a file and provide them
-  /// across multiple compiler invocations.
-  /// FIXME: Allow returning an error.
-  std::function<std::optional<ArrayRef<dependency_directives_scan::Directive>>(
-      FileEntryRef)>
-      DependencyDirectivesForFile;
-
   /// Set up preprocessor for RunAnalysis action.
   bool SetUpStaticAnalyzer = false;
 
diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
index d12814e7c9253..f07bd5e820dab 100644
--- 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
+++ 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
@@ -371,6 +371,16 @@ class DependencyScanningWorkerFilesystem
   /// false if not (i.e. this entry is not a file or its scan fails).
   bool ensureDirectiveTokensArePopulated(EntryRef Entry);
 
+  /// \returns The scanned preprocessor directive tokens of the file that are
+  /// used to speed up preprocessing, if available.
+  std::optional<ArrayRef<dependency_directives_scan::Directive>>
+  getDirectiveTokens(const Twine &Path) {
+    if (llvm::ErrorOr<EntryRef> Entry = getOrCreateFileSystemEntry(Path.str()))
+      if (ensureDirectiveTokensArePopulated(*Entry))
+        return Entry->getDirectiveTokens();
+    return std::nullopt;
+  }
+
   /// Check whether \p Path exists. By default checks cached result of \c
   /// status(), and falls back on FS if unable to do so.
   bool exists(const Twine &Path) override;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 243e0a3c15b05..0efe0ada4873f 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -535,6 +535,9 @@ void 
CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
                            /*ShowAllHeaders=*/true, /*OutputPath=*/"",
                            /*ShowDepth=*/true, /*MSStyle=*/true);
   }
+
+  if (GetDependencyDirectives)
+    PP->setDependencyDirectivesGetter(GetDependencyDirectives);
 }
 
 std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) 
{
@@ -1237,6 +1240,8 @@ std::unique_ptr<CompilerInstance> 
CompilerInstance::cloneForModuleCompileImpl(
   // Make a copy for the new instance.
   Instance.FailedModules = FailedModules;
 
+  Instance.GetDependencyDirectives = GetDependencyDirectives;
+
   // If we're collecting module dependencies, we need to share a collector
   // between all of the module CompilerInstances. Other than that, we don't
   // want to produce any dependency output from the module build.
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index a373a52506a24..09ef921f67202 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -92,16 +92,10 @@ bool Preprocessor::EnterSourceFile(FileID FID, 
ConstSearchDirIterator CurDir,
   }
 
   Lexer *TheLexer = new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile);
-  if (getPreprocessorOpts().DependencyDirectivesForFile &&
-      FID != PredefinesFileID) {
-    if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID)) {
-      if (std::optional<ArrayRef<dependency_directives_scan::Directive>>
-              DepDirectives =
-                  getPreprocessorOpts().DependencyDirectivesForFile(*File)) {
-        TheLexer->DepDirectives = *DepDirectives;
-      }
-    }
-  }
+  if (GetDependencyDirectives && FID != PredefinesFileID)
+    if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID))
+      if (auto MaybeDepDirectives = GetDependencyDirectives(FileMgr, *File))
+        TheLexer->DepDirectives = *MaybeDepDirectives;
 
   EnterSourceFileWithLexer(TheLexer, CurDir);
   return false;
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 6595f8ff5dc55..a9e35e0484ac9 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -357,6 +357,57 @@ static void canonicalizeDefines(PreprocessorOptions 
&PPOpts) {
   std::swap(PPOpts.Macros, NewMacros);
 }
 
+static GetDependencyDirectivesFn makeDepDirectivesGetter() {
+  /// This is a functor that conforms to \c GetDependencyDirectivesFn.
+  /// It ensures it's always invoked with the same \c FileManager and caches 
the
+  /// extraction of the scanning VFS for better performance.
+  struct DepDirectivesGetter {
+    DepDirectivesGetter() : DepFS(nullptr), FM(nullptr) {}
+
+    /// It's important copies do not carry over the cached members. The copies
+    /// are likely to be used from distinct \c CompilerInstance objects with
+    /// distinct \c FileManager \c llvm::vfs::FileSystem.
+    DepDirectivesGetter(const DepDirectivesGetter &)
+        : DepFS(nullptr), FM(nullptr) {}
+    DepDirectivesGetter &operator=(const DepDirectivesGetter &) {
+      DepFS = nullptr;
+      FM = nullptr;
+      return *this;
+    }
+
+    auto operator()(FileManager &FileMgr, FileEntryRef File) {
+      ensureConsistentFileManager(FileMgr);
+      ensurePopulatedFileSystem(FileMgr);
+      return DepFS->getDirectiveTokens(File.getName());
+    }
+
+  private:
+    DependencyScanningWorkerFilesystem *DepFS;
+    FileManager *FM;
+
+    void ensureConsistentFileManager(FileManager &FileMgr) {
+      if (!FM)
+        FM = &FileMgr;
+      assert(&FileMgr == FM);
+    }
+
+    void ensurePopulatedFileSystem(FileManager &FM) {
+      if (DepFS)
+        return;
+      FM.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
+        auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
+        if (DFS) {
+          assert(!DepFS && "Found multiple scanning VFSs");
+          DepFS = DFS;
+        }
+      });
+      assert(DepFS && "Did not find scanning VFS");
+    }
+  };
+
+  return DepDirectivesGetter{};
+}
+
 /// A clang tool that runs the preprocessor in a mode that's optimized for
 /// dependency scanning for the given compiler invocation.
 class DependencyScanningAction : public tooling::ToolAction {
@@ -433,15 +484,7 @@ class DependencyScanningAction : public 
tooling::ToolAction {
       if (!ModulesCachePath.empty())
         DepFS->setBypassedPathPrefix(ModulesCachePath);
 
-      ScanInstance.getPreprocessorOpts().DependencyDirectivesForFile =
-          [LocalDepFS = DepFS](FileEntryRef File)
-          -> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
-        if (llvm::ErrorOr<EntryRef> Entry =
-                LocalDepFS->getOrCreateFileSystemEntry(File.getName()))
-          if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry))
-            return Entry->getDirectiveTokens();
-        return std::nullopt;
-      };
+      ScanInstance.setDependencyDirectivesGetter(makeDepDirectivesGetter());
     }
 
     // Create a new FileManager to match the invocation's FileSystemOptions.
diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp 
b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
index 03f1432d990cb..c52d5091eabfb 100644
--- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
+++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
@@ -105,8 +105,7 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
   };
   SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
 
-  auto getDependencyDirectives = [&](FileEntryRef File)
-      -> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
+  auto GetDependencyDirectives = [&](FileManager &FileMgr, FileEntryRef File) {
     DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
     StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
     bool Err = scanSourceForDependencyDirectives(
@@ -117,11 +116,6 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
   };
 
   PreprocessorOptions PPOpts;
-  PPOpts.DependencyDirectivesForFile = [&](FileEntryRef File)
-      -> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
-    return getDependencyDirectives(File);
-  };
-
   HeaderSearchOptions HSOpts;
   TrivialModuleLoader ModLoader;
   HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());
@@ -130,6 +124,10 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
                   /*OwnsHeaderSearch =*/false);
   PP.Initialize(*Target);
 
+  PP.setDependencyDirectivesGetter([&](FileManager &FM, FileEntryRef File) {
+    return GetDependencyDirectives(FM, File);
+  });
+
   SmallVector<StringRef> IncludedFiles;
   PP.addPPCallbacks(std::make_unique<IncludeCollector>(PP, IncludedFiles));
   PP.EnterMainSourceFile();

>From 00099ccf341ba443e356b514a4f81dae2b01e0bd Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Thu, 17 Apr 2025 11:44:01 -0700
Subject: [PATCH 2/3] Simplify test

---
 clang/unittests/Lex/PPDependencyDirectivesTest.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp 
b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
index c52d5091eabfb..5f4c2706a519d 100644
--- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
+++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
@@ -124,9 +124,7 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
                   /*OwnsHeaderSearch =*/false);
   PP.Initialize(*Target);
 
-  PP.setDependencyDirectivesGetter([&](FileManager &FM, FileEntryRef File) {
-    return GetDependencyDirectives(FM, File);
-  });
+  PP.setDependencyDirectivesGetter(GetDependencyDirectives);
 
   SmallVector<StringRef> IncludedFiles;
   PP.addPPCallbacks(std::make_unique<IncludeCollector>(PP, IncludedFiles));

>From 105e148b597907b9ef21c492f401c10725cf49e2 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Tue, 22 Apr 2025 13:21:28 -0700
Subject: [PATCH 3/3] Interface with explicit `cloneFor(FileManager&)` API

---
 .../include/clang/Frontend/CompilerInstance.h |  9 ++-
 .../clang/Lex/DependencyDirectivesScanner.h   | 18 +++--
 clang/include/clang/Lex/Preprocessor.h        |  8 +-
 clang/lib/Frontend/CompilerInstance.cpp       |  6 +-
 clang/lib/Lex/PPLexerChange.cpp               |  2 +-
 .../DependencyScanningWorker.cpp              | 77 +++++++------------
 .../Lex/PPDependencyDirectivesTest.cpp        | 34 +++++---
 7 files changed, 78 insertions(+), 76 deletions(-)

diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index ecd1f5cabc79e..078044ed2d039 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -100,8 +100,8 @@ class CompilerInstance : public ModuleLoader {
   /// The cache of PCM files.
   IntrusiveRefCntPtr<ModuleCache> ModCache;
 
-  /// Function for getting the dependency preprocessor directives of a file.
-  GetDependencyDirectivesFn GetDependencyDirectives;
+  /// Functor for getting the dependency preprocessor directives of a file.
+  std::unique_ptr<DependencyDirectivesGetter> GetDependencyDirectives;
 
   /// The preprocessor.
   std::shared_ptr<Preprocessor> PP;
@@ -701,8 +701,9 @@ class CompilerInstance : public ModuleLoader {
   /// and replace any existing one with it.
   void createPreprocessor(TranslationUnitKind TUKind);
 
-  void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
-    GetDependencyDirectives = Fn;
+  void setDependencyDirectivesGetter(
+      std::unique_ptr<DependencyDirectivesGetter> Getter) {
+    GetDependencyDirectives = std::move(Getter);
   }
 
   std::string getSpecificModuleCachePath(StringRef ModuleHash);
diff --git a/clang/include/clang/Lex/DependencyDirectivesScanner.h 
b/clang/include/clang/Lex/DependencyDirectivesScanner.h
index c975311f8bf33..acdc9e2bf9aa4 100644
--- a/clang/include/clang/Lex/DependencyDirectivesScanner.h
+++ b/clang/include/clang/Lex/DependencyDirectivesScanner.h
@@ -136,11 +136,19 @@ void printDependencyDirectivesAsSource(
     ArrayRef<dependency_directives_scan::Directive> Directives,
     llvm::raw_ostream &OS);
 
-// FIXME: Allow returning an error.
-using GetDependencyDirectivesFn = std::function<
-    std::optional<ArrayRef<dependency_directives_scan::Directive>>(
-        FileManager &, FileEntryRef)>;
-
+/// Functor that returns the dependency directives for a given file.
+class DependencyDirectivesGetter {
+public:
+  /// Clone the getter for a new \c FileManager instance.
+  virtual std::unique_ptr<DependencyDirectivesGetter>
+  cloneFor(FileManager &FileMgr) = 0;
+
+  /// Get the dependency directives for the given file.
+  virtual std::optional<ArrayRef<dependency_directives_scan::Directive>>
+  operator()(FileEntryRef File) = 0;
+
+  virtual ~DependencyDirectivesGetter() = default;
+};
 } // end namespace clang
 
 #endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index 8554068b19607..3ec02a754138f 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -140,12 +140,12 @@ class Preprocessor {
   friend class VariadicMacroScopeGuard;
 
   llvm::unique_function<void(const clang::Token &)> OnToken;
-  /// Function for getting the dependency preprocessor directives of a file.
+  /// Functor for getting the dependency preprocessor directives of a file.
   ///
   /// These are directives derived from a special form of lexing where the
   /// source input is scanned for the preprocessor directives that might have 
an
   /// effect on the dependencies for a compilation unit.
-  GetDependencyDirectivesFn GetDependencyDirectives;
+  DependencyDirectivesGetter *GetDependencyDirectives = nullptr;
   const PreprocessorOptions &PPOpts;
   DiagnosticsEngine        *Diags;
   const LangOptions &LangOpts;
@@ -1332,8 +1332,8 @@ class Preprocessor {
     OnToken = std::move(F);
   }
 
-  void setDependencyDirectivesGetter(GetDependencyDirectivesFn Fn) {
-    GetDependencyDirectives = Fn;
+  void setDependencyDirectivesGetter(DependencyDirectivesGetter &Get) {
+    GetDependencyDirectives = &Get;
   }
 
   void setPreprocessToken(bool Preprocess) { PreprocessToken = Preprocess; }
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 0efe0ada4873f..9f27224ddd6f0 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -537,7 +537,7 @@ void 
CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
   }
 
   if (GetDependencyDirectives)
-    PP->setDependencyDirectivesGetter(GetDependencyDirectives);
+    PP->setDependencyDirectivesGetter(*GetDependencyDirectives);
 }
 
 std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) 
{
@@ -1240,7 +1240,9 @@ std::unique_ptr<CompilerInstance> 
CompilerInstance::cloneForModuleCompileImpl(
   // Make a copy for the new instance.
   Instance.FailedModules = FailedModules;
 
-  Instance.GetDependencyDirectives = GetDependencyDirectives;
+  if (GetDependencyDirectives)
+    Instance.GetDependencyDirectives =
+        GetDependencyDirectives->cloneFor(Instance.getFileManager());
 
   // If we're collecting module dependencies, we need to share a collector
   // between all of the module CompilerInstances. Other than that, we don't
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index 09ef921f67202..f95e38317a872 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -94,7 +94,7 @@ bool Preprocessor::EnterSourceFile(FileID FID, 
ConstSearchDirIterator CurDir,
   Lexer *TheLexer = new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile);
   if (GetDependencyDirectives && FID != PredefinesFileID)
     if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID))
-      if (auto MaybeDepDirectives = GetDependencyDirectives(FileMgr, *File))
+      if (auto MaybeDepDirectives = (*GetDependencyDirectives)(*File))
         TheLexer->DepDirectives = *MaybeDepDirectives;
 
   EnterSourceFileWithLexer(TheLexer, CurDir);
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index a9e35e0484ac9..ef38c7c9defee 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -357,56 +357,31 @@ static void canonicalizeDefines(PreprocessorOptions 
&PPOpts) {
   std::swap(PPOpts.Macros, NewMacros);
 }
 
-static GetDependencyDirectivesFn makeDepDirectivesGetter() {
-  /// This is a functor that conforms to \c GetDependencyDirectivesFn.
-  /// It ensures it's always invoked with the same \c FileManager and caches 
the
-  /// extraction of the scanning VFS for better performance.
-  struct DepDirectivesGetter {
-    DepDirectivesGetter() : DepFS(nullptr), FM(nullptr) {}
-
-    /// It's important copies do not carry over the cached members. The copies
-    /// are likely to be used from distinct \c CompilerInstance objects with
-    /// distinct \c FileManager \c llvm::vfs::FileSystem.
-    DepDirectivesGetter(const DepDirectivesGetter &)
-        : DepFS(nullptr), FM(nullptr) {}
-    DepDirectivesGetter &operator=(const DepDirectivesGetter &) {
-      DepFS = nullptr;
-      FM = nullptr;
-      return *this;
-    }
-
-    auto operator()(FileManager &FileMgr, FileEntryRef File) {
-      ensureConsistentFileManager(FileMgr);
-      ensurePopulatedFileSystem(FileMgr);
-      return DepFS->getDirectiveTokens(File.getName());
-    }
+class ActualDependencyDirectivesGetter : public DependencyDirectivesGetter {
+  DependencyScanningWorkerFilesystem *DepFS;
 
-  private:
-    DependencyScanningWorkerFilesystem *DepFS;
-    FileManager *FM;
-
-    void ensureConsistentFileManager(FileManager &FileMgr) {
-      if (!FM)
-        FM = &FileMgr;
-      assert(&FileMgr == FM);
-    }
+public:
+  ActualDependencyDirectivesGetter(FileManager &FileMgr) : DepFS(nullptr) {
+    FileMgr.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
+      auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
+      if (DFS) {
+        assert(!DepFS && "Found multiple scanning VFSs");
+        DepFS = DFS;
+      }
+    });
+    assert(DepFS && "Did not find scanning VFS");
+  }
 
-    void ensurePopulatedFileSystem(FileManager &FM) {
-      if (DepFS)
-        return;
-      FM.getVirtualFileSystem().visit([&](llvm::vfs::FileSystem &FS) {
-        auto *DFS = llvm::dyn_cast<DependencyScanningWorkerFilesystem>(&FS);
-        if (DFS) {
-          assert(!DepFS && "Found multiple scanning VFSs");
-          DepFS = DFS;
-        }
-      });
-      assert(DepFS && "Did not find scanning VFS");
-    }
-  };
+  std::unique_ptr<DependencyDirectivesGetter>
+  cloneFor(FileManager &FileMgr) override {
+    return std::make_unique<ActualDependencyDirectivesGetter>(FileMgr);
+  }
 
-  return DepDirectivesGetter{};
-}
+  std::optional<ArrayRef<dependency_directives_scan::Directive>>
+  operator()(FileEntryRef File) override {
+    return DepFS->getDirectiveTokens(File.getName());
+  }
+};
 
 /// A clang tool that runs the preprocessor in a mode that's optimized for
 /// dependency scanning for the given compiler invocation.
@@ -475,6 +450,9 @@ class DependencyScanningAction : public tooling::ToolAction 
{
         ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
         DriverFileMgr->getVirtualFileSystemPtr());
 
+    // Create a new FileManager to match the invocation's FileSystemOptions.
+    auto *FileMgr = ScanInstance.createFileManager(FS);
+
     // Use the dependency scanning optimized file system if requested to do so.
     if (DepFS) {
       StringRef ModulesCachePath =
@@ -484,11 +462,10 @@ class DependencyScanningAction : public 
tooling::ToolAction {
       if (!ModulesCachePath.empty())
         DepFS->setBypassedPathPrefix(ModulesCachePath);
 
-      ScanInstance.setDependencyDirectivesGetter(makeDepDirectivesGetter());
+      ScanInstance.setDependencyDirectivesGetter(
+          std::make_unique<ActualDependencyDirectivesGetter>(*FileMgr));
     }
 
-    // Create a new FileManager to match the invocation's FileSystemOptions.
-    auto *FileMgr = ScanInstance.createFileManager(FS);
     ScanInstance.createSourceManager(*FileMgr);
 
     // Store a mapping of prebuilt module files and their properties like 
header
diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp 
b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
index 5f4c2706a519d..6ab80ba01677e 100644
--- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
+++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
@@ -103,17 +103,31 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
     SmallVector<dependency_directives_scan::Token> Tokens;
     SmallVector<dependency_directives_scan::Directive> Directives;
   };
-  SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
-
-  auto GetDependencyDirectives = [&](FileManager &FileMgr, FileEntryRef File) {
-    DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
-    StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
-    bool Err = scanSourceForDependencyDirectives(
-        Input, DepDirectivesObjects.back()->Tokens,
-        DepDirectivesObjects.back()->Directives);
-    EXPECT_FALSE(Err);
-    return llvm::ArrayRef(DepDirectivesObjects.back()->Directives);
+
+  class TestDependencyDirectivesGetter : public DependencyDirectivesGetter {
+    FileManager &FileMgr;
+    SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
+
+  public:
+    TestDependencyDirectivesGetter(FileManager &FileMgr) : FileMgr(FileMgr) {}
+
+    std::unique_ptr<DependencyDirectivesGetter>
+    cloneFor(FileManager &FileMgr) override {
+      return std::make_unique<TestDependencyDirectivesGetter>(FileMgr);
+    }
+
+    std::optional<ArrayRef<dependency_directives_scan::Directive>>
+    operator()(FileEntryRef File) override {
+      DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
+      StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
+      bool Err = scanSourceForDependencyDirectives(
+          Input, DepDirectivesObjects.back()->Tokens,
+          DepDirectivesObjects.back()->Directives);
+      EXPECT_FALSE(Err);
+      return DepDirectivesObjects.back()->Directives;
+    }
   };
+  TestDependencyDirectivesGetter GetDependencyDirectives(FileMgr);
 
   PreprocessorOptions PPOpts;
   HeaderSearchOptions HSOpts;

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to