@@ -153,6 +153,19 @@ struct PPCallbacksDependencyCollector : public DependencyCollector {
153
153
PP.addPPCallbacks (std::move (CB));
154
154
}
155
155
};
156
+ // / A utility for adding \c ASTReaderListener to a compiler instance at the
157
+ // / appropriate time.
158
+ struct ASTReaderListenerDependencyCollector : public DependencyCollector {
159
+ using MakeL =
160
+ llvm::unique_function<std::unique_ptr<ASTReaderListener>(ASTReader &R)>;
161
+ MakeL Create;
162
+ ASTReaderListenerDependencyCollector (MakeL Create) : Create(std::move(Create)) {}
163
+ void attachToASTReader (ASTReader &R) final {
164
+ std::unique_ptr<ASTReaderListener> L = Create (R);
165
+ assert (L);
166
+ R.addListener (std::move (L));
167
+ }
168
+ };
156
169
157
170
struct IncludeTreePPCallbacks : public PPCallbacks {
158
171
IncludeTreeBuilder &Builder;
@@ -217,6 +230,40 @@ struct IncludeTreePPCallbacks : public PPCallbacks {
217
230
Builder.exitedSubmodule (PP, M, ImportLoc, ForPragma);
218
231
}
219
232
};
233
+
234
+ // / Utility to trigger module lookup in header search for modules loaded via
235
+ // / PCH. This causes dependency scanning via PCH to parse modulemap files at
236
+ // / roughly the same point they would with modulemap files embedded in the pcms,
237
+ // / which is disabled with include-tree modules. Without this, we can fail to
238
+ // / find modules that are in the same directory as a named import, since
239
+ // / it may be skipped during search (see \c loadFrameworkModule).
240
+ // /
241
+ // / The specific lookup we do matches what happens in ASTReader for the
242
+ // / MODULE_DIRECTORY record, and ignores the result.
243
+ class LookupPCHModulesListener : public ASTReaderListener {
244
+ public:
245
+ LookupPCHModulesListener (Preprocessor &PP) : PP(PP) {}
246
+
247
+ private:
248
+ void ReadModuleName (StringRef ModuleName) final {
249
+ if (PCHFinished)
250
+ return ;
251
+ // Match MODULE_DIRECTORY: allow full search and ignore failure to find
252
+ // the module.
253
+ (void )PP.getHeaderSearchInfo ().lookupModule (
254
+ ModuleName, SourceLocation (), /* AllowSearch=*/ true ,
255
+ /* AllowExtraModuleMapSearch=*/ true );
256
+ }
257
+ void visitModuleFile (StringRef Filename,
258
+ serialization::ModuleKind Kind) final {
259
+ if (Kind == serialization::MK_PCH)
260
+ PCHFinished = true ;
261
+ }
262
+
263
+ private:
264
+ Preprocessor &PP;
265
+ bool PCHFinished = false ;
266
+ };
220
267
} // namespace
221
268
222
269
// / The PCH recorded file paths with canonical paths, create a VFS that
@@ -274,6 +321,15 @@ Error IncludeTreeActionController::initialize(
274
321
});
275
322
ScanInstance.addDependencyCollector (std::move (DC));
276
323
324
+ // Attach callback for modules loaded via PCH.
325
+ if (!ScanInstance.getPreprocessorOpts ().ImplicitPCHInclude .empty ()) {
326
+ auto DC = std::make_shared<ASTReaderListenerDependencyCollector>(
327
+ [&](ASTReader &R) {
328
+ return std::make_unique<LookupPCHModulesListener>(R.getPreprocessor ());
329
+ });
330
+ ScanInstance.addDependencyCollector (std::move (DC));
331
+ }
332
+
277
333
// Enable caching in the resulting commands.
278
334
ScanInstance.getFrontendOpts ().CacheCompileJob = true ;
279
335
CASOpts = ScanInstance.getCASOpts ();
0 commit comments