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 (Module && SearchName.consume_back("_Private"))

320 AllowExtraModuleMapSearch);

321 if (Module && 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 (File) {

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.