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";
675 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
686 RelativePath->clear();
687 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
691 unsigned OrigSize = FrameworkName.size();
693 FrameworkName +=
"Headers/";
698 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
701 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
707 const char *
Private =
"Private";
708 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
711 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
721 StringRef FrameworkPath =
File->getDir().getName();
722 bool FoundFramework =
false;
731 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
732 FoundFramework =
true;
737 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
738 if (FrameworkPath.empty())
743 if (FoundFramework) {
744 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
746 SuggestedModule, IsSystem))
749 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
750 SuggestedModule, IsSystem))
759void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
762 CacheLookup.HitIt = HitIt;
763 noteLookupUsage(HitIt.Idx, Loc);
766void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
767 SearchDirsUsage[HitIdx] =
true;
769 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
770 if (UserEntryIdxIt != SearchDirToHSEntry.end())
771 Diags.Report(Loc, diag::remark_pp_search_path_usage)
772 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
790 if (MSFE && FE != *MSFE) {
791 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
797static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
798 assert(!Str.empty());
799 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
800 std::copy(Str.begin(), Str.end(), CopyStr);
801 CopyStr[Str.size()] =
'\0';
808 using namespace llvm::sys;
809 path::const_iterator I = path::begin(Path);
810 path::const_iterator E = path::end(Path);
811 IsPrivateHeader =
false;
823 if (*I ==
"Headers") {
825 }
else if (*I ==
"PrivateHeaders") {
827 IsPrivateHeader =
true;
828 }
else if (I->ends_with(
".framework")) {
829 StringRef Name = I->drop_back(10);
831 FrameworkName.clear();
832 FrameworkName.append(Name.begin(), Name.end());
833 IncludeSpelling.clear();
834 IncludeSpelling.append(Name.begin(), Name.end());
836 }
else if (FoundComp >= 2) {
837 IncludeSpelling.push_back(
'/');
838 IncludeSpelling.append(I->begin(), I->end());
843 return !FrameworkName.empty() && FoundComp >= 2;
848 StringRef Includer, StringRef IncludeFilename,
850 bool FoundByHeaderMap =
false) {
851 bool IsIncluderPrivateHeader =
false;
855 FromIncludeSpelling))
857 bool IsIncludeePrivateHeader =
false;
858 bool IsIncludeeInFramework =
860 ToFramework, ToIncludeSpelling);
862 if (!isAngled && !FoundByHeaderMap) {
864 if (IsIncludeeInFramework) {
865 NewInclude += ToIncludeSpelling;
868 NewInclude += IncludeFilename;
871 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
879 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
880 IsIncludeePrivateHeader && FromFramework == ToFramework)
881 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
892 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
893 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
896 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
897 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
898 ConstSearchDirIterator CurDirLocal =
nullptr;
899 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
904 if (IsFrameworkFound)
905 *IsFrameworkFound =
false;
911 if (llvm::sys::path::is_absolute(Filename)) {
921 RelativePath->clear();
922 RelativePath->append(Filename.begin(), Filename.end());
925 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
927 RequestingModule, SuggestedModule, OpenFile,
940 if (!Includers.empty() && !isAngled) {
943 for (
const auto &IncluderAndDir : Includers) {
947 TmpDir = IncluderAndDir.second.getName();
948 llvm::sys::path::append(TmpDir, Filename);
957 bool IncluderIsSystemHeader = [&]() {
959 return BuildSystemModule;
961 assert(HFI &&
"includer without file info");
965 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
966 RequestingModule, SuggestedModule)) {
968 assert(
First &&
"only first includer can have no file");
979 assert(FromHFI &&
"includer without file info");
980 unsigned DirInfo = FromHFI->
DirInfo;
986 StringRef SearchPathRef(IncluderAndDir.second.getName());
988 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
991 RelativePath->clear();
992 RelativePath->append(Filename.begin(), Filename.end());
996 IncluderAndDir.second.getName(), Filename,
1004 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1008 if (SuggestedModule) {
1009 MSSuggestedModule = *SuggestedModule;
1022 ConstSearchDirIterator It =
1034 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1036 ConstSearchDirIterator NextIt = std::next(It);
1039 if (CacheLookup.StartIt == NextIt &&
1040 CacheLookup.RequestingModule == RequestingModule) {
1042 if (CacheLookup.HitIt)
1043 It = CacheLookup.HitIt;
1044 if (CacheLookup.MappedName) {
1045 Filename = CacheLookup.MappedName;
1053 CacheLookup.reset(RequestingModule, NextIt);
1059 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1060 if (Iter == SearchDirHeaderMapIndex.end())
1069 CacheLookup.reset(RequestingModule, NextIt);
1076 bool InUserSpecifiedSystemFramework =
false;
1077 bool IsInHeaderMap =
false;
1078 bool IsFrameworkFoundInDir =
false;
1080 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1081 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1082 IsInHeaderMap, MappedName, OpenFile);
1083 if (!MappedName.empty()) {
1084 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1085 CacheLookup.MappedName =
1086 copyString(MappedName, LookupFileCache.getAllocator());
1092 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1093 if (IsFrameworkFound)
1097 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1103 IncludeNames[*
File] = Filename;
1107 HFI.
DirInfo = CurDir->getDirCharacteristic();
1117 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1118 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1126 if (SuggestedModule)
1127 *SuggestedModule = MSSuggestedModule;
1131 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1132 if (!Includers.empty())
1134 Includers.front().second.getName(), Filename,
1135 *
File, isAngled, FoundByHeaderMap);
1138 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1143 if (SuggestedModule)
1144 *SuggestedModule = MSSuggestedModule;
1150 return std::nullopt;
1164 size_t SlashPos = Filename.find(
'/');
1165 if (SlashPos == StringRef::npos)
1166 return std::nullopt;
1169 StringRef ContextName = ContextFileEnt.
getName();
1172 const unsigned DotFrameworkLen = 10;
1173 auto FrameworkPos = ContextName.find(
".framework");
1174 if (FrameworkPos == StringRef::npos ||
1175 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1176 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1177 return std::nullopt;
1181 DotFrameworkLen + 1);
1184 FrameworkName +=
"Frameworks/";
1185 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1186 FrameworkName +=
".framework/";
1189 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1193 if (CacheLookup.second.Directory &&
1194 CacheLookup.first().size() == FrameworkName.size() &&
1195 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1196 CacheLookup.first().size()) != 0)
1197 return std::nullopt;
1200 if (!CacheLookup.second.Directory) {
1201 ++NumSubFrameworkLookups;
1204 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1206 return std::nullopt;
1210 CacheLookup.second.Directory = Dir;
1215 RelativePath->clear();
1216 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1221 HeadersFilename +=
"Headers/";
1223 SearchPath->clear();
1225 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1228 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1229 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1232 HeadersFilename = FrameworkName;
1233 HeadersFilename +=
"PrivateHeaders/";
1235 SearchPath->clear();
1237 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1240 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1241 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1244 return std::nullopt;
1249 assert(ContextHFI &&
"context file without file info");
1252 unsigned DirInfo = ContextHFI->
DirInfo;
1255 FrameworkName.pop_back();
1256 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1257 RequestingModule, SuggestedModule,
1259 return std::nullopt;
1278 bool isModuleHeader,
1279 bool isTextualModuleHeader) {
1296 assert(OtherHFI.
External &&
"expected to merge external HFI");
1312 if (FE.
getUID() >= FileInfo.size())
1313 FileInfo.resize(FE.
getUID() + 1);
1317 if (ExternalSource && !HFI->
Resolved) {
1318 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1319 if (ExternalHFI.IsValid) {
1321 if (ExternalHFI.External)
1335 if (ExternalSource) {
1336 if (FE.
getUID() >= FileInfo.size())
1337 FileInfo.resize(FE.
getUID() + 1);
1339 HFI = &FileInfo[FE.
getUID()];
1342 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1343 if (ExternalHFI.IsValid) {
1345 if (ExternalHFI.External)
1349 }
else if (FE.
getUID() < FileInfo.size()) {
1350 HFI = &FileInfo[FE.
getUID()];
1355 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1361 if (FE.
getUID() < FileInfo.size()) {
1362 HFI = &FileInfo[FE.
getUID()];
1375 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1381 bool isCompilingModuleHeader) {
1383 if (!isCompilingModuleHeader) {
1392 HFI.mergeModuleMembership(
Role);
1393 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1398 bool ModulesEnabled,
Module *M,
1399 bool &IsFirstIncludeOfFile) {
1415 IsFirstIncludeOfFile =
false;
1418 auto MaybeReenterImportedFile = [&]() ->
bool {
1436 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1440 ModMap.resolveHeaderDirectives(
File);
1460 if (FileInfo.isTextualModuleHeader)
1463 if (FileInfo.isCompilingModuleHeader) {
1466 if (FileInfo.isModuleHeader) {
1471 if (ModMap.isBuiltinHeader(
File))
1480 if (FileInfo.getControllingMacro(ExternalLookup))
1500 FileInfo.isImport =
true;
1507 if (FileInfo.isPragmaOnce ||
1508 (FileInfo.isImport && !MaybeReenterImportedFile()))
1517 FileInfo.getControllingMacro(ExternalLookup)) {
1524 ++NumMultiIncludeFileOptzn;
1534 return SearchDirs.capacity()
1535 + llvm::capacity_in_bytes(FileInfo)
1536 + llvm::capacity_in_bytes(HeaderMaps)
1537 + LookupFileCache.getAllocator().getTotalMemory()
1538 + FrameworkMap.getAllocator().getTotalMemory();
1542 return &DL - &*SearchDirs.begin();
1546 return FrameworkNames.insert(Framework).first->first();
1550 auto It = IncludeNames.find(
File);
1551 if (It == IncludeNames.end())
1559 if (!HSOpts.ImplicitModuleMaps)
1567 DirName = llvm::sys::path::parent_path(DirName);
1568 if (DirName.empty())
1572 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1579 llvm::sys::path::extension(Dir->getName()) ==
".framework")) {
1580 case MMR_NewlyProcessed:
1581 case MMR_AlreadyProcessed: {
1584 const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];
1585 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1586 DirectoryModuleMap[FixUpDirectories[I]] = MMDS;
1589 case MMR_NoDirectory:
1590 case MMR_InvalidModuleMap:
1600 FixUpDirectories.push_back(*Dir);
1606 bool AllowExcluded)
const {
1607 if (ExternalSource) {
1612 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1617 if (ExternalSource) {
1622 return ModMap.findAllModulesForHeader(
File);
1627 if (ExternalSource) {
1632 return ModMap.findResolvedModulesForHeader(
File);
1636 Module *RequestingModule,
1652 if (SuggestedModule)
1662 if (SuggestedModule)
1670bool HeaderSearch::findUsableModuleForHeader(
1681bool HeaderSearch::findUsableModuleForFrameworkHeader(
1687 SmallVector<std::string, 4> SubmodulePath;
1690 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1693 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1697 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1711 bool Diagnose =
true) {
1712 StringRef Filename = llvm::sys::path::filename(
File.getName());
1714 if (Filename ==
"module.map")
1715 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1716 else if (Filename ==
"module.modulemap")
1717 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1719 return std::nullopt;
1720 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
1722 if (Diagnose && Filename ==
"module.map")
1723 Diags.
Report(diag::warn_deprecated_module_dot_map)
1724 << PrivateFilename << 1
1725 <<
File.getDir().getName().ends_with(
".framework");
1731 FileID ID,
unsigned *Offset,
1732 StringRef OriginalModuleMapFile) {
1737 Dir = FileMgr.getOptionalDirectoryRef(
".");
1739 if (!OriginalModuleMapFile.empty()) {
1742 Dir = FileMgr.getOptionalDirectoryRef(
1743 llvm::sys::path::parent_path(OriginalModuleMapFile));
1745 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
1746 Dir = FakeFile.getDir();
1749 Dir =
File.getDir();
1752 assert(Dir &&
"parent must exist");
1753 StringRef DirName(Dir->
getName());
1754 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1755 DirName = llvm::sys::path::parent_path(DirName);
1756 if (DirName.ends_with(
".framework"))
1757 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
1761 assert(Dir &&
"parent must exist");
1765 assert(Dir &&
"module map home directory must exist");
1766 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1767 case MMR_AlreadyProcessed:
1768 case MMR_NewlyProcessed:
1770 case MMR_NoDirectory:
1771 case MMR_InvalidModuleMap:
1774 llvm_unreachable(
"Unknown load module map result");
1777HeaderSearch::ModuleMapResult
1778HeaderSearch::parseAndLoadModuleMapFileImpl(
FileEntryRef File,
bool IsSystem,
1783 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1784 if (!AddResult.second)
1785 return AddResult.first->second ? MMR_AlreadyProcessed
1786 : MMR_InvalidModuleMap;
1789 LoadedModuleMaps[
File] =
false;
1790 return MMR_InvalidModuleMap;
1797 LoadedModuleMaps[
File] =
false;
1798 return MMR_InvalidModuleMap;
1803 return MMR_NewlyProcessed;
1806HeaderSearch::ModuleMapResult
1811 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
1812 if (!AddResult.second)
1813 return AddResult.first->second ? MMR_AlreadyProcessed
1814 : MMR_InvalidModuleMap;
1816 if (ModMap.parseModuleMapFile(
File, IsSystem, Dir, ID)) {
1817 ParsedModuleMaps[
File] =
false;
1818 return MMR_InvalidModuleMap;
1824 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {
1825 ParsedModuleMaps[
File] =
false;
1826 return MMR_InvalidModuleMap;
1831 return MMR_NewlyProcessed;
1836 if (!HSOpts.ImplicitModuleMaps)
1837 return std::nullopt;
1842 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1843 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1844 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1848 ModuleMapFileName = Dir.
getName();
1849 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1850 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
1851 Diags.Report(diag::warn_deprecated_module_dot_map)
1852 << ModuleMapFileName << 0 << IsFramework;
1859 ModuleMapFileName = Dir.
getName();
1860 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1861 "module.private.modulemap");
1862 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1865 return std::nullopt;
1872 case MMR_InvalidModuleMap:
1875 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1878 case MMR_NoDirectory:
1881 case MMR_AlreadyProcessed:
1882 case MMR_NewlyProcessed:
1889HeaderSearch::ModuleMapResult
1892 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1895 return MMR_NoDirectory;
1898HeaderSearch::ModuleMapResult
1901 auto InsertRes = DirectoryModuleMap.insert(std::pair{
1902 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
1903 ModuleMapDirectoryState &MMState = InsertRes.first->second;
1904 if (!InsertRes.second) {
1905 switch (MMState.Status) {
1906 case ModuleMapDirectoryState::Parsed:
1908 case ModuleMapDirectoryState::Loaded:
1909 return MMR_AlreadyProcessed;
1910 case ModuleMapDirectoryState::Invalid:
1911 return MMR_InvalidModuleMap;
1915 if (!MMState.ModuleMapFile)
1918 if (MMState.ModuleMapFile) {
1920 parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1924 if (
Result == MMR_NewlyProcessed)
1925 MMState.Status = ModuleMapDirectoryState::Loaded;
1926 else if (
Result == MMR_InvalidModuleMap)
1927 MMState.Status = ModuleMapDirectoryState::Invalid;
1930 return MMR_InvalidModuleMap;
1933HeaderSearch::ModuleMapResult
1934HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
1936 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1937 return parseModuleMapFile(*Dir, IsSystem, IsFramework);
1939 return MMR_NoDirectory;
1942HeaderSearch::ModuleMapResult
1945 auto InsertRes = DirectoryModuleMap.insert(std::pair{
1946 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
1947 ModuleMapDirectoryState &MMState = InsertRes.first->second;
1948 if (!InsertRes.second) {
1949 switch (MMState.Status) {
1950 case ModuleMapDirectoryState::Parsed:
1951 case ModuleMapDirectoryState::Loaded:
1952 return MMR_AlreadyProcessed;
1953 case ModuleMapDirectoryState::Invalid:
1954 return MMR_InvalidModuleMap;
1958 if (!MMState.ModuleMapFile)
1961 if (MMState.ModuleMapFile) {
1963 parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1967 if (
Result == MMR_NewlyProcessed)
1968 MMState.Status = ModuleMapDirectoryState::Parsed;
1969 else if (
Result == MMR_InvalidModuleMap)
1970 MMState.Status = ModuleMapDirectoryState::Invalid;
1973 return MMR_InvalidModuleMap;
1979 if (HSOpts.ImplicitModuleMaps) {
1982 bool IsSystem = DL.isSystemHeaderDirectory();
1983 if (DL.isFramework()) {
1986 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1989 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1990 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1992 Dir != DirEnd && !EC; Dir.increment(EC)) {
1993 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1996 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2001 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2008 if (DL.isHeaderMap())
2017 loadSubdirectoryModuleMaps(DL);
2022 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2026 if (!HSOpts.ImplicitModuleMaps)
2032 if (!DL.isNormalDir())
2041void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2043 "Should not be loading subdirectory module maps");
2050 FileMgr.makeAbsolutePath(Dir);
2052 llvm::sys::path::native(Dir, DirNative);
2053 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2054 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2055 Dir != DirEnd && !EC; Dir.increment(EC)) {
2056 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2058 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2071 MainFile, IsAngled);
2075 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2076 bool *IsAngled)
const {
2077 using namespace llvm::sys;
2080 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2081 fs::make_absolute(WorkingDir, FilePath);
2085 path::remove_dots(FilePath,
true);
2086 path::native(FilePath, path::Style::posix);
2089 unsigned BestPrefixLength = 0;
2094 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2095 fs::make_absolute(WorkingDir, Dir);
2096 path::remove_dots(Dir,
true);
2097 for (
auto NI = path::begin(
File), NE = path::end(
File),
2098 DI = path::begin(Dir), DE = path::end(Dir);
2099 NI != NE; ++NI, ++DI) {
2102 unsigned PrefixLength = NI - path::begin(
File);
2103 if (PrefixLength > BestPrefixLength) {
2104 BestPrefixLength = PrefixLength;
2111 if (NI->size() == 1 && DI->size() == 1 &&
2112 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2118 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2119 StringRef NBasename = path::stem(*NI);
2120 StringRef DBasename = path::stem(*DI);
2121 if (DBasename.starts_with(NBasename))
2131 bool BestPrefixIsFramework =
false;
2133 if (DL.isNormalDir()) {
2134 StringRef Dir = DL.getDirRef()->getName();
2135 if (CheckDir(Dir)) {
2137 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2138 BestPrefixIsFramework =
false;
2140 }
else if (DL.isFramework()) {
2141 StringRef Dir = DL.getFrameworkDirRef()->getName();
2142 if (CheckDir(Dir)) {
2145 *IsAngled = BestPrefixLength;
2146 BestPrefixIsFramework =
true;
2153 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2156 BestPrefixIsFramework =
false;
2161 StringRef Filename =
File.drop_front(BestPrefixLength);
2163 if (!DL.isHeaderMap())
2166 StringRef SpelledFilename =
2167 DL.getHeaderMap()->reverseLookupFilename(Filename);
2168 if (!SpelledFilename.empty()) {
2169 Filename = SpelledFilename;
2170 BestPrefixIsFramework =
false;
2177 bool IsPrivateHeader;
2179 if (BestPrefixIsFramework &&
2182 Filename = IncludeSpelling;
2184 return path::convert_to_slash(Filename);
2189 NormalizedPath.assign(Path.begin(), Path.end());
2190 FileMgr.makeAbsolutePath(NormalizedPath);
2191 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.