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