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/FileSystem.h"

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

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

35#include "llvm/Support/Path.h"

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

37#include

38#include

39#include

40#include

41#include

42#include

43#include

44#include

45#include

46

47using namespace clang;

48using namespace SrcMgr;

49using llvm::MemoryBuffer;

50

51#define DEBUG_TYPE "source-manager"

52

53

54

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

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

57

58

59

60

61

62

63

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

66}

67

68

69

71 if (Buffer == nullptr) {

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

73 return llvm::MemoryBuffer::MemoryBuffer_Malloc;

74 }

75 return Buffer->getBufferKind();

76}

77

78

79

80

81

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

85}

86

88

89

90

91 const char *InvalidBOM =

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

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

94 "UTF-32 (BE)")

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

96 "UTF-32 (LE)")

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

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

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

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

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

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

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

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

105 .Default(nullptr);

106

107 return InvalidBOM;

108}

109

110std::optionalllvm::MemoryBufferRef

113

114

116 return std::nullopt;

117 if (Buffer)

118 return Buffer->getMemBufferRef();

120 return std::nullopt;

121

122

123

125

127

128

129

130

131

132

133 if (!BufferOrError) {

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

136

137 return std::nullopt;

138 }

139

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

141

142

143

144

145

146

147

148

149

150

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

153

154 return std::nullopt;

155 }

156

157

158

159

160

161

166

167 return std::nullopt;

168 }

169

170

171

172

173 StringRef BufStr = Buffer->getBuffer();

175

176 if (InvalidBOM) {

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

179 return std::nullopt;

180 }

181

182

184 return Buffer->getMemBufferRef();

185}

186

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

189 if (IterBool.second)

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

191 return IterBool.first->second;

192}

193

194

195

196

197

198

199

201 int FilenameID, unsigned EntryExit,

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

204

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

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

207

208 unsigned IncludeOffset = 0;

209 if (EntryExit == 1) {

210

211 IncludeOffset = Offset-1;

212 } else {

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

214 if (EntryExit == 2) {

215

216 assert(PrevEntry && PrevEntry->IncludeOffset &&

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

218 "stack");

219 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);

220 }

221 if (PrevEntry) {

222 IncludeOffset = PrevEntry->IncludeOffset;

223 if (FilenameID == -1) {

224

225

226 FilenameID = PrevEntry->FilenameID;

227 }

228 }

229 }

230

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

232 IncludeOffset));

233}

234

235

236

238 unsigned Offset) {

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

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

241

242

243

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

245 return &Entries.back();

246

247

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

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

250 return nullptr;

251 return &*--I;

252}

253

254

255

257 const std::vector &Entries) {

258 LineEntries[FID] = Entries;

259}

260

261

263 return getLineTable().getLineTableFilenameID(Name);

264}

265

266

267

268

270 int FilenameID, bool IsFileEntry,

271 bool IsFileExit,

273 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);

274

278 return;

279

281

282

284

285 (void) getLineTable();

286

287 unsigned EntryExit = 0;

288 if (IsFileEntry)

289 EntryExit = 1;

290 else if (IsFileExit)

291 EntryExit = 2;

292

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

294 EntryExit, FileKind);

295}

296

298 if (!LineTable)

300 return *LineTable;

301}

302

303

304

305

306

308 bool UserFilesAreVolatile)

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

312}

313

315

316

317

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

319 if (MemBufferInfos[i]) {

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

321 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);

322 }

323 }

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

325 if (I->second) {

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

327 ContentCacheAlloc.Deallocate(I->second);

328 }

329 }

330}

331

333 MainFileID = FileID();

334 LocalSLocEntryTable.clear();

335 LoadedSLocEntryTable.clear();

336 SLocEntryLoaded.clear();

337 SLocEntryOffsetLoaded.clear();

338 LastLineNoFileIDQuery = FileID();

339 LastLineNoContentCache = nullptr;

340 LastFileIDLookup = FileID();

341

342 IncludedLocMap.clear();

343 if (LineTable)

344 LineTable->clear();

345

346

347 NextLocalOffset = 0;

348 CurrentLoadedOffset = MaxLoadedOffset;

350}

351

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

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

356 return false;

357}

358

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

361

365 Clone->ContentsEntry = Cache->ContentsEntry;

366 Clone->BufferOverridden = Cache->BufferOverridden;

367 Clone->IsFileVolatile = Cache->IsFileVolatile;

368 Clone->IsTransient = Cache->IsTransient;

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

370 return Clone;

371 };

372

373

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

375 if (!Old.SLocEntryLoaded[I])

376 Old.loadSLocEntry(I, nullptr);

377

378

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

381 if (Slot)

382 continue;

383 Slot = CloneContentCache(FileInfo.second);

384 }

385}

386

388 bool isSystemFile) {

389

391 if (Entry)

392 return *Entry;

393

394

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

396

397 if (OverriddenFilesInfo) {

398

399

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

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

403 else

404 new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt

405 : overI->second,

406 overI->second);

407 } else {

409 }

410

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

414

415 return *Entry;

416}

417

418

419

420ContentCache &SourceManager::createMemBufferContentCache(

421 std::unique_ptrllvm::MemoryBuffer Buffer) {

422

425 MemBufferInfos.push_back(Entry);

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

427 return *Entry;

428}

429

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

433}

434

436 assert(!SLocEntryLoaded[Index]);

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

440

441 if (!SLocEntryLoaded[Index]) {

442

443 if (!FakeSLocEntryForRecovery)

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

447 return *FakeSLocEntryForRecovery;

448 }

449 }

450

451 return LoadedSLocEntryTable[Index];

452}

453

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

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

458

459 if (CurrentLoadedOffset < TotalSize ||

460 CurrentLoadedOffset - TotalSize < NextLocalOffset) {

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

462 }

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

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

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

466 CurrentLoadedOffset -= TotalSize;

467 updateSlocUsageStats();

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

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

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

471}

472

473

474

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

476 if (!FakeBufferForRecovery)

477 FakeBufferForRecovery =

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

479

480 return *FakeBufferForRecovery;

481}

482

483

484

486 if (!FakeContentCacheForRecovery) {

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

488 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());

489 }

490 return *FakeContentCacheForRecovery;

491}

492

493

494

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

498

499 int ID = FID.ID;

500 if (ID == -1)

502

503 if (ID > 0) {

504 if (ID-1 == 0)

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

508 }

509

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

511}

512

513

514

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

518

519 int ID = FID.ID;

520 if (ID > 0) {

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

525 }

526

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

528}

529

530

531

532

533

534

535

539 int LoadedID,

543

544

545

548

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

550 LoadedID, LoadedOffset);

551}

552

553

554

555

556

559 int LoadedID,

562 StringRef Name = Buffer->getBufferIdentifier();

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

564 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);

565}

566

567

568

569

570

573 int LoadedID,

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

577 LoadedID, LoadedOffset, IncludeLoc);

578}

579

580

581

587 FileCharacter);

588}

589

590

592#ifdef __MVS__

593 llvm::ErrorOr NeedConversion =

594 llvm::needzOSConversion(Filename.str().c_str());

595 return NeedConversion && *NeedConversion;

596#else

597 return false;

598#endif

599}

600

601

602

603

607 int LoadedID,

609 if (LoadedID < 0) {

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

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

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

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

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

617 return FileID::get(LoadedID);

618 }

619 unsigned FileSize = File.getSize();

621 if (NeedConversion) {

622

623

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

626 unsigned BufSize = Buffer->getBufferSize();

627 if (BufSize > FileSize) {

628 if (File.ContentsEntry.has_value())

629 File.ContentsEntry->updateFileEntryBufferSize(BufSize);

630 FileSize = BufSize;

631 }

632 }

633 }

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

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

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

639 }

640 LocalSLocEntryTable.push_back(

643

644

645 NextLocalOffset += FileSize + 1;

646 updateSlocUsageStats();

647

648

649

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

651 return LastFileIDLookup = FID;

652}

653

657 ExpansionLoc);

658 return createExpansionLocImpl(Info, Length);

659}

660

664 bool ExpansionIsTokenRange, int LoadedID,

667 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);

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

669}

670

675 "token spans multiple files");

676 return createExpansionLocImpl(

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

679}

680

682SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,

683 unsigned Length, int LoadedID,

685 if (LoadedID < 0) {

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

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

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

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

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

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

692 return SourceLocation::getMacroLoc(LoadedOffset);

693 }

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

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

696 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {

697 Diag.Report(diag::err_sloc_space_too_large);

698

699

700

701

702

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

704 }

705

706 NextLocalOffset += Length + 1;

707 updateSlocUsageStats();

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

709}

710

711std::optionalllvm::MemoryBufferRef

715}

716

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

720

723

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

725}

726

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

731 "the correct size");

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

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

734 "any parsing occurs.");

735

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

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

738 if (!Pair.second)

739 Pair.first->second = NewFile;

740}

741

746

747

748 if (!BypassFile)

749 return std::nullopt;

750

751 (void)getOrCreateContentCache(*BypassFile);

752 return BypassFile;

753}

754

757}

758

759std::optional

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

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

764 return std::nullopt;

765}

766

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

772}

773

774std::optional

778 return std::nullopt;

779}

780

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

785 return B->getBuffer();

786 return std::nullopt;

787}

788

789

790

791

792

793

794

795

796

797

799 if (!SLocOffset)

800 return FileID::get(0);

801

802

803

804 if (SLocOffset < NextLocalOffset)

805 return getFileIDLocal(SLocOffset);

806 return getFileIDLoaded(SLocOffset);

807}

808

809

810

811

812

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

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831 unsigned LessIndex = 0;

832

833 unsigned GreaterIndex = LocalSLocEntryTable.size();

834 if (LastFileIDLookup.ID >= 0) {

835

836 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)

837 LessIndex = LastFileIDLookup.ID;

838 else

839 GreaterIndex = LastFileIDLookup.ID;

840 }

841

842

843 unsigned NumProbes = 0;

844 while (true) {

845 --GreaterIndex;

846 assert(GreaterIndex < LocalSLocEntryTable.size());

847 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {

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

849

850 LastFileIDLookup = Res;

851 NumLinearScans += NumProbes+1;

852 return Res;

853 }

854 if (++NumProbes == 8)

855 break;

856 }

857

858 NumProbes = 0;

859 while (true) {

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

863

864 ++NumProbes;

865

866

867

868 if (MidOffset > SLocOffset) {

869 GreaterIndex = MiddleIndex;

870 continue;

871 }

872

873

874 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||

876 FileID Res = FileID::get(MiddleIndex);

877

878

879 LastFileIDLookup = Res;

880 NumBinaryProbes += NumProbes;

881 return Res;

882 }

883

884

885 LessIndex = MiddleIndex;

886 }

887}

888

889

890

891

892

894 if (SLocOffset < CurrentLoadedOffset) {

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

897 }

898

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

900}

901

904 do {

905

906

907

908

909

910

913

914 return Loc;

915}

916

918 do {

923 return Loc;

924}

925

927 do {

930 else

933 return Loc;

934}

935

936

937std::pair<FileID, unsigned>

938SourceManager::getDecomposedExpansionLocSlowCase(

940

943 unsigned Offset;

944 do {

945 Loc = E->getExpansion().getExpansionLocStart();

946

949 Offset = Loc.getOffset()-E->getOffset();

951

952 return std::make_pair(FID, Offset);

953}

954

955std::pair<FileID, unsigned>

956SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,

957 unsigned Offset) const {

958

961 do {

962 Loc = E->getExpansion().getSpellingLoc();

964

967 Offset = Loc.getOffset()-E->getOffset();

969

970 return std::make_pair(FID, Offset);

971}

972

973

974

975

976

982}

983

984

987 return F->getName();

988 return StringRef();

989}

990

991

992

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

998}

999

1003 return Loc;

1004}

1005

1006

1007

1011

1013

1014

1015

1022 }

1023 return Res;

1024}

1025

1029

1033

1034 if (StartLoc)

1036 return true;

1037}

1038

1041

1045}

1046

1050

1052 if (DecompLoc.second > 0)

1053 return false;

1054

1059 return false;

1061

1063

1064

1065

1066 FileID PrevFID = getPreviousFileID(DecompLoc.first);

1070 return false;

1073 return false;

1074 }

1075 }

1076

1077 if (MacroBegin)

1078 *MacroBegin = ExpLoc;

1079 return true;

1080}

1081

1085

1089 return false;

1090

1095 return false;

1096

1098

1099

1100

1101 FileID NextFID = getNextFileID(FID);

1105 return false;

1109 return false;

1110 }

1111 }

1112

1113 if (MacroEnd)

1115 return true;

1116}

1117

1118

1119

1120

1121

1122

1123

1126

1127

1129

1130

1131 bool CharDataInvalid = false;

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

1136

1137 return "<<<>>>";

1138 }

1139 std::optionalllvm::MemoryBufferRef Buffer =

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

1145 : "<<<>>>";

1146}

1147

1148

1149

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

1155

1156 if (!MemBuf)

1157 return 1;

1158

1159

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

1163 return 1;

1164 }

1165

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

1167

1168

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

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

1171 const unsigned *SourceLineCache =

1173 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];

1174 unsigned LineEnd = SourceLineCache[LastLineNoResult];

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

1176

1177

1178

1179

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

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

1182 --FilePos;

1183 }

1184 return FilePos - LineStart + 1;

1185 }

1186 }

1187

1188 unsigned LineStart = FilePos;

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

1190 --LineStart;

1191 return FilePos-LineStart+1;

1192}

1193

1194

1195

1196template

1201 return MyInvalid;

1202}

1203

1209}

1210

1216}

1217

1223}

1224

1225

1226

1227

1228

1229template

1231 unsigned char n) {

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

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

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

1235 ~static_cast(0) / 255 * 128;

1236}

1237

1239 llvm::BumpPtrAllocator &Alloc) {

1240

1241

1242

1244

1245

1246 LineOffsets.push_back(0);

1247

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

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

1250 const unsigned char *Buf = Start;

1251

1252 uint64_t Word;

1253

1254

1255

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

1257 do {

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

1259

1261 if (!Mask) {

1262 Buf += sizeof(Word);

1263 continue;

1264 }

1265

1266

1267

1268

1269

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

1271 Word >>= N;

1272 Buf += N / 8 + 1;

1273 unsigned char Byte = Word;

1274 switch (Byte) {

1275 case '\r':

1276

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

1278 ++Buf;

1279 }

1280 [[fallthrough]];

1281 case '\n':

1282 LineOffsets.push_back(Buf - Start);

1283 };

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

1285 }

1286

1287

1288 while (Buf < End) {

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

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

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

1292

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

1294 ++Buf;

1295 }

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

1297 }

1298 ++Buf;

1299 }

1300

1302}

1303

1305 llvm::BumpPtrAllocator &Alloc)

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

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

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

1309}

1310

1311

1312

1313

1314

1320 return 1;

1321 }

1322

1324 if (LastLineNoFileIDQuery == FID)

1325 Content = LastLineNoContentCache;

1326 else {

1327 bool MyInvalid = false;

1328 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);

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

1332 return 1;

1333 }

1334

1336 }

1337

1338

1339

1341 std::optionalllvm::MemoryBufferRef Buffer =

1345 if (!Buffer)

1346 return 1;

1347

1352

1353

1354

1356 const unsigned *SourceLineCacheStart = SourceLineCache;

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

1358

1359 unsigned QueriedFilePos = FilePos+1;

1360

1361

1362

1363

1364

1365

1366

1367

1368

1369

1370

1371

1372

1373

1374 if (LastLineNoFileIDQuery == FID) {

1375 if (QueriedFilePos >= LastLineNoFilePos) {

1376

1377 SourceLineCache = SourceLineCache+LastLineNoResult-1;

1378

1379

1380

1381

1382

1383 if (SourceLineCache+5 < SourceLineCacheEnd) {

1384 if (SourceLineCache[5] > QueriedFilePos)

1385 SourceLineCacheEnd = SourceLineCache+5;

1386 else if (SourceLineCache+10 < SourceLineCacheEnd) {

1387 if (SourceLineCache[10] > QueriedFilePos)

1388 SourceLineCacheEnd = SourceLineCache+10;

1389 else if (SourceLineCache+20 < SourceLineCacheEnd) {

1390 if (SourceLineCache[20] > QueriedFilePos)

1391 SourceLineCacheEnd = SourceLineCache+20;

1392 }

1393 }

1394 }

1395 } else {

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

1397 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;

1398 }

1399 }

1400

1401 const unsigned *Pos =

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

1403 unsigned LineNo = Pos-SourceLineCacheStart;

1404

1405 LastLineNoFileIDQuery = FID;

1406 LastLineNoContentCache = Content;

1407 LastLineNoFilePos = QueriedFilePos;

1408 LastLineNoResult = LineNo;

1409 return LineNo;

1410}

1411

1415 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);

1416 return getLineNumber(LocInfo.first, LocInfo.second);

1417}

1421 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);

1422 return getLineNumber(LocInfo.first, LocInfo.second);

1423}

1429}

1430

1431

1432

1433

1434

1435

1436

1437

1438

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

1442 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);

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

1444 if (!SEntry)

1446

1448

1449

1450

1453

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

1455

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

1458

1459

1460 if (!Entry)

1462

1464}

1465

1466

1467

1468

1472

1473 auto B = getBufferOrNone(getFileID(Loc));

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

1477}

1478

1479

1480

1481

1482

1483

1484

1485

1487 bool UseLineDirectives) const {

1489

1490

1491 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);

1492

1494 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);

1497

1500

1501

1502

1503

1504 FileID FID = LocInfo.first;

1506 if (C->OrigEntry)

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

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

1509 Filename = Buffer->getBufferIdentifier();

1510

1511 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);

1514 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);

1517

1519

1520

1521

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

1524

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

1527

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

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

1530

1531

1532 FID = FileID::get(0);

1533 }

1534

1535

1536

1537

1538

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

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

1541

1542

1543

1544

1545 if (Entry->IncludeOffset) {

1546 IncludeLoc = getLocForStartOfFile(LocInfo.first);

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

1548 }

1549 }

1550 }

1551

1553}

1554

1555

1556

1557

1558

1559

1560

1561

1564

1565

1566 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);

1567

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

1569 if (!Entry)

1570 return false;

1571

1573

1574

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

1578 if (Entry->IncludeOffset)

1579 return false;

1580

1582}

1583

1584

1589 return 0;

1590

1591 int ID = FID.ID;

1593 if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))

1594 NextOffset = getNextLocalOffset();

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

1596 NextOffset = MaxLoadedOffset;

1597 else

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

1599

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

1601}

1602

1603

1604

1605

1606

1607

1608

1609

1610

1612 unsigned Line,

1613 unsigned Col) const {

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

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

1616

1617 FileID FirstFID = translateFile(SourceFile);

1618 return translateLineCol(FirstFID, Line, Col);

1619}

1620

1621

1622

1623

1624

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

1627

1628

1629

1630 if (MainFileID.isValid()) {

1632 const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid);

1635

1636 if (MainSLoc.isFile()) {

1638 return MainFileID;

1639 }

1640 }

1641

1642

1643

1644 for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {

1645 const SLocEntry &SLoc = getLocalSLocEntry(I);

1646 if (SLoc.isFile() &&

1648 return FileID::get(I);

1649 }

1650

1651

1652 for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {

1653 const SLocEntry &SLoc = getLoadedSLocEntry(I);

1654 if (SLoc.isFile() &&

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

1657 }

1658

1660}

1661

1662

1663

1665 unsigned Line,

1666 unsigned Col) const {

1667

1668

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

1670

1673

1678

1679 if (!Entry.isFile())

1681

1683

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

1685 return FileLoc;

1686

1688

1689

1690

1691 std::optionalllvm::MemoryBufferRef Buffer =

1693 if (!Buffer)

1698

1700 unsigned Size = Buffer->getBufferSize();

1701 if (Size > 0)

1702 --Size;

1704 }

1705

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

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

1709 if (BufLength == 0)

1711

1712 unsigned i = 0;

1713

1714

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

1716 ++i;

1718}

1719

1720

1721

1722

1723

1724

1725

1726

1727void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,

1730

1731

1732 MacroArgsCache.insert(std::make_pair(0, SourceLocation()));

1733

1734 int ID = FID.ID;

1735 while (true) {

1736 ++ID;

1737

1738 if (ID > 0) {

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

1740 return;

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

1742 return;

1743 }

1744

1748 return;

1749 if (Entry.isFile()) {

1753 continue;

1754

1756 bool IncludedInFID =

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

1758

1759

1760

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

1762 if (IncludedInFID) {

1763

1764

1765 if (Entry.getFile().NumCreatedFIDs)

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

1767 continue;

1768 }

1769

1770

1771 if (IncludeLoc.isValid())

1772 return;

1773 continue;

1774 }

1775

1777

1780 return;

1781 }

1782

1784 continue;

1785

1786 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,

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

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

1790 }

1791}

1792

1793void SourceManager::associateFileChunkWithMacroArgExp(

1794 MacroArgsMap &MacroArgsCache,

1798 unsigned ExpansionLength) const {

1802

1803

1804

1805

1806

1807

1808 FileID SpellFID;

1809 unsigned SpellRelativeOffs;

1810 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);

1811 while (true) {

1812 const SLocEntry &Entry = getSLocEntry(SpellFID);

1814 unsigned SpellFIDSize = getFileIDSize(SpellFID);

1818 unsigned CurrSpellLength;

1819 if (SpellFIDEndOffs < SpellEndOffs)

1820 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;

1821 else

1822 CurrSpellLength = ExpansionLength;

1823 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,

1825 ExpansionLoc, CurrSpellLength);

1826 }

1827

1828 if (SpellFIDEndOffs >= SpellEndOffs)

1829 return;

1830

1831

1832 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;

1834 ExpansionLength -= advance;

1835 ++SpellFID.ID;

1836 SpellRelativeOffs = 0;

1837 }

1838 }

1839

1840 assert(SpellLoc.isFileID());

1841

1842 unsigned BeginOffs;

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

1844 return;

1845

1846 unsigned EndOffs = BeginOffs + ExpansionLength;

1847

1848

1849

1850

1851

1852

1853

1854

1855

1856

1857

1858

1859

1860

1861

1862

1863

1864

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

1866 --I;

1868 MacroArgsCache[BeginOffs] = ExpansionLoc;

1869 MacroArgsCache[EndOffs] = EndOffsMappedLoc;

1870}

1871

1872void SourceManager::updateSlocUsageStats() const {

1874 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);

1875 MaxUsedSLocBytes.updateMax(UsedBytes);

1876}

1877

1878

1879

1880

1881

1882

1883

1884

1885

1886

1890 return Loc;

1891

1893 unsigned Offset;

1894 std::tie(FID, Offset) = getDecomposedLoc(Loc);

1896 return Loc;

1897

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

1899 if (!MacroArgsCache) {

1900 MacroArgsCache = std::make_unique();

1901 computeMacroArgsCache(*MacroArgsCache, FID);

1902 }

1903

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

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

1906

1907

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

1909 return Loc;

1910

1911 --I;

1912

1915 if (MacroArgExpandedLoc.isValid())

1916 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);

1917

1918 return Loc;

1919}

1920

1921std::pair<FileID, unsigned>

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

1925

1926

1927

1928 using DecompTy = std::pair<FileID, unsigned>;

1929 auto InsertOp = IncludedLocMap.try_emplace(FID);

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

1931 if (!InsertOp.second)

1932 return DecompLoc;

1933

1940 else

1942 }

1943

1945 DecompLoc = getDecomposedLoc(UpperLoc);

1946

1947 return DecompLoc;

1948}

1949

1951 assert(isLoadedSourceLocation(Loc) &&

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

1953

1954 auto [FID, Ignore] = getDecomposedLoc(Loc);

1955

1956

1957

1958

1959 const FileID *FirstFID =

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

1961

1962 assert(FirstFID &&

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

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

1965 return *FirstFID;

1966}

1967

1969 const std::pair<FileID, unsigned> &LOffs,

1970 const std::pair<FileID, unsigned> &ROffs) const {

1971

1972 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))

1973 return false;

1974

1975 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {

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

1977

1978

1979 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,

1980 std::greater{});

1981 };

1982

1983

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

1985 return false;

1986 }

1987

1988 return true;

1989}

1990

1991

1992

1993

1994

1995static bool

1998 std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);

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

2000 SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))

2001 return true;

2002

2003 Loc = UpperLoc;

2004 return false;

2005}

2006

2007

2008

2010 FileID RFID) const {

2011

2012

2013

2014

2015 enum { MagicCacheSize = 300 };

2016 IsBeforeInTUCacheKey Key(LFID, RFID);

2017

2018

2019

2020

2021

2022 if (IBTUCache.size() < MagicCacheSize)

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

2024

2025

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

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

2028 return I->second;

2029

2030

2031 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);

2032 return IBTUCacheOverflow;

2033}

2034

2035

2036

2037

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

2041 if (LHS == RHS)

2042 return false;

2043

2044 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);

2045 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);

2046

2047

2048

2049

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

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

2052

2053 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);

2054 if (InSameTU.first)

2055 return InSameTU.second;

2056

2057 return LOffs.first < ROffs.first;

2058}

2059

2061 std::pair<FileID, unsigned> &LOffs,

2062 std::pair<FileID, unsigned> &ROffs) const {

2063

2064 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))

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

2066

2067

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

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

2070

2071

2072

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

2075

2076

2077

2079 return std::make_pair(

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

2081

2082

2083

2084

2085

2086

2087

2088 struct Entry {

2089 std::pair<FileID, unsigned> DecomposedLoc;

2090 FileID ChildFID;

2091 };

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

2093

2095 do {

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

2097

2098

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

2100 break;

2101 LChild = LOffs.first;

2103

2105 do {

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

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

2108

2109 LOffs = LIt->second.DecomposedLoc;

2110 LChild = LIt->second.ChildFID;

2111

2112

2113

2114

2115

2116

2117

2118

2119 unsigned LChildID = LChild.ID;

2120 unsigned RChildID = RChild.ID;

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

2122 (LChildID == 0 || RChildID == 0) ||

2123 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),

2124 getComposedLoc(RChild, 0), nullptr)) &&

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

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

2127 LChildID < RChildID);

2128 return std::make_pair(

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

2130 }

2131 RChild = ROffs.first;

2133

2134

2135

2136

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

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

2139

2140 bool LIsBuiltins = LB == "";

2141 bool RIsBuiltins = RB == "";

2142

2143 if (LIsBuiltins || RIsBuiltins) {

2144 if (LIsBuiltins != RIsBuiltins)

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

2146

2147

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

2149 }

2150

2151 bool LIsAsm = LB == "";

2152 bool RIsAsm = RB == "";

2153

2154 if (LIsAsm || RIsAsm) {

2155 if (LIsAsm != RIsAsm)

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

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

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

2159 }

2160

2161 bool LIsScratch = LB == "";

2162 bool RIsScratch = RB == "";

2163

2164 if (LIsScratch || RIsScratch) {

2165 if (LIsScratch != RIsScratch)

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

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

2168 }

2169

2170 llvm_unreachable("Unsortable locations found");

2171}

2172

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

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

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

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

2178 << llvm::capacity_in_bytes(LocalSLocEntryTable)

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

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

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

2182 << " loaded SLocEntries allocated ("

2183 << llvm::capacity_in_bytes(LoadedSLocEntryTable)

2184 << " bytes of capacity), "

2185 << MaxLoadedOffset - CurrentLoadedOffset

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

2187

2188 unsigned NumLineNumsComputed = 0;

2189 unsigned NumFileBytesMapped = 0;

2190 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){

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

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

2193 }

2194 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();

2195

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

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

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

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

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

2201}

2202

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

2205

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

2207 std::optionalSourceLocation::UIntTy NextStart) {

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

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

2210 if (NextStart)

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

2212 else

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

2214 if (Entry.isFile()) {

2215 auto &FI = Entry.getFile();

2216 if (FI.NumCreatedFIDs)

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

2218 << ">\n";

2219 if (FI.getIncludeLoc().isValid())

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

2221 auto &CC = FI.getContentCache();

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

2223 << "\n";

2224 if (CC.BufferOverridden)

2225 out << " contents overridden\n";

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

2227 out << " contents from "

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

2229 << "\n";

2230 }

2231 } else {

2232 auto &EI = Entry.getExpansion();

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

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

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

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

2237 }

2238 };

2239

2240

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

2242 DumpSLocEntry(ID, LocalSLocEntryTable[ID],

2243 ID == NumIDs - 1 ? NextLocalOffset

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

2245 }

2246

2247 std::optionalSourceLocation::UIntTy NextStart;

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

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

2250 if (SLocEntryLoaded[Index]) {

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

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

2253 } else {

2254 NextStart = std::nullopt;

2255 }

2256 }

2257}

2258

2261 struct Info {

2262

2264

2265 unsigned Inclusions = 0;

2266

2267 uint64_t DirectSize = 0;

2268

2269 uint64_t TotalSize = 0;

2270 };

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

2272

2273 UsageMap Usage;

2274 uint64_t CountedSize = 0;

2275

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

2277

2278

2279 unsigned Size = getFileIDSize(ID) + 1;

2280

2281

2282

2283 SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0));

2284 FileID FileLocID = getFileID(FileStart);

2285 const FileEntry *Entry = getFileEntryForID(FileLocID);

2286

2287 Info &EntryInfo = Usage[Entry];

2288 if (EntryInfo.Loc.isInvalid())

2289 EntryInfo.Loc = FileStart;

2290 if (ID == FileLocID) {

2291 ++EntryInfo.Inclusions;

2292 EntryInfo.DirectSize += Size;

2293 }

2294 EntryInfo.TotalSize += Size;

2295 CountedSize += Size;

2296 };

2297

2298

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

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

2301 }

2302

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

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

2305 }

2306

2307

2308

2309 auto SortedUsage = Usage.takeVector();

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

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

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

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

2314 };

2315 auto SortedEnd = SortedUsage.end();

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

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

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

2319 }

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

2321

2322

2323 uint64_t LocalUsage = NextLocalOffset;

2324 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;

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

2326 MaxLoadedOffset);

2327 Diag.Report(diag::note_total_sloc_usage)

2328 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)

2329 << UsagePercent;

2330

2331

2332 uint64_t ReportedSize = 0;

2333 for (auto &[Entry, FileInfo] :

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

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

2338 ReportedSize += FileInfo.TotalSize;

2339 }

2340

2341

2342 if (ReportedSize != CountedSize) {

2343 Diag.Report(diag::note_file_misc_sloc_usage)

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

2345 }

2346}

2347

2349

2350

2351

2353 size_t malloc_bytes = 0;

2354 size_t mmap_bytes = 0;

2355

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

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

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

2359 case llvm::MemoryBuffer::MemoryBuffer_MMap:

2360 mmap_bytes += sized_mapped;

2361 break;

2362 case llvm::MemoryBuffer::MemoryBuffer_Malloc:

2363 malloc_bytes += sized_mapped;

2364 break;

2365 }

2366

2368}

2369

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

2372 llvm::capacity_in_bytes(LocalSLocEntryTable) +

2373 llvm::capacity_in_bytes(LoadedSLocEntryTable) +

2374 llvm::capacity_in_bytes(SLocEntryLoaded) +

2375 llvm::capacity_in_bytes(FileInfos);

2376

2377 if (OverriddenFilesInfo)

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

2379

2380 return size;

2381}

2382

2384 StringRef Content) {

2385

2386

2388 new llvm::vfs::InMemoryFileSystem);

2389 InMemoryFileSystem->addFile(

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

2392 false));

2393

2394

2395 FileMgr =

2396 std::make_unique(FileSystemOptions(), InMemoryFileSystem);

2397

2398

2399 Diagnostics = std::make_unique(

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

2406 assert(ID.isValid());

2407 SourceMgr->setMainFileID(ID);

2408}

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)

static bool MoveUpTranslationUnitIncludeHierarchy(std::pair< FileID, unsigned > &Loc, const SourceManager &SM)

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

static bool isInvalid(LocType Loc, bool *Invalid)

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

bool needConversion(StringRef Filename)

Helper function to determine if an input file requires conversion.

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)

Used for handling and querying diagnostic IDs.

Options for controlling the compiler diagnostics engine.

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

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

void setSourceManager(SourceManager *SrcMgr)

virtual int getSLocEntryID(SourceLocation::UIntTy SLocOffset)=0

Get the index ID for the loaded SourceLocation offset.

virtual ~ExternalSLocEntrySource()

virtual bool ReadSLocEntry(int ID)=0

Read the source location entry with index ID, which will always be less than -1.

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,...

OptionalFileEntryRef getBypassFile(FileEntryRef VFE)

Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual file entry,...

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.

unsigned getLineTableFilenameID(StringRef Str)

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...

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...

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.

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...

bool isMacroBodyExpansion(SourceLocation Loc) const

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

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

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...

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

Return the column # for the specified file position.

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

bool isInMainFile(SourceLocation Loc) const

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

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.

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

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

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

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

Returns the "presumed" location of a SourceLocation specifies.

MemoryBufferSizes getMemoryBufferSizes() const

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

void setFileIsTransient(FileEntryRef SourceFile)

Specify that a file is transient.

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 translateLineCol(FileID FID, unsigned Line, unsigned Col) const

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

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

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

SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const

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

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

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

FileID translateFile(const FileEntry *SourceFile) const

Get the FileID for the given file.

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

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

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...

void PrintStats() const

Print statistics to stderr.

FileID getUniqueLoadedASTFileID(SourceLocation Loc) const

bool isMainFile(const FileEntry &SourceFile)

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

size_t getDataStructureSizes() const

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

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

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

bool isInTheSameTranslationUnitImpl(const std::pair< FileID, unsigned > &LOffs, const std::pair< FileID, unsigned > &ROffs) const

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

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

Get a local SLocEntry. This is exposed for indexing.

OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)

Bypass the overridden contents of a file.

FileManager & getFileManager() 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...

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

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

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...

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

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

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

unsigned getFileIDSize(FileID FID) const

The size of the SLocEntry that FID represents.

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

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

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

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

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

CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const

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

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

CharSourceRange getExpansionRange(SourceLocation Loc) const

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

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.

std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const

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

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

void initializeForReplay(const SourceManager &Old)

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

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

Get the FileID for SourceFile if it exists.

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

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

std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const

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

const FileEntry * getFileEntryForID(FileID FID) const

Returns the FileEntry record for the provided FileID.

std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const

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

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

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

SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const

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

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.

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

std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const

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

StringRef getFilename(SourceLocation SpellingLoc) const

Return the filename of the file containing a SourceLocation.

SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const

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

bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const

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

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

Return the buffer for the specified FileID.

LineTableInfo & getLineTable()

Retrieve the stored line table.

SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const

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

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

Retrieve the memory buffer associated with the given file.

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.

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.

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.

llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const

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

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.

static const char * getInvalidBOM(StringRef BufStr)

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

StringRef getName() const

Returns the name of the file that was used when the file was loaded from the underlying file system.

Mapping of line offsets into a source file.

const unsigned * begin() const

LineOffsetMapping()=default

const unsigned * end() const

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

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

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.

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

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)