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 (
unsigned i = 0, e = FileInfo.size(); i != e; ++i)
95 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].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");
1379 if (FE.
getUID() >= FileInfo.size())
1380 FileInfo.resize(FE.
getUID() + 1);
1384 if (ExternalSource && !HFI->
Resolved) {
1385 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1386 if (ExternalHFI.IsValid) {
1388 if (ExternalHFI.External)
1402 if (ExternalSource) {
1403 if (FE.
getUID() >= FileInfo.size())
1404 FileInfo.resize(FE.
getUID() + 1);
1406 HFI = &FileInfo[FE.
getUID()];
1409 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1410 if (ExternalHFI.IsValid) {
1412 if (ExternalHFI.External)
1416 }
else if (FE.
getUID() < FileInfo.size()) {
1417 HFI = &FileInfo[FE.
getUID()];
1422 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1428 if (FE.
getUID() < FileInfo.size()) {
1429 HFI = &FileInfo[FE.
getUID()];
1442 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1448 bool isCompilingModuleHeader) {
1450 if (!isCompilingModuleHeader) {
1459 HFI.mergeModuleMembership(
Role);
1460 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1465 bool ModulesEnabled,
Module *M,
1466 bool &IsFirstIncludeOfFile) {
1482 IsFirstIncludeOfFile =
false;
1485 auto MaybeReenterImportedFile = [&]() ->
bool {
1503 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1507 ModMap.resolveHeaderDirectives(
File);
1527 if (FileInfo.isTextualModuleHeader)
1530 if (FileInfo.isCompilingModuleHeader) {
1533 if (FileInfo.isModuleHeader) {
1538 if (ModMap.isBuiltinHeader(
File))
1547 if (FileInfo.getControllingMacro(ExternalLookup))
1567 FileInfo.isImport =
true;
1574 if (FileInfo.isPragmaOnce ||
1575 (FileInfo.isImport && !MaybeReenterImportedFile()))
1584 FileInfo.getControllingMacro(ExternalLookup)) {
1591 ++NumMultiIncludeFileOptzn;
1601 return SearchDirs.capacity()
1602 + llvm::capacity_in_bytes(FileInfo)
1603 + llvm::capacity_in_bytes(HeaderMaps)
1604 + LookupFileCache.getAllocator().getTotalMemory()
1605 + FrameworkMap.getAllocator().getTotalMemory();
1609 return &DL - &*SearchDirs.begin();
1613 return FrameworkNames.insert(Framework).first->first();
1617 auto It = IncludeNames.find(
File);
1618 if (It == IncludeNames.end())
1624 ModuleMapDirectoryState &MMState) {
1625 if (!MMState.ModuleMapFile)
1632 if (MMState.PrivateModuleMapFile)
1635 processModuleMapForIndex(*ParsedMM, Dir,
"", MMState);
1636 if (ParsedPrivateMM)
1637 processModuleMapForIndex(*ParsedPrivateMM, Dir,
"", MMState);
1640void HeaderSearch::addToModuleMapIndex(StringRef RelPath, StringRef ModuleName,
1641 StringRef PathPrefix,
1642 ModuleMapDirectoryState &MMState) {
1644 llvm::sys::path::append(RelFromRootPath, RelPath);
1645 llvm::sys::path::native(RelFromRootPath);
1646 MMState.HeaderToModules[RelFromRootPath].push_back(ModuleName);
1649void HeaderSearch::processExternModuleDeclForIndex(
1651 StringRef PathPrefix, ModuleMapDirectoryState &MMState) {
1652 StringRef FileNameRef = EMD.
Path;
1653 SmallString<128> ModuleMapFileName;
1654 if (llvm::sys::path::is_relative(FileNameRef)) {
1655 ModuleMapFileName = MMDir.
getName();
1656 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
1657 FileNameRef = ModuleMapFileName;
1659 if (
auto EFile = FileMgr.getOptionalFileRef(FileNameRef)) {
1660 if (
auto *ExtMMF = ModMap.getParsedModuleMap(*EFile)) {
1663 SmallString<128> NewPrefix(PathPrefix);
1664 StringRef ExternDir = llvm::sys::path::parent_path(EMD.
Path);
1665 if (!ExternDir.empty()) {
1666 llvm::sys::path::append(NewPrefix, ExternDir);
1667 llvm::sys::path::native(NewPrefix);
1669 processModuleMapForIndex(*ExtMMF, EFile->getDir(), NewPrefix, MMState);
1675 StringRef ModuleName,
1677 StringRef PathPrefix,
1678 ModuleMapDirectoryState &MMState) {
1680 if (MD.
Id.front().first ==
"*")
1683 auto ProcessDecl = llvm::makeVisitor(
1684 [&](
const modulemap::HeaderDecl &HD) {
1686 MMState.UmbrellaHeaderModules.push_back(ModuleName);
1688 addToModuleMapIndex(HD.
Path, ModuleName, PathPrefix, MMState);
1691 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1692 SmallString<128> FullPath(PathPrefix);
1693 llvm::sys::path::append(FullPath, UDD.Path);
1694 llvm::sys::path::native(FullPath);
1695 MMState.UmbrellaDirModules.push_back(
1696 std::make_pair(std::string(FullPath), ModuleName));
1698 [&](
const modulemap::ModuleDecl &SubMD) {
1699 processModuleDeclForIndex(SubMD, ModuleName, MMDir, PathPrefix,
1702 [&](
const modulemap::ExternModuleDecl &EMD) {
1703 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix, MMState);
1709 for (
const auto &Decl : MD.
Decls) {
1710 std::visit(ProcessDecl, Decl);
1716 StringRef PathPrefix,
1717 ModuleMapDirectoryState &MMState) {
1718 for (
const auto &Decl : MMF.
Decls) {
1719 std::visit(llvm::makeVisitor(
1720 [&](
const modulemap::ModuleDecl &MD) {
1721 processModuleDeclForIndex(MD, MD.
Id.front().first, MMDir,
1722 PathPrefix, MMState);
1724 [&](
const modulemap::ExternModuleDecl &EMD) {
1725 processExternModuleDeclForIndex(EMD, MMDir, PathPrefix,
1737 if (!
FileName.starts_with(DirPath))
1739 StringRef RelativePath =
FileName.substr(DirPath.size());
1740 while (!RelativePath.empty() &&
1741 llvm::sys::path::is_separator(RelativePath.front()))
1742 RelativePath = RelativePath.substr(1);
1743 return RelativePath;
1747 StringRef RelativePath,
const ModuleMapDirectoryState &MMState)
const {
1748 SmallVector<StringRef, 1> Modules;
1751 auto CachedMods = MMState.HeaderToModules.find(RelativePath);
1752 if (CachedMods != MMState.HeaderToModules.end())
1753 Modules.append(CachedMods->second.begin(), CachedMods->second.end());
1756 for (
const auto &UmbrellaDir : MMState.UmbrellaDirModules) {
1757 if (RelativePath.starts_with(UmbrellaDir.first) || UmbrellaDir.first ==
".")
1758 Modules.push_back(UmbrellaDir.second);
1772 Modules.append(MMState.UmbrellaHeaderModules.begin(),
1773 MMState.UmbrellaHeaderModules.end());
1781 if (!HSOpts.ImplicitModuleMaps)
1788 DirName = llvm::sys::path::parent_path(DirName);
1789 if (DirName.empty())
1793 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1799 llvm::sys::path::extension(Dir->
getName()) ==
".framework";
1803 parseModuleMapFile(*Dir, IsSystem,
true,
1805 auto DirState = DirectoryModuleMap.find(*Dir);
1806 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1809 if (!HSOpts.LazyLoadModuleMaps &&
1810 Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1814 auto &MMState = DirState->second;
1817 if (MMState.HeaderToModules.empty() && MMState.UmbrellaDirModules.empty() &&
1818 MMState.UmbrellaHeaderModules.empty()) {
1819 buildModuleMapIndex(*Dir, MMState);
1823 if (!HSOpts.LazyLoadModuleMaps)
1831 llvm::sys::path::native(RelativePathNative);
1833 auto ModulesToLoad =
1834 findMatchingModulesInIndex(RelativePathNative, MMState);
1837 bool LoadedAny =
false;
1838 for (StringRef ModName : ModulesToLoad) {
1839 if (ModMap.findOrLoadModule(ModName)) {
1848 }
while (CurDir != Root);
1854 bool AllowExcluded)
const {
1855 if (ExternalSource) {
1860 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1865 if (ExternalSource) {
1870 return ModMap.findAllModulesForHeader(
File);
1875 if (ExternalSource) {
1880 return ModMap.findResolvedModulesForHeader(
File);
1897 if (SuggestedModule)
1907 if (SuggestedModule)
1921 if (!HSOpts.ImplicitModuleMaps ||
Module.getModule()->isPartOfFramework() ||
1922 !
Module.getModule()->isModuleMapModule())
1925 if (Diags.isIgnored(diag::warn_mmap_deprecated_symlink_to_modular_header,
1926 Module.getModule()->DefinitionLoc))
1929 if (
File.isDeviceFile() ||
File.isNamedPipe())
1932 llvm::SmallString<128> AbsPath(
File.getName());
1933 FileMgr.makeAbsolutePath(AbsPath);
1934 llvm::sys::path::remove_dots(AbsPath,
true);
1938 llvm::SmallString<128> LinkTarget;
1939 if (llvm::sys::fs::readlink(AbsPath, LinkTarget))
1947 const DirectoryEntry *CurDir =
nullptr;
1951 DirName = llvm::sys::path::parent_path(DirName);
1952 if (DirName.empty())
1955 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1960 auto DirState = DirectoryModuleMap.find(*Dir);
1961 if (DirState == DirectoryModuleMap.end() || !DirState->second.ModuleMapFile)
1967 if (RelativePath.empty())
1969 SmallString<128> RelativePathNative(RelativePath);
1970 llvm::sys::path::native(RelativePathNative);
1972 auto MatchingModules =
1973 findMatchingModulesInIndex(RelativePathNative, DirState->second);
1974 if (!MatchingModules.empty())
1976 }
while (CurDir != Root);
1979 Diags.Report(diag::warn_mmap_deprecated_symlink_to_modular_header)
1980 <<
File.getName() << LinkTarget
1981 <<
Module.getModule()->getFullModuleName();
1982 Diags.Report(
Module.getModule()->DefinitionLoc,
1983 diag::note_mmap_module_defined_here);
1986bool HeaderSearch::findUsableModuleForHeader(
1990 if (!HSOpts.LazyLoadModuleMaps) {
1996 ModuleMap::KnownHeader
Module =
1998 diagnoseUncoveredSymlink(
File,
Module, Root);
2004 ModuleMap::KnownHeader
Module =
2012 Module = ModMap.findModuleForHeader(
File,
true);
2014 diagnoseUncoveredSymlink(
File,
Module, Root);
2021bool HeaderSearch::findUsableModuleForFrameworkHeader(
2027 SmallVector<std::string, 4> SubmodulePath;
2030 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
2033 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
2037 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework,
2044 ModuleMap::KnownHeader
Module =
2055 bool Diagnose =
true) {
2056 StringRef Filename = llvm::sys::path::filename(
File.getName());
2058 if (Filename ==
"module.map")
2059 llvm::sys::path::append(PrivateFilename,
"module_private.map");
2060 else if (Filename ==
"module.modulemap")
2061 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
2063 return std::nullopt;
2064 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
2066 if (Diagnose && Filename ==
"module.map")
2067 Diags.
Report(diag::warn_deprecated_module_dot_map)
2068 << PrivateFilename << 1
2069 <<
File.getDir().getName().ends_with(
".framework");
2075 bool ImplicitlyDiscovered,
2076 FileID ID,
unsigned *Offset,
2077 StringRef OriginalModuleMapFile) {
2082 Dir = FileMgr.getOptionalDirectoryRef(
".");
2084 if (!OriginalModuleMapFile.empty()) {
2087 Dir = FileMgr.getOptionalDirectoryRef(
2088 llvm::sys::path::parent_path(OriginalModuleMapFile));
2090 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
2091 Dir = FakeFile.getDir();
2094 Dir =
File.getDir();
2097 assert(Dir &&
"parent must exist");
2098 StringRef DirName(Dir->
getName());
2099 if (llvm::sys::path::filename(DirName) ==
"Modules") {
2100 DirName = llvm::sys::path::parent_path(DirName);
2101 if (DirName.ends_with(
".framework"))
2102 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
2106 assert(Dir &&
"parent must exist");
2110 assert(Dir &&
"module map home directory must exist");
2111 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, ImplicitlyDiscovered,
2114 case MMR_AlreadyProcessed:
2115 case MMR_NewlyProcessed:
2117 case MMR_NoDirectory:
2118 case MMR_InvalidModuleMap:
2121 llvm_unreachable(
"Unknown load module map result");
2124HeaderSearch::ModuleMapResult HeaderSearch::parseAndLoadModuleMapFileImpl(
2129 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
2130 if (!AddResult.second)
2131 return AddResult.first->second ? MMR_AlreadyProcessed
2132 : MMR_InvalidModuleMap;
2136 LoadedModuleMaps[
File] =
false;
2137 return MMR_InvalidModuleMap;
2144 ImplicitlyDiscovered, Dir)) {
2145 LoadedModuleMaps[
File] =
false;
2146 return MMR_InvalidModuleMap;
2151 return MMR_NewlyProcessed;
2154HeaderSearch::ModuleMapResult
2156 bool ImplicitlyDiscovered,
2160 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
2161 if (!AddResult.second)
2162 return AddResult.first->second ? MMR_AlreadyProcessed
2163 : MMR_InvalidModuleMap;
2165 if (ModMap.parseModuleMapFile(
File, IsSystem, ImplicitlyDiscovered, Dir,
2167 ParsedModuleMaps[
File] =
false;
2168 return MMR_InvalidModuleMap;
2174 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, ImplicitlyDiscovered,
2176 ParsedModuleMaps[
File] =
false;
2177 return MMR_InvalidModuleMap;
2182 return MMR_NewlyProcessed;
2187 if (!HSOpts.ImplicitModuleMaps)
2188 return std::nullopt;
2193 llvm::sys::path::append(ModuleMapFileName,
"Modules");
2194 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
2195 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2199 ModuleMapFileName = Dir.
getName();
2200 llvm::sys::path::append(ModuleMapFileName,
"module.map");
2201 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
2202 Diags.Report(diag::warn_deprecated_module_dot_map)
2203 << ModuleMapFileName << 0 << IsFramework;
2210 ModuleMapFileName = Dir.
getName();
2211 llvm::sys::path::append(ModuleMapFileName,
"Modules",
2212 "module.private.modulemap");
2213 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
2216 return std::nullopt;
2221 bool ImplicitlyDiscovered) {
2225 case MMR_InvalidModuleMap:
2228 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
2231 case MMR_NoDirectory:
2234 case MMR_AlreadyProcessed:
2235 case MMR_NewlyProcessed:
2242HeaderSearch::ModuleMapResult
2244 bool ImplicitlyDiscovered,
2246 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2250 return MMR_NoDirectory;
2253HeaderSearch::ModuleMapResult
2255 bool ImplicitlyDiscovered,
2257 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2258 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2259 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2260 if (!InsertRes.second) {
2261 switch (MMState.Status) {
2262 case ModuleMapDirectoryState::Parsed:
2264 case ModuleMapDirectoryState::Loaded:
2265 return MMR_AlreadyProcessed;
2266 case ModuleMapDirectoryState::Invalid:
2267 return MMR_InvalidModuleMap;
2271 if (!MMState.ModuleMapFile) {
2273 if (MMState.ModuleMapFile)
2274 MMState.PrivateModuleMapFile =
2278 if (MMState.ModuleMapFile) {
2279 ModuleMapResult
Result = parseAndLoadModuleMapFileImpl(
2280 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2284 if (
Result == MMR_NewlyProcessed)
2285 MMState.Status = ModuleMapDirectoryState::Loaded;
2286 else if (
Result == MMR_InvalidModuleMap)
2287 MMState.Status = ModuleMapDirectoryState::Invalid;
2290 return MMR_InvalidModuleMap;
2293HeaderSearch::ModuleMapResult
2294HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
2295 bool ImplicitlyDiscovered,
bool IsFramework) {
2296 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2297 return parseModuleMapFile(*Dir, IsSystem, ImplicitlyDiscovered,
2300 return MMR_NoDirectory;
2303HeaderSearch::ModuleMapResult
2305 bool ImplicitlyDiscovered,
bool IsFramework) {
2306 if (!HSOpts.LazyLoadModuleMaps)
2310 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2311 Dir, ModuleMapDirectoryState{{}, {}, ModuleMapDirectoryState::Invalid}});
2312 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2313 if (!InsertRes.second) {
2314 switch (MMState.Status) {
2315 case ModuleMapDirectoryState::Parsed:
2316 case ModuleMapDirectoryState::Loaded:
2317 return MMR_AlreadyProcessed;
2318 case ModuleMapDirectoryState::Invalid:
2319 return MMR_InvalidModuleMap;
2323 if (!MMState.ModuleMapFile) {
2325 if (MMState.ModuleMapFile)
2326 MMState.PrivateModuleMapFile =
2330 if (MMState.ModuleMapFile) {
2331 ModuleMapResult
Result = parseModuleMapFileImpl(
2332 *MMState.ModuleMapFile, IsSystem, ImplicitlyDiscovered, Dir);
2336 if (
Result == MMR_NewlyProcessed)
2337 MMState.Status = ModuleMapDirectoryState::Parsed;
2338 else if (
Result == MMR_InvalidModuleMap)
2339 MMState.Status = ModuleMapDirectoryState::Invalid;
2342 return MMR_InvalidModuleMap;
2348 if (HSOpts.ImplicitModuleMaps) {
2351 bool IsSystem = DL.isSystemHeaderDirectory();
2352 if (DL.isFramework()) {
2355 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2358 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2359 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2361 Dir != DirEnd && !EC; Dir.increment(EC)) {
2362 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
2365 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2370 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2377 if (DL.isHeaderMap())
2387 loadSubdirectoryModuleMaps(DL);
2392 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2396 if (!HSOpts.ImplicitModuleMaps)
2402 if (!DL.isNormalDir())
2407 true, DL.isFramework());
2411void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2413 "Should not be loading subdirectory module maps");
2420 FileMgr.makeAbsolutePath(Dir);
2422 llvm::sys::path::native(Dir, DirNative);
2423 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2424 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2425 Dir != DirEnd && !EC; Dir.increment(EC)) {
2426 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2428 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2441 MainFile, IsAngled);
2445 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2446 bool *IsAngled)
const {
2447 using namespace llvm::sys;
2450 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2451 path::make_absolute(WorkingDir, FilePath);
2455 path::remove_dots(FilePath,
true);
2456 path::native(FilePath, path::Style::posix);
2459 unsigned BestPrefixLength = 0;
2464 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2465 path::make_absolute(WorkingDir, Dir);
2466 path::remove_dots(Dir,
true);
2467 for (
auto NI = path::begin(
File), NE = path::end(
File),
2468 DI = path::begin(Dir), DE = path::end(Dir);
2469 NI != NE; ++NI, ++DI) {
2472 unsigned PrefixLength = NI - path::begin(
File);
2473 if (PrefixLength > BestPrefixLength) {
2474 BestPrefixLength = PrefixLength;
2481 if (NI->size() == 1 && DI->size() == 1 &&
2482 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2488 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2489 StringRef NBasename = path::stem(*NI);
2490 StringRef DBasename = path::stem(*DI);
2491 if (DBasename.starts_with(NBasename))
2501 bool BestPrefixIsFramework =
false;
2503 if (DL.isNormalDir()) {
2504 StringRef Dir = DL.getDirRef()->getName();
2505 if (CheckDir(Dir)) {
2507 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2508 BestPrefixIsFramework =
false;
2510 }
else if (DL.isFramework()) {
2511 StringRef Dir = DL.getFrameworkDirRef()->getName();
2512 if (CheckDir(Dir)) {
2515 *IsAngled = BestPrefixLength;
2516 BestPrefixIsFramework =
true;
2523 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2526 BestPrefixIsFramework =
false;
2531 StringRef Filename =
File.drop_front(BestPrefixLength);
2533 if (!DL.isHeaderMap())
2536 StringRef SpelledFilename =
2537 DL.getHeaderMap()->reverseLookupFilename(Filename);
2538 if (!SpelledFilename.empty()) {
2539 Filename = SpelledFilename;
2540 BestPrefixIsFramework =
false;
2547 bool IsPrivateHeader;
2549 if (BestPrefixIsFramework &&
2552 Filename = IncludeSpelling;
2554 return path::convert_to_slash(Filename);
2559 NormalizedPath.assign(Path.begin(), Path.end());
2560 if (!NormalizedPath.empty()) {
2561 FileMgr.makeAbsolutePath(NormalizedPath);
2562 llvm::sys::path::remove_dots(NormalizedPath);
2568 std::string ContextHash,
size_t &NormalizedModuleCachePathLen) {
2571 NormalizedModuleCachePathLen = SpecificModuleCachePath.size();
2572 if (!SpecificModuleCachePath.empty() && !DisableModuleHash)
2573 llvm::sys::path::append(SpecificModuleCachePath, ContextHash);
2574 return std::string(SpecificModuleCachePath);
2578 ContextHash = std::move(NewContextHash);
2580 FileMgr, HSOpts.ModuleCachePath, HSOpts.DisableModuleHash, ContextHash,
2581 NormalizedModuleCachePathLen);
2585 StringRef ModuleCachePath,
2586 bool DisableModuleHash,
2587 std::string ContextHash) {
2588 size_t NormalizedModuleCachePathLen;
2590 FileMgr, ModuleCachePath, DisableModuleHash, std::move(ContextHash),
2591 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.
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.
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).
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