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;
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()));
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();
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");
286 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
289 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
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) {
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 =
345 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
354 if (!Dir.isNormalDir())
357 bool IsSystem = Dir.isSystemHeaderDirectory();
362 if (parseModuleMapFile(NormalDir, IsSystem,
363 false) == MMR_NewlyProcessed) {
374 NestedModuleMapDirName = Dir.getDirRef()->getName();
375 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
376 if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,
377 false) == MMR_NewlyProcessed) {
387 if (Dir.haveSearchedAllModuleMaps())
392 if (AllowExtraModuleMapSearch)
393 loadSubdirectoryModuleMaps(Dir);
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();
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();
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");
593 DirName = llvm::sys::path::parent_path(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)
647 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
648 FrameworkName.push_back(
'/');
651 StringRef ModuleName(
Filename.begin(), SlashPos);
652 FrameworkName += ModuleName;
655 FrameworkName +=
".framework/";
659 ++NumFrameworkLookups;
674 SystemFrameworkMarker +=
".system_framework";
675 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
686 RelativePath->clear();
691 unsigned OrigSize = FrameworkName.size();
693 FrameworkName +=
"Headers/";
698 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
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);
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)
893 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
896 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
897 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
904 if (IsFrameworkFound)
905 *IsFrameworkFound =
false;
911 if (llvm::sys::path::is_absolute(
Filename)) {
921 RelativePath->clear();
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();
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)) {
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/";
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;
1206 return std::nullopt;
1210 CacheLookup.second.Directory = Dir;
1215 RelativePath->clear();
1221 HeadersFilename +=
"Headers/";
1223 SearchPath->clear();
1225 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1232 HeadersFilename = FrameworkName;
1233 HeadersFilename +=
"PrivateHeaders/";
1235 SearchPath->clear();
1237 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
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);
1319 if (ExternalHFI.IsValid) {
1321 if (ExternalHFI.External)
1336 if (FE.
getUID() >= FileInfo.size())
1337 FileInfo.resize(FE.
getUID() + 1);
1339 HFI = &FileInfo[FE.
getUID()];
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 {
1508 (FileInfo.
isImport && !MaybeReenterImportedFile()))
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())
1567 DirName = llvm::sys::path::parent_path(DirName);
1568 if (DirName.empty())
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 {
1636 Module *RequestingModule,
1652 if (SuggestedModule)
1662 if (SuggestedModule)
1670bool HeaderSearch::findUsableModuleForHeader(
1681bool HeaderSearch::findUsableModuleForFrameworkHeader(
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());
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;
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) {
1739 if (!OriginalModuleMapFile.empty()) {
1743 llvm::sys::path::parent_path(OriginalModuleMapFile));
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"))
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;
1817 ParsedModuleMaps[
File] =
false;
1818 return MMR_InvalidModuleMap;
1825 ParsedModuleMaps[
File] =
false;
1826 return MMR_InvalidModuleMap;
1831 return MMR_NewlyProcessed;
1837 return std::nullopt;
1842 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1843 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1848 ModuleMapFileName = Dir.
getName();
1849 llvm::sys::path::append(ModuleMapFileName,
"module.map");
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");
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
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,
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;
1982 bool IsSystem = DL.isSystemHeaderDirectory();
1983 if (DL.isFramework()) {
1986 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
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")
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()));
2032 if (!DL.isNormalDir())
2041void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2043 "Should not be loading subdirectory module maps");
2052 llvm::sys::path::native(Dir, DirNative);
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()) {
2170 BestPrefixIsFramework =
false;
2177 bool IsPrivateHeader;
2179 if (BestPrefixIsFramework &&
2184 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.
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, 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.
IdentifierInfo * getPtr() const
bool isID() const
Whether this pointer is currently stored as ID.
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.
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 Dir, FileID ID=FileID(), SourceLocation ExternModuleLoc=SourceLocation())
Parse a module map without creating clang::Module instances.
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.
Module * findOrLoadModule(StringRef Name)
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.