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(std::move(HSOpts)), Diags(Diags),

88 FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),

89 ModMap(SourceMgr, Diags, LangOpts, Target, *this) {}

90

92 llvm::errs() << "\n*** HeaderSearch Stats:\n"

93 << FileInfo.size() << " files tracked.\n";

94 unsigned NumOnceOnlyFiles = 0;

95 for (unsigned i = 0, e = FileInfo.size(); i != e; ++i)

96 NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport);

97 llvm::errs() << " " << NumOnceOnlyFiles << " #import/#pragma once files.\n";

98

99 llvm::errs() << " " << NumIncluded << " #include/#include_next/#import.\n"

100 << " " << NumMultiIncludeFileOptzn

101 << " #includes skipped due to the multi-include optimization.\n";

102

103 llvm::errs() << NumFrameworkLookups << " framework lookups.\n"

104 << NumSubFrameworkLookups << " subframework lookups.\n";

105}

106

108 std::vector dirs, unsigned int angledDirIdx,

109 unsigned int systemDirIdx,

110 llvm::DenseMap<unsigned int, unsigned int> searchDirToHSEntry) {

111 assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&

112 "Directory indices are unordered");

113 SearchDirs = std::move(dirs);

114 SearchDirsUsage.assign(SearchDirs.size(), false);

115 AngledDirIdx = angledDirIdx;

116 SystemDirIdx = systemDirIdx;

117 SearchDirToHSEntry = std::move(searchDirToHSEntry);

118

119 indexInitialHeaderMaps();

120}

121

123 unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;

124 SearchDirs.insert(SearchDirs.begin() + idx, dir);

125 SearchDirsUsage.insert(SearchDirsUsage.begin() + idx, false);

126 if (!isAngled)

127 AngledDirIdx++;

128 SystemDirIdx++;

129}

130

132 std::vector UserEntryUsage(HSOpts->UserEntries.size());

133 for (unsigned I = 0, E = SearchDirsUsage.size(); I < E; ++I) {

134

135 if (SearchDirsUsage[I]) {

136 auto UserEntryIdxIt = SearchDirToHSEntry.find(I);

137

138 if (UserEntryIdxIt != SearchDirToHSEntry.end())

139 UserEntryUsage[UserEntryIdxIt->second] = true;

140 }

141 }

142 return UserEntryUsage;

143}

144

146 std::vector VFSUsage;

148 return VFSUsage;

149

151

152

153 RootFS.visit([&](llvm::vfs::FileSystem &FS) {

154 if (auto *RFS = dyn_castllvm::vfs::RedirectingFileSystem(&FS)) {

155 VFSUsage.push_back(RFS->hasBeenUsed());

156 RFS->clearHasBeenUsed();

157 }

158 });

159 assert(VFSUsage.size() == getHeaderSearchOpts().VFSOverlayFiles.size() &&

160 "A different number of RedirectingFileSystem's were present than "

161 "-ivfsoverlay options passed to Clang!");

162

163 std::reverse(VFSUsage.begin(), VFSUsage.end());

164 return VFSUsage;

165}

166

167

168

170

171

172 if (!HeaderMaps.empty()) {

173 for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)

174

175

176 if (HeaderMaps[i].first == FE)

177 return HeaderMaps[i].second.get();

178 }

179

180 if (std::unique_ptr HM = HeaderMap::Create(FE, FileMgr)) {

181 HeaderMaps.emplace_back(FE, std::move(HM));

182 return HeaderMaps.back().second.get();

183 }

184

185 return nullptr;

186}

187

188

191 for (auto &HM : HeaderMaps)

192 Names.push_back(std::string(HM.first.getName()));

193}

194

198

199

201 return {};

203}

204

206 bool FileMapOnly) {

207

208 auto i(HSOpts->PrebuiltModuleFiles.find(ModuleName));

209 if (i != HSOpts->PrebuiltModuleFiles.end())

210 return i->second;

211

212 if (FileMapOnly || HSOpts->PrebuiltModulePaths.empty())

213 return {};

214

215

216

217 for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {

219 llvm::sys::fs::make_absolute(Result);

220 if (ModuleName.contains(':'))

221

222

223

224 llvm::sys::path::append(Result, ModuleName.split(':').first + "-" +

225 ModuleName.split(':').second +

226 ".pcm");

227 else

228 llvm::sys::path::append(Result, ModuleName + ".pcm");

230 return std::string(Result);

231 }

232

233 return {};

234}

235

240 StringRef ModuleMapPath = ModuleMap->getName();

241 StringRef ModuleCacheHash = HSOpts->DisableModuleHash ? "" : getModuleHash();

242 for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {

244 llvm::sys::fs::make_absolute(CachePath);

245 llvm::sys::path::append(CachePath, ModuleCacheHash);

247 getCachedModuleFileNameImpl(ModuleName, ModuleMapPath, CachePath);

250 }

251 return {};

252}

253

255 StringRef ModuleMapPath) {

256 return getCachedModuleFileNameImpl(ModuleName, ModuleMapPath,

258}

259

260std::string HeaderSearch::getCachedModuleFileNameImpl(StringRef ModuleName,

261 StringRef ModuleMapPath,

262 StringRef CachePath) {

263

264

265 if (CachePath.empty())

266 return {};

267

269

270 if (HSOpts->DisableModuleHash) {

271 llvm::sys::path::append(Result, ModuleName + ".pcm");

272 } else {

273

274

275

276

277

278

279

281 if (getModuleMap().canonicalizeModuleMapPath(CanonicalPath))

282 return {};

283

284 auto Hash = llvm::xxh3_64bits(CanonicalPath.str().lower());

285

287 llvm::APInt(64, Hash).toStringUnsigned(HashStr, 36);

288 llvm::sys::path::append(Result, ModuleName + "-" + HashStr + ".pcm");

289 }

290 return Result.str().str();

291}

292

295 bool AllowExtraModuleMapSearch) {

296

298 if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)

300

301 StringRef SearchName = ModuleName;

303 AllowExtraModuleMapSearch);

304

305

306

307

308

309

310

311

312

313 if (Module && SearchName.consume_back("_Private"))

315 AllowExtraModuleMapSearch);

316 if (Module && SearchName.consume_back("Private"))

318 AllowExtraModuleMapSearch);

320}

321

324 bool AllowExtraModuleMapSearch) {

326

327

328

330 if (Dir.isFramework()) {

331

332

333

335 FrameworkDirName += Dir.getFrameworkDirRef()->getName();

336 llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");

337 if (auto FrameworkDir =

339 bool IsSystem = Dir.getDirCharacteristic() != SrcMgr::C_User;

340 Module = loadFrameworkModule(ModuleName, *FrameworkDir, IsSystem);

342 break;

343 }

344 }

345

346

347

348

349 if (!Dir.isNormalDir())

350 continue;

351

352 bool IsSystem = Dir.isSystemHeaderDirectory();

353

354

356

358 false) == LMM_NewlyLoaded) {

359

360

363 break;

364 }

365

366

367

369 NestedModuleMapDirName = Dir.getDirRef()->getName();

370 llvm::sys::path::append(NestedModuleMapDirName, ModuleName);

372 false) == LMM_NewlyLoaded){

373

376 break;

377 }

378

379 if (HSOpts->AllowModuleMapSubdirectorySearch) {

380

381

382 if (Dir.haveSearchedAllModuleMaps())

383 continue;

384

385

386

387 if (AllowExtraModuleMapSearch)

388 loadSubdirectoryModuleMaps(Dir);

389

390

393 break;

394 }

395 }

396

398}

399

400void HeaderSearch::indexInitialHeaderMaps() {

401 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> Index(SearchDirs.size());

402

403

404 for (unsigned i = 0; i != SearchDirs.size(); ++i) {

405 auto &Dir = SearchDirs[i];

406

407

408

409

410 if (!Dir.isHeaderMap()) {

411 SearchDirHeaderMapIndex = std::move(Index);

412 FirstNonHeaderMapSearchDirIdx = i;

413 break;

414 }

415

416

417 auto Callback = [&](StringRef Filename) {

418 Index.try_emplace(Filename.lower(), i);

419 };

420 Dir.getHeaderMap()->forEachKey(Callback);

421 }

422}

423

424

425

426

427

428

429

435 assert(isHeaderMap() && "Unknown DirectoryLookup");

437}

438

441 bool IsSystemHeaderDir, Module *RequestingModule,

443 bool CacheFailures ) {

444

445

448

449

450 std::error_code EC = llvm::errorToErrorCode(File.takeError());

451 if (EC != llvm::errc::no_such_file_or_directory &&

452 EC != llvm::errc::invalid_argument &&

453 EC != llvm::errc::is_a_directory && EC != llvm::errc::not_a_directory) {

454 Diags.Report(IncludeLoc, diag::err_cannot_open_file)

456 }

457 return std::nullopt;

458 }

459

460

461 if (!findUsableModuleForHeader(

462 *File, Dir ? Dir : File->getFileEntry().getDir(), RequestingModule,

463 SuggestedModule, IsSystemHeaderDir))

464 return std::nullopt;

465

466 return *File;

467}

468

469

470

475 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,

477 bool OpenFile) const {

478 InUserSpecifiedSystemFramework = false;

479 IsInHeaderMap = false;

480 MappedName.clear();

481

484

486 llvm::sys::path::append(TmpDir, Filename);

487 if (SearchPath) {

489 SearchPath->clear();

490 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());

491 }

492 if (RelativePath) {

493 RelativePath->clear();

495 }

496

497 return HS.getFileAndSuggestModule(

499 RequestingModule, SuggestedModule, OpenFile);

500 }

501

503 return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,

504 RequestingModule, SuggestedModule,

505 InUserSpecifiedSystemFramework, IsFrameworkFound);

506

507 assert(isHeaderMap() && "Unknown directory lookup");

511 if (Dest.empty())

512 return std::nullopt;

513

514 IsInHeaderMap = true;

515

516 auto FixupSearchPathAndFindUsableModule =

518 if (SearchPath) {

519 StringRef SearchPathRef(getName());

520 SearchPath->clear();

521 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());

522 }

523 if (RelativePath) {

524 RelativePath->clear();

526 }

527 if (!HS.findUsableModuleForHeader(File, File.getFileEntry().getDir(),

528 RequestingModule, SuggestedModule,

530 return std::nullopt;

531 }

533 };

534

535

536

537

538 if (llvm::sys::path::is_relative(Dest)) {

539 MappedName.append(Dest.begin(), Dest.end());

540 Filename = StringRef(MappedName.begin(), MappedName.size());

542 }

543

545 return FixupSearchPathAndFindUsableModule(*Res);

546 }

547

548

549

550

551

552 HS.noteLookupUsage(HS.searchDirIdx(*this), IncludeLoc);

553 return std::nullopt;

554}

555

556

557

558

559

560

561

565 assert(llvm::sys::path::extension(DirName) == ".framework" &&

566 "Not a framework directory");

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

583

584 if (TopFrameworkDir)

586 do {

587

588 DirName = llvm::sys::path::parent_path(DirName);

589 if (DirName.empty())

590 break;

591

592

594 if (!Dir)

595 break;

596

597

598

599 if (llvm::sys::path::extension(DirName) == ".framework") {

600 SubmodulePath.push_back(std::string(llvm::sys::path::stem(DirName)));

601 TopFrameworkDir = *Dir;

602 }

603 } while (true);

604

605 return TopFrameworkDir;

606}

607

609 bool HasSuggestedModule) {

610 return HasSuggestedModule ||

612}

613

614

615

620 bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {

622

623

624 size_t SlashPos = Filename.find('/');

625 if (SlashPos == StringRef::npos)

626 return std::nullopt;

627

628

629

632

633

635 return std::nullopt;

636

637

638

639

642 if (FrameworkName.empty() || FrameworkName.back() != '/')

643 FrameworkName.push_back('/');

644

645

646 StringRef ModuleName(Filename.begin(), SlashPos);

647 FrameworkName += ModuleName;

648

649

650 FrameworkName += ".framework/";

651

652

654 ++NumFrameworkLookups;

655

656

658 if (!Dir)

659 return std::nullopt;

660

661

662

664

665

666

669 SystemFrameworkMarker += ".system_framework";

670 if (llvm::sys::fs::exists(SystemFrameworkMarker)) {

672 }

673 }

674 }

675

676

679

680 if (RelativePath) {

681 RelativePath->clear();

682 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());

683 }

684

685

686 unsigned OrigSize = FrameworkName.size();

687

688 FrameworkName += "Headers/";

689

690 if (SearchPath) {

691 SearchPath->clear();

692

693 SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);

694 }

695

696 FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());

697

699 FileMgr.getOptionalFileRef(FrameworkName, !SuggestedModule);

701

702 const char *Private = "Private";

703 FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,

705 if (SearchPath)

706 SearchPath->insert(SearchPath->begin()+OrigSize, Private,

708

710 !SuggestedModule);

711 }

712

713

715

716 StringRef FrameworkPath = File->getDir().getName();

717 bool FoundFramework = false;

718 do {

719

721 if (!Dir)

722 break;

723

724

725

726 if (llvm::sys::path::extension(FrameworkPath) == ".framework") {

727 FoundFramework = true;

728 break;

729 }

730

731

732 FrameworkPath = llvm::sys::path::parent_path(FrameworkPath);

733 if (FrameworkPath.empty())

734 break;

735 } while (true);

736

738 if (FoundFramework) {

739 if (!HS.findUsableModuleForFrameworkHeader(*File, FrameworkPath,

740 RequestingModule,

741 SuggestedModule, IsSystem))

742 return std::nullopt;

743 } else {

744 if (!HS.findUsableModuleForHeader(*File, getDir(), RequestingModule,

745 SuggestedModule, IsSystem))

746 return std::nullopt;

747 }

748 }

750 return *File;

751 return std::nullopt;

752}

753

754void HeaderSearch::cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,

757 CacheLookup.HitIt = HitIt;

758 noteLookupUsage(HitIt.Idx, Loc);

759}

760

761void HeaderSearch::noteLookupUsage(unsigned HitIdx, SourceLocation Loc) {

762 SearchDirsUsage[HitIdx] = true;

763

764 auto UserEntryIdxIt = SearchDirToHSEntry.find(HitIdx);

765 if (UserEntryIdxIt != SearchDirToHSEntry.end())

766 Diags.Report(Loc, diag::remark_pp_search_path_usage)

767 << HSOpts->UserEntries[UserEntryIdxIt->second].Path;

768}

769

772}

773

774

775

776

777

778

779

780

785 if (MSFE && FE != *MSFE) {

786 Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms) << MSFE->getName();

787 return true;

788 }

789 return false;

790}

791

792static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {

793 assert(!Str.empty());

794 char *CopyStr = Alloc.Allocate<char>(Str.size()+1);

795 std::copy(Str.begin(), Str.end(), CopyStr);

796 CopyStr[Str.size()] = '\0';

797 return CopyStr;

798}

799

803 using namespace llvm::sys;

804 path::const_iterator I = path::begin(Path);

805 path::const_iterator E = path::end(Path);

806 IsPrivateHeader = false;

807

808

809

810

811

812

813

814

815

816 int FoundComp = 0;

817 while (I != E) {

818 if (*I == "Headers") {

819 ++FoundComp;

820 } else if (*I == "PrivateHeaders") {

821 ++FoundComp;

822 IsPrivateHeader = true;

823 } else if (I->ends_with(".framework")) {

824 StringRef Name = I->drop_back(10);

825

826 FrameworkName.clear();

827 FrameworkName.append(Name.begin(), Name.end());

828 IncludeSpelling.clear();

829 IncludeSpelling.append(Name.begin(), Name.end());

830 FoundComp = 1;

831 } else if (FoundComp >= 2) {

832 IncludeSpelling.push_back('/');

833 IncludeSpelling.append(I->begin(), I->end());

834 }

835 ++I;

836 }

837

838 return !FrameworkName.empty() && FoundComp >= 2;

839}

840

841static void

843 StringRef Includer, StringRef IncludeFilename,

844 FileEntryRef IncludeFE, bool isAngled = false,

845 bool FoundByHeaderMap = false) {

846 bool IsIncluderPrivateHeader = false;

850 FromIncludeSpelling))

851 return;

852 bool IsIncludeePrivateHeader = false;

853 bool IsIncludeeInFramework =

855 ToFramework, ToIncludeSpelling);

856

857 if (!isAngled && !FoundByHeaderMap) {

859 if (IsIncludeeInFramework) {

860 NewInclude += ToIncludeSpelling;

861 NewInclude += ">";

862 } else {

863 NewInclude += IncludeFilename;

864 NewInclude += ">";

865 }

866 Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header)

867 << IncludeFilename

869 }

870

871

872

873

874 if (!IsIncluderPrivateHeader && IsIncludeeInFramework &&

875 IsIncludeePrivateHeader && FromFramework == ToFramework)

876 Diags.Report(IncludeLoc, diag::warn_framework_include_private_from_public)

877 << IncludeFilename;

878}

879

880

881

882

883

884

888 ArrayRef<std::pair<OptionalFileEntryRef, DirectoryEntryRef>> Includers,

891 bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,

892 bool BuildSystemModule, bool OpenFile, bool CacheFailures) {

895

896 if (IsMapped)

897 *IsMapped = false;

898

899 if (IsFrameworkFound)

900 *IsFrameworkFound = false;

901

902 if (SuggestedModule)

904

905

906 if (llvm::sys::path::is_absolute(Filename)) {

907 CurDir = nullptr;

908

909

910 if (FromDir)

911 return std::nullopt;

912

913 if (SearchPath)

914 SearchPath->clear();

915 if (RelativePath) {

916 RelativePath->clear();

918 }

919

920 return getFileAndSuggestModule(Filename, IncludeLoc, nullptr,

921 false,

922 RequestingModule, SuggestedModule, OpenFile,

923 CacheFailures);

924 }

925

926

929

930

931

932

933

934

935 if (!Includers.empty() && !isAngled) {

937 bool First = true;

938 for (const auto &IncluderAndDir : Includers) {

940

941

942 TmpDir = IncluderAndDir.second.getName();

943 llvm::sys::path::append(TmpDir, Filename);

944

945

946

947

948

949

950

951

952 bool IncluderIsSystemHeader = [&]() {

953 if (!Includer)

954 return BuildSystemModule;

956 assert(HFI && "includer without file info");

958 }();

960 TmpDir, IncludeLoc, IncluderAndDir.second, IncluderIsSystemHeader,

961 RequestingModule, SuggestedModule)) {

962 if (!Includer) {

963 assert(First && "only first includer can have no file");

964 return FE;

965 }

966

967

968

969

970

971

972

974 assert(FromHFI && "includer without file info");

975 unsigned DirInfo = FromHFI->DirInfo;

976

979

980 if (SearchPath) {

981 StringRef SearchPathRef(IncluderAndDir.second.getName());

982 SearchPath->clear();

983 SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());

984 }

985 if (RelativePath) {

986 RelativePath->clear();

988 }

991 IncluderAndDir.second.getName(), Filename,

992 *FE);

993 return FE;

994 }

995

996

997

998

999 if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) {

1000 return FE;

1001 } else {

1002 MSFE = FE;

1003 if (SuggestedModule) {

1004 MSSuggestedModule = *SuggestedModule;

1006 }

1007 break;

1008 }

1009 }

1011 }

1012 }

1013

1014 CurDir = nullptr;

1015

1016

1019

1020

1021

1022 if (FromDir)

1023 It = FromDir;

1024

1025

1026

1027

1028

1029 LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename];

1030

1032

1033 if (!SkipCache) {

1034 if (CacheLookup.StartIt == NextIt &&

1035 CacheLookup.RequestingModule == RequestingModule) {

1036

1037 if (CacheLookup.HitIt)

1038 It = CacheLookup.HitIt;

1039 if (CacheLookup.MappedName) {

1040 Filename = CacheLookup.MappedName;

1041 if (IsMapped)

1042 *IsMapped = true;

1043 }

1044 } else {

1045

1046

1047

1048 CacheLookup.reset(RequestingModule, NextIt);

1049

1050 if (It == search_dir_begin() && FirstNonHeaderMapSearchDirIdx > 0) {

1051

1052

1053

1054 auto Iter = SearchDirHeaderMapIndex.find(Filename.lower());

1055 if (Iter == SearchDirHeaderMapIndex.end())

1056

1058 else

1059

1061 }

1062 }

1063 } else {

1064 CacheLookup.reset(RequestingModule, NextIt);

1065 }

1066

1068

1069

1071 bool InUserSpecifiedSystemFramework = false;

1072 bool IsInHeaderMap = false;

1073 bool IsFrameworkFoundInDir = false;

1075 Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,

1076 SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,

1077 IsInHeaderMap, MappedName, OpenFile);

1078 if (!MappedName.empty()) {

1079 assert(IsInHeaderMap && "MappedName should come from a header map");

1080 CacheLookup.MappedName =

1081 copyString(MappedName, LookupFileCache.getAllocator());

1082 }

1083 if (IsMapped)

1084

1085

1086

1087 *IsMapped |= (!MappedName.empty() || (IsInHeaderMap && File));

1088 if (IsFrameworkFound)

1089

1090

1091

1092 *IsFrameworkFound |= (IsFrameworkFoundInDir && !CacheLookup.MappedName);

1094 continue;

1095

1096 CurDir = It;

1097

1099

1100

1102 HFI.DirInfo = CurDir->getDirCharacteristic();

1103

1104

1105

1106

1109

1110

1111

1112 for (unsigned j = SystemHeaderPrefixes.size(); j; --j) {

1113 if (Filename.starts_with(SystemHeaderPrefixes[j - 1].first)) {

1116 break;

1117 }

1118 }

1119

1121 if (SuggestedModule)

1122 *SuggestedModule = MSSuggestedModule;

1123 return MSFE;

1124 }

1125

1126 bool FoundByHeaderMap = !IsMapped ? false : *IsMapped;

1127 if (!Includers.empty())

1129 Includers.front().second.getName(), Filename,

1130 *File, isAngled, FoundByHeaderMap);

1131

1132

1133 cacheLookupSuccess(CacheLookup, It, IncludeLoc);

1134 return File;

1135 }

1136

1138 if (SuggestedModule)

1139 *SuggestedModule = MSSuggestedModule;

1140 return MSFE;

1141 }

1142

1143

1145 return std::nullopt;

1146}

1147

1148

1149

1150

1151

1152

1157

1158

1159 size_t SlashPos = Filename.find('/');

1160 if (SlashPos == StringRef::npos)

1161 return std::nullopt;

1162

1163

1164 StringRef ContextName = ContextFileEnt.getName();

1165

1166

1167 const unsigned DotFrameworkLen = 10;

1168 auto FrameworkPos = ContextName.find(".framework");

1169 if (FrameworkPos == StringRef::npos ||

1170 (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&

1171 ContextName[FrameworkPos + DotFrameworkLen] != '\\'))

1172 return std::nullopt;

1173

1174 SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +

1175 FrameworkPos +

1176 DotFrameworkLen + 1);

1177

1178

1179 FrameworkName += "Frameworks/";

1180 FrameworkName.append(Filename.begin(), Filename.begin()+SlashPos);

1181 FrameworkName += ".framework/";

1182

1183 auto &CacheLookup =

1184 *FrameworkMap.insert(std::make_pair(Filename.substr(0, SlashPos),

1186

1187

1188 if (CacheLookup.second.Directory &&

1189 CacheLookup.first().size() == FrameworkName.size() &&

1190 memcmp(CacheLookup.first().data(), &FrameworkName[0],

1191 CacheLookup.first().size()) != 0)

1192 return std::nullopt;

1193

1194

1195 if (!CacheLookup.second.Directory) {

1196 ++NumSubFrameworkLookups;

1197

1198

1200 if (!Dir)

1201 return std::nullopt;

1202

1203

1204

1205 CacheLookup.second.Directory = Dir;

1206 }

1207

1208

1209 if (RelativePath) {

1210 RelativePath->clear();

1211 RelativePath->append(Filename.begin()+SlashPos+1, Filename.end());

1212 }

1213

1214

1216 HeadersFilename += "Headers/";

1217 if (SearchPath) {

1218 SearchPath->clear();

1219

1220 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);

1221 }

1222

1223 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());

1225 if (File) {

1226

1227 HeadersFilename = FrameworkName;

1228 HeadersFilename += "PrivateHeaders/";

1229 if (SearchPath) {

1230 SearchPath->clear();

1231

1232 SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1);

1233 }

1234

1235 HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());

1237

1239 return std::nullopt;

1240 }

1241

1242

1244 assert(ContextHFI && "context file without file info");

1245

1246

1247 unsigned DirInfo = ContextHFI->DirInfo;

1249

1250 FrameworkName.pop_back();

1251 if (!findUsableModuleForFrameworkHeader(*File, FrameworkName,

1252 RequestingModule, SuggestedModule,

1253 false))

1254 return std::nullopt;

1255

1256 return *File;

1257}

1258

1259

1260

1261

1262

1269 return false;

1270}

1271

1273 bool isModuleHeader,

1274 bool isTextualModuleHeader) {

1278 else

1280}

1281

1285}

1286

1287

1288

1291 assert(OtherHFI.External && "expected to merge external HFI");

1292

1297

1300

1304}

1305

1307 if (FE.getUID() >= FileInfo.size())

1308 FileInfo.resize(FE.getUID() + 1);

1309

1311

1313 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);

1314 if (ExternalHFI.IsValid) {

1316 if (ExternalHFI.External)

1318 }

1319 }

1320

1322

1323

1325 return *HFI;

1326}

1327

1331 if (FE.getUID() >= FileInfo.size())

1332 FileInfo.resize(FE.getUID() + 1);

1333

1334 HFI = &FileInfo[FE.getUID()];

1335

1337 auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);

1338 if (ExternalHFI.IsValid) {

1340 if (ExternalHFI.External)

1342 }

1343 }

1344 } else if (FE.getUID() < FileInfo.size()) {

1345 HFI = &FileInfo[FE.getUID()];

1346 } else {

1347 HFI = nullptr;

1348 }

1349

1350 return (HFI && HFI->IsValid) ? HFI : nullptr;

1351}

1352

1356 if (FE.getUID() < FileInfo.size()) {

1357 HFI = &FileInfo[FE.getUID()];

1358 } else {

1359 HFI = nullptr;

1360 }

1361

1362 return (HFI && HFI->IsValid && !HFI->External) ? HFI : nullptr;

1363}

1364

1366

1367

1368

1370 return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();

1371 return false;

1372}

1373

1376 bool isCompilingModuleHeader) {

1377

1378 if (!isCompilingModuleHeader) {

1380 return;

1383 return;

1384 }

1385

1387 HFI.mergeModuleMembership(Role);

1388 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;

1389}

1390

1393 bool ModulesEnabled, Module *M,

1394 bool &IsFirstIncludeOfFile) {

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408

1409 ++NumIncluded;

1410 IsFirstIncludeOfFile = false;

1412

1413 auto MaybeReenterImportedFile = [&]() -> bool {

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1429

1430

1431 if (!ModulesEnabled || FileInfo.isPragmaOnce)

1432 return false;

1433

1434

1436

1437

1438

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1452

1453

1454

1456 return true;

1457

1459

1460

1462

1463

1464

1465

1467 return true;

1468 } else {

1469

1470

1471

1472

1473

1474

1476 return true;

1477 }

1478 }

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489 return false;

1490 };

1491

1492 if (isImport) {

1493

1494

1497 return false;

1498 } else {

1499

1500

1501

1503 (FileInfo.isImport && !MaybeReenterImportedFile()))

1504 return false;

1505 }

1506

1507

1508

1509

1510

1513

1514

1515

1516

1519 ++NumMultiIncludeFileOptzn;

1520 return false;

1521 }

1522 }

1523

1525 return true;

1526}

1527

1529 return SearchDirs.capacity()

1530 + llvm::capacity_in_bytes(FileInfo)

1531 + llvm::capacity_in_bytes(HeaderMaps)

1532 + LookupFileCache.getAllocator().getTotalMemory()

1533 + FrameworkMap.getAllocator().getTotalMemory();

1534}

1535

1537 return &DL - &*SearchDirs.begin();

1538}

1539

1541 return FrameworkNames.insert(Framework).first->first();

1542}

1543

1545 auto It = IncludeNames.find(File);

1546 if (It == IncludeNames.end())

1547 return {};

1548 return It->second;

1549}

1550

1553 bool IsSystem) {

1554 if (!HSOpts->ImplicitModuleMaps)

1555 return false;

1556

1558

1559 StringRef DirName = FileName;

1560 do {

1561

1562 DirName = llvm::sys::path::parent_path(DirName);

1563 if (DirName.empty())

1564 return false;

1565

1566

1568 if (!Dir)

1569 return false;

1570

1571

1573 llvm::sys::path::extension(Dir->getName()) ==

1574 ".framework")) {

1575 case LMM_NewlyLoaded:

1576 case LMM_AlreadyLoaded:

1577

1578

1579 for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)

1580 DirectoryHasModuleMap[FixUpDirectories[I]] = true;

1581 return true;

1582

1583 case LMM_NoDirectory:

1584 case LMM_InvalidModuleMap:

1585 break;

1586 }

1587

1588

1589 if (*Dir == Root)

1590 return false;

1591

1592

1593

1594 FixUpDirectories.push_back(*Dir);

1595 } while (true);

1596}

1597

1600 bool AllowExcluded) const {

1602

1603

1605 }

1607}

1608

1612

1613

1615 }

1617}

1618

1622

1623

1625 }

1627}

1628

1630 Module *RequestingModule,

1634

1635

1636

1640

1641

1642

1643

1644

1646 if (SuggestedModule)

1648 return true;

1649 }

1650

1651

1652 return false;

1653 }

1654 }

1655

1656 if (SuggestedModule)

1660

1661 return true;

1662}

1663

1664bool HeaderSearch::findUsableModuleForHeader(

1668

1669 hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);

1670 return suggestModule(*this, File, RequestingModule, SuggestedModule);

1671 }

1672 return true;

1673}

1674

1675bool HeaderSearch::findUsableModuleForFrameworkHeader(

1678

1680

1684 assert(TopFrameworkDir && "Could not find the top-most framework dir");

1685

1686

1687 StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName());

1688

1689

1690

1691 loadFrameworkModule(ModuleName, *TopFrameworkDir, IsSystemFramework);

1692

1693

1694

1695

1696

1697 return suggestModule(*this, File, RequestingModule, SuggestedModule);

1698 }

1699 return true;

1700}

1701

1705 StringRef Filename = llvm::sys::path::filename(File.getName());

1707 if (Filename == "module.map")

1708 llvm::sys::path::append(PrivateFilename, "module_private.map");

1709 else if (Filename == "module.modulemap")

1710 llvm::sys::path::append(PrivateFilename, "module.private.modulemap");

1711 else

1712 return std::nullopt;

1714 if (PMMFile) {

1715 if (Filename == "module.map")

1716 Diags.Report(diag::warn_deprecated_module_dot_map)

1717 << PrivateFilename << 1

1718 << File.getDir().getName().ends_with(".framework");

1719 }

1720 return PMMFile;

1721}

1722

1724 FileID ID, unsigned *Offset,

1725 StringRef OriginalModuleMapFile) {

1726

1727

1731 } else {

1732 if (!OriginalModuleMapFile.empty()) {

1733

1734

1736 llvm::sys::path::parent_path(OriginalModuleMapFile));

1737 if (!Dir) {

1738 auto FakeFile = FileMgr.getVirtualFileRef(OriginalModuleMapFile, 0, 0);

1739 Dir = FakeFile.getDir();

1740 }

1741 } else {

1742 Dir = File.getDir();

1743 }

1744

1745 assert(Dir && "parent must exist");

1746 StringRef DirName(Dir->getName());

1747 if (llvm::sys::path::filename(DirName) == "Modules") {

1748 DirName = llvm::sys::path::parent_path(DirName);

1749 if (DirName.ends_with(".framework"))

1751 Dir = *MaybeDir;

1752

1753

1754 assert(Dir && "parent must exist");

1755 }

1756 }

1757

1758 assert(Dir && "module map home directory must exist");

1759 switch (loadModuleMapFileImpl(File, IsSystem, *Dir, ID, Offset)) {

1760 case LMM_AlreadyLoaded:

1761 case LMM_NewlyLoaded:

1762 return false;

1763 case LMM_NoDirectory:

1764 case LMM_InvalidModuleMap:

1765 return true;

1766 }

1767 llvm_unreachable("Unknown load module map result");

1768}

1769

1770HeaderSearch::LoadModuleMapResult

1771HeaderSearch::loadModuleMapFileImpl(FileEntryRef File, bool IsSystem,

1773 unsigned *Offset) {

1774

1775

1776 auto AddResult = LoadedModuleMaps.insert(std::make_pair(File, true));

1777 if (!AddResult.second)

1778 return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;

1779

1781 LoadedModuleMaps[File] = false;

1782 return LMM_InvalidModuleMap;

1783 }

1784

1785

1789 LoadedModuleMaps[File] = false;

1790 return LMM_InvalidModuleMap;

1791 }

1792 }

1793

1794

1795 return LMM_NewlyLoaded;

1796}

1797

1800 if (!HSOpts->ImplicitModuleMaps)

1801 return std::nullopt;

1802

1803

1805 if (IsFramework)

1806 llvm::sys::path::append(ModuleMapFileName, "Modules");

1807 llvm::sys::path::append(ModuleMapFileName, "module.modulemap");

1809 return *F;

1810

1811

1812 ModuleMapFileName = Dir.getName();

1813 llvm::sys::path::append(ModuleMapFileName, "module.map");

1815 Diags.Report(diag::warn_deprecated_module_dot_map)

1816 << ModuleMapFileName << 0 << IsFramework;

1817 return *F;

1818 }

1819

1820

1821

1822 if (IsFramework) {

1823 ModuleMapFileName = Dir.getName();

1824 llvm::sys::path::append(ModuleMapFileName, "Modules",

1825 "module.private.modulemap");

1827 return *F;

1828 }

1829 return std::nullopt;

1830}

1831

1833 bool IsSystem) {

1834

1835 switch (loadModuleMapFile(Dir, IsSystem, true)) {

1836 case LMM_InvalidModuleMap:

1837

1838 if (HSOpts->ImplicitModuleMaps)

1839 ModMap.inferFrameworkModule(Dir, IsSystem, nullptr);

1840 break;

1841

1842 case LMM_NoDirectory:

1843 return nullptr;

1844

1845 case LMM_AlreadyLoaded:

1846 case LMM_NewlyLoaded:

1847 break;

1848 }

1849

1851}

1852

1853HeaderSearch::LoadModuleMapResult

1855 bool IsFramework) {

1858

1859 return LMM_NoDirectory;

1860}

1861

1862HeaderSearch::LoadModuleMapResult

1864 bool IsFramework) {

1865 auto KnownDir = DirectoryHasModuleMap.find(Dir);

1866 if (KnownDir != DirectoryHasModuleMap.end())

1867 return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;

1868

1871 LoadModuleMapResult Result =

1872 loadModuleMapFileImpl(*ModuleMapFile, IsSystem, Dir);

1873

1874

1875

1876 if (Result == LMM_NewlyLoaded)

1877 DirectoryHasModuleMap[Dir] = true;

1878 else if (Result == LMM_InvalidModuleMap)

1879 DirectoryHasModuleMap[Dir] = false;

1881 }

1882 return LMM_InvalidModuleMap;

1883}

1884

1886 Modules.clear();

1887

1888 if (HSOpts->ImplicitModuleMaps) {

1889

1891 bool IsSystem = DL.isSystemHeaderDirectory();

1892 if (DL.isFramework()) {

1893 std::error_code EC;

1895 llvm::sys::path::native(DL.getFrameworkDirRef()->getName(), DirNative);

1896

1897

1899 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC),

1900 DirEnd;

1901 Dir != DirEnd && !EC; Dir.increment(EC)) {

1902 if (llvm::sys::path::extension(Dir->path()) != ".framework")

1903 continue;

1904

1906 if (!FrameworkDir)

1907 continue;

1908

1909

1910 loadFrameworkModule(llvm::sys::path::stem(Dir->path()), *FrameworkDir,

1911 IsSystem);

1912 }

1913 continue;

1914 }

1915

1916

1917 if (DL.isHeaderMap())

1918 continue;

1919

1920

1921 loadModuleMapFile(*DL.getDirRef(), IsSystem, false);

1922

1923

1924

1925 loadSubdirectoryModuleMaps(DL);

1926 }

1927 }

1928

1929

1930 llvm::transform(ModMap.modules(), std::back_inserter(Modules),

1931 [](const auto &NameAndMod) { return NameAndMod.second; });

1932}

1933

1935 if (!HSOpts->ImplicitModuleMaps)

1936 return;

1937

1938

1940

1941 if (!DL.isNormalDir())

1942 continue;

1943

1944

1945 loadModuleMapFile(*DL.getDirRef(), DL.isSystemHeaderDirectory(),

1946 DL.isFramework());

1947 }

1948}

1949

1950void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {

1951 assert(HSOpts->ImplicitModuleMaps &&

1952 "Should not be loading subdirectory module maps");

1953

1955 return;

1956

1957 std::error_code EC;

1961 llvm::sys::path::native(Dir, DirNative);

1963 for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;

1964 Dir != DirEnd && !EC; Dir.increment(EC)) {

1965 if (Dir->type() == llvm::sys::fs::file_type::regular_file)

1966 continue;

1967 bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";

1968 if (IsFramework == SearchDir.isFramework())

1971 }

1972

1974}

1975

1977 FileEntryRef File, llvm::StringRef MainFile, bool *IsAngled) const {

1979 MainFile, IsAngled);

1980}

1981

1983 llvm::StringRef File, llvm::StringRef WorkingDir, llvm::StringRef MainFile,

1984 bool *IsAngled) const {

1985 using namespace llvm::sys;

1986

1988 if (!WorkingDir.empty() && !path::is_absolute(FilePath))

1989 fs::make_absolute(WorkingDir, FilePath);

1990

1991

1992

1993 path::remove_dots(FilePath, true);

1994 path::native(FilePath, path::Style::posix);

1995 File = FilePath;

1996

1997 unsigned BestPrefixLength = 0;

1998

1999

2000

2002 if (!WorkingDir.empty() && !path::is_absolute(Dir))

2003 fs::make_absolute(WorkingDir, Dir);

2004 path::remove_dots(Dir, true);

2005 for (auto NI = path::begin(File), NE = path::end(File),

2006 DI = path::begin(Dir), DE = path::end(Dir);

2007 NI != NE; ++NI, ++DI) {

2008 if (DI == DE) {

2009

2010 unsigned PrefixLength = NI - path::begin(File);

2011 if (PrefixLength > BestPrefixLength) {

2012 BestPrefixLength = PrefixLength;

2013 return true;

2014 }

2015 break;

2016 }

2017

2018

2019 if (NI->size() == 1 && DI->size() == 1 &&

2020 path::is_separator(NI->front()) && path::is_separator(DI->front()))

2021 continue;

2022

2023

2024

2025

2026 if (NI->ends_with(".sdk") && DI->ends_with(".sdk")) {

2027 StringRef NBasename = path::stem(*NI);

2028 StringRef DBasename = path::stem(*DI);

2029 if (DBasename.starts_with(NBasename))

2030 continue;

2031 }

2032

2033 if (*NI != *DI)

2034 break;

2035 }

2036 return false;

2037 };

2038

2039 bool BestPrefixIsFramework = false;

2041 if (DL.isNormalDir()) {

2042 StringRef Dir = DL.getDirRef()->getName();

2043 if (CheckDir(Dir)) {

2044 if (IsAngled)

2045 *IsAngled = BestPrefixLength && isSystem(DL.getDirCharacteristic());

2046 BestPrefixIsFramework = false;

2047 }

2048 } else if (DL.isFramework()) {

2049 StringRef Dir = DL.getFrameworkDirRef()->getName();

2050 if (CheckDir(Dir)) {

2051

2052 if (IsAngled)

2053 *IsAngled = BestPrefixLength;

2054 BestPrefixIsFramework = true;

2055 }

2056 }

2057 }

2058

2059

2060

2061 if (!BestPrefixLength && CheckDir(path::parent_path(MainFile))) {

2062 if (IsAngled)

2063 *IsAngled = false;

2064 BestPrefixIsFramework = false;

2065 }

2066

2067

2068

2069 StringRef Filename = File.drop_front(BestPrefixLength);

2071 if (!DL.isHeaderMap())

2072 continue;

2073

2074 StringRef SpelledFilename =

2075 DL.getHeaderMap()->reverseLookupFilename(Filename);

2076 if (!SpelledFilename.empty()) {

2078 BestPrefixIsFramework = false;

2079 break;

2080 }

2081 }

2082

2083

2084

2085 bool IsPrivateHeader;

2087 if (BestPrefixIsFramework &&

2089 IncludeSpelling)) {

2091 }

2092 return path::convert_to_slash(Filename);

2093}

Defines the Diagnostic-related interfaces.

Defines the clang::FileManager interface and associated types.

Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.

llvm::MachO::Target Target

Defines the clang::Module class, which describes a module in the source code.

Defines the clang::Preprocessor interface.

Defines the SourceManager interface.

constexpr bool has_value() const

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

bool isIgnored(unsigned DiagID, SourceLocation Loc) const

Determine whether the diagnostic is known to be ignored.

A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...

StringRef getName() const

Cached information about one directory (either on disk or in the virtual file system).

DirectoryLookup - This class represents one entry in the search list that specifies the search order ...

SrcMgr::CharacteristicKind getDirCharacteristic() const

DirCharacteristic - The type of directory this is, one of the DirType enum values.

OptionalFileEntryRef LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, bool &IsInHeaderMap, SmallVectorImpl< char > &MappedName, bool OpenFile=true) const

LookupFile - Lookup the specified file in this search path, returning it if it exists or returning nu...

bool isFramework() const

isFramework - True if this is a framework directory.

bool isSystemHeaderDirectory() const

Whether this describes a system header directory.

OptionalDirectoryEntryRef getFrameworkDirRef() const

void setSearchedAllModuleMaps(bool SAMM)

Specify whether we have already searched all of the subdirectories for module maps.

bool isHeaderMap() const

isHeaderMap - Return true if this is a header map, not a normal directory.

StringRef getName() const

getName - Return the directory or filename corresponding to this lookup object.

OptionalDirectoryEntryRef getDirRef() const

bool haveSearchedAllModuleMaps() const

Determine whether we have already searched this entire directory for module maps.

const DirectoryEntry * getDir() const

getDir - Return the directory that this entry refers to.

bool isNormalDir() const

isNormalDir - Return true if this is a normal directory, not a header map.

const HeaderMap * getHeaderMap() const

getHeaderMap - Return the directory that this entry refers to.

Abstract interface for external sources of preprocessor information.

A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...

StringRef getName() const

The name of this FileEntry.

Cached information about one file (either on disk or in the virtual file system).

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

Implements support for file system lookup, file system caching, and directory search management.

llvm::vfs::FileSystem & getVirtualFileSystem() const

OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)

Get a FileEntryRef if it exists, without doing anything on error.

StringRef getCanonicalName(DirectoryEntryRef Dir)

Retrieve the canonical name for a given directory.

bool makeAbsolutePath(SmallVectorImpl< char > &Path) const

Makes Path absolute taking into account FileSystemOptions and the working directory option.

FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, time_t ModificationTime)

Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...

OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)

Get a DirectoryEntryRef if it exists, without doing anything on error.

LLVM_DEPRECATED("Functions returning DirectoryEntry are deprecated.", "getOptionalDirectoryRef()") llvm LLVM_DEPRECATED("Functions returning FileEntry are deprecated.", "getOptionalFileRef()") llvm llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)

Lookup, cache, and verify the specified directory (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.

IdentifierInfo * getPtr() const

bool isID() const

Whether this pointer is currently stored as ID.

Module * findModule(StringRef Name) const

Retrieve a module with the given name.

KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)

Retrieve the module that owns the given header file, if any.

static bool isModular(ModuleHeaderRole Role)

Check if the header with the given role is a modular one.

void resolveHeaderDirectives(const FileEntry *File) const

Resolve all lazy header directives for the specified file.

ArrayRef< KnownHeader > findResolvedModulesForHeader(FileEntryRef File) const

Like findAllModulesForHeader, but do not attempt to infer module ownership from umbrella headers if w...

OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const

bool isBuiltinHeader(FileEntryRef File)

Is this a compiler builtin header?

bool parseModuleMapFile(FileEntryRef File, bool IsSystem, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())

Parse the given module map file, and record any modules we encounter.

void setTarget(const TargetInfo &Target)

Set the target information.

ModuleHeaderRole

Flags describing the role of a module header.

@ ExcludedHeader

This header is explicitly excluded from the module.

@ TextualHeader

This header is part of the module (for layering purposes) but should be textually included.

ArrayRef< KnownHeader > findAllModulesForHeader(FileEntryRef File)

Retrieve all the modules that contain the given header file.

llvm::iterator_range< module_iterator > modules() const

bool resolveUses(Module *Mod, bool Complain)

Resolve all of the unresolved uses in the given module.

Describes a module or submodule.

bool directlyUses(const Module *Requested)

Determine whether this module has declared its intention to directly use another module.

std::string Name

The name of this module.

unsigned NoUndeclaredIncludes

Whether files in this module can only include non-modular headers and headers from used modules.

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

bool markIncluded(FileEntryRef File)

Mark the file as included.

bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M)

Determine whether II is defined as a macro within the module M, if that is a module that we've alread...

bool isMacroDefined(StringRef Id)

bool alreadyIncluded(FileEntryRef File) const

Return true if this header has already been included.

Encodes a location in the source.

This class handles loading and caching of source files into memory.

Exposes information about the current target.

The JSON file list parser is used to communicate input to InstallAPI.

@ Private

'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...

@ External

External linkage, which indicates that the entity can be referred to from other translation units.

@ Result

The result type of a method or function.

This structure is used to record entries in our framework cache.

bool IsUserSpecifiedSystemFramework

Whether this framework has been "user-specified" to be treated as if it were a system framework (even...

OptionalDirectoryEntryRef Directory

The directory entry which should be used for the cached framework.