26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/Statistic.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/Allocator.h"
33#include "llvm/Support/Capacity.h"
34#include "llvm/Support/Errc.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/FileSystem.h"
37#include "llvm/Support/Path.h"
38#include "llvm/Support/VirtualFileSystem.h"
39#include "llvm/Support/xxhash.h"
46#include <system_error>
51#define DEBUG_TYPE "file-search"
55 NumMultiIncludeFileOptzn,
56 "Number of #includes skipped due to the multi-include optimization.");
59 "Number of subframework lookups.");
73 if (ControllingMacro && ControllingMacro->
isOutOfDate()) {
74 assert(
External &&
"We must have an external source if we have a "
75 "controlling macro that is out of date.");
76 External->updateOutOfDateIdentifier(*ControllingMacro);
78 return ControllingMacro;
87 : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
88 FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts,
Target, *this) {}
91 llvm::errs() <<
"\n*** HeaderSearch Stats:\n"
92 << FileInfo.size() <<
" files tracked.\n";
93 unsigned NumOnceOnlyFiles = 0;
94 for (
unsigned i = 0, e = FileInfo.size(); i != e; ++i)
95 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);
96 llvm::errs() <<
" " << NumOnceOnlyFiles <<
" #import/#pragma once files.\n";
98 llvm::errs() <<
" " << NumIncluded <<
" #include/#include_next/#import.\n"
99 <<
" " << NumMultiIncludeFileOptzn
100 <<
" #includes skipped due to the multi-include optimization.\n";
102 llvm::errs() << NumFrameworkLookups <<
" framework lookups.\n"
103 << NumSubFrameworkLookups <<
" subframework lookups.\n";
107 std::vector<DirectoryLookup> dirs,
unsigned int angledDirIdx,
108 unsigned int systemDirIdx,
109 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {
110 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
111 "Directory indices are unordered");
112 SearchDirs = std::move(dirs);
113 SearchDirsUsage.assign(SearchDirs.size(),
false);
114 AngledDirIdx = angledDirIdx;
115 SystemDirIdx = systemDirIdx;
116 SearchDirToHSEntry = std::move(searchDirToHSEntry);
118 indexInitialHeaderMaps();
122 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
123 SearchDirs.insert(SearchDirs.begin() + idx, dir);
124 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx,
false);
131 std::vector<bool> UserEntryUsage(HSOpts.UserEntries.size());
132 for (
unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
134 if (SearchDirsUsage[I]) {
135 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
137 if (UserEntryIdxIt != SearchDirToHSEntry.end())
138 UserEntryUsage[UserEntryIdxIt->second] =
true;
141 return UserEntryUsage;
145 std::vector<bool> VFSUsage;
149 llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
153 RootFS.visit([&](llvm::vfs::FileSystem &FS) {
154 if (
auto *RFS = dyn_cast<llvm::vfs::RedirectingFileSystem>(&FS)) {
158 if (!RFS->getOverlayFileDir().empty()) {
159 VFSUsage.push_back(RFS->hasBeenUsed());
160 RFS->clearHasBeenUsed();
165 "A different number of RedirectingFileSystem's were present than "
166 "-ivfsoverlay options passed to Clang!");
168 std::reverse(VFSUsage.begin(), VFSUsage.end());
177 if (!HeaderMaps.empty()) {
178 for (
unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
181 if (HeaderMaps[i].first == FE)
182 return HeaderMaps[i].second.get();
186 HeaderMaps.emplace_back(FE, std::move(HM));
187 return HeaderMaps.back().second.get();
196 for (
auto &HM : HeaderMaps)
197 Names.push_back(std::string(HM.first.getName()));
213 auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));
214 if (i != HSOpts.PrebuiltModuleFiles.end())
217 if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())
222 for (
const std::string &Dir : HSOpts.PrebuiltModulePaths) {
224 FileMgr.makeAbsolutePath(
Result);
225 if (ModuleName.contains(
':'))
229 llvm::sys::path::append(
Result, ModuleName.split(
':').first +
"-" +
230 ModuleName.split(
':').second +
233 llvm::sys::path::append(
Result, ModuleName +
".pcm");
235 return std::string(
Result);
245 StringRef ModuleMapPath =
ModuleMap->getName();
246 StringRef ModuleCacheHash = HSOpts.DisableModuleHash ?
"" :
getModuleHash();
247 for (
const std::string &Dir : HSOpts.PrebuiltModulePaths) {
249 FileMgr.makeAbsolutePath(CachePath);
250 llvm::sys::path::append(CachePath, ModuleCacheHash);
252 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);
260 StringRef ModuleMapPath) {
261 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
265std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
266 StringRef ModuleMapPath,
267 StringRef CachePath) {
270 if (CachePath.empty())
276 llvm::sys::path::append(Result, ModuleName +
".pcm");
285 SmallString<128> CanonicalPath(ModuleMapPath);
286 if (
getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
289 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
291 SmallString<128> HashStr;
292 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
293 llvm::sys::path::append(
Result, ModuleName +
"-" + HashStr +
".pcm");
295 return Result.str().str();
300 bool AllowExtraModuleMapSearch) {
303 if (
Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
306 StringRef SearchName = ModuleName;
308 AllowExtraModuleMapSearch);
318 if (!
Module && SearchName.consume_back(
"_Private"))
320 AllowExtraModuleMapSearch);
321 if (!
Module && SearchName.consume_back(
"Private"))
323 AllowExtraModuleMapSearch);
329 bool AllowExtraModuleMapSearch) {
335 if (Dir.isFramework()) {
340 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
341 llvm::sys::path::append(FrameworkDirName, SearchName +
".framework");
342 if (
auto FrameworkDir =
343 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
345 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
354 if (!Dir.isNormalDir())
357 bool IsSystem = Dir.isSystemHeaderDirectory();
360 DirectoryEntryRef NormalDir = *Dir.getDirRef();
362 if (parseModuleMapFile(NormalDir, IsSystem,
363 false) == MMR_NewlyProcessed) {
366 Module = ModMap.findOrLoadModule(ModuleName);
373 SmallString<128> NestedModuleMapDirName;
374 NestedModuleMapDirName = Dir.getDirRef()->getName();
375 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);
376 if (parseModuleMapFile(NestedModuleMapDirName, IsSystem,
377 false) == MMR_NewlyProcessed) {
379 Module = ModMap.findOrLoadModule(ModuleName);
384 if (HSOpts.AllowModuleMapSubdirectorySearch) {
387 if (Dir.haveSearchedAllModuleMaps())
392 if (AllowExtraModuleMapSearch)
393 loadSubdirectoryModuleMaps(Dir);
396 Module = ModMap.findOrLoadModule(ModuleName);
405void HeaderSearch::indexInitialHeaderMaps() {
406 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
409 for (
unsigned i = 0; i != SearchDirs.size(); ++i) {
410 auto &Dir = SearchDirs[i];
415 if (!Dir.isHeaderMap()) {
416 SearchDirHeaderMapIndex = std::move(Index);
417 FirstNonHeaderMapSearchDirIdx = i;
422 auto Callback = [&](StringRef Filename) {
423 Index.try_emplace(Filename.lower(), i);
425 Dir.getHeaderMap()->forEachKey(Callback);
440 assert(
isHeaderMap() &&
"Unknown DirectoryLookup");
446 bool IsSystemHeaderDir,
Module *RequestingModule,
448 bool CacheFailures ) {
455 std::error_code EC = llvm::errorToErrorCode(
File.takeError());
456 if (EC != llvm::errc::no_such_file_or_directory &&
457 EC != llvm::errc::invalid_argument &&
458 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {
459 Diags.
Report(IncludeLoc, diag::err_cannot_open_file)
466 if (!findUsableModuleForHeader(
467 *
File, Dir ? Dir :
File->getFileEntry().getDir(), RequestingModule,
468 SuggestedModule, IsSystemHeaderDir))
480 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
482 bool OpenFile)
const {
483 InUserSpecifiedSystemFramework =
false;
484 IsInHeaderMap =
false;
491 llvm::sys::path::append(TmpDir, Filename);
495 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
498 RelativePath->clear();
499 RelativePath->append(Filename.begin(), Filename.end());
502 return HS.getFileAndSuggestModule(
504 RequestingModule, SuggestedModule, OpenFile);
508 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
509 RequestingModule, SuggestedModule,
510 InUserSpecifiedSystemFramework, IsFrameworkFound);
512 assert(
isHeaderMap() &&
"Unknown directory lookup");
519 IsInHeaderMap =
true;
521 auto FixupSearchPathAndFindUsableModule =
524 StringRef SearchPathRef(
getName());
526 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
529 RelativePath->clear();
530 RelativePath->append(Filename.begin(), Filename.end());
532 if (!HS.findUsableModuleForHeader(
File,
File.getFileEntry().getDir(),
533 RequestingModule, SuggestedModule,
543 if (llvm::sys::path::is_relative(Dest)) {
544 MappedName.append(Dest.begin(), Dest.end());
545 Filename = StringRef(MappedName.begin(), MappedName.size());
550 return FixupSearchPathAndFindUsableModule(*Res);
570 assert(llvm::sys::path::extension(DirName) ==
".framework" &&
571 "Not a framework directory");
587 auto TopFrameworkDir =
FileMgr.getOptionalDirectoryRef(DirName);
590 DirName =
FileMgr.getCanonicalName(*TopFrameworkDir);
593 DirName = llvm::sys::path::parent_path(DirName);
598 auto Dir =
FileMgr.getOptionalDirectoryRef(DirName);
604 if (llvm::sys::path::extension(DirName) ==
".framework") {
605 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
606 TopFrameworkDir = *Dir;
610 return TopFrameworkDir;
614 bool HasSuggestedModule) {
615 return HasSuggestedModule ||
625 bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound)
const {
629 size_t SlashPos = Filename.find(
'/');
630 if (SlashPos == StringRef::npos)
635 FrameworkCacheEntry &CacheEntry =
645 SmallString<1024> FrameworkName;
647 if (FrameworkName.empty() || FrameworkName.back() !=
'/')
648 FrameworkName.push_back(
'/');
651 StringRef ModuleName(Filename.begin(), SlashPos);
652 FrameworkName += ModuleName;
655 FrameworkName +=
".framework/";
659 ++NumFrameworkLookups;
673 SmallString<1024> SystemFrameworkMarker(FrameworkName);
674 SystemFrameworkMarker +=
".system_framework";
685 RelativePath->clear();
686 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
690 unsigned OrigSize = FrameworkName.size();
692 FrameworkName +=
"Headers/";
697 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
700 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
706 const char *
Private =
"Private";
707 FrameworkName.insert(FrameworkName.begin()+OrigSize,
Private,
710 SearchPath->insert(SearchPath->begin()+OrigSize,
Private,
720 StringRef FrameworkPath =
File->getDir().getName();
721 bool FoundFramework =
false;
730 if (llvm::sys::path::extension(FrameworkPath) ==
".framework") {
731 FoundFramework =
true;
736 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
737 if (FrameworkPath.empty())
742 if (FoundFramework) {
743 if (!HS.findUsableModuleForFrameworkHeader(*
File, FrameworkPath,
745 SuggestedModule, IsSystem))
748 if (!HS.findUsableModuleForHeader(*
File,
getDir(), RequestingModule,
749 SuggestedModule, IsSystem))
758void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
761 CacheLookup.HitIt = HitIt;
762 noteLookupUsage(HitIt.Idx, Loc);
765void HeaderSearch::noteLookupUsage(
unsigned HitIdx,
SourceLocation Loc) {
766 SearchDirsUsage[HitIdx] =
true;
768 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);
769 if (UserEntryIdxIt != SearchDirToHSEntry.end())
770 Diags.Report(Loc, diag::remark_pp_search_path_usage)
771 << HSOpts.UserEntries[UserEntryIdxIt->second].Path;
789 if (MSFE && FE != *MSFE) {
790 Diags.
Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->
getName();
796static const char *
copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
797 assert(!Str.empty());
798 char *CopyStr = Alloc.Allocate<
char>(Str.size()+1);
799 std::copy(Str.begin(), Str.end(), CopyStr);
800 CopyStr[Str.size()] =
'\0';
807 using namespace llvm::sys;
808 path::const_iterator I = path::begin(Path);
809 path::const_iterator E = path::end(Path);
810 IsPrivateHeader =
false;
822 if (*I ==
"Headers") {
824 }
else if (*I ==
"PrivateHeaders") {
826 IsPrivateHeader =
true;
827 }
else if (I->ends_with(
".framework")) {
828 StringRef Name = I->drop_back(10);
830 FrameworkName.clear();
831 FrameworkName.append(Name.begin(), Name.end());
832 IncludeSpelling.clear();
833 IncludeSpelling.append(Name.begin(), Name.end());
835 }
else if (FoundComp >= 2) {
836 IncludeSpelling.push_back(
'/');
837 IncludeSpelling.append(I->begin(), I->end());
842 return !FrameworkName.empty() && FoundComp >= 2;
847 StringRef Includer, StringRef IncludeFilename,
849 bool FoundByHeaderMap =
false) {
850 bool IsIncluderPrivateHeader =
false;
854 FromIncludeSpelling))
856 bool IsIncludeePrivateHeader =
false;
857 bool IsIncludeeInFramework =
859 ToFramework, ToIncludeSpelling);
861 if (!isAngled && !FoundByHeaderMap) {
863 if (IsIncludeeInFramework) {
864 NewInclude += ToIncludeSpelling;
867 NewInclude += IncludeFilename;
870 Diags.
Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
878 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
879 IsIncludeePrivateHeader && FromFramework == ToFramework)
880 Diags.
Report(IncludeLoc, diag::warn_framework_include_private_from_public)
887 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
888 bool isAngled,
int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
890 if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc) ||
894 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
897 DiagnosedShadowing =
true;
901 for (
size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
902 const auto &IncluderAndDir = Includers[i];
904 llvm::sys::path::append(TmpDir, Filename);
906 if (&
File->getFileEntry() == *FE)
908 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
909 << Filename << (*FE).getDir().getName()
910 << IncluderAndDir.second.getName();
913 llvm::errorToErrorCode(
File.takeError());
919 ConstSearchDirIterator It =
922 It = std::next(MainLoopIt);
923 }
else if (FromDir) {
931 llvm::sys::path::append(TmpPath, Filename);
933 if (&
File->getFileEntry() == *FE)
935 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
936 << Filename << (*FE).getDir().getName() << It->getName();
939 llvm::errorToErrorCode(
File.takeError());
951 ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDirArg,
952 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
955 bool *IsMapped,
bool *IsFrameworkFound,
bool SkipCache,
956 bool BuildSystemModule,
bool OpenFile,
bool CacheFailures) {
957 ConstSearchDirIterator CurDirLocal =
nullptr;
958 ConstSearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
963 if (IsFrameworkFound)
964 *IsFrameworkFound =
false;
970 if (llvm::sys::path::is_absolute(Filename)) {
980 RelativePath->clear();
981 RelativePath->append(Filename.begin(), Filename.end());
984 return getFileAndSuggestModule(Filename, IncludeLoc,
nullptr,
986 RequestingModule, SuggestedModule, OpenFile,
993 bool DiagnosedShadowing =
false;
1000 if (!Includers.empty() && !isAngled) {
1003 for (
const auto &IncluderAndDir : Includers) {
1007 TmpDir = IncluderAndDir.second.getName();
1008 llvm::sys::path::append(TmpDir, Filename);
1017 bool IncluderIsSystemHeader = [&]() {
1019 return BuildSystemModule;
1021 assert(HFI &&
"includer without file info");
1025 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
1026 RequestingModule, SuggestedModule)) {
1028 FromDir, Includers, isAngled,
1029 &IncluderAndDir - Includers.begin(),
nullptr);
1031 assert(
First &&
"only first includer can have no file");
1042 assert(FromHFI &&
"includer without file info");
1043 unsigned DirInfo = FromHFI->
DirInfo;
1049 StringRef SearchPathRef(IncluderAndDir.second.getName());
1050 SearchPath->clear();
1051 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
1054 RelativePath->clear();
1055 RelativePath->append(Filename.begin(), Filename.end());
1059 IncluderAndDir.second.getName(), Filename,
1067 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1071 if (SuggestedModule) {
1072 MSSuggestedModule = *SuggestedModule;
1085 ConstSearchDirIterator It =
1097 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1099 ConstSearchDirIterator NextIt = std::next(It);
1102 if (CacheLookup.StartIt == NextIt &&
1103 CacheLookup.RequestingModule == RequestingModule) {
1105 if (CacheLookup.HitIt)
1106 It = CacheLookup.HitIt;
1107 if (CacheLookup.MappedName) {
1108 Filename = CacheLookup.MappedName;
1116 CacheLookup.reset(RequestingModule, NextIt);
1122 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1123 if (Iter == SearchDirHeaderMapIndex.end())
1132 CacheLookup.reset(RequestingModule, NextIt);
1139 bool InUserSpecifiedSystemFramework =
false;
1140 bool IsInHeaderMap =
false;
1141 bool IsFrameworkFoundInDir =
false;
1143 Filename, *
this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
1144 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
1145 IsInHeaderMap, MappedName, OpenFile);
1146 if (!MappedName.empty()) {
1147 assert(IsInHeaderMap &&
"MappedName should come from a header map");
1148 CacheLookup.MappedName =
1149 copyString(MappedName, LookupFileCache.getAllocator());
1155 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap &&
File));
1156 if (IsFrameworkFound)
1160 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1165 FromDir, Includers, isAngled, -1, It);
1169 IncludeNames[*
File] = Filename;
1173 HFI.
DirInfo = CurDir->getDirCharacteristic();
1183 for (
unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1184 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1192 if (SuggestedModule)
1193 *SuggestedModule = MSSuggestedModule;
1197 bool FoundByHeaderMap = !IsMapped ?
false : *IsMapped;
1198 if (!Includers.empty())
1200 Includers.front().second.getName(), Filename,
1201 *
File, isAngled, FoundByHeaderMap);
1204 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1209 if (SuggestedModule)
1210 *SuggestedModule = MSSuggestedModule;
1216 return std::nullopt;
1230 size_t SlashPos = Filename.find(
'/');
1231 if (SlashPos == StringRef::npos)
1232 return std::nullopt;
1235 StringRef ContextName = ContextFileEnt.
getName();
1238 const unsigned DotFrameworkLen = 10;
1239 auto FrameworkPos = ContextName.find(
".framework");
1240 if (FrameworkPos == StringRef::npos ||
1241 (ContextName[FrameworkPos + DotFrameworkLen] !=
'/' &&
1242 ContextName[FrameworkPos + DotFrameworkLen] !=
'\\'))
1243 return std::nullopt;
1247 DotFrameworkLen + 1);
1250 FrameworkName +=
"Frameworks/";
1251 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1252 FrameworkName +=
".framework/";
1255 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1259 if (CacheLookup.second.Directory &&
1260 CacheLookup.first().size() == FrameworkName.size() &&
1261 memcmp(CacheLookup.first().data(), &FrameworkName[0],
1262 CacheLookup.first().size()) != 0)
1263 return std::nullopt;
1266 if (!CacheLookup.second.Directory) {
1267 ++NumSubFrameworkLookups;
1270 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1272 return std::nullopt;
1276 CacheLookup.second.Directory = Dir;
1281 RelativePath->clear();
1282 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1287 HeadersFilename +=
"Headers/";
1289 SearchPath->clear();
1291 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1294 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1295 auto File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1298 HeadersFilename = FrameworkName;
1299 HeadersFilename +=
"PrivateHeaders/";
1301 SearchPath->clear();
1303 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1306 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1307 File = FileMgr.getOptionalFileRef(HeadersFilename,
true);
1310 return std::nullopt;
1315 assert(ContextHFI &&
"context file without file info");
1318 unsigned DirInfo = ContextHFI->
DirInfo;
1321 FrameworkName.pop_back();
1322 if (!findUsableModuleForFrameworkHeader(*
File, FrameworkName,
1323 RequestingModule, SuggestedModule,
1325 return std::nullopt;
1344 bool isModuleHeader,
1345 bool isTextualModuleHeader) {
1362 assert(OtherHFI.
External &&
"expected to merge external HFI");
1378 if (FE.
getUID() >= FileInfo.size())
1379 FileInfo.resize(FE.
getUID() + 1);
1383 if (ExternalSource && !HFI->
Resolved) {
1384 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1385 if (ExternalHFI.IsValid) {
1387 if (ExternalHFI.External)
1401 if (ExternalSource) {
1402 if (FE.
getUID() >= FileInfo.size())
1403 FileInfo.resize(FE.
getUID() + 1);
1405 HFI = &FileInfo[FE.
getUID()];
1408 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1409 if (ExternalHFI.IsValid) {
1411 if (ExternalHFI.External)
1415 }
else if (FE.
getUID() < FileInfo.size()) {
1416 HFI = &FileInfo[FE.
getUID()];
1421 return (HFI && HFI->
IsValid) ? HFI :
nullptr;
1427 if (FE.
getUID() < FileInfo.size()) {
1428 HFI = &FileInfo[FE.
getUID()];
1441 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1447 bool isCompilingModuleHeader) {
1449 if (!isCompilingModuleHeader) {
1458 HFI.mergeModuleMembership(
Role);
1459 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1464 bool ModulesEnabled,
Module *M,
1465 bool &IsFirstIncludeOfFile) {
1481 IsFirstIncludeOfFile =
false;
1484 auto MaybeReenterImportedFile = [&]() ->
bool {
1502 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1506 ModMap.resolveHeaderDirectives(
File);
1526 if (FileInfo.isTextualModuleHeader)
1529 if (FileInfo.isCompilingModuleHeader) {
1532 if (FileInfo.isModuleHeader) {
1537 if (ModMap.isBuiltinHeader(
File))
1546 if (FileInfo.getControllingMacro(ExternalLookup))
1566 FileInfo.isImport =
true;
1573 if (FileInfo.isPragmaOnce ||
1574 (FileInfo.isImport && !MaybeReenterImportedFile()))
1583 FileInfo.getControllingMacro(ExternalLookup)) {
1590 ++NumMultiIncludeFileOptzn;
1600 return SearchDirs.capacity()
1601 + llvm::capacity_in_bytes(FileInfo)
1602 + llvm::capacity_in_bytes(HeaderMaps)
1603 + LookupFileCache.getAllocator().getTotalMemory()
1604 + FrameworkMap.getAllocator().getTotalMemory();
1608 return &DL - &*SearchDirs.begin();
1612 return FrameworkNames.insert(Framework).first->first();
1616 auto It = IncludeNames.find(
File);
1617 if (It == IncludeNames.end())
1625 if (!HSOpts.ImplicitModuleMaps)
1633 DirName = llvm::sys::path::parent_path(DirName);
1634 if (DirName.empty())
1638 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1645 llvm::sys::path::extension(Dir->getName()) ==
".framework")) {
1646 case MMR_NewlyProcessed:
1647 case MMR_AlreadyProcessed: {
1650 const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];
1651 for (
unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1652 DirectoryModuleMap[FixUpDirectories[I]] = MMDS;
1655 case MMR_NoDirectory:
1656 case MMR_InvalidModuleMap:
1666 FixUpDirectories.push_back(*Dir);
1672 bool AllowExcluded)
const {
1673 if (ExternalSource) {
1678 return ModMap.findModuleForHeader(
File, AllowTextual, AllowExcluded);
1683 if (ExternalSource) {
1688 return ModMap.findAllModulesForHeader(
File);
1693 if (ExternalSource) {
1698 return ModMap.findResolvedModulesForHeader(
File);
1702 Module *RequestingModule,
1718 if (SuggestedModule)
1728 if (SuggestedModule)
1736bool HeaderSearch::findUsableModuleForHeader(
1747bool HeaderSearch::findUsableModuleForFrameworkHeader(
1753 SmallVector<std::string, 4> SubmodulePath;
1756 assert(TopFrameworkDir &&
"Could not find the top-most framework dir");
1759 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->
getName());
1763 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1777 bool Diagnose =
true) {
1778 StringRef Filename = llvm::sys::path::filename(
File.getName());
1780 if (Filename ==
"module.map")
1781 llvm::sys::path::append(PrivateFilename,
"module_private.map");
1782 else if (Filename ==
"module.modulemap")
1783 llvm::sys::path::append(PrivateFilename,
"module.private.modulemap");
1785 return std::nullopt;
1786 auto PMMFile =
FileMgr.getOptionalFileRef(PrivateFilename);
1788 if (Diagnose && Filename ==
"module.map")
1789 Diags.
Report(diag::warn_deprecated_module_dot_map)
1790 << PrivateFilename << 1
1791 <<
File.getDir().getName().ends_with(
".framework");
1797 FileID ID,
unsigned *Offset,
1798 StringRef OriginalModuleMapFile) {
1803 Dir = FileMgr.getOptionalDirectoryRef(
".");
1805 if (!OriginalModuleMapFile.empty()) {
1808 Dir = FileMgr.getOptionalDirectoryRef(
1809 llvm::sys::path::parent_path(OriginalModuleMapFile));
1811 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
1812 Dir = FakeFile.getDir();
1815 Dir =
File.getDir();
1818 assert(Dir &&
"parent must exist");
1819 StringRef DirName(Dir->
getName());
1820 if (llvm::sys::path::filename(DirName) ==
"Modules") {
1821 DirName = llvm::sys::path::parent_path(DirName);
1822 if (DirName.ends_with(
".framework"))
1823 if (
auto MaybeDir = FileMgr.getOptionalDirectoryRef(DirName))
1827 assert(Dir &&
"parent must exist");
1831 assert(Dir &&
"module map home directory must exist");
1832 switch (parseAndLoadModuleMapFileImpl(
File, IsSystem, *Dir, ID, Offset)) {
1833 case MMR_AlreadyProcessed:
1834 case MMR_NewlyProcessed:
1836 case MMR_NoDirectory:
1837 case MMR_InvalidModuleMap:
1840 llvm_unreachable(
"Unknown load module map result");
1843HeaderSearch::ModuleMapResult
1844HeaderSearch::parseAndLoadModuleMapFileImpl(
FileEntryRef File,
bool IsSystem,
1849 auto AddResult = LoadedModuleMaps.insert(std::make_pair(
File,
true));
1850 if (!AddResult.second)
1851 return AddResult.first->second ? MMR_AlreadyProcessed
1852 : MMR_InvalidModuleMap;
1855 LoadedModuleMaps[
File] =
false;
1856 return MMR_InvalidModuleMap;
1863 LoadedModuleMaps[
File] =
false;
1864 return MMR_InvalidModuleMap;
1869 return MMR_NewlyProcessed;
1872HeaderSearch::ModuleMapResult
1877 auto AddResult = ParsedModuleMaps.insert(std::make_pair(
File,
true));
1878 if (!AddResult.second)
1879 return AddResult.first->second ? MMR_AlreadyProcessed
1880 : MMR_InvalidModuleMap;
1882 if (ModMap.parseModuleMapFile(
File, IsSystem, Dir, ID)) {
1883 ParsedModuleMaps[
File] =
false;
1884 return MMR_InvalidModuleMap;
1890 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {
1891 ParsedModuleMaps[
File] =
false;
1892 return MMR_InvalidModuleMap;
1897 return MMR_NewlyProcessed;
1902 if (!HSOpts.ImplicitModuleMaps)
1903 return std::nullopt;
1908 llvm::sys::path::append(ModuleMapFileName,
"Modules");
1909 llvm::sys::path::append(ModuleMapFileName,
"module.modulemap");
1910 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1914 ModuleMapFileName = Dir.
getName();
1915 llvm::sys::path::append(ModuleMapFileName,
"module.map");
1916 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName)) {
1917 Diags.Report(diag::warn_deprecated_module_dot_map)
1918 << ModuleMapFileName << 0 << IsFramework;
1925 ModuleMapFileName = Dir.
getName();
1926 llvm::sys::path::append(ModuleMapFileName,
"Modules",
1927 "module.private.modulemap");
1928 if (
auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1931 return std::nullopt;
1938 case MMR_InvalidModuleMap:
1941 ModMap.inferFrameworkModule(Dir, IsSystem,
nullptr);
1944 case MMR_NoDirectory:
1947 case MMR_AlreadyProcessed:
1948 case MMR_NewlyProcessed:
1955HeaderSearch::ModuleMapResult
1958 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1961 return MMR_NoDirectory;
1964HeaderSearch::ModuleMapResult
1967 auto InsertRes = DirectoryModuleMap.insert(std::pair{
1968 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
1969 ModuleMapDirectoryState &MMState = InsertRes.first->second;
1970 if (!InsertRes.second) {
1971 switch (MMState.Status) {
1972 case ModuleMapDirectoryState::Parsed:
1974 case ModuleMapDirectoryState::Loaded:
1975 return MMR_AlreadyProcessed;
1976 case ModuleMapDirectoryState::Invalid:
1977 return MMR_InvalidModuleMap;
1981 if (!MMState.ModuleMapFile)
1984 if (MMState.ModuleMapFile) {
1986 parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1990 if (
Result == MMR_NewlyProcessed)
1991 MMState.Status = ModuleMapDirectoryState::Loaded;
1992 else if (
Result == MMR_InvalidModuleMap)
1993 MMState.Status = ModuleMapDirectoryState::Invalid;
1996 return MMR_InvalidModuleMap;
1999HeaderSearch::ModuleMapResult
2000HeaderSearch::parseModuleMapFile(StringRef DirName,
bool IsSystem,
2002 if (
auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2003 return parseModuleMapFile(*Dir, IsSystem, IsFramework);
2005 return MMR_NoDirectory;
2008HeaderSearch::ModuleMapResult
2011 auto InsertRes = DirectoryModuleMap.insert(std::pair{
2012 Dir, ModuleMapDirectoryState{{}, ModuleMapDirectoryState::Invalid}});
2013 ModuleMapDirectoryState &MMState = InsertRes.first->second;
2014 if (!InsertRes.second) {
2015 switch (MMState.Status) {
2016 case ModuleMapDirectoryState::Parsed:
2017 case ModuleMapDirectoryState::Loaded:
2018 return MMR_AlreadyProcessed;
2019 case ModuleMapDirectoryState::Invalid:
2020 return MMR_InvalidModuleMap;
2024 if (!MMState.ModuleMapFile)
2027 if (MMState.ModuleMapFile) {
2029 parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
2033 if (
Result == MMR_NewlyProcessed)
2034 MMState.Status = ModuleMapDirectoryState::Parsed;
2035 else if (
Result == MMR_InvalidModuleMap)
2036 MMState.Status = ModuleMapDirectoryState::Invalid;
2039 return MMR_InvalidModuleMap;
2045 if (HSOpts.ImplicitModuleMaps) {
2048 bool IsSystem = DL.isSystemHeaderDirectory();
2049 if (DL.isFramework()) {
2052 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2055 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2056 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2058 Dir != DirEnd && !EC; Dir.increment(EC)) {
2059 if (llvm::sys::path::extension(Dir->path()) !=
".framework")
2062 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2067 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2074 if (DL.isHeaderMap())
2083 loadSubdirectoryModuleMaps(DL);
2088 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2092 if (!HSOpts.ImplicitModuleMaps)
2098 if (!DL.isNormalDir())
2107void HeaderSearch::loadSubdirectoryModuleMaps(
DirectoryLookup &SearchDir) {
2109 "Should not be loading subdirectory module maps");
2116 FileMgr.makeAbsolutePath(Dir);
2118 llvm::sys::path::native(Dir, DirNative);
2119 llvm::vfs::FileSystem &FS =
FileMgr.getVirtualFileSystem();
2120 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2121 Dir != DirEnd && !EC; Dir.increment(EC)) {
2122 if (Dir->type() == llvm::sys::fs::file_type::regular_file)
2124 bool IsFramework = llvm::sys::path::extension(Dir->path()) ==
".framework";
2137 MainFile, IsAngled);
2141 llvm::StringRef
File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2142 bool *IsAngled)
const {
2143 using namespace llvm::sys;
2146 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2147 path::make_absolute(WorkingDir, FilePath);
2151 path::remove_dots(FilePath,
true);
2152 path::native(FilePath, path::Style::posix);
2155 unsigned BestPrefixLength = 0;
2160 if (!WorkingDir.empty() && !path::is_absolute(Dir))
2161 path::make_absolute(WorkingDir, Dir);
2162 path::remove_dots(Dir,
true);
2163 for (
auto NI = path::begin(
File), NE = path::end(
File),
2164 DI = path::begin(Dir), DE = path::end(Dir);
2165 NI != NE; ++NI, ++DI) {
2168 unsigned PrefixLength = NI - path::begin(
File);
2169 if (PrefixLength > BestPrefixLength) {
2170 BestPrefixLength = PrefixLength;
2177 if (NI->size() == 1 && DI->size() == 1 &&
2178 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2184 if (NI->ends_with(
".sdk") && DI->ends_with(
".sdk")) {
2185 StringRef NBasename = path::stem(*NI);
2186 StringRef DBasename = path::stem(*DI);
2187 if (DBasename.starts_with(NBasename))
2197 bool BestPrefixIsFramework =
false;
2199 if (DL.isNormalDir()) {
2200 StringRef Dir = DL.getDirRef()->getName();
2201 if (CheckDir(Dir)) {
2203 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2204 BestPrefixIsFramework =
false;
2206 }
else if (DL.isFramework()) {
2207 StringRef Dir = DL.getFrameworkDirRef()->getName();
2208 if (CheckDir(Dir)) {
2211 *IsAngled = BestPrefixLength;
2212 BestPrefixIsFramework =
true;
2219 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2222 BestPrefixIsFramework =
false;
2227 StringRef Filename =
File.drop_front(BestPrefixLength);
2229 if (!DL.isHeaderMap())
2232 StringRef SpelledFilename =
2233 DL.getHeaderMap()->reverseLookupFilename(Filename);
2234 if (!SpelledFilename.empty()) {
2235 Filename = SpelledFilename;
2236 BestPrefixIsFramework =
false;
2243 bool IsPrivateHeader;
2245 if (BestPrefixIsFramework &&
2248 Filename = IncludeSpelling;
2250 return path::convert_to_slash(Filename);
2255 NormalizedPath.assign(Path.begin(), Path.end());
2256 if (!NormalizedPath.empty()) {
2257 FileMgr.makeAbsolutePath(NormalizedPath);
2258 llvm::sys::path::remove_dots(NormalizedPath);
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.
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.
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified file (real or virtual).
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
One of these records is kept for each identifier that is lexed.
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isValid() const
Whether this pointer is non-NULL.
bool parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Load the given module map file, and record any modules we encounter.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
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.
Module * findOrLoadModule(StringRef Name)
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.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
detail::SearchDirIteratorImpl< true > ConstSearchDirIterator
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path, SmallVectorImpl< char > &NormalizedPath)
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
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.