1 //===----------------- ModulesBuilder.h --------------------------*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Experimental support for C++20 Modules. 10 // 11 // Currently we simplify the implementations by preventing reusing module files 12 // across different versions and different source files. But this is clearly a 13 // waste of time and space in the end of the day. 14 // 15 // TODO: Supporting reusing module files across different versions and 16 // different source files. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H 21 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H 22 23 #include "GlobalCompilationDatabase.h" 24 #include "ProjectModules.h" 25 #include "support/Path.h" 26 #include "support/ThreadsafeFS.h" 27 #include "clang/Frontend/CompilerInvocation.h" 28 #include "llvm/ADT/SmallString.h" 29 #include <memory> 30 31 namespace clang { 32 namespace clangd { 33 34 /// Store all the needed module files information to parse a single 35 /// source file. e.g., 36 /// 37 /// ``` 38 /// // a.cppm 39 /// export module a; 40 /// 41 /// // b.cppm 42 /// export module b; 43 /// import a; 44 /// 45 /// // c.cppm 46 /// export module c; 47 /// import b; 48 /// ``` 49 /// 50 /// For the source file `c.cppm`, an instance of the class will store 51 /// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm` 52 /// won't be stored. Since it is not needed to parse `c.cppm`. 53 /// 54 /// Users should only get PrerequisiteModules from 55 /// `ModulesBuilder::buildPrerequisiteModulesFor(...)`. 56 /// 57 /// Users can detect whether the PrerequisiteModules is still up to date by 58 /// calling the `canReuse()` member function. 59 /// 60 /// The users should call `adjustHeaderSearchOptions(...)` to update the 61 /// compilation commands to select the built module files first. Before calling 62 /// `adjustHeaderSearchOptions()`, users should call `canReuse()` first to check 63 /// if all the stored module files are valid. In case they are not valid, 64 /// users should call `ModulesBuilder::buildPrerequisiteModulesFor(...)` again 65 /// to get the new PrerequisiteModules. 66 class PrerequisiteModules { 67 public: 68 /// Change commands to load the module files recorded in this 69 /// PrerequisiteModules first. 70 virtual void 71 adjustHeaderSearchOptions(HeaderSearchOptions &Options) const = 0; 72 73 /// Whether or not the built module files are up to date. 74 /// Note that this can only be used after building the module files. 75 virtual bool 76 canReuse(const CompilerInvocation &CI, 77 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const = 0; 78 79 virtual ~PrerequisiteModules() = default; 80 }; 81 82 /// This class handles building module files for a given source file. 83 /// 84 /// In the future, we want the class to manage the module files acorss 85 /// different versions and different source files. 86 class ModulesBuilder { 87 public: 88 ModulesBuilder(const GlobalCompilationDatabase &CDB); 89 ~ModulesBuilder(); 90 91 ModulesBuilder(const ModulesBuilder &) = delete; 92 ModulesBuilder(ModulesBuilder &&) = delete; 93 94 ModulesBuilder &operator=(const ModulesBuilder &) = delete; 95 ModulesBuilder &operator=(ModulesBuilder &&) = delete; 96 97 std::unique_ptr<PrerequisiteModules> 98 buildPrerequisiteModulesFor(PathRef File, const ThreadsafeFS &TFS); 99 100 private: 101 class ModulesBuilderImpl; 102 std::unique_ptr<ModulesBuilderImpl> Impl; 103 }; 104 105 } // namespace clangd 106 } // namespace clang 107 108 #endif 109