clang: lib/Basic/SourceManager.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19#include "llvm/ADT/DenseMap.h"

20#include "llvm/ADT/MapVector.h"

21#include "llvm/ADT/STLExtras.h"

22#include "llvm/ADT/SmallVector.h"

23#include "llvm/ADT/Statistic.h"

24#include "llvm/ADT/StringRef.h"

25#include "llvm/ADT/StringSwitch.h"

26#include "llvm/Support/Allocator.h"

27#include "llvm/Support/AutoConvert.h"

28#include "llvm/Support/Capacity.h"

29#include "llvm/Support/Compiler.h"

30#include "llvm/Support/Endian.h"

31#include "llvm/Support/ErrorHandling.h"

32#include "llvm/Support/MemoryBuffer.h"

33#include "llvm/Support/raw_ostream.h"

34#include

35#include

36#include

37#include

38#include

39#include

40#include

41#include

42#include

43

44using namespace clang;

45using namespace SrcMgr;

46using llvm::MemoryBuffer;

47

48#define DEBUG_TYPE "source-manager"

49

50

51

52STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations "

53 "(both loaded and local).");

54

55

56

57

58

59

60

62 return Buffer ? Buffer->getBufferSize() : 0;

63}

64

65

66

68 if (Buffer == nullptr) {

69 assert(0 && "Buffer should never be null");

70 return llvm::MemoryBuffer::MemoryBuffer_Malloc;

71 }

72 return Buffer->getBufferKind();

73}

74

75

76

77

78

80 return Buffer ? (unsigned)Buffer->getBufferSize()

82}

83

85

86

87

88 const char *InvalidBOM =

89 llvm::StringSwitch<const char *>(BufStr)

90 .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),

91 "UTF-32 (BE)")

92 .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),

93 "UTF-32 (LE)")

94 .StartsWith("\xFE\xFF", "UTF-16 (BE)")

95 .StartsWith("\xFF\xFE", "UTF-16 (LE)")

96 .StartsWith("\x2B\x2F\x76", "UTF-7")

97 .StartsWith("\xF7\x64\x4C", "UTF-1")

98 .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")

99 .StartsWith("\x0E\xFE\xFF", "SCSU")

100 .StartsWith("\xFB\xEE\x28", "BOCU-1")

101 .StartsWith("\x84\x31\x95\x33", "GB-18030")

102 .Default(nullptr);

103

104 return InvalidBOM;

105}

106

107std::optionalllvm::MemoryBufferRef

110

111

113 return std::nullopt;

114 if (Buffer)

115 return Buffer->getMemBufferRef();

117 return std::nullopt;

118

119

120

122

124

125

126

127

128

129

130 if (!BufferOrError) {

131 Diag.Report(Loc, diag::err_cannot_open_file)

132 << ContentsEntry->getName() << BufferOrError.getError().message();

133

134 return std::nullopt;

135 }

136

137 Buffer = std::move(*BufferOrError);

138

139

140

141

142

143

144

145

146

147

148 if (Buffer->getBufferSize() >= std::numeric_limits::max()) {

149 Diag.Report(Loc, diag::err_file_too_large) << ContentsEntry->getName();

150

151 return std::nullopt;

152 }

153

154

155

156

157

158

159 assert(Buffer->getBufferSize() >= (size_t)ContentsEntry->getSize());

161 Buffer->getBufferSize() < (size_t)ContentsEntry->getSize()) {

162 Diag.Report(Loc, diag::err_file_modified) << ContentsEntry->getName();

163

164 return std::nullopt;

165 }

166

167

168

169

170 StringRef BufStr = Buffer->getBuffer();

172

173 if (InvalidBOM) {

174 Diag.Report(Loc, diag::err_unsupported_bom)

176 return std::nullopt;

177 }

178

179

181 return Buffer->getMemBufferRef();

182}

183

185 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());

186 if (IterBool.second)

187 FilenamesByID.push_back(&*IterBool.first);

188 return IterBool.first->second;

189}

190

191

192

193

194

195

196

198 int FilenameID, unsigned EntryExit,

200 std::vector &Entries = LineEntries[FID];

201

202 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&

203 "Adding line entries out of order!");

204

205 unsigned IncludeOffset = 0;

206 if (EntryExit == 1) {

207

208 IncludeOffset = Offset-1;

209 } else {

210 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();

211 if (EntryExit == 2) {

212

213 assert(PrevEntry && PrevEntry->IncludeOffset &&

214 "PPDirectives should have caught case when popping empty include "

215 "stack");

217 }

218 if (PrevEntry) {

219 IncludeOffset = PrevEntry->IncludeOffset;

220 if (FilenameID == -1) {

221

222

223 FilenameID = PrevEntry->FilenameID;

224 }

225 }

226 }

227

228 Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,

229 IncludeOffset));

230}

231

232

233

235 unsigned Offset) {

236 const std::vector &Entries = LineEntries[FID];

237 assert(!Entries.empty() && "No #line entries for this FID after all!");

238

239

240

241 if (Entries.back().FileOffset <= Offset)

242 return &Entries.back();

243

244

245 std::vector::const_iterator I = llvm::upper_bound(Entries, Offset);

246 if (I == Entries.begin())

247 return nullptr;

248 return &*--I;

249}

250

251

252

254 const std::vector &Entries) {

255 LineEntries[FID] = Entries;

256}

257

258

260 return getLineTable().getLineTableFilenameID(Name);

261}

262

263

264

265

267 int FilenameID, bool IsFileEntry,

268 bool IsFileExit,

271

275 return;

276

278

279

281

283

284 unsigned EntryExit = 0;

285 if (IsFileEntry)

286 EntryExit = 1;

287 else if (IsFileExit)

288 EntryExit = 2;

289

290 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,

291 EntryExit, FileKind);

292}

293

295 if (!LineTable)

297 return *LineTable;

298}

299

300

301

302

303

305 bool UserFilesAreVolatile)

306 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {

308 Diag.setSourceManager(this);

309}

310

312

313

314

315 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {

316 if (MemBufferInfos[i]) {

317 MemBufferInfos[i]->~ContentCache();

318 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);

319 }

320 }

321 for (auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {

322 if (I->second) {

323 I->second->~ContentCache();

324 ContentCacheAlloc.Deallocate(I->second);

325 }

326 }

327}

328

330 MainFileID = FileID();

331 LocalSLocEntryTable.clear();

332 LocalLocOffsetTable.clear();

333 LoadedSLocEntryTable.clear();

334 SLocEntryLoaded.clear();

335 SLocEntryOffsetLoaded.clear();

336 LastLineNoFileIDQuery = FileID();

337 LastLineNoContentCache = nullptr;

338 LastFileIDLookup = FileID();

339 LastLookupStartOffset = LastLookupEndOffset = 0;

340

341 IncludedLocMap.clear();

342 if (LineTable)

343 LineTable->clear();

344

345

346 NextLocalOffset = 0;

347 CurrentLoadedOffset = MaxLoadedOffset;

349

350

351 Diag.ResetPragmas();

352}

353

355 assert(MainFileID.isValid() && "expected initialized SourceManager");

357 return FE->getUID() == SourceFile.getUID();

358 return false;

359}

360

362 assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");

363

367 Clone->ContentsEntry = Cache->ContentsEntry;

368 Clone->BufferOverridden = Cache->BufferOverridden;

369 Clone->IsFileVolatile = Cache->IsFileVolatile;

370 Clone->IsTransient = Cache->IsTransient;

371 Clone->setUnownedBuffer(Cache->getBufferIfLoaded());

372 return Clone;

373 };

374

375

376 for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)

377 if (!Old.SLocEntryLoaded[I])

378 Old.loadSLocEntry(I, nullptr);

379

380

381 for (auto &FileInfo : Old.FileInfos) {

383 if (Slot)

384 continue;

385 Slot = CloneContentCache(FileInfo.second);

386 }

387}

388

390 bool isSystemFile) {

391

393 if (Entry)

394 return *Entry;

395

396

397 Entry = ContentCacheAlloc.Allocate<ContentCache>();

398

399 if (OverriddenFilesInfo) {

400

401

402 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);

403 if (overI == OverriddenFilesInfo->OverriddenFiles.end())

405 else

406 new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt

407 : overI->second,

408 overI->second);

409 } else {

411 }

412

413 Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;

416

417 return *Entry;

418}

419

420

421

422ContentCache &SourceManager::createMemBufferContentCache(

423 std::unique_ptrllvm::MemoryBuffer Buffer) {

424

425 ContentCache *Entry = ContentCacheAlloc.Allocate();

426 new (Entry) ContentCache();

427 MemBufferInfos.push_back(Entry);

428 Entry->setBuffer(std::move(Buffer));

429 return *Entry;

430}

431

432const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,

435}

436

438 assert(!SLocEntryLoaded[Index]);

439 if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {

442

443 if (!SLocEntryLoaded[Index]) {

444

445 if (!FakeSLocEntryForRecovery)

446 FakeSLocEntryForRecovery = std::make_unique(SLocEntry::get(

447 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),

449 return *FakeSLocEntryForRecovery;

450 }

451 }

452

453 return LoadedSLocEntryTable[Index];

454}

455

456std::pair<int, SourceLocation::UIntTy>

459 assert(ExternalSLocEntries && "Don't have an external sloc source");

460

461 if (CurrentLoadedOffset < TotalSize ||

462 CurrentLoadedOffset - TotalSize < NextLocalOffset) {

463 return std::make_pair(0, 0);

464 }

465 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);

466 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());

467 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());

468 CurrentLoadedOffset -= TotalSize;

469 updateSlocUsageStats();

470 int BaseID = -int(LoadedSLocEntryTable.size()) - 1;

471 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));

472 return std::make_pair(BaseID, CurrentLoadedOffset);

473}

474

475

476

477llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const {

478 if (!FakeBufferForRecovery)

479 FakeBufferForRecovery =

480 llvm::MemoryBuffer::getMemBuffer("<<>");

481

482 return *FakeBufferForRecovery;

483}

484

485

486

488 if (!FakeContentCacheForRecovery) {

489 FakeContentCacheForRecovery = std::make_uniqueSrcMgr::ContentCache();

490 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());

491 }

492 return *FakeContentCacheForRecovery;

493}

494

495

496

497FileID SourceManager::getPreviousFileID(FileID FID) const {

499 return FileID();

500

501 int ID = FID.ID;

502 if (ID == -1)

503 return FileID();

504

505 if (ID > 0) {

506 if (ID-1 == 0)

507 return FileID();

508 } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {

509 return FileID();

510 }

511

512 return FileID::get(ID-1);

513}

514

515

516

517FileID SourceManager::getNextFileID(FileID FID) const {

519 return FileID();

520

521 int ID = FID.ID;

522 if (ID > 0) {

524 return FileID();

525 } else if (ID+1 >= -1) {

526 return FileID();

527 }

528

529 return FileID::get(ID+1);

530}

531

532

533

534

535

536

537

541 int LoadedID,

545

546

547

550

551 return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,

552 LoadedID, LoadedOffset);

553}

554

555

556

557

558

561 int LoadedID,

564 StringRef Name = Buffer->getBufferIdentifier();

565 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,

566 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);

567}

568

569

570

571

572

575 int LoadedID,

578 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,

579 LoadedID, LoadedOffset, IncludeLoc);

580}

581

582

583

591

592

593

594

598 int LoadedID,

600 if (LoadedID < 0) {

601 assert(LoadedID != -1 && "Loading sentinel FileID");

602 unsigned Index = unsigned(-LoadedID) - 2;

603 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");

604 assert(!SLocEntryLoaded[Index] && "FileID already loaded");

606 LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));

607 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;

608 return FileID::get(LoadedID);

609 }

610 unsigned FileSize = File.getSize();

611 llvm::ErrorOr NeedConversion = llvm::needConversion(Filename);

612 if (NeedConversion && *NeedConversion) {

613

614

615 if (std::optionalllvm::MemoryBufferRef Buffer =

617 unsigned BufSize = Buffer->getBufferSize();

618 if (BufSize > FileSize) {

619 if (File.ContentsEntry.has_value())

620 File.ContentsEntry->updateFileEntryBufferSize(BufSize);

621 FileSize = BufSize;

622 }

623 }

624 }

625 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&

626 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {

627 Diag.Report(IncludePos, diag::err_sloc_space_too_large);

629 return FileID();

630 }

631 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());

632 LocalSLocEntryTable.push_back(

635 LocalLocOffsetTable.push_back(NextLocalOffset);

636 LastLookupStartOffset = NextLocalOffset;

637

638

639 NextLocalOffset += FileSize + 1;

640 LastLookupEndOffset = NextLocalOffset;

641 updateSlocUsageStats();

642

643

644

645 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);

646 return LastFileIDLookup = FID;

647}

648

652 ExpansionLoc);

653 return createExpansionLocImpl(Info, Length);

654}

655

659 bool ExpansionIsTokenRange, int LoadedID,

662 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);

663 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);

664}

665

670 "token spans multiple files");

671 return createExpansionLocImpl(

673 TokenEnd.getOffset() - TokenStart.getOffset());

674}

675

677SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,

678 unsigned Length, int LoadedID,

680 if (LoadedID < 0) {

681 assert(LoadedID != -1 && "Loading sentinel FileID");

682 unsigned Index = unsigned(-LoadedID) - 2;

683 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");

684 assert(!SLocEntryLoaded[Index] && "FileID already loaded");

685 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);

686 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;

687 return SourceLocation::getMacroLoc(LoadedOffset);

688 }

689 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());

690 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));

691 LocalLocOffsetTable.push_back(NextLocalOffset);

692 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||

693 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {

694 Diag.Report(diag::err_sloc_space_too_large);

695

696

697

698

699

700 llvm::report_fatal_error("ran out of source locations");

701 }

702

703 NextLocalOffset += Length + 1;

704 updateSlocUsageStats();

705 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));

706}

707

708std::optionalllvm::MemoryBufferRef

713

715 FileEntryRef SourceFile, std::unique_ptrllvm::MemoryBuffer Buffer) {

717

720

721 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);

722}

723

727 "Different sizes, use the FileManager to create a virtual file with "

728 "the correct size");

729 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&

730 "This function should be called at the initialization stage, before "

731 "any parsing occurs.");

732

733 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(

734 std::make_pair(SourceFile, NewFile));

735 if (!Pair.second)

736 Pair.first->second = NewFile;

737}

738

743

744

745 if (!BypassFile)

746 return std::nullopt;

747

748 (void)getOrCreateContentCache(*BypassFile);

749 return BypassFile;

750}

751

753 getOrCreateContentCache(File).IsTransient = true;

754}

755

756std::optional

759 if (Entry->getFile().getContentCache().OrigEntry)

760 return Entry->getFile().getName();

761 return std::nullopt;

762}

763

768 return B ? *B : "<<<<>>>>";

769}

770

771std::optional

775 return std::nullopt;

776}

777

780 if (auto B = Entry->getFile().getContentCache().getBufferOrNone(

782 return B->getBuffer();

783 return std::nullopt;

784}

785

786

787

788

789

790

791

792

793

794

796 if (!SLocOffset)

797 return FileID::get(0);

798

799

800

801 if (SLocOffset < NextLocalOffset)

802 return getFileIDLocal(SLocOffset);

803 return getFileIDLoaded(SLocOffset);

804}

805

806

807

808

809

811 assert(SLocOffset < NextLocalOffset && "Bad function choice");

812 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&

813 "Invalid SLocOffset");

814 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());

815 assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832 unsigned LessIndex = 0;

833

834 unsigned GreaterIndex = LocalLocOffsetTable.size();

835

836 if (LastLookupStartOffset < SLocOffset)

837 LessIndex = LastFileIDLookup.ID;

838 else

839 GreaterIndex = LastFileIDLookup.ID;

840

841

842 unsigned NumProbes = 0;

843 while (true) {

844 --GreaterIndex;

845 assert(GreaterIndex < LocalLocOffsetTable.size());

846 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {

847 FileID Res = FileID::get(int(GreaterIndex));

848

849 LastFileIDLookup = Res;

850 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];

851 LastLookupEndOffset =

852 GreaterIndex + 1 >= LocalLocOffsetTable.size()

853 ? NextLocalOffset

854 : LocalLocOffsetTable[GreaterIndex + 1];

855 NumLinearScans += NumProbes + 1;

856 return Res;

857 }

858 if (++NumProbes == 8)

859 break;

860 }

861

862 while (LessIndex < GreaterIndex) {

863 ++NumBinaryProbes;

864

865 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;

866 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)

867 LessIndex = MiddleIndex + 1;

868 else

869 GreaterIndex = MiddleIndex;

870 }

871

872

873

874

875 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];

876 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];

877 return LastFileIDLookup = FileID::get(LessIndex - 1);

878}

879

880

881

882

883

885 if (SLocOffset < CurrentLoadedOffset) {

886 assert(0 && "Invalid SLocOffset or bad function choice");

887 return FileID();

888 }

889

890 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));

891}

892

895 do {

896

897

898

899

900

901

904

905 return Loc;

906}

907

909 do {

912 Loc.getOffset() - Entry.getOffset());

914 return Loc;

915}

916

918 do {

920 const ExpansionInfo &ExpInfo = Entry.getExpansion();

924 } else {

926 }

928 return Loc;

929}

930

931

932

933

934

936 if (Loc.isFileID()) return Loc;

940}

941

942

945 return F->getName();

946 return StringRef();

947}

948

949

950

953 assert(Loc.isMacroID() && "Not a macro expansion loc!");

956}

957

963

964

965

969

971

972

973

980 }

981 return Res;

982}

983

986 if (!Loc.isMacroID()) return false;

987

991

992 if (StartLoc)

994 return true;

995}

996

998 if (!Loc.isMacroID()) return false;

999

1003}

1004

1007 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");

1008

1010 if (DecompLoc.second > 0)

1011 return false;

1012

1017 return false;

1019

1021

1022

1023

1024 FileID PrevFID = getPreviousFileID(DecompLoc.first);

1028 return false;

1031 return false;

1032 }

1033 }

1034

1035 if (MacroBegin)

1036 *MacroBegin = ExpLoc;

1037 return true;

1038}

1039

1042 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");

1043

1047 return false;

1048

1053 return false;

1054

1056

1057

1058

1059 FileID NextFID = getNextFileID(FID);

1063 return false;

1067 return false;

1068 }

1069 }

1070

1071 if (MacroEnd)

1073 return true;

1074}

1075

1076

1077

1078

1079

1080

1081

1084

1085

1087

1088

1089 bool CharDataInvalid = false;

1091 if (CharDataInvalid || !Entry.isFile()) {

1094

1095 return "<<<>>>";

1096 }

1097 std::optionalllvm::MemoryBufferRef Buffer =

1102 return Buffer ? Buffer->getBufferStart() + LocInfo.second

1103 : "<<<>>>";

1104}

1105

1106

1107

1110 std::optionalllvm::MemoryBufferRef MemBuf = getBufferOrNone(FID);

1113

1114 if (!MemBuf)

1115 return 1;

1116

1117

1118 if (FilePos > MemBuf->getBufferSize()) {

1121 return 1;

1122 }

1123

1124 const char *Buf = MemBuf->getBufferStart();

1125

1126

1127 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&

1128 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {

1129 const unsigned *SourceLineCache =

1130 LastLineNoContentCache->SourceLineCache.begin();

1131 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];

1132 unsigned LineEnd = SourceLineCache[LastLineNoResult];

1133 if (FilePos >= LineStart && FilePos < LineEnd) {

1134

1135

1136

1137

1138 if (FilePos + 1 == LineEnd && FilePos > LineStart) {

1139 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')

1140 --FilePos;

1141 }

1142 return (FilePos - LineStart) + 1;

1143 }

1144 }

1145

1146 unsigned LineStart = FilePos;

1147 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')

1148 --LineStart;

1149 return (FilePos - LineStart) + 1;

1150}

1151

1152

1153

1154template

1156 bool MyInvalid = Loc.isInvalid();

1159 return MyInvalid;

1160}

1161

1169

1176

1177

1178

1179

1180

1181template

1183 unsigned char n) {

1184 return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &

1185 ((x & ~static_cast<T>(0) / 255 * 127) +

1186 (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &

1187 ~static_cast(0) / 255 * 128;

1188}

1189

1191 llvm::BumpPtrAllocator &Alloc) {

1192

1193

1194

1196

1197

1198 LineOffsets.push_back(0);

1199

1200 const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();

1201 const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();

1202 const unsigned char *Buf = Start;

1203

1204 uint64_t Word;

1205

1206

1207

1208 if ((unsigned long)(End - Start) > sizeof(Word)) {

1209 do {

1210 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);

1211

1213 if (!Mask) {

1214 Buf += sizeof(Word);

1215 continue;

1216 }

1217

1218

1219

1220

1221

1222 unsigned N = llvm::countr_zero(Mask) - 7;

1223 Word >>= N;

1224 Buf += N / 8 + 1;

1225 unsigned char Byte = Word;

1226 switch (Byte) {

1227 case '\r':

1228

1229 if (*Buf == '\n') {

1230 ++Buf;

1231 }

1232 [[fallthrough]];

1233 case '\n':

1234 LineOffsets.push_back(Buf - Start);

1235 };

1236 } while (Buf < End - sizeof(Word) - 1);

1237 }

1238

1239

1240 while (Buf < End) {

1241 if (*Buf == '\n') {

1242 LineOffsets.push_back(Buf - Start + 1);

1243 } else if (*Buf == '\r') {

1244

1245 if (Buf + 1 < End && Buf[1] == '\n') {

1246 ++Buf;

1247 }

1248 LineOffsets.push_back(Buf - Start + 1);

1249 }

1250 ++Buf;

1251 }

1252

1254}

1255

1257 llvm::BumpPtrAllocator &Alloc)

1258 : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {

1259 Storage[0] = LineOffsets.size();

1260 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);

1261}

1262

1263

1264

1265

1266

1272 return 1;

1273 }

1274

1276 if (LastLineNoFileIDQuery == FID)

1277 Content = LastLineNoContentCache;

1278 else {

1279 bool MyInvalid = false;

1281 if (MyInvalid || !Entry.isFile()) {

1284 return 1;

1285 }

1286

1288 }

1289

1290

1291

1293 std::optionalllvm::MemoryBufferRef Buffer =

1297 if (!Buffer)

1298 return 1;

1299

1304

1305

1306

1308 const unsigned *SourceLineCacheStart = SourceLineCache;

1309 const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();

1310

1311 unsigned QueriedFilePos = FilePos+1;

1312

1313

1314

1315

1316

1317

1318

1319

1320

1321

1322

1323

1324

1325

1326 if (LastLineNoFileIDQuery == FID) {

1327 if (QueriedFilePos >= LastLineNoFilePos) {

1328

1329 SourceLineCache = SourceLineCache+LastLineNoResult-1;

1330

1331

1332

1333

1334

1335 if (SourceLineCache+5 < SourceLineCacheEnd) {

1336 if (SourceLineCache[5] > QueriedFilePos)

1337 SourceLineCacheEnd = SourceLineCache+5;

1338 else if (SourceLineCache+10 < SourceLineCacheEnd) {

1339 if (SourceLineCache[10] > QueriedFilePos)

1340 SourceLineCacheEnd = SourceLineCache+10;

1341 else if (SourceLineCache+20 < SourceLineCacheEnd) {

1342 if (SourceLineCache[20] > QueriedFilePos)

1343 SourceLineCacheEnd = SourceLineCache+20;

1344 }

1345 }

1346 }

1347 } else {

1348 if (LastLineNoResult < Content->SourceLineCache.size())

1349 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;

1350 }

1351 }

1352

1353 const unsigned *Pos =

1354 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);

1355 unsigned LineNo = Pos-SourceLineCacheStart;

1356

1357 LastLineNoFileIDQuery = FID;

1358 LastLineNoContentCache = Content;

1359 LastLineNoFilePos = QueriedFilePos;

1360 LastLineNoResult = LineNo;

1361 return LineNo;

1362}

1363

1370

1377

1378

1379

1380

1381

1382

1383

1384

1385

1388 assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");

1390 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);

1391 if (!SEntry)

1393

1395

1396

1397

1400

1401 assert(LineTable && "Can't have linetable entries without a LineTable!");

1402

1404 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);

1405

1406

1407 if (!Entry)

1409

1411}

1412

1413

1414

1415

1419

1423 return B ? B->getBufferIdentifier() : "";

1424}

1425

1426

1427

1428

1429

1430

1431

1432

1434 bool UseLineDirectives) const {

1436

1437

1439

1444

1447

1448

1449

1450

1451 FileID FID = LocInfo.first;

1452 StringRef Filename;

1453 if (C->OrigEntry)

1454 Filename = C->OrigEntry->getName();

1455 else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))

1456 Filename = Buffer->getBufferIdentifier();

1457

1464

1466

1467

1468

1470 assert(LineTable && "Can't have linetable entries without a LineTable!");

1471

1473 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {

1474

1475 if (Entry->FilenameID != -1) {

1476 Filename = LineTable->getFilename(Entry->FilenameID);

1477

1478

1479 FID = FileID::get(0);

1480 }

1481

1482

1483

1484

1485

1486 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);

1487 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);

1488

1489

1490

1491

1492 if (Entry->IncludeOffset) {

1494 IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);

1495 }

1496 }

1497 }

1498

1499 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);

1500}

1501

1502

1503

1504

1505

1506

1507

1508

1510 if (Loc.isInvalid()) return false;

1511

1512

1514

1515 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);

1516 if (!Entry)

1517 return false;

1518

1520

1521

1524 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))

1525 if (Entry->IncludeOffset)

1526 return false;

1527

1529}

1530

1531

1536 return 0;

1537

1538 int ID = FID.ID;

1542 else if (ID+1 == -1)

1543 NextOffset = MaxLoadedOffset;

1544 else

1545 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();

1546

1547 return NextOffset - Entry.getOffset() - 1;

1548}

1549

1550

1551

1552

1553

1554

1555

1556

1557

1559 unsigned Line,

1560 unsigned Col) const {

1561 assert(SourceFile && "Null source file!");

1562 assert(Line && Col && "Line and column should start from 1!");

1563

1566}

1567

1568

1569

1570

1571

1573 assert(SourceFile && "Null source file!");

1574

1575

1576

1577 if (MainFileID.isValid()) {

1582

1583 if (MainSLoc.isFile()) {

1585 return MainFileID;

1586 }

1587 }

1588

1589

1590

1593 if (SLoc.isFile() &&

1595 return FileID::get(I);

1596 }

1597

1598

1601 if (SLoc.isFile() &&

1603 return FileID::get(-int(I) - 2);

1604 }

1605

1607}

1608

1609

1610

1612 unsigned Line,

1613 unsigned Col) const {

1614

1615

1616 assert(Line && Col && "Line and column should start from 1!");

1617

1620

1625

1626 if (!Entry.isFile())

1628

1630

1631 if (Line == 1 && Col == 1)

1632 return FileLoc;

1633

1635

1636

1637

1638 std::optionalllvm::MemoryBufferRef Buffer =

1640 if (!Buffer)

1645

1647 unsigned Size = Buffer->getBufferSize();

1648 if (Size > 0)

1649 --Size;

1651 }

1652

1654 const char *Buf = Buffer->getBufferStart() + FilePos;

1655 unsigned BufLength = Buffer->getBufferSize() - FilePos;

1656 if (BufLength == 0)

1658

1659 unsigned i = 0;

1660

1661

1662 while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')

1663 ++i;

1665}

1666

1667

1668

1669

1670

1671

1672

1673

1674void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,

1677

1678

1679 MacroArgsCache.try_emplace(0);

1680

1681 int ID = FID.ID;

1682 while (true) {

1683 ++ID;

1684

1685 if (ID > 0) {

1686 if (unsigned(ID) >= local_sloc_entry_size())

1687 return;

1688 } else if (ID == -1) {

1689 return;

1690 }

1691

1693 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);

1695 return;

1696 if (Entry.isFile()) {

1700 continue;

1701

1703 bool IncludedInFID =

1704 (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||

1705

1706

1707

1708 (FID == MainFileID && Entry.getFile().getName() == "");

1709 if (IncludedInFID) {

1710

1711

1712 if (Entry.getFile().NumCreatedFIDs)

1713 ID += Entry.getFile().NumCreatedFIDs - 1 ;

1714 continue;

1715 }

1716

1717

1718 if (IncludeLoc.isValid())

1719 return;

1720 continue;

1721 }

1722

1724

1727 return;

1728 }

1729

1731 continue;

1732

1733 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,

1735 SourceLocation::getMacroLoc(Entry.getOffset()),

1736 getFileIDSize(FileID::get(ID)));

1737 }

1738}

1739

1740void SourceManager::associateFileChunkWithMacroArgExp(

1741 MacroArgsMap &MacroArgsCache,

1742 FileID FID,

1743 SourceLocation SpellLoc,

1744 SourceLocation ExpansionLoc,

1745 unsigned ExpansionLength) const {

1749

1750

1751

1752

1753

1754

1755

1756 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);

1757 while (true) {

1758 const SLocEntry &Entry = getSLocEntry(SpellFID);

1760 unsigned SpellFIDSize = getFileIDSize(SpellFID);

1764 unsigned CurrSpellLength;

1765 if (SpellFIDEndOffs < SpellEndOffs)

1766 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;

1767 else

1768 CurrSpellLength = ExpansionLength;

1769 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,

1771 ExpansionLoc, CurrSpellLength);

1772 }

1773

1774 if (SpellFIDEndOffs >= SpellEndOffs)

1775 return;

1776

1777

1778 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;

1780 ExpansionLength -= advance;

1781 ++SpellFID.ID;

1782 SpellRelativeOffs = 0;

1783 }

1784 }

1785

1786 assert(SpellLoc.isFileID());

1787

1788 unsigned BeginOffs;

1789 if (!isInFileID(SpellLoc, FID, &BeginOffs))

1790 return;

1791

1792 unsigned EndOffs = BeginOffs + ExpansionLength;

1793

1794

1795

1796

1797

1798

1799

1800

1801

1802

1803

1804

1805

1806

1807

1808

1809

1810

1811 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);

1812 --I;

1813 SourceLocation EndOffsMappedLoc = I->second;

1814 MacroArgsCache[BeginOffs] = ExpansionLoc;

1815 MacroArgsCache[EndOffs] = EndOffsMappedLoc;

1816}

1817

1818void SourceManager::updateSlocUsageStats() const {

1820 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);

1821 MaxUsedSLocBytes.updateMax(UsedBytes);

1822}

1823

1824

1825

1826

1827

1828

1829

1830

1831

1832

1833SourceLocation

1836 return Loc;

1837

1840 return Loc;

1841

1842 std::unique_ptr &MacroArgsCache = MacroArgsCacheMap[FID];

1843 if (!MacroArgsCache) {

1844 MacroArgsCache = std::make_unique();

1845 computeMacroArgsCache(*MacroArgsCache, FID);

1846 }

1847

1848 assert(!MacroArgsCache->empty());

1849 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);

1850

1851

1852 if (I == MacroArgsCache->begin())

1853 return Loc;

1854

1855 --I;

1856

1859 if (MacroArgExpandedLoc.isValid())

1860 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);

1861

1862 return Loc;

1863}

1864

1867 return std::make_pair(FileID(), 0);

1868

1869

1870

1872 auto InsertOp = IncludedLocMap.try_emplace(FID);

1873 DecompTy &DecompLoc = InsertOp.first->second;

1874 if (!InsertOp.second)

1875 return DecompLoc;

1876

1883 else

1885 }

1886

1889

1890 return DecompLoc;

1891}

1892

1895 "Must be a source location in a loaded PCH/Module file");

1896

1898

1899

1900

1901

1902 const FileID *FirstFID =

1903 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater{});

1904

1905 assert(FirstFID &&

1906 "The failure to find the first FileID of a "

1907 "loaded AST from a loaded source location was unexpected.");

1908 return *FirstFID;

1909}

1910

1913

1915 return false;

1916

1918 auto FindSLocEntryAlloc = [this](FileID FID) {

1919

1920

1921 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,

1922 std::greater{});

1923 };

1924

1925

1926 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))

1927 return false;

1928 }

1929

1930 return true;

1931}

1932

1933

1934

1935

1936

1939 FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);

1940 if (UpperLoc.first.isInvalid() ||

1941 SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))

1942 return true;

1943

1944 Loc = UpperLoc;

1945 return false;

1946}

1947

1948

1949

1950InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,

1951 FileID RFID) const {

1952

1953

1954

1955

1956 enum { MagicCacheSize = 300 };

1957 IsBeforeInTUCacheKey Key(LFID, RFID);

1958

1959

1960

1961

1962

1963 if (IBTUCache.size() < MagicCacheSize)

1964 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;

1965

1966

1967 InBeforeInTUCache::iterator I = IBTUCache.find(Key);

1968 if (I != IBTUCache.end())

1969 return I->second;

1970

1971

1972 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);

1973 return IBTUCacheOverflow;

1974}

1975

1976

1977

1978

1981 assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");

1982 if (LHS == RHS)

1983 return false;

1984

1987

1988

1989

1990

1991 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())

1992 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();

1993

1995 if (InSameTU.first)

1996 return InSameTU.second;

1997

1998 return LOffs.first < ROffs.first;

1999}

2000

2001std::pair<bool, bool>

2004

2006 return std::make_pair(false, false);

2007

2008

2009 if (LOffs.first == ROffs.first)

2010 return std::make_pair(true, LOffs.second < ROffs.second);

2011

2012

2013

2015 getInBeforeInTUCache(LOffs.first, ROffs.first);

2016

2017

2018

2020 return std::make_pair(

2021 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));

2022

2023

2024

2025

2026

2027

2028

2029 struct Entry {

2030 FileIDAndOffset DecomposedLoc;

2031 FileID ChildFID;

2032 };

2033 llvm::SmallDenseMap<FileID, Entry, 16> LChain;

2034

2036 do {

2037 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});

2038

2039

2040 if (LOffs.first == ROffs.first)

2041 break;

2042 LChild = LOffs.first;

2044

2046 do {

2047 auto LIt = LChain.find(ROffs.first);

2048 if (LIt != LChain.end()) {

2049

2050 LOffs = LIt->second.DecomposedLoc;

2051 LChild = LIt->second.ChildFID;

2052

2053

2054

2055

2056

2057

2058

2059

2060 unsigned LChildID = LChild.ID;

2061 unsigned RChildID = RChild.ID;

2062 assert(((LOffs.second != ROffs.second) ||

2063 (LChildID == 0 || RChildID == 0) ||

2066 "Mixed local/loaded FileIDs with same include location?");

2067 IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,

2068 LChildID < RChildID);

2069 return std::make_pair(

2070 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));

2071 }

2072 RChild = ROffs.first;

2074

2075

2076

2077

2078 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();

2079 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();

2080

2081 bool LIsBuiltins = LB == "";

2082 bool RIsBuiltins = RB == "";

2083

2084 if (LIsBuiltins || RIsBuiltins) {

2085 if (LIsBuiltins != RIsBuiltins)

2086 return std::make_pair(true, LIsBuiltins);

2087

2088

2089 return std::make_pair(true, LOffs.first < ROffs.first);

2090 }

2091

2092 bool LIsAsm = LB == "";

2093 bool RIsAsm = RB == "";

2094

2095 if (LIsAsm || RIsAsm) {

2096 if (LIsAsm != RIsAsm)

2097 return std::make_pair(true, RIsAsm);

2098 assert(LOffs.first == ROffs.first);

2099 return std::make_pair(true, false);

2100 }

2101

2102 bool LIsScratch = LB == "";

2103 bool RIsScratch = RB == "";

2104

2105 if (LIsScratch || RIsScratch) {

2106 if (LIsScratch != RIsScratch)

2107 return std::make_pair(true, LIsScratch);

2108 return std::make_pair(true, LOffs.second < ROffs.second);

2109 }

2110

2111 llvm_unreachable("Unsortable locations found");

2112}

2113

2115 llvm::errs() << "\n*** Source Manager Stats:\n";

2116 llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()

2117 << " mem buffers mapped.\n";

2118 llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntries allocated ("

2119 << llvm::capacity_in_bytes(LocalSLocEntryTable)

2120 << " bytes of capacity), " << NextLocalOffset

2121 << "B of SLoc address space used.\n";

2122 llvm::errs() << LoadedSLocEntryTable.size()

2123 << " loaded SLocEntries allocated ("

2124 << llvm::capacity_in_bytes(LoadedSLocEntryTable)

2125 << " bytes of capacity), "

2126 << MaxLoadedOffset - CurrentLoadedOffset

2127 << "B of SLoc address space used.\n";

2128

2129 unsigned NumLineNumsComputed = 0;

2130 unsigned NumFileBytesMapped = 0;

2132 NumLineNumsComputed += bool(I->second->SourceLineCache);

2133 NumFileBytesMapped += I->second->getSizeBytesMapped();

2134 }

2135 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();

2136

2137 llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "

2138 << NumLineNumsComputed << " files with line #'s computed, "

2139 << NumMacroArgsComputed << " files with macro args computed.\n";

2140 llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "

2141 << NumBinaryProbes << " binary.\n";

2142}

2143

2145 llvm::raw_ostream &out = llvm::errs();

2146

2147 auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,

2148 std::optionalSourceLocation::UIntTy NextStart) {

2149 out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")

2150 << " <SourceLocation " << Entry.getOffset() << ":";

2151 if (NextStart)

2152 out << *NextStart << ">\n";

2153 else

2154 out << "???\?>\n";

2155 if (Entry.isFile()) {

2156 auto &FI = Entry.getFile();

2157 if (FI.NumCreatedFIDs)

2158 out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)

2159 << ">\n";

2160 if (FI.getIncludeLoc().isValid())

2161 out << " included from " << FI.getIncludeLoc().getOffset() << "\n";

2162 auto &CC = FI.getContentCache();

2163 out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "")

2164 << "\n";

2165 if (CC.BufferOverridden)

2166 out << " contents overridden\n";

2167 if (CC.ContentsEntry != CC.OrigEntry) {

2168 out << " contents from "

2169 << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "")

2170 << "\n";

2171 }

2172 } else {

2173 auto &EI = Entry.getExpansion();

2174 out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";

2175 out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")

2176 << " range <" << EI.getExpansionLocStart().getOffset() << ":"

2177 << EI.getExpansionLocEnd().getOffset() << ">\n";

2178 }

2179 };

2180

2181

2182 for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {

2183 DumpSLocEntry(ID, LocalSLocEntryTable[ID],

2184 ID == NumIDs - 1 ? NextLocalOffset

2185 : LocalSLocEntryTable[ID + 1].getOffset());

2186 }

2187

2188 std::optionalSourceLocation::UIntTy NextStart;

2189 for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {

2190 int ID = -(int)Index - 2;

2191 if (SLocEntryLoaded[Index]) {

2192 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);

2193 NextStart = LoadedSLocEntryTable[Index].getOffset();

2194 } else {

2195 NextStart = std::nullopt;

2196 }

2197 }

2198}

2199

2201 DiagnosticsEngine &Diag, std::optional MaxNotes) const {

2202 struct Info {

2203

2205

2206 unsigned Inclusions = 0;

2207

2208 uint64_t DirectSize = 0;

2209

2210 uint64_t TotalSize = 0;

2211 };

2212 using UsageMap = llvm::MapVector<const FileEntry*, Info>;

2213

2214 UsageMap Usage;

2215 uint64_t CountedSize = 0;

2216

2217 auto AddUsageForFileID = [&](FileID ID) {

2218

2219

2221

2222

2223

2227

2228 Info &EntryInfo = Usage[Entry];

2229 if (EntryInfo.Loc.isInvalid())

2230 EntryInfo.Loc = FileStart;

2231 if (ID == FileLocID) {

2232 ++EntryInfo.Inclusions;

2233 EntryInfo.DirectSize += Size;

2234 }

2235 EntryInfo.TotalSize += Size;

2236 CountedSize += Size;

2237 };

2238

2239

2240 for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {

2241 AddUsageForFileID(FileID::get(-2 - Index));

2242 }

2243

2244 for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {

2245 AddUsageForFileID(FileID::get(Index));

2246 }

2247

2248

2249

2250 auto SortedUsage = Usage.takeVector();

2251 auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {

2252 return A.second.TotalSize > B.second.TotalSize ||

2253 (A.second.TotalSize == B.second.TotalSize &&

2254 A.second.Loc < B.second.Loc);

2255 };

2256 auto SortedEnd = SortedUsage.end();

2257 if (MaxNotes && SortedUsage.size() > *MaxNotes) {

2258 SortedEnd = SortedUsage.begin() + *MaxNotes;

2259 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);

2260 }

2261 std::sort(SortedUsage.begin(), SortedEnd, Cmp);

2262

2263

2264 uint64_t LocalUsage = NextLocalOffset;

2265 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;

2266 int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /

2267 MaxLoadedOffset);

2268 Diag.Report(diag::note_total_sloc_usage)

2269 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)

2270 << UsagePercent;

2271

2272

2273 uint64_t ReportedSize = 0;

2274 for (auto &[Entry, FileInfo] :

2275 llvm::make_range(SortedUsage.begin(), SortedEnd)) {

2276 Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)

2279 ReportedSize += FileInfo.TotalSize;

2280 }

2281

2282

2283 if (ReportedSize != CountedSize) {

2284 Diag.Report(diag::note_file_misc_sloc_usage)

2285 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;

2286 }

2287}

2288

2290

2291

2292

2294 size_t malloc_bytes = 0;

2295 size_t mmap_bytes = 0;

2296

2297 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)

2298 if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())

2299 switch (MemBufferInfos[i]->getMemoryBufferKind()) {

2300 case llvm::MemoryBuffer::MemoryBuffer_MMap:

2301 mmap_bytes += sized_mapped;

2302 break;

2303 case llvm::MemoryBuffer::MemoryBuffer_Malloc:

2304 malloc_bytes += sized_mapped;

2305 break;

2306 }

2307

2309}

2310

2312 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +

2313 llvm::capacity_in_bytes(LocalSLocEntryTable) +

2314 llvm::capacity_in_bytes(LoadedSLocEntryTable) +

2315 llvm::capacity_in_bytes(SLocEntryLoaded) +

2316 llvm::capacity_in_bytes(FileInfos);

2317

2318 if (OverriddenFilesInfo)

2319 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);

2320

2321 return size;

2322}

2323

2325 StringRef Content) {

2326 auto InMemoryFileSystem =

2327 llvm::makeIntrusiveRefCntllvm::vfs::InMemoryFileSystem();

2328 InMemoryFileSystem->addFile(

2330 llvm::MemoryBuffer::getMemBuffer(Content, FileName,

2331 false));

2332

2333

2335 std::move(InMemoryFileSystem));

2336 DiagOpts = std::make_unique();

2337

2338

2339 Diagnostics =

2341 SourceMgr = std::make_unique(*Diagnostics, *FileMgr);

2345 assert(ID.isValid());

2346 SourceMgr->setMainFileID(ID);

2347}

Defines the Diagnostic-related interfaces.

Defines the clang::FileManager interface and associated types.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

static ParseState advance(ParseState S, size_t N)

Defines the clang::SourceLocation class and associated facilities.

Defines implementation details of the clang::SourceManager class.

static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)

Definition SourceManager.cpp:1182

static bool isInvalid(LocType Loc, bool *Invalid)

Definition SourceManager.cpp:1155

STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")

static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)

Given a decomposed source location, move it up the include/expansion stack to the parent source locat...

Definition SourceManager.cpp:1937

Defines the SourceManager interface.

Represents a character-granular source range.

void setEnd(SourceLocation e)

bool isTokenRange() const

Return true if the end of this range specifies the start of the last token.

void setBegin(SourceLocation b)

SourceLocation getEnd() const

SourceLocation getBegin() const

void setTokenRange(bool TR)

static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()

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

virtual ~ExternalSLocEntrySource()

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::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)

Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...

Keeps track of options that affect how file operations are performed.

Holds the cache used by isBeforeInTranslationUnit.

void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)

bool getCachedResult(unsigned LOffset, unsigned ROffset) const

If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.

bool isCacheValid() const

Return true if the currently cached values match up with the specified LHS/RHS query.

Used to hold and unique data used to represent #line information.

const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)

Find the line entry nearest to FID that is before it.

Definition SourceManager.cpp:234

unsigned getLineTableFilenameID(StringRef Str)

Definition SourceManager.cpp:184

void AddEntry(FileID FID, const std::vector< LineEntry > &Entries)

Add a new line entry that has already been encoded into the internal representation of the line table...

Definition SourceManager.cpp:253

void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind)

Add a line note to the line table that indicates that there is a #line or GNU line marker at the spec...

Definition SourceManager.cpp:197

Represents an unpacked "presumed" location which can be presented to the user.

unsigned getColumn() const

Return the presumed column number of this location.

unsigned getLine() const

Return the presumed line number of this location.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

SourceManagerForFile(StringRef FileName, StringRef Content)

Creates SourceManager and necessary dependencies (e.g.

Definition SourceManager.cpp:2324

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

std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const

Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...

Definition SourceManager.cpp:757

FileIDAndOffset getDecomposedExpansionLoc(SourceLocation Loc) const

Decompose the specified location into a raw FileID + Offset pair.

bool isMacroBodyExpansion(SourceLocation Loc) const

Tests whether the given source location represents the expansion of a macro body.

Definition SourceManager.cpp:997

FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const

Decompose the specified location into a raw FileID + Offset pair.

unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const

Definition SourceManager.cpp:1371

FileID getFileID(SourceLocation SpellingLoc) const

Return the FileID for a SourceLocation.

bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const

Returns true if the given MacroID location points at the character end of the immediate macro expansi...

Definition SourceManager.cpp:1040

~SourceManager()

Definition SourceManager.cpp:311

SourceLocation::UIntTy getNextLocalOffset() const

unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const

Return the column # for the specified file position.

Definition SourceManager.cpp:1108

void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const

Definition SourceManager.cpp:2200

bool isInMainFile(SourceLocation Loc) const

Returns whether the PresumedLoc for a given SourceLocation is in the main file.

Definition SourceManager.cpp:1509

void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)

Add a line note to the line table for the FileID and offset specified by Loc.

Definition SourceManager.cpp:266

SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)

Definition SourceManager.cpp:304

SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)

Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...

Definition SourceManager.cpp:666

PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const

Returns the "presumed" location of a SourceLocation specifies.

Definition SourceManager.cpp:1433

bool isInTheSameTranslationUnitImpl(const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const

Determines whether the two decomposed source location is in the same TU.

Definition SourceManager.cpp:1911

MemoryBufferSizes getMemoryBufferSizes() const

Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...

Definition SourceManager.cpp:2293

void setFileIsTransient(FileEntryRef SourceFile)

Specify that a file is transient.

Definition SourceManager.cpp:752

bool isFileOverridden(const FileEntry *File) const

Returns true if the file contents have been overridden.

OptionalFileEntryRef getFileEntryRefForID(FileID FID) const

Returns the FileEntryRef for the provided FileID.

SourceLocation getFileLoc(SourceLocation Loc) const

Given Loc, if it is a macro location return the expansion location or the spelling location,...

SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const

Get the source location in FID for the given line:col.

Definition SourceManager.cpp:1611

StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const

Return the filename or buffer identifier of the buffer the location is in.

Definition SourceManager.cpp:1416

SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const

Definition SourceManager.cpp:958

std::optional< StringRef > getBufferDataOrNone(FileID FID) const

Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...

Definition SourceManager.cpp:778

FileID translateFile(const FileEntry *SourceFile) const

Get the FileID for the given file.

Definition SourceManager.cpp:1572

StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const

Return a StringRef to the source buffer data for the specified FileID.

Definition SourceManager.cpp:764

FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)

Create a new FileID that represents the specified file being #included from the specified IncludePosi...

Definition SourceManager.cpp:538

void PrintStats() const

Print statistics to stderr.

Definition SourceManager.cpp:2114

FileID getUniqueLoadedASTFileID(SourceLocation Loc) const

Definition SourceManager.cpp:1893

bool isMainFile(const FileEntry &SourceFile)

Returns true when the given FileEntry corresponds to the main file.

Definition SourceManager.cpp:354

size_t getDataStructureSizes() const

Return the amount of memory used for various side tables and data structures in the SourceManager.

Definition SourceManager.cpp:2311

bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const

Tests whether the given source location represents a macro argument's expansion into the function-lik...

Definition SourceManager.cpp:984

void clearIDTables()

Definition SourceManager.cpp:329

const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const

Get a local SLocEntry. This is exposed for indexing.

SourceLocation getComposedLoc(FileID FID, unsigned Offset) const

Form a SourceLocation from a FileID and Offset pair.

OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)

Bypass the overridden contents of a file.

Definition SourceManager.cpp:740

const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const

Get a loaded SLocEntry. This is exposed for indexing.

llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator

FileManager & getFileManager() const

fileinfo_iterator fileinfo_end() const

unsigned local_sloc_entry_size() const

Get the number of local SLocEntries we have.

std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const

Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...

Definition SourceManager.cpp:772

FileIDAndOffset getDecomposedSpellingLoc(SourceLocation Loc) const

Decompose the specified location into a raw FileID + Offset pair.

const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const

Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.

Definition SourceManager.cpp:1082

std::pair< int, SourceLocation::UIntTy > AllocateLoadedSLocEntries(unsigned NumSLocEntries, SourceLocation::UIntTy TotalSize)

Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...

Definition SourceManager.cpp:457

void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)

Override the contents of the given source file by providing an already-allocated buffer.

llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const

Return the buffer for the specified FileID.

unsigned getFileIDSize(FileID FID) const

The size of the SLocEntry that FID represents.

Definition SourceManager.cpp:1532

unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const

Given a SourceLocation, return the spelling line number for the position indicated.

Definition SourceManager.cpp:1267

void dump() const

Definition SourceManager.cpp:2144

CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const

Return the start/end of the expansion information for an expansion location.

Definition SourceManager.cpp:952

CharSourceRange getExpansionRange(SourceLocation Loc) const

Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...

Definition SourceManager.cpp:966

bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const

Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...

unsigned getLineTableFilenameID(StringRef Str)

Return the uniqued ID for the specified filename.

Definition SourceManager.cpp:259

void initializeForReplay(const SourceManager &Old)

Initialize this source manager suitably to replay the compilation described by Old.

Definition SourceManager.cpp:361

FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const

Returns the "included/expanded in" decomposed location of the given FileID.

Definition SourceManager.cpp:1865

bool isLoadedSourceLocation(SourceLocation Loc) const

Returns true if Loc came from a PCH/Module.

unsigned loaded_sloc_entry_size() const

Get the number of loaded SLocEntries we have.

FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)

Get the FileID for SourceFile if it exists.

Definition SourceManager.cpp:585

SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const

Get the source location for the given file:line:col triplet.

Definition SourceManager.cpp:1558

bool isLoadedFileID(FileID FID) const

Returns true if FID came from a PCH/Module.

const FileEntry * getFileEntryForID(FileID FID) const

Returns the FileEntry record for the provided FileID.

bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, SourceLocation::IntTy *RelativeOffset) const

Return true if both LHS and RHS are in the local source location address space or the loaded one.

SourceLocation getLocForStartOfFile(FileID FID) const

Return the source location corresponding to the first byte of the specified file.

bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const

Returns true if the given MacroID location points at the beginning of the immediate macro expansion.

Definition SourceManager.cpp:1005

SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const

Return the file characteristic of the specified source location, indicating whether this is a normal ...

Definition SourceManager.cpp:1387

SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)

Creates an expansion SLocEntry for a macro use.

Definition SourceManager.cpp:656

unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const

Definition SourceManager.cpp:1170

std::pair< bool, bool > isInTheSameTranslationUnit(FileIDAndOffset &LOffs, FileIDAndOffset &ROffs) const

Determines whether the two decomposed source location is in the same translation unit.

Definition SourceManager.cpp:2002

StringRef getFilename(SourceLocation SpellingLoc) const

Return the filename of the file containing a SourceLocation.

Definition SourceManager.cpp:943

SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const

If Loc points inside a function macro argument, the returned location will be the macro location in w...

Definition SourceManager.cpp:1834

bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const

Determines the order of 2 source locations in the translation unit.

Definition SourceManager.cpp:1979

std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const

Return the buffer for the specified FileID.

fileinfo_iterator fileinfo_begin() const

LineTableInfo & getLineTable()

Retrieve the stored line table.

Definition SourceManager.cpp:294

SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const

Given a SourceLocation object, return the spelling location referenced by the ID.

Definition SourceManager.cpp:935

std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)

Retrieve the memory buffer associated with the given file.

Definition SourceManager.cpp:709

const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const

SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)

Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.

Definition SourceManager.cpp:649

A trivial tuple used to represent a source range.

One instance of this struct is kept for every file loaded or used.

void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)

Set the buffer.

std::optional< StringRef > getBufferDataIfLoaded() const

Return a StringRef to the source buffer data, only if it has already been loaded.

OptionalFileEntryRef ContentsEntry

References the file which the contents were actually loaded from.

unsigned getSizeBytesMapped() const

Returns the number of bytes actually mapped for this ContentCache.

Definition SourceManager.cpp:61

unsigned IsTransient

True if this file may be transient, that is, if it might not exist at some later point in time when t...

unsigned getSize() const

Returns the size of the content encapsulated by this ContentCache.

Definition SourceManager.cpp:79

llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const

Returns the kind of memory used to back the memory buffer for this content cache.

Definition SourceManager.cpp:67

unsigned IsFileVolatile

True if this content cache was initially created for a source file considered to be volatile (likely ...

LineOffsetMapping SourceLineCache

A bump pointer allocated array of offsets for each source line.

std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const

Returns the memory buffer for the associated content.

Definition SourceManager.cpp:108

static const char * getInvalidBOM(StringRef BufStr)

Definition SourceManager.cpp:84

unsigned BufferOverridden

Indicates whether the buffer itself was provided to override the actual file contents.

OptionalFileEntryRef OrigEntry

Reference to the file entry representing this ContentCache.

Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...

SourceLocation getExpansionLocStart() const

static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)

Return a ExpansionInfo for an expansion.

bool isMacroBodyExpansion() const

SourceLocation getSpellingLoc() const

CharSourceRange getExpansionLocRange() const

bool isMacroArgExpansion() const

static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)

Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...

static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)

Return a special ExpansionInfo representing a token that ends prematurely.

SourceLocation getExpansionLocEnd() const

Information about a FileID, basically just the logical file that it represents and include stack info...

const ContentCache & getContentCache() const

CharacteristicKind getFileCharacteristic() const

Return whether this is a system header or not.

static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)

Return a FileInfo object.

bool hasLineDirectives() const

Return true if this FileID has #line directives in it.

void setHasLineDirectives()

Set the flag that indicates that this FileID has line table entries associated with it.

SourceLocation getIncludeLoc() const

const unsigned * begin() const

LineOffsetMapping()=default

const unsigned * end() const

static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)

Definition SourceManager.cpp:1190

This is a discriminated union of FileInfo and ExpansionInfo.

SourceLocation::UIntTy getOffset() const

static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)

const FileInfo & getFile() const

const ExpansionInfo & getExpansion() const

Public enums and private classes that are part of the SourceManager implementation.

CharacteristicKind

Indicates whether a file or directory holds normal user code, system code, or system code which is im...

bool isSystem(CharacteristicKind CK)

Determine whether a file / directory characteristic is for system code.

StringRef getName(const HeaderType T)

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

CustomizableOptional< FileEntryRef > OptionalFileEntryRef

std::pair< FileID, unsigned > FileIDAndOffset

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

const FunctionProtoType * T

SrcMgr::CharacteristicKind FileKind

Set the 0 if no flags, 1 if a system header,.

static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)