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.");
85 : HSOpts(
std::move(HSOpts)), Diags(Diags),
86 FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
87 ModMap(SourceMgr, Diags, LangOpts,
Target, *this) {}
90 llvm::errs() <<
"\n*** HeaderSearch Stats:\n"
91 << FileInfo.size() <<
" files tracked.\n";
92 unsigned NumOnceOnlyFiles = 0;
93 for (
unsigned i = 0, e = FileInfo.size(); i != e; ++i)
94 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);
95 llvm::errs() <<
" " << NumOnceOnlyFiles <<
" #import/#pragma once files.\n";
97 llvm::errs() <<
" " << NumIncluded <<
" #include/#include_next/#import.\n"
98 <<
" " << NumMultiIncludeFileOptzn
99 <<
" #includes skipped due to the multi-include optimization.\n";
101 llvm::errs() << NumFrameworkLookups <<
" framework lookups.\n"
102 << NumSubFrameworkLookups <<
" subframework lookups.\n";
106 std::vector<DirectoryLookup> dirs,
unsigned int angledDirIdx,
107 unsigned int systemDirIdx,
108 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
109 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
110 "Directory indices are unordered");
111 SearchDirs = std::move(dirs);
112 SearchDirsUsage.assign(SearchDirs.size(),
false);
113 AngledDirIdx = angledDirIdx;
114 SystemDirIdx = systemDirIdx;
115 SearchDirToHSEntry = std::move(searchDirToHSEntry);
117 indexInitialHeaderMaps();
121 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
122 SearchDirs.insert(SearchDirs.begin() + idx, dir);
123 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx,
false);
130 std::vector<bool> UserEntryUsage(HSOpts->UserEntries.size());
131 for (
unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
133 if (SearchDirsUsage[I]) {
134 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
136 if (UserEntryIdxIt != SearchDirToHSEntry.end())
137 UserEntryUsage[UserEntryIdxIt->second] =
true;
140 return UserEntryUsage;
144 std::vector<bool> VFSUsage;
151 RootFS.visit([&](llvm::vfs::FileSystem &FS) {
152 if (
auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {
153 VFSUsage.push_back(RFS->hasBeenUsed());
154 RFS->clearHasBeenUsed();
158 "A different number of RedirectingFileSystem's were present than "
159 "-ivfsoverlay options passed to Clang!");
161 std::reverse(VFSUsage.begin(), VFSUsage.end());
170 if (!HeaderMaps.empty()) {
171 for (
unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
174 if (HeaderMaps[i].first == FE)
175 return HeaderMaps[i].second.get();
179 HeaderMaps.emplace_back(FE, std::move(HM));
180 return HeaderMaps.back().second.get();
189 for (
auto &HM : HeaderMaps)
190 Names.push_back(std::string(HM.first.getName()));
206 auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName));
207 if (i != HSOpts->PrebuiltModuleFiles.end())
210 if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())
215 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
217 llvm::sys::fs::make_absolute(
Result);
218 if (ModuleName.contains(
':'))
222 llvm::sys::path::append(
Result, ModuleName.split(
':').first +
"-" +
223 ModuleName.split(
':').second +
226 llvm::sys::path::append(
Result, ModuleName +
".pcm");
228 return std::string(
Result);
238 StringRef ModuleMapPath =
ModuleMap->getName();
239 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ?
"" :
getModuleHash();
240 for (
const std::string &Dir : HSOpts->PrebuiltModulePaths) {
242 llvm::sys::fs::make_absolute(CachePath);
243 llvm::sys::path::append(CachePath, ModuleCacheHash);
245 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
253 StringRef ModuleMapPath) {
254 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
258std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
259 StringRef ModuleMapPath,
260 StringRef CachePath) {
263 if (CachePath.empty())
267 llvm::sys::fs::make_absolute(
Result);
269 if (HSOpts->DisableModuleHash) {
270 llvm::sys::path::append(
Result, ModuleName +
".pcm");
280 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
283 llvm::hash_code Hash = llvm::hash_combine(CanonicalPath.str().lower());
286 llvm::APInt(64,
size_t(Hash)).toStringUnsigned(HashStr, 36);
287 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
289 return Result.str().str();
294 bool AllowExtraModuleMapSearch) {
297 if (
Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
300 StringRef SearchName = ModuleName;
302 AllowExtraModuleMapSearch);
312 if (!
Module && SearchName.consume_back(
"_Private"))
314 AllowExtraModuleMapSearch);
315 if (!
Module && SearchName.consume_back(
"Private"))
317 AllowExtraModuleMapSearch);
323 bool AllowExtraModuleMapSearch) {
329 if (Dir.isFramework()) {
334 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
335 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
336 if (
auto FrameworkDir =
339 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
348 if (!Dir.isNormalDir())
351 bool IsSystem = Dir.isSystemHeaderDirectory();
357 false) == LMM_NewlyLoaded) {
368 NestedModuleMapDirName = Dir.getDirRef()->getName();
369 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
371 false) == LMM_NewlyLoaded){
380 if (Dir.haveSearchedAllModuleMaps())
385 if (AllowExtraModuleMapSearch)
386 loadSubdirectoryModuleMaps(Dir);
397void HeaderSearch::indexInitialHeaderMaps() {
398 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
401 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
402 auto &Dir = SearchDirs[i];
407 if (!Dir.isHeaderMap()) {
408 SearchDirHeaderMapIndex = std::move(Index);
409 FirstNonHeaderMapSearchDirIdx = i;
414 auto Callback = [&](StringRef
Filename) {
415 Index.try_emplace(
Filename.lower(), i);
417 Dir.getHeaderMap()->forEachKey(Callback);
432 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
438 bool IsSystemHeaderDir,
Module *RequestingModule,
440 bool CacheFailures ) {
447 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
448 if (EC != llvm::errc::no_such_file_or_directory &&
449 EC != llvm::errc::invalid_argument &&
450 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
451 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
458 if (!findUsableModuleForHeader(
459 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
460 SuggestedModule, IsSystemHeaderDir))
472 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
474 bool OpenFile)
const {
475 InUserSpecifiedSystemFramework =
false;
476 IsInHeaderMap =
false;
483 llvm::sys::path::append(TmpDir,
Filename);
487 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
490 RelativePath->clear();
494 return HS.getFileAndSuggestModule(
496 RequestingModule, SuggestedModule, OpenFile);
500 return DoFrameworkLookup(
Filename, HS, SearchPath, RelativePath,
501 RequestingModule, SuggestedModule,
502 InUserSpecifiedSystemFramework, IsFrameworkFound);
504 assert(
isHeaderMap() &&
"Unknown directory lookup");
511 IsInHeaderMap =
true;
513 auto FixupSearchPathAndFindUsableModule =
516 StringRef SearchPathRef(
getName());
518 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
521 RelativePath->clear();
524 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
525 RequestingModule, SuggestedModule,
535 if (llvm::sys::path::is_relative(Dest)) {
536 MappedName.append(Dest.begin(), Dest.end());
537 Filename = StringRef(MappedName.begin(), MappedName.size());
542 return FixupSearchPathAndFindUsableModule(*Res);
562 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
563 "Not a framework directory");
585 DirName = llvm::sys::path::parent_path(DirName);
596 if (llvm::sys::path::extension(DirName) ==
".framework") {
597 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
598 TopFrameworkDir = *Dir;
602 return TopFrameworkDir;
606 bool HasSuggestedModule) {
607 return HasSuggestedModule ||
617 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
621 size_t SlashPos =
Filename.find(
'/');
622 if (SlashPos == StringRef::npos)
639 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
640 FrameworkName.push_back(
'/');
643 StringRef ModuleName(
Filename.begin(), SlashPos);
644 FrameworkName += ModuleName;
647 FrameworkName +=
".framework/";
651 ++NumFrameworkLookups;
666 SystemFrameworkMarker +=
".system_framework";
667 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {
678 RelativePath->clear();
683 unsigned OrigSize = FrameworkName.size();
685 FrameworkName +=
"Headers/";
690 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
699 const char *
Private =
"Private";
700 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
703 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
713 StringRef FrameworkPath =
File->getDir().getName();
714 bool FoundFramework =
false;
723 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
724 FoundFramework =
true;
729 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
730 if (FrameworkPath.empty())
735 if (FoundFramework) {
736 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
738 SuggestedModule, IsSystem))
741 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
742 SuggestedModule, IsSystem))
751void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
754 CacheLookup.HitIt = HitIt;
755 noteLookupUsage(HitIt.Idx, Loc);
758void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
759 SearchDirsUsage[HitIdx] =
true;
761 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
762 if (UserEntryIdxIt != SearchDirToHSEntry.end())
763 Diags.
Report(Loc, diag::remark_pp_search_path_usage)
764 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;
782 if (MSFE && FE != *MSFE) {
783 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
789static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
790 assert(!Str.empty());
791 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
792 std::copy(Str.begin(), Str.end(), CopyStr);
793 CopyStr[Str.size()] =
'\0';
800 using namespace llvm::sys;
801 path::const_iterator I = path::begin(Path);
802 path::const_iterator E = path::end(Path);
803 IsPrivateHeader =
false;
815 if (*I ==
"Headers") {
817 }
else if (*I ==
"PrivateHeaders") {
819 IsPrivateHeader =
true;
820 }
else if (I->ends_with(
".framework")) {
821 StringRef Name = I->drop_back(10);
823 FrameworkName.clear();
824 FrameworkName.append(Name.begin(), Name.end());
825 IncludeSpelling.clear();
826 IncludeSpelling.append(Name.begin(), Name.end());
828 }
else if (FoundComp >= 2) {
829 IncludeSpelling.push_back(
'/');
830 IncludeSpelling.append(I->begin(), I->end());
835 return !FrameworkName.empty() && FoundComp >= 2;
840 StringRef Includer, StringRef IncludeFilename,
842 bool FoundByHeaderMap =
false) {
843 bool IsIncluderPrivateHeader =
false;
847 FromIncludeSpelling))
849 bool IsIncludeePrivateHeader =
false;
850 bool IsIncludeeInFramework =
852 ToFramework, ToIncludeSpelling);
854 if (!isAngled && !FoundByHeaderMap) {
856 if (IsIncludeeInFramework) {
857 NewInclude += ToIncludeSpelling;
860 NewInclude += IncludeFilename;
863 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
871 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
872 IsIncludeePrivateHeader && FromFramework == ToFramework)
873 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
885 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
888 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
889 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
896 if (IsFrameworkFound)
897 *IsFrameworkFound =
false;
903 if (llvm::sys::path::is_absolute(
Filename)) {
913 RelativePath->clear();
917 return getFileAndSuggestModule(
Filename, IncludeLoc,
nullptr,
919 RequestingModule, SuggestedModule, OpenFile,
932 if (!Includers.empty() && !isAngled) {
935 for (
const auto &IncluderAndDir : Includers) {
939 TmpDir = IncluderAndDir.second.getName();
940 llvm::sys::path::append(TmpDir,
Filename);
949 bool IncluderIsSystemHeader = [&]() {
951 return BuildSystemModule;
953 assert(HFI &&
"includer without file info");
957 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
958 RequestingModule, SuggestedModule)) {
960 assert(
First &&
"only first includer can have no file");
971 assert(FromHFI &&
"includer without file info");
972 unsigned DirInfo = FromHFI->
DirInfo;
974 StringRef Framework = FromHFI->
Framework;
982 StringRef SearchPathRef(IncluderAndDir.second.getName());
984 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
987 RelativePath->clear();
992 IncluderAndDir.second.getName(),
Filename,
1000 if (Diags.
isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1004 if (SuggestedModule) {
1005 MSSuggestedModule = *SuggestedModule;
1030 LookupFileCacheInfo &CacheLookup = LookupFileCache[
Filename];
1035 if (CacheLookup.StartIt == NextIt &&
1036 CacheLookup.RequestingModule == RequestingModule) {
1038 if (CacheLookup.HitIt)
1039 It = CacheLookup.HitIt;
1040 if (CacheLookup.MappedName) {
1049 CacheLookup.reset(RequestingModule, NextIt);
1055 auto Iter = SearchDirHeaderMapIndex.find(
Filename.lower());
1056 if (
Iter == SearchDirHeaderMapIndex.end())
1065 CacheLookup.reset(RequestingModule, NextIt);
1072 bool InUserSpecifiedSystemFramework =
false;
1073 bool IsInHeaderMap =
false;
1074 bool IsFrameworkFoundInDir =
false;
1076 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1077 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1078 IsInHeaderMap, MappedName, OpenFile);
1079 if (!MappedName.empty()) {
1080 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1081 CacheLookup.MappedName =
1082 copyString(MappedName, LookupFileCache.getAllocator());
1088 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1089 if (IsFrameworkFound)
1093 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1103 HFI.
DirInfo = CurDir->getDirCharacteristic();
1113 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1114 if (
Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1124 if (CurDir->isHeaderMap() && isAngled) {
1125 size_t SlashPos =
Filename.find(
'/');
1126 if (SlashPos != StringRef::npos)
1129 if (CurDir->isIndexHeaderMap())
1131 }
else if (CurDir->isFramework()) {
1132 size_t SlashPos =
Filename.find(
'/');
1133 if (SlashPos != StringRef::npos)
1139 if (SuggestedModule)
1140 *SuggestedModule = MSSuggestedModule;
1144 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1145 if (!Includers.empty())
1147 Includers.front().second.getName(),
Filename,
1148 *
File, isAngled, FoundByHeaderMap);
1151 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1159 if (!Includers.empty() && Includers.front().first && !isAngled &&
1163 assert(IncludingHFI &&
"includer without file info");
1166 ScratchFilename += IncludingHFI->
Framework;
1167 ScratchFilename +=
'/';
1171 ScratchFilename, IncludeLoc,
true, FromDir, &CurDir,
1172 Includers.front(), SearchPath, RelativePath, RequestingModule,
1173 SuggestedModule, IsMapped,
nullptr);
1176 File ? &
File->getFileEntry() :
nullptr,
1178 if (SuggestedModule)
1179 *SuggestedModule = MSSuggestedModule;
1183 cacheLookupSuccess(LookupFileCache[
Filename],
1184 LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
1191 if (SuggestedModule)
1192 *SuggestedModule = MSSuggestedModule;
1198 return std::nullopt;
1212 size_t SlashPos =
Filename.find(
'/');
1213 if (SlashPos == StringRef::npos)
1214 return std::nullopt;
1217 StringRef ContextName = ContextFileEnt.
getName();
1220 const unsigned DotFrameworkLen = 10;
1221 auto FrameworkPos = ContextName.find(
".framework");
1222 if (FrameworkPos == StringRef::npos ||
1223 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1224 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1225 return std::nullopt;
1229 DotFrameworkLen + 1);
1232 FrameworkName +=
"Frameworks/";
1234 FrameworkName +=
".framework/";
1237 *FrameworkMap.insert(std::make_pair(
Filename.substr(0, SlashPos),
1241 if (CacheLookup.second.Directory &&
1242 CacheLookup.first().size() == FrameworkName.size() &&
1243 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1244 CacheLookup.first().size()) != 0)
1245 return std::nullopt;
1248 if (!CacheLookup.second.Directory) {
1249 ++NumSubFrameworkLookups;
1254 return std::nullopt;
1258 CacheLookup.second.Directory = Dir;
1263 RelativePath->clear();
1269 HeadersFilename +=
"Headers/";
1271 SearchPath->clear();
1273 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1280 HeadersFilename = FrameworkName;
1281 HeadersFilename +=
"PrivateHeaders/";
1283 SearchPath->clear();
1285 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1292 return std::nullopt;
1297 assert(ContextHFI &&
"context file without file info");
1300 unsigned DirInfo = ContextHFI->
DirInfo;
1303 FrameworkName.pop_back();
1304 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1305 RequestingModule, SuggestedModule,
1307 return std::nullopt;
1317 bool isModuleHeader,
1318 bool isTextualModuleHeader) {
1319 assert((!isModuleHeader || !isTextualModuleHeader) &&
1320 "A header can't build with a module and be textual at the same time");
1337 assert(OtherHFI.
External &&
"expected to merge external HFI");
1359 if (FE.
getUID() >= FileInfo.size())
1360 FileInfo.resize(FE.
getUID() + 1);
1366 if (ExternalHFI.IsValid) {
1368 if (ExternalHFI.External)
1383 if (FE.
getUID() >= FileInfo.size())
1384 FileInfo.resize(FE.
getUID() + 1);
1386 HFI = &FileInfo[FE.
getUID()];
1390 if (ExternalHFI.IsValid) {
1392 if (ExternalHFI.External)
1396 }
else if (FE.
getUID() < FileInfo.size()) {
1397 HFI = &FileInfo[FE.
getUID()];
1402 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1408 if (FE.
getUID() < FileInfo.size()) {
1409 HFI = &FileInfo[FE.
getUID()];
1422 return HFI->isPragmaOnce || HFI->ControllingMacro ||
1423 HFI->ControllingMacroID;
1429 bool isCompilingModuleHeader) {
1431 if (!isCompilingModuleHeader) {
1435 if (HFI && HFI->isModuleHeader)
1440 HFI.mergeModuleMembership(Role);
1441 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1446 bool ModulesEnabled,
Module *M,
1447 bool &IsFirstIncludeOfFile) {
1463 IsFirstIncludeOfFile =
false;
1466 auto MaybeReenterImportedFile = [&]() ->
bool {
1556 (FileInfo.
isImport && !MaybeReenterImportedFile()))
1572 ++NumMultiIncludeFileOptzn;
1583 return SearchDirs.capacity()
1584 + llvm::capacity_in_bytes(FileInfo)
1585 + llvm::capacity_in_bytes(HeaderMaps)
1586 + LookupFileCache.getAllocator().getTotalMemory()
1587 + FrameworkMap.getAllocator().getTotalMemory();
1591 return &DL - &*SearchDirs.begin();
1595 return FrameworkNames.insert(Framework).first->first();
1599 auto It = IncludeNames.find(
File);
1600 if (It == IncludeNames.end())
1608 if (!HSOpts->ImplicitModuleMaps)
1616 DirName = llvm::sys::path::parent_path(DirName);
1617 if (DirName.empty())
1627 llvm::sys::path::extension(Dir->getName()) ==
1629 case LMM_NewlyLoaded:
1630 case LMM_AlreadyLoaded:
1633 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1634 DirectoryHasModuleMap[FixUpDirectories[I]] =
true;
1637 case LMM_NoDirectory:
1638 case LMM_InvalidModuleMap:
1648 FixUpDirectories.push_back(*Dir);
1654 bool AllowExcluded)
const {
1684 Module *RequestingModule,
1700 if (SuggestedModule)
1710 if (SuggestedModule)
1718bool HeaderSearch::findUsableModuleForHeader(
1729bool HeaderSearch::findUsableModuleForFrameworkHeader(
1738 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1741 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1745 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1759 StringRef
Filename = llvm::sys::path::filename(
File.getName());
1762 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1763 else if (
Filename ==
"module.modulemap")
1764 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1766 return std::nullopt;
1770 Diags.
Report(diag::warn_deprecated_module_dot_map)
1771 << PrivateFilename << 1
1772 <<
File.getDir().getName().ends_with(
".framework");
1778 FileID ID,
unsigned *Offset,
1779 StringRef OriginalModuleMapFile) {
1786 if (!OriginalModuleMapFile.empty()) {
1790 llvm::sys::path::parent_path(OriginalModuleMapFile));
1793 Dir = FakeFile.getDir();
1796 Dir =
File.getDir();
1799 assert(Dir &&
"parent must exist");
1800 StringRef DirName(Dir->
getName());
1801 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1802 DirName = llvm::sys::path::parent_path(DirName);
1803 if (DirName.ends_with(
".framework"))
1808 assert(Dir &&
"parent must exist");
1812 assert(Dir &&
"module map home directory must exist");
1813 switch (loadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1814 case LMM_AlreadyLoaded:
1815 case LMM_NewlyLoaded:
1817 case LMM_NoDirectory:
1818 case LMM_InvalidModuleMap:
1821 llvm_unreachable(
"Unknown load module map result");
1824HeaderSearch::LoadModuleMapResult
1830 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1831 if (!AddResult.second)
1832 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1835 LoadedModuleMaps[
File] =
false;
1836 return LMM_InvalidModuleMap;
1843 LoadedModuleMaps[
File] =
false;
1844 return LMM_InvalidModuleMap;
1849 return LMM_NewlyLoaded;
1854 if (!HSOpts->ImplicitModuleMaps)
1855 return std::nullopt;
1860 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1861 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1866 ModuleMapFileName = Dir.
getName();
1867 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1869 Diags.
Report(diag::warn_deprecated_module_dot_map)
1870 << ModuleMapFileName << 0 << IsFramework;
1877 ModuleMapFileName = Dir.
getName();
1878 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1879 "module.private.modulemap");
1883 return std::nullopt;
1890 case LMM_InvalidModuleMap:
1892 if (HSOpts->ImplicitModuleMaps)
1893 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1896 case LMM_NoDirectory:
1899 case LMM_AlreadyLoaded:
1900 case LMM_NewlyLoaded:
1907HeaderSearch::LoadModuleMapResult
1913 return LMM_NoDirectory;
1916HeaderSearch::LoadModuleMapResult
1919 auto KnownDir = DirectoryHasModuleMap.find(Dir);
1920 if (KnownDir != DirectoryHasModuleMap.end())
1921 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
1925 LoadModuleMapResult
Result =
1926 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir);
1930 if (
Result == LMM_NewlyLoaded)
1931 DirectoryHasModuleMap[Dir] =
true;
1932 else if (
Result == LMM_InvalidModuleMap)
1933 DirectoryHasModuleMap[Dir] =
false;
1936 return LMM_InvalidModuleMap;
1942 if (HSOpts->ImplicitModuleMaps) {
1945 bool IsSystem = DL.isSystemHeaderDirectory();
1946 if (DL.isFramework()) {
1949 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
1953 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
1955 Dir != DirEnd && !EC; Dir.increment(EC)) {
1956 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
1964 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
1971 if (DL.isHeaderMap())
1979 loadSubdirectoryModuleMaps(DL);
1984 llvm::transform(ModMap.
modules(), std::back_inserter(Modules),
1985 [](
const auto &NameAndMod) { return NameAndMod.second; });
1989 if (!HSOpts->ImplicitModuleMaps)
1995 if (!DL.isNormalDir())
2004void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2005 assert(HSOpts->ImplicitModuleMaps &&
2006 "Should not be loading subdirectory module maps");
2015 llvm::sys::path::native(Dir, DirNative);
2017 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2018 Dir != DirEnd && !EC; Dir.increment(EC)) {
2019 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2021 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2033 MainFile, IsAngled);
2037 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2038 bool *IsAngled)
const {
2039 using namespace llvm::sys;
2045 path::remove_dots(FilePath,
true);
2046 path::native(FilePath, path::Style::posix);
2049 unsigned BestPrefixLength = 0;
2054 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2055 fs::make_absolute(WorkingDir, Dir);
2056 path::remove_dots(Dir,
true);
2057 for (
auto NI = path::begin(
File), NE = path::end(
File),
2058 DI = path::begin(Dir), DE = path::end(Dir);
2059 NI != NE; ++NI, ++DI) {
2062 unsigned PrefixLength = NI - path::begin(
File);
2063 if (PrefixLength > BestPrefixLength) {
2064 BestPrefixLength = PrefixLength;
2071 if (NI->size() == 1 && DI->size() == 1 &&
2072 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2078 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2079 StringRef NBasename = path::stem(*NI);
2080 StringRef DBasename = path::stem(*DI);
2081 if (DBasename.starts_with(NBasename))
2091 bool BestPrefixIsFramework =
false;
2093 if (DL.isNormalDir()) {
2094 StringRef Dir = DL.getDirRef()->getName();
2095 if (CheckDir(Dir)) {
2097 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2098 BestPrefixIsFramework =
false;
2100 }
else if (DL.isFramework()) {
2101 StringRef Dir = DL.getFrameworkDirRef()->getName();
2102 if (CheckDir(Dir)) {
2105 *IsAngled = BestPrefixLength;
2106 BestPrefixIsFramework =
true;
2113 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2116 BestPrefixIsFramework =
false;
2121 StringRef
Filename =
File.drop_front(BestPrefixLength);
2123 if (!DL.isHeaderMap())
2126 StringRef SpelledFilename =
2127 DL.getHeaderMap()->reverseLookupFilename(
Filename);
2128 if (!SpelledFilename.empty()) {
2130 BestPrefixIsFramework =
false;
2137 bool IsPrivateHeader;
2139 if (BestPrefixIsFramework &&
2144 return path::convert_to_slash(
Filename);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
llvm::MachO::Target Target
Defines the clang::Module class, which describes a module in the source code.
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
constexpr bool has_value() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
Cached information about one directory (either on disk or in the virtual file system).
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
SrcMgr::CharacteristicKind getDirCharacteristic() const
DirCharacteristic - The type of directory this is, one of the DirType enum values.
OptionalFileEntryRef LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, bool &IsInHeaderMap, SmallVectorImpl< char > &MappedName, bool OpenFile=true) const
LookupFile - Lookup the specified file in this search path, returning it if it exists or returning nu...
bool isFramework() const
isFramework - True if this is a framework directory.
bool isSystemHeaderDirectory() const
Whether this describes a system header directory.
OptionalDirectoryEntryRef getFrameworkDirRef() const
void setSearchedAllModuleMaps(bool SAMM)
Specify whether we have already searched all of the subdirectories for module maps.
bool isHeaderMap() const
isHeaderMap - Return true if this is a header map, not a normal directory.
StringRef getName() const
getName - Return the directory or filename corresponding to this lookup object.
OptionalDirectoryEntryRef getDirRef() const
bool haveSearchedAllModuleMaps() const
Determine whether we have already searched this entire directory for module maps.
const DirectoryEntry * getDir() const
getDir - Return the directory that this entry refers to.
bool isNormalDir() const
isNormalDir - Return true if this is a normal directory, not a header map.
const HeaderMap * getHeaderMap() const
getHeaderMap - Return the directory that this entry refers to.
Abstract interface for external sources of preprocessor information.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::vfs::FileSystem & getVirtualFileSystem() const
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
llvm::ErrorOr< const DirectoryEntry * > getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option.
FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, time_t ModificationTime)
Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
One of these records is kept for each identifier that is lexed.
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
ArrayRef< KnownHeader > findResolvedModulesForHeader(FileEntryRef File) const
Like findAllModulesForHeader, but do not attempt to infer module ownership from umbrella headers if w...
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
bool parseModuleMapFile(FileEntryRef File, bool IsSystem, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Parse the given module map file, and record any modules we encounter.
void setTarget(const TargetInfo &Target)
Set the target information.
ModuleHeaderRole
Flags describing the role of a module header.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
ArrayRef< KnownHeader > findAllModulesForHeader(FileEntryRef File)
Retrieve all the modules that contain the given header file.
llvm::iterator_range< module_iterator > modules() const
bool resolveUses(Module *Mod, bool Complain)
Resolve all of the unresolved uses in the given module.
Describes a module or submodule.
bool directlyUses(const Module *Requested)
Determine whether this module has declared its intention to directly use another module.
std::string Name
The name of this module.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool markIncluded(FileEntryRef File)
Mark the file as included.
bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M)
Determine whether II is defined as a macro within the module M, if that is a module that we've alread...
bool isMacroDefined(StringRef Id)
bool alreadyIncluded(FileEntryRef File) const
Return true if this header has already been included.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Exposes information about the current target.
The JSON file list parser is used to communicate input to InstallAPI.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Result
The result type of a method or function.
This structure is used to record entries in our framework cache.
bool IsUserSpecifiedSystemFramework
Whether this framework has been "user-specified" to be treated as if it were a system framework (even...
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.