26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/Hashing.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/ADT/STLExtras.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"
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.");
65 assert(
External &&
"We must have an external source if we have a "
66 "controlling macro that is out of date.");
86 : HSOpts(
std::move(HSOpts)), Diags(Diags),
87 FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
88 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,
bool noCurDirSearch,
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 NoCurDirSearch = noCurDirSearch;
117 SearchDirToHSEntry = std::move(searchDirToHSEntry);
119 indexInitialHeaderMaps();
123 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
124 SearchDirs.insert(SearchDirs.begin() + idx, dir);
125 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx,
false);
132 std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
133 for (
unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
135 if (SearchDirsUsage[I]) {
136 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
138 if (UserEntryIdxIt != SearchDirToHSEntry.end())
139 UserEntryUsage[UserEntryIdxIt->second] =
true;
142 return UserEntryUsage;
150 if (!HeaderMaps.empty()) {
151 for (
unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
154 if (HeaderMaps[i].first == FE)
155 return HeaderMaps[i].second.get();
159 HeaderMaps.emplace_back(FE, std::move(HM));
160 return HeaderMaps.back().second.get();
169 for (
auto &HM : HeaderMaps)
170 Names.push_back(std::string(HM.first.getName()));
186 auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName));
187 if (i != HSOpts->PrebuiltModuleFiles.end())
190 if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())
195 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
197 llvm::sys::fs::make_absolute(
Result);
198 if (ModuleName.contains(
':'))
202 llvm::sys::path::append(
Result, ModuleName.split(
':').first +
"-" +
203 ModuleName.split(
':').second +
206 llvm::sys::path::append(
Result, ModuleName +
".pcm");
208 return std::string(
Result);
218 StringRef ModuleMapPath =
ModuleMap->getName();
219 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ?
"" :
getModuleHash();
220 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
222 llvm::sys::fs::make_absolute(CachePath);
223 llvm::sys::path::append(CachePath, ModuleCacheHash);
225 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
233 StringRef ModuleMapPath) {
234 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
238std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
239 StringRef ModuleMapPath,
240 StringRef CachePath) {
243 if (CachePath.empty())
247 llvm::sys::fs::make_absolute(
Result);
249 if (HSOpts->DisableModuleHash) {
250 llvm::sys::path::append(
Result, ModuleName +
".pcm");
260 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
263 llvm::hash_code Hash = llvm::hash_combine(CanonicalPath.str().lower());
266 llvm::APInt(64,
size_t(Hash)).toStringUnsigned(HashStr, 36);
267 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
269 return Result.str().str();
274 bool AllowExtraModuleMapSearch) {
277 if (
Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
280 StringRef SearchName = ModuleName;
282 AllowExtraModuleMapSearch);
292 if (!
Module && SearchName.consume_back(
"_Private"))
294 AllowExtraModuleMapSearch);
295 if (!
Module && SearchName.consume_back(
"Private"))
297 AllowExtraModuleMapSearch);
303 bool AllowExtraModuleMapSearch) {
309 if (Dir.isFramework()) {
314 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
315 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
316 if (
auto FrameworkDir =
319 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
328 if (!Dir.isNormalDir())
331 bool IsSystem = Dir.isSystemHeaderDirectory();
337 false) == LMM_NewlyLoaded) {
348 NestedModuleMapDirName = Dir.getDirRef()->getName();
349 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
351 false) == LMM_NewlyLoaded){
360 if (Dir.haveSearchedAllModuleMaps())
365 if (AllowExtraModuleMapSearch)
366 loadSubdirectoryModuleMaps(Dir);
377void HeaderSearch::indexInitialHeaderMaps() {
378 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
381 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
382 auto &Dir = SearchDirs[i];
387 if (!Dir.isHeaderMap()) {
388 SearchDirHeaderMapIndex = std::move(Index);
389 FirstNonHeaderMapSearchDirIdx = i;
394 auto Callback = [&](StringRef
Filename) {
395 Index.try_emplace(
Filename.lower(), i);
397 Dir.getHeaderMap()->forEachKey(Callback);
412 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
418 bool IsSystemHeaderDir,
Module *RequestingModule,
420 bool CacheFailures ) {
427 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
428 if (EC != llvm::errc::no_such_file_or_directory &&
429 EC != llvm::errc::invalid_argument &&
430 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
431 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
438 if (!findUsableModuleForHeader(
439 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
440 SuggestedModule, IsSystemHeaderDir))
452 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
454 bool OpenFile)
const {
455 InUserSpecifiedSystemFramework =
false;
456 IsInHeaderMap =
false;
463 llvm::sys::path::append(TmpDir,
Filename);
467 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
470 RelativePath->clear();
474 return HS.getFileAndSuggestModule(
476 RequestingModule, SuggestedModule, OpenFile);
480 return DoFrameworkLookup(
Filename, HS, SearchPath, RelativePath,
481 RequestingModule, SuggestedModule,
482 InUserSpecifiedSystemFramework, IsFrameworkFound);
484 assert(
isHeaderMap() &&
"Unknown directory lookup");
491 IsInHeaderMap =
true;
493 auto FixupSearchPathAndFindUsableModule =
496 StringRef SearchPathRef(
getName());
498 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
501 RelativePath->clear();
504 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
505 RequestingModule, SuggestedModule,
515 if (llvm::sys::path::is_relative(Dest)) {
516 MappedName.append(Dest.begin(), Dest.end());
517 Filename = StringRef(MappedName.begin(), MappedName.size());
522 return FixupSearchPathAndFindUsableModule(*Res);
542 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
543 "Not a framework directory");
565 DirName = llvm::sys::path::parent_path(DirName);
576 if (llvm::sys::path::extension(DirName) ==
".framework") {
577 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
578 TopFrameworkDir = *Dir;
582 return TopFrameworkDir;
586 bool HasSuggestedModule) {
587 return HasSuggestedModule ||
597 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
601 size_t SlashPos =
Filename.find(
'/');
602 if (SlashPos == StringRef::npos)
619 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
620 FrameworkName.push_back(
'/');
623 StringRef ModuleName(
Filename.begin(), SlashPos);
624 FrameworkName += ModuleName;
627 FrameworkName +=
".framework/";
631 ++NumFrameworkLookups;
646 SystemFrameworkMarker +=
".system_framework";
647 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
658 RelativePath->clear();
663 unsigned OrigSize = FrameworkName.size();
665 FrameworkName +=
"Headers/";
670 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
679 const char *Private =
"Private";
680 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
681 Private+strlen(Private));
683 SearchPath->insert(SearchPath->begin()+OrigSize, Private,
684 Private+strlen(Private));
693 StringRef FrameworkPath =
File->getDir().getName();
694 bool FoundFramework =
false;
703 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
704 FoundFramework =
true;
709 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
710 if (FrameworkPath.empty())
715 if (FoundFramework) {
716 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
718 SuggestedModule, IsSystem))
721 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
722 SuggestedModule, IsSystem))
731void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
734 CacheLookup.HitIt = HitIt;
735 noteLookupUsage(HitIt.Idx, Loc);
738void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
739 SearchDirsUsage[HitIdx] =
true;
741 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
742 if (UserEntryIdxIt != SearchDirToHSEntry.end())
743 Diags.
Report(Loc, diag::remark_pp_search_path_usage)
744 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
762 if (MSFE && FE != *MSFE) {
763 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
769static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
770 assert(!Str.empty());
771 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
772 std::copy(Str.begin(), Str.end(), CopyStr);
773 CopyStr[Str.size()] =
'\0';
780 using namespace llvm::sys;
781 path::const_iterator I = path::begin(Path);
782 path::const_iterator E = path::end(Path);
783 IsPrivateHeader =
false;
795 if (*I ==
"Headers") {
797 }
else if (*I ==
"PrivateHeaders") {
799 IsPrivateHeader =
true;
800 }
else if (I->endswith(
".framework")) {
801 StringRef Name = I->drop_back(10);
803 FrameworkName.clear();
804 FrameworkName.append(Name.begin(), Name.end());
805 IncludeSpelling.clear();
806 IncludeSpelling.append(Name.begin(), Name.end());
808 }
else if (FoundComp >= 2) {
809 IncludeSpelling.push_back(
'/');
810 IncludeSpelling.append(I->begin(), I->end());
815 return !FrameworkName.empty() && FoundComp >= 2;
820 StringRef Includer, StringRef IncludeFilename,
822 bool FoundByHeaderMap =
false) {
823 bool IsIncluderPrivateHeader =
false;
827 FromIncludeSpelling))
829 bool IsIncludeePrivateHeader =
false;
830 bool IsIncludeeInFramework =
832 ToFramework, ToIncludeSpelling);
834 if (!isAngled && !FoundByHeaderMap) {
836 if (IsIncludeeInFramework) {
837 NewInclude += ToIncludeSpelling;
840 NewInclude += IncludeFilename;
843 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
851 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
852 IsIncludeePrivateHeader && FromFramework == ToFramework)
853 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
865 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
868 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
869 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
876 if (IsFrameworkFound)
877 *IsFrameworkFound =
false;
883 if (llvm::sys::path::is_absolute(
Filename)) {
893 RelativePath->clear();
897 return getFileAndSuggestModule(
Filename, IncludeLoc,
nullptr,
899 RequestingModule, SuggestedModule, OpenFile,
912 if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
915 for (
const auto &IncluderAndDir : Includers) {
919 TmpDir = IncluderAndDir.second.getName();
920 llvm::sys::path::append(TmpDir,
Filename);
929 bool IncluderIsSystemHeader =
933 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
934 RequestingModule, SuggestedModule)) {
936 assert(
First &&
"only first includer can have no file");
947 unsigned DirInfo = FromHFI.
DirInfo;
957 StringRef SearchPathRef(IncluderAndDir.second.getName());
959 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
962 RelativePath->clear();
967 IncluderAndDir.second.getName(),
Filename,
975 if (Diags.
isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
979 if (SuggestedModule) {
980 MSSuggestedModule = *SuggestedModule;
1005 LookupFileCacheInfo &CacheLookup = LookupFileCache[
Filename];
1010 if (CacheLookup.StartIt == NextIt &&
1011 CacheLookup.RequestingModule == RequestingModule) {
1013 if (CacheLookup.HitIt)
1014 It = CacheLookup.HitIt;
1015 if (CacheLookup.MappedName) {
1024 CacheLookup.reset(RequestingModule, NextIt);
1030 auto Iter = SearchDirHeaderMapIndex.find(
Filename.lower());
1031 if (
Iter == SearchDirHeaderMapIndex.end())
1040 CacheLookup.reset(RequestingModule, NextIt);
1047 bool InUserSpecifiedSystemFramework =
false;
1048 bool IsInHeaderMap =
false;
1049 bool IsFrameworkFoundInDir =
false;
1051 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1052 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1053 IsInHeaderMap, MappedName, OpenFile);
1054 if (!MappedName.empty()) {
1055 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1056 CacheLookup.MappedName =
1057 copyString(MappedName, LookupFileCache.getAllocator());
1063 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1064 if (IsFrameworkFound)
1068 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1078 HFI.
DirInfo = CurDir->getDirCharacteristic();
1088 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1089 if (
Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
1099 if (CurDir->isHeaderMap() && isAngled) {
1100 size_t SlashPos =
Filename.find(
'/');
1101 if (SlashPos != StringRef::npos)
1104 if (CurDir->isIndexHeaderMap())
1106 }
else if (CurDir->isFramework()) {
1107 size_t SlashPos =
Filename.find(
'/');
1108 if (SlashPos != StringRef::npos)
1114 if (SuggestedModule)
1115 *SuggestedModule = MSSuggestedModule;
1119 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1120 if (!Includers.empty())
1122 Includers.front().second.getName(),
Filename,
1123 *
File, isAngled, FoundByHeaderMap);
1126 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1134 if (!Includers.empty() && Includers.front().first && !isAngled &&
1139 ScratchFilename += IncludingHFI.
Framework;
1140 ScratchFilename +=
'/';
1144 ScratchFilename, IncludeLoc,
true, FromDir, &CurDir,
1145 Includers.front(), SearchPath, RelativePath, RequestingModule,
1146 SuggestedModule, IsMapped,
nullptr);
1149 File ? &
File->getFileEntry() :
nullptr,
1151 if (SuggestedModule)
1152 *SuggestedModule = MSSuggestedModule;
1156 cacheLookupSuccess(LookupFileCache[
Filename],
1157 LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
1164 if (SuggestedModule)
1165 *SuggestedModule = MSSuggestedModule;
1171 return std::nullopt;
1185 size_t SlashPos =
Filename.find(
'/');
1186 if (SlashPos == StringRef::npos)
1187 return std::nullopt;
1190 StringRef ContextName = ContextFileEnt.
getName();
1193 const unsigned DotFrameworkLen = 10;
1194 auto FrameworkPos = ContextName.find(
".framework");
1195 if (FrameworkPos == StringRef::npos ||
1196 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1197 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1198 return std::nullopt;
1202 DotFrameworkLen + 1);
1205 FrameworkName +=
"Frameworks/";
1207 FrameworkName +=
".framework/";
1210 *FrameworkMap.insert(std::make_pair(
Filename.substr(0, SlashPos),
1214 if (CacheLookup.second.Directory &&
1215 CacheLookup.first().size() == FrameworkName.size() &&
1216 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1217 CacheLookup.first().size()) != 0)
1218 return std::nullopt;
1221 if (!CacheLookup.second.Directory) {
1222 ++NumSubFrameworkLookups;
1227 return std::nullopt;
1231 CacheLookup.second.Directory = Dir;
1236 RelativePath->clear();
1242 HeadersFilename +=
"Headers/";
1244 SearchPath->clear();
1246 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1253 HeadersFilename = FrameworkName;
1254 HeadersFilename +=
"PrivateHeaders/";
1256 SearchPath->clear();
1258 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1265 return std::nullopt;
1276 FrameworkName.pop_back();
1277 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1278 RequestingModule, SuggestedModule,
1280 return std::nullopt;
1293 assert(OtherHFI.
External &&
"expected to merge external HFI");
1316 if (FE.
getUID() >= FileInfo.size())
1317 FileInfo.resize(FE.
getUID() + 1);
1323 if (ExternalHFI.IsValid) {
1325 if (ExternalHFI.External)
1343 if (FE.
getUID() >= FileInfo.size()) {
1346 FileInfo.resize(FE.
getUID() + 1);
1349 HFI = &FileInfo[FE.
getUID()];
1354 if (ExternalHFI.IsValid) {
1356 if (ExternalHFI.External)
1360 }
else if (FE.
getUID() >= FileInfo.size()) {
1363 HFI = &FileInfo[FE.
getUID()];
1377 return HFI->isPragmaOnce || HFI->ControllingMacro ||
1378 HFI->ControllingMacroID;
1384 bool isCompilingModuleHeader) {
1388 if (!isCompilingModuleHeader) {
1389 if (!isModularHeader)
1392 if (HFI && HFI->isModuleHeader)
1397 HFI.isModuleHeader |= isModularHeader;
1398 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1403 bool ModulesEnabled,
Module *M,
1404 bool &IsFirstIncludeOfFile) {
1407 IsFirstIncludeOfFile =
false;
1414 auto TryEnterImported = [&]() ->
bool {
1415 if (!ModulesEnabled)
1436 bool TryEnterHdr =
false;
1475 ++NumMultiIncludeFileOptzn;
1486 return SearchDirs.capacity()
1487 + llvm::capacity_in_bytes(FileInfo)
1488 + llvm::capacity_in_bytes(HeaderMaps)
1489 + LookupFileCache.getAllocator().getTotalMemory()
1490 + FrameworkMap.getAllocator().getTotalMemory();
1494 return &DL - &*SearchDirs.begin();
1498 return FrameworkNames.insert(Framework).first->first();
1502 auto It = IncludeNames.find(
File);
1503 if (It == IncludeNames.end())
1511 if (!HSOpts->ImplicitModuleMaps)
1519 DirName = llvm::sys::path::parent_path(DirName);
1520 if (DirName.empty())
1530 llvm::sys::path::extension(Dir->
getName()) ==
1532 case LMM_NewlyLoaded:
1533 case LMM_AlreadyLoaded:
1536 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1537 DirectoryHasModuleMap[FixUpDirectories[I]] =
true;
1540 case LMM_NoDirectory:
1541 case LMM_InvalidModuleMap:
1551 FixUpDirectories.push_back(*Dir);
1557 bool AllowExcluded)
const {
1587 Module *RequestingModule,
1603 if (SuggestedModule)
1613 if (SuggestedModule)
1621bool HeaderSearch::findUsableModuleForHeader(
1632bool HeaderSearch::findUsableModuleForFrameworkHeader(
1641 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1644 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1648 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1661 StringRef
Filename = llvm::sys::path::filename(
File.getName());
1664 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1665 else if (
Filename ==
"module.modulemap")
1666 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1668 return std::nullopt;
1673 FileID ID,
unsigned *Offset,
1674 StringRef OriginalModuleMapFile) {
1681 if (!OriginalModuleMapFile.empty()) {
1685 llvm::sys::path::parent_path(OriginalModuleMapFile));
1688 Dir = FakeFile.getDir();
1691 Dir =
File.getDir();
1694 assert(Dir &&
"parent must exist");
1695 StringRef DirName(Dir->
getName());
1696 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1697 DirName = llvm::sys::path::parent_path(DirName);
1698 if (DirName.endswith(
".framework"))
1703 assert(Dir &&
"parent must exist");
1707 assert(Dir &&
"module map home directory must exist");
1708 switch (loadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1709 case LMM_AlreadyLoaded:
1710 case LMM_NewlyLoaded:
1712 case LMM_NoDirectory:
1713 case LMM_InvalidModuleMap:
1716 llvm_unreachable(
"Unknown load module map result");
1719HeaderSearch::LoadModuleMapResult
1725 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1726 if (!AddResult.second)
1727 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1730 LoadedModuleMaps[
File] =
false;
1731 return LMM_InvalidModuleMap;
1737 LoadedModuleMaps[
File] =
false;
1738 return LMM_InvalidModuleMap;
1743 return LMM_NewlyLoaded;
1748 if (!HSOpts->ImplicitModuleMaps)
1749 return std::nullopt;
1754 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1755 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1760 ModuleMapFileName = Dir.
getName();
1761 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1768 ModuleMapFileName = Dir.
getName();
1769 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1770 "module.private.modulemap");
1774 return std::nullopt;
1781 case LMM_InvalidModuleMap:
1783 if (HSOpts->ImplicitModuleMaps)
1784 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1787 case LMM_NoDirectory:
1790 case LMM_AlreadyLoaded:
1791 case LMM_NewlyLoaded:
1798HeaderSearch::LoadModuleMapResult
1804 return LMM_NoDirectory;
1807HeaderSearch::LoadModuleMapResult
1810 auto KnownDir = DirectoryHasModuleMap.find(Dir);
1811 if (KnownDir != DirectoryHasModuleMap.end())
1812 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1816 LoadModuleMapResult
Result =
1817 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir);
1821 if (
Result == LMM_NewlyLoaded)
1822 DirectoryHasModuleMap[Dir] =
true;
1823 else if (
Result == LMM_InvalidModuleMap)
1824 DirectoryHasModuleMap[Dir] =
false;
1827 return LMM_InvalidModuleMap;
1833 if (HSOpts->ImplicitModuleMaps) {
1836 bool IsSystem = DL.isSystemHeaderDirectory();
1837 if (DL.isFramework()) {
1840 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1844 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1846 Dir != DirEnd && !EC; Dir.increment(EC)) {
1847 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1855 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
1862 if (DL.isHeaderMap())
1870 loadSubdirectoryModuleMaps(DL);
1875 llvm::transform(ModMap.
modules(), std::back_inserter(Modules),
1876 [](
const auto &NameAndMod) { return NameAndMod.second; });
1880 if (!HSOpts->ImplicitModuleMaps)
1886 if (!DL.isNormalDir())
1895void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
1896 assert(HSOpts->ImplicitModuleMaps &&
1897 "Should not be loading subdirectory module maps");
1906 llvm::sys::path::native(Dir, DirNative);
1908 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
1909 Dir != DirEnd && !EC; Dir.increment(EC)) {
1910 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
1912 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
1924 MainFile, IsAngled);
1928 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
1929 bool *IsAngled)
const {
1930 using namespace llvm::sys;
1936 path::remove_dots(FilePath,
true);
1937 path::native(FilePath, path::Style::posix);
1940 unsigned BestPrefixLength = 0;
1945 if (!WorkingDir.empty() && !path::is_absolute(Dir))
1946 fs::make_absolute(WorkingDir, Dir);
1947 path::remove_dots(Dir,
true);
1948 for (
auto NI = path::begin(
File), NE = path::end(
File),
1949 DI = path::begin(Dir), DE = path::end(Dir);
1950 NI != NE; ++NI, ++DI) {
1953 unsigned PrefixLength = NI - path::begin(
File);
1954 if (PrefixLength > BestPrefixLength) {
1955 BestPrefixLength = PrefixLength;
1962 if (NI->size() == 1 && DI->size() == 1 &&
1963 path::is_separator(NI->front()) && path::is_separator(DI->front()))
1969 if (NI->endswith(
".sdk") && DI->endswith(
".sdk")) {
1970 StringRef NBasename = path::stem(*NI);
1971 StringRef DBasename = path::stem(*DI);
1972 if (DBasename.startswith(NBasename))
1982 bool BestPrefixIsFramework =
false;
1984 if (DL.isNormalDir()) {
1985 StringRef Dir = DL.getDirRef()->getName();
1986 if (CheckDir(Dir)) {
1988 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
1989 BestPrefixIsFramework =
false;
1991 }
else if (DL.isFramework()) {
1992 StringRef Dir = DL.getFrameworkDirRef()->getName();
1993 if (CheckDir(Dir)) {
1996 *IsAngled = BestPrefixLength;
1997 BestPrefixIsFramework =
true;
2004 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2007 BestPrefixIsFramework =
false;
2012 StringRef
Filename =
File.drop_front(BestPrefixLength);
2014 if (!DL.isHeaderMap())
2017 StringRef SpelledFilename =
2018 DL.getHeaderMap()->reverseLookupFilename(
Filename);
2019 if (!SpelledFilename.empty()) {
2021 BestPrefixIsFramework =
false;
2028 bool IsPrivateHeader;
2030 if (BestPrefixIsFramework &&
2035 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.
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).
StringRef getName() const
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...
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
Get the module map file that (along with the module name) uniquely identifies this module.
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.
@ 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.
@ 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.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
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.