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

>From a41ba702f42671f7e9c51c29a846a6c7c7324378 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Mon, 7 Apr 2025 13:30:28 -0700
Subject: [PATCH 1/6] [clang] Extract `CompilerInstance` creation out of
 `compileModuleImpl()`

---
 clang/lib/Frontend/CompilerInstance.cpp | 68 +++++++++++++++----------
 1 file changed, 42 insertions(+), 26 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 9cab17ae70eeb..126398fd6e765 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1150,29 +1150,10 @@ static Language getLanguageFromOptions(const 
LangOptions &LangOpts) {
   return LangOpts.CPlusPlus ? Language::CXX : Language::C;
 }
 
-/// Compile a module file for the given module, using the options
-/// provided by the importing compiler instance. Returns true if the module
-/// was built without errors.
-static bool
-compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation 
ImportLoc,
-                  StringRef ModuleName, FrontendInputFile Input,
-                  StringRef OriginalModuleMapFile, StringRef ModuleFileName,
-                  llvm::function_ref<void(CompilerInstance &)> PreBuildStep =
-                      [](CompilerInstance &) {},
-                  llvm::function_ref<void(CompilerInstance &)> PostBuildStep =
-                      [](CompilerInstance &) {}) {
-  llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
-
-  // Never compile a module that's already finalized - this would cause the
-  // existing module to be freed, causing crashes if it is later referenced
-  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
-          ModuleFileName)) {
-    ImportingInstance.getDiagnostics().Report(
-        ImportLoc, diag::err_module_rebuild_finalized)
-        << ModuleName;
-    return false;
-  }
-
+static std::unique_ptr<CompilerInstance> 
createCompilerInstanceForModuleCompile(
+    CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
+    StringRef ModuleName, FrontendInputFile Input,
+    StringRef OriginalModuleMapFile, StringRef ModuleFileName) {
   // Construct a compiler invocation for creating this module.
   auto Invocation =
       std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
@@ -1226,8 +1207,11 @@ compileModuleImpl(CompilerInstance &ImportingInstance, 
SourceLocation ImportLoc,
   // module.  Since we're sharing an in-memory module cache,
   // CompilerInstance::CompilerInstance is responsible for finalizing the
   // buffers to prevent use-after-frees.
-  CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
-                            &ImportingInstance.getModuleCache());
+  auto InstancePtr = std::make_unique<CompilerInstance>(
+      ImportingInstance.getPCHContainerOperations(),
+      &ImportingInstance.getModuleCache());
+  auto &Instance = *InstancePtr;
+
   auto &Inv = *Invocation;
   Instance.setInvocation(std::move(Invocation));
 
@@ -1267,6 +1251,38 @@ compileModuleImpl(CompilerInstance &ImportingInstance, 
SourceLocation ImportLoc,
   Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
   Inv.getDependencyOutputOpts() = DependencyOutputOptions();
 
+  return InstancePtr;
+}
+
+/// Compile a module file for the given module, using the options
+/// provided by the importing compiler instance. Returns true if the module
+/// was built without errors.
+static bool
+compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation 
ImportLoc,
+                  StringRef ModuleName, FrontendInputFile Input,
+                  StringRef OriginalModuleMapFile, StringRef ModuleFileName,
+                  llvm::function_ref<void(CompilerInstance &)> PreBuildStep =
+                      [](CompilerInstance &) {},
+                  llvm::function_ref<void(CompilerInstance &)> PostBuildStep =
+                      [](CompilerInstance &) {}) {
+  llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
+
+  // Never compile a module that's already finalized - this would cause the
+  // existing module to be freed, causing crashes if it is later referenced
+  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
+          ModuleFileName)) {
+    ImportingInstance.getDiagnostics().Report(
+        ImportLoc, diag::err_module_rebuild_finalized)
+        << ModuleName;
+    return false;
+  }
+
+  std::unique_ptr<CompilerInstance> InstancePtr =
+      createCompilerInstanceForModuleCompile(
+          ImportingInstance, ImportLoc, ModuleName, Input,
+          OriginalModuleMapFile, ModuleFileName);
+  CompilerInstance &Instance = *InstancePtr;
+
   ImportingInstance.getDiagnostics().Report(ImportLoc,
                                             diag::remark_module_build)
     << ModuleName << ModuleFileName;
@@ -1289,7 +1305,7 @@ compileModuleImpl(CompilerInstance &ImportingInstance, 
SourceLocation ImportLoc,
     << ModuleName;
 
   // Propagate the statistics to the parent FileManager.
-  if (!FrontendOpts.ModulesShareFileManager)
+  if (ImportingInstance.getFileManagerPtr() != Instance.getFileManagerPtr())
     ImportingInstance.getFileManager().AddStats(Instance.getFileManager());
 
   if (Crashed) {

>From e5f448d78557625d27d8194f88b24d15c2f9ed77 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Mon, 7 Apr 2025 14:43:43 -0700
Subject: [PATCH 2/6] [clang] Pass `CompilerInstance` instance into
 `compileModuleImpl()` from the outside

---
 clang/lib/Frontend/CompilerInstance.cpp | 109 +++++++++++-------------
 1 file changed, 50 insertions(+), 59 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 126398fd6e765..5ebee46a1116d 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1257,38 +1257,16 @@ static std::unique_ptr<CompilerInstance> 
createCompilerInstanceForModuleCompile(
 /// Compile a module file for the given module, using the options
 /// provided by the importing compiler instance. Returns true if the module
 /// was built without errors.
-static bool
-compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation 
ImportLoc,
-                  StringRef ModuleName, FrontendInputFile Input,
-                  StringRef OriginalModuleMapFile, StringRef ModuleFileName,
-                  llvm::function_ref<void(CompilerInstance &)> PreBuildStep =
-                      [](CompilerInstance &) {},
-                  llvm::function_ref<void(CompilerInstance &)> PostBuildStep =
-                      [](CompilerInstance &) {}) {
+static bool compileModuleImpl(CompilerInstance &ImportingInstance,
+                              SourceLocation ImportLoc, StringRef ModuleName,
+                              StringRef ModuleFileName,
+                              CompilerInstance &Instance) {
   llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
 
-  // Never compile a module that's already finalized - this would cause the
-  // existing module to be freed, causing crashes if it is later referenced
-  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
-          ModuleFileName)) {
-    ImportingInstance.getDiagnostics().Report(
-        ImportLoc, diag::err_module_rebuild_finalized)
-        << ModuleName;
-    return false;
-  }
-
-  std::unique_ptr<CompilerInstance> InstancePtr =
-      createCompilerInstanceForModuleCompile(
-          ImportingInstance, ImportLoc, ModuleName, Input,
-          OriginalModuleMapFile, ModuleFileName);
-  CompilerInstance &Instance = *InstancePtr;
-
   ImportingInstance.getDiagnostics().Report(ImportLoc,
                                             diag::remark_module_build)
     << ModuleName << ModuleFileName;
 
-  PreBuildStep(Instance);
-
   // Execute the action to actually build the module in-place. Use a separate
   // thread so that we get a stack large enough.
   bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
@@ -1298,8 +1276,6 @@ compileModuleImpl(CompilerInstance &ImportingInstance, 
SourceLocation ImportLoc,
       },
       DesiredStackSize);
 
-  PostBuildStep(Instance);
-
   ImportingInstance.getDiagnostics().Report(ImportLoc,
                                             diag::remark_module_build_done)
     << ModuleName;
@@ -1343,6 +1319,18 @@ static OptionalFileEntryRef 
getPublicModuleMap(FileEntryRef File,
 static bool compileModule(CompilerInstance &ImportingInstance,
                           SourceLocation ImportLoc, Module *Module,
                           StringRef ModuleFileName) {
+  StringRef ModuleName = Module->getTopLevelModuleName();
+
+  // Never compile a module that's already finalized - this would cause the
+  // existing module to be freed, causing crashes if it is later referenced
+  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
+          ModuleFileName)) {
+    ImportingInstance.getDiagnostics().Report(
+        ImportLoc, diag::err_module_rebuild_finalized)
+        << ModuleName;
+    return false;
+  }
+
   InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
                InputKind::ModuleMap);
 
@@ -1350,7 +1338,8 @@ static bool compileModule(CompilerInstance 
&ImportingInstance,
   ModuleMap &ModMap
     = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
   SourceManager &SourceMgr = ImportingInstance.getSourceManager();
-  bool Result;
+
+  std::unique_ptr<CompilerInstance> Instance;
   if (FileID ModuleMapFID = ModMap.getContainingModuleMapFileID(Module);
       ModuleMapFID.isValid()) {
     // We want to use the top-level module map. If we don't, the compiling
@@ -1384,8 +1373,8 @@ static bool compileModule(CompilerInstance 
&ImportingInstance,
     bool IsSystem = isSystem(SLoc.getFile().getFileCharacteristic());
 
     // Use the module map where this module resides.
-    Result = compileModuleImpl(
-        ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
+    Instance = createCompilerInstanceForModuleCompile(
+        ImportingInstance, ImportLoc, ModuleName,
         FrontendInputFile(ModuleMapFilePath, IK, IsSystem),
         ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
   } else {
@@ -1400,28 +1389,29 @@ static bool compileModule(CompilerInstance 
&ImportingInstance,
     llvm::raw_string_ostream OS(InferredModuleMapContent);
     Module->print(OS);
 
-    Result = compileModuleImpl(
-        ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
+    Instance = createCompilerInstanceForModuleCompile(
+        ImportingInstance, ImportLoc, ModuleName,
         FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
-        ModMap.getModuleMapFileForUniquing(Module)->getName(),
-        ModuleFileName,
-        [&](CompilerInstance &Instance) {
-      std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
-          llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
-      FileEntryRef ModuleMapFile = Instance.getFileManager().getVirtualFileRef(
-          FakeModuleMapFile, InferredModuleMapContent.size(), 0);
-      Instance.getSourceManager().overrideFileContents(
-          ModuleMapFile, std::move(ModuleMapBuffer));
-    });
+        ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
+
+    std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
+        llvm::MemoryBuffer::getMemBufferCopy(InferredModuleMapContent);
+    FileEntryRef ModuleMapFile = Instance->getFileManager().getVirtualFileRef(
+        FakeModuleMapFile, InferredModuleMapContent.size(), 0);
+    Instance->getSourceManager().overrideFileContents(
+        ModuleMapFile, std::move(ModuleMapBuffer));
   }
 
+  bool Success = compileModuleImpl(ImportingInstance, ImportLoc, ModuleName,
+                                   ModuleFileName, *Instance);
+
   // We've rebuilt a module. If we're allowed to generate or update the global
   // module index, record that fact in the importing compiler instance.
   if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
     ImportingInstance.setBuildGlobalModuleIndex(true);
   }
 
-  return Result;
+  return Success;
 }
 
 /// Read the AST right after compiling the module.
@@ -2248,25 +2238,26 @@ void 
CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
 
   std::string NullTerminatedSource(Source.str());
 
-  auto PreBuildStep = [&](CompilerInstance &Other) {
-    // Create a virtual file containing our desired source.
-    // FIXME: We shouldn't need to do this.
-    FileEntryRef ModuleMapFile = Other.getFileManager().getVirtualFileRef(
-        ModuleMapFileName, NullTerminatedSource.size(), 0);
-    Other.getSourceManager().overrideFileContents(
-        ModuleMapFile, llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource));
+  auto Other = createCompilerInstanceForModuleCompile(
+      *this, ImportLoc, ModuleName, Input, StringRef(), ModuleFileName);
 
-    Other.BuiltModules = std::move(BuiltModules);
-    Other.DeleteBuiltModules = false;
-  };
+  // Create a virtual file containing our desired source.
+  // FIXME: We shouldn't need to do this.
+  FileEntryRef ModuleMapFile = Other->getFileManager().getVirtualFileRef(
+      ModuleMapFileName, NullTerminatedSource.size(), 0);
+  Other->getSourceManager().overrideFileContents(
+      ModuleMapFile, llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource));
 
-  auto PostBuildStep = [this](CompilerInstance &Other) {
-    BuiltModules = std::move(Other.BuiltModules);
-  };
+  Other->BuiltModules = std::move(BuiltModules);
+  Other->DeleteBuiltModules = false;
 
   // Build the module, inheriting any modules that we've built locally.
-  if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(),
-                        ModuleFileName, PreBuildStep, PostBuildStep)) {
+  bool Success =
+      compileModuleImpl(*this, ImportLoc, ModuleName, ModuleFileName, *Other);
+
+  BuiltModules = std::move(Other->BuiltModules);
+
+  if (Success) {
     BuiltModules[std::string(ModuleName)] = std::string(ModuleFileName);
     llvm::sys::RemoveFileOnSignal(ModuleFileName);
   }

>From 5bc798d2924d3c7f844d76c034f40901312ac379 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Tue, 8 Apr 2025 10:24:00 -0700
Subject: [PATCH 3/6] [clang] Also extract the `FrontendInputFile` logic

---
 clang/lib/Frontend/CompilerInstance.cpp | 221 +++++++++++++-----------
 1 file changed, 121 insertions(+), 100 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 5ebee46a1116d..62fff9e2397a1 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1138,22 +1138,16 @@ void CompilerInstance::LoadRequestedPlugins() {
   }
 }
 
-/// Determine the appropriate source input kind based on language
-/// options.
-static Language getLanguageFromOptions(const LangOptions &LangOpts) {
-  if (LangOpts.OpenCL)
-    return Language::OpenCL;
-  if (LangOpts.CUDA)
-    return Language::CUDA;
-  if (LangOpts.ObjC)
-    return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
-  return LangOpts.CPlusPlus ? Language::CXX : Language::C;
-}
-
-static std::unique_ptr<CompilerInstance> 
createCompilerInstanceForModuleCompile(
-    CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
-    StringRef ModuleName, FrontendInputFile Input,
-    StringRef OriginalModuleMapFile, StringRef ModuleFileName) {
+/// Creates a \c CompilerInstance for compiling a module.
+///
+/// This expects a properly initialized \c FrontendInputFile.
+static std::unique_ptr<CompilerInstance>
+createCompilerInstanceForModuleCompileImpl(CompilerInstance &ImportingInstance,
+                                           SourceLocation ImportLoc,
+                                           StringRef ModuleName,
+                                           FrontendInputFile Input,
+                                           StringRef OriginalModuleMapFile,
+                                           StringRef ModuleFileName) {
   // Construct a compiler invocation for creating this module.
   auto Invocation =
       std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
@@ -1254,6 +1248,114 @@ static std::unique_ptr<CompilerInstance> 
createCompilerInstanceForModuleCompile(
   return InstancePtr;
 }
 
+/// Determine the appropriate source input kind based on language
+/// options.
+static Language getLanguageFromOptions(const LangOptions &LangOpts) {
+  if (LangOpts.OpenCL)
+    return Language::OpenCL;
+  if (LangOpts.CUDA)
+    return Language::CUDA;
+  if (LangOpts.ObjC)
+    return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
+  return LangOpts.CPlusPlus ? Language::CXX : Language::C;
+}
+
+static OptionalFileEntryRef getPublicModuleMap(FileEntryRef File,
+                                               FileManager &FileMgr) {
+  StringRef Filename = llvm::sys::path::filename(File.getName());
+  SmallString<128> PublicFilename(File.getDir().getName());
+  if (Filename == "module_private.map")
+    llvm::sys::path::append(PublicFilename, "module.map");
+  else if (Filename == "module.private.modulemap")
+    llvm::sys::path::append(PublicFilename, "module.modulemap");
+  else
+    return std::nullopt;
+  return FileMgr.getOptionalFileRef(PublicFilename);
+}
+
+/// Creates a \c CompilerInstance for compiling a module.
+///
+/// This takes care of creating appropriate \c FrontendInputFile for
+/// public/private frameworks, inferred modules and such.
+static std::unique_ptr<CompilerInstance>
+createCompilerInstanceForModuleCompile(CompilerInstance &ImportingInstance,
+                                       SourceLocation ImportLoc, Module 
*Module,
+                                       StringRef ModuleFileName) {
+  StringRef ModuleName = Module->getTopLevelModuleName();
+
+  InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
+               InputKind::ModuleMap);
+
+  // Get or create the module map that we'll use to build this module.
+  ModuleMap &ModMap =
+      ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+  SourceManager &SourceMgr = ImportingInstance.getSourceManager();
+
+  if (FileID ModuleMapFID = ModMap.getContainingModuleMapFileID(Module);
+      ModuleMapFID.isValid()) {
+    // We want to use the top-level module map. If we don't, the compiling
+    // instance may think the containing module map is a top-level one, while
+    // the importing instance knows it's included from a parent module map via
+    // the extern directive. This mismatch could bite us later.
+    SourceLocation Loc = SourceMgr.getIncludeLoc(ModuleMapFID);
+    while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) 
{
+      ModuleMapFID = SourceMgr.getFileID(Loc);
+      Loc = SourceMgr.getIncludeLoc(ModuleMapFID);
+    }
+
+    OptionalFileEntryRef ModuleMapFile =
+        SourceMgr.getFileEntryRefForID(ModuleMapFID);
+    assert(ModuleMapFile && "Top-level module map with no FileID");
+
+    // Canonicalize compilation to start with the public module map. This is
+    // vital for submodules declarations in the private module maps to be
+    // correctly parsed when depending on a top level module in the public one.
+    if (OptionalFileEntryRef PublicMMFile = getPublicModuleMap(
+            *ModuleMapFile, ImportingInstance.getFileManager()))
+      ModuleMapFile = PublicMMFile;
+
+    StringRef ModuleMapFilePath = ModuleMapFile->getNameAsRequested();
+
+    // Use the systemness of the module map as parsed instead of using the
+    // IsSystem attribute of the module. If the module has [system] but the
+    // module map is not in a system path, then this would incorrectly parse
+    // any other modules in that module map as system too.
+    const SrcMgr::SLocEntry &SLoc = SourceMgr.getSLocEntry(ModuleMapFID);
+    bool IsSystem = isSystem(SLoc.getFile().getFileCharacteristic());
+
+    // Use the module map where this module resides.
+    return createCompilerInstanceForModuleCompileImpl(
+        ImportingInstance, ImportLoc, ModuleName,
+        FrontendInputFile(ModuleMapFilePath, IK, IsSystem),
+        ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
+  }
+
+  // FIXME: We only need to fake up an input file here as a way of
+  // transporting the module's directory to the module map parser. We should
+  // be able to do that more directly, and parse from a memory buffer without
+  // inventing this file.
+  SmallString<128> FakeModuleMapFile(Module->Directory->getName());
+  llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
+
+  std::string InferredModuleMapContent;
+  llvm::raw_string_ostream OS(InferredModuleMapContent);
+  Module->print(OS);
+
+  auto Instance = createCompilerInstanceForModuleCompileImpl(
+      ImportingInstance, ImportLoc, ModuleName,
+      FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
+      ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
+
+  std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
+      llvm::MemoryBuffer::getMemBufferCopy(InferredModuleMapContent);
+  FileEntryRef ModuleMapFile = Instance->getFileManager().getVirtualFileRef(
+      FakeModuleMapFile, InferredModuleMapContent.size(), 0);
+  Instance->getSourceManager().overrideFileContents(ModuleMapFile,
+                                                    
std::move(ModuleMapBuffer));
+
+  return Instance;
+}
+
 /// Compile a module file for the given module, using the options
 /// provided by the importing compiler instance. Returns true if the module
 /// was built without errors.
@@ -1300,19 +1402,6 @@ static bool compileModuleImpl(CompilerInstance 
&ImportingInstance,
          Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
 }
 
-static OptionalFileEntryRef getPublicModuleMap(FileEntryRef File,
-                                               FileManager &FileMgr) {
-  StringRef Filename = llvm::sys::path::filename(File.getName());
-  SmallString<128> PublicFilename(File.getDir().getName());
-  if (Filename == "module_private.map")
-    llvm::sys::path::append(PublicFilename, "module.map");
-  else if (Filename == "module.private.modulemap")
-    llvm::sys::path::append(PublicFilename, "module.modulemap");
-  else
-    return std::nullopt;
-  return FileMgr.getOptionalFileRef(PublicFilename);
-}
-
 /// Compile a module file for the given module in a separate compiler instance,
 /// using the options provided by the importing compiler instance. Returns true
 /// if the module was built without errors.
@@ -1331,76 +1420,8 @@ static bool compileModule(CompilerInstance 
&ImportingInstance,
     return false;
   }
 
-  InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
-               InputKind::ModuleMap);
-
-  // Get or create the module map that we'll use to build this module.
-  ModuleMap &ModMap
-    = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
-  SourceManager &SourceMgr = ImportingInstance.getSourceManager();
-
-  std::unique_ptr<CompilerInstance> Instance;
-  if (FileID ModuleMapFID = ModMap.getContainingModuleMapFileID(Module);
-      ModuleMapFID.isValid()) {
-    // We want to use the top-level module map. If we don't, the compiling
-    // instance may think the containing module map is a top-level one, while
-    // the importing instance knows it's included from a parent module map via
-    // the extern directive. This mismatch could bite us later.
-    SourceLocation Loc = SourceMgr.getIncludeLoc(ModuleMapFID);
-    while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) 
{
-      ModuleMapFID = SourceMgr.getFileID(Loc);
-      Loc = SourceMgr.getIncludeLoc(ModuleMapFID);
-    }
-
-    OptionalFileEntryRef ModuleMapFile =
-        SourceMgr.getFileEntryRefForID(ModuleMapFID);
-    assert(ModuleMapFile && "Top-level module map with no FileID");
-
-    // Canonicalize compilation to start with the public module map. This is
-    // vital for submodules declarations in the private module maps to be
-    // correctly parsed when depending on a top level module in the public one.
-    if (OptionalFileEntryRef PublicMMFile = getPublicModuleMap(
-            *ModuleMapFile, ImportingInstance.getFileManager()))
-      ModuleMapFile = PublicMMFile;
-
-    StringRef ModuleMapFilePath = ModuleMapFile->getNameAsRequested();
-
-    // Use the systemness of the module map as parsed instead of using the
-    // IsSystem attribute of the module. If the module has [system] but the
-    // module map is not in a system path, then this would incorrectly parse
-    // any other modules in that module map as system too.
-    const SrcMgr::SLocEntry &SLoc = SourceMgr.getSLocEntry(ModuleMapFID);
-    bool IsSystem = isSystem(SLoc.getFile().getFileCharacteristic());
-
-    // Use the module map where this module resides.
-    Instance = createCompilerInstanceForModuleCompile(
-        ImportingInstance, ImportLoc, ModuleName,
-        FrontendInputFile(ModuleMapFilePath, IK, IsSystem),
-        ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
-  } else {
-    // FIXME: We only need to fake up an input file here as a way of
-    // transporting the module's directory to the module map parser. We should
-    // be able to do that more directly, and parse from a memory buffer without
-    // inventing this file.
-    SmallString<128> FakeModuleMapFile(Module->Directory->getName());
-    llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
-
-    std::string InferredModuleMapContent;
-    llvm::raw_string_ostream OS(InferredModuleMapContent);
-    Module->print(OS);
-
-    Instance = createCompilerInstanceForModuleCompile(
-        ImportingInstance, ImportLoc, ModuleName,
-        FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
-        ModMap.getModuleMapFileForUniquing(Module)->getName(), ModuleFileName);
-
-    std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
-        llvm::MemoryBuffer::getMemBufferCopy(InferredModuleMapContent);
-    FileEntryRef ModuleMapFile = Instance->getFileManager().getVirtualFileRef(
-        FakeModuleMapFile, InferredModuleMapContent.size(), 0);
-    Instance->getSourceManager().overrideFileContents(
-        ModuleMapFile, std::move(ModuleMapBuffer));
-  }
+  auto Instance = createCompilerInstanceForModuleCompile(
+      ImportingInstance, ImportLoc, Module, ModuleFileName);
 
   bool Success = compileModuleImpl(ImportingInstance, ImportLoc, ModuleName,
                                    ModuleFileName, *Instance);
@@ -2238,7 +2259,7 @@ void 
CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
 
   std::string NullTerminatedSource(Source.str());
 
-  auto Other = createCompilerInstanceForModuleCompile(
+  auto Other = createCompilerInstanceForModuleCompileImpl(
       *this, ImportLoc, ModuleName, Input, StringRef(), ModuleFileName);
 
   // Create a virtual file containing our desired source.

>From 7baba5b26b9cf5d0161875fdb3c6a88a6e462395 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Thu, 10 Apr 2025 15:39:45 -0700
Subject: [PATCH 4/6] Squash `compileModule()` and `compileModuleImpl()`

---
 clang/lib/Frontend/CompilerInstance.cpp | 63 ++++++++++---------------
 1 file changed, 25 insertions(+), 38 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index 62fff9e2397a1..db5390fb71af6 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1359,12 +1359,22 @@ createCompilerInstanceForModuleCompile(CompilerInstance 
&ImportingInstance,
 /// Compile a module file for the given module, using the options
 /// provided by the importing compiler instance. Returns true if the module
 /// was built without errors.
-static bool compileModuleImpl(CompilerInstance &ImportingInstance,
-                              SourceLocation ImportLoc, StringRef ModuleName,
-                              StringRef ModuleFileName,
-                              CompilerInstance &Instance) {
+static bool compileModule(CompilerInstance &ImportingInstance,
+                          SourceLocation ImportLoc, StringRef ModuleName,
+                          StringRef ModuleFileName,
+                          CompilerInstance &Instance) {
   llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
 
+  // Never compile a module that's already finalized - this would cause the
+  // existing module to be freed, causing crashes if it is later referenced
+  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
+          ModuleFileName)) {
+    ImportingInstance.getDiagnostics().Report(
+        ImportLoc, diag::err_module_rebuild_finalized)
+        << ModuleName;
+    return false;
+  }
+
   ImportingInstance.getDiagnostics().Report(ImportLoc,
                                             diag::remark_module_build)
     << ModuleName << ModuleFileName;
@@ -1396,43 +1406,16 @@ static bool compileModuleImpl(CompilerInstance 
&ImportingInstance,
     Instance.clearOutputFiles(/*EraseFiles=*/true);
   }
 
-  // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
-  // occurred.
-  return !Instance.getDiagnostics().hasErrorOccurred() ||
-         Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
-}
-
-/// Compile a module file for the given module in a separate compiler instance,
-/// using the options provided by the importing compiler instance. Returns true
-/// if the module was built without errors.
-static bool compileModule(CompilerInstance &ImportingInstance,
-                          SourceLocation ImportLoc, Module *Module,
-                          StringRef ModuleFileName) {
-  StringRef ModuleName = Module->getTopLevelModuleName();
-
-  // Never compile a module that's already finalized - this would cause the
-  // existing module to be freed, causing crashes if it is later referenced
-  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
-          ModuleFileName)) {
-    ImportingInstance.getDiagnostics().Report(
-        ImportLoc, diag::err_module_rebuild_finalized)
-        << ModuleName;
-    return false;
-  }
-
-  auto Instance = createCompilerInstanceForModuleCompile(
-      ImportingInstance, ImportLoc, Module, ModuleFileName);
-
-  bool Success = compileModuleImpl(ImportingInstance, ImportLoc, ModuleName,
-                                   ModuleFileName, *Instance);
-
   // We've rebuilt a module. If we're allowed to generate or update the global
   // module index, record that fact in the importing compiler instance.
   if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
     ImportingInstance.setBuildGlobalModuleIndex(true);
   }
 
-  return Success;
+  // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
+  // occurred.
+  return !Instance.getDiagnostics().hasErrorOccurred() ||
+         Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
 }
 
 /// Read the AST right after compiling the module.
@@ -1482,8 +1465,12 @@ static bool compileModuleAndReadASTImpl(CompilerInstance 
&ImportingInstance,
                                         SourceLocation ModuleNameLoc,
                                         Module *Module,
                                         StringRef ModuleFileName) {
-  if (!compileModule(ImportingInstance, ModuleNameLoc, Module,
-                     ModuleFileName)) {
+  auto Instance = createCompilerInstanceForModuleCompile(
+      ImportingInstance, ImportLoc, Module, ModuleFileName);
+
+  if (!compileModule(ImportingInstance, ModuleNameLoc,
+                     Module->getTopLevelModuleName(), ModuleFileName,
+                     *Instance)) {
     ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
                                               diag::err_module_not_built)
         << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
@@ -2274,7 +2261,7 @@ void 
CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
 
   // Build the module, inheriting any modules that we've built locally.
   bool Success =
-      compileModuleImpl(*this, ImportLoc, ModuleName, ModuleFileName, *Other);
+      compileModule(*this, ImportLoc, ModuleName, ModuleFileName, *Other);
 
   BuiltModules = std::move(Other->BuiltModules);
 

>From 7de880d67d445a4ce9566efe568ff38171175e11 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Thu, 10 Apr 2025 15:44:29 -0700
Subject: [PATCH 5/6] Minimize diff

---
 clang/lib/Frontend/CompilerInstance.cpp | 144 ++++++++++++------------
 1 file changed, 72 insertions(+), 72 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index db5390fb71af6..b1dcc190ab988 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1138,6 +1138,18 @@ void CompilerInstance::LoadRequestedPlugins() {
   }
 }
 
+/// Determine the appropriate source input kind based on language
+/// options.
+static Language getLanguageFromOptions(const LangOptions &LangOpts) {
+  if (LangOpts.OpenCL)
+    return Language::OpenCL;
+  if (LangOpts.CUDA)
+    return Language::CUDA;
+  if (LangOpts.ObjC)
+    return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
+  return LangOpts.CPlusPlus ? Language::CXX : Language::C;
+}
+
 /// Creates a \c CompilerInstance for compiling a module.
 ///
 /// This expects a properly initialized \c FrontendInputFile.
@@ -1248,16 +1260,66 @@ 
createCompilerInstanceForModuleCompileImpl(CompilerInstance &ImportingInstance,
   return InstancePtr;
 }
 
-/// Determine the appropriate source input kind based on language
-/// options.
-static Language getLanguageFromOptions(const LangOptions &LangOpts) {
-  if (LangOpts.OpenCL)
-    return Language::OpenCL;
-  if (LangOpts.CUDA)
-    return Language::CUDA;
-  if (LangOpts.ObjC)
-    return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
-  return LangOpts.CPlusPlus ? Language::CXX : Language::C;
+/// Compile a module file for the given module, using the options
+/// provided by the importing compiler instance. Returns true if the module
+/// was built without errors.
+static bool compileModule(CompilerInstance &ImportingInstance,
+                          SourceLocation ImportLoc, StringRef ModuleName,
+                          StringRef ModuleFileName,
+                          CompilerInstance &Instance) {
+  llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
+
+  // Never compile a module that's already finalized - this would cause the
+  // existing module to be freed, causing crashes if it is later referenced
+  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
+          ModuleFileName)) {
+    ImportingInstance.getDiagnostics().Report(
+        ImportLoc, diag::err_module_rebuild_finalized)
+        << ModuleName;
+    return false;
+  }
+
+  ImportingInstance.getDiagnostics().Report(ImportLoc,
+                                            diag::remark_module_build)
+    << ModuleName << ModuleFileName;
+
+  // Execute the action to actually build the module in-place. Use a separate
+  // thread so that we get a stack large enough.
+  bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
+      [&]() {
+        GenerateModuleFromModuleMapAction Action;
+        Instance.ExecuteAction(Action);
+      },
+      DesiredStackSize);
+
+  ImportingInstance.getDiagnostics().Report(ImportLoc,
+                                            diag::remark_module_build_done)
+    << ModuleName;
+
+  // Propagate the statistics to the parent FileManager.
+  if (ImportingInstance.getFrontendOpts().ModulesShareFileManager)
+    ImportingInstance.getFileManager().AddStats(Instance.getFileManager());
+
+  if (Crashed) {
+    // Clear the ASTConsumer if it hasn't been already, in case it owns streams
+    // that must be closed before clearing output files.
+    Instance.setSema(nullptr);
+    Instance.setASTConsumer(nullptr);
+
+    // Delete any remaining temporary files related to Instance.
+    Instance.clearOutputFiles(/*EraseFiles=*/true);
+  }
+
+  // We've rebuilt a module. If we're allowed to generate or update the global
+  // module index, record that fact in the importing compiler instance.
+  if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
+    ImportingInstance.setBuildGlobalModuleIndex(true);
+  }
+
+  // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
+  // occurred.
+  return !Instance.getDiagnostics().hasErrorOccurred() ||
+         Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
 }
 
 static OptionalFileEntryRef getPublicModuleMap(FileEntryRef File,
@@ -1356,68 +1418,6 @@ createCompilerInstanceForModuleCompile(CompilerInstance 
&ImportingInstance,
   return Instance;
 }
 
-/// Compile a module file for the given module, using the options
-/// provided by the importing compiler instance. Returns true if the module
-/// was built without errors.
-static bool compileModule(CompilerInstance &ImportingInstance,
-                          SourceLocation ImportLoc, StringRef ModuleName,
-                          StringRef ModuleFileName,
-                          CompilerInstance &Instance) {
-  llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
-
-  // Never compile a module that's already finalized - this would cause the
-  // existing module to be freed, causing crashes if it is later referenced
-  if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
-          ModuleFileName)) {
-    ImportingInstance.getDiagnostics().Report(
-        ImportLoc, diag::err_module_rebuild_finalized)
-        << ModuleName;
-    return false;
-  }
-
-  ImportingInstance.getDiagnostics().Report(ImportLoc,
-                                            diag::remark_module_build)
-    << ModuleName << ModuleFileName;
-
-  // Execute the action to actually build the module in-place. Use a separate
-  // thread so that we get a stack large enough.
-  bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
-      [&]() {
-        GenerateModuleFromModuleMapAction Action;
-        Instance.ExecuteAction(Action);
-      },
-      DesiredStackSize);
-
-  ImportingInstance.getDiagnostics().Report(ImportLoc,
-                                            diag::remark_module_build_done)
-    << ModuleName;
-
-  // Propagate the statistics to the parent FileManager.
-  if (ImportingInstance.getFileManagerPtr() != Instance.getFileManagerPtr())
-    ImportingInstance.getFileManager().AddStats(Instance.getFileManager());
-
-  if (Crashed) {
-    // Clear the ASTConsumer if it hasn't been already, in case it owns streams
-    // that must be closed before clearing output files.
-    Instance.setSema(nullptr);
-    Instance.setASTConsumer(nullptr);
-
-    // Delete any remaining temporary files related to Instance.
-    Instance.clearOutputFiles(/*EraseFiles=*/true);
-  }
-
-  // We've rebuilt a module. If we're allowed to generate or update the global
-  // module index, record that fact in the importing compiler instance.
-  if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
-    ImportingInstance.setBuildGlobalModuleIndex(true);
-  }
-
-  // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
-  // occurred.
-  return !Instance.getDiagnostics().hasErrorOccurred() ||
-         Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
-}
-
 /// Read the AST right after compiling the module.
 static bool readASTAfterCompileModule(CompilerInstance &ImportingInstance,
                                       SourceLocation ImportLoc,

>From 922ee8a6fe7b04ab097b9ea58f06b7b5c66af9a5 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svob...@apple.com>
Date: Thu, 10 Apr 2025 18:16:45 -0700
Subject: [PATCH 6/6] Fix flipped condition

---
 clang/lib/Frontend/CompilerInstance.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Frontend/CompilerInstance.cpp 
b/clang/lib/Frontend/CompilerInstance.cpp
index b1dcc190ab988..95b0bfedb7cd8 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1297,7 +1297,7 @@ static bool compileModule(CompilerInstance 
&ImportingInstance,
     << ModuleName;
 
   // Propagate the statistics to the parent FileManager.
-  if (ImportingInstance.getFrontendOpts().ModulesShareFileManager)
+  if (!ImportingInstance.getFrontendOpts().ModulesShareFileManager)
     ImportingInstance.getFileManager().AddStats(Instance.getFileManager());
 
   if (Crashed) {

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

Reply via email to