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)
892 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
893 bool isAngled,
int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
895 if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc) ||
899 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
902 DiagnosedShadowing =
true;
906 for (
size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
907 const auto &IncluderAndDir = Includers[i];
909 llvm::sys::path::append(TmpDir, Filename);
910 if (
auto File =
getFileMgr().getOptionalFileRef(TmpDir,
false,
false)) {
911 if (&
File->getFileEntry() == *FE)
913 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
914 << Filename << (*FE).getDir().getName()
915 << IncluderAndDir.second.getName();
922 ConstSearchDirIterator It =
925 It = std::next(MainLoopIt);
926 }
else if (FromDir) {
934 llvm::sys::path::append(TmpPath, Filename);
935 if (
auto File =
getFileMgr().getOptionalFileRef(TmpPath,
false,
false)) {
936 if (&
File->getFileEntry() == *FE)
938 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
939 << Filename << (*FE).getDir().getName() << It->getName();
952 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
953 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
956 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
957 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
958 ConstSearchDirIterator CurDirLocal =
nullptr;
959 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
964 if (IsFrameworkFound)
965 *IsFrameworkFound =
false;
971 if (llvm::sys::path::is_absolute(Filename)) {
981 RelativePath->clear();
982 RelativePath->append(Filename.begin(), Filename.end());
985 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
987 RequestingModule, SuggestedModule, OpenFile,
994 bool DiagnosedShadowing =
false;
1001 if (!Includers.empty() && !isAngled) {
1004 for (
const auto &IncluderAndDir : Includers) {
1008 TmpDir = IncluderAndDir.second.getName();
1009 llvm::sys::path::append(TmpDir, Filename);
1018 bool IncluderIsSystemHeader = [&]() {
1020 return BuildSystemModule;
1022 assert(HFI &&
"includer without file info");
1026 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
1027 RequestingModule, SuggestedModule)) {
1029 FromDir, Includers, isAngled,
1030 &IncluderAndDir - Includers.begin(),
nullptr);
1032 assert(
First &&
"only first includer can have no file");
1043 assert(FromHFI &&
"includer without file info");
1044 unsigned DirInfo = FromHFI->
DirInfo;
1050 StringRef SearchPathRef(IncluderAndDir.second.getName());
1051 SearchPath->clear();
1052 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
1055 RelativePath->clear();
1056 RelativePath->append(Filename.begin(), Filename.end());
1060 IncluderAndDir.second.getName(), Filename,
1068 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1072 if (SuggestedModule) {
1073 MSSuggestedModule = *SuggestedModule;
1086 ConstSearchDirIterator It =
1098 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1100 ConstSearchDirIterator NextIt = std::next(It);
1103 if (CacheLookup.StartIt == NextIt &&
1104 CacheLookup.RequestingModule == RequestingModule) {
1106 if (CacheLookup.HitIt)
1107 It = CacheLookup.HitIt;
1108 if (CacheLookup.MappedName) {
1109 Filename = CacheLookup.MappedName;
1117 CacheLookup.reset(RequestingModule, NextIt);
1123 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1124 if (Iter == SearchDirHeaderMapIndex.end())
1133 CacheLookup.reset(RequestingModule, NextIt);
1140 bool InUserSpecifiedSystemFramework =
false;
1141 bool IsInHeaderMap =
false;
1142 bool IsFrameworkFoundInDir =
false;
1144 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1145 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1146 IsInHeaderMap, MappedName, OpenFile);
1147 if (!MappedName.empty()) {
1148 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1149 CacheLookup.MappedName =
1150 copyString(MappedName, LookupFileCache.getAllocator());
1156 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1157 if (IsFrameworkFound)
1161 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1166 FromDir, Includers, isAngled, -1, It);
1170 IncludeNames[*
File] = Filename;
1174 HFI.
DirInfo = CurDir->getDirCharacteristic();
1184 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1185 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1193 if (SuggestedModule)
1194 *SuggestedModule = MSSuggestedModule;
1198 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1199 if (!Includers.empty())
1201 Includers.front().second.getName(), Filename,
1202 *
File, isAngled, FoundByHeaderMap);
1205 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1210 if (SuggestedModule)
1211 *SuggestedModule = MSSuggestedModule;
1217 return std::nullopt;
1231 size_t SlashPos = Filename.find(
'/');
1232 if (SlashPos == StringRef::npos)
1233 return std::nullopt;
1236 StringRef ContextName = ContextFileEnt.
getName();
1239 const unsigned DotFrameworkLen = 10;
1240 auto FrameworkPos = ContextName.find(
".framework");
1241 if (FrameworkPos == StringRef::npos ||
1242 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1243 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1244 return std::nullopt;
1248 DotFrameworkLen + 1);
1251 FrameworkName +=
"Frameworks/";
1252 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1253 FrameworkName +=
".framework/";
1256 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1260 if (CacheLookup.second.Directory &&
1261 CacheLookup.first().size() == FrameworkName.size() &&
1262 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1263 CacheLookup.first().size()) != 0)
1264 return std::nullopt;
1267 if (!CacheLookup.second.Directory) {
1268 ++NumSubFrameworkLookups;
1271 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1273 return std::nullopt;
1277 CacheLookup.second.Directory = Dir;
1282 RelativePath->clear();
1283 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1288 HeadersFilename +=
"Headers/";
1290 SearchPath->clear();
1292 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1295 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1296 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1299 HeadersFilename = FrameworkName;
1300 HeadersFilename +=
"PrivateHeaders/";
1302 SearchPath->clear();
1304 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1307 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1308 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1311 return std::nullopt;
1316 assert(ContextHFI &&
"context file without file info");
1319 unsigned DirInfo = ContextHFI->
DirInfo;
1322 FrameworkName.pop_back();
1323 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1324 RequestingModule, SuggestedModule,
1326 return std::nullopt;
1345 bool isModuleHeader,
1346 bool isTextualModuleHeader) {
1363 assert(OtherHFI.
External &&
"expected to merge external HFI");
1381 if (ExternalSource && !HFI->
Resolved) {
1382 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1383 if (ExternalHFI.IsValid) {
1385 if (ExternalHFI.External)
1399 if (ExternalSource) {
1400 HFI = &FileInfo[FE];
1403 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1404 if (ExternalHFI.IsValid) {
1406 if (ExternalHFI.External)
1410 }
else if (
auto It = FileInfo.find(FE); It != FileInfo.end()) {
1416 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1421 for (
const auto &[FE, HFI] : FileInfo)
1422 if (HFI.IsValid && !HFI.External)
1431 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1437 bool isCompilingModuleHeader) {
1439 if (!isCompilingModuleHeader) {
1448 HFI.mergeModuleMembership(
Role);
1449 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1454 bool ModulesEnabled,
Module *M,
1455 bool &IsFirstIncludeOfFile) {
1471 IsFirstIncludeOfFile =
false;
1474 auto MaybeReenterImportedFile = [&]() ->
bool {
1492 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1496 ModMap.resolveHeaderDirectives(
File);
1516 if (FileInfo.isTextualModuleHeader)
1519 if (FileInfo.isCompilingModuleHeader) {
1522 if (FileInfo.isModuleHeader) {
1527 if (ModMap.isBuiltinHeader(
File))
1536 if (FileInfo.getControllingMacro(ExternalLookup))
1556 FileInfo.isImport =
true;
1563 if (FileInfo.isPragmaOnce ||
1564 (FileInfo.isImport && !MaybeReenterImportedFile()))
1573 FileInfo.getControllingMacro(ExternalLookup)) {
1580 ++NumMultiIncludeFileOptzn;
1590 return SearchDirs.capacity()
1591 + llvm::capacity_in_bytes(FileInfo)
1592 + llvm::capacity_in_bytes(HeaderMaps)
1593 + LookupFileCache.getAllocator().getTotalMemory()
1594 + FrameworkMap.getAllocator().getTotalMemory();
1598 return &DL - &*SearchDirs.begin();
1602 return FrameworkNames.insert(Framework).first->first();
1606 auto It = IncludeNames.find(
File);
1607 if (It == IncludeNames.end())
1613 ModuleMapDirectoryState &MMState) {
1614 if (!MMState.ModuleMapFile)
1621 if (MMState.PrivateModuleMapFile)
1624 processModuleMapForIndex(*ParsedMM, Dir,
"", MMState);
1625 if (ParsedPrivateMM)
1626 processModuleMapForIndex(*ParsedPrivateMM, Dir,
"", MMState);
1629void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
1630 StringRef PathPrefix,
1631 ModuleMapDirectoryState &MMState) {
1633 llvm::sys::path::append(RelFromRootPath, RelPath);
1634 llvm::sys::path::native(RelFromRootPath);
1635 MMState.HeaderToModules[RelFromRootPath].push_back(ModuleName);
1638void HeaderSearch::processExternModuleDeclForIndex(
1640 StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
1641 StringRef FileNameRef = EMD.
Path;
1642 SmallString<128> ModuleMapFileName;
1643 if (llvm::sys::path::is_relative(FileNameRef)) {
1644 ModuleMapFileName = MMDir.
getName();
1645 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
1646 FileNameRef = ModuleMapFileName;
1648 if (
auto EFile = FileMgr.getOptionalFileRef(FileNameRef)) {
1649 if (
auto *ExtMMF = ModMap.getParsedModuleMap(*EFile)) {
1652 SmallString<128> NewPrefix(PathPrefix);
1653 StringRef ExternDir = llvm::sys::path::parent_path(EMD.
Path);
1654 if (!ExternDir.empty()) {
1655 llvm::sys::path::append(NewPrefix, ExternDir);
1656 llvm::sys::path::native(NewPrefix);
1658 processModuleMapForIndex(*ExtMMF, EFile->getDir(), NewPrefix, MMState);
1664 StringRef ModuleName,
1666 StringRef PathPrefix,
1667 ModuleMapDirectoryState &MMState) {
1669 if (MD.
Id.front().first ==
"*")
1672 auto ProcessDecl = llvm::makeVisitor(
1673 [&](
const modulemap::HeaderDecl &HD) {
1675 MMState.UmbrellaHeaderModules.push_back(ModuleName);
1677 addToModuleMapIndex(HD.
Path, ModuleName, PathPrefix, MMState);
1680 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1681 SmallString<128> FullPath(PathPrefix);
1682 llvm::sys::path::append(FullPath, UDD.Path);
1683 llvm::sys::path::native(FullPath);
1684 MMState.UmbrellaDirModules.push_back(
1685 std::make_pair(std::string(FullPath), ModuleName));
1687 [&](
const modulemap::ModuleDecl &SubMD) {
1688 processModuleDeclForIndex(SubMD, ModuleName, MMDir, PathPrefix,
1691 [&](
const modulemap::ExternModuleDecl &EMD) {
1692 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
1698 for (
const auto &Decl : MD.
Decls) {
1699 std::visit(ProcessDecl, Decl);
1705 StringRef PathPrefix,
1706 ModuleMapDirectoryState &MMState) {
1707 for (
const auto &Decl : MMF.
Decls) {
1708 std::visit(llvm::makeVisitor(
1709 [&](
const modulemap::ModuleDecl &MD) {
1710 processModuleDeclForIndex(MD, MD.
Id.front().first, MMDir,
1711 PathPrefix, MMState);
1713 [&](
const modulemap::ExternModuleDecl &EMD) {
1714 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
1726 if (!
FileName.starts_with(DirPath))
1728 StringRef RelativePath =
FileName.substr(DirPath.size());
1729 while (!RelativePath.empty() &&
1730 llvm::sys::path::is_separator(RelativePath.front()))
1731 RelativePath = RelativePath.substr(1);
1732 return RelativePath;
1736 StringRef RelativePath,
const ModuleMapDirectoryState &MMState)
const {
1737 SmallVector<StringRef, 1> Modules;
1740 auto CachedMods = MMState.HeaderToModules.find(RelativePath);
1741 if (CachedMods != MMState.HeaderToModules.end())
1742 Modules.append(CachedMods->second.begin(), CachedMods->second.end());
1745 for (
const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
1746 if (RelativePath.starts_with(UmbrellaDir.first) || UmbrellaDir.first ==
".")
1747 Modules.push_back(UmbrellaDir.second);
1761 Modules.append(MMState.UmbrellaHeaderModules.begin(),
1762 MMState.UmbrellaHeaderModules.end());
1770 if (!HSOpts.ImplicitModuleMaps)
1777 DirName = llvm::sys::path::parent_path(DirName);
1778 if (DirName.empty())
1782 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1788 llvm::sys::path::extension(Dir->
getName()) ==
".framework";
1792 parseModuleMapFile(*Dir, IsSystem,
true,
1794 auto DirState = DirectoryModuleMap.find(*Dir);
1795 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1798 if (!HSOpts.LazyLoadModuleMaps &&
1799 Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1803 auto &MMState = DirState->second;
1806 if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
1807 MMState.UmbrellaHeaderModules.empty()) {
1808 buildModuleMapIndex(*Dir, MMState);
1812 if (!HSOpts.LazyLoadModuleMaps)
1820 llvm::sys::path::native(RelativePathNative);
1822 auto ModulesToLoad =
1823 findMatchingModulesInIndex(RelativePathNative, MMState);
1826 bool LoadedAny =
false;
1827 for (StringRef ModName : ModulesToLoad) {
1828 if (ModMap.findOrLoadModule(ModName)) {
1837 }
while (CurDir != Root);
1843 bool AllowExcluded)
const {
1844 if (ExternalSource) {
1849 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1854 if (ExternalSource) {
1859 return ModMap.findAllModulesForHeader(
File);
1864 if (ExternalSource) {
1869 return ModMap.findResolvedModulesForHeader(
File);
1886 if (SuggestedModule)
1896 if (SuggestedModule)
1910 if (!HSOpts.ImplicitModuleMaps ||
Module.getModule()->isPartOfFramework() ||
1911 !
Module.getModule()->isModuleMapModule())
1914 if (Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1915 Module.getModule()->DefinitionLoc))
1918 if (
File.isDeviceFile() ||
File.isNamedPipe())
1921 llvm::SmallString<128> AbsPath(
File.getName());
1922 FileMgr.makeAbsolutePath(AbsPath);
1923 llvm::sys::path::remove_dots(AbsPath,
true);
1927 llvm::SmallString<128> LinkTarget;
1928 if (llvm::sys::fs::readlink(AbsPath, LinkTarget))
1936 const DirectoryEntry *CurDir =
nullptr;
1940 DirName = llvm::sys::path::parent_path(DirName);
1941 if (DirName.empty())
1944 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1949 auto DirState = DirectoryModuleMap.find(*Dir);
1950 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1956 if (RelativePath.empty())
1958 SmallString<128> RelativePathNative(RelativePath);
1959 llvm::sys::path::native(RelativePathNative);
1961 auto MatchingModules =
1962 findMatchingModulesInIndex(RelativePathNative, DirState->second);
1963 if (!MatchingModules.empty())
1965 }
while (CurDir != Root);
1968 Diags.Report(diag::warn_mmap_deprecated_symlink_to_modular_header)
1969 <<
File.getName() << LinkTarget
1970 <<
Module.getModule()->getFullModuleName();
1971 Diags.Report(
Module.getModule()->DefinitionLoc,
1972 diag::note_mmap_module_defined_here);
1975bool HeaderSearch::findUsableModuleForHeader(
1979 if (!HSOpts.LazyLoadModuleMaps) {
1985 ModuleMap::KnownHeader
Module =
1987 diagnoseUncoveredSymlink(
File,
Module, Root);
1993 ModuleMap::KnownHeader
Module =
2001 Module = ModMap.findModuleForHeader(
File,
true);
2003 diagnoseUncoveredSymlink(
File,
Module, Root);
2010bool HeaderSearch::findUsableModuleForFrameworkHeader(
2016 SmallVector<std::string, 4> SubmodulePath;
2019 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
2022 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
2026 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework,
2033 ModuleMap::KnownHeader
Module =
2044 bool Diagnose =
true) {
2045 StringRef Filename = llvm::sys::path::filename(
File.getName());
2047 if (Filename ==
"module.map")
2048 llvm::sys::path::append(PrivateFilename,
"module_private.map");
2049 else if (Filename ==
"module.modulemap")
2050 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
2052 return std::nullopt;
2053 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
2055 if (Diagnose && Filename ==
"module.map")
2056 Diags.
Report(diag::warn_deprecated_module_dot_map)
2057 << PrivateFilename << 1
2058 <<
File.getDir().getName().ends_with(
".framework");
2064 bool ImplicitlyDiscovered,
2065 FileID ID,
unsigned *Offset,
2066 StringRef OriginalModuleMapFile) {
2071 Dir = FileMgr.getOptionalDirectoryRef(
".");
2073 if (!OriginalModuleMapFile.empty()) {
2076 Dir = FileMgr.getOptionalDirectoryRef(
2077 llvm::sys::path::parent_path(OriginalModuleMapFile));
2079 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
2080 Dir = FakeFile.getDir();
2083 Dir =
File.getDir();
2086 assert(Dir &&
"parent must exist");
2087 StringRef DirName(Dir->
getName());
2088 if (llvm::sys::path::filename(DirName) ==
"Modules") {
2089 DirName = llvm::sys::path::parent_path(DirName);
2090 if (DirName.ends_with(
".framework"))
2091 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
2095 assert(Dir &&
"parent must exist");
2099 assert(Dir &&
"module map home directory must exist");
2100 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, ImplicitlyDiscovered,
2103 case MMR_AlreadyProcessed:
2104 case MMR_NewlyProcessed:
2106 case MMR_NoDirectory:
2107 case MMR_InvalidModuleMap:
2110 llvm_unreachable(
"Unknown load module map result");
2113HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
2118 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
2119 if (!AddResult.second)
2120 return AddResult.first->second ? MMR_AlreadyProcessed
2121 : MMR_InvalidModuleMap;
2125 LoadedModuleMaps[
File] =
false;
2126 return MMR_InvalidModuleMap;
2133 ImplicitlyDiscovered, Dir)) {
2134 LoadedModuleMaps[
File] =
false;
2135 return MMR_InvalidModuleMap;
2140 return MMR_NewlyProcessed;
2143HeaderSearch::ModuleMapResult
2145 bool ImplicitlyDiscovered,
2149 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
2150 if (!AddResult.second)
2151 return AddResult.first->second ? MMR_AlreadyProcessed
2152 : MMR_InvalidModuleMap;
2154 if (ModMap.parseModuleMapFile(
File, IsSystem, ImplicitlyDiscovered, Dir,
2156 ParsedModuleMaps[
File] =
false;
2157 return MMR_InvalidModuleMap;
2163 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, ImplicitlyDiscovered,
2165 ParsedModuleMaps[
File] =
false;
2166 return MMR_InvalidModuleMap;
2171 return MMR_NewlyProcessed;
2176 if (!HSOpts.ImplicitModuleMaps)
2177 return std::nullopt;
2182 llvm::sys::path::append(ModuleMapFileName,
"Modules");
2183 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
2184 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2188 ModuleMapFileName = Dir.
getName();
2189 llvm::sys::path::append(ModuleMapFileName,
"module.map");
2190 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
2191 Diags.Report(diag::warn_deprecated_module_dot_map)
2192 << ModuleMapFileName << 0 << IsFramework;
2199 ModuleMapFileName = Dir.
getName();
2200 llvm::sys::path::append(ModuleMapFileName,
"Modules",
2201 "module.private.modulemap");
2202 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2205 return std::nullopt;
2210 bool ImplicitlyDiscovered) {
2214 case MMR_InvalidModuleMap:
2217 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
2220 case MMR_NoDirectory:
2223 case MMR_AlreadyProcessed:
2224 case MMR_NewlyProcessed:
2231HeaderSearch::ModuleMapResult
2233 bool ImplicitlyDiscovered,
2235 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2239 return MMR_NoDirectory;
2242HeaderSearch::ModuleMapResult
2244 bool ImplicitlyDiscovered,
2246 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2247 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2248 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2249 if (!InsertRes.second) {
2250 switch (MMState.Status) {
2251 case ModuleMapDirectoryState::Parsed:
2253 case ModuleMapDirectoryState::Loaded:
2254 return MMR_AlreadyProcessed;
2255 case ModuleMapDirectoryState::Invalid:
2256 return MMR_InvalidModuleMap;
2260 if (!MMState.ModuleMapFile) {
2262 if (MMState.ModuleMapFile)
2263 MMState.PrivateModuleMapFile =
2267 if (MMState.ModuleMapFile) {
2268 ModuleMapResult
Result = parseAndLoadModuleMapFileImpl(
2269 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2273 if (
Result == MMR_NewlyProcessed)
2274 MMState.Status = ModuleMapDirectoryState::Loaded;
2275 else if (
Result == MMR_InvalidModuleMap)
2276 MMState.Status = ModuleMapDirectoryState::Invalid;
2279 return MMR_InvalidModuleMap;
2282HeaderSearch::ModuleMapResult
2283HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
2284 bool ImplicitlyDiscovered,
bool IsFramework) {
2285 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2286 return parseModuleMapFile(*Dir, IsSystem, ImplicitlyDiscovered,
2289 return MMR_NoDirectory;
2292HeaderSearch::ModuleMapResult
2294 bool ImplicitlyDiscovered,
bool IsFramework) {
2295 if (!HSOpts.LazyLoadModuleMaps)
2299 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2300 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2301 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2302 if (!InsertRes.second) {
2303 switch (MMState.Status) {
2304 case ModuleMapDirectoryState::Parsed:
2305 case ModuleMapDirectoryState::Loaded:
2306 return MMR_AlreadyProcessed;
2307 case ModuleMapDirectoryState::Invalid:
2308 return MMR_InvalidModuleMap;
2312 if (!MMState.ModuleMapFile) {
2314 if (MMState.ModuleMapFile)
2315 MMState.PrivateModuleMapFile =
2319 if (MMState.ModuleMapFile) {
2320 ModuleMapResult
Result = parseModuleMapFileImpl(
2321 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2325 if (
Result == MMR_NewlyProcessed)
2326 MMState.Status = ModuleMapDirectoryState::Parsed;
2327 else if (
Result == MMR_InvalidModuleMap)
2328 MMState.Status = ModuleMapDirectoryState::Invalid;
2331 return MMR_InvalidModuleMap;
2337 if (HSOpts.ImplicitModuleMaps) {
2340 bool IsSystem = DL.isSystemHeaderDirectory();
2341 if (DL.isFramework()) {
2344 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2347 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2348 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2350 Dir != DirEnd && !EC; Dir.increment(EC)) {
2351 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
2354 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2359 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2366 if (DL.isHeaderMap())
2376 loadSubdirectoryModuleMaps(DL);
2381 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2385 if (!HSOpts.ImplicitModuleMaps)
2391 if (!DL.isNormalDir())
2396 true, DL.isFramework());
2400void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2402 "Should not be loading subdirectory module maps");
2409 FileMgr.makeAbsolutePath(Dir);
2411 llvm::sys::path::native(Dir, DirNative);
2412 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2413 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2414 Dir != DirEnd && !EC; Dir.increment(EC)) {
2415 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2417 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2430 MainFile, IsAngled);
2434 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2435 bool *IsAngled)
const {
2436 using namespace llvm::sys;
2439 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2440 path::make_absolute(WorkingDir, FilePath);
2444 path::remove_dots(FilePath,
true);
2445 path::native(FilePath, path::Style::posix);
2448 unsigned BestPrefixLength = 0;
2453 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2454 path::make_absolute(WorkingDir, Dir);
2455 path::remove_dots(Dir,
true);
2456 for (
auto NI = path::begin(
File), NE = path::end(
File),
2457 DI = path::begin(Dir), DE = path::end(Dir);
2458 NI != NE; ++NI, ++DI) {
2461 unsigned PrefixLength = NI - path::begin(
File);
2462 if (PrefixLength > BestPrefixLength) {
2463 BestPrefixLength = PrefixLength;
2470 if (NI->size() == 1 && DI->size() == 1 &&
2471 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2477 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2478 StringRef NBasename = path::stem(*NI);
2479 StringRef DBasename = path::stem(*DI);
2480 if (DBasename.starts_with(NBasename))
2490 bool BestPrefixIsFramework =
false;
2492 if (DL.isNormalDir()) {
2493 StringRef Dir = DL.getDirRef()->getName();
2494 if (CheckDir(Dir)) {
2496 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2497 BestPrefixIsFramework =
false;
2499 }
else if (DL.isFramework()) {
2500 StringRef Dir = DL.getFrameworkDirRef()->getName();
2501 if (CheckDir(Dir)) {
2504 *IsAngled = BestPrefixLength;
2505 BestPrefixIsFramework =
true;
2512 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2515 BestPrefixIsFramework =
false;
2520 StringRef Filename =
File.drop_front(BestPrefixLength);
2522 if (!DL.isHeaderMap())
2525 StringRef SpelledFilename =
2526 DL.getHeaderMap()->reverseLookupFilename(Filename);
2527 if (!SpelledFilename.empty()) {
2528 Filename = SpelledFilename;
2529 BestPrefixIsFramework =
false;
2536 bool IsPrivateHeader;
2538 if (BestPrefixIsFramework &&
2541 Filename = IncludeSpelling;
2543 return path::convert_to_slash(Filename);
2548 NormalizedPath.assign(Path.begin(), Path.end());
2549 if (!NormalizedPath.empty()) {
2550 FileMgr.makeAbsolutePath(NormalizedPath);
2551 llvm::sys::path::remove_dots(NormalizedPath);
2557 std::string ContextHash,
size_t &NormalizedModuleCachePathLen) {
2560 NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
2561 if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
2562 llvm::sys::path::append(SpecificModuleCachePath, ContextHash);
2563 return std::string(SpecificModuleCachePath);
2567 ContextHash = std::move(NewContextHash);
2569 FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash,
2570 NormalizedModuleCachePathLen);
2574 StringRef ModuleCachePath,
2575 bool DisableModuleHash,
2576 std::string ContextHash) {
2577 size_t NormalizedModuleCachePathLen;
2579 FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash),
2580 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.
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.
The JSON file list parser is used to communicate input to InstallAPI.
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