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())
271 if (HSOpts->DisableModuleHash) {
272 llvm::sys::path::append(
Result, ModuleName +
".pcm");
282 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
285 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
288 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
289 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
291 return Result.str().str();
296 bool AllowExtraModuleMapSearch) {
299 if (
Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
302 StringRef SearchName = ModuleName;
304 AllowExtraModuleMapSearch);
314 if (!
Module && SearchName.consume_back(
"_Private"))
316 AllowExtraModuleMapSearch);
317 if (!
Module && SearchName.consume_back(
"Private"))
319 AllowExtraModuleMapSearch);
325 bool AllowExtraModuleMapSearch) {
331 if (Dir.isFramework()) {
336 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
337 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
338 if (
auto FrameworkDir =
341 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
350 if (!Dir.isNormalDir())
353 bool IsSystem = Dir.isSystemHeaderDirectory();
359 false) == LMM_NewlyLoaded) {
370 NestedModuleMapDirName = Dir.getDirRef()->getName();
371 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
373 false) == LMM_NewlyLoaded){
380 if (HSOpts->AllowModuleMapSubdirectorySearch) {
383 if (Dir.haveSearchedAllModuleMaps())
388 if (AllowExtraModuleMapSearch)
389 loadSubdirectoryModuleMaps(Dir);
401void HeaderSearch::indexInitialHeaderMaps() {
402 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
405 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
406 auto &Dir = SearchDirs[i];
411 if (!Dir.isHeaderMap()) {
412 SearchDirHeaderMapIndex = std::move(Index);
413 FirstNonHeaderMapSearchDirIdx = i;
418 auto Callback = [&](StringRef
Filename) {
419 Index.try_emplace(
Filename.lower(), i);
421 Dir.getHeaderMap()->forEachKey(Callback);
436 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
442 bool IsSystemHeaderDir,
Module *RequestingModule,
444 bool CacheFailures ) {
451 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
452 if (EC != llvm::errc::no_such_file_or_directory &&
453 EC != llvm::errc::invalid_argument &&
454 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
455 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
462 if (!findUsableModuleForHeader(
463 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
464 SuggestedModule, IsSystemHeaderDir))
476 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
478 bool OpenFile)
const {
479 InUserSpecifiedSystemFramework =
false;
480 IsInHeaderMap =
false;
487 llvm::sys::path::append(TmpDir,
Filename);
491 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
494 RelativePath->clear();
498 return HS.getFileAndSuggestModule(
500 RequestingModule, SuggestedModule, OpenFile);
504 return DoFrameworkLookup(
Filename, HS, SearchPath, RelativePath,
505 RequestingModule, SuggestedModule,
506 InUserSpecifiedSystemFramework, IsFrameworkFound);
508 assert(
isHeaderMap() &&
"Unknown directory lookup");
515 IsInHeaderMap =
true;
517 auto FixupSearchPathAndFindUsableModule =
520 StringRef SearchPathRef(
getName());
522 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
525 RelativePath->clear();
528 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
529 RequestingModule, SuggestedModule,
539 if (llvm::sys::path::is_relative(Dest)) {
540 MappedName.append(Dest.begin(), Dest.end());
541 Filename = StringRef(MappedName.begin(), MappedName.size());
546 return FixupSearchPathAndFindUsableModule(*Res);
566 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
567 "Not a framework directory");
589 DirName = llvm::sys::path::parent_path(DirName);
600 if (llvm::sys::path::extension(DirName) ==
".framework") {
601 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
602 TopFrameworkDir = *Dir;
606 return TopFrameworkDir;
610 bool HasSuggestedModule) {
611 return HasSuggestedModule ||
621 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
625 size_t SlashPos =
Filename.find(
'/');
626 if (SlashPos == StringRef::npos)
643 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
644 FrameworkName.push_back(
'/');
647 StringRef ModuleName(
Filename.begin(), SlashPos);
648 FrameworkName += ModuleName;
651 FrameworkName +=
".framework/";
655 ++NumFrameworkLookups;
670 SystemFrameworkMarker +=
".system_framework";
671 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
682 RelativePath->clear();
687 unsigned OrigSize = FrameworkName.size();
689 FrameworkName +=
"Headers/";
694 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
703 const char *
Private =
"Private";
704 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
707 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
717 StringRef FrameworkPath =
File->getDir().getName();
718 bool FoundFramework =
false;
727 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
728 FoundFramework =
true;
733 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
734 if (FrameworkPath.empty())
739 if (FoundFramework) {
740 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
742 SuggestedModule, IsSystem))
745 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
746 SuggestedModule, IsSystem))
755void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
758 CacheLookup.HitIt = HitIt;
759 noteLookupUsage(HitIt.Idx,
Loc);
763 SearchDirsUsage[HitIdx] =
true;
765 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
766 if (UserEntryIdxIt != SearchDirToHSEntry.end())
767 Diags.
Report(
Loc, diag::remark_pp_search_path_usage)
768 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
786 if (MSFE && FE != *MSFE) {
787 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
793static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
794 assert(!Str.empty());
795 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
796 std::copy(Str.begin(), Str.end(), CopyStr);
797 CopyStr[Str.size()] =
'\0';
804 using namespace llvm::sys;
805 path::const_iterator I = path::begin(
Path);
806 path::const_iterator
E = path::end(
Path);
807 IsPrivateHeader =
false;
819 if (*I ==
"Headers") {
821 }
else if (*I ==
"PrivateHeaders") {
823 IsPrivateHeader =
true;
824 }
else if (I->ends_with(
".framework")) {
825 StringRef Name = I->drop_back(10);
827 FrameworkName.clear();
828 FrameworkName.append(Name.begin(), Name.end());
829 IncludeSpelling.clear();
830 IncludeSpelling.append(Name.begin(), Name.end());
832 }
else if (FoundComp >= 2) {
833 IncludeSpelling.push_back(
'/');
834 IncludeSpelling.append(I->begin(), I->end());
839 return !FrameworkName.empty() && FoundComp >= 2;
844 StringRef Includer, StringRef IncludeFilename,
846 bool FoundByHeaderMap =
false) {
847 bool IsIncluderPrivateHeader =
false;
851 FromIncludeSpelling))
853 bool IsIncludeePrivateHeader =
false;
854 bool IsIncludeeInFramework =
856 ToFramework, ToIncludeSpelling);
858 if (!isAngled && !FoundByHeaderMap) {
860 if (IsIncludeeInFramework) {
861 NewInclude += ToIncludeSpelling;
864 NewInclude += IncludeFilename;
867 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
875 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
876 IsIncludeePrivateHeader && FromFramework == ToFramework)
877 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
889 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
892 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
893 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
900 if (IsFrameworkFound)
901 *IsFrameworkFound =
false;
907 if (llvm::sys::path::is_absolute(
Filename)) {
917 RelativePath->clear();
921 return getFileAndSuggestModule(
Filename, IncludeLoc,
nullptr,
923 RequestingModule, SuggestedModule, OpenFile,
936 if (!Includers.empty() && !isAngled) {
939 for (
const auto &IncluderAndDir : Includers) {
943 TmpDir = IncluderAndDir.second.getName();
944 llvm::sys::path::append(TmpDir,
Filename);
953 bool IncluderIsSystemHeader = [&]() {
955 return BuildSystemModule;
957 assert(HFI &&
"includer without file info");
961 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
962 RequestingModule, SuggestedModule)) {
964 assert(
First &&
"only first includer can have no file");
975 assert(FromHFI &&
"includer without file info");
976 unsigned DirInfo = FromHFI->
DirInfo;
978 StringRef Framework = FromHFI->
Framework;
986 StringRef SearchPathRef(IncluderAndDir.second.getName());
988 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
991 RelativePath->clear();
996 IncluderAndDir.second.getName(),
Filename,
1004 if (Diags.
isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1008 if (SuggestedModule) {
1009 MSSuggestedModule = *SuggestedModule;
1034 LookupFileCacheInfo &CacheLookup = LookupFileCache[
Filename];
1039 if (CacheLookup.StartIt == NextIt &&
1040 CacheLookup.RequestingModule == RequestingModule) {
1042 if (CacheLookup.HitIt)
1043 It = CacheLookup.HitIt;
1044 if (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);
1107 HFI.
DirInfo = CurDir->getDirCharacteristic();
1117 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1118 if (
Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1128 if (CurDir->isHeaderMap() && isAngled) {
1129 size_t SlashPos =
Filename.find(
'/');
1130 if (SlashPos != StringRef::npos)
1133 if (CurDir->isIndexHeaderMap())
1135 }
else if (CurDir->isFramework()) {
1136 size_t SlashPos =
Filename.find(
'/');
1137 if (SlashPos != StringRef::npos)
1143 if (SuggestedModule)
1144 *SuggestedModule = MSSuggestedModule;
1148 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1149 if (!Includers.empty())
1151 Includers.front().second.getName(),
Filename,
1152 *
File, isAngled, FoundByHeaderMap);
1155 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1163 if (!Includers.empty() && Includers.front().first && !isAngled &&
1167 assert(IncludingHFI &&
"includer without file info");
1170 ScratchFilename += IncludingHFI->
Framework;
1171 ScratchFilename +=
'/';
1175 ScratchFilename, IncludeLoc,
true, FromDir, &CurDir,
1176 Includers.front(), SearchPath, RelativePath, RequestingModule,
1177 SuggestedModule, IsMapped,
nullptr);
1180 File ? &
File->getFileEntry() :
nullptr,
1182 if (SuggestedModule)
1183 *SuggestedModule = MSSuggestedModule;
1187 cacheLookupSuccess(LookupFileCache[
Filename],
1188 LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
1195 if (SuggestedModule)
1196 *SuggestedModule = MSSuggestedModule;
1202 return std::nullopt;
1216 size_t SlashPos =
Filename.find(
'/');
1217 if (SlashPos == StringRef::npos)
1218 return std::nullopt;
1221 StringRef ContextName = ContextFileEnt.
getName();
1224 const unsigned DotFrameworkLen = 10;
1225 auto FrameworkPos = ContextName.find(
".framework");
1226 if (FrameworkPos == StringRef::npos ||
1227 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1228 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1229 return std::nullopt;
1233 DotFrameworkLen + 1);
1236 FrameworkName +=
"Frameworks/";
1238 FrameworkName +=
".framework/";
1241 *FrameworkMap.insert(std::make_pair(
Filename.substr(0, SlashPos),
1245 if (CacheLookup.second.Directory &&
1246 CacheLookup.first().size() == FrameworkName.size() &&
1247 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1248 CacheLookup.first().size()) != 0)
1249 return std::nullopt;
1252 if (!CacheLookup.second.Directory) {
1253 ++NumSubFrameworkLookups;
1258 return std::nullopt;
1262 CacheLookup.second.Directory = Dir;
1267 RelativePath->clear();
1273 HeadersFilename +=
"Headers/";
1275 SearchPath->clear();
1277 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1284 HeadersFilename = FrameworkName;
1285 HeadersFilename +=
"PrivateHeaders/";
1287 SearchPath->clear();
1289 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1296 return std::nullopt;
1301 assert(ContextHFI &&
"context file without file info");
1304 unsigned DirInfo = ContextHFI->
DirInfo;
1307 FrameworkName.pop_back();
1308 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1309 RequestingModule, SuggestedModule,
1311 return std::nullopt;
1330 bool isModuleHeader,
1331 bool isTextualModuleHeader) {
1348 assert(OtherHFI.
External &&
"expected to merge external HFI");
1368 if (FE.
getUID() >= FileInfo.size())
1369 FileInfo.resize(FE.
getUID() + 1);
1375 if (ExternalHFI.IsValid) {
1377 if (ExternalHFI.External)
1392 if (FE.
getUID() >= FileInfo.size())
1393 FileInfo.resize(FE.
getUID() + 1);
1395 HFI = &FileInfo[FE.
getUID()];
1399 if (ExternalHFI.IsValid) {
1401 if (ExternalHFI.External)
1405 }
else if (FE.
getUID() < FileInfo.size()) {
1406 HFI = &FileInfo[FE.
getUID()];
1411 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1417 if (FE.
getUID() < FileInfo.size()) {
1418 HFI = &FileInfo[FE.
getUID()];
1431 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1437 bool isCompilingModuleHeader) {
1439 if (!isCompilingModuleHeader) {
1448 HFI.mergeModuleMembership(Role);
1449 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1454 bool ModulesEnabled,
Module *M,
1455 bool &IsFirstIncludeOfFile) {
1471 IsFirstIncludeOfFile =
false;
1474 auto MaybeReenterImportedFile = [&]() ->
bool {
1564 (FileInfo.
isImport && !MaybeReenterImportedFile()))
1580 ++NumMultiIncludeFileOptzn;
1591 return SearchDirs.capacity()
1592 + llvm::capacity_in_bytes(FileInfo)
1593 + llvm::capacity_in_bytes(HeaderMaps)
1594 + LookupFileCache.getAllocator().getTotalMemory()
1595 + FrameworkMap.getAllocator().getTotalMemory();
1599 return &DL - &*SearchDirs.begin();
1603 return FrameworkNames.insert(Framework).first->first();
1607 auto It = IncludeNames.find(
File);
1608 if (It == IncludeNames.end())
1616 if (!HSOpts->ImplicitModuleMaps)
1624 DirName = llvm::sys::path::parent_path(DirName);
1625 if (DirName.empty())
1635 llvm::sys::path::extension(Dir->getName()) ==
1637 case LMM_NewlyLoaded:
1638 case LMM_AlreadyLoaded:
1641 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1642 DirectoryHasModuleMap[FixUpDirectories[I]] =
true;
1645 case LMM_NoDirectory:
1646 case LMM_InvalidModuleMap:
1656 FixUpDirectories.push_back(*Dir);
1662 bool AllowExcluded)
const {
1692 Module *RequestingModule,
1708 if (SuggestedModule)
1718 if (SuggestedModule)
1726bool HeaderSearch::findUsableModuleForHeader(
1737bool HeaderSearch::findUsableModuleForFrameworkHeader(
1746 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1749 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1753 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1767 StringRef
Filename = llvm::sys::path::filename(
File.getName());
1770 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1771 else if (
Filename ==
"module.modulemap")
1772 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1774 return std::nullopt;
1778 Diags.
Report(diag::warn_deprecated_module_dot_map)
1779 << PrivateFilename << 1
1780 <<
File.getDir().getName().ends_with(
".framework");
1786 FileID ID,
unsigned *Offset,
1787 StringRef OriginalModuleMapFile) {
1794 if (!OriginalModuleMapFile.empty()) {
1798 llvm::sys::path::parent_path(OriginalModuleMapFile));
1801 Dir = FakeFile.getDir();
1804 Dir =
File.getDir();
1807 assert(Dir &&
"parent must exist");
1808 StringRef DirName(Dir->
getName());
1809 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1810 DirName = llvm::sys::path::parent_path(DirName);
1811 if (DirName.ends_with(
".framework"))
1816 assert(Dir &&
"parent must exist");
1820 assert(Dir &&
"module map home directory must exist");
1821 switch (loadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1822 case LMM_AlreadyLoaded:
1823 case LMM_NewlyLoaded:
1825 case LMM_NoDirectory:
1826 case LMM_InvalidModuleMap:
1829 llvm_unreachable(
"Unknown load module map result");
1832HeaderSearch::LoadModuleMapResult
1838 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1839 if (!AddResult.second)
1840 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1843 LoadedModuleMaps[
File] =
false;
1844 return LMM_InvalidModuleMap;
1851 LoadedModuleMaps[
File] =
false;
1852 return LMM_InvalidModuleMap;
1857 return LMM_NewlyLoaded;
1862 if (!HSOpts->ImplicitModuleMaps)
1863 return std::nullopt;
1868 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1869 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1874 ModuleMapFileName = Dir.
getName();
1875 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1877 Diags.
Report(diag::warn_deprecated_module_dot_map)
1878 << ModuleMapFileName << 0 << IsFramework;
1885 ModuleMapFileName = Dir.
getName();
1886 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1887 "module.private.modulemap");
1891 return std::nullopt;
1898 case LMM_InvalidModuleMap:
1900 if (HSOpts->ImplicitModuleMaps)
1901 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1904 case LMM_NoDirectory:
1907 case LMM_AlreadyLoaded:
1908 case LMM_NewlyLoaded:
1915HeaderSearch::LoadModuleMapResult
1921 return LMM_NoDirectory;
1924HeaderSearch::LoadModuleMapResult
1927 auto KnownDir = DirectoryHasModuleMap.find(Dir);
1928 if (KnownDir != DirectoryHasModuleMap.end())
1929 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1933 LoadModuleMapResult
Result =
1934 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir);
1938 if (
Result == LMM_NewlyLoaded)
1939 DirectoryHasModuleMap[Dir] =
true;
1940 else if (
Result == LMM_InvalidModuleMap)
1941 DirectoryHasModuleMap[Dir] =
false;
1944 return LMM_InvalidModuleMap;
1950 if (HSOpts->ImplicitModuleMaps) {
1953 bool IsSystem = DL.isSystemHeaderDirectory();
1954 if (DL.isFramework()) {
1957 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1961 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1963 Dir != DirEnd && !EC; Dir.increment(EC)) {
1964 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1972 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
1979 if (DL.isHeaderMap())
1987 loadSubdirectoryModuleMaps(DL);
1992 llvm::transform(ModMap.
modules(), std::back_inserter(Modules),
1993 [](
const auto &NameAndMod) { return NameAndMod.second; });
1997 if (!HSOpts->ImplicitModuleMaps)
2003 if (!DL.isNormalDir())
2012void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2013 assert(HSOpts->ImplicitModuleMaps &&
2014 "Should not be loading subdirectory module maps");
2023 llvm::sys::path::native(Dir, DirNative);
2025 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2026 Dir != DirEnd && !EC; Dir.increment(EC)) {
2027 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2029 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2041 MainFile, IsAngled);
2045 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2046 bool *IsAngled)
const {
2047 using namespace llvm::sys;
2050 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2051 fs::make_absolute(WorkingDir, FilePath);
2055 path::remove_dots(FilePath,
true);
2056 path::native(FilePath, path::Style::posix);
2059 unsigned BestPrefixLength = 0;
2064 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2065 fs::make_absolute(WorkingDir, Dir);
2066 path::remove_dots(Dir,
true);
2067 for (
auto NI = path::begin(
File), NE = path::end(
File),
2068 DI = path::begin(Dir), DE = path::end(Dir);
2069 NI != NE; ++NI, ++DI) {
2072 unsigned PrefixLength = NI - path::begin(
File);
2073 if (PrefixLength > BestPrefixLength) {
2074 BestPrefixLength = PrefixLength;
2081 if (NI->size() == 1 && DI->size() == 1 &&
2082 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2088 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2089 StringRef NBasename = path::stem(*NI);
2090 StringRef DBasename = path::stem(*DI);
2091 if (DBasename.starts_with(NBasename))
2101 bool BestPrefixIsFramework =
false;
2103 if (DL.isNormalDir()) {
2104 StringRef Dir = DL.getDirRef()->getName();
2105 if (CheckDir(Dir)) {
2107 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2108 BestPrefixIsFramework =
false;
2110 }
else if (DL.isFramework()) {
2111 StringRef Dir = DL.getFrameworkDirRef()->getName();
2112 if (CheckDir(Dir)) {
2115 *IsAngled = BestPrefixLength;
2116 BestPrefixIsFramework =
true;
2123 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2126 BestPrefixIsFramework =
false;
2131 StringRef
Filename =
File.drop_front(BestPrefixLength);
2133 if (!DL.isHeaderMap())
2136 StringRef SpelledFilename =
2137 DL.getHeaderMap()->reverseLookupFilename(
Filename);
2138 if (!SpelledFilename.empty()) {
2140 BestPrefixIsFramework =
false;
2147 bool IsPrivateHeader;
2149 if (BestPrefixIsFramework &&
2154 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.