[clang] [clang] Extract `CompilerInstance` creation out of `compileModuleImpl()` (PR #134887)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 8 10:25:02 PDT 2025
https://github.com/jansvoboda11 created https://github.com/llvm/llvm-project/pull/134887
This PR extracts the creation of `CompilerInstance` for compiling an implicitly-discovered module out of `compileModuleImpl()` into its own separate function and passes it into `compileModuleImpl()` from the outside. This makes the instance creation logic reusable (useful for my experiments) and also simplifies the API, removing the `PreBuildStep` and `PostBuildStep` hooks from `compileModuleImpl()`.
>From a41ba702f42671f7e9c51c29a846a6c7c7324378 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 7 Apr 2025 13:30:28 -0700
Subject: [PATCH 1/3] [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_svoboda at apple.com>
Date: Mon, 7 Apr 2025 14:43:43 -0700
Subject: [PATCH 2/3] [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_svoboda at apple.com>
Date: Tue, 8 Apr 2025 10:24:00 -0700
Subject: [PATCH 3/3] [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.
More information about the cfe-commits
mailing list