24
24
#include " clang/Tooling/DependencyScanning/DependencyScanningService.h"
25
25
#include " clang/Tooling/DependencyScanning/ModuleDepCollector.h"
26
26
#include " clang/Tooling/Tooling.h"
27
+ #include " llvm/ADT/ScopeExit.h"
27
28
#include " llvm/Support/Allocator.h"
28
29
#include " llvm/Support/Error.h"
29
30
#include " llvm/TargetParser/Host.h"
@@ -67,7 +68,7 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
67
68
if (LangOpts.Modules ) {
68
69
if (HSOpts.VFSOverlayFiles != ExistingHSOpts.VFSOverlayFiles ) {
69
70
if (Diags) {
70
- Diags->Report (diag::err_pch_vfsoverlay_mismatch );
71
+ Diags->Report (diag::warn_pch_vfsoverlay_mismatch );
71
72
auto VFSNote = [&](int Type, ArrayRef<std::string> VFSOverlays) {
72
73
if (VFSOverlays.empty ()) {
73
74
Diags->Report (diag::note_pch_vfsoverlay_empty) << Type;
@@ -79,7 +80,6 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
79
80
VFSNote (0 , HSOpts.VFSOverlayFiles );
80
81
VFSNote (1 , ExistingHSOpts.VFSOverlayFiles );
81
82
}
82
- return true ;
83
83
}
84
84
}
85
85
return false ;
@@ -93,10 +93,12 @@ class PrebuiltModuleListener : public ASTReaderListener {
93
93
public:
94
94
PrebuiltModuleListener (PrebuiltModuleFilesT &PrebuiltModuleFiles,
95
95
llvm::SmallVector<std::string> &NewModuleFiles,
96
+ PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
96
97
const HeaderSearchOptions &HSOpts,
97
98
const LangOptions &LangOpts, DiagnosticsEngine &Diags)
98
99
: PrebuiltModuleFiles(PrebuiltModuleFiles),
99
- NewModuleFiles (NewModuleFiles), ExistingHSOpts(HSOpts),
100
+ NewModuleFiles (NewModuleFiles),
101
+ PrebuiltModuleVFSMap(PrebuiltModuleVFSMap), ExistingHSOpts(HSOpts),
100
102
ExistingLangOpts(LangOpts), Diags(Diags) {}
101
103
102
104
bool needsImportVisitation () const override { return true ; }
@@ -106,31 +108,45 @@ class PrebuiltModuleListener : public ASTReaderListener {
106
108
NewModuleFiles.push_back (Filename.str ());
107
109
}
108
110
111
+ void visitModuleFile (StringRef Filename,
112
+ serialization::ModuleKind Kind) override {
113
+ CurrentFile = Filename;
114
+ }
115
+
109
116
bool ReadHeaderSearchPaths (const HeaderSearchOptions &HSOpts,
110
117
bool Complain) override {
118
+ std::vector<std::string> VFSOverlayFiles = HSOpts.VFSOverlayFiles ;
119
+ PrebuiltModuleVFSMap.insert (
120
+ {CurrentFile, llvm::StringSet<>(VFSOverlayFiles)});
111
121
return checkHeaderSearchPaths (
112
122
HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr , ExistingLangOpts);
113
123
}
114
124
115
125
private:
116
126
PrebuiltModuleFilesT &PrebuiltModuleFiles;
117
127
llvm::SmallVector<std::string> &NewModuleFiles;
128
+ PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap;
118
129
const HeaderSearchOptions &ExistingHSOpts;
119
130
const LangOptions &ExistingLangOpts;
120
131
DiagnosticsEngine &Diags;
132
+ std::string CurrentFile;
121
133
};
122
134
123
135
// / Visit the given prebuilt module and collect all of the modules it
124
136
// / transitively imports and contributing input files.
125
137
static bool visitPrebuiltModule (StringRef PrebuiltModuleFilename,
126
138
CompilerInstance &CI,
127
139
PrebuiltModuleFilesT &ModuleFiles,
140
+ PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap,
128
141
DiagnosticsEngine &Diags) {
129
142
// List of module files to be processed.
130
143
llvm::SmallVector<std::string> Worklist;
131
- PrebuiltModuleListener Listener (
132
- ModuleFiles, Worklist, CI.getHeaderSearchOpts (), CI.getLangOpts (), Diags);
144
+ PrebuiltModuleListener Listener (ModuleFiles, Worklist, PrebuiltModuleVFSMap,
145
+ CI.getHeaderSearchOpts (), CI.getLangOpts (),
146
+ Diags);
133
147
148
+ Listener.visitModuleFile (PrebuiltModuleFilename,
149
+ serialization::MK_ExplicitModule);
134
150
if (ASTReader::readASTFileControlBlock (
135
151
PrebuiltModuleFilename, CI.getFileManager (), CI.getModuleCache (),
136
152
CI.getPCHContainerReader (),
@@ -139,6 +155,7 @@ static bool visitPrebuiltModule(StringRef PrebuiltModuleFilename,
139
155
return true ;
140
156
141
157
while (!Worklist.empty ()) {
158
+ Listener.visitModuleFile (Worklist.back (), serialization::MK_ExplicitModule);
142
159
if (ASTReader::readASTFileControlBlock (
143
160
Worklist.pop_back_val (), CI.getFileManager (), CI.getModuleCache (),
144
161
CI.getPCHContainerReader (),
@@ -175,8 +192,19 @@ static void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) {
175
192
DiagOpts.ShowCarets = false ;
176
193
// Don't write out diagnostic file.
177
194
DiagOpts.DiagnosticSerializationFile .clear ();
178
- // Don't emit warnings as errors (and all other warnings too).
179
- DiagOpts.IgnoreWarnings = true ;
195
+ // Don't emit warnings except for scanning specific warnings.
196
+ // TODO: It would be useful to add a more principled way to ignore all
197
+ // warnings that come from source code. The issue is that we need to
198
+ // ignore warnings that could be surpressed by
199
+ // `#pragma clang diagnostic`, while still allowing some scanning
200
+ // warnings for things we're not ready to turn into errors yet.
201
+ // See `test/ClangScanDeps/diagnostic-pragmas.c` for an example.
202
+ llvm::erase_if (DiagOpts.Warnings , [](StringRef Warning) {
203
+ return llvm::StringSwitch<bool >(Warning)
204
+ .Cases (" pch-vfs-diff" , " error=pch-vfs-diff" , false )
205
+ .StartsWith (" no-error=" , false )
206
+ .Default (true );
207
+ });
180
208
}
181
209
182
210
// / A clang tool that runs the preprocessor in a mode that's optimized for
@@ -226,14 +254,19 @@ class DependencyScanningAction : public tooling::ToolAction {
226
254
if (!ScanInstance.hasDiagnostics ())
227
255
return false ;
228
256
257
+ // Some DiagnosticConsumers require that finish() is called.
258
+ auto DiagConsumerFinisher =
259
+ llvm::make_scope_exit ([DiagConsumer]() { DiagConsumer->finish (); });
260
+
229
261
ScanInstance.getPreprocessorOpts ().AllowPCHWithDifferentModulesCachePath =
230
262
true ;
231
263
232
264
ScanInstance.getFrontendOpts ().GenerateGlobalModuleIndex = false ;
233
265
ScanInstance.getFrontendOpts ().UseGlobalModuleIndex = false ;
234
266
ScanInstance.getFrontendOpts ().ModulesShareFileManager = false ;
235
267
ScanInstance.getHeaderSearchOpts ().ModuleFormat = " raw" ;
236
- ScanInstance.getHeaderSearchOpts ().ModulesIncludeVFSUsage = true ;
268
+ ScanInstance.getHeaderSearchOpts ().ModulesIncludeVFSUsage =
269
+ any (OptimizeArgs & ScanningOptimizations::VFS);
237
270
238
271
ScanInstance.setFileManager (FileMgr);
239
272
// Support for virtual file system overlays.
@@ -246,12 +279,13 @@ class DependencyScanningAction : public tooling::ToolAction {
246
279
// Store the list of prebuilt module files into header search options. This
247
280
// will prevent the implicit build to create duplicate modules and will
248
281
// force reuse of the existing prebuilt module files instead.
282
+ PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
249
283
if (!ScanInstance.getPreprocessorOpts ().ImplicitPCHInclude .empty ())
250
284
if (visitPrebuiltModule (
251
285
ScanInstance.getPreprocessorOpts ().ImplicitPCHInclude ,
252
286
ScanInstance,
253
287
ScanInstance.getHeaderSearchOpts ().PrebuiltModuleFiles ,
254
- ScanInstance.getDiagnostics ()))
288
+ PrebuiltModuleVFSMap, ScanInstance.getDiagnostics ()))
255
289
return false ;
256
290
257
291
// Use the dependency scanning optimized file system if requested to do so.
@@ -295,8 +329,8 @@ class DependencyScanningAction : public tooling::ToolAction {
295
329
case ScanningOutputFormat::Full:
296
330
MDC = std::make_shared<ModuleDepCollector>(
297
331
std::move (Opts), ScanInstance, Consumer, Controller,
298
- OriginalInvocation, OptimizeArgs, EagerLoadModules ,
299
- Format == ScanningOutputFormat::P1689);
332
+ OriginalInvocation, std::move (PrebuiltModuleVFSMap), OptimizeArgs ,
333
+ EagerLoadModules, Format == ScanningOutputFormat::P1689);
300
334
ScanInstance.addDependencyCollector (MDC);
301
335
break ;
302
336
}
@@ -325,6 +359,8 @@ class DependencyScanningAction : public tooling::ToolAction {
325
359
if (ScanInstance.getDiagnostics ().hasErrorOccurred ())
326
360
return false ;
327
361
362
+ // Each action is responsible for calling finish.
363
+ DiagConsumerFinisher.release ();
328
364
const bool Result = ScanInstance.ExecuteAction (*Action);
329
365
330
366
if (Result)
0 commit comments