[clang-tools-extra] 448d8fa - [NFC] [clangd] [Modules] Extract ModuleFile class and IsModuleFileUpToDate function
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 29 23:48:19 PDT 2024
Author: Chuanqi Xu
Date: 2024-08-30T14:43:41+08:00
New Revision: 448d8fa880be5cae0f63c3b248f07f647013a5a4
URL: https://github.com/llvm/llvm-project/commit/448d8fa880be5cae0f63c3b248f07f647013a5a4
DIFF: https://github.com/llvm/llvm-project/commit/448d8fa880be5cae0f63c3b248f07f647013a5a4.diff
LOG: [NFC] [clangd] [Modules] Extract ModuleFile class and IsModuleFileUpToDate function
This patch extracts ModuleFile class from StandalonePrerequisiteModules
so that we can reuse it further. And also we implement
IsModuleFileUpToDate function to implement
StandalonePrerequisiteModules::CanReuse. Both of them aims to ease the
future improvements to the support of modules in clangd. And both of
them should be NFC.
Added:
Modified:
clang-tools-extra/clangd/ModulesBuilder.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp
index 94c7eec2d09e4e..dd00adc6f6c8d2 100644
--- a/clang-tools-extra/clangd/ModulesBuilder.cpp
+++ b/clang-tools-extra/clangd/ModulesBuilder.cpp
@@ -92,6 +92,88 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
}
};
+struct ModuleFile {
+ ModuleFile(StringRef ModuleName, PathRef ModuleFilePath)
+ : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
+
+ ModuleFile() = delete;
+
+ ModuleFile(const ModuleFile &) = delete;
+ ModuleFile operator=(const ModuleFile &) = delete;
+
+ // The move constructor is needed for llvm::SmallVector.
+ ModuleFile(ModuleFile &&Other)
+ : ModuleName(std::move(Other.ModuleName)),
+ ModuleFilePath(std::move(Other.ModuleFilePath)) {
+ Other.ModuleName.clear();
+ Other.ModuleFilePath.clear();
+ }
+
+ ModuleFile &operator=(ModuleFile &&Other) {
+ if (this == &Other)
+ return *this;
+
+ this->~ModuleFile();
+ new (this) ModuleFile(std::move(Other));
+ return *this;
+ }
+
+ ~ModuleFile() {
+ if (!ModuleFilePath.empty())
+ llvm::sys::fs::remove(ModuleFilePath);
+ }
+
+ std::string ModuleName;
+ std::string ModuleFilePath;
+};
+
+bool IsModuleFileUpToDate(
+ PathRef ModuleFilePath,
+ const PrerequisiteModules *RequisiteModules) {
+IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ CompilerInstance::createDiagnostics(new DiagnosticOptions());
+
+ auto HSOpts = std::make_shared<HeaderSearchOptions>();
+ if (RequisiteModules)
+ RequisiteModules->adjustHeaderSearchOptions(*HSOpts);
+ HSOpts->ForceCheckCXX20ModulesInputFiles = true;
+ HSOpts->ValidateASTInputFilesContent = true;
+
+ PCHContainerOperations PCHOperations;
+ std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
+ ModuleFilePath.str(), PCHOperations.getRawReader(), ASTUnit::LoadASTOnly,
+ Diags, FileSystemOptions(), std::move(HSOpts));
+
+ if (!Unit)
+ return false;
+
+ auto Reader = Unit->getASTReader();
+ if (!Reader)
+ return false;
+
+ bool UpToDate = true;
+ Reader->getModuleManager().visit([&](serialization::ModuleFile &MF) -> bool {
+ Reader->visitInputFiles(
+ MF, /*IncludeSystem=*/false, /*Complain=*/false,
+ [&](const serialization::InputFile &IF, bool isSystem) {
+ if (!IF.getFile() || IF.isOutOfDate())
+ UpToDate = false;
+ });
+
+ return !UpToDate;
+ });
+
+ return UpToDate;
+}
+
+bool IsModuleFilesUpToDate(
+ llvm::SmallVector<PathRef> ModuleFilePaths,
+ const PrerequisiteModules *RequisiteModules = nullptr) {
+ return llvm::all_of(ModuleFilePaths, [RequisiteModules](auto ModuleFilePath) {
+ return IsModuleFileUpToDate(ModuleFilePath, RequisiteModules);
+ });
+}
+
// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all
// the required modules are built successfully. All the module files
// are owned by the StandalonePrerequisiteModules class.
@@ -135,29 +217,6 @@ class StandalonePrerequisiteModules : public PrerequisiteModules {
}
private:
- struct ModuleFile {
- ModuleFile(llvm::StringRef ModuleName, PathRef ModuleFilePath)
- : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
-
- ModuleFile(const ModuleFile &) = delete;
- ModuleFile operator=(const ModuleFile &) = delete;
-
- // The move constructor is needed for llvm::SmallVector.
- ModuleFile(ModuleFile &&Other)
- : ModuleName(std::move(Other.ModuleName)),
- ModuleFilePath(std::move(Other.ModuleFilePath)) {}
-
- ModuleFile &operator=(ModuleFile &&Other) = delete;
-
- ~ModuleFile() {
- if (!ModuleFilePath.empty())
- llvm::sys::fs::remove(ModuleFilePath);
- }
-
- std::string ModuleName;
- std::string ModuleFilePath;
- };
-
llvm::SmallVector<ModuleFile, 8> RequiredModules;
// A helper class to speedup the query if a module is built.
llvm::StringSet<> BuiltModuleNames;
@@ -286,50 +345,10 @@ bool StandalonePrerequisiteModules::canReuse(
if (RequiredModules.empty())
return true;
- CompilerInstance Clang;
-
- Clang.setInvocation(std::make_shared<CompilerInvocation>(CI));
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
- CompilerInstance::createDiagnostics(new DiagnosticOptions());
- Clang.setDiagnostics(Diags.get());
-
- FileManager *FM = Clang.createFileManager(VFS);
- Clang.createSourceManager(*FM);
-
- if (!Clang.createTarget())
- return false;
-
- assert(Clang.getHeaderSearchOptsPtr());
- adjustHeaderSearchOptions(Clang.getHeaderSearchOpts());
- // Since we don't need to compile the source code actually, the TU kind here
- // doesn't matter.
- Clang.createPreprocessor(TU_Complete);
- Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;
- Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
-
- // Following the practice of clang's driver to suppres the checking for ODR
- // violation in GMF.
- // See
- // https://clang.llvm.org/docs/StandardCPlusPlusModules.html#object-definition-consistency
- // for example.
- Clang.getLangOpts().SkipODRCheckInGMF = true;
-
- Clang.createASTReader();
- for (auto &RequiredModule : RequiredModules) {
- llvm::StringRef BMIPath = RequiredModule.ModuleFilePath;
- // FIXME: Loading BMI fully is too heavy considering something cheaply to
- // check if we can reuse the BMI.
- auto ReadResult =
- Clang.getASTReader()->ReadAST(BMIPath, serialization::MK_MainFile,
- SourceLocation(), ASTReader::ARR_None);
-
- if (ReadResult != ASTReader::Success) {
- elog("Can't reuse {0}: {1}", BMIPath, ReadResult);
- return false;
- }
- }
-
- return true;
+ SmallVector<StringRef> BMIPaths;
+ for (auto &MF : RequiredModules)
+ BMIPaths.push_back(MF.ModuleFilePath);
+ return IsModuleFilesUpToDate(BMIPaths, this);
}
} // namespace clangd
More information about the cfe-commits
mailing list