26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/Statistic.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/Allocator.h"
33#include "llvm/Support/Capacity.h"
34#include "llvm/Support/Errc.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Path.h"
38#include "llvm/Support/VirtualFileSystem.h"
39#include "llvm/Support/xxhash.h"
46#include <system_error>
51#define DEBUG_TYPE "file-search"
55 NumMultiIncludeFileOptzn,
56 "Number of #includes skipped due to the multi-include optimization.");
59 "Number of subframework lookups.");
73 if (ControllingMacro && ControllingMacro->
isOutOfDate()) {
74 assert(
External &&
"We must have an external source if we have a "
75 "controlling macro that is out of date.");
76 External->updateOutOfDateIdentifier(*ControllingMacro);
78 return ControllingMacro;
87 : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
88 FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts,
Target, *this) {}
91 llvm::errs() <<
"\n*** HeaderSearch Stats:\n"
92 << FileInfo.size() <<
" files tracked.\n";
93 unsigned NumOnceOnlyFiles = 0;
94 for (
const auto &[FE, HFI] : FileInfo)
95 NumOnceOnlyFiles += (HFI.isPragmaOnce || HFI.isImport);
96 llvm::errs() <<
" " << NumOnceOnlyFiles <<
" #import/#pragma once files.\n";
98 llvm::errs() <<
" " << NumIncluded <<
" #include/#include_next/#import.\n"
99 <<
" " << NumMultiIncludeFileOptzn
100 <<
" #includes skipped due to the multi-include optimization.\n";
102 llvm::errs() << NumFrameworkLookups <<
" framework lookups.\n"
103 << NumSubFrameworkLookups <<
" subframework lookups.\n";
107 std::vector<DirectoryLookup> dirs,
unsigned int angledDirIdx,
108 unsigned int systemDirIdx,
109 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
110 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
111 "Directory indices are unordered");
112 SearchDirs = std::move(dirs);
113 SearchDirsUsage.assign(SearchDirs.size(),
false);
114 AngledDirIdx = angledDirIdx;
115 SystemDirIdx = systemDirIdx;
116 SearchDirToHSEntry = std::move(searchDirToHSEntry);
118 indexInitialHeaderMaps();
122 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
123 SearchDirs.insert(SearchDirs.begin() + idx, dir);
124 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx,
false);
131 std::vector<bool> UserEntryUsage(HSOpts.UserEntries.size());
132 for (
unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
134 if (SearchDirsUsage[I]) {
135 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
137 if (UserEntryIdxIt != SearchDirToHSEntry.end())
138 UserEntryUsage[UserEntryIdxIt->second] =
true;
141 return UserEntryUsage;
145 std::vector<bool> VFSUsage;
149 llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
153 RootFS.visit([&](llvm::vfs::FileSystem &FS) {
154 if (
auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {
158 if (!RFS->getOverlayFileDir().empty()) {
159 VFSUsage.push_back(RFS->hasBeenUsed());
160 RFS->clearHasBeenUsed();
165 "A different number of RedirectingFileSystem's were present than "
166 "-ivfsoverlay options passed to Clang!");
168 std::reverse(VFSUsage.begin(), VFSUsage.end());
177 if (!HeaderMaps.empty()) {
178 for (
unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
181 if (HeaderMaps[i].first == FE)
182 return HeaderMaps[i].second.get();
186 HeaderMaps.emplace_back(FE, std::move(HM));
187 return HeaderMaps.back().second.get();
196 for (
auto &HM : HeaderMaps)
197 Names.push_back(std::string(HM.first.getName()));
213 auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));
214 if (i != HSOpts.PrebuiltModuleFiles.end())
217 if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())
222 for (
const std::string &Dir : HSOpts.PrebuiltModulePaths) {
224 FileMgr.makeAbsolutePath(
Result);
225 if (ModuleName.contains(
':'))
229 llvm::sys::path::append(
Result, ModuleName.split(
':').first +
"-" +
230 ModuleName.split(
':').second +
233 llvm::sys::path::append(
Result, ModuleName +
".pcm");
245 StringRef ModuleMapPath =
ModuleMap->getName();
246 for (
const std::string &Dir : HSOpts.PrebuiltModulePaths) {
248 FileMgr.makeAbsolutePath(CachePath);
250 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
258 StringRef ModuleMapPath) {
259 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
264 StringRef ModuleName, StringRef ModuleMapPath, StringRef CachePath) {
267 if (CachePath.empty())
274 unsigned SuffixBegin =
Result.size();
277 llvm::sys::path::append(
Result, ModuleName +
".pcm");
279 llvm::sys::path::append(
Result, ContextHash);
287 SmallString<128> CanonicalPath(ModuleMapPath);
288 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
291 auto Hash = llvm::xxh3_64bits(CanonicalPath);
293 SmallString<128> HashStr;
294 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
295 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
302 bool AllowExtraModuleMapSearch) {
305 if (
Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
308 if (!lookupModuleWithPrivateFallbacks(
309 ModuleName, ImportLoc, AllowExtraModuleMapSearch,
true))
311 return ModMap.findOrLoadModule(ModuleName);
316 bool AllowExtraModuleMapSearch) {
317 assert(HSOpts.LazyLoadModuleMaps &&
318 "module map lookup requires lazy loading support");
319 if (!ModMap.isModuleKnown(ModuleName)) {
320 if (!HSOpts.ImplicitModuleMaps)
323 if (!lookupModuleWithPrivateFallbacks(ModuleName,
SourceLocation(),
324 AllowExtraModuleMapSearch,
328 return ModMap.getModuleMapFileForName(ModuleName);
331bool HeaderSearch::lookupModuleWithPrivateFallbacks(
333 bool AllowExtraModuleMapSearch,
bool Load) {
334 StringRef SearchName = ModuleName;
335 if (lookupModuleImpl(ModuleName, SearchName, ImportLoc,
336 AllowExtraModuleMapSearch, Load))
348 if (SearchName.consume_back(
"_Private") &&
349 lookupModuleImpl(ModuleName, SearchName, ImportLoc,
350 AllowExtraModuleMapSearch, Load))
352 if (SearchName.consume_back(
"Private") &&
353 lookupModuleImpl(ModuleName, SearchName, ImportLoc,
354 AllowExtraModuleMapSearch, Load))
359bool HeaderSearch::lookupModuleImpl(StringRef ModuleName, StringRef SearchName,
361 bool AllowExtraModuleMapSearch,
bool Load) {
362 auto FindModule = [&] {
371 if (Dir.isFramework()) {
375 SmallString<128> FrameworkDirName;
376 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
377 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
378 if (
auto FrameworkDir =
379 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
381 parseFrameworkModuleMap(*FrameworkDir, IsSystem,
391 if (!Dir.isNormalDir())
394 bool IsSystem = Dir.isSystemHeaderDirectory();
397 DirectoryEntryRef NormalDir = *Dir.getDirRef();
400 false) == MMR_NewlyProcessed) {
409 SmallString<128> NestedModuleMapDirName;
410 NestedModuleMapDirName = Dir.getDirRef()->getName();
411 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
414 false) == MMR_NewlyProcessed) {
420 if (HSOpts.AllowModuleMapSubdirectorySearch) {
423 if (Dir.haveLoadedAllModuleMaps())
428 if (AllowExtraModuleMapSearch)
429 parseSubdirectoryModuleMaps(Dir, Load);
440void HeaderSearch::indexInitialHeaderMaps() {
441 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
444 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
445 auto &Dir = SearchDirs[i];
450 if (!Dir.isHeaderMap()) {
451 SearchDirHeaderMapIndex = std::move(Index);
452 FirstNonHeaderMapSearchDirIdx = i;
457 auto Callback = [&](StringRef Filename) {
458 Index.try_emplace(Filename.lower(), i);
460 Dir.getHeaderMap()->forEachKey(
Callback);
475 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
481 bool IsSystemHeaderDir,
Module *RequestingModule,
483 bool CacheFailures ) {
490 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
491 if (EC != llvm::errc::no_such_file_or_directory &&
492 EC != llvm::errc::invalid_argument &&
493 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
494 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
501 if (!findUsableModuleForHeader(
502 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
503 SuggestedModule, IsSystemHeaderDir))
515 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
517 bool OpenFile)
const {
518 InUserSpecifiedSystemFramework =
false;
519 IsInHeaderMap =
false;
526 llvm::sys::path::append(TmpDir, Filename);
530 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
533 RelativePath->clear();
534 RelativePath->append(Filename.begin(), Filename.end());
537 return HS.getFileAndSuggestModule(
539 RequestingModule, SuggestedModule, OpenFile);
543 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
544 RequestingModule, SuggestedModule,
545 InUserSpecifiedSystemFramework, IsFrameworkFound);
547 assert(
isHeaderMap() &&
"Unknown directory lookup");
554 IsInHeaderMap =
true;
556 auto FixupSearchPathAndFindUsableModule =
559 StringRef SearchPathRef(
getName());
561 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
564 RelativePath->clear();
565 RelativePath->append(Filename.begin(), Filename.end());
567 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
568 RequestingModule, SuggestedModule,
578 if (llvm::sys::path::is_relative(Dest)) {
579 MappedName.append(Dest.begin(), Dest.end());
580 Filename = StringRef(MappedName.begin(), MappedName.size());
585 return FixupSearchPathAndFindUsableModule(*Res);
605 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
606 "Not a framework directory");
622 auto TopFrameworkDir =
FileMgr.getOptionalDirectoryRef(DirName);
625 DirName =
FileMgr.getCanonicalName(*TopFrameworkDir);
628 DirName = llvm::sys::path::parent_path(DirName);
633 auto Dir =
FileMgr.getOptionalDirectoryRef(DirName);
639 if (llvm::sys::path::extension(DirName) ==
".framework") {
640 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
641 TopFrameworkDir = *Dir;
645 return TopFrameworkDir;
649 bool HasSuggestedModule) {
650 return HasSuggestedModule ||
660 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
664 size_t SlashPos = Filename.find(
'/');
665 if (SlashPos == StringRef::npos)
670 FrameworkCacheEntry &CacheEntry =
680 SmallString<1024> FrameworkName;
682 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
683 FrameworkName.push_back(
'/');
686 StringRef ModuleName(Filename.begin(), SlashPos);
687 FrameworkName += ModuleName;
690 FrameworkName +=
".framework/";
694 ++NumFrameworkLookups;
708 SmallString<1024> SystemFrameworkMarker(FrameworkName);
709 SystemFrameworkMarker +=
".system_framework";
720 RelativePath->clear();
721 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
725 unsigned OrigSize = FrameworkName.size();
727 FrameworkName +=
"Headers/";
732 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
735 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
741 const char *
Private =
"Private";
742 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
745 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
755 StringRef FrameworkPath =
File->getDir().getName();
756 bool FoundFramework =
false;
765 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
766 FoundFramework =
true;
771 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
772 if (FrameworkPath.empty())
777 if (FoundFramework) {
778 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
780 SuggestedModule, IsSystem))
783 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
784 SuggestedModule, IsSystem))
793void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
796 CacheLookup.HitIt = HitIt;
797 noteLookupUsage(HitIt.Idx, Loc);
800void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
801 SearchDirsUsage[HitIdx] =
true;
803 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
804 if (UserEntryIdxIt != SearchDirToHSEntry.end())
805 Diags.Report(Loc, diag::remark_pp_search_path_usage)
806 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
824 if (MSFE && FE != *MSFE) {
825 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
831static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
832 assert(!Str.empty());
833 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
834 std::copy(Str.begin(), Str.end(), CopyStr);
835 CopyStr[Str.size()] =
'\0';
842 using namespace llvm::sys;
843 path::const_iterator I = path::begin(Path);
844 path::const_iterator E = path::end(Path);
845 IsPrivateHeader =
false;
857 if (*I ==
"Headers") {
859 }
else if (*I ==
"PrivateHeaders") {
861 IsPrivateHeader =
true;
862 }
else if (I->ends_with(
".framework")) {
863 StringRef Name = I->drop_back(10);
865 FrameworkName.clear();
866 FrameworkName.append(Name.begin(), Name.end());
867 IncludeSpelling.clear();
868 IncludeSpelling.append(Name.begin(), Name.end());
870 }
else if (FoundComp >= 2) {
871 IncludeSpelling.push_back(
'/');
872 IncludeSpelling.append(I->begin(), I->end());
877 return !FrameworkName.empty() && FoundComp >= 2;
882 StringRef Includer, StringRef IncludeFilename,
884 bool FoundByHeaderMap =
false) {
885 bool IsIncluderPrivateHeader =
false;
889 FromIncludeSpelling))
891 bool IsIncludeePrivateHeader =
false;
892 bool IsIncludeeInFramework =
894 ToFramework, ToIncludeSpelling);
896 if (!isAngled && !FoundByHeaderMap) {
898 if (IsIncludeeInFramework) {
899 NewInclude += ToIncludeSpelling;
902 NewInclude += IncludeFilename;
905 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
913 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
914 IsIncludeePrivateHeader && FromFramework == ToFramework)
915 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
921 ConstSearchDirIterator FromDir,
922 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
923 bool isAngled,
int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
925 if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc))
928 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
934 if (!ShadowCheckedHeaders[Filename].insert(FE).second)
939 for (
size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
940 const auto &IncluderAndDir = Includers[i];
942 llvm::sys::path::append(TmpDir, Filename);
946 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
948 << IncluderAndDir.second.getName();
955 ConstSearchDirIterator It =
958 It = std::next(MainLoopIt);
959 }
else if (FromDir) {
967 llvm::sys::path::append(TmpPath, Filename);
971 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
985 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
986 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
989 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
990 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
991 ConstSearchDirIterator CurDirLocal =
nullptr;
992 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
997 if (IsFrameworkFound)
998 *IsFrameworkFound =
false;
1000 if (SuggestedModule)
1004 if (llvm::sys::path::is_absolute(Filename)) {
1009 return std::nullopt;
1012 SearchPath->clear();
1014 RelativePath->clear();
1015 RelativePath->append(Filename.begin(), Filename.end());
1018 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
1020 RequestingModule, SuggestedModule, OpenFile,
1033 if (!Includers.empty() && !isAngled) {
1036 for (
const auto &IncluderAndDir : Includers) {
1040 TmpDir = IncluderAndDir.second.getName();
1041 llvm::sys::path::append(TmpDir, Filename);
1050 bool IncluderIsSystemHeader = [&]() {
1052 return BuildSystemModule;
1054 assert(HFI &&
"includer without file info");
1058 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
1059 RequestingModule, SuggestedModule)) {
1061 isAngled, &IncluderAndDir - Includers.begin(),
1064 assert(
First &&
"only first includer can have no file");
1075 assert(FromHFI &&
"includer without file info");
1076 unsigned DirInfo = FromHFI->
DirInfo;
1082 StringRef SearchPathRef(IncluderAndDir.second.getName());
1083 SearchPath->clear();
1084 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
1087 RelativePath->clear();
1088 RelativePath->append(Filename.begin(), Filename.end());
1092 IncluderAndDir.second.getName(), Filename,
1100 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1104 if (SuggestedModule) {
1105 MSSuggestedModule = *SuggestedModule;
1118 ConstSearchDirIterator It =
1130 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1132 ConstSearchDirIterator NextIt = std::next(It);
1135 if (CacheLookup.StartIt == NextIt &&
1136 CacheLookup.RequestingModule == RequestingModule) {
1138 if (CacheLookup.HitIt)
1139 It = CacheLookup.HitIt;
1140 if (CacheLookup.MappedName) {
1141 Filename = CacheLookup.MappedName;
1149 CacheLookup.reset(RequestingModule, NextIt);
1155 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1156 if (Iter == SearchDirHeaderMapIndex.end())
1165 CacheLookup.reset(RequestingModule, NextIt);
1172 bool InUserSpecifiedSystemFramework =
false;
1173 bool IsInHeaderMap =
false;
1174 bool IsFrameworkFoundInDir =
false;
1176 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1177 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1178 IsInHeaderMap, MappedName, OpenFile);
1179 if (!MappedName.empty()) {
1180 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1181 CacheLookup.MappedName =
1182 copyString(MappedName, LookupFileCache.getAllocator());
1188 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1189 if (IsFrameworkFound)
1193 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1207 IncludeNames[*
File] = Filename;
1211 HFI.
DirInfo = CurDir->getDirCharacteristic();
1221 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1222 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1230 if (SuggestedModule)
1231 *SuggestedModule = MSSuggestedModule;
1235 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1236 if (!Includers.empty())
1238 Includers.front().second.getName(), Filename,
1239 *
File, isAngled, FoundByHeaderMap);
1242 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1247 if (SuggestedModule)
1248 *SuggestedModule = MSSuggestedModule;
1254 return std::nullopt;
1268 size_t SlashPos = Filename.find(
'/');
1269 if (SlashPos == StringRef::npos)
1270 return std::nullopt;
1273 StringRef ContextName = ContextFileEnt.
getName();
1276 const unsigned DotFrameworkLen = 10;
1277 auto FrameworkPos = ContextName.find(
".framework");
1278 if (FrameworkPos == StringRef::npos ||
1279 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1280 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1281 return std::nullopt;
1285 DotFrameworkLen + 1);
1288 FrameworkName +=
"Frameworks/";
1289 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1290 FrameworkName +=
".framework/";
1293 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1297 if (CacheLookup.second.Directory &&
1298 CacheLookup.first().size() == FrameworkName.size() &&
1299 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1300 CacheLookup.first().size()) != 0)
1301 return std::nullopt;
1304 if (!CacheLookup.second.Directory) {
1305 ++NumSubFrameworkLookups;
1308 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1310 return std::nullopt;
1314 CacheLookup.second.Directory = Dir;
1319 RelativePath->clear();
1320 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1325 HeadersFilename +=
"Headers/";
1327 SearchPath->clear();
1329 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1332 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1333 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1336 HeadersFilename = FrameworkName;
1337 HeadersFilename +=
"PrivateHeaders/";
1339 SearchPath->clear();
1341 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1344 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1345 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1348 return std::nullopt;
1353 assert(ContextHFI &&
"context file without file info");
1356 unsigned DirInfo = ContextHFI->
DirInfo;
1359 FrameworkName.pop_back();
1360 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1361 RequestingModule, SuggestedModule,
1363 return std::nullopt;
1382 bool isModuleHeader,
1383 bool isTextualModuleHeader) {
1400 assert(OtherHFI.
External &&
"expected to merge external HFI");
1418 if (ExternalSource && !HFI->
Resolved) {
1419 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1420 if (ExternalHFI.IsValid) {
1422 if (ExternalHFI.External)
1436 if (ExternalSource) {
1437 HFI = &FileInfo[FE];
1440 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1441 if (ExternalHFI.IsValid) {
1443 if (ExternalHFI.External)
1447 }
else if (
auto It = FileInfo.find(FE); It != FileInfo.end()) {
1453 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1458 for (
const auto &[FE, HFI] : FileInfo)
1459 if (HFI.IsValid && !HFI.External)
1468 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1474 bool isCompilingModuleHeader) {
1476 if (!isCompilingModuleHeader) {
1485 HFI.mergeModuleMembership(
Role);
1486 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1491 bool ModulesEnabled,
Module *M,
1492 bool &IsFirstIncludeOfFile) {
1508 IsFirstIncludeOfFile =
false;
1511 auto MaybeReenterImportedFile = [&]() ->
bool {
1529 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1533 ModMap.resolveHeaderDirectives(
File);
1553 if (FileInfo.isTextualModuleHeader)
1556 if (FileInfo.isCompilingModuleHeader) {
1559 if (FileInfo.isModuleHeader) {
1564 if (ModMap.isBuiltinHeader(
File))
1573 if (FileInfo.getControllingMacro(ExternalLookup))
1593 FileInfo.isImport =
true;
1600 if (FileInfo.isPragmaOnce ||
1601 (FileInfo.isImport && !MaybeReenterImportedFile()))
1610 FileInfo.getControllingMacro(ExternalLookup)) {
1617 ++NumMultiIncludeFileOptzn;
1627 return SearchDirs.capacity()
1628 + llvm::capacity_in_bytes(FileInfo)
1629 + llvm::capacity_in_bytes(HeaderMaps)
1630 + LookupFileCache.getAllocator().getTotalMemory()
1631 + FrameworkMap.getAllocator().getTotalMemory();
1635 return &DL - &*SearchDirs.begin();
1639 return FrameworkNames.insert(Framework).first->first();
1643 auto It = IncludeNames.find(
File);
1644 if (It == IncludeNames.end())
1650 ModuleMapDirectoryState &MMState) {
1651 if (!MMState.ModuleMapFile)
1658 if (MMState.PrivateModuleMapFile)
1661 processModuleMapForIndex(*ParsedMM, Dir,
"", MMState);
1662 if (ParsedPrivateMM)
1663 processModuleMapForIndex(*ParsedPrivateMM, Dir,
"", MMState);
1666void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
1667 StringRef PathPrefix,
1668 ModuleMapDirectoryState &MMState) {
1670 llvm::sys::path::append(RelFromRootPath, RelPath);
1671 llvm::sys::path::native(RelFromRootPath);
1672 MMState.HeaderToModules[RelFromRootPath].push_back(ModuleName);
1675void HeaderSearch::processExternModuleDeclForIndex(
1677 StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
1678 StringRef FileNameRef = EMD.
Path;
1679 SmallString<128> ModuleMapFileName;
1680 if (llvm::sys::path::is_relative(FileNameRef)) {
1681 ModuleMapFileName = MMDir.
getName();
1682 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
1683 FileNameRef = ModuleMapFileName;
1685 if (
auto EFile = FileMgr.getOptionalFileRef(FileNameRef)) {
1686 if (
auto *ExtMMF = ModMap.getParsedModuleMap(*EFile)) {
1689 SmallString<128> NewPrefix(PathPrefix);
1690 StringRef ExternDir = llvm::sys::path::parent_path(EMD.
Path);
1691 if (!ExternDir.empty()) {
1692 llvm::sys::path::append(NewPrefix, ExternDir);
1693 llvm::sys::path::native(NewPrefix);
1695 processModuleMapForIndex(*ExtMMF, EFile->getDir(), NewPrefix, MMState);
1701 StringRef ModuleName,
1703 StringRef PathPrefix,
1704 ModuleMapDirectoryState &MMState) {
1706 if (MD.
Id.front().first ==
"*")
1709 auto ProcessDecl = llvm::makeVisitor(
1710 [&](
const modulemap::HeaderDecl &HD) {
1712 MMState.UmbrellaHeaderModules.push_back(ModuleName);
1714 addToModuleMapIndex(HD.
Path, ModuleName, PathPrefix, MMState);
1717 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1718 SmallString<128> FullPath(PathPrefix);
1719 llvm::sys::path::append(FullPath, UDD.Path);
1720 llvm::sys::path::native(FullPath);
1721 MMState.UmbrellaDirModules.push_back(
1722 std::make_pair(std::string(FullPath), ModuleName));
1724 [&](
const modulemap::ModuleDecl &SubMD) {
1725 processModuleDeclForIndex(SubMD, ModuleName, MMDir, PathPrefix,
1728 [&](
const modulemap::ExternModuleDecl &EMD) {
1729 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
1735 for (
const auto &Decl : MD.
Decls) {
1736 std::visit(ProcessDecl, Decl);
1742 StringRef PathPrefix,
1743 ModuleMapDirectoryState &MMState) {
1744 for (
const auto &Decl : MMF.
Decls) {
1745 std::visit(llvm::makeVisitor(
1746 [&](
const modulemap::ModuleDecl &MD) {
1747 processModuleDeclForIndex(MD, MD.
Id.front().first, MMDir,
1748 PathPrefix, MMState);
1750 [&](
const modulemap::ExternModuleDecl &EMD) {
1751 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
1763 if (!
FileName.starts_with(DirPath))
1765 StringRef RelativePath =
FileName.substr(DirPath.size());
1766 while (!RelativePath.empty() &&
1767 llvm::sys::path::is_separator(RelativePath.front()))
1768 RelativePath = RelativePath.substr(1);
1769 return RelativePath;
1773 StringRef RelativePath,
const ModuleMapDirectoryState &MMState)
const {
1774 SmallVector<StringRef, 1> Modules;
1777 auto CachedMods = MMState.HeaderToModules.find(RelativePath);
1778 if (CachedMods != MMState.HeaderToModules.end())
1779 Modules.append(CachedMods->second.begin(), CachedMods->second.end());
1782 for (
const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
1783 if (RelativePath.starts_with(UmbrellaDir.first) || UmbrellaDir.first ==
".")
1784 Modules.push_back(UmbrellaDir.second);
1798 Modules.append(MMState.UmbrellaHeaderModules.begin(),
1799 MMState.UmbrellaHeaderModules.end());
1807 if (!HSOpts.ImplicitModuleMaps)
1814 DirName = llvm::sys::path::parent_path(DirName);
1815 if (DirName.empty())
1819 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1825 llvm::sys::path::extension(Dir->
getName()) ==
".framework";
1831 auto DirState = DirectoryModuleMap.find(*Dir);
1832 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1835 if (!HSOpts.LazyLoadModuleMaps &&
1836 Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1840 auto &MMState = DirState->second;
1843 if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
1844 MMState.UmbrellaHeaderModules.empty()) {
1845 buildModuleMapIndex(*Dir, MMState);
1849 if (!HSOpts.LazyLoadModuleMaps)
1857 llvm::sys::path::native(RelativePathNative);
1859 auto ModulesToLoad =
1860 findMatchingModulesInIndex(RelativePathNative, MMState);
1863 bool LoadedAny =
false;
1864 for (StringRef ModName : ModulesToLoad) {
1865 if (ModMap.findOrLoadModule(ModName)) {
1874 }
while (CurDir != Root);
1880 bool AllowExcluded)
const {
1881 if (ExternalSource) {
1886 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1891 if (ExternalSource) {
1896 return ModMap.findAllModulesForHeader(
File);
1901 if (ExternalSource) {
1906 return ModMap.findResolvedModulesForHeader(
File);
1923 if (SuggestedModule)
1933 if (SuggestedModule)
1947 if (!HSOpts.ImplicitModuleMaps ||
Module.getModule()->isPartOfFramework() ||
1948 !
Module.getModule()->isModuleMapModule())
1951 if (Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1952 Module.getModule()->DefinitionLoc))
1955 if (
File.isDeviceFile() ||
File.isNamedPipe())
1958 llvm::SmallString<128> AbsPath(
File.getName());
1959 FileMgr.makeAbsolutePath(AbsPath);
1960 llvm::sys::path::remove_dots(AbsPath,
true);
1964 llvm::SmallString<128> LinkTarget;
1965 if (llvm::sys::fs::readlink(AbsPath, LinkTarget))
1973 const DirectoryEntry *CurDir =
nullptr;
1977 DirName = llvm::sys::path::parent_path(DirName);
1978 if (DirName.empty())
1981 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1986 auto DirState = DirectoryModuleMap.find(*Dir);
1987 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1993 if (RelativePath.empty())
1995 SmallString<128> RelativePathNative(RelativePath);
1996 llvm::sys::path::native(RelativePathNative);
1998 auto MatchingModules =
1999 findMatchingModulesInIndex(RelativePathNative, DirState->second);
2000 if (!MatchingModules.empty())
2002 }
while (CurDir != Root);
2005 Diags.Report(diag::warn_mmap_deprecated_symlink_to_modular_header)
2006 <<
File.getName() << LinkTarget
2007 <<
Module.getModule()->getFullModuleName();
2008 Diags.Report(
Module.getModule()->DefinitionLoc,
2009 diag::note_mmap_module_defined_here);
2012bool HeaderSearch::findUsableModuleForHeader(
2016 if (!HSOpts.LazyLoadModuleMaps) {
2022 ModuleMap::KnownHeader
Module =
2024 diagnoseUncoveredSymlink(
File,
Module, Root);
2030 ModuleMap::KnownHeader
Module =
2038 Module = ModMap.findModuleForHeader(
File,
true);
2040 diagnoseUncoveredSymlink(
File,
Module, Root);
2047bool HeaderSearch::findUsableModuleForFrameworkHeader(
2053 SmallVector<std::string, 4> SubmodulePath;
2056 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
2059 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
2063 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework,
2070 ModuleMap::KnownHeader
Module =
2081 bool Diagnose =
true) {
2082 StringRef Filename = llvm::sys::path::filename(
File.getName());
2084 if (Filename ==
"module.map")
2085 llvm::sys::path::append(PrivateFilename,
"module_private.map");
2086 else if (Filename ==
"module.modulemap")
2087 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
2089 return std::nullopt;
2090 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
2092 if (Diagnose && Filename ==
"module.map")
2093 Diags.
Report(diag::warn_deprecated_module_dot_map)
2094 << PrivateFilename << 1
2095 <<
File.getDir().getName().ends_with(
".framework");
2102 StringRef OriginalModuleMapFile) {
2107 Dir = FileMgr.getOptionalDirectoryRef(
".");
2109 if (!OriginalModuleMapFile.empty()) {
2112 Dir = FileMgr.getOptionalDirectoryRef(
2113 llvm::sys::path::parent_path(OriginalModuleMapFile));
2115 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
2116 Dir = FakeFile.getDir();
2119 Dir =
File.getDir();
2122 assert(Dir &&
"parent must exist");
2123 StringRef DirName(Dir->
getName());
2124 if (llvm::sys::path::filename(DirName) ==
"Modules") {
2125 DirName = llvm::sys::path::parent_path(DirName);
2126 if (DirName.ends_with(
".framework"))
2127 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
2131 assert(Dir &&
"parent must exist");
2138 bool ImplicitlyDiscovered,
2139 FileID ID,
unsigned *Offset,
2140 StringRef OriginalModuleMapFile) {
2142 getModuleMapHomeDir(
File, OriginalModuleMapFile);
2143 assert(Dir &&
"module map home directory must exist");
2144 return hasModuleMapError(parseAndLoadModuleMapFileImpl(
2145 File, IsSystem, ImplicitlyDiscovered, *Dir, ID, Offset,
2149bool HeaderSearch::hasModuleMapError(ModuleMapResult
Result) {
2151 case MMR_AlreadyProcessed:
2152 case MMR_NewlyProcessed:
2154 case MMR_NoDirectory:
2155 case MMR_InvalidModuleMap:
2158 llvm_unreachable(
"Unknown module map result");
2162 bool ImplicitlyDiscovered) {
2163 assert(HSOpts.LazyLoadModuleMaps &&
2164 "module map parsing requires lazy loading support");
2166 getModuleMapHomeDir(
File, StringRef());
2167 assert(Dir &&
"module map home directory must exist");
2168 return hasModuleMapError(
2169 parseModuleMapFileImpl(
File, IsSystem, ImplicitlyDiscovered, *Dir));
2172HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
2177 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
2178 if (!AddResult.second)
2179 return AddResult.first->second ? MMR_AlreadyProcessed
2180 : MMR_InvalidModuleMap;
2184 LoadedModuleMaps[
File] =
false;
2185 return MMR_InvalidModuleMap;
2192 ImplicitlyDiscovered, Dir)) {
2193 LoadedModuleMaps[
File] =
false;
2194 return MMR_InvalidModuleMap;
2199 return MMR_NewlyProcessed;
2202HeaderSearch::ModuleMapResult
2204 bool ImplicitlyDiscovered,
2208 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
2209 if (!AddResult.second)
2210 return AddResult.first->second ? MMR_AlreadyProcessed
2211 : MMR_InvalidModuleMap;
2213 if (ModMap.parseModuleMapFile(
File, IsSystem, ImplicitlyDiscovered, Dir,
2215 ParsedModuleMaps[
File] =
false;
2216 return MMR_InvalidModuleMap;
2222 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, ImplicitlyDiscovered,
2224 ParsedModuleMaps[
File] =
false;
2225 return MMR_InvalidModuleMap;
2230 return MMR_NewlyProcessed;
2235 if (!HSOpts.ImplicitModuleMaps)
2236 return std::nullopt;
2241 llvm::sys::path::append(ModuleMapFileName,
"Modules");
2242 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
2243 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2247 ModuleMapFileName = Dir.
getName();
2248 llvm::sys::path::append(ModuleMapFileName,
"module.map");
2249 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
2250 Diags.Report(diag::warn_deprecated_module_dot_map)
2251 << ModuleMapFileName << 0 << IsFramework;
2258 ModuleMapFileName = Dir.
getName();
2259 llvm::sys::path::append(ModuleMapFileName,
"Modules",
2260 "module.private.modulemap");
2261 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2264 return std::nullopt;
2269 bool ImplicitlyDiscovered) {
2270 parseFrameworkModuleMap(Dir, IsSystem, ImplicitlyDiscovered,
true);
2275 bool ImplicitlyDiscovered,
2282 case MMR_InvalidModuleMap:
2285 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
2288 case MMR_NoDirectory:
2289 case MMR_AlreadyProcessed:
2290 case MMR_NewlyProcessed:
2295HeaderSearch::ModuleMapResult
2297 bool ImplicitlyDiscovered,
2299 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2303 return MMR_NoDirectory;
2306HeaderSearch::ModuleMapResult
2308 bool ImplicitlyDiscovered,
2310 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2311 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2312 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2313 if (!InsertRes.second) {
2314 switch (MMState.Status) {
2315 case ModuleMapDirectoryState::Parsed:
2317 case ModuleMapDirectoryState::Loaded:
2318 return MMR_AlreadyProcessed;
2319 case ModuleMapDirectoryState::Invalid:
2320 return MMR_InvalidModuleMap;
2324 if (!MMState.ModuleMapFile) {
2326 if (MMState.ModuleMapFile)
2327 MMState.PrivateModuleMapFile =
2331 if (MMState.ModuleMapFile) {
2332 ModuleMapResult
Result = parseAndLoadModuleMapFileImpl(
2333 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2337 if (
Result == MMR_NewlyProcessed)
2338 MMState.Status = ModuleMapDirectoryState::Loaded;
2339 else if (
Result == MMR_InvalidModuleMap)
2340 MMState.Status = ModuleMapDirectoryState::Invalid;
2343 return MMR_InvalidModuleMap;
2346HeaderSearch::ModuleMapResult
2348 bool ImplicitlyDiscovered,
bool IsFramework) {
2349 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2353 return MMR_NoDirectory;
2356HeaderSearch::ModuleMapResult
2358 bool ImplicitlyDiscovered,
bool IsFramework) {
2359 if (!HSOpts.LazyLoadModuleMaps)
2363 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2364 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2365 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2366 if (!InsertRes.second) {
2367 switch (MMState.Status) {
2368 case ModuleMapDirectoryState::Parsed:
2369 case ModuleMapDirectoryState::Loaded:
2370 return MMR_AlreadyProcessed;
2371 case ModuleMapDirectoryState::Invalid:
2372 return MMR_InvalidModuleMap;
2376 if (!MMState.ModuleMapFile) {
2378 if (MMState.ModuleMapFile)
2379 MMState.PrivateModuleMapFile =
2383 if (MMState.ModuleMapFile) {
2384 ModuleMapResult
Result = parseModuleMapFileImpl(
2385 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2389 if (
Result == MMR_NewlyProcessed)
2390 MMState.Status = ModuleMapDirectoryState::Parsed;
2391 else if (
Result == MMR_InvalidModuleMap)
2392 MMState.Status = ModuleMapDirectoryState::Invalid;
2395 return MMR_InvalidModuleMap;
2401 if (HSOpts.ImplicitModuleMaps) {
2404 bool IsSystem = DL.isSystemHeaderDirectory();
2405 if (DL.isFramework()) {
2408 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2411 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2412 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2414 Dir != DirEnd && !EC; Dir.increment(EC)) {
2415 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
2418 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2423 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2430 if (DL.isHeaderMap())
2440 parseSubdirectoryModuleMaps(DL,
true);
2445 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2449 if (!HSOpts.ImplicitModuleMaps)
2455 if (!DL.isNormalDir())
2460 true, DL.isFramework());
2464void HeaderSearch::parseSubdirectoryModuleMaps(
DirectoryLookup &SearchDir,
2467 "Should not be loading subdirectory module maps");
2474 FileMgr.makeAbsolutePath(Dir);
2476 llvm::sys::path::native(Dir, DirNative);
2477 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2478 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2479 Dir != DirEnd && !EC; Dir.increment(EC)) {
2480 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2482 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2502 MainFile, IsAngled);
2506 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2507 bool *IsAngled)
const {
2508 using namespace llvm::sys;
2511 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2512 path::make_absolute(WorkingDir, FilePath);
2516 path::remove_dots(FilePath,
true);
2517 path::native(FilePath, path::Style::posix);
2520 unsigned BestPrefixLength = 0;
2525 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2526 path::make_absolute(WorkingDir, Dir);
2527 path::remove_dots(Dir,
true);
2528 for (
auto NI = path::begin(
File), NE = path::end(
File),
2529 DI = path::begin(Dir), DE = path::end(Dir);
2530 NI != NE; ++NI, ++DI) {
2533 unsigned PrefixLength = NI - path::begin(
File);
2534 if (PrefixLength > BestPrefixLength) {
2535 BestPrefixLength = PrefixLength;
2542 if (NI->size() == 1 && DI->size() == 1 &&
2543 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2549 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2550 StringRef NBasename = path::stem(*NI);
2551 StringRef DBasename = path::stem(*DI);
2552 if (DBasename.starts_with(NBasename))
2562 bool BestPrefixIsFramework =
false;
2564 if (DL.isNormalDir()) {
2565 StringRef Dir = DL.getDirRef()->getName();
2566 if (CheckDir(Dir)) {
2568 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2569 BestPrefixIsFramework =
false;
2571 }
else if (DL.isFramework()) {
2572 StringRef Dir = DL.getFrameworkDirRef()->getName();
2573 if (CheckDir(Dir)) {
2576 *IsAngled = BestPrefixLength;
2577 BestPrefixIsFramework =
true;
2584 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2587 BestPrefixIsFramework =
false;
2592 StringRef Filename =
File.drop_front(BestPrefixLength);
2594 if (!DL.isHeaderMap())
2597 StringRef SpelledFilename =
2598 DL.getHeaderMap()->reverseLookupFilename(Filename);
2599 if (!SpelledFilename.empty()) {
2600 Filename = SpelledFilename;
2601 BestPrefixIsFramework =
false;
2608 bool IsPrivateHeader;
2610 if (BestPrefixIsFramework &&
2613 Filename = IncludeSpelling;
2615 return path::convert_to_slash(Filename);
2620 NormalizedPath.assign(Path.begin(), Path.end());
2621 if (!NormalizedPath.empty()) {
2622 FileMgr.makeAbsolutePath(NormalizedPath);
2623 llvm::sys::path::remove_dots(NormalizedPath);
2629 std::string ContextHash,
size_t &NormalizedModuleCachePathLen) {
2632 NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
2633 if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
2634 llvm::sys::path::append(SpecificModuleCachePath, ContextHash);
2635 return std::string(SpecificModuleCachePath);
2639 ContextHash = std::move(NewContextHash);
2641 FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash,
2642 NormalizedModuleCachePathLen);
2646 StringRef ModuleCachePath,
2647 bool DisableModuleHash,
2648 std::string ContextHash) {
2649 size_t NormalizedModuleCachePathLen;
2651 FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash),
2652 NormalizedModuleCachePathLen);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
Defines the clang::Module class, which describes a module in the source code.
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
constexpr bool has_value() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
Cached information about one directory (either on disk or in the virtual file system).
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
SrcMgr::CharacteristicKind getDirCharacteristic() const
DirCharacteristic - The type of directory this is, one of the DirType enum values.
bool haveLoadedAllModuleMaps() const
Determine whether we have already searched and loaded all of the module maps within this entire direc...
OptionalFileEntryRef LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, bool &IsInHeaderMap, SmallVectorImpl< char > &MappedName, bool OpenFile=true) const
LookupFile - Lookup the specified file in this search path, returning it if it exists or returning nu...
void setLoadedAllModuleMaps(bool LAMM)
Specify whether we have already loaded all of the module maps within the subdirectories of this direc...
bool isFramework() const
isFramework - True if this is a framework directory.
bool isSystemHeaderDirectory() const
Whether this describes a system header directory.
OptionalDirectoryEntryRef getFrameworkDirRef() const
bool isHeaderMap() const
isHeaderMap - Return true if this is a header map, not a normal directory.
StringRef getName() const
getName - Return the directory or filename corresponding to this lookup object.
OptionalDirectoryEntryRef getDirRef() const
const DirectoryEntry * getDir() const
getDir - Return the directory that this entry refers to.
bool isNormalDir() const
isNormalDir - Return true if this is a normal directory, not a header map.
const HeaderMap * getHeaderMap() const
getHeaderMap - Return the directory that this entry refers to.
Abstract interface for external sources of preprocessor information.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified file (real or virtual).
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Get a FileEntryRef if it exists, without doing anything on error.
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
One of these records is kept for each identifier that is lexed.
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isValid() const
Whether this pointer is non-NULL.
Identifies a module file to be loaded.
static ModuleFileName makeImplicit(std::string Name, unsigned SuffixLength)
Creates a file name for an implicit module.
static ModuleFileName makeExplicit(std::string Name)
Creates a file name for an explicit module.
bool isModuleKnown(StringRef Name) const
Determine if a top-level module named Name was loaded or parsed.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Load the given module map file, and record any modules we encounter.
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
const modulemap::ModuleMapFile * getParsedModuleMap(FileEntryRef File) const
Get the ModuleMapFile for a FileEntry previously parsed with parseModuleMapFile.
ModuleHeaderRole
Flags describing the role of a module header.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
Module * findOrLoadModule(StringRef Name)
bool resolveUses(Module *Mod, bool Complain)
Resolve all of the unresolved uses in the given module.
Describes a module or submodule.
bool directlyUses(const Module *Requested)
Determine whether this module has declared its intention to directly use another module.
std::string Name
The name of this module.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool markIncluded(FileEntryRef File)
Mark the file as included.
bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M)
Determine whether II is defined as a macro within the module M, if that is a module that we've alread...
bool isMacroDefined(StringRef Id)
bool alreadyIncluded(FileEntryRef File) const
Return true if this header has already been included.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Exposes information about the current target.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
detail::SearchDirIteratorImpl< true > ConstSearchDirIterator
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
std::string createSpecificModuleCachePath(FileManager &FileMgr, StringRef ModuleCachePath, bool DisableModuleHash, std::string ContextHash)
void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, SmallVectorImpl< char > &NormalizedPath)
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
This structure is used to record entries in our framework cache.
bool IsUserSpecifiedSystemFramework
Whether this framework has been "user-specified" to be treated as if it were a system framework (even...
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.
std::vector< Decl > Decls
Represents the parsed form of a module map file.
std::vector< TopLevelDecl > Decls