@@ -292,5 +292,73 @@ TEST_F(HeaderSearchTest, HeaderMapFrameworkLookup) {
292
292
EXPECT_EQ (Search.getIncludeNameForHeader (FE), " Foo/Foo.h" );
293
293
}
294
294
295
+ TEST_F (HeaderSearchTest, HeaderFileInfoMerge) {
296
+ auto AddHeader = [&](std::string HeaderPath) -> FileEntryRef {
297
+ VFS->addFile (HeaderPath, 0 ,
298
+ llvm::MemoryBuffer::getMemBufferCopy (" " , HeaderPath),
299
+ /* User=*/ std::nullopt, /* Group=*/ std::nullopt,
300
+ llvm::sys::fs::file_type::regular_file);
301
+ return *FileMgr.getOptionalFileRef (HeaderPath);
302
+ };
303
+
304
+ class MockExternalHeaderFileInfoSource : public ExternalHeaderFileInfoSource {
305
+ HeaderFileInfo GetHeaderFileInfo (const FileEntry *FE) {
306
+ HeaderFileInfo HFI;
307
+ auto FileName = FE->getName ();
308
+ if (FileName == ModularPath)
309
+ HFI.mergeModuleMembership (ModuleMap::NormalHeader);
310
+ else if (FileName == TextualPath)
311
+ HFI.mergeModuleMembership (ModuleMap::TextualHeader);
312
+ HFI.External = true ;
313
+ HFI.IsValid = true ;
314
+ return HFI;
315
+ }
316
+
317
+ public:
318
+ std::string ModularPath = " /modular.h" ;
319
+ std::string TextualPath = " /textual.h" ;
320
+ };
321
+
322
+ auto ExternalSource = new MockExternalHeaderFileInfoSource ();
323
+ Search.SetExternalSource (ExternalSource);
324
+
325
+ // Everything should start out external.
326
+ auto ModularFE = AddHeader (ExternalSource->ModularPath );
327
+ auto TextualFE = AddHeader (ExternalSource->TextualPath );
328
+ EXPECT_TRUE (Search.getExistingFileInfo (ModularFE)->External );
329
+ EXPECT_TRUE (Search.getExistingFileInfo (TextualFE)->External );
330
+
331
+ // Marking the same role should keep it external
332
+ Search.MarkFileModuleHeader (ModularFE, ModuleMap::NormalHeader,
333
+ /* isCompilingModuleHeader=*/ false );
334
+ Search.MarkFileModuleHeader (TextualFE, ModuleMap::TextualHeader,
335
+ /* isCompilingModuleHeader=*/ false );
336
+ EXPECT_TRUE (Search.getExistingFileInfo (ModularFE)->External );
337
+ EXPECT_TRUE (Search.getExistingFileInfo (TextualFE)->External );
338
+
339
+ // textual -> modular should update the HFI, but modular -> textual should be
340
+ // a no-op.
341
+ Search.MarkFileModuleHeader (ModularFE, ModuleMap::TextualHeader,
342
+ /* isCompilingModuleHeader=*/ false );
343
+ Search.MarkFileModuleHeader (TextualFE, ModuleMap::NormalHeader,
344
+ /* isCompilingModuleHeader=*/ false );
345
+ auto ModularFI = Search.getExistingFileInfo (ModularFE);
346
+ auto TextualFI = Search.getExistingFileInfo (TextualFE);
347
+ EXPECT_TRUE (ModularFI->External );
348
+ EXPECT_TRUE (ModularFI->isModuleHeader );
349
+ EXPECT_FALSE (ModularFI->isTextualModuleHeader );
350
+ EXPECT_FALSE (TextualFI->External );
351
+ EXPECT_TRUE (TextualFI->isModuleHeader );
352
+ EXPECT_FALSE (TextualFI->isTextualModuleHeader );
353
+
354
+ // Compiling the module should make the HFI local.
355
+ Search.MarkFileModuleHeader (ModularFE, ModuleMap::NormalHeader,
356
+ /* isCompilingModuleHeader=*/ true );
357
+ Search.MarkFileModuleHeader (TextualFE, ModuleMap::NormalHeader,
358
+ /* isCompilingModuleHeader=*/ true );
359
+ EXPECT_FALSE (Search.getExistingFileInfo (ModularFE)->External );
360
+ EXPECT_FALSE (Search.getExistingFileInfo (TextualFE)->External );
361
+ }
362
+
295
363
} // namespace
296
364
} // namespace clang
0 commit comments