@@ -444,8 +444,8 @@ StringRef DirectoryLookup::getName() const {
444444OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule (
445445 StringRef FileName, SourceLocation IncludeLoc, const DirectoryEntry *Dir,
446446 bool IsSystemHeaderDir, Module *RequestingModule,
447- ModuleMap::KnownHeader *SuggestedModule, bool OpenFile /* =true */ ,
448- bool CacheFailures /* =true*/ ) {
447+ ModuleMap::KnownHeader *SuggestedModule, bool NeedSuggest ,
448+ bool OpenFile /* =true */ , bool CacheFailures /* =true*/ ) {
449449 // If we have a module map that might map this header, load it and
450450 // check whether we'll have a suggestion for a module.
451451 auto File = getFileMgr ().getFileRef (FileName, OpenFile, CacheFailures);
@@ -462,6 +462,9 @@ OptionalFileEntryRef HeaderSearch::getFileAndSuggestModule(
462462 return std::nullopt ;
463463 }
464464
465+ if (!NeedSuggest)
466+ return *File;
467+
465468 // If there is a module that corresponds to this header, suggest it.
466469 if (!findUsableModuleForHeader (
467470 *File, Dir ? Dir : File->getFileEntry ().getDir (), RequestingModule,
@@ -478,7 +481,7 @@ OptionalFileEntryRef DirectoryLookup::LookupFile(
478481 SmallVectorImpl<char > *SearchPath, SmallVectorImpl<char > *RelativePath,
479482 Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
480483 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
481- bool &IsInHeaderMap, SmallVectorImpl<char > &MappedName,
484+ bool &IsInHeaderMap, SmallVectorImpl<char > &MappedName, bool NeedSuggest,
482485 bool OpenFile) const {
483486 InUserSpecifiedSystemFramework = false ;
484487 IsInHeaderMap = false ;
@@ -501,7 +504,7 @@ OptionalFileEntryRef DirectoryLookup::LookupFile(
501504
502505 return HS.getFileAndSuggestModule (
503506 TmpDir, IncludeLoc, getDir (), isSystemHeaderDirectory (),
504- RequestingModule, SuggestedModule, OpenFile);
507+ RequestingModule, SuggestedModule, NeedSuggest, OpenFile);
505508 }
506509
507510 if (isFramework ())
@@ -881,6 +884,35 @@ diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc,
881884 << IncludeFilename;
882885}
883886
887+ // / Return true if a shadow has been detected and the caller should
888+ // / stop and return the first-found file and module, false otherwise.
889+ static bool checkAndStoreCandidate (
890+ ModuleMap::KnownHeader *SuggestedModule, OptionalFileEntryRef CandidateFile,
891+ StringRef CandidateDir, DiagnosticsEngine &Diags, StringRef Filename,
892+ SourceLocation IncludeLoc, ModuleMap::KnownHeader &FirstModule,
893+ OptionalFileEntryRef &FirstHeader, SmallString<1024 > &FirstDir) {
894+ if (!FirstHeader) {
895+ // Found the first candidate
896+ FirstHeader = CandidateFile;
897+ FirstDir = CandidateDir;
898+ if (SuggestedModule)
899+ FirstModule = *SuggestedModule;
900+ return false ;
901+ }
902+
903+ if (FirstDir != CandidateDir) {
904+ // Found a second candidate from a different directory
905+ Diags.Report (IncludeLoc, diag::warn_header_shadowed)
906+ << Filename << FirstDir << CandidateDir;
907+ if (SuggestedModule)
908+ *SuggestedModule = FirstModule;
909+ return true ;
910+ }
911+
912+ // Found a candidate from the same directory as the first one
913+ return false ;
914+ }
915+
884916// / LookupFile - Given a "foo" or \<foo> reference, look up the indicated file,
885917// / return null on failure. isAngled indicates whether the file reference is
886918// / for system \#include's or not (i.e. using <> instead of ""). Includers, if
@@ -923,13 +955,18 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
923955 // Otherwise, just return the file.
924956 return getFileAndSuggestModule (Filename, IncludeLoc, nullptr ,
925957 /* IsSystemHeaderDir*/ false ,
926- RequestingModule, SuggestedModule, OpenFile ,
927- CacheFailures);
958+ RequestingModule, SuggestedModule, true ,
959+ OpenFile, CacheFailures);
928960 }
929961
930962 // This is the header that MSVC's header search would have found.
963+ bool First = true ;
964+ bool NeedSuggest = true ;
931965 ModuleMap::KnownHeader MSSuggestedModule;
932966 OptionalFileEntryRef MSFE;
967+ ModuleMap::KnownHeader FirstModule;
968+ OptionalFileEntryRef FirstHeader;
969+ SmallString<1024 > FirstDir;
933970
934971 // Check to see if the file is in the #includer's directory. This cannot be
935972 // based on CurDir, because each includer could be a #include of a
@@ -938,7 +975,6 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
938975 // headers.
939976 if (!Includers.empty () && !isAngled) {
940977 SmallString<1024 > TmpDir;
941- bool First = true ;
942978 for (const auto &IncluderAndDir : Includers) {
943979 OptionalFileEntryRef Includer = IncluderAndDir.first ;
944980
@@ -962,10 +998,15 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
962998 }();
963999 if (OptionalFileEntryRef FE = getFileAndSuggestModule (
9641000 TmpDir, IncludeLoc, IncluderAndDir.second , IncluderIsSystemHeader,
965- RequestingModule, SuggestedModule)) {
1001+ RequestingModule, SuggestedModule, NeedSuggest)) {
1002+ NeedSuggest = false ;
1003+
9661004 if (!Includer) {
9671005 assert (First && " only first includer can have no file" );
968- return FE;
1006+ checkAndStoreCandidate (
1007+ SuggestedModule, FE, IncluderAndDir.second .getName (), Diags,
1008+ Filename, IncludeLoc, FirstModule, FirstHeader, FirstDir);
1009+ break ;
9691010 }
9701011
9711012 // Leave CurDir unset.
@@ -994,22 +1035,28 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
9941035 diagnoseFrameworkInclude (Diags, IncludeLoc,
9951036 IncluderAndDir.second .getName (), Filename,
9961037 *FE);
997- return FE;
1038+ checkAndStoreCandidate (
1039+ SuggestedModule, FE, IncluderAndDir.second .getName (), Diags,
1040+ Filename, IncludeLoc, FirstModule, FirstHeader, FirstDir);
1041+ break ;
9981042 }
9991043
10001044 // Otherwise, we found the path via MSVC header search rules. If
10011045 // -Wmsvc-include is enabled, we have to keep searching to see if we
10021046 // would've found this header in -I or -isystem directories.
1003- if (Diags.isIgnored (diag::ext_pp_include_search_ms, IncludeLoc)) {
1004- return FE;
1005- } else {
1006- MSFE = FE;
1007- if (SuggestedModule) {
1008- MSSuggestedModule = *SuggestedModule;
1009- *SuggestedModule = ModuleMap::KnownHeader ();
1010- }
1047+ if (checkAndStoreCandidate (
1048+ SuggestedModule, FE, IncluderAndDir.second .getName (), Diags,
1049+ Filename, IncludeLoc, FirstModule, FirstHeader, FirstDir)) {
1050+ // Found mutiple candidates via MSVC rules
1051+ if (Diags.isIgnored (diag::ext_pp_include_search_ms, IncludeLoc))
1052+ return FirstHeader;
10111053 break ;
10121054 }
1055+ MSFE = FE;
1056+ if (SuggestedModule) {
1057+ MSSuggestedModule = *SuggestedModule;
1058+ *SuggestedModule = ModuleMap::KnownHeader ();
1059+ }
10131060 }
10141061 First = false ;
10151062 }
@@ -1069,6 +1116,7 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
10691116 }
10701117
10711118 SmallString<64 > MappedName;
1119+ First = true ;
10721120
10731121 // Check each directory in sequence to see if it contains this file.
10741122 for (; It != search_dir_end (); ++It) {
@@ -1078,7 +1126,7 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
10781126 OptionalFileEntryRef File = It->LookupFile (
10791127 Filename, *this , IncludeLoc, SearchPath, RelativePath, RequestingModule,
10801128 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1081- IsInHeaderMap, MappedName, OpenFile);
1129+ IsInHeaderMap, MappedName, NeedSuggest, OpenFile);
10821130 if (!MappedName.empty ()) {
10831131 assert (IsInHeaderMap && " MappedName should come from a header map" );
10841132 CacheLookup.MappedName =
@@ -1097,53 +1145,62 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
10971145 if (!File)
10981146 continue ;
10991147
1100- CurDir = It;
1101-
1102- IncludeNames[*File] = Filename;
1103-
1104- // This file is a system header or C++ unfriendly if the dir is.
1105- HeaderFileInfo &HFI = getFileInfo (*File);
1106- HFI.DirInfo = CurDir->getDirCharacteristic ();
1107-
1108- // If the directory characteristic is User but this framework was
1109- // user-specified to be treated as a system framework, promote the
1110- // characteristic.
1111- if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
1112- HFI.DirInfo = SrcMgr::C_System;
1113-
1114- // If the filename matches a known system header prefix, override
1115- // whether the file is a system header.
1116- for (unsigned j = SystemHeaderPrefixes.size (); j; --j) {
1117- if (Filename.starts_with (SystemHeaderPrefixes[j - 1 ].first )) {
1118- HFI.DirInfo = SystemHeaderPrefixes[j-1 ].second ? SrcMgr::C_System
1119- : SrcMgr::C_User;
1120- break ;
1148+ if (First) {
1149+ First = false ;
1150+ NeedSuggest = false ;
1151+ CurDir = It;
1152+ IncludeNames[*File] = Filename;
1153+
1154+ // This file is a system header or C++ unfriendly if the dir is.
1155+ HeaderFileInfo &HFI = getFileInfo (*File);
1156+ HFI.DirInfo = CurDir->getDirCharacteristic ();
1157+
1158+ // If the directory characteristic is User but this framework was
1159+ // user-specified to be treated as a system framework, promote the
1160+ // characteristic.
1161+ if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
1162+ HFI.DirInfo = SrcMgr::C_System;
1163+
1164+ // If the filename matches a known system header prefix, override
1165+ // whether the file is a system header.
1166+ for (unsigned j = SystemHeaderPrefixes.size (); j; --j) {
1167+ if (Filename.starts_with (SystemHeaderPrefixes[j - 1 ].first )) {
1168+ HFI.DirInfo = SystemHeaderPrefixes[j - 1 ].second ? SrcMgr::C_System
1169+ : SrcMgr::C_User;
1170+ break ;
1171+ }
11211172 }
1122- }
11231173
1124- if (checkMSVCHeaderSearch (Diags, MSFE, &File->getFileEntry (), IncludeLoc)) {
1125- if (SuggestedModule)
1174+ if (checkMSVCHeaderSearch (Diags, MSFE, &File->getFileEntry (),
1175+ IncludeLoc) &&
1176+ SuggestedModule)
11261177 *SuggestedModule = MSSuggestedModule;
1127- return MSFE;
1128- }
11291178
1130- bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
1131- if (!Includers.empty ())
1132- diagnoseFrameworkInclude (Diags, IncludeLoc,
1133- Includers.front ().second .getName (), Filename,
1134- *File, isAngled, FoundByHeaderMap);
1179+ bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
1180+ if (!Includers.empty ())
1181+ diagnoseFrameworkInclude (Diags, IncludeLoc,
1182+ Includers.front ().second .getName (), Filename,
1183+ *File, isAngled, FoundByHeaderMap);
11351184
1136- // Remember this location for the next lookup we do.
1137- cacheLookupSuccess (CacheLookup, It, IncludeLoc);
1138- return File;
1185+ // Remember this location for the next lookup we do.
1186+ cacheLookupSuccess (CacheLookup, It, IncludeLoc);
1187+ }
1188+
1189+ if (checkAndStoreCandidate (SuggestedModule, File, It->getName (), Diags,
1190+ Filename, IncludeLoc, FirstModule, FirstHeader,
1191+ FirstDir))
1192+ return FirstHeader;
11391193 }
11401194
1141- if (checkMSVCHeaderSearch (Diags, MSFE, nullptr , IncludeLoc)) {
1195+ if (First && checkMSVCHeaderSearch (Diags, MSFE, nullptr , IncludeLoc)) {
11421196 if (SuggestedModule)
11431197 *SuggestedModule = MSSuggestedModule;
11441198 return MSFE;
11451199 }
11461200
1201+ if (FirstHeader)
1202+ return FirstHeader;
1203+
11471204 // Otherwise, didn't find it. Remember we didn't find this.
11481205 CacheLookup.HitIt = search_dir_end ();
11491206 return std::nullopt ;
0 commit comments