clang: lib/Lex/HeaderSearch.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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"
40#include
41#include
42#include
43#include
44#include
45#include
46#include <system_error>
47#include
48
49using namespace clang;
50
51#define DEBUG_TYPE "file-search"
52
55 NumMultiIncludeFileOptzn,
56 "Number of #includes skipped due to the multi-include optimization.");
59 "Number of subframework lookups.");
60
65 return nullptr;
66
70 }
71
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);
77 }
78 return ControllingMacro;
79}
80
82
87 : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
88 FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}
89
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";
97
98 llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n"
99 << " " << NumMultiIncludeFileOptzn
100 << " #includes skipped due to the multi-include optimization.\n";
101
102 llvm::errs() << NumFrameworkLookups << " framework lookups.\n"
103 << NumSubFrameworkLookups << " subframework lookups.\n";
104}
105
107 std::vector 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);
117
118 indexInitialHeaderMaps();
119}
120
122 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
123 SearchDirs.insert(SearchDirs.begin() + idx, dir);
124 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);
125 if (!isAngled)
126 AngledDirIdx++;
127 SystemDirIdx++;
128}
129
131 std::vector UserEntryUsage(HSOpts.UserEntries.size());
132 for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {
133
134 if (SearchDirsUsage[I]) {
135 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);
136
137 if (UserEntryIdxIt != SearchDirToHSEntry.end())
138 UserEntryUsage[UserEntryIdxIt->second] = true;
139 }
140 }
141 return UserEntryUsage;
142}
143
145 std::vector VFSUsage;
147 return VFSUsage;
148
149 llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
150
151
152
153 RootFS.visit([&](llvm::vfs::FileSystem &FS) {
154 if (auto *RFS = dyn_castllvm::vfs::RedirectingFileSystem(&FS)) {
155
156
157
158 if (!RFS->getOverlayFileDir().empty()) {
159 VFSUsage.push_back(RFS->hasBeenUsed());
160 RFS->clearHasBeenUsed();
161 }
162 }
163 });
164 assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() &&
165 "A different number of RedirectingFileSystem's were present than "
166 "-ivfsoverlay options passed to Clang!");
167
168 std::reverse(VFSUsage.begin(), VFSUsage.end());
169 return VFSUsage;
170}
171
172
173
175
176
177 if (!HeaderMaps.empty()) {
178 for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
179
180
181 if (HeaderMaps[i].first == FE)
182 return HeaderMaps[i].second.get();
183 }
184
185 if (std::unique_ptr HM = HeaderMap::Create(FE, FileMgr)) {
186 HeaderMaps.emplace_back(FE, std::move(HM));
187 return HeaderMaps.back().second.get();
188 }
189
190 return nullptr;
191}
192
193
196 for (auto &HM : HeaderMaps)
197 Names.push_back(std::string(HM.first.getName()));
198}
199
203
204
206 return {};
208}
209
211 bool FileMapOnly) {
212
213 auto i(HSOpts.PrebuiltModuleFiles.find(ModuleName));
214 if (i != HSOpts.PrebuiltModuleFiles.end())
215 return i->second;
216
217 if (FileMapOnly || HSOpts.PrebuiltModulePaths.empty())
218 return {};
219
220
221
222 for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
224 FileMgr.makeAbsolutePath(Result);
225 if (ModuleName.contains(':'))
226
227
228
229 llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +
230 ModuleName.split(':').second +
231 ".pcm");
232 else
233 llvm::sys::path::append(Result, ModuleName + ".pcm");
235 return std::string(Result);
236 }
237
238 return {};
239}
240
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);
255 }
256 return {};
257}
258
260 StringRef ModuleMapPath) {
261 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,
263}
264
265std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,
266 StringRef ModuleMapPath,
267 StringRef CachePath) {
268
269
270 if (CachePath.empty())
271 return {};
272
274
276 llvm::sys::path::append(Result, ModuleName + ".pcm");
277 } else {
278
279
280
281
282
283
284
285 SmallString<128> CanonicalPath(ModuleMapPath);
286 if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath))
287 return {};
288
289 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());
290
291 SmallString<128> HashStr;
292 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);
293 llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");
294 }
295 return Result.str().str();
296}
297
300 bool AllowExtraModuleMapSearch) {
301
302 Module *Module = ModMap.findOrLoadModule(ModuleName);
303 if (Module || !AllowSearch || !HSOpts.ImplicitModuleMaps)
305
306 StringRef SearchName = ModuleName;
308 AllowExtraModuleMapSearch);
309
310
311
312
313
314
315
316
317
318 if ( && SearchName.consume_back("_Private"))
320 AllowExtraModuleMapSearch);
321 if ( && SearchName.consume_back("Private"))
323 AllowExtraModuleMapSearch);
325}
326
329 bool AllowExtraModuleMapSearch) {
331
332
333
335 if (Dir.isFramework()) {
336
337
338
340 FrameworkDirName += Dir.getFrameworkDirRef()->getName();
341 llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
342 if (auto FrameworkDir =
343 FileMgr.getOptionalDirectoryRef(FrameworkDirName)) {
344 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;
345 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);
347 break;
348 }
349 }
350
351
352
353
354 if (!Dir.isNormalDir())
355 continue;
356
357 bool IsSystem = Dir.isSystemHeaderDirectory();
358
359
360 DirectoryEntryRef NormalDir = *Dir.getDirRef();
361
362 if (parseModuleMapFile(NormalDir, IsSystem,
363 false) == MMR_NewlyProcessed) {
364
365
366 Module = ModMap.findOrLoadModule(ModuleName);
368 break;
369 }
370
371
372
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) {
378
379 Module = ModMap.findOrLoadModule(ModuleName);
381 break;
382 }
383
384 if (HSOpts.AllowModuleMapSubdirectorySearch) {
385
386
387 if (Dir.haveSearchedAllModuleMaps())
388 continue;
389
390
391
392 if (AllowExtraModuleMapSearch)
393 loadSubdirectoryModuleMaps(Dir);
394
395
396 Module = ModMap.findOrLoadModule(ModuleName);
398 break;
399 }
400 }
401
403}
404
405void HeaderSearch::indexInitialHeaderMaps() {
406 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());
407
408
409 for (unsigned i = 0; i != SearchDirs.size(); ++i) {
410 auto &Dir = SearchDirs[i];
411
412
413
414
415 if (!Dir.isHeaderMap()) {
416 SearchDirHeaderMapIndex = std::move(Index);
417 FirstNonHeaderMapSearchDirIdx = i;
418 break;
419 }
420
421
422 auto Callback = [&](StringRef Filename) {
423 Index.try_emplace(Filename.lower(), i);
424 };
425 Dir.getHeaderMap()->forEachKey(Callback);
426 }
427}
428
429
430
431
432
433
434
440 assert(isHeaderMap() && "Unknown DirectoryLookup");
442}
443
446 bool IsSystemHeaderDir, Module *RequestingModule,
448 bool CacheFailures ) {
449
450
453
454
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)
461 }
462 return std::nullopt;
463 }
464
465
466 if (!findUsableModuleForHeader(
467 *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,
468 SuggestedModule, IsSystemHeaderDir))
469 return std::nullopt;
470
471 return *File;
472}
473
474
475
480 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
482 bool OpenFile) const {
483 InUserSpecifiedSystemFramework = false;
484 IsInHeaderMap = false;
485 MappedName.clear();
486
489
491 llvm::sys::path::append(TmpDir, Filename);
492 if (SearchPath) {
494 SearchPath->clear();
495 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
496 }
497 if (RelativePath) {
498 RelativePath->clear();
499 RelativePath->append(Filename.begin(), Filename.end());
500 }
501
502 return HS.getFileAndSuggestModule(
504 RequestingModule, SuggestedModule, OpenFile);
505 }
506
508 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
509 RequestingModule, SuggestedModule,
510 InUserSpecifiedSystemFramework, IsFrameworkFound);
511
512 assert(isHeaderMap() && "Unknown directory lookup");
516 if (Dest.empty())
517 return std::nullopt;
518
519 IsInHeaderMap = true;
520
521 auto FixupSearchPathAndFindUsableModule =
523 if (SearchPath) {
524 StringRef SearchPathRef(getName());
525 SearchPath->clear();
526 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
527 }
528 if (RelativePath) {
529 RelativePath->clear();
530 RelativePath->append(Filename.begin(), Filename.end());
531 }
532 if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(),
533 RequestingModule, SuggestedModule,
535 return std::nullopt;
536 }
538 };
539
540
541
542
543 if (llvm::sys::path::is_relative(Dest)) {
544 MappedName.append(Dest.begin(), Dest.end());
545 Filename = StringRef(MappedName.begin(), MappedName.size());
547 }
548
550 return FixupSearchPathAndFindUsableModule(*Res);
551 }
552
553
554
555
556
557 HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);
558 return std::nullopt;
559}
560
561
562
563
564
565
566
570 assert(llvm::sys::path::extension(DirName) == ".framework" &&
571 "Not a framework directory");
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587 auto TopFrameworkDir = FileMgr.getOptionalDirectoryRef(DirName);
588
589 if (TopFrameworkDir)
590 DirName = FileMgr.getCanonicalName(*TopFrameworkDir);
591 do {
592
593 DirName = llvm::sys::path::parent_path(DirName);
594 if (DirName.empty())
595 break;
596
597
598 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
599 if (!Dir)
600 break;
601
602
603
604 if (llvm::sys::path::extension(DirName) == ".framework") {
605 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));
606 TopFrameworkDir = *Dir;
607 }
608 } while (true);
609
610 return TopFrameworkDir;
611}
612
614 bool HasSuggestedModule) {
615 return HasSuggestedModule ||
617}
618
619
620
625 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
626 FileManager &FileMgr = HS.getFileMgr();
627
628
629 size_t SlashPos = Filename.find('/');
630 if (SlashPos == StringRef::npos)
631 return std::nullopt;
632
633
634
635 FrameworkCacheEntry &CacheEntry =
637
638
640 return std::nullopt;
641
642
643
644
645 SmallString<1024> FrameworkName;
647 if (FrameworkName.empty() || FrameworkName.back() != '/')
648 FrameworkName.push_back('/');
649
650
651 StringRef ModuleName(Filename.begin(), SlashPos);
652 FrameworkName += ModuleName;
653
654
655 FrameworkName += ".framework/";
656
657
659 ++NumFrameworkLookups;
660
661
663 if (!Dir)
664 return std::nullopt;
665
666
667
669
670
671
673 SmallString<1024> SystemFrameworkMarker(FrameworkName);
674 SystemFrameworkMarker += ".system_framework";
677 }
678 }
679
680
683
684 if (RelativePath) {
685 RelativePath->clear();
686 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
687 }
688
689
690 unsigned OrigSize = FrameworkName.size();
691
692 FrameworkName += "Headers/";
693
694 if (SearchPath) {
695 SearchPath->clear();
696
697 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
698 }
699
700 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
701
703 FileMgr.getOptionalFileRef(FrameworkName, !SuggestedModule);
705
706 const char *Private = "Private";
707 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
709 if (SearchPath)
710 SearchPath->insert(SearchPath->begin()+OrigSize, Private,
712
714 !SuggestedModule);
715 }
716
717
719
720 StringRef FrameworkPath = File->getDir().getName();
721 bool FoundFramework = false;
722 do {
723
725 if (!Dir)
726 break;
727
728
729
730 if (llvm::sys::path::extension(FrameworkPath) == ".framework") {
731 FoundFramework = true;
732 break;
733 }
734
735
736 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);
737 if (FrameworkPath.empty())
738 break;
739 } while (true);
740
742 if (FoundFramework) {
743 if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath,
744 RequestingModule,
745 SuggestedModule, IsSystem))
746 return std::nullopt;
747 } else {
748 if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule,
749 SuggestedModule, IsSystem))
750 return std::nullopt;
751 }
752 }
754 return *File;
755 return std::nullopt;
756}
757
758void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
761 CacheLookup.HitIt = HitIt;
762 noteLookupUsage(HitIt.Idx, Loc);
763}
764
765void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {
766 SearchDirsUsage[HitIdx] = true;
767
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;
772}
773
775 ModMap.setTarget(Target);
776}
777
778
779
780
781
782
783
784
789 if (MSFE && FE != *MSFE) {
790 Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();
791 return true;
792 }
793 return false;
794}
795
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';
801 return CopyStr;
802}
803
807 using namespace llvm::sys;
808 path::const_iterator I = path::begin(Path);
809 path::const_iterator E = path::end(Path);
810 IsPrivateHeader = false;
811
812
813
814
815
816
817
818
819
820 int FoundComp = 0;
821 while (I != E) {
822 if (*I == "Headers") {
823 ++FoundComp;
824 } else if (*I == "PrivateHeaders") {
825 ++FoundComp;
826 IsPrivateHeader = true;
827 } else if (I->ends_with(".framework")) {
828 StringRef Name = I->drop_back(10);
829
830 FrameworkName.clear();
831 FrameworkName.append(Name.begin(), Name.end());
832 IncludeSpelling.clear();
833 IncludeSpelling.append(Name.begin(), Name.end());
834 FoundComp = 1;
835 } else if (FoundComp >= 2) {
836 IncludeSpelling.push_back('/');
837 IncludeSpelling.append(I->begin(), I->end());
838 }
839 ++I;
840 }
841
842 return !FrameworkName.empty() && FoundComp >= 2;
843}
844
845static void
847 StringRef Includer, StringRef IncludeFilename,
848 FileEntryRef IncludeFE, bool isAngled = false,
849 bool FoundByHeaderMap = false) {
850 bool IsIncluderPrivateHeader = false;
854 FromIncludeSpelling))
855 return;
856 bool IsIncludeePrivateHeader = false;
857 bool IsIncludeeInFramework =
859 ToFramework, ToIncludeSpelling);
860
861 if (!isAngled && !FoundByHeaderMap) {
863 if (IsIncludeeInFramework) {
864 NewInclude += ToIncludeSpelling;
865 NewInclude += ">";
866 } else {
867 NewInclude += IncludeFilename;
868 NewInclude += ">";
869 }
870 Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)
871 << IncludeFilename
873 }
874
875
876
877
878 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&
879 IsIncludeePrivateHeader && FromFramework == ToFramework)
880 Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)
881 << IncludeFilename;
882}
883
886 SourceLocation IncludeLoc, ConstSearchDirIterator FromDir,
887 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,
888 bool isAngled, int IncluderLoopIndex, ConstSearchDirIterator MainLoopIt) {
889
890 if (Diags.isIgnored(diag::warn_header_shadowing, IncludeLoc) ||
891 DiagnosedShadowing)
892 return;
893
894 if (MainLoopIt && MainLoopIt->isSystemHeaderDirectory())
895 return;
896
897 DiagnosedShadowing = true;
898
899
900 if (!MainLoopIt) {
901 for (size_t i = IncluderLoopIndex + 1; i < Includers.size(); ++i) {
902 const auto &IncluderAndDir = Includers[i];
904 llvm::sys::path::append(TmpDir, Filename);
905 if (auto File = getFileMgr().getFileRef(TmpDir, false, false)) {
906 if (&File->getFileEntry() == *FE)
907 continue;
908 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
909 << Filename << (*FE).getDir().getName()
910 << IncluderAndDir.second.getName();
911 return;
912 } else {
913 llvm::errorToErrorCode(File.takeError());
914 }
915 }
916 }
917
918
919 ConstSearchDirIterator It =
921 if (MainLoopIt) {
922 It = std::next(MainLoopIt);
923 } else if (FromDir) {
924 It = FromDir;
925 }
927
929 continue;
931 llvm::sys::path::append(TmpPath, Filename);
932 if (auto File = getFileMgr().getFileRef(TmpPath, false, false)) {
933 if (&File->getFileEntry() == *FE)
934 continue;
935 Diags.Report(IncludeLoc, diag::warn_header_shadowing)
936 << Filename << (*FE).getDir().getName() << It->getName();
937 return;
938 } else {
939 llvm::errorToErrorCode(File.takeError());
940 }
941 }
942}
943
944
945
946
947
948
950 StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
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;
959
960 if (IsMapped)
961 *IsMapped = false;
962
963 if (IsFrameworkFound)
964 *IsFrameworkFound = false;
965
966 if (SuggestedModule)
968
969
970 if (llvm::sys::path::is_absolute(Filename)) {
971 CurDir = nullptr;
972
973
974 if (FromDir)
975 return std::nullopt;
976
977 if (SearchPath)
978 SearchPath->clear();
979 if (RelativePath) {
980 RelativePath->clear();
981 RelativePath->append(Filename.begin(), Filename.end());
982 }
983
984 return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,
985 false,
986 RequestingModule, SuggestedModule, OpenFile,
987 CacheFailures);
988 }
989
990
993 bool DiagnosedShadowing = false;
994
995
996
997
998
999
1000 if (!Includers.empty() && !isAngled) {
1002 bool First = true;
1003 for (const auto &IncluderAndDir : Includers) {
1005
1006
1007 TmpDir = IncluderAndDir.second.getName();
1008 llvm::sys::path::append(TmpDir, Filename);
1009
1010
1011
1012
1013
1014
1015
1016
1017 bool IncluderIsSystemHeader = [&]() {
1018 if (!Includer)
1019 return BuildSystemModule;
1021 assert(HFI && "includer without file info");
1023 }();
1025 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,
1026 RequestingModule, SuggestedModule)) {
1028 FromDir, Includers, isAngled,
1029 &IncluderAndDir - Includers.begin(), nullptr);
1030 if (!Includer) {
1031 assert(First && "only first includer can have no file");
1032 return FE;
1033 }
1034
1035
1036
1037
1038
1039
1040
1042 assert(FromHFI && "includer without file info");
1043 unsigned DirInfo = FromHFI->DirInfo;
1044
1046 ToHFI.DirInfo = DirInfo;
1047
1048 if (SearchPath) {
1049 StringRef SearchPathRef(IncluderAndDir.second.getName());
1050 SearchPath->clear();
1051 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
1052 }
1053 if (RelativePath) {
1054 RelativePath->clear();
1055 RelativePath->append(Filename.begin(), Filename.end());
1056 }
1059 IncluderAndDir.second.getName(), Filename,
1060 *FE);
1061 return FE;
1062 }
1063
1064
1065
1066
1067 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {
1068 return FE;
1069 } else {
1070 MSFE = FE;
1071 if (SuggestedModule) {
1072 MSSuggestedModule = *SuggestedModule;
1074 }
1075 break;
1076 }
1077 }
1079 }
1080 }
1081
1082 CurDir = nullptr;
1083
1084
1085 ConstSearchDirIterator It =
1087
1088
1089
1090 if (FromDir)
1091 It = FromDir;
1092
1093
1094
1095
1096
1097 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];
1098
1099 ConstSearchDirIterator NextIt = std::next(It);
1100
1101 if (!SkipCache) {
1102 if (CacheLookup.StartIt == NextIt &&
1103 CacheLookup.RequestingModule == RequestingModule) {
1104
1105 if (CacheLookup.HitIt)
1106 It = CacheLookup.HitIt;
1107 if (CacheLookup.MappedName) {
1108 Filename = CacheLookup.MappedName;
1109 if (IsMapped)
1110 *IsMapped = true;
1111 }
1112 } else {
1113
1114
1115
1116 CacheLookup.reset(RequestingModule, NextIt);
1117
1118 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {
1119
1120
1121
1122 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());
1123 if (Iter == SearchDirHeaderMapIndex.end())
1124
1126 else
1127
1129 }
1130 }
1131 } else {
1132 CacheLookup.reset(RequestingModule, NextIt);
1133 }
1134
1136
1137
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());
1150 }
1151 if (IsMapped)
1152
1153
1154
1155 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));
1156 if (IsFrameworkFound)
1157
1158
1159
1160 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);
1162 continue;
1163
1165 FromDir, Includers, isAngled, -1, It);
1166
1167 CurDir = It;
1168
1169 IncludeNames[*File] = Filename;
1170
1171
1173 HFI.DirInfo = CurDir->getDirCharacteristic();
1174
1175
1176
1177
1180
1181
1182
1183 for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {
1184 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {
1187 break;
1188 }
1189 }
1190
1192 if (SuggestedModule)
1193 *SuggestedModule = MSSuggestedModule;
1194 return MSFE;
1195 }
1196
1197 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;
1198 if (!Includers.empty())
1200 Includers.front().second.getName(), Filename,
1201 *File, isAngled, FoundByHeaderMap);
1202
1203
1204 cacheLookupSuccess(CacheLookup, It, IncludeLoc);
1205 return File;
1206 }
1207
1209 if (SuggestedModule)
1210 *SuggestedModule = MSSuggestedModule;
1211 return MSFE;
1212 }
1213
1214
1216 return std::nullopt;
1217}
1218
1219
1220
1221
1222
1223
1225 StringRef Filename, FileEntryRef ContextFileEnt,
1228
1229
1230 size_t SlashPos = Filename.find('/');
1231 if (SlashPos == StringRef::npos)
1232 return std::nullopt;
1233
1234
1235 StringRef ContextName = ContextFileEnt.getName();
1236
1237
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;
1244
1245 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +
1246 FrameworkPos +
1247 DotFrameworkLen + 1);
1248
1249
1250 FrameworkName += "Frameworks/";
1251 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);
1252 FrameworkName += ".framework/";
1253
1254 auto &CacheLookup =
1255 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),
1257
1258
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;
1264
1265
1266 if (!CacheLookup.second.Directory) {
1267 ++NumSubFrameworkLookups;
1268
1269
1270 auto Dir = FileMgr.getOptionalDirectoryRef(FrameworkName);
1271 if (!Dir)
1272 return std::nullopt;
1273
1274
1275
1276 CacheLookup.second.Directory = Dir;
1277 }
1278
1279
1280 if (RelativePath) {
1281 RelativePath->clear();
1282 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());
1283 }
1284
1285
1287 HeadersFilename += "Headers/";
1288 if (SearchPath) {
1289 SearchPath->clear();
1290
1291 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1292 }
1293
1294 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1295 auto File = FileMgr.getOptionalFileRef(HeadersFilename, true);
1296 if () {
1297
1298 HeadersFilename = FrameworkName;
1299 HeadersFilename += "PrivateHeaders/";
1300 if (SearchPath) {
1301 SearchPath->clear();
1302
1303 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);
1304 }
1305
1306 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
1307 File = FileMgr.getOptionalFileRef(HeadersFilename, true);
1308
1310 return std::nullopt;
1311 }
1312
1313
1315 assert(ContextHFI && "context file without file info");
1316
1317
1318 unsigned DirInfo = ContextHFI->DirInfo;
1320
1321 FrameworkName.pop_back();
1322 if (!findUsableModuleForFrameworkHeader(*File, FrameworkName,
1323 RequestingModule, SuggestedModule,
1324 false))
1325 return std::nullopt;
1326
1327 return *File;
1328}
1329
1330
1331
1332
1333
1342
1344 bool isModuleHeader,
1345 bool isTextualModuleHeader) {
1349 else
1351}
1352
1357
1358
1359
1362 assert(OtherHFI.External && "expected to merge external HFI");
1363
1368
1371
1375}
1376
1378 if (FE.getUID() >= FileInfo.size())
1379 FileInfo.resize(FE.getUID() + 1);
1380
1382
1383 if (ExternalSource && !HFI->Resolved) {
1384 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1385 if (ExternalHFI.IsValid) {
1387 if (ExternalHFI.External)
1389 }
1390 }
1391
1393
1394
1396 return *HFI;
1397}
1398
1401 if (ExternalSource) {
1402 if (FE.getUID() >= FileInfo.size())
1403 FileInfo.resize(FE.getUID() + 1);
1404
1405 HFI = &FileInfo[FE.getUID()];
1406
1408 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
1409 if (ExternalHFI.IsValid) {
1411 if (ExternalHFI.External)
1413 }
1414 }
1415 } else if (FE.getUID() < FileInfo.size()) {
1416 HFI = &FileInfo[FE.getUID()];
1417 } else {
1418 HFI = nullptr;
1419 }
1420
1421 return (HFI && HFI->IsValid) ? HFI : nullptr;
1422}
1423
1427 if (FE.getUID() < FileInfo.size()) {
1428 HFI = &FileInfo[FE.getUID()];
1429 } else {
1430 HFI = nullptr;
1431 }
1432
1433 return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr;
1434}
1435
1437
1438
1439
1441 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
1442 return false;
1443}
1444
1447 bool isCompilingModuleHeader) {
1448
1449 if (!isCompilingModuleHeader) {
1451 return;
1454 return;
1455 }
1456
1458 HFI.mergeModuleMembership(Role);
1459 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1460}
1461
1464 bool ModulesEnabled, Module *M,
1465 bool &IsFirstIncludeOfFile) {
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480 ++NumIncluded;
1481 IsFirstIncludeOfFile = false;
1483
1484 auto MaybeReenterImportedFile = [&]() -> bool {
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502 if (!ModulesEnabled || FileInfo.isPragmaOnce)
1503 return false;
1504
1505
1506 ModMap.resolveHeaderDirectives(File);
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526 if (FileInfo.isTextualModuleHeader)
1527 return true;
1528
1529 if (FileInfo.isCompilingModuleHeader) {
1530
1531
1532 if (FileInfo.isModuleHeader) {
1533
1534
1535
1536
1537 if (ModMap.isBuiltinHeader(File))
1538 return true;
1539 } else {
1540
1541
1542
1543
1544
1545
1546 if (FileInfo.getControllingMacro(ExternalLookup))
1547 return true;
1548 }
1549 }
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560 return false;
1561 };
1562
1563 if (isImport) {
1564
1565
1566 FileInfo.isImport = true;
1568 return false;
1569 } else {
1570
1571
1572
1573 if (FileInfo.isPragmaOnce ||
1574 (FileInfo.isImport && !MaybeReenterImportedFile()))
1575 return false;
1576 }
1577
1578
1579
1580
1581
1583 FileInfo.getControllingMacro(ExternalLookup)) {
1584
1585
1586
1587
1590 ++NumMultiIncludeFileOptzn;
1591 return false;
1592 }
1593 }
1594
1596 return true;
1597}
1598
1600 return SearchDirs.capacity()
1601 + llvm::capacity_in_bytes(FileInfo)
1602 + llvm::capacity_in_bytes(HeaderMaps)
1603 + LookupFileCache.getAllocator().getTotalMemory()
1604 + FrameworkMap.getAllocator().getTotalMemory();
1605}
1606
1608 return &DL - &*SearchDirs.begin();
1609}
1610
1612 return FrameworkNames.insert(Framework).first->first();
1613}
1614
1616 auto It = IncludeNames.find(File);
1617 if (It == IncludeNames.end())
1618 return {};
1619 return It->second;
1620}
1621
1624 bool IsSystem) {
1625 if (!HSOpts.ImplicitModuleMaps)
1626 return false;
1627
1629
1630 StringRef DirName = FileName;
1631 do {
1632
1633 DirName = llvm::sys::path::parent_path(DirName);
1634 if (DirName.empty())
1635 return false;
1636
1637
1638 auto Dir = FileMgr.getOptionalDirectoryRef(DirName);
1639 if (!Dir)
1640 return false;
1641
1642
1644 *Dir, IsSystem,
1645 llvm::sys::path::extension(Dir->getName()) == ".framework")) {
1646 case MMR_NewlyProcessed:
1647 case MMR_AlreadyProcessed: {
1648
1649
1650 const ModuleMapDirectoryState &MMDS = DirectoryModuleMap[*Dir];
1651 for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
1652 DirectoryModuleMap[FixUpDirectories[I]] = MMDS;
1653 return true;
1654 }
1655 case MMR_NoDirectory:
1656 case MMR_InvalidModuleMap:
1657 break;
1658 }
1659
1660
1661 if (*Dir == Root)
1662 return false;
1663
1664
1665
1666 FixUpDirectories.push_back(*Dir);
1667 } while (true);
1668}
1669
1672 bool AllowExcluded) const {
1673 if (ExternalSource) {
1674
1675
1677 }
1678 return ModMap.findModuleForHeader(File, AllowTextual, AllowExcluded);
1679}
1680
1683 if (ExternalSource) {
1684
1685
1687 }
1688 return ModMap.findAllModulesForHeader(File);
1689}
1690
1693 if (ExternalSource) {
1694
1695
1697 }
1698 return ModMap.findResolvedModulesForHeader(File);
1699}
1700
1702 Module *RequestingModule,
1706
1707
1708
1712
1713
1714
1715
1716
1718 if (SuggestedModule)
1720 return true;
1721 }
1722
1723
1724 return false;
1725 }
1726 }
1727
1728 if (SuggestedModule)
1732
1733 return true;
1734}
1735
1736bool HeaderSearch::findUsableModuleForHeader(
1740
1741 hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);
1742 return suggestModule(*this, File, RequestingModule, SuggestedModule);
1743 }
1744 return true;
1745}
1746
1747bool HeaderSearch::findUsableModuleForFrameworkHeader(
1750
1752
1753 SmallVector<std::string, 4> SubmodulePath;
1756 assert(TopFrameworkDir && "Could not find the top-most framework dir");
1757
1758
1759 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());
1760
1761
1762
1763 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);
1764
1765
1766
1767
1768
1769 return suggestModule(*this, File, RequestingModule, SuggestedModule);
1770 }
1771 return true;
1772}
1773
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");
1784 else
1785 return std::nullopt;
1786 auto PMMFile = FileMgr.getOptionalFileRef(PrivateFilename);
1787 if (PMMFile) {
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");
1792 }
1793 return PMMFile;
1794}
1795
1797 FileID ID, unsigned *Offset,
1798 StringRef OriginalModuleMapFile) {
1799
1800
1803 Dir = FileMgr.getOptionalDirectoryRef(".");
1804 } else {
1805 if (!OriginalModuleMapFile.empty()) {
1806
1807
1808 Dir = FileMgr.getOptionalDirectoryRef(
1809 llvm::sys::path::parent_path(OriginalModuleMapFile));
1810 if (!Dir) {
1811 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);
1812 Dir = FakeFile.getDir();
1813 }
1814 } else {
1815 Dir = File.getDir();
1816 }
1817
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))
1824 Dir = *MaybeDir;
1825
1826
1827 assert(Dir && "parent must exist");
1828 }
1829 }
1830
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:
1835 return false;
1836 case MMR_NoDirectory:
1837 case MMR_InvalidModuleMap:
1838 return true;
1839 }
1840 llvm_unreachable("Unknown load module map result");
1841}
1842
1843HeaderSearch::ModuleMapResult
1844HeaderSearch::parseAndLoadModuleMapFileImpl(FileEntryRef File, bool IsSystem,
1846 unsigned *Offset) {
1847
1848
1849 auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));
1850 if (!AddResult.second)
1851 return AddResult.first->second ? MMR_AlreadyProcessed
1852 : MMR_InvalidModuleMap;
1853
1855 LoadedModuleMaps[File] = false;
1856 return MMR_InvalidModuleMap;
1857 }
1858
1859
1863 LoadedModuleMaps[File] = false;
1864 return MMR_InvalidModuleMap;
1865 }
1866 }
1867
1868
1869 return MMR_NewlyProcessed;
1870}
1871
1872HeaderSearch::ModuleMapResult
1873HeaderSearch::parseModuleMapFileImpl(FileEntryRef File, bool IsSystem,
1875
1876
1877 auto AddResult = ParsedModuleMaps.insert(std::make_pair(File, true));
1878 if (!AddResult.second)
1879 return AddResult.first->second ? MMR_AlreadyProcessed
1880 : MMR_InvalidModuleMap;
1881
1882 if (ModMap.parseModuleMapFile(File, IsSystem, Dir, ID)) {
1883 ParsedModuleMaps[File] = false;
1884 return MMR_InvalidModuleMap;
1885 }
1886
1887
1890 if (ModMap.parseModuleMapFile(*PMMFile, IsSystem, Dir)) {
1891 ParsedModuleMaps[File] = false;
1892 return MMR_InvalidModuleMap;
1893 }
1894 }
1895
1896
1897 return MMR_NewlyProcessed;
1898}
1899
1902 if (!HSOpts.ImplicitModuleMaps)
1903 return std::nullopt;
1904
1905
1907 if (IsFramework)
1908 llvm::sys::path::append(ModuleMapFileName, "Modules");
1909 llvm::sys::path::append(ModuleMapFileName, "module.modulemap");
1910 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1911 return *F;
1912
1913
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;
1919 return *F;
1920 }
1921
1922
1923
1924 if (IsFramework) {
1925 ModuleMapFileName = Dir.getName();
1926 llvm::sys::path::append(ModuleMapFileName, "Modules",
1927 "module.private.modulemap");
1928 if (auto F = FileMgr.getOptionalFileRef(ModuleMapFileName))
1929 return *F;
1930 }
1931 return std::nullopt;
1932}
1933
1935 bool IsSystem) {
1936
1938 case MMR_InvalidModuleMap:
1939
1941 ModMap.inferFrameworkModule(Dir, IsSystem, nullptr);
1942 break;
1943
1944 case MMR_NoDirectory:
1945 return nullptr;
1946
1947 case MMR_AlreadyProcessed:
1948 case MMR_NewlyProcessed:
1949 break;
1950 }
1951
1953}
1954
1955HeaderSearch::ModuleMapResult
1957 bool IsFramework) {
1958 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
1960
1961 return MMR_NoDirectory;
1962}
1963
1964HeaderSearch::ModuleMapResult
1966 bool IsFramework) {
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:
1973 break;
1974 case ModuleMapDirectoryState::Loaded:
1975 return MMR_AlreadyProcessed;
1976 case ModuleMapDirectoryState::Invalid:
1977 return MMR_InvalidModuleMap;
1978 };
1979 }
1980
1981 if (!MMState.ModuleMapFile)
1983
1984 if (MMState.ModuleMapFile) {
1985 ModuleMapResult Result =
1986 parseAndLoadModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
1987
1988
1989
1990 if (Result == MMR_NewlyProcessed)
1991 MMState.Status = ModuleMapDirectoryState::Loaded;
1992 else if (Result == MMR_InvalidModuleMap)
1993 MMState.Status = ModuleMapDirectoryState::Invalid;
1995 }
1996 return MMR_InvalidModuleMap;
1997}
1998
1999HeaderSearch::ModuleMapResult
2000HeaderSearch::parseModuleMapFile(StringRef DirName, bool IsSystem,
2001 bool IsFramework) {
2002 if (auto Dir = FileMgr.getOptionalDirectoryRef(DirName))
2003 return parseModuleMapFile(*Dir, IsSystem, IsFramework);
2004
2005 return MMR_NoDirectory;
2006}
2007
2008HeaderSearch::ModuleMapResult
2009HeaderSearch::parseModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
2010 bool IsFramework) {
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;
2021 };
2022 }
2023
2024 if (!MMState.ModuleMapFile)
2026
2027 if (MMState.ModuleMapFile) {
2028 ModuleMapResult Result =
2029 parseModuleMapFileImpl(*MMState.ModuleMapFile, IsSystem, Dir);
2030
2031
2032
2033 if (Result == MMR_NewlyProcessed)
2034 MMState.Status = ModuleMapDirectoryState::Parsed;
2035 else if (Result == MMR_InvalidModuleMap)
2036 MMState.Status = ModuleMapDirectoryState::Invalid;
2038 }
2039 return MMR_InvalidModuleMap;
2040}
2041
2043 Modules.clear();
2044
2045 if (HSOpts.ImplicitModuleMaps) {
2046
2048 bool IsSystem = DL.isSystemHeaderDirectory();
2049 if (DL.isFramework()) {
2050 std::error_code EC;
2052 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);
2053
2054
2055 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2056 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),
2057 DirEnd;
2058 Dir != DirEnd && !EC; Dir.increment(EC)) {
2059 if (llvm::sys::path::extension(Dir->path()) != ".framework")
2060 continue;
2061
2062 auto FrameworkDir = FileMgr.getOptionalDirectoryRef(Dir->path());
2063 if (!FrameworkDir)
2064 continue;
2065
2066
2067 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,
2068 IsSystem);
2069 }
2070 continue;
2071 }
2072
2073
2074 if (DL.isHeaderMap())
2075 continue;
2076
2077
2079 false);
2080
2081
2082
2083 loadSubdirectoryModuleMaps(DL);
2084 }
2085 }
2086
2087
2088 llvm::append_range(Modules, llvm::make_second_range(ModMap.modules()));
2089}
2090
2092 if (!HSOpts.ImplicitModuleMaps)
2093 return;
2094
2095
2097
2098 if (!DL.isNormalDir())
2099 continue;
2100
2101
2103 DL.isFramework());
2104 }
2105}
2106
2107void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
2109 "Should not be loading subdirectory module maps");
2110
2112 return;
2113
2114 std::error_code EC;
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)
2123 continue;
2124 bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
2125 if (IsFramework == SearchDir.isFramework())
2129 }
2130
2132}
2133
2135 FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {
2137 MainFile, IsAngled);
2138}
2139
2141 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,
2142 bool *IsAngled) const {
2143 using namespace llvm::sys;
2144
2146 if (!WorkingDir.empty() && !path::is_absolute(FilePath))
2147 path::make_absolute(WorkingDir, FilePath);
2148
2149
2150
2151 path::remove_dots(FilePath, true);
2152 path::native(FilePath, path::Style::posix);
2153 File = FilePath;
2154
2155 unsigned BestPrefixLength = 0;
2156
2157
2158
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) {
2166 if (DI == DE) {
2167
2168 unsigned PrefixLength = NI - path::begin(File);
2169 if (PrefixLength > BestPrefixLength) {
2170 BestPrefixLength = PrefixLength;
2171 return true;
2172 }
2173 break;
2174 }
2175
2176
2177 if (NI->size() == 1 && DI->size() == 1 &&
2178 path::is_separator(NI->front()) && path::is_separator(DI->front()))
2179 continue;
2180
2181
2182
2183
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))
2188 continue;
2189 }
2190
2191 if (*NI != *DI)
2192 break;
2193 }
2194 return false;
2195 };
2196
2197 bool BestPrefixIsFramework = false;
2199 if (DL.isNormalDir()) {
2200 StringRef Dir = DL.getDirRef()->getName();
2201 if (CheckDir(Dir)) {
2202 if (IsAngled)
2203 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());
2204 BestPrefixIsFramework = false;
2205 }
2206 } else if (DL.isFramework()) {
2207 StringRef Dir = DL.getFrameworkDirRef()->getName();
2208 if (CheckDir(Dir)) {
2209
2210 if (IsAngled)
2211 *IsAngled = BestPrefixLength;
2212 BestPrefixIsFramework = true;
2213 }
2214 }
2215 }
2216
2217
2218
2219 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {
2220 if (IsAngled)
2221 *IsAngled = false;
2222 BestPrefixIsFramework = false;
2223 }
2224
2225
2226
2227 StringRef Filename = File.drop_front(BestPrefixLength);
2229 if (!DL.isHeaderMap())
2230 continue;
2231
2232 StringRef SpelledFilename =
2233 DL.getHeaderMap()->reverseLookupFilename(Filename);
2234 if (!SpelledFilename.empty()) {
2235 Filename = SpelledFilename;
2236 BestPrefixIsFramework = false;
2237 break;
2238 }
2239 }
2240
2241
2242
2243 bool IsPrivateHeader;
2245 if (BestPrefixIsFramework &&
2247 IncludeSpelling)) {
2248 Filename = IncludeSpelling;
2249 }
2250 return path::convert_to_slash(Filename);
2251}
2252
2255 NormalizedPath.assign(Path.begin(), Path.end());
2256 if (!NormalizedPath.empty()) {
2257 FileMgr.makeAbsolutePath(NormalizedPath);
2258 llvm::sys::path::remove_dots(NormalizedPath);
2259 }
2260}
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
std::shared_ptr< TokenRole > Role
A token can have a special role that can carry extra information about the token's formatting.
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...
Definition HeaderSearch.cpp:476
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.
Definition HeaderSearch.cpp:435
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)
Definition HeaderSearch.cpp:2253
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.