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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits