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