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 llvm::sys::fs::make_absolute(
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");
235 return std::string(
Result);
245 StringRef ModuleMapPath =
ModuleMap->getName();
246 StringRef ModuleCacheHash = HSOpts.DisableModuleHash ?
"" :
getModuleHash();
247 for (
const std::string &Dir : HSOpts.PrebuiltModulePaths) {
249 llvm::sys::fs::make_absolute(CachePath);
250 llvm::sys::path::append(CachePath, ModuleCacheHash);
252 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
260 StringRef ModuleMapPath) {
261 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
265std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
266 StringRef ModuleMapPath,
267 StringRef CachePath) {
270 if (CachePath.empty())
276 llvm::sys::path::append(Result, ModuleName +
".pcm");
285 SmallString<128> CanonicalPath(ModuleMapPath);
286 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
289 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
291 SmallString<128> HashStr;
292 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
293 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
295 return Result.str().str();
300 bool AllowExtraModuleMapSearch) {
303 if (
Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
306 StringRef SearchName = ModuleName;
308 AllowExtraModuleMapSearch);
318 if (!
Module && SearchName.consume_back(
"_Private"))
320 AllowExtraModuleMapSearch);
321 if (!
Module && SearchName.consume_back(
"Private"))
323 AllowExtraModuleMapSearch);
329 bool AllowExtraModuleMapSearch) {
335 if (Dir.isFramework()) {
340 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
341 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
342 if (
auto FrameworkDir =
343 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
345 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
354 if (!Dir.isNormalDir())
357 bool IsSystem = Dir.isSystemHeaderDirectory();
360 DirectoryEntryRef NormalDir = *Dir.getDirRef();
362 if (parseModuleMapFile(NormalDir, IsSystem,
363 false) == MMR_NewlyProcessed) {
366 Module = ModMap.findOrLoadModule(ModuleName);
373 SmallString<128> NestedModuleMapDirName;
374 NestedModuleMapDirName = Dir.getDirRef()->getName();
375 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
376 if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,
377 false) == MMR_NewlyProcessed) {
379 Module = ModMap.findOrLoadModule(ModuleName);
384 if (HSOpts.AllowModuleMapSubdirectorySearch) {
387 if (Dir.haveSearchedAllModuleMaps())
392 if (AllowExtraModuleMapSearch)
393 loadSubdirectoryModuleMaps(Dir);
396 Module = ModMap.findOrLoadModule(ModuleName);
405void HeaderSearch::indexInitialHeaderMaps() {
406 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
409 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
410 auto &Dir = SearchDirs[i];
415 if (!Dir.isHeaderMap()) {
416 SearchDirHeaderMapIndex = std::move(Index);
417 FirstNonHeaderMapSearchDirIdx = i;
422 auto Callback = [&](StringRef Filename) {
423 Index.try_emplace(Filename.lower(), i);
425 Dir.getHeaderMap()->forEachKey(Callback);
440 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
446 bool IsSystemHeaderDir,
Module *RequestingModule,
448 bool CacheFailures ) {
455 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
456 if (EC != llvm::errc::no_such_file_or_directory &&
457 EC != llvm::errc::invalid_argument &&
458 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
459 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
466 if (!findUsableModuleForHeader(
467 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
468 SuggestedModule, IsSystemHeaderDir))
480 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
482 bool OpenFile)
const {
483 InUserSpecifiedSystemFramework =
false;
484 IsInHeaderMap =
false;
491 llvm::sys::path::append(TmpDir, Filename);
495 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
498 RelativePath->clear();
499 RelativePath->append(Filename.begin(), Filename.end());
502 return HS.getFileAndSuggestModule(
504 RequestingModule, SuggestedModule, OpenFile);
508 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
509 RequestingModule, SuggestedModule,
510 InUserSpecifiedSystemFramework, IsFrameworkFound);
512 assert(
isHeaderMap() &&
"Unknown directory lookup");
519 IsInHeaderMap =
true;
521 auto FixupSearchPathAndFindUsableModule =
524 StringRef SearchPathRef(
getName());
526 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
529 RelativePath->clear();
530 RelativePath->append(Filename.begin(), Filename.end());
532 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
533 RequestingModule, SuggestedModule,
543 if (llvm::sys::path::is_relative(Dest)) {
544 MappedName.append(Dest.begin(), Dest.end());
545 Filename = StringRef(MappedName.begin(), MappedName.size());
550 return FixupSearchPathAndFindUsableModule(*Res);
570 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
571 "Not a framework directory");
587 auto TopFrameworkDir =
FileMgr.getOptionalDirectoryRef(DirName);
590 DirName =
FileMgr.getCanonicalName(*TopFrameworkDir);
593 DirName = llvm::sys::path::parent_path(DirName);
598 auto Dir =
FileMgr.getOptionalDirectoryRef(DirName);
604 if (llvm::sys::path::extension(DirName) ==
".framework") {
605 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
606 TopFrameworkDir = *Dir;
610 return TopFrameworkDir;
614 bool HasSuggestedModule) {
615 return HasSuggestedModule ||
625 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
629 size_t SlashPos = Filename.find(
'/');
630 if (SlashPos == StringRef::npos)
635 FrameworkCacheEntry &CacheEntry =
645 SmallString<1024> FrameworkName;
647 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
648 FrameworkName.push_back(
'/');
651 StringRef ModuleName(Filename.begin(), SlashPos);
652 FrameworkName += ModuleName;
655 FrameworkName +=
".framework/";
659 ++NumFrameworkLookups;
673 SmallString<1024> SystemFrameworkMarker(FrameworkName);
674 SystemFrameworkMarker +=
".system_framework";
685 RelativePath->clear();
686 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
690 unsigned OrigSize = FrameworkName.size();
692 FrameworkName +=
"Headers/";
697 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
700 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
706 const char *
Private =
"Private";
707 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
710 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
720 StringRef FrameworkPath =
File->getDir().getName();
721 bool FoundFramework =
false;
730 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
731 FoundFramework =
true;
736 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
737 if (FrameworkPath.empty())
742 if (FoundFramework) {
743 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
745 SuggestedModule, IsSystem))
748 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
749 SuggestedModule, IsSystem))
758void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
761 CacheLookup.HitIt = HitIt;
762 noteLookupUsage(HitIt.Idx, Loc);
765void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
766 SearchDirsUsage[HitIdx] =
true;
768 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
769 if (UserEntryIdxIt != SearchDirToHSEntry.end())
770 Diags.Report(Loc, diag::remark_pp_search_path_usage)
771 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
789 if (MSFE && FE != *MSFE) {
790 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
796static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
797 assert(!Str.empty());
798 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
799 std::copy(Str.begin(), Str.end(), CopyStr);
800 CopyStr[Str.size()] =
'\0';
807 using namespace llvm::sys;
808 path::const_iterator I = path::begin(Path);
809 path::const_iterator E = path::end(Path);
810 IsPrivateHeader =
false;
822 if (*I ==
"Headers") {
824 }
else if (*I ==
"PrivateHeaders") {
826 IsPrivateHeader =
true;
827 }
else if (I->ends_with(
".framework")) {
828 StringRef Name = I->drop_back(10);
830 FrameworkName.clear();
831 FrameworkName.append(Name.begin(), Name.end());
832 IncludeSpelling.clear();
833 IncludeSpelling.append(Name.begin(), Name.end());
835 }
else if (FoundComp >= 2) {
836 IncludeSpelling.push_back(
'/');
837 IncludeSpelling.append(I->begin(), I->end());
842 return !FrameworkName.empty() && FoundComp >= 2;
847 StringRef Includer, StringRef IncludeFilename,
849 bool FoundByHeaderMap =
false) {
850 bool IsIncluderPrivateHeader =
false;
854 FromIncludeSpelling))
856 bool IsIncludeePrivateHeader =
false;
857 bool IsIncludeeInFramework =
859 ToFramework, ToIncludeSpelling);
861 if (!isAngled && !FoundByHeaderMap) {
863 if (IsIncludeeInFramework) {
864 NewInclude += ToIncludeSpelling;
867 NewInclude += IncludeFilename;
870 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
878 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
879 IsIncludeePrivateHeader && FromFramework == ToFramework)
880 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
891 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
892 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
895 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
896 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
897 ConstSearchDirIterator CurDirLocal =
nullptr;
898 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
903 if (IsFrameworkFound)
904 *IsFrameworkFound =
false;
910 if (llvm::sys::path::is_absolute(Filename)) {
920 RelativePath->clear();
921 RelativePath->append(Filename.begin(), Filename.end());
924 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
926 RequestingModule, SuggestedModule, OpenFile,
939 if (!Includers.empty() && !isAngled) {
942 for (
const auto &IncluderAndDir : Includers) {
946 TmpDir = IncluderAndDir.second.getName();
947 llvm::sys::path::append(TmpDir, Filename);
956 bool IncluderIsSystemHeader = [&]() {
958 return BuildSystemModule;
960 assert(HFI &&
"includer without file info");
964 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
965 RequestingModule, SuggestedModule)) {
967 assert(
First &&
"only first includer can have no file");
978 assert(FromHFI &&
"includer without file info");
979 unsigned DirInfo = FromHFI->
DirInfo;
985 StringRef SearchPathRef(IncluderAndDir.second.getName());
987 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
990 RelativePath->clear();
991 RelativePath->append(Filename.begin(), Filename.end());
995 IncluderAndDir.second.getName(), Filename,
1003 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1007 if (SuggestedModule) {
1008 MSSuggestedModule = *SuggestedModule;
1021 ConstSearchDirIterator It =
1033 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1035 ConstSearchDirIterator NextIt = std::next(It);
1038 if (CacheLookup.StartIt == NextIt &&
1039 CacheLookup.RequestingModule == RequestingModule) {
1041 if (CacheLookup.HitIt)
1042 It = CacheLookup.HitIt;
1043 if (CacheLookup.MappedName) {
1044 Filename = CacheLookup.MappedName;
1052 CacheLookup.reset(RequestingModule, NextIt);
1058 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1059 if (Iter == SearchDirHeaderMapIndex.end())
1068 CacheLookup.reset(RequestingModule, NextIt);
1075 bool InUserSpecifiedSystemFramework =
false;
1076 bool IsInHeaderMap =
false;
1077 bool IsFrameworkFoundInDir =
false;
1079 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1080 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1081 IsInHeaderMap, MappedName, OpenFile);
1082 if (!MappedName.empty()) {
1083 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1084 CacheLookup.MappedName =
1085 copyString(MappedName, LookupFileCache.getAllocator());
1091 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1092 if (IsFrameworkFound)
1096 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1102 IncludeNames[*
File] = Filename;
1106 HFI.
DirInfo = CurDir->getDirCharacteristic();
1116 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1117 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1125 if (SuggestedModule)
1126 *SuggestedModule = MSSuggestedModule;
1130 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1131 if (!Includers.empty())
1133 Includers.front().second.getName(), Filename,
1134 *
File, isAngled, FoundByHeaderMap);
1137 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1142 if (SuggestedModule)
1143 *SuggestedModule = MSSuggestedModule;
1149 return std::nullopt;
1163 size_t SlashPos = Filename.find(
'/');
1164 if (SlashPos == StringRef::npos)
1165 return std::nullopt;
1168 StringRef ContextName = ContextFileEnt.
getName();
1171 const unsigned DotFrameworkLen = 10;
1172 auto FrameworkPos = ContextName.find(
".framework");
1173 if (FrameworkPos == StringRef::npos ||
1174 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1175 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1176 return std::nullopt;
1180 DotFrameworkLen + 1);
1183 FrameworkName +=
"Frameworks/";
1184 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1185 FrameworkName +=
".framework/";
1188 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1192 if (CacheLookup.second.Directory &&
1193 CacheLookup.first().size() == FrameworkName.size() &&
1194 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1195 CacheLookup.first().size()) != 0)
1196 return std::nullopt;
1199 if (!CacheLookup.second.Directory) {
1200 ++NumSubFrameworkLookups;
1203 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1205 return std::nullopt;
1209 CacheLookup.second.Directory = Dir;
1214 RelativePath->clear();
1215 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1220 HeadersFilename +=
"Headers/";
1222 SearchPath->clear();
1224 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1227 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1228 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1231 HeadersFilename = FrameworkName;
1232 HeadersFilename +=
"PrivateHeaders/";
1234 SearchPath->clear();
1236 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1239 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1240 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1243 return std::nullopt;
1248 assert(ContextHFI &&
"context file without file info");
1251 unsigned DirInfo = ContextHFI->
DirInfo;
1254 FrameworkName.pop_back();
1255 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1256 RequestingModule, SuggestedModule,
1258 return std::nullopt;
1277 bool isModuleHeader,
1278 bool isTextualModuleHeader) {
1295 assert(OtherHFI.
External &&
"expected to merge external HFI");
1311 if (FE.
getUID() >= FileInfo.size())
1312 FileInfo.resize(FE.
getUID() + 1);
1316 if (ExternalSource && !HFI->
Resolved) {
1317 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1318 if (ExternalHFI.IsValid) {
1320 if (ExternalHFI.External)
1334 if (ExternalSource) {
1335 if (FE.
getUID() >= FileInfo.size())
1336 FileInfo.resize(FE.
getUID() + 1);
1338 HFI = &FileInfo[FE.
getUID()];
1341 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1342 if (ExternalHFI.IsValid) {
1344 if (ExternalHFI.External)
1348 }
else if (FE.
getUID() < FileInfo.size()) {
1349 HFI = &FileInfo[FE.
getUID()];
1354 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1360 if (FE.
getUID() < FileInfo.size()) {
1361 HFI = &FileInfo[FE.
getUID()];
1374 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1380 bool isCompilingModuleHeader) {
1382 if (!isCompilingModuleHeader) {
1391 HFI.mergeModuleMembership(
Role);
1392 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1397 bool ModulesEnabled,
Module *M,
1398 bool &IsFirstIncludeOfFile) {
1414 IsFirstIncludeOfFile =
false;
1417 auto MaybeReenterImportedFile = [&]() ->
bool {
1435 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1439 ModMap.resolveHeaderDirectives(
File);
1459 if (FileInfo.isTextualModuleHeader)
1462 if (FileInfo.isCompilingModuleHeader) {
1465 if (FileInfo.isModuleHeader) {
1470 if (ModMap.isBuiltinHeader(
File))
1479 if (FileInfo.getControllingMacro(ExternalLookup))
1499 FileInfo.isImport =
true;
1506 if (FileInfo.isPragmaOnce ||
1507 (FileInfo.isImport && !MaybeReenterImportedFile()))
1516 FileInfo.getControllingMacro(ExternalLookup)) {
1523 ++NumMultiIncludeFileOptzn;
1533 return SearchDirs.capacity()
1534 + llvm::capacity_in_bytes(FileInfo)
1535 + llvm::capacity_in_bytes(HeaderMaps)
1536 + LookupFileCache.getAllocator().getTotalMemory()
1537 + FrameworkMap.getAllocator().getTotalMemory();
1541 return &DL - &*SearchDirs.begin();
1545 return FrameworkNames.insert(Framework).first->first();
1549 auto It = IncludeNames.find(
File);
1550 if (It == IncludeNames.end())
1558 if (!HSOpts.ImplicitModuleMaps)
1566 DirName = llvm::sys::path::parent_path(DirName);
1567 if (DirName.empty())
1571 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1578 llvm::sys::path::extension(Dir->getName()) ==
".framework")) {
1579 case MMR_NewlyProcessed:
1580 case MMR_AlreadyProcessed: {
1583 const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];
1584 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1585 DirectoryModuleMap[FixUpDirectories[I]] = MMDS;
1588 case MMR_NoDirectory:
1589 case MMR_InvalidModuleMap:
1599 FixUpDirectories.push_back(*Dir);
1605 bool AllowExcluded)
const {
1606 if (ExternalSource) {
1611 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1616 if (ExternalSource) {
1621 return ModMap.findAllModulesForHeader(
File);
1626 if (ExternalSource) {
1631 return ModMap.findResolvedModulesForHeader(
File);
1635 Module *RequestingModule,
1651 if (SuggestedModule)
1661 if (SuggestedModule)
1669bool HeaderSearch::findUsableModuleForHeader(
1680bool HeaderSearch::findUsableModuleForFrameworkHeader(
1686 SmallVector<std::string, 4> SubmodulePath;
1689 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1692 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1696 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1710 bool Diagnose =
true) {
1711 StringRef Filename = llvm::sys::path::filename(
File.getName());
1713 if (Filename ==
"module.map")
1714 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1715 else if (Filename ==
"module.modulemap")
1716 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1718 return std::nullopt;
1719 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
1721 if (Diagnose && Filename ==
"module.map")
1722 Diags.
Report(diag::warn_deprecated_module_dot_map)
1723 << PrivateFilename << 1
1724 <<
File.getDir().getName().ends_with(
".framework");
1730 FileID ID,
unsigned *Offset,
1731 StringRef OriginalModuleMapFile) {
1736 Dir = FileMgr.getOptionalDirectoryRef(
".");
1738 if (!OriginalModuleMapFile.empty()) {
1741 Dir = FileMgr.getOptionalDirectoryRef(
1742 llvm::sys::path::parent_path(OriginalModuleMapFile));
1744 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
1745 Dir = FakeFile.getDir();
1748 Dir =
File.getDir();
1751 assert(Dir &&
"parent must exist");
1752 StringRef DirName(Dir->
getName());
1753 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1754 DirName = llvm::sys::path::parent_path(DirName);
1755 if (DirName.ends_with(
".framework"))
1756 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
1760 assert(Dir &&
"parent must exist");
1764 assert(Dir &&
"module map home directory must exist");
1765 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1766 case MMR_AlreadyProcessed:
1767 case MMR_NewlyProcessed:
1769 case MMR_NoDirectory:
1770 case MMR_InvalidModuleMap:
1773 llvm_unreachable(
"Unknown load module map result");
1776HeaderSearch::ModuleMapResult
1777HeaderSearch::parseAndLoadModuleMapFileImpl(
FileEntryRef File,
bool IsSystem,
1782 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1783 if (!AddResult.second)
1784 return AddResult.first->second ? MMR_AlreadyProcessed
1785 : MMR_InvalidModuleMap;
1788 LoadedModuleMaps[
File] =
false;
1789 return MMR_InvalidModuleMap;
1796 LoadedModuleMaps[
File] =
false;
1797 return MMR_InvalidModuleMap;
1802 return MMR_NewlyProcessed;
1805HeaderSearch::ModuleMapResult
1810 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
1811 if (!AddResult.second)
1812 return AddResult.first->second ? MMR_AlreadyProcessed
1813 : MMR_InvalidModuleMap;
1815 if (ModMap.parseModuleMapFile(
File, IsSystem, Dir, ID)) {
1816 ParsedModuleMaps[
File] =
false;
1817 return MMR_InvalidModuleMap;
1823 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {
1824 ParsedModuleMaps[
File] =
false;
1825 return MMR_InvalidModuleMap;
1830 return MMR_NewlyProcessed;
1835 if (!HSOpts.ImplicitModuleMaps)
1836 return std::nullopt;
1841 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1842 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1843 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1847 ModuleMapFileName = Dir.
getName();
1848 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1849 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
1850 Diags.Report(diag::warn_deprecated_module_dot_map)
1851 << ModuleMapFileName << 0 << IsFramework;
1858 ModuleMapFileName = Dir.
getName();
1859 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1860 "module.private.modulemap");
1861 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1864 return std::nullopt;
1871 case MMR_InvalidModuleMap:
1874 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1877 case MMR_NoDirectory:
1880 case MMR_AlreadyProcessed:
1881 case MMR_NewlyProcessed:
1888HeaderSearch::ModuleMapResult
1891 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1894 return MMR_NoDirectory;
1897HeaderSearch::ModuleMapResult
1900 auto InsertRes = DirectoryModuleMap.insert(std::pair{
1901 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
1902 ModuleMapDirectoryState &MMState = InsertRes.first->second;
1903 if (!InsertRes.second) {
1904 switch (MMState.Status) {
1905 case ModuleMapDirectoryState::Parsed:
1907 case ModuleMapDirectoryState::Loaded:
1908 return MMR_AlreadyProcessed;
1909 case ModuleMapDirectoryState::Invalid:
1910 return MMR_InvalidModuleMap;
1914 if (!MMState.ModuleMapFile)
1917 if (MMState.ModuleMapFile) {
1919 parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1923 if (
Result == MMR_NewlyProcessed)
1924 MMState.Status = ModuleMapDirectoryState::Loaded;
1925 else if (
Result == MMR_InvalidModuleMap)
1926 MMState.Status = ModuleMapDirectoryState::Invalid;
1929 return MMR_InvalidModuleMap;
1932HeaderSearch::ModuleMapResult
1933HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
1935 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1936 return parseModuleMapFile(*Dir, IsSystem, IsFramework);
1938 return MMR_NoDirectory;
1941HeaderSearch::ModuleMapResult
1944 auto InsertRes = DirectoryModuleMap.insert(std::pair{
1945 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
1946 ModuleMapDirectoryState &MMState = InsertRes.first->second;
1947 if (!InsertRes.second) {
1948 switch (MMState.Status) {
1949 case ModuleMapDirectoryState::Parsed:
1950 case ModuleMapDirectoryState::Loaded:
1951 return MMR_AlreadyProcessed;
1952 case ModuleMapDirectoryState::Invalid:
1953 return MMR_InvalidModuleMap;
1957 if (!MMState.ModuleMapFile)
1960 if (MMState.ModuleMapFile) {
1962 parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1966 if (
Result == MMR_NewlyProcessed)
1967 MMState.Status = ModuleMapDirectoryState::Parsed;
1968 else if (
Result == MMR_InvalidModuleMap)
1969 MMState.Status = ModuleMapDirectoryState::Invalid;
1972 return MMR_InvalidModuleMap;
1978 if (HSOpts.ImplicitModuleMaps) {
1981 bool IsSystem = DL.isSystemHeaderDirectory();
1982 if (DL.isFramework()) {
1985 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1988 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1989 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1991 Dir != DirEnd && !EC; Dir.increment(EC)) {
1992 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1995 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2000 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2007 if (DL.isHeaderMap())
2016 loadSubdirectoryModuleMaps(DL);
2021 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2025 if (!HSOpts.ImplicitModuleMaps)
2031 if (!DL.isNormalDir())
2040void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2042 "Should not be loading subdirectory module maps");
2049 FileMgr.makeAbsolutePath(Dir);
2051 llvm::sys::path::native(Dir, DirNative);
2052 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2053 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2054 Dir != DirEnd && !EC; Dir.increment(EC)) {
2055 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2057 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2070 MainFile, IsAngled);
2074 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2075 bool *IsAngled)
const {
2076 using namespace llvm::sys;
2079 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2080 fs::make_absolute(WorkingDir, FilePath);
2084 path::remove_dots(FilePath,
true);
2085 path::native(FilePath, path::Style::posix);
2088 unsigned BestPrefixLength = 0;
2093 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2094 fs::make_absolute(WorkingDir, Dir);
2095 path::remove_dots(Dir,
true);
2096 for (
auto NI = path::begin(
File), NE = path::end(
File),
2097 DI = path::begin(Dir), DE = path::end(Dir);
2098 NI != NE; ++NI, ++DI) {
2101 unsigned PrefixLength = NI - path::begin(
File);
2102 if (PrefixLength > BestPrefixLength) {
2103 BestPrefixLength = PrefixLength;
2110 if (NI->size() == 1 && DI->size() == 1 &&
2111 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2117 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2118 StringRef NBasename = path::stem(*NI);
2119 StringRef DBasename = path::stem(*DI);
2120 if (DBasename.starts_with(NBasename))
2130 bool BestPrefixIsFramework =
false;
2132 if (DL.isNormalDir()) {
2133 StringRef Dir = DL.getDirRef()->getName();
2134 if (CheckDir(Dir)) {
2136 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2137 BestPrefixIsFramework =
false;
2139 }
else if (DL.isFramework()) {
2140 StringRef Dir = DL.getFrameworkDirRef()->getName();
2141 if (CheckDir(Dir)) {
2144 *IsAngled = BestPrefixLength;
2145 BestPrefixIsFramework =
true;
2152 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2155 BestPrefixIsFramework =
false;
2160 StringRef Filename =
File.drop_front(BestPrefixLength);
2162 if (!DL.isHeaderMap())
2165 StringRef SpelledFilename =
2166 DL.getHeaderMap()->reverseLookupFilename(Filename);
2167 if (!SpelledFilename.empty()) {
2168 Filename = SpelledFilename;
2169 BestPrefixIsFramework =
false;
2176 bool IsPrivateHeader;
2178 if (BestPrefixIsFramework &&
2181 Filename = IncludeSpelling;
2183 return path::convert_to_slash(Filename);
2188 NormalizedPath.assign(Path.begin(), Path.end());
2189 FileMgr.makeAbsolutePath(NormalizedPath);
2190 llvm::sys::path::remove_dots(NormalizedPath);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
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)
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.
bool parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Load the given module map file, and record any modules we encounter.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
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.
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.
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.