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