@@ -92,6 +92,88 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
92
92
}
93
93
};
94
94
95
+ struct ModuleFile {
96
+ ModuleFile (StringRef ModuleName, PathRef ModuleFilePath)
97
+ : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
98
+
99
+ ModuleFile () = delete ;
100
+
101
+ ModuleFile (const ModuleFile &) = delete ;
102
+ ModuleFile operator =(const ModuleFile &) = delete ;
103
+
104
+ // The move constructor is needed for llvm::SmallVector.
105
+ ModuleFile (ModuleFile &&Other)
106
+ : ModuleName(std::move(Other.ModuleName)),
107
+ ModuleFilePath (std::move(Other.ModuleFilePath)) {
108
+ Other.ModuleName .clear ();
109
+ Other.ModuleFilePath .clear ();
110
+ }
111
+
112
+ ModuleFile &operator =(ModuleFile &&Other) {
113
+ if (this == &Other)
114
+ return *this ;
115
+
116
+ this ->~ModuleFile ();
117
+ new (this ) ModuleFile (std::move (Other));
118
+ return *this ;
119
+ }
120
+
121
+ ~ModuleFile () {
122
+ if (!ModuleFilePath.empty ())
123
+ llvm::sys::fs::remove (ModuleFilePath);
124
+ }
125
+
126
+ std::string ModuleName;
127
+ std::string ModuleFilePath;
128
+ };
129
+
130
+ bool IsModuleFileUpToDate (
131
+ PathRef ModuleFilePath,
132
+ const PrerequisiteModules *RequisiteModules) {
133
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
134
+ CompilerInstance::createDiagnostics (new DiagnosticOptions ());
135
+
136
+ auto HSOpts = std::make_shared<HeaderSearchOptions>();
137
+ if (RequisiteModules)
138
+ RequisiteModules->adjustHeaderSearchOptions (*HSOpts);
139
+ HSOpts->ForceCheckCXX20ModulesInputFiles = true ;
140
+ HSOpts->ValidateASTInputFilesContent = true ;
141
+
142
+ PCHContainerOperations PCHOperations;
143
+ std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile (
144
+ ModuleFilePath.str (), PCHOperations.getRawReader (), ASTUnit::LoadASTOnly,
145
+ Diags, FileSystemOptions (), std::move (HSOpts));
146
+
147
+ if (!Unit)
148
+ return false ;
149
+
150
+ auto Reader = Unit->getASTReader ();
151
+ if (!Reader)
152
+ return false ;
153
+
154
+ bool UpToDate = true ;
155
+ Reader->getModuleManager ().visit ([&](serialization::ModuleFile &MF) -> bool {
156
+ Reader->visitInputFiles (
157
+ MF, /* IncludeSystem=*/ false , /* Complain=*/ false ,
158
+ [&](const serialization::InputFile &IF, bool isSystem) {
159
+ if (!IF.getFile () || IF.isOutOfDate ())
160
+ UpToDate = false ;
161
+ });
162
+
163
+ return !UpToDate;
164
+ });
165
+
166
+ return UpToDate;
167
+ }
168
+
169
+ bool IsModuleFilesUpToDate (
170
+ llvm::SmallVector<PathRef> ModuleFilePaths,
171
+ const PrerequisiteModules *RequisiteModules = nullptr ) {
172
+ return llvm::all_of (ModuleFilePaths, [RequisiteModules](auto ModuleFilePath) {
173
+ return IsModuleFileUpToDate (ModuleFilePath, RequisiteModules);
174
+ });
175
+ }
176
+
95
177
// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all
96
178
// the required modules are built successfully. All the module files
97
179
// are owned by the StandalonePrerequisiteModules class.
@@ -135,29 +217,6 @@ class StandalonePrerequisiteModules : public PrerequisiteModules {
135
217
}
136
218
137
219
private:
138
- struct ModuleFile {
139
- ModuleFile (llvm::StringRef ModuleName, PathRef ModuleFilePath)
140
- : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
141
-
142
- ModuleFile (const ModuleFile &) = delete ;
143
- ModuleFile operator =(const ModuleFile &) = delete ;
144
-
145
- // The move constructor is needed for llvm::SmallVector.
146
- ModuleFile (ModuleFile &&Other)
147
- : ModuleName(std::move(Other.ModuleName)),
148
- ModuleFilePath (std::move(Other.ModuleFilePath)) {}
149
-
150
- ModuleFile &operator =(ModuleFile &&Other) = delete ;
151
-
152
- ~ModuleFile () {
153
- if (!ModuleFilePath.empty ())
154
- llvm::sys::fs::remove (ModuleFilePath);
155
- }
156
-
157
- std::string ModuleName;
158
- std::string ModuleFilePath;
159
- };
160
-
161
220
llvm::SmallVector<ModuleFile, 8 > RequiredModules;
162
221
// A helper class to speedup the query if a module is built.
163
222
llvm::StringSet<> BuiltModuleNames;
@@ -286,50 +345,10 @@ bool StandalonePrerequisiteModules::canReuse(
286
345
if (RequiredModules.empty ())
287
346
return true ;
288
347
289
- CompilerInstance Clang;
290
-
291
- Clang.setInvocation (std::make_shared<CompilerInvocation>(CI));
292
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
293
- CompilerInstance::createDiagnostics (new DiagnosticOptions ());
294
- Clang.setDiagnostics (Diags.get ());
295
-
296
- FileManager *FM = Clang.createFileManager (VFS);
297
- Clang.createSourceManager (*FM);
298
-
299
- if (!Clang.createTarget ())
300
- return false ;
301
-
302
- assert (Clang.getHeaderSearchOptsPtr ());
303
- adjustHeaderSearchOptions (Clang.getHeaderSearchOpts ());
304
- // Since we don't need to compile the source code actually, the TU kind here
305
- // doesn't matter.
306
- Clang.createPreprocessor (TU_Complete);
307
- Clang.getHeaderSearchOpts ().ForceCheckCXX20ModulesInputFiles = true ;
308
- Clang.getHeaderSearchOpts ().ValidateASTInputFilesContent = true ;
309
-
310
- // Following the practice of clang's driver to suppres the checking for ODR
311
- // violation in GMF.
312
- // See
313
- // https://clang.llvm.org/docs/StandardCPlusPlusModules.html#object-definition-consistency
314
- // for example.
315
- Clang.getLangOpts ().SkipODRCheckInGMF = true ;
316
-
317
- Clang.createASTReader ();
318
- for (auto &RequiredModule : RequiredModules) {
319
- llvm::StringRef BMIPath = RequiredModule.ModuleFilePath ;
320
- // FIXME: Loading BMI fully is too heavy considering something cheaply to
321
- // check if we can reuse the BMI.
322
- auto ReadResult =
323
- Clang.getASTReader ()->ReadAST (BMIPath, serialization::MK_MainFile,
324
- SourceLocation (), ASTReader::ARR_None);
325
-
326
- if (ReadResult != ASTReader::Success) {
327
- elog (" Can't reuse {0}: {1}" , BMIPath, ReadResult);
328
- return false ;
329
- }
330
- }
331
-
332
- return true ;
348
+ SmallVector<StringRef> BMIPaths;
349
+ for (auto &MF : RequiredModules)
350
+ BMIPaths.push_back (MF.ModuleFilePath );
351
+ return IsModuleFilesUpToDate (BMIPaths, this );
333
352
}
334
353
335
354
} // namespace clangd
0 commit comments