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);
288 SmallString<128> CanonicalPath(ModuleMapPath);
289 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
292 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
294 SmallString<128> HashStr;
295 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
296 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
303 bool AllowExtraModuleMapSearch) {
306 if (
Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
309 StringRef SearchName = ModuleName;
311 AllowExtraModuleMapSearch);
321 if (!
Module && SearchName.consume_back(
"_Private"))
323 AllowExtraModuleMapSearch);
324 if (!
Module && SearchName.consume_back(
"Private"))
326 AllowExtraModuleMapSearch);
332 bool AllowExtraModuleMapSearch) {
338 if (Dir.isFramework()) {
343 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
344 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
345 if (
auto FrameworkDir =
346 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
348 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem,
358 if (!Dir.isNormalDir())
361 bool IsSystem = Dir.isSystemHeaderDirectory();
364 DirectoryEntryRef NormalDir = *Dir.getDirRef();
366 if (parseModuleMapFile(NormalDir, IsSystem,
true,
367 false) == MMR_NewlyProcessed) {
370 Module = ModMap.findOrLoadModule(ModuleName);
377 SmallString<128> NestedModuleMapDirName;
378 NestedModuleMapDirName = Dir.getDirRef()->getName();
379 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
380 if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,
382 false) == MMR_NewlyProcessed) {
384 Module = ModMap.findOrLoadModule(ModuleName);
389 if (HSOpts.AllowModuleMapSubdirectorySearch) {
392 if (Dir.haveSearchedAllModuleMaps())
397 if (AllowExtraModuleMapSearch)
398 loadSubdirectoryModuleMaps(Dir);
401 Module = ModMap.findOrLoadModule(ModuleName);
410void HeaderSearch::indexInitialHeaderMaps() {
411 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
414 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
415 auto &Dir = SearchDirs[i];
420 if (!Dir.isHeaderMap()) {
421 SearchDirHeaderMapIndex = std::move(Index);
422 FirstNonHeaderMapSearchDirIdx = i;
427 auto Callback = [&](StringRef Filename) {
428 Index.try_emplace(Filename.lower(), i);
430 Dir.getHeaderMap()->forEachKey(
Callback);
445 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
451 bool IsSystemHeaderDir,
Module *RequestingModule,
453 bool CacheFailures ) {
460 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
461 if (EC != llvm::errc::no_such_file_or_directory &&
462 EC != llvm::errc::invalid_argument &&
463 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
464 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
471 if (!findUsableModuleForHeader(
472 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
473 SuggestedModule, IsSystemHeaderDir))
485 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
487 bool OpenFile)
const {
488 InUserSpecifiedSystemFramework =
false;
489 IsInHeaderMap =
false;
496 llvm::sys::path::append(TmpDir, Filename);
500 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
503 RelativePath->clear();
504 RelativePath->append(Filename.begin(), Filename.end());
507 return HS.getFileAndSuggestModule(
509 RequestingModule, SuggestedModule, OpenFile);
513 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
514 RequestingModule, SuggestedModule,
515 InUserSpecifiedSystemFramework, IsFrameworkFound);
517 assert(
isHeaderMap() &&
"Unknown directory lookup");
524 IsInHeaderMap =
true;
526 auto FixupSearchPathAndFindUsableModule =
529 StringRef SearchPathRef(
getName());
531 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
534 RelativePath->clear();
535 RelativePath->append(Filename.begin(), Filename.end());
537 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
538 RequestingModule, SuggestedModule,
548 if (llvm::sys::path::is_relative(Dest)) {
549 MappedName.append(Dest.begin(), Dest.end());
550 Filename = StringRef(MappedName.begin(), MappedName.size());
555 return FixupSearchPathAndFindUsableModule(*Res);
575 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
576 "Not a framework directory");
592 auto TopFrameworkDir =
FileMgr.getOptionalDirectoryRef(DirName);
595 DirName =
FileMgr.getCanonicalName(*TopFrameworkDir);
598 DirName = llvm::sys::path::parent_path(DirName);
603 auto Dir =
FileMgr.getOptionalDirectoryRef(DirName);
609 if (llvm::sys::path::extension(DirName) ==
".framework") {
610 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
611 TopFrameworkDir = *Dir;
615 return TopFrameworkDir;
619 bool HasSuggestedModule) {
620 return HasSuggestedModule ||
630 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
634 size_t SlashPos = Filename.find(
'/');
635 if (SlashPos == StringRef::npos)
640 FrameworkCacheEntry &CacheEntry =
650 SmallString<1024> FrameworkName;
652 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
653 FrameworkName.push_back(
'/');
656 StringRef ModuleName(Filename.begin(), SlashPos);
657 FrameworkName += ModuleName;
660 FrameworkName +=
".framework/";
664 ++NumFrameworkLookups;
678 SmallString<1024> SystemFrameworkMarker(FrameworkName);
679 SystemFrameworkMarker +=
".system_framework";
690 RelativePath->clear();
691 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
695 unsigned OrigSize = FrameworkName.size();
697 FrameworkName +=
"Headers/";
702 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
705 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
711 const char *
Private =
"Private";
712 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
715 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
725 StringRef FrameworkPath =
File->getDir().getName();
726 bool FoundFramework =
false;
735 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
736 FoundFramework =
true;
741 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
742 if (FrameworkPath.empty())
747 if (FoundFramework) {
748 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
750 SuggestedModule, IsSystem))
753 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
754 SuggestedModule, IsSystem))
763void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
766 CacheLookup.HitIt = HitIt;
767 noteLookupUsage(HitIt.Idx, Loc);
770void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
771 SearchDirsUsage[HitIdx] =
true;
773 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
774 if (UserEntryIdxIt != SearchDirToHSEntry.end())
775 Diags.Report(Loc, diag::remark_pp_search_path_usage)
776 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
794 if (MSFE && FE != *MSFE) {
795 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
801static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
802 assert(!Str.empty());
803 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
804 std::copy(Str.begin(), Str.end(), CopyStr);
805 CopyStr[Str.size()] =
'\0';
812 using namespace llvm::sys;
813 path::const_iterator I = path::begin(Path);
814 path::const_iterator E = path::end(Path);
815 IsPrivateHeader =
false;
827 if (*I ==
"Headers") {
829 }
else if (*I ==
"PrivateHeaders") {
831 IsPrivateHeader =
true;
832 }
else if (I->ends_with(
".framework")) {
833 StringRef Name = I->drop_back(10);
835 FrameworkName.clear();
836 FrameworkName.append(Name.begin(), Name.end());
837 IncludeSpelling.clear();
838 IncludeSpelling.append(Name.begin(), Name.end());
840 }
else if (FoundComp >= 2) {
841 IncludeSpelling.push_back(
'/');
842 IncludeSpelling.append(I->begin(), I->end());
847 return !FrameworkName.empty() && FoundComp >= 2;
852 StringRef Includer, StringRef IncludeFilename,
854 bool FoundByHeaderMap =
false) {
855 bool IsIncluderPrivateHeader =
false;
859 FromIncludeSpelling))
861 bool IsIncludeePrivateHeader =
false;
862 bool IsIncludeeInFramework =
864 ToFramework, ToIncludeSpelling);
866 if (!isAngled && !FoundByHeaderMap) {
868 if (IsIncludeeInFramework) {
869 NewInclude += ToIncludeSpelling;
872 NewInclude += IncludeFilename;
875 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
883 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
884 IsIncludeePrivateHeader && FromFramework == ToFramework)
885 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
891 ConstSearchDirIterator FromDir,
892 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
893 bool isAngled,
int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
895 if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc))
898 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
904 if (!ShadowCheckedHeaders[Filename].insert(FE).second)
909 for (
size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
910 const auto &IncluderAndDir = Includers[i];
912 llvm::sys::path::append(TmpDir, Filename);
916 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
918 << IncluderAndDir.second.getName();
925 ConstSearchDirIterator It =
928 It = std::next(MainLoopIt);
929 }
else if (FromDir) {
937 llvm::sys::path::append(TmpPath, Filename);
941 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
955 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
956 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
959 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
960 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
961 ConstSearchDirIterator CurDirLocal =
nullptr;
962 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
967 if (IsFrameworkFound)
968 *IsFrameworkFound =
false;
974 if (llvm::sys::path::is_absolute(Filename)) {
984 RelativePath->clear();
985 RelativePath->append(Filename.begin(), Filename.end());
988 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
990 RequestingModule, SuggestedModule, OpenFile,
1003 if (!Includers.empty() && !isAngled) {
1006 for (
const auto &IncluderAndDir : Includers) {
1010 TmpDir = IncluderAndDir.second.getName();
1011 llvm::sys::path::append(TmpDir, Filename);
1020 bool IncluderIsSystemHeader = [&]() {
1022 return BuildSystemModule;
1024 assert(HFI &&
"includer without file info");
1028 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
1029 RequestingModule, SuggestedModule)) {
1031 isAngled, &IncluderAndDir - Includers.begin(),
1034 assert(
First &&
"only first includer can have no file");
1045 assert(FromHFI &&
"includer without file info");
1046 unsigned DirInfo = FromHFI->
DirInfo;
1052 StringRef SearchPathRef(IncluderAndDir.second.getName());
1053 SearchPath->clear();
1054 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
1057 RelativePath->clear();
1058 RelativePath->append(Filename.begin(), Filename.end());
1062 IncluderAndDir.second.getName(), Filename,
1070 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1074 if (SuggestedModule) {
1075 MSSuggestedModule = *SuggestedModule;
1088 ConstSearchDirIterator It =
1100 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1102 ConstSearchDirIterator NextIt = std::next(It);
1105 if (CacheLookup.StartIt == NextIt &&
1106 CacheLookup.RequestingModule == RequestingModule) {
1108 if (CacheLookup.HitIt)
1109 It = CacheLookup.HitIt;
1110 if (CacheLookup.MappedName) {
1111 Filename = CacheLookup.MappedName;
1119 CacheLookup.reset(RequestingModule, NextIt);
1125 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1126 if (Iter == SearchDirHeaderMapIndex.end())
1135 CacheLookup.reset(RequestingModule, NextIt);
1142 bool InUserSpecifiedSystemFramework =
false;
1143 bool IsInHeaderMap =
false;
1144 bool IsFrameworkFoundInDir =
false;
1146 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1147 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1148 IsInHeaderMap, MappedName, OpenFile);
1149 if (!MappedName.empty()) {
1150 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1151 CacheLookup.MappedName =
1152 copyString(MappedName, LookupFileCache.getAllocator());
1158 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1159 if (IsFrameworkFound)
1163 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1177 IncludeNames[*
File] = Filename;
1181 HFI.
DirInfo = CurDir->getDirCharacteristic();
1191 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1192 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1200 if (SuggestedModule)
1201 *SuggestedModule = MSSuggestedModule;
1205 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1206 if (!Includers.empty())
1208 Includers.front().second.getName(), Filename,
1209 *
File, isAngled, FoundByHeaderMap);
1212 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1217 if (SuggestedModule)
1218 *SuggestedModule = MSSuggestedModule;
1224 return std::nullopt;
1238 size_t SlashPos = Filename.find(
'/');
1239 if (SlashPos == StringRef::npos)
1240 return std::nullopt;
1243 StringRef ContextName = ContextFileEnt.
getName();
1246 const unsigned DotFrameworkLen = 10;
1247 auto FrameworkPos = ContextName.find(
".framework");
1248 if (FrameworkPos == StringRef::npos ||
1249 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1250 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1251 return std::nullopt;
1255 DotFrameworkLen + 1);
1258 FrameworkName +=
"Frameworks/";
1259 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1260 FrameworkName +=
".framework/";
1263 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1267 if (CacheLookup.second.Directory &&
1268 CacheLookup.first().size() == FrameworkName.size() &&
1269 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1270 CacheLookup.first().size()) != 0)
1271 return std::nullopt;
1274 if (!CacheLookup.second.Directory) {
1275 ++NumSubFrameworkLookups;
1278 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1280 return std::nullopt;
1284 CacheLookup.second.Directory = Dir;
1289 RelativePath->clear();
1290 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1295 HeadersFilename +=
"Headers/";
1297 SearchPath->clear();
1299 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1302 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1303 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1306 HeadersFilename = FrameworkName;
1307 HeadersFilename +=
"PrivateHeaders/";
1309 SearchPath->clear();
1311 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1314 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1315 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1318 return std::nullopt;
1323 assert(ContextHFI &&
"context file without file info");
1326 unsigned DirInfo = ContextHFI->
DirInfo;
1329 FrameworkName.pop_back();
1330 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1331 RequestingModule, SuggestedModule,
1333 return std::nullopt;
1352 bool isModuleHeader,
1353 bool isTextualModuleHeader) {
1370 assert(OtherHFI.
External &&
"expected to merge external HFI");
1388 if (ExternalSource && !HFI->
Resolved) {
1389 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1390 if (ExternalHFI.IsValid) {
1392 if (ExternalHFI.External)
1406 if (ExternalSource) {
1407 HFI = &FileInfo[FE];
1410 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1411 if (ExternalHFI.IsValid) {
1413 if (ExternalHFI.External)
1417 }
else if (
auto It = FileInfo.find(FE); It != FileInfo.end()) {
1423 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1428 for (
const auto &[FE, HFI] : FileInfo)
1429 if (HFI.IsValid && !HFI.External)
1438 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1444 bool isCompilingModuleHeader) {
1446 if (!isCompilingModuleHeader) {
1455 HFI.mergeModuleMembership(
Role);
1456 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1461 bool ModulesEnabled,
Module *M,
1462 bool &IsFirstIncludeOfFile) {
1478 IsFirstIncludeOfFile =
false;
1481 auto MaybeReenterImportedFile = [&]() ->
bool {
1499 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1503 ModMap.resolveHeaderDirectives(
File);
1523 if (FileInfo.isTextualModuleHeader)
1526 if (FileInfo.isCompilingModuleHeader) {
1529 if (FileInfo.isModuleHeader) {
1534 if (ModMap.isBuiltinHeader(
File))
1543 if (FileInfo.getControllingMacro(ExternalLookup))
1563 FileInfo.isImport =
true;
1570 if (FileInfo.isPragmaOnce ||
1571 (FileInfo.isImport && !MaybeReenterImportedFile()))
1580 FileInfo.getControllingMacro(ExternalLookup)) {
1587 ++NumMultiIncludeFileOptzn;
1597 return SearchDirs.capacity()
1598 + llvm::capacity_in_bytes(FileInfo)
1599 + llvm::capacity_in_bytes(HeaderMaps)
1600 + LookupFileCache.getAllocator().getTotalMemory()
1601 + FrameworkMap.getAllocator().getTotalMemory();
1605 return &DL - &*SearchDirs.begin();
1609 return FrameworkNames.insert(Framework).first->first();
1613 auto It = IncludeNames.find(
File);
1614 if (It == IncludeNames.end())
1620 ModuleMapDirectoryState &MMState) {
1621 if (!MMState.ModuleMapFile)
1628 if (MMState.PrivateModuleMapFile)
1631 processModuleMapForIndex(*ParsedMM, Dir,
"", MMState);
1632 if (ParsedPrivateMM)
1633 processModuleMapForIndex(*ParsedPrivateMM, Dir,
"", MMState);
1636void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
1637 StringRef PathPrefix,
1638 ModuleMapDirectoryState &MMState) {
1640 llvm::sys::path::append(RelFromRootPath, RelPath);
1641 llvm::sys::path::native(RelFromRootPath);
1642 MMState.HeaderToModules[RelFromRootPath].push_back(ModuleName);
1645void HeaderSearch::processExternModuleDeclForIndex(
1647 StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
1648 StringRef FileNameRef = EMD.
Path;
1649 SmallString<128> ModuleMapFileName;
1650 if (llvm::sys::path::is_relative(FileNameRef)) {
1651 ModuleMapFileName = MMDir.
getName();
1652 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
1653 FileNameRef = ModuleMapFileName;
1655 if (
auto EFile = FileMgr.getOptionalFileRef(FileNameRef)) {
1656 if (
auto *ExtMMF = ModMap.getParsedModuleMap(*EFile)) {
1659 SmallString<128> NewPrefix(PathPrefix);
1660 StringRef ExternDir = llvm::sys::path::parent_path(EMD.
Path);
1661 if (!ExternDir.empty()) {
1662 llvm::sys::path::append(NewPrefix, ExternDir);
1663 llvm::sys::path::native(NewPrefix);
1665 processModuleMapForIndex(*ExtMMF, EFile->getDir(), NewPrefix, MMState);
1671 StringRef ModuleName,
1673 StringRef PathPrefix,
1674 ModuleMapDirectoryState &MMState) {
1676 if (MD.
Id.front().first ==
"*")
1679 auto ProcessDecl = llvm::makeVisitor(
1680 [&](
const modulemap::HeaderDecl &HD) {
1682 MMState.UmbrellaHeaderModules.push_back(ModuleName);
1684 addToModuleMapIndex(HD.
Path, ModuleName, PathPrefix, MMState);
1687 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1688 SmallString<128> FullPath(PathPrefix);
1689 llvm::sys::path::append(FullPath, UDD.Path);
1690 llvm::sys::path::native(FullPath);
1691 MMState.UmbrellaDirModules.push_back(
1692 std::make_pair(std::string(FullPath), ModuleName));
1694 [&](
const modulemap::ModuleDecl &SubMD) {
1695 processModuleDeclForIndex(SubMD, ModuleName, MMDir, PathPrefix,
1698 [&](
const modulemap::ExternModuleDecl &EMD) {
1699 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
1705 for (
const auto &Decl : MD.
Decls) {
1706 std::visit(ProcessDecl, Decl);
1712 StringRef PathPrefix,
1713 ModuleMapDirectoryState &MMState) {
1714 for (
const auto &Decl : MMF.
Decls) {
1715 std::visit(llvm::makeVisitor(
1716 [&](
const modulemap::ModuleDecl &MD) {
1717 processModuleDeclForIndex(MD, MD.
Id.front().first, MMDir,
1718 PathPrefix, MMState);
1720 [&](
const modulemap::ExternModuleDecl &EMD) {
1721 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
1733 if (!
FileName.starts_with(DirPath))
1735 StringRef RelativePath =
FileName.substr(DirPath.size());
1736 while (!RelativePath.empty() &&
1737 llvm::sys::path::is_separator(RelativePath.front()))
1738 RelativePath = RelativePath.substr(1);
1739 return RelativePath;
1743 StringRef RelativePath,
const ModuleMapDirectoryState &MMState)
const {
1744 SmallVector<StringRef, 1> Modules;
1747 auto CachedMods = MMState.HeaderToModules.find(RelativePath);
1748 if (CachedMods != MMState.HeaderToModules.end())
1749 Modules.append(CachedMods->second.begin(), CachedMods->second.end());
1752 for (
const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
1753 if (RelativePath.starts_with(UmbrellaDir.first) || UmbrellaDir.first ==
".")
1754 Modules.push_back(UmbrellaDir.second);
1768 Modules.append(MMState.UmbrellaHeaderModules.begin(),
1769 MMState.UmbrellaHeaderModules.end());
1777 if (!HSOpts.ImplicitModuleMaps)
1784 DirName = llvm::sys::path::parent_path(DirName);
1785 if (DirName.empty())
1789 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1795 llvm::sys::path::extension(Dir->
getName()) ==
".framework";
1799 parseModuleMapFile(*Dir, IsSystem,
true,
1801 auto DirState = DirectoryModuleMap.find(*Dir);
1802 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1805 if (!HSOpts.LazyLoadModuleMaps &&
1806 Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1810 auto &MMState = DirState->second;
1813 if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
1814 MMState.UmbrellaHeaderModules.empty()) {
1815 buildModuleMapIndex(*Dir, MMState);
1819 if (!HSOpts.LazyLoadModuleMaps)
1827 llvm::sys::path::native(RelativePathNative);
1829 auto ModulesToLoad =
1830 findMatchingModulesInIndex(RelativePathNative, MMState);
1833 bool LoadedAny =
false;
1834 for (StringRef ModName : ModulesToLoad) {
1835 if (ModMap.findOrLoadModule(ModName)) {
1844 }
while (CurDir != Root);
1850 bool AllowExcluded)
const {
1851 if (ExternalSource) {
1856 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1861 if (ExternalSource) {
1866 return ModMap.findAllModulesForHeader(
File);
1871 if (ExternalSource) {
1876 return ModMap.findResolvedModulesForHeader(
File);
1893 if (SuggestedModule)
1903 if (SuggestedModule)
1917 if (!HSOpts.ImplicitModuleMaps ||
Module.getModule()->isPartOfFramework() ||
1918 !
Module.getModule()->isModuleMapModule())
1921 if (Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1922 Module.getModule()->DefinitionLoc))
1925 if (
File.isDeviceFile() ||
File.isNamedPipe())
1928 llvm::SmallString<128> AbsPath(
File.getName());
1929 FileMgr.makeAbsolutePath(AbsPath);
1930 llvm::sys::path::remove_dots(AbsPath,
true);
1934 llvm::SmallString<128> LinkTarget;
1935 if (llvm::sys::fs::readlink(AbsPath, LinkTarget))
1943 const DirectoryEntry *CurDir =
nullptr;
1947 DirName = llvm::sys::path::parent_path(DirName);
1948 if (DirName.empty())
1951 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1956 auto DirState = DirectoryModuleMap.find(*Dir);
1957 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1963 if (RelativePath.empty())
1965 SmallString<128> RelativePathNative(RelativePath);
1966 llvm::sys::path::native(RelativePathNative);
1968 auto MatchingModules =
1969 findMatchingModulesInIndex(RelativePathNative, DirState->second);
1970 if (!MatchingModules.empty())
1972 }
while (CurDir != Root);
1975 Diags.Report(diag::warn_mmap_deprecated_symlink_to_modular_header)
1976 <<
File.getName() << LinkTarget
1977 <<
Module.getModule()->getFullModuleName();
1978 Diags.Report(
Module.getModule()->DefinitionLoc,
1979 diag::note_mmap_module_defined_here);
1982bool HeaderSearch::findUsableModuleForHeader(
1986 if (!HSOpts.LazyLoadModuleMaps) {
1992 ModuleMap::KnownHeader
Module =
1994 diagnoseUncoveredSymlink(
File,
Module, Root);
2000 ModuleMap::KnownHeader
Module =
2008 Module = ModMap.findModuleForHeader(
File,
true);
2010 diagnoseUncoveredSymlink(
File,
Module, Root);
2017bool HeaderSearch::findUsableModuleForFrameworkHeader(
2023 SmallVector<std::string, 4> SubmodulePath;
2026 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
2029 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
2033 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework,
2040 ModuleMap::KnownHeader
Module =
2051 bool Diagnose =
true) {
2052 StringRef Filename = llvm::sys::path::filename(
File.getName());
2054 if (Filename ==
"module.map")
2055 llvm::sys::path::append(PrivateFilename,
"module_private.map");
2056 else if (Filename ==
"module.modulemap")
2057 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
2059 return std::nullopt;
2060 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
2062 if (Diagnose && Filename ==
"module.map")
2063 Diags.
Report(diag::warn_deprecated_module_dot_map)
2064 << PrivateFilename << 1
2065 <<
File.getDir().getName().ends_with(
".framework");
2071 bool ImplicitlyDiscovered,
2072 FileID ID,
unsigned *Offset,
2073 StringRef OriginalModuleMapFile) {
2078 Dir = FileMgr.getOptionalDirectoryRef(
".");
2080 if (!OriginalModuleMapFile.empty()) {
2083 Dir = FileMgr.getOptionalDirectoryRef(
2084 llvm::sys::path::parent_path(OriginalModuleMapFile));
2086 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
2087 Dir = FakeFile.getDir();
2090 Dir =
File.getDir();
2093 assert(Dir &&
"parent must exist");
2094 StringRef DirName(Dir->
getName());
2095 if (llvm::sys::path::filename(DirName) ==
"Modules") {
2096 DirName = llvm::sys::path::parent_path(DirName);
2097 if (DirName.ends_with(
".framework"))
2098 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
2102 assert(Dir &&
"parent must exist");
2106 assert(Dir &&
"module map home directory must exist");
2107 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, ImplicitlyDiscovered,
2110 case MMR_AlreadyProcessed:
2111 case MMR_NewlyProcessed:
2113 case MMR_NoDirectory:
2114 case MMR_InvalidModuleMap:
2117 llvm_unreachable(
"Unknown load module map result");
2120HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
2125 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
2126 if (!AddResult.second)
2127 return AddResult.first->second ? MMR_AlreadyProcessed
2128 : MMR_InvalidModuleMap;
2132 LoadedModuleMaps[
File] =
false;
2133 return MMR_InvalidModuleMap;
2140 ImplicitlyDiscovered, Dir)) {
2141 LoadedModuleMaps[
File] =
false;
2142 return MMR_InvalidModuleMap;
2147 return MMR_NewlyProcessed;
2150HeaderSearch::ModuleMapResult
2152 bool ImplicitlyDiscovered,
2156 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
2157 if (!AddResult.second)
2158 return AddResult.first->second ? MMR_AlreadyProcessed
2159 : MMR_InvalidModuleMap;
2161 if (ModMap.parseModuleMapFile(
File, IsSystem, ImplicitlyDiscovered, Dir,
2163 ParsedModuleMaps[
File] =
false;
2164 return MMR_InvalidModuleMap;
2170 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, ImplicitlyDiscovered,
2172 ParsedModuleMaps[
File] =
false;
2173 return MMR_InvalidModuleMap;
2178 return MMR_NewlyProcessed;
2183 if (!HSOpts.ImplicitModuleMaps)
2184 return std::nullopt;
2189 llvm::sys::path::append(ModuleMapFileName,
"Modules");
2190 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
2191 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2195 ModuleMapFileName = Dir.
getName();
2196 llvm::sys::path::append(ModuleMapFileName,
"module.map");
2197 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
2198 Diags.Report(diag::warn_deprecated_module_dot_map)
2199 << ModuleMapFileName << 0 << IsFramework;
2206 ModuleMapFileName = Dir.
getName();
2207 llvm::sys::path::append(ModuleMapFileName,
"Modules",
2208 "module.private.modulemap");
2209 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2212 return std::nullopt;
2217 bool ImplicitlyDiscovered) {
2221 case MMR_InvalidModuleMap:
2224 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
2227 case MMR_NoDirectory:
2230 case MMR_AlreadyProcessed:
2231 case MMR_NewlyProcessed:
2238HeaderSearch::ModuleMapResult
2240 bool ImplicitlyDiscovered,
2242 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2246 return MMR_NoDirectory;
2249HeaderSearch::ModuleMapResult
2251 bool ImplicitlyDiscovered,
2253 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2254 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2255 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2256 if (!InsertRes.second) {
2257 switch (MMState.Status) {
2258 case ModuleMapDirectoryState::Parsed:
2260 case ModuleMapDirectoryState::Loaded:
2261 return MMR_AlreadyProcessed;
2262 case ModuleMapDirectoryState::Invalid:
2263 return MMR_InvalidModuleMap;
2267 if (!MMState.ModuleMapFile) {
2269 if (MMState.ModuleMapFile)
2270 MMState.PrivateModuleMapFile =
2274 if (MMState.ModuleMapFile) {
2275 ModuleMapResult
Result = parseAndLoadModuleMapFileImpl(
2276 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2280 if (
Result == MMR_NewlyProcessed)
2281 MMState.Status = ModuleMapDirectoryState::Loaded;
2282 else if (
Result == MMR_InvalidModuleMap)
2283 MMState.Status = ModuleMapDirectoryState::Invalid;
2286 return MMR_InvalidModuleMap;
2289HeaderSearch::ModuleMapResult
2290HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
2291 bool ImplicitlyDiscovered,
bool IsFramework) {
2292 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2293 return parseModuleMapFile(*Dir, IsSystem, ImplicitlyDiscovered,
2296 return MMR_NoDirectory;
2299HeaderSearch::ModuleMapResult
2301 bool ImplicitlyDiscovered,
bool IsFramework) {
2302 if (!HSOpts.LazyLoadModuleMaps)
2306 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2307 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2308 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2309 if (!InsertRes.second) {
2310 switch (MMState.Status) {
2311 case ModuleMapDirectoryState::Parsed:
2312 case ModuleMapDirectoryState::Loaded:
2313 return MMR_AlreadyProcessed;
2314 case ModuleMapDirectoryState::Invalid:
2315 return MMR_InvalidModuleMap;
2319 if (!MMState.ModuleMapFile) {
2321 if (MMState.ModuleMapFile)
2322 MMState.PrivateModuleMapFile =
2326 if (MMState.ModuleMapFile) {
2327 ModuleMapResult
Result = parseModuleMapFileImpl(
2328 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2332 if (
Result == MMR_NewlyProcessed)
2333 MMState.Status = ModuleMapDirectoryState::Parsed;
2334 else if (
Result == MMR_InvalidModuleMap)
2335 MMState.Status = ModuleMapDirectoryState::Invalid;
2338 return MMR_InvalidModuleMap;
2344 if (HSOpts.ImplicitModuleMaps) {
2347 bool IsSystem = DL.isSystemHeaderDirectory();
2348 if (DL.isFramework()) {
2351 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2354 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2355 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2357 Dir != DirEnd && !EC; Dir.increment(EC)) {
2358 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
2361 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2366 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2373 if (DL.isHeaderMap())
2383 loadSubdirectoryModuleMaps(DL);
2388 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2392 if (!HSOpts.ImplicitModuleMaps)
2398 if (!DL.isNormalDir())
2403 true, DL.isFramework());
2407void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2409 "Should not be loading subdirectory module maps");
2416 FileMgr.makeAbsolutePath(Dir);
2418 llvm::sys::path::native(Dir, DirNative);
2419 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2420 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2421 Dir != DirEnd && !EC; Dir.increment(EC)) {
2422 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2424 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2437 MainFile, IsAngled);
2441 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2442 bool *IsAngled)
const {
2443 using namespace llvm::sys;
2446 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2447 path::make_absolute(WorkingDir, FilePath);
2451 path::remove_dots(FilePath,
true);
2452 path::native(FilePath, path::Style::posix);
2455 unsigned BestPrefixLength = 0;
2460 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2461 path::make_absolute(WorkingDir, Dir);
2462 path::remove_dots(Dir,
true);
2463 for (
auto NI = path::begin(
File), NE = path::end(
File),
2464 DI = path::begin(Dir), DE = path::end(Dir);
2465 NI != NE; ++NI, ++DI) {
2468 unsigned PrefixLength = NI - path::begin(
File);
2469 if (PrefixLength > BestPrefixLength) {
2470 BestPrefixLength = PrefixLength;
2477 if (NI->size() == 1 && DI->size() == 1 &&
2478 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2484 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2485 StringRef NBasename = path::stem(*NI);
2486 StringRef DBasename = path::stem(*DI);
2487 if (DBasename.starts_with(NBasename))
2497 bool BestPrefixIsFramework =
false;
2499 if (DL.isNormalDir()) {
2500 StringRef Dir = DL.getDirRef()->getName();
2501 if (CheckDir(Dir)) {
2503 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2504 BestPrefixIsFramework =
false;
2506 }
else if (DL.isFramework()) {
2507 StringRef Dir = DL.getFrameworkDirRef()->getName();
2508 if (CheckDir(Dir)) {
2511 *IsAngled = BestPrefixLength;
2512 BestPrefixIsFramework =
true;
2519 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2522 BestPrefixIsFramework =
false;
2527 StringRef Filename =
File.drop_front(BestPrefixLength);
2529 if (!DL.isHeaderMap())
2532 StringRef SpelledFilename =
2533 DL.getHeaderMap()->reverseLookupFilename(Filename);
2534 if (!SpelledFilename.empty()) {
2535 Filename = SpelledFilename;
2536 BestPrefixIsFramework =
false;
2543 bool IsPrivateHeader;
2545 if (BestPrefixIsFramework &&
2548 Filename = IncludeSpelling;
2550 return path::convert_to_slash(Filename);
2555 NormalizedPath.assign(Path.begin(), Path.end());
2556 if (!NormalizedPath.empty()) {
2557 FileMgr.makeAbsolutePath(NormalizedPath);
2558 llvm::sys::path::remove_dots(NormalizedPath);
2564 std::string ContextHash,
size_t &NormalizedModuleCachePathLen) {
2567 NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
2568 if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
2569 llvm::sys::path::append(SpecificModuleCachePath, ContextHash);
2570 return std::string(SpecificModuleCachePath);
2574 ContextHash = std::move(NewContextHash);
2576 FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash,
2577 NormalizedModuleCachePathLen);
2581 StringRef ModuleCachePath,
2582 bool DisableModuleHash,
2583 std::string ContextHash) {
2584 size_t NormalizedModuleCachePathLen;
2586 FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash),
2587 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.
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...
bool isFramework() const
isFramework - True if this is a framework directory.
bool isSystemHeaderDirectory() const
Whether this describes a system header directory.
OptionalDirectoryEntryRef getFrameworkDirRef() const
void setSearchedAllModuleMaps(bool SAMM)
Specify whether we have already searched all of the subdirectories for module maps.
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
bool haveSearchedAllModuleMaps() const
Determine whether we have already searched this entire directory for module maps.
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.
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...
@ 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