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);
224 std::string FileName =
225 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
226 if (!FileName.empty() &&
getFileMgr().getFile(FileName))
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.getFrameworkDir()->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.getDir()->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);
413 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
419 bool IsSystemHeaderDir,
Module *RequestingModule,
421 bool CacheFailures ) {
428 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
429 if (EC != llvm::errc::no_such_file_or_directory &&
430 EC != llvm::errc::invalid_argument &&
431 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
432 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
433 << FileName << EC.message();
439 if (!findUsableModuleForHeader(
440 &
File->getFileEntry(), Dir ? Dir :
File->getFileEntry().getDir(),
441 RequestingModule, SuggestedModule, IsSystemHeaderDir))
453 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
455 bool OpenFile)
const {
456 InUserSpecifiedSystemFramework =
false;
457 IsInHeaderMap =
false;
464 llvm::sys::path::append(TmpDir,
Filename);
468 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
471 RelativePath->clear();
475 return HS.getFileAndSuggestModule(
477 RequestingModule, SuggestedModule, OpenFile);
481 return DoFrameworkLookup(
Filename, HS, SearchPath, RelativePath,
482 RequestingModule, SuggestedModule,
483 InUserSpecifiedSystemFramework, IsFrameworkFound);
485 assert(
isHeaderMap() &&
"Unknown directory lookup");
492 IsInHeaderMap =
true;
494 auto FixupSearchPath = [&]() {
496 StringRef SearchPathRef(
getName());
498 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
501 RelativePath->clear();
509 if (llvm::sys::path::is_relative(Dest)) {
510 MappedName.append(Dest.begin(), Dest.end());
511 Filename = StringRef(MappedName.begin(), MappedName.size());
537 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
538 "Not a framework directory");
560 DirName = llvm::sys::path::parent_path(DirName);
571 if (llvm::sys::path::extension(DirName) ==
".framework") {
572 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
573 TopFrameworkDir = *Dir;
577 return TopFrameworkDir;
581 bool HasSuggestedModule) {
582 return HasSuggestedModule ||
592 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
596 size_t SlashPos =
Filename.find(
'/');
597 if (SlashPos == StringRef::npos)
614 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
615 FrameworkName.push_back(
'/');
618 StringRef ModuleName(
Filename.begin(), SlashPos);
619 FrameworkName += ModuleName;
622 FrameworkName +=
".framework/";
626 ++NumFrameworkLookups;
641 SystemFrameworkMarker +=
".system_framework";
642 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
653 RelativePath->clear();
658 unsigned OrigSize = FrameworkName.size();
660 FrameworkName +=
"Headers/";
665 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
674 const char *Private =
"Private";
675 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
676 Private+strlen(Private));
678 SearchPath->insert(SearchPath->begin()+OrigSize, Private,
679 Private+strlen(Private));
688 StringRef FrameworkPath =
File->getFileEntry().getDir()->getName();
689 bool FoundFramework =
false;
698 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
699 FoundFramework =
true;
704 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
705 if (FrameworkPath.empty())
710 if (FoundFramework) {
711 if (!HS.findUsableModuleForFrameworkHeader(
712 &
File->getFileEntry(), FrameworkPath, RequestingModule,
713 SuggestedModule, IsSystem))
716 if (!HS.findUsableModuleForHeader(&
File->getFileEntry(),
getDir(),
717 RequestingModule, SuggestedModule,
727void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
730 CacheLookup.HitIt = HitIt;
731 noteLookupUsage(HitIt.Idx, Loc);
734void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
735 SearchDirsUsage[HitIdx] =
true;
737 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
738 if (UserEntryIdxIt != SearchDirToHSEntry.end())
739 Diags.
Report(Loc, diag::remark_pp_search_path_usage)
740 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
757 if (MSFE && FE != MSFE) {
758 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
764static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
765 assert(!Str.empty());
766 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
767 std::copy(Str.begin(), Str.end(), CopyStr);
768 CopyStr[Str.size()] =
'\0';
775 using namespace llvm::sys;
776 path::const_iterator I = path::begin(Path);
777 path::const_iterator E = path::end(Path);
778 IsPrivateHeader =
false;
790 if (*I ==
"Headers") {
792 }
else if (*I ==
"PrivateHeaders") {
794 IsPrivateHeader =
true;
795 }
else if (I->endswith(
".framework")) {
796 StringRef Name = I->drop_back(10);
798 FrameworkName.clear();
799 FrameworkName.append(Name.begin(), Name.end());
800 IncludeSpelling.clear();
801 IncludeSpelling.append(Name.begin(), Name.end());
803 }
else if (FoundComp >= 2) {
804 IncludeSpelling.push_back(
'/');
805 IncludeSpelling.append(I->begin(), I->end());
810 return !FrameworkName.empty() && FoundComp >= 2;
815 StringRef Includer, StringRef IncludeFilename,
816 const FileEntry *IncludeFE,
bool isAngled =
false,
817 bool FoundByHeaderMap =
false) {
818 bool IsIncluderPrivateHeader =
false;
822 FromIncludeSpelling))
824 bool IsIncludeePrivateHeader =
false;
825 bool IsIncludeeInFramework =
827 ToFramework, ToIncludeSpelling);
829 if (!isAngled && !FoundByHeaderMap) {
831 if (IsIncludeeInFramework) {
832 NewInclude += ToIncludeSpelling;
835 NewInclude += IncludeFilename;
838 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
846 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
847 IsIncludeePrivateHeader && FromFramework == ToFramework)
848 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
860 ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
863 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
864 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
871 if (IsFrameworkFound)
872 *IsFrameworkFound =
false;
878 if (llvm::sys::path::is_absolute(
Filename)) {
888 RelativePath->clear();
892 return getFileAndSuggestModule(
Filename, IncludeLoc,
nullptr,
894 RequestingModule, SuggestedModule, OpenFile,
907 if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
910 for (
const auto &IncluderAndDir : Includers) {
911 const FileEntry *Includer = IncluderAndDir.first;
915 TmpDir = IncluderAndDir.second->getName();
916 TmpDir.push_back(
'/');
926 bool IncluderIsSystemHeader =
930 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
931 RequestingModule, SuggestedModule)) {
933 assert(
First &&
"only first includer can have no file");
944 unsigned DirInfo = FromHFI.
DirInfo;
954 StringRef SearchPathRef(IncluderAndDir.second->getName());
956 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
959 RelativePath->clear();
964 IncluderAndDir.second->getName(),
Filename,
965 &FE->getFileEntry());
972 if (Diags.
isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
976 if (SuggestedModule) {
977 MSSuggestedModule = *SuggestedModule;
1002 LookupFileCacheInfo &CacheLookup = LookupFileCache[
Filename];
1007 if (CacheLookup.StartIt == NextIt) {
1009 if (CacheLookup.HitIt)
1010 It = CacheLookup.HitIt;
1011 if (CacheLookup.MappedName) {
1020 CacheLookup.reset(NextIt);
1026 auto Iter = SearchDirHeaderMapIndex.find(
Filename.lower());
1027 if (Iter == SearchDirHeaderMapIndex.end())
1036 CacheLookup.reset(NextIt);
1042 bool InUserSpecifiedSystemFramework =
false;
1043 bool IsInHeaderMap =
false;
1044 bool IsFrameworkFoundInDir =
false;
1046 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1047 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1048 IsInHeaderMap, MappedName, OpenFile);
1049 if (!MappedName.empty()) {
1050 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1051 CacheLookup.MappedName =
1052 copyString(MappedName, LookupFileCache.getAllocator());
1058 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1059 if (IsFrameworkFound)
1063 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1069 const auto FE = &
File->getFileEntry();
1074 HFI.
DirInfo = CurDir->getDirCharacteristic();
1084 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1085 if (
Filename.startswith(SystemHeaderPrefixes[j-1].first)) {
1095 if (CurDir->isHeaderMap() && isAngled) {
1096 size_t SlashPos =
Filename.find(
'/');
1097 if (SlashPos != StringRef::npos)
1100 if (CurDir->isIndexHeaderMap())
1102 }
else if (CurDir->isFramework()) {
1103 size_t SlashPos =
Filename.find(
'/');
1104 if (SlashPos != StringRef::npos)
1110 &
File->getFileEntry(), IncludeLoc)) {
1111 if (SuggestedModule)
1112 *SuggestedModule = MSSuggestedModule;
1116 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1117 if (!Includers.empty())
1119 Diags, IncludeLoc, Includers.front().second->getName(),
Filename,
1120 &
File->getFileEntry(), isAngled, FoundByHeaderMap);
1123 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1131 if (!Includers.empty() && Includers.front().first && !isAngled &&
1136 ScratchFilename += IncludingHFI.
Framework;
1137 ScratchFilename +=
'/';
1141 ScratchFilename, IncludeLoc,
true, FromDir, &CurDir,
1142 Includers.front(), SearchPath, RelativePath, RequestingModule,
1143 SuggestedModule, IsMapped,
nullptr);
1146 File ? &
File->getFileEntry() :
nullptr,
1148 if (SuggestedModule)
1149 *SuggestedModule = MSSuggestedModule;
1153 cacheLookupSuccess(LookupFileCache[
Filename],
1154 LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
1161 nullptr, IncludeLoc)) {
1162 if (SuggestedModule)
1163 *SuggestedModule = MSSuggestedModule;
1169 return std::nullopt;
1181 assert(ContextFileEnt &&
"No context file?");
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->getFileEntry(), 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);
1321 if (ExternalSource && !HFI->
Resolved) {
1323 if (ExternalHFI.IsValid) {
1325 if (ExternalHFI.External)
1339 bool WantExternal)
const {
1343 if (ExternalSource) {
1344 if (FE->
getUID() >= FileInfo.size()) {
1347 FileInfo.resize(FE->
getUID() + 1);
1350 HFI = &FileInfo[FE->
getUID()];
1355 if (ExternalHFI.IsValid) {
1357 if (ExternalHFI.External)
1361 }
else if (FE->
getUID() >= FileInfo.size()) {
1364 HFI = &FileInfo[FE->
getUID()];
1378 return HFI->isPragmaOnce || HFI->ControllingMacro ||
1379 HFI->ControllingMacroID;
1385 bool isCompilingModuleHeader) {
1389 if (!isCompilingModuleHeader) {
1390 if (!isModularHeader)
1393 if (HFI && HFI->isModuleHeader)
1398 HFI.isModuleHeader |= isModularHeader;
1399 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1404 bool ModulesEnabled,
Module *M,
1405 bool &IsFirstIncludeOfFile) {
1408 IsFirstIncludeOfFile =
false;
1415 auto TryEnterImported = [&]() ->
bool {
1416 if (!ModulesEnabled)
1437 bool TryEnterHdr =
false;
1476 ++NumMultiIncludeFileOptzn;
1487 return SearchDirs.capacity()
1488 + llvm::capacity_in_bytes(FileInfo)
1489 + llvm::capacity_in_bytes(HeaderMaps)
1490 + LookupFileCache.getAllocator().getTotalMemory()
1491 + FrameworkMap.getAllocator().getTotalMemory();
1495 return &DL - &*SearchDirs.begin();
1499 return FrameworkNames.insert(Framework).first->first();
1503 auto It = IncludeNames.find(
File);
1504 if (It == IncludeNames.end())
1512 if (!HSOpts->ImplicitModuleMaps)
1517 StringRef DirName = FileName;
1520 DirName = llvm::sys::path::parent_path(DirName);
1521 if (DirName.empty())
1531 llvm::sys::path::extension(Dir->
getName()) ==
1533 case LMM_NewlyLoaded:
1534 case LMM_AlreadyLoaded:
1537 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1538 DirectoryHasModuleMap[FixUpDirectories[I]] =
true;
1541 case LMM_NoDirectory:
1542 case LMM_InvalidModuleMap:
1552 FixUpDirectories.push_back(*Dir);
1558 bool AllowExcluded)
const {
1559 if (ExternalSource) {
1569 if (ExternalSource) {
1578 Module *RequestingModule,
1594 if (SuggestedModule)
1604 if (SuggestedModule)
1612bool HeaderSearch::findUsableModuleForHeader(
1623bool HeaderSearch::findUsableModuleForFrameworkHeader(
1632 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1635 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1639 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1652 StringRef
Filename = llvm::sys::path::filename(
File->getName());
1655 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1656 else if (
Filename ==
"module.modulemap")
1657 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1667 StringRef OriginalModuleMapFile) {
1674 if (!OriginalModuleMapFile.empty()) {
1678 llvm::sys::path::parent_path(OriginalModuleMapFile));
1681 Dir = FakeFile.getDir();
1689 assert(Dir &&
"parent must exist");
1690 StringRef DirName(Dir->
getName());
1691 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1692 DirName = llvm::sys::path::parent_path(DirName);
1693 if (DirName.endswith(
".framework"))
1698 assert(Dir &&
"parent must exist");
1702 assert(Dir &&
"module map home directory must exist");
1703 switch (loadModuleMapFileImpl(
File, IsSystem, *Dir, ID,
Offset)) {
1704 case LMM_AlreadyLoaded:
1705 case LMM_NewlyLoaded:
1707 case LMM_NoDirectory:
1708 case LMM_InvalidModuleMap:
1711 llvm_unreachable(
"Unknown load module map result");
1714HeaderSearch::LoadModuleMapResult
1715HeaderSearch::loadModuleMapFileImpl(
const FileEntry *
File,
bool IsSystem,
1718 assert(
File &&
"expected FileEntry");
1722 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1723 if (!AddResult.second)
1724 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1727 LoadedModuleMaps[
File] =
false;
1728 return LMM_InvalidModuleMap;
1734 LoadedModuleMaps[
File] =
false;
1735 return LMM_InvalidModuleMap;
1740 return LMM_NewlyLoaded;
1745 if (!HSOpts->ImplicitModuleMaps)
1751 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1752 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1753 if (
auto F = FileMgr.
getFile(ModuleMapFileName))
1757 ModuleMapFileName = Dir->
getName();
1758 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1759 if (
auto F = FileMgr.
getFile(ModuleMapFileName))
1765 ModuleMapFileName = Dir->
getName();
1766 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1767 "module.private.modulemap");
1768 if (
auto F = FileMgr.
getFile(ModuleMapFileName))
1781 case LMM_InvalidModuleMap:
1783 if (HSOpts->ImplicitModuleMaps)
1784 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1787 case LMM_AlreadyLoaded:
1788 case LMM_NoDirectory:
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;
1815 LoadModuleMapResult
Result =
1816 loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
1820 if (
Result == LMM_NewlyLoaded)
1821 DirectoryHasModuleMap[Dir] =
true;
1822 else if (
Result == LMM_InvalidModuleMap)
1823 DirectoryHasModuleMap[Dir] =
false;
1826 return LMM_InvalidModuleMap;
1832 if (HSOpts->ImplicitModuleMaps) {
1835 bool IsSystem = DL.isSystemHeaderDirectory();
1836 if (DL.isFramework()) {
1839 llvm::sys::path::native(DL.getFrameworkDir()->getName(), DirNative);
1843 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1845 Dir != DirEnd && !EC; Dir.increment(EC)) {
1846 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1854 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
1861 if (DL.isHeaderMap())
1869 loadSubdirectoryModuleMaps(DL);
1874 llvm::transform(ModMap.
modules(), std::back_inserter(Modules),
1875 [](
const auto &NameAndMod) { return NameAndMod.second; });
1879 if (!HSOpts->ImplicitModuleMaps)
1885 if (!DL.isNormalDir())
1894void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
1895 assert(HSOpts->ImplicitModuleMaps &&
1896 "Should not be loading subdirectory module maps");
1905 llvm::sys::path::native(Dir, DirNative);
1907 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
1908 Dir != DirEnd && !EC; Dir.increment(EC)) {
1909 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
1919 const FileEntry *
File, llvm::StringRef MainFile,
bool *IsSystem) {
1924 MainFile, IsSystem);
1928 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
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.getDir()->getName();
1986 if (CheckDir(Dir)) {
1988 *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
1989 BestPrefixIsFramework =
false;
1991 }
else if (DL.isFramework()) {
1992 StringRef Dir = DL.getFrameworkDir()->getName();
1993 if (CheckDir(Dir)) {
1995 *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
1996 BestPrefixIsFramework =
true;
2003 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2006 BestPrefixIsFramework =
false;
2011 StringRef
Filename =
File.drop_front(BestPrefixLength);
2013 if (!DL.isHeaderMap())
2016 StringRef SpelledFilename =
2017 DL.getHeaderMap()->reverseLookupFilename(
Filename);
2018 if (!SpelledFilename.empty()) {
2020 BestPrefixIsFramework =
false;
2027 bool IsPrivateHeader;
2029 if (BestPrefixIsFramework &&
2034 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.
const DirectoryEntry * getFrameworkDir() const
getFrameworkDir - Return the directory that this framework refers to.
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.
const FileEntry & getFileEntry() const
Cached information about one file (either on disk or in the virtual file system).
StringRef getName() const
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).
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...
llvm::ErrorOr< const FileEntry * > getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
StringRef getCanonicalName(const DirectoryEntry *Dir)
Retrieve the canonical name for a given directory.
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.
static bool isBuiltinHeader(StringRef FileName)
Is this a compiler builtin header?
bool parseModuleMapFile(const FileEntry *File, bool IsSystem, const DirectoryEntry *HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Parse the given module map file, and record any modules we encounter.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
Get the module map file that (along with the module name) uniquely identifies this module.
ArrayRef< KnownHeader > findAllModulesForHeader(const FileEntry *File)
Retrieve all the modules that contain the given header file.
void setTarget(const TargetInfo &Target)
Set the target information.
KnownHeader findModuleForHeader(const FileEntry *File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
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.
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(const FileEntry *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(const FileEntry *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.
@ 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.