https://github.com/jansvoboda11 created 
https://github.com/llvm/llvm-project/pull/136601

The `DiagnosticConsumer` interface is not thread-safe. To enable thread-safety 
of `CompilerInstance` objects cloned from the same parent, this PR allows 
passing an explicit `DiagnosticConsumer` to `cloneForModuleCompile()`. This 
will be used from the dependency scanner.

>From 1c8f8988358dd602829a3261cff4e721b4108ab9 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Mon, 21 Apr 2025 12:45:23 -0700
Subject: [PATCH] [clang] Enable making `CompilerInstance` diagnostics
 thread-safe

---
 .../include/clang/Frontend/CompilerInstance.h | 15 ++++++++----
 clang/lib/Frontend/CompilerInstance.cpp       | 23 ++++++++++++-------
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index d70f5c45b3d38..86e6eb38f5306 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -848,10 +848,13 @@ class CompilerInstance : public ModuleLoader {
   ///
   /// Explicitly-specified \c VFS takes precedence over the VFS of this 
instance
   /// when creating the clone and also prevents \c FileManager sharing.
+  /// Explicitly-specified \c DiagConsumer takes precedence over forwarding to
+  /// this instance.
   std::unique_ptr<CompilerInstance> cloneForModuleCompileImpl(
       SourceLocation ImportLoc, StringRef ModuleName, FrontendInputFile Input,
       StringRef OriginalModuleMapFile, StringRef ModuleFileName,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr,
+      DiagnosticConsumer *DiagConsumer = nullptr);
 
 public:
   /// Creates a new \c CompilerInstance for compiling a module.
@@ -861,9 +864,13 @@ class CompilerInstance : public ModuleLoader {
   ///
   /// Explicitly-specified \c VFS takes precedence over the VFS of this 
instance
   /// when creating the clone and also prevents \c FileManager sharing.
-  std::unique_ptr<CompilerInstance> cloneForModuleCompile(
-      SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName,
-      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
+  /// Explicitly-specified \c DiagConsumer takes precedence over forwarding to
+  /// this instance.
+  std::unique_ptr<CompilerInstance>
+  cloneForModuleCompile(SourceLocation ImportLoc, Module *Module,
+                        StringRef ModuleFileName,
+                        IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = 
nullptr,
+                        DiagnosticConsumer *DiagConsumer = nullptr);
 
   /// Compile a module file for the given module, using the options
   /// provided by the importing compiler instance. Returns true if the module
diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index bc663acb034e7..ad502827f98c7 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1153,7 +1153,8 @@ static Language getLanguageFromOptions(const LangOptions 
&LangOpts) {
 std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl(
     SourceLocation ImportLoc, StringRef ModuleName, FrontendInputFile Input,
     StringRef OriginalModuleMapFile, StringRef ModuleFileName,
-    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+    DiagnosticConsumer *DiagConsumer) {
   // Construct a compiler invocation for creating this module.
   auto Invocation = std::make_shared<CompilerInvocation>(getInvocation());
 
@@ -1221,10 +1222,15 @@ std::unique_ptr<CompilerInstance> 
CompilerInstance::cloneForModuleCompileImpl(
     Instance.createFileManager(&getVirtualFileSystem());
   }
 
-  Instance.createDiagnostics(
-      Instance.getVirtualFileSystem(),
-      new ForwardingDiagnosticConsumer(getDiagnosticClient()),
-      /*ShouldOwnClient=*/true);
+  if (DiagConsumer) {
+    Instance.createDiagnostics(Instance.getVirtualFileSystem(), DiagConsumer,
+                               /*ShouldOwnClient=*/false);
+  } else {
+    Instance.createDiagnostics(
+        Instance.getVirtualFileSystem(),
+        new ForwardingDiagnosticConsumer(getDiagnosticClient()),
+        /*ShouldOwnClient=*/true);
+  }
   if (llvm::is_contained(DiagOpts.SystemHeaderWarningsModules, ModuleName))
     Instance.getDiagnostics().setSuppressSystemWarnings(false);
 
@@ -1322,7 +1328,8 @@ static OptionalFileEntryRef 
getPublicModuleMap(FileEntryRef File,
 
 std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompile(
     SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName,
-    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
+    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+    DiagnosticConsumer *DiagConsumer) {
   StringRef ModuleName = Module->getTopLevelModuleName();
 
   InputKind IK(getLanguageFromOptions(getLangOpts()), InputKind::ModuleMap);
@@ -1368,7 +1375,7 @@ std::unique_ptr<CompilerInstance> 
CompilerInstance::cloneForModuleCompile(
         ImportLoc, ModuleName,
         FrontendInputFile(ModuleMapFilePath, IK, IsSystem),
         ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName,
-        std::move(VFS));
+        std::move(VFS), DiagConsumer);
   }
 
   // FIXME: We only need to fake up an input file here as a way of
@@ -1386,7 +1393,7 @@ std::unique_ptr<CompilerInstance> 
CompilerInstance::cloneForModuleCompile(
       ImportLoc, ModuleName,
       FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
       ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName,
-      std::move(VFS));
+      std::move(VFS), DiagConsumer);
 
   std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
       llvm::MemoryBuffer::getMemBufferCopy(InferredModuleMapContent);

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

Reply via email to