LLVM: lib/Support/SourceMgr.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

30#include

31#include

32#include

33#include

34#include

35#include

36#include

37

38using namespace llvm;

39

41

42

49

53

55 this->FS = std::move(FS);

56}

57

60 std::string &IncludedFile) {

63 if (!NewBufOrErr)

64 return 0;

65

67}

68

71 std::string &IncludedFile) {

72 auto GetFile = [this](StringRef Path) {

74 };

75

77

79

80 for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;

81 ++i) {

82 Buffer = IncludeDirectories[i];

84 NewBufOrErr = GetFile(Buffer);

85 }

86

87 if (NewBufOrErr)

88 IncludedFile = static_caststd::string\(Buffer);

89

90 return NewBufOrErr;

91}

92

94 for (unsigned i = 0, e = Buffers.size(); i != e; ++i)

95 if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&

96

97

98 Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())

99 return i + 1;

100 return 0;

101}

102

103template

106 if (OffsetCache)

107 return *static_cast<std::vector *>(OffsetCache);

108

109

110 auto *Offsets = new std::vector();

112 assert(Sz <= std::numeric_limits::max());

114 for (size_t N = 0; N < Sz; ++N) {

115 if (S[N] == '\n')

116 Offsets->push_back(static_cast<T>(N));

117 }

118

119 OffsetCache = Offsets;

120 return *Offsets;

121}

122

123template

124unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *Ptr) const {

125 std::vector &Offsets =

127

128 const char *BufStart = Buffer->getBufferStart();

129 assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());

130 ptrdiff_t PtrDiff = Ptr - BufStart;

131 assert(PtrDiff >= 0 &&

132 static_cast<size_t>(PtrDiff) <= std::numeric_limits::max());

133 T PtrOffset = static_cast<T>(PtrDiff);

134

135

136

138}

139

140

141

142unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {

143 size_t Sz = Buffer->getBufferSize();

144 if (Sz <= std::numeric_limits<uint8_t>::max())

145 return getLineNumberSpecialized<uint8_t>(Ptr);

146 else if (Sz <= std::numeric_limits<uint16_t>::max())

147 return getLineNumberSpecialized<uint16_t>(Ptr);

148 else if (Sz <= std::numeric_limits<uint32_t>::max())

149 return getLineNumberSpecialized<uint32_t>(Ptr);

150 else

151 return getLineNumberSpecialized<uint64_t>(Ptr);

152}

153

154template

155const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(

156 unsigned LineNo) const {

157 std::vector &Offsets =

159

160

161 if (LineNo != 0)

162 --LineNo;

163

164 const char *BufStart = Buffer->getBufferStart();

165

166

167

168 if (LineNo == 0)

169 return BufStart;

170 if (LineNo > Offsets.size())

171 return nullptr;

172 return BufStart + Offsets[LineNo - 1] + 1;

173}

174

175

176

177const char *

178SourceMgr::SrcBuffer::getPointerForLineNumber(unsigned LineNo) const {

179 size_t Sz = Buffer->getBufferSize();

180 if (Sz <= std::numeric_limits<uint8_t>::max())

181 return getPointerForLineNumberSpecialized<uint8_t>(LineNo);

182 else if (Sz <= std::numeric_limits<uint16_t>::max())

183 return getPointerForLineNumberSpecialized<uint16_t>(LineNo);

184 else if (Sz <= std::numeric_limits<uint32_t>::max())

185 return getPointerForLineNumberSpecialized<uint32_t>(LineNo);

186 else

187 return getPointerForLineNumberSpecialized<uint64_t>(LineNo);

188}

189

190SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other)

191 : Buffer(std::move(Other.Buffer)), OffsetCache(Other.OffsetCache),

192 IncludeLoc(Other.IncludeLoc) {

193 Other.OffsetCache = nullptr;

194}

195

196SourceMgr::SrcBuffer::~SrcBuffer() {

197 if (OffsetCache) {

198 size_t Sz = Buffer->getBufferSize();

199 if (Sz <= std::numeric_limits<uint8_t>::max())

200 delete static_cast<std::vector<uint8_t> *>(OffsetCache);

201 else if (Sz <= std::numeric_limits<uint16_t>::max())

202 delete static_cast<std::vector<uint16_t> *>(OffsetCache);

203 else if (Sz <= std::numeric_limits<uint32_t>::max())

204 delete static_cast<std::vector<uint32_t> *>(OffsetCache);

205 else

206 delete static_cast<std::vector<uint64_t> *>(OffsetCache);

207 OffsetCache = nullptr;

208 }

209}

210

211std::pair<unsigned, unsigned>

213 if (!BufferID)

215 assert(BufferID && "Invalid location!");

216

218 const char *Ptr = Loc.getPointer();

219

220 unsigned LineNo = SB.getLineNumber(Ptr);

221 const char *BufStart = SB.Buffer->getBufferStart();

224 NewlineOffs = ~(size_t)0;

225 return {LineNo, Ptr - BufStart - NewlineOffs};

226}

227

228

229

230

231

232

233

234

235

237 bool IncludePath) const {

239 assert(BufferID && "Invalid location!");

240 auto FileSpec = getBufferInfo(BufferID).Buffer->getBufferIdentifier();

241

242 if (IncludePath) {

243 return FileSpec.str() + ":" + std::to_string(FindLineNumber(Loc, BufferID));

244 } else {

245 auto I = FileSpec.find_last_of("/\\");

246 I = (I == FileSpec.size()) ? 0 : (I + 1);

247 return FileSpec.substr(I).str() + ":" +

249 }

250}

251

252

253

255 unsigned ColNo) {

257 const char *Ptr = SB.getPointerForLineNumber(LineNo);

258 if (!Ptr)

260

261

262 if (ColNo != 0)

263 --ColNo;

264

265

266 if (ColNo) {

267

268 if (Ptr + ColNo > SB.Buffer->getBufferEnd())

270

271

274

275 Ptr += ColNo;

276 }

277

279}

280

282 if (IncludeLoc == SMLoc())

283 return;

284

286 assert(CurBuf && "Invalid or unspecified location!");

287

289

290 OS << "Included from " << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()

291 << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";

292}

293

297

298

300 std::pair<unsigned, unsigned> LineAndCol;

301 StringRef BufferID = "";

303

304 if (Loc.isValid()) {

306 assert(CurBuf && "Invalid or unspecified location!");

307

310

311

312 const char *LineStart = Loc.getPointer();

314 while (LineStart != BufStart && LineStart[-1] != '\n' &&

315 LineStart[-1] != '\r')

316 --LineStart;

317

318

319 const char *LineEnd = Loc.getPointer();

321 while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')

322 ++LineEnd;

323 LineStr = StringRef(LineStart, LineEnd - LineStart);

324

325

326

327 for (SMRange R : Ranges) {

328 if (!R.isValid())

329 continue;

330

331

332 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)

333 continue;

334

335

336 if (R.Start.getPointer() < LineStart)

338 if (R.End.getPointer() > LineEnd)

340

341

342

343 ColRanges.push_back(std::make_pair(R.Start.getPointer() - LineStart,

344 R.End.getPointer() - LineStart));

345 }

346

348 }

349

350 return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,

351 LineAndCol.second - 1, Kind, Msg.str(), LineStr,

352 ColRanges, FixIts);

353}

354

356 bool ShowColors) const {

357

358 if (DiagHandler) {

359 DiagHandler(Diagnostic, DiagContext);

360 return;

361 }

362

365 assert(CurBuf && "Invalid or unspecified location!");

367 }

368

369 Diagnostic.print(nullptr, OS, ShowColors);

370}

371

375 bool ShowColors) const {

377}

378

384

385

386

387

388

390 : Range(R), Text(Replacement.str()) {

392}

393

394

395

396

397

401 ArrayRef<std::pair<unsigned, unsigned>> Ranges,

403 : SM(&sm), Loc(L), Filename(std::string(FN)), LineNo(Line), ColumnNo(Col),

404 Kind(Kind), Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),

405 FixIts(Hints) {

407}

408

409static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,

412 if (FixIts.empty())

413 return;

414

415 const char *LineStart = SourceLine.begin();

416 const char *LineEnd = SourceLine.end();

417

418 size_t PrevHintEndCol = 0;

419

421

422 if (Fixit.getText().find_first_of("\n\r\t") != StringRef::npos)

423 continue;

424

425 SMRange R = Fixit.getRange();

426

427

428 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)

429 continue;

430

431

432

433

434 unsigned FirstCol;

435 if (R.Start.getPointer() < LineStart)

436 FirstCol = 0;

437 else

438 FirstCol = R.Start.getPointer() - LineStart;

439

440

441

442

443

444

445

446

447 unsigned HintCol = FirstCol;

448 if (HintCol < PrevHintEndCol)

449 HintCol = PrevHintEndCol + 1;

450

451

452

453

455 Fixit.getText().size());

456

457

458 unsigned LastColumnModified = HintCol + Fixit.getText().size();

459 if (LastColumnModified > FixItLine.size())

460 FixItLine.resize(LastColumnModified, ' ');

461

462 llvm::copy(Fixit.getText(), FixItLine.begin() + HintCol);

463

464 PrevHintEndCol = LastColumnModified;

465

466

467

468 unsigned LastCol;

469 if (R.End.getPointer() >= LineEnd)

470 LastCol = LineEnd - LineStart;

471 else

472 LastCol = R.End.getPointer() - LineStart;

473

474 std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');

475 }

476}

477

479

480 for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {

481 size_t NextTab = LineContents.find('\t', i);

482

485 break;

486 }

487

488

489 S << LineContents.slice(i, NextTab);

490 OutCol += NextTab - i;

491 i = NextTab;

492

493

494 do {

495 S << ' ';

496 ++OutCol;

497 } while ((OutCol % TabStop) != 0);

498 }

499 S << '\n';

500}

501

502static bool isNonASCII(char c) { return c & 0x80; }

503

505 bool ShowKindLabel, bool ShowLocation) const {

507

508 {

510

511 if (ProgName && ProgName[0])

512 S << ProgName << ": ";

513

514 if (ShowLocation && !Filename.empty()) {

515 if (Filename == "-")

516 S << "";

517 else

518 S << Filename;

519

520 if (LineNo != -1) {

521 S << ':' << LineNo;

522 if (ColumnNo != -1)

523 S << ':' << (ColumnNo + 1);

524 }

525 S << ": ";

526 }

527 }

528

529 if (ShowKindLabel) {

530 switch (Kind) {

533 break;

536 break;

539 break;

542 break;

543 }

544 }

545

547

548 if (LineNo == -1 || ColumnNo == -1)

549 return;

550

551

552

553

554

555

558 return;

559 }

560 size_t NumColumns = LineContents.size();

561

562

563 std::string CaretLine(NumColumns + 1, ' ');

564

565

566 for (const std::pair<unsigned, unsigned> &R : Ranges)

567 std::fill(&CaretLine[R.first],

568 &CaretLine[std::min((size_t)R.second, CaretLine.size())], '~');

569

570

571

572 std::string FixItInsertionLine;

573 buildFixItLine(CaretLine, FixItInsertionLine, FixIts,

574 ArrayRef(Loc.getPointer() - ColumnNo, LineContents.size()));

575

576

577 if (unsigned(ColumnNo) <= NumColumns)

578 CaretLine[ColumnNo] = '^';

579 else

580 CaretLine[NumColumns] = '^';

581

582

583

584

585 CaretLine.erase(CaretLine.find_last_not_of(' ') + 1);

586

588

589 {

592

593

594 for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {

595 if (i >= LineContents.size() || LineContents[i] != '\t') {

596 S << CaretLine[i];

597 ++OutCol;

598 continue;

599 }

600

601

602 do {

603 S << CaretLine[i];

604 ++OutCol;

605 } while ((OutCol % TabStop) != 0);

606 }

607 S << '\n';

608 }

609

610

611 if (FixItInsertionLine.empty())

612 return;

613

614 for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {

615 if (i >= LineContents.size() || LineContents[i] != '\t') {

616 OS << FixItInsertionLine[i];

617 ++OutCol;

618 continue;

619 }

620

621

622 do {

623 OS << FixItInsertionLine[i];

624

625

626

627

628

629 if (FixItInsertionLine[i] != ' ')

630 ++i;

631 ++OutCol;

632 } while (((OutCol % TabStop) != 0) && i != e);

633 }

634 OS << '\n';

635}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Provides ErrorOr smart pointer.

This file defines the SmallString class.

This file defines the SmallVector class.

static const size_t TabStop

Definition SourceMgr.cpp:40

static bool isNonASCII(char c)

Definition SourceMgr.cpp:502

static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, ArrayRef< SMFixIt > FixIts, ArrayRef< char > SourceLine)

Definition SourceMgr.cpp:409

static void printSourceLine(raw_ostream &S, StringRef LineContents)

Definition SourceMgr.cpp:478

static std::vector< T > & GetOrCreateOffsetCache(void *&OffsetCache, MemoryBuffer *Buffer)

Definition SourceMgr.cpp:104

Defines the virtual file system interface vfs::FileSystem.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

bool empty() const

empty - Check if the array is empty.

Represents either an error or a value T.

A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...

This interface provides simple read-only access to a block of memory, and provides simple methods for...

virtual StringRef getBufferIdentifier() const

Return an identifier for this buffer, typically the filename it was read from.

size_t getBufferSize() const

StringRef getBuffer() const

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

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

const char * getBufferEnd() const

const char * getBufferStart() const

Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...

LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const

Definition SourceMgr.cpp:504

Represents a single fixit, a replacement of one range of text with another.

LLVM_ABI SMFixIt(SMRange R, const Twine &Replacement)

Definition SourceMgr.cpp:389

Represents a location in source code.

static SMLoc getFromPointer(const char *Ptr)

constexpr bool isValid() const

Represents a range in source code.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.

LLVM_ABI ErrorOr< std::unique_ptr< MemoryBuffer > > OpenIncludeFile(const std::string &Filename, std::string &IncludedFile)

Search for a file with the specified name in the current directory or in one of the IncludeDirs,...

Definition SourceMgr.cpp:70

SourceMgr & operator=(const SourceMgr &)=delete

LLVM_ABI std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const

Find the line and column number for the specified location in the specified file.

Definition SourceMgr.cpp:212

LLVM_ABI void setVirtualFileSystem(IntrusiveRefCntPtr< vfs::FileSystem > FS)

Definition SourceMgr.cpp:54

const MemoryBuffer * getMemoryBuffer(unsigned i) const

LLVM_ABI void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const

Emit a message about the specified location with the specified string.

Definition SourceMgr.cpp:372

LLVM_ABI void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const

Prints the names of included files and the line of the file they were included from.

Definition SourceMgr.cpp:281

LLVM_ABI SourceMgr()

Create new source manager without support for include files.

LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const

Return the ID of the buffer containing the specified location.

Definition SourceMgr.cpp:93

IntrusiveRefCntPtr< vfs::FileSystem > getVirtualFileSystem() const

Definition SourceMgr.cpp:50

LLVM_ABI SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}) const

Return an SMDiagnostic at the specified location with the specified string.

Definition SourceMgr.cpp:294

LLVM_ABI unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)

Search for a file with the specified name in the current directory or in one of the IncludeDirs.

Definition SourceMgr.cpp:58

unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const

Find the line number for the specified location in the specified file.

LLVM_ABI std::string getFormattedLocationNoOffset(SMLoc Loc, bool IncludePath=false) const

Get a string with the SMLoc filename and line number formatted in the standard style.

Definition SourceMgr.cpp:236

unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)

Add a new source buffer to this source manager.

LLVM_ABI SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo, unsigned ColNo)

Given a line and column number in a mapped buffer, turn it into an SMLoc.

Definition SourceMgr.cpp:254

const SrcBuffer & getBufferInfo(unsigned i) const

StringRef - Represent a constant reference to a string, i.e.

static constexpr size_t npos

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

StringRef slice(size_t Start, size_t End) const

Return a reference to the substring from [Start, End).

constexpr size_t size() const

size - Get the string size.

size_t find_last_of(char C, size_t From=npos) const

Find the last character in the string that is C, or npos if not found.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

LLVM_ABI std::string str() const

Return the twine contents as a std::string.

An RAII object that temporarily switches an output stream to a specific color.

static LLVM_ABI raw_ostream & warning()

Convenience method for printing "warning: " to stderr.

static LLVM_ABI raw_ostream & error()

Convenience method for printing "error: " to stderr.

static LLVM_ABI raw_ostream & note()

Convenience method for printing "note: " to stderr.

static LLVM_ABI raw_ostream & remark()

Convenience method for printing "remark: " to stderr.

This class implements an extremely fast bulk output stream that can only output to a stream.

static constexpr Colors GREEN

static constexpr Colors SAVEDCOLOR

Offsets

Offsets in bytes from the start of the input buffer.

LLVM_ABI int columnWidth(StringRef s)

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

This is an optimization pass for GlobalISel generic memory operations.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

auto lower_bound(R &&Range, T &&Value)

Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...

ArrayRef(const T &OneElt) -> ArrayRef< T >

OutputIt copy(R &&Range, OutputIt Out)

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

@ Auto

Determine whether to use color based on the command line argument and the raw_ostream.

Implement std::hash so that hash_code can be used in STL containers.