26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/Hashing.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/SmallString.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/ADT/Statistic.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/Support/Allocator.h"
34#include "llvm/Support/Capacity.h"
35#include "llvm/Support/Errc.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/FileSystem.h"
38#include "llvm/Support/Path.h"
39#include "llvm/Support/VirtualFileSystem.h"
40#include "llvm/Support/xxhash.h"
47#include <system_error>
52#define DEBUG_TYPE "file-search"
56 NumMultiIncludeFileOptzn,
57 "Number of #includes skipped due to the multi-include optimization.");
60 "Number of subframework lookups.");
74 if (ControllingMacro && ControllingMacro->
isOutOfDate()) {
75 assert(
External &&
"We must have an external source if we have a "
76 "controlling macro that is out of date.");
77 External->updateOutOfDateIdentifier(*ControllingMacro);
79 return ControllingMacro;
88 : HSOpts(
std::move(HSOpts)), Diags(Diags),
89 FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
90 ModMap(SourceMgr, Diags, LangOpts,
Target, *this) {}
93 llvm::errs() <<
"\n*** HeaderSearch Stats:\n"
94 << FileInfo.size() <<
" files tracked.\n";
95 unsigned NumOnceOnlyFiles = 0;
96 for (
unsigned i = 0, e = FileInfo.size(); i != e; ++i)
97 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);
98 llvm::errs() <<
" " << NumOnceOnlyFiles <<
" #import/#pragma once files.\n";
100 llvm::errs() <<
" " << NumIncluded <<
" #include/#include_next/#import.\n"
101 <<
" " << NumMultiIncludeFileOptzn
102 <<
" #includes skipped due to the multi-include optimization.\n";
104 llvm::errs() << NumFrameworkLookups <<
" framework lookups.\n"
105 << NumSubFrameworkLookups <<
" subframework lookups.\n";
109 std::vector<DirectoryLookup> dirs,
unsigned int angledDirIdx,
110 unsigned int systemDirIdx,
111 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
112 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
113 "Directory indices are unordered");
114 SearchDirs = std::move(dirs);
115 SearchDirsUsage.assign(SearchDirs.size(),
false);
116 AngledDirIdx = angledDirIdx;
117 SystemDirIdx = systemDirIdx;
118 SearchDirToHSEntry = std::move(searchDirToHSEntry);
120 indexInitialHeaderMaps();
124 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
125 SearchDirs.insert(SearchDirs.begin() + idx, dir);
126 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx,
false);
133 std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
134 for (
unsigned I = 0,
E = SearchDirsUsage.size(); I <
E; ++I) {
136 if (SearchDirsUsage[I]) {
137 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
139 if (UserEntryIdxIt != SearchDirToHSEntry.end())
140 UserEntryUsage[UserEntryIdxIt->second] =
true;
143 return UserEntryUsage;
147 std::vector<bool> VFSUsage;
154 RootFS.visit([&](llvm::vfs::FileSystem &FS) {
155 if (
auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {
156 VFSUsage.push_back(RFS->hasBeenUsed());
157 RFS->clearHasBeenUsed();
161 "A different number of RedirectingFileSystem's were present than "
162 "-ivfsoverlay options passed to Clang!");
164 std::reverse(VFSUsage.begin(), VFSUsage.end());
173 if (!HeaderMaps.empty()) {
174 for (
unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
177 if (HeaderMaps[i].first == FE)
178 return HeaderMaps[i].second.get();
182 HeaderMaps.emplace_back(FE, std::move(HM));
183 return HeaderMaps.back().second.get();
192 for (
auto &HM : HeaderMaps)
193 Names.push_back(std::string(HM.first.getName()));
209 auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName));
210 if (i != HSOpts->PrebuiltModuleFiles.end())
213 if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())
218 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
220 llvm::sys::fs::make_absolute(
Result);
221 if (ModuleName.contains(
':'))
225 llvm::sys::path::append(
Result, ModuleName.split(
':').first +
"-" +
226 ModuleName.split(
':').second +
229 llvm::sys::path::append(
Result, ModuleName +
".pcm");
231 return std::string(
Result);
241 StringRef ModuleMapPath =
ModuleMap->getName();
242 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ?
"" :
getModuleHash();
243 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
245 llvm::sys::fs::make_absolute(CachePath);
246 llvm::sys::path::append(CachePath, ModuleCacheHash);
248 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
256 StringRef ModuleMapPath) {
257 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
261std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
262 StringRef ModuleMapPath,
263 StringRef CachePath) {
266 if (CachePath.empty())
270 llvm::sys::fs::make_absolute(
Result);
272 if (HSOpts->DisableModuleHash) {
273 llvm::sys::path::append(
Result, ModuleName +
".pcm");
283 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
286 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
289 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
290 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
292 return Result.str().str();
297 bool AllowExtraModuleMapSearch) {
300 if (
Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
303 StringRef SearchName = ModuleName;
305 AllowExtraModuleMapSearch);
315 if (!
Module && SearchName.consume_back(
"_Private"))
317 AllowExtraModuleMapSearch);
318 if (!
Module && SearchName.consume_back(
"Private"))
320 AllowExtraModuleMapSearch);
326 bool AllowExtraModuleMapSearch) {
332 if (Dir.isFramework()) {
337 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
338 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
339 if (
auto FrameworkDir =
342 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
351 if (!Dir.isNormalDir())
354 bool IsSystem = Dir.isSystemHeaderDirectory();
360 false) == LMM_NewlyLoaded) {
371 NestedModuleMapDirName = Dir.getDirRef()->getName();
372 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
374 false) == LMM_NewlyLoaded){
381 if (HSOpts->AllowModuleMapSubdirectorySearch) {
384 if (Dir.haveSearchedAllModuleMaps())
389 if (AllowExtraModuleMapSearch)
390 loadSubdirectoryModuleMaps(Dir);
402void HeaderSearch::indexInitialHeaderMaps() {
403 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
406 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
407 auto &Dir = SearchDirs[i];
412 if (!Dir.isHeaderMap()) {
413 SearchDirHeaderMapIndex = std::move(Index);
414 FirstNonHeaderMapSearchDirIdx = i;
419 auto Callback = [&](StringRef
Filename) {
420 Index.try_emplace(
Filename.lower(), i);
422 Dir.getHeaderMap()->forEachKey(Callback);
437 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
443 bool IsSystemHeaderDir,
Module *RequestingModule,
445 bool CacheFailures ) {
452 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
453 if (EC != llvm::errc::no_such_file_or_directory &&
454 EC != llvm::errc::invalid_argument &&
455 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
456 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
463 if (!findUsableModuleForHeader(
464 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
465 SuggestedModule, IsSystemHeaderDir))
477 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
479 bool OpenFile)
const {
480 InUserSpecifiedSystemFramework =
false;
481 IsInHeaderMap =
false;
488 llvm::sys::path::append(TmpDir,
Filename);
492 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
495 RelativePath->clear();
499 return HS.getFileAndSuggestModule(
501 RequestingModule, SuggestedModule, OpenFile);
505 return DoFrameworkLookup(
Filename, HS, SearchPath, RelativePath,
506 RequestingModule, SuggestedModule,
507 InUserSpecifiedSystemFramework, IsFrameworkFound);
509 assert(
isHeaderMap() &&
"Unknown directory lookup");
516 IsInHeaderMap =
true;
518 auto FixupSearchPathAndFindUsableModule =
521 StringRef SearchPathRef(
getName());
523 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
526 RelativePath->clear();
529 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
530 RequestingModule, SuggestedModule,
540 if (llvm::sys::path::is_relative(Dest)) {
541 MappedName.append(Dest.begin(), Dest.end());
542 Filename = StringRef(MappedName.begin(), MappedName.size());
547 return FixupSearchPathAndFindUsableModule(*Res);
567 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
568 "Not a framework directory");
590 DirName = llvm::sys::path::parent_path(DirName);
601 if (llvm::sys::path::extension(DirName) ==
".framework") {
602 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
603 TopFrameworkDir = *Dir;
607 return TopFrameworkDir;
611 bool HasSuggestedModule) {
612 return HasSuggestedModule ||
622 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
626 size_t SlashPos =
Filename.find(
'/');
627 if (SlashPos == StringRef::npos)
644 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
645 FrameworkName.push_back(
'/');
648 StringRef ModuleName(
Filename.begin(), SlashPos);
649 FrameworkName += ModuleName;
652 FrameworkName +=
".framework/";
656 ++NumFrameworkLookups;
671 SystemFrameworkMarker +=
".system_framework";
672 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
683 RelativePath->clear();
688 unsigned OrigSize = FrameworkName.size();
690 FrameworkName +=
"Headers/";
695 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
704 const char *
Private =
"Private";
705 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
708 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
718 StringRef FrameworkPath =
File->getDir().getName();
719 bool FoundFramework =
false;
728 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
729 FoundFramework =
true;
734 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
735 if (FrameworkPath.empty())
740 if (FoundFramework) {
741 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
743 SuggestedModule, IsSystem))
746 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
747 SuggestedModule, IsSystem))
756void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
759 CacheLookup.HitIt = HitIt;
760 noteLookupUsage(HitIt.Idx,
Loc);
764 SearchDirsUsage[HitIdx] =
true;
766 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
767 if (UserEntryIdxIt != SearchDirToHSEntry.end())
768 Diags.
Report(
Loc, diag::remark_pp_search_path_usage)
769 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
787 if (MSFE && FE != *MSFE) {
788 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
794static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
795 assert(!Str.empty());
796 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
797 std::copy(Str.begin(), Str.end(), CopyStr);
798 CopyStr[Str.size()] =
'\0';
805 using namespace llvm::sys;
806 path::const_iterator I = path::begin(
Path);
807 path::const_iterator
E = path::end(
Path);
808 IsPrivateHeader =
false;
820 if (*I ==
"Headers") {
822 }
else if (*I ==
"PrivateHeaders") {
824 IsPrivateHeader =
true;
825 }
else if (I->ends_with(
".framework")) {
826 StringRef Name = I->drop_back(10);
828 FrameworkName.clear();
829 FrameworkName.append(Name.begin(), Name.end());
830 IncludeSpelling.clear();
831 IncludeSpelling.append(Name.begin(), Name.end());
833 }
else if (FoundComp >= 2) {
834 IncludeSpelling.push_back(
'/');
835 IncludeSpelling.append(I->begin(), I->end());
840 return !FrameworkName.empty() && FoundComp >= 2;
845 StringRef Includer, StringRef IncludeFilename,
847 bool FoundByHeaderMap =
false) {
848 bool IsIncluderPrivateHeader =
false;
852 FromIncludeSpelling))
854 bool IsIncludeePrivateHeader =
false;
855 bool IsIncludeeInFramework =
857 ToFramework, ToIncludeSpelling);
859 if (!isAngled && !FoundByHeaderMap) {
861 if (IsIncludeeInFramework) {
862 NewInclude += ToIncludeSpelling;
865 NewInclude += IncludeFilename;
868 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
876 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
877 IsIncludeePrivateHeader && FromFramework == ToFramework)
878 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
890 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
893 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
894 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
901 if (IsFrameworkFound)
902 *IsFrameworkFound =
false;
908 if (llvm::sys::path::is_absolute(
Filename)) {
918 RelativePath->clear();
922 return getFileAndSuggestModule(
Filename, IncludeLoc,
nullptr,
924 RequestingModule, SuggestedModule, OpenFile,
937 if (!Includers.empty() && !isAngled) {
940 for (
const auto &IncluderAndDir : Includers) {
944 TmpDir = IncluderAndDir.second.getName();
945 llvm::sys::path::append(TmpDir,
Filename);
954 bool IncluderIsSystemHeader = [&]() {
956 return BuildSystemModule;
958 assert(HFI &&
"includer without file info");
962 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
963 RequestingModule, SuggestedModule)) {
965 assert(
First &&
"only first includer can have no file");
976 assert(FromHFI &&
"includer without file info");
977 unsigned DirInfo = FromHFI->
DirInfo;
979 StringRef Framework = FromHFI->
Framework;
987 StringRef SearchPathRef(IncluderAndDir.second.getName());
989 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
992 RelativePath->clear();
997 IncluderAndDir.second.getName(),
Filename,
1005 if (Diags.
isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1009 if (SuggestedModule) {
1010 MSSuggestedModule = *SuggestedModule;
1035 LookupFileCacheInfo &CacheLookup = LookupFileCache[
Filename];
1040 if (CacheLookup.StartIt == NextIt &&
1041 CacheLookup.RequestingModule == RequestingModule) {
1043 if (CacheLookup.HitIt)
1044 It = CacheLookup.HitIt;
1045 if (CacheLookup.MappedName) {
1054 CacheLookup.reset(RequestingModule, NextIt);
1060 auto Iter = SearchDirHeaderMapIndex.find(
Filename.lower());
1061 if (
Iter == SearchDirHeaderMapIndex.end())
1070 CacheLookup.reset(RequestingModule, NextIt);
1077 bool InUserSpecifiedSystemFramework =
false;
1078 bool IsInHeaderMap =
false;
1079 bool IsFrameworkFoundInDir =
false;
1081 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1082 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1083 IsInHeaderMap, MappedName, OpenFile);
1084 if (!MappedName.empty()) {
1085 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1086 CacheLookup.MappedName =
1087 copyString(MappedName, LookupFileCache.getAllocator());
1093 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1094 if (IsFrameworkFound)
1098 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1108 HFI.
DirInfo = CurDir->getDirCharacteristic();
1118 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1119 if (
Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1129 if (CurDir->isHeaderMap() && isAngled) {
1130 size_t SlashPos =
Filename.find(
'/');
1131 if (SlashPos != StringRef::npos)
1134 if (CurDir->isIndexHeaderMap())
1136 }
else if (CurDir->isFramework()) {
1137 size_t SlashPos =
Filename.find(
'/');
1138 if (SlashPos != StringRef::npos)
1144 if (SuggestedModule)
1145 *SuggestedModule = MSSuggestedModule;
1149 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1150 if (!Includers.empty())
1152 Includers.front().second.getName(),
Filename,
1153 *
File, isAngled, FoundByHeaderMap);
1156 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1164 if (!Includers.empty() && Includers.front().first && !isAngled &&
1168 assert(IncludingHFI &&
"includer without file info");
1171 ScratchFilename += IncludingHFI->
Framework;
1172 ScratchFilename +=
'/';
1176 ScratchFilename, IncludeLoc,
true, FromDir, &CurDir,
1177 Includers.front(), SearchPath, RelativePath, RequestingModule,
1178 SuggestedModule, IsMapped,
nullptr);
1181 File ? &
File->getFileEntry() :
nullptr,
1183 if (SuggestedModule)
1184 *SuggestedModule = MSSuggestedModule;
1188 cacheLookupSuccess(LookupFileCache[
Filename],
1189 LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
1196 if (SuggestedModule)
1197 *SuggestedModule = MSSuggestedModule;
1203 return std::nullopt;
1217 size_t SlashPos =
Filename.find(
'/');
1218 if (SlashPos == StringRef::npos)
1219 return std::nullopt;
1222 StringRef ContextName = ContextFileEnt.
getName();
1225 const unsigned DotFrameworkLen = 10;
1226 auto FrameworkPos = ContextName.find(
".framework");
1227 if (FrameworkPos == StringRef::npos ||
1228 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1229 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1230 return std::nullopt;
1234 DotFrameworkLen + 1);
1237 FrameworkName +=
"Frameworks/";
1239 FrameworkName +=
".framework/";
1242 *FrameworkMap.insert(std::make_pair(
Filename.substr(0, SlashPos),
1246 if (CacheLookup.second.Directory &&
1247 CacheLookup.first().size() == FrameworkName.size() &&
1248 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1249 CacheLookup.first().size()) != 0)
1250 return std::nullopt;
1253 if (!CacheLookup.second.Directory) {
1254 ++NumSubFrameworkLookups;
1259 return std::nullopt;
1263 CacheLookup.second.Directory = Dir;
1268 RelativePath->clear();
1274 HeadersFilename +=
"Headers/";
1276 SearchPath->clear();
1278 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1285 HeadersFilename = FrameworkName;
1286 HeadersFilename +=
"PrivateHeaders/";
1288 SearchPath->clear();
1290 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1297 return std::nullopt;
1302 assert(ContextHFI &&
"context file without file info");
1305 unsigned DirInfo = ContextHFI->
DirInfo;
1308 FrameworkName.pop_back();
1309 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1310 RequestingModule, SuggestedModule,
1312 return std::nullopt;
1331 bool isModuleHeader,
1332 bool isTextualModuleHeader) {
1349 assert(OtherHFI.
External &&
"expected to merge external HFI");
1369 if (FE.
getUID() >= FileInfo.size())
1370 FileInfo.resize(FE.
getUID() + 1);
1376 if (ExternalHFI.IsValid) {
1378 if (ExternalHFI.External)
1393 if (FE.
getUID() >= FileInfo.size())
1394 FileInfo.resize(FE.
getUID() + 1);
1396 HFI = &FileInfo[FE.
getUID()];
1400 if (ExternalHFI.IsValid) {
1402 if (ExternalHFI.External)
1406 }
else if (FE.
getUID() < FileInfo.size()) {
1407 HFI = &FileInfo[FE.
getUID()];
1412 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1418 if (FE.
getUID() < FileInfo.size()) {
1419 HFI = &FileInfo[FE.
getUID()];
1432 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1438 bool isCompilingModuleHeader) {
1440 if (!isCompilingModuleHeader) {
1449 HFI.mergeModuleMembership(Role);
1450 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1455 bool ModulesEnabled,
Module *M,
1456 bool &IsFirstIncludeOfFile) {
1472 IsFirstIncludeOfFile =
false;
1475 auto MaybeReenterImportedFile = [&]() ->
bool {
1565 (FileInfo.
isImport && !MaybeReenterImportedFile()))
1581 ++NumMultiIncludeFileOptzn;
1592 return SearchDirs.capacity()
1593 + llvm::capacity_in_bytes(FileInfo)
1594 + llvm::capacity_in_bytes(HeaderMaps)
1595 + LookupFileCache.getAllocator().getTotalMemory()
1596 + FrameworkMap.getAllocator().getTotalMemory();
1600 return &DL - &*SearchDirs.begin();
1604 return FrameworkNames.insert(Framework).first->first();
1608 auto It = IncludeNames.find(
File);
1609 if (It == IncludeNames.end())
1617 if (!HSOpts->ImplicitModuleMaps)
1625 DirName = llvm::sys::path::parent_path(DirName);
1626 if (DirName.empty())
1636 llvm::sys::path::extension(Dir->getName()) ==
1638 case LMM_NewlyLoaded:
1639 case LMM_AlreadyLoaded:
1642 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1643 DirectoryHasModuleMap[FixUpDirectories[I]] =
true;
1646 case LMM_NoDirectory:
1647 case LMM_InvalidModuleMap:
1657 FixUpDirectories.push_back(*Dir);
1663 bool AllowExcluded)
const {
1693 Module *RequestingModule,
1709 if (SuggestedModule)
1719 if (SuggestedModule)
1727bool HeaderSearch::findUsableModuleForHeader(
1738bool HeaderSearch::findUsableModuleForFrameworkHeader(
1747 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1750 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1754 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1768 StringRef
Filename = llvm::sys::path::filename(
File.getName());
1771 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1772 else if (
Filename ==
"module.modulemap")
1773 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1775 return std::nullopt;
1779 Diags.
Report(diag::warn_deprecated_module_dot_map)
1780 << PrivateFilename << 1
1781 <<
File.getDir().getName().ends_with(
".framework");
1787 FileID ID,
unsigned *Offset,
1788 StringRef OriginalModuleMapFile) {
1795 if (!OriginalModuleMapFile.empty()) {
1799 llvm::sys::path::parent_path(OriginalModuleMapFile));
1802 Dir = FakeFile.getDir();
1805 Dir =
File.getDir();
1808 assert(Dir &&
"parent must exist");
1809 StringRef DirName(Dir->
getName());
1810 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1811 DirName = llvm::sys::path::parent_path(DirName);
1812 if (DirName.ends_with(
".framework"))
1817 assert(Dir &&
"parent must exist");
1821 assert(Dir &&
"module map home directory must exist");
1822 switch (loadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1823 case LMM_AlreadyLoaded:
1824 case LMM_NewlyLoaded:
1826 case LMM_NoDirectory:
1827 case LMM_InvalidModuleMap:
1830 llvm_unreachable(
"Unknown load module map result");
1833HeaderSearch::LoadModuleMapResult
1839 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1840 if (!AddResult.second)
1841 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1844 LoadedModuleMaps[
File] =
false;
1845 return LMM_InvalidModuleMap;
1852 LoadedModuleMaps[
File] =
false;
1853 return LMM_InvalidModuleMap;
1858 return LMM_NewlyLoaded;
1863 if (!HSOpts->ImplicitModuleMaps)
1864 return std::nullopt;
1869 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1870 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1875 ModuleMapFileName = Dir.
getName();
1876 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1878 Diags.
Report(diag::warn_deprecated_module_dot_map)
1879 << ModuleMapFileName << 0 << IsFramework;
1886 ModuleMapFileName = Dir.
getName();
1887 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1888 "module.private.modulemap");
1892 return std::nullopt;
1899 case LMM_InvalidModuleMap:
1901 if (HSOpts->ImplicitModuleMaps)
1902 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1905 case LMM_NoDirectory:
1908 case LMM_AlreadyLoaded:
1909 case LMM_NewlyLoaded:
1916HeaderSearch::LoadModuleMapResult
1922 return LMM_NoDirectory;
1925HeaderSearch::LoadModuleMapResult
1928 auto KnownDir = DirectoryHasModuleMap.find(Dir);
1929 if (KnownDir != DirectoryHasModuleMap.end())
1930 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1934 LoadModuleMapResult
Result =
1935 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir);
1939 if (
Result == LMM_NewlyLoaded)
1940 DirectoryHasModuleMap[Dir] =
true;
1941 else if (
Result == LMM_InvalidModuleMap)
1942 DirectoryHasModuleMap[Dir] =
false;
1945 return LMM_InvalidModuleMap;
1951 if (HSOpts->ImplicitModuleMaps) {
1954 bool IsSystem = DL.isSystemHeaderDirectory();
1955 if (DL.isFramework()) {
1958 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1962 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1964 Dir != DirEnd && !EC; Dir.increment(EC)) {
1965 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1973 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
1980 if (DL.isHeaderMap())
1988 loadSubdirectoryModuleMaps(DL);
1993 llvm::transform(ModMap.
modules(), std::back_inserter(Modules),
1994 [](
const auto &NameAndMod) { return NameAndMod.second; });
1998 if (!HSOpts->ImplicitModuleMaps)
2004 if (!DL.isNormalDir())
2013void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2014 assert(HSOpts->ImplicitModuleMaps &&
2015 "Should not be loading subdirectory module maps");
2024 llvm::sys::path::native(Dir, DirNative);
2026 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2027 Dir != DirEnd && !EC; Dir.increment(EC)) {
2028 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2030 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2042 MainFile, IsAngled);
2046 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2047 bool *IsAngled)
const {
2048 using namespace llvm::sys;
2051 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2052 fs::make_absolute(WorkingDir, FilePath);
2056 path::remove_dots(FilePath,
true);
2057 path::native(FilePath, path::Style::posix);
2060 unsigned BestPrefixLength = 0;
2065 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2066 fs::make_absolute(WorkingDir, Dir);
2067 path::remove_dots(Dir,
true);
2068 for (
auto NI = path::begin(
File), NE = path::end(
File),
2069 DI = path::begin(Dir), DE = path::end(Dir);
2070 NI != NE; ++NI, ++DI) {
2073 unsigned PrefixLength = NI - path::begin(
File);
2074 if (PrefixLength > BestPrefixLength) {
2075 BestPrefixLength = PrefixLength;
2082 if (NI->size() == 1 && DI->size() == 1 &&
2083 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2089 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2090 StringRef NBasename = path::stem(*NI);
2091 StringRef DBasename = path::stem(*DI);
2092 if (DBasename.starts_with(NBasename))
2102 bool BestPrefixIsFramework =
false;
2104 if (DL.isNormalDir()) {
2105 StringRef Dir = DL.getDirRef()->getName();
2106 if (CheckDir(Dir)) {
2108 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2109 BestPrefixIsFramework =
false;
2111 }
else if (DL.isFramework()) {
2112 StringRef Dir = DL.getFrameworkDirRef()->getName();
2113 if (CheckDir(Dir)) {
2116 *IsAngled = BestPrefixLength;
2117 BestPrefixIsFramework =
true;
2124 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2127 BestPrefixIsFramework =
false;
2132 StringRef
Filename =
File.drop_front(BestPrefixLength);
2134 if (!DL.isHeaderMap())
2137 StringRef SpelledFilename =
2138 DL.getHeaderMap()->reverseLookupFilename(
Filename);
2139 if (!SpelledFilename.empty()) {
2141 BestPrefixIsFramework =
false;
2148 bool IsPrivateHeader;
2150 if (BestPrefixIsFramework &&
2155 return path::convert_to_slash(
Filename);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
llvm::MachO::Target Target
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.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
Cached information about one directory (either on disk or in the virtual file system).
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
SrcMgr::CharacteristicKind getDirCharacteristic() const
DirCharacteristic - The type of directory this is, one of the DirType enum values.
OptionalFileEntryRef LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, bool &IsInHeaderMap, SmallVectorImpl< char > &MappedName, bool OpenFile=true) const
LookupFile - Lookup the specified file in this search path, returning it if it exists or returning nu...
bool isFramework() const
isFramework - True if this is a framework directory.
bool isSystemHeaderDirectory() const
Whether this describes a system header directory.
OptionalDirectoryEntryRef getFrameworkDirRef() const
void setSearchedAllModuleMaps(bool SAMM)
Specify whether we have already searched all of the subdirectories for module maps.
bool isHeaderMap() const
isHeaderMap - Return true if this is a header map, not a normal directory.
StringRef getName() const
getName - Return the directory or filename corresponding to this lookup object.
OptionalDirectoryEntryRef getDirRef() const
bool haveSearchedAllModuleMaps() const
Determine whether we have already searched this entire directory for module maps.
const DirectoryEntry * getDir() const
getDir - Return the directory that this entry refers to.
bool isNormalDir() const
isNormalDir - Return true if this is a normal directory, not a header map.
const HeaderMap * getHeaderMap() const
getHeaderMap - Return the directory that this entry refers to.
Abstract interface for external sources of preprocessor information.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::vfs::FileSystem & getVirtualFileSystem() const
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
llvm::ErrorOr< const DirectoryEntry * > getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option.
FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, time_t ModificationTime)
Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...
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)
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.
IdentifierInfo * getPtr() const
bool isID() const
Whether this pointer is currently stored as ID.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
ArrayRef< KnownHeader > findResolvedModulesForHeader(FileEntryRef File) const
Like findAllModulesForHeader, but do not attempt to infer module ownership from umbrella headers if w...
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
bool parseModuleMapFile(FileEntryRef File, bool IsSystem, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Parse the given module map file, and record any modules we encounter.
void setTarget(const TargetInfo &Target)
Set the target information.
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.
ArrayRef< KnownHeader > findAllModulesForHeader(FileEntryRef File)
Retrieve all the modules that contain the given header file.
llvm::iterator_range< module_iterator > modules() const
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.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Result
The result type of a method or function.
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.