clang: lib/Frontend/TextDiagnostic.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

16#include "llvm/ADT/StringExtras.h"

17#include "llvm/Support/ConvertUTF.h"

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

19#include "llvm/Support/Locale.h"

20#include

21#include

22

23using namespace clang;

24

25static constexpr raw_ostream::Colors NoteColor = raw_ostream::CYAN;

26static constexpr raw_ostream::Colors RemarkColor = raw_ostream::BLUE;

27static constexpr raw_ostream::Colors FixitColor = raw_ostream::GREEN;

28static constexpr raw_ostream::Colors CaretColor = raw_ostream::GREEN;

29static constexpr raw_ostream::Colors WarningColor = raw_ostream::MAGENTA;

30static constexpr raw_ostream::Colors TemplateColor = raw_ostream::CYAN;

31static constexpr raw_ostream::Colors ErrorColor = raw_ostream::RED;

32static constexpr raw_ostream::Colors FatalColor = raw_ostream::RED;

33

34static constexpr raw_ostream::Colors SavedColor = raw_ostream::SAVEDCOLOR;

35

36

37

38

39

40static constexpr raw_ostream::Colors CommentColor = raw_ostream::YELLOW;

41static constexpr raw_ostream::Colors LiteralColor = raw_ostream::GREEN;

42static constexpr raw_ostream::Colors KeywordColor = raw_ostream::BLUE;

43

44namespace {

45template class ColumnsOrBytes {

46public:

47 int V = 0;

48 ColumnsOrBytes(int V) : V(V) {}

49 bool isValid() const { return V != -1; }

50 Sub next() const { return Sub(V + 1); }

51 Sub prev() const { return Sub(V - 1); }

52

53 bool operator>(Sub O) const { return V > O.V; }

54 bool operator<(Sub O) const { return V < O.V; }

55 bool operator<=(Sub B) const { return V <= B.V; }

57

58 Sub operator+(Sub B) const { return Sub(V + B.V); }

60 V += B.V;

61 return *static_cast<Sub *>(this);

62 }

63 Sub operator-(Sub B) const { return Sub(V - B.V); }

64 Sub &operator-=(Sub B) {

65 V -= B.V;

66 return *static_cast<Sub *>(this);

67 }

68};

69

70class Bytes final : public ColumnsOrBytes {

71public:

72 Bytes(int V) : ColumnsOrBytes(V) {}

73};

74

75class Columns final : public ColumnsOrBytes {

76public:

77 Columns(int V) : ColumnsOrBytes(V) {}

78};

79}

80

81

83 bool &Normal, bool Bold) {

84 while (true) {

86 OS << Str.slice(0, Pos);

87 if (Pos == StringRef::npos)

88 break;

89

90 Str = Str.substr(Pos + 1);

93 else {

94 OS.resetColor();

95 if (Bold)

97 }

99 }

100}

101

102

104

107 while (0<i) {

108 if (SourceLine[--i]=='\t')

109 break;

111 }

113}

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134static std::pair<SmallString<16>, bool>

136 unsigned TabStop) {

137 assert(I && "I must not be null");

138 assert(*I < SourceLine.size() && "must point to a valid index");

139

140 if (SourceLine[*I] == '\t') {

142 "Invalid -ftabstop value");

144 unsigned NumSpaces = TabStop - (LineBytes % TabStop);

145 assert(0 < NumSpaces && NumSpaces <= TabStop

146 && "Invalid computation of space amt");

147 ++(*I);

148

150 ExpandedTab.assign(NumSpaces, ' ');

151 return std::make_pair(ExpandedTab, true);

152 }

153

154 const unsigned char *Begin = SourceLine.bytes_begin() + *I;

155

156

157 if (*Begin < 0x80 && llvm::sys::locale::isPrint(*Begin)) {

158 ++(*I);

159 return std::make_pair(SmallString<16>(Begin, Begin + 1), true);

160 }

161 unsigned CharSize = llvm::getNumBytesForUTF8(*Begin);

162 const unsigned char *End = Begin + CharSize;

163

164

165 if (End <= SourceLine.bytes_end() && llvm::isLegalUTF8Sequence(Begin, End)) {

166 llvm::UTF32 C;

167 llvm::UTF32 *CPtr = &C;

168

169

170 unsigned char const *OriginalBegin = Begin;

171 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(

172 &Begin, End, &CPtr, CPtr + 1, llvm::strictConversion);

173 (void)Res;

174 assert(Res == llvm::conversionOK);

175 assert(OriginalBegin < Begin);

176 assert(unsigned(Begin - OriginalBegin) == CharSize);

177

178 (*I) += (Begin - OriginalBegin);

179

180

181 if (llvm::sys::locale::isPrint(C))

182 return std::make_pair(SmallString<16>(OriginalBegin, End), true);

183

184

186 while (C) {

187 Str.insert(Str.begin() + 3, llvm::hexdigit(C % 16));

188 C /= 16;

189 }

190 while (Str.size() < 8)

191 Str.insert(Str.begin() + 3, llvm::hexdigit(0));

192 return std::make_pair(Str, false);

193 }

194

195

197 unsigned char Byte = SourceLine[*I];

198 ExpandedByte[1] = llvm::hexdigit(Byte / 16);

199 ExpandedByte[2] = llvm::hexdigit(Byte % 16);

200 ++(*I);

201 return std::make_pair(ExpandedByte, false);

202}

203

204static void expandTabs(std::string &SourceLine, unsigned TabStop) {

205 size_t I = SourceLine.size();

206 while (I > 0) {

207 I--;

208 if (SourceLine[I] != '\t')

209 continue;

210 size_t TmpI = I;

211 auto [Str, Printable] =

213 SourceLine.replace(I, 1, Str.c_str());

214 }

215}

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

256 assert(BytesOut.empty());

257 assert(ColumnsOut.empty());

258

259 if (SourceLine.empty()) {

260 BytesOut.resize(1u, Bytes(0));

261 ColumnsOut.resize(1u, Columns(0));

262 return;

263 }

264

265 ColumnsOut.resize(SourceLine.size() + 1, -1);

266

267 Columns NumColumns = 0;

268 size_t I = 0;

269 while (I < SourceLine.size()) {

270 ColumnsOut[I] = NumColumns;

271 BytesOut.resize(NumColumns.V + 1, -1);

272 BytesOut.back() = Bytes(I);

273 auto [Str, Printable] =

275 NumColumns += Columns(llvm::sys::locale::columnWidth(Str));

276 }

277

278 ColumnsOut.back() = NumColumns;

279 BytesOut.resize(NumColumns.V + 1, -1);

280 BytesOut.back() = Bytes(I);

281}

282

283namespace {

284struct SourceColumnMap {

285 SourceColumnMap(StringRef SourceLine, unsigned TabStop)

286 : SourceLine(SourceLine) {

287

289

290 assert(ByteToColumn.size() == SourceLine.size() + 1);

291 assert(0 < ByteToColumn.size() && 0 < ColumnToByte.size());

292 assert(ByteToColumn.size() ==

293 static_cast<unsigned>(ColumnToByte.back().V + 1));

294 assert(static_cast<unsigned>(ByteToColumn.back().V + 1) ==

295 ColumnToByte.size());

296 }

297 Columns columns() const { return ByteToColumn.back(); }

298 Bytes bytes() const { return ColumnToByte.back(); }

299

300

301

302 Columns byteToColumn(Bytes N) const {

303 assert(0 <= N.V && N.V < static_cast<int>(ByteToColumn.size()));

304 return ByteToColumn[N.V];

305 }

306

307

308 Columns byteToContainingColumn(Bytes N) const {

309 assert(0 <= N.V && N.V < static_cast<int>(ByteToColumn.size()));

310 while (!ByteToColumn[N.V].isValid())

311 --N.V;

312 return ByteToColumn[N.V];

313 }

314

315

316

317

318 Bytes columnToByte(Columns N) const {

319 assert(0 <= N.V && N.V < static_cast<int>(ColumnToByte.size()));

320 return ColumnToByte[N.V];

321 }

322

323

324 Bytes startOfNextColumn(Bytes N) const {

325 assert(0 <= N.V && N.V < static_cast<int>(ByteToColumn.size() - 1));

326 N = N.next();

327 while (!byteToColumn(N).isValid())

328 N = N.next();

329 return N;

330 }

331

332

333 Bytes startOfPreviousColumn(Bytes N) const {

334 assert(0 < N.V && N.V < static_cast<int>(ByteToColumn.size()));

335 N = N.prev();

336 while (!byteToColumn(N).isValid())

337 N = N.prev();

338 return N;

339 }

340

341 StringRef getSourceLine() const { return SourceLine; }

342

343private:

344 StringRef SourceLine;

345 SmallVector<Columns, 200> ByteToColumn;

346 SmallVector<Bytes, 200> ColumnToByte;

347};

348}

349

350

351

353 std::string &SourceLine, std::string &CaretLine,

354 std::string &FixItInsertionLine, Columns NonGutterColumns,

355 const SourceColumnMap &Map,

357 Columns CaretColumns = CaretLine.size();

358 Columns FixItColumns = llvm::sys::locale::columnWidth(FixItInsertionLine);

359 Columns MaxColumns =

360 std::max({Map.columns().V, CaretColumns.V, FixItColumns.V});

361

362 if (MaxColumns <= NonGutterColumns)

363 return;

364

365

366 assert(llvm::none_of(CaretLine, [](char c) { return c < ' ' || '~' < c; }));

367

368

369

370 Columns CaretStart = 0, CaretEnd = CaretLine.size();

371 while (CaretStart != CaretEnd && isWhitespace(CaretLine[CaretStart.V]))

372 CaretStart = CaretStart.next();

373

374 while (CaretEnd != CaretStart && isWhitespace(CaretLine[CaretEnd.V]))

375 CaretEnd = CaretEnd.prev();

376

377

378

379

380

381

382 if (!FixItInsertionLine.empty()) {

383

384

385

386 Bytes FixItStart = 0;

387 Bytes FixItEnd = Bytes(FixItInsertionLine.size());

388 while (FixItStart != FixItEnd &&

389 isWhitespace(FixItInsertionLine[FixItStart.V]))

390 FixItStart = FixItStart.next();

391

392 while (FixItEnd != FixItStart &&

393 isWhitespace(FixItInsertionLine[FixItEnd.V - 1]))

394 FixItEnd = FixItEnd.prev();

395

396 Columns FixItStartCol = Columns(FixItStart.V);

397 Columns FixItEndCol = Columns(llvm::sys::locale::columnWidth(

398 FixItInsertionLine.substr(0, FixItEnd.V)));

399

400 CaretStart = std::min(FixItStartCol.V, CaretStart.V);

401 CaretEnd = std::max(FixItEndCol.V, CaretEnd.V);

402 }

403

404

405

406

407 while (CaretEnd < Map.columns() && !Map.columnToByte(CaretEnd).isValid())

408 CaretEnd = CaretEnd.next();

409

410 assert(

411 (CaretStart > Map.columns() || Map.columnToByte(CaretStart).isValid()) &&

412 "CaretStart must not point to a column in the middle of a source"

413 " line character");

414 assert((CaretEnd > Map.columns() || Map.columnToByte(CaretEnd).isValid()) &&

415 "CaretEnd must not point to a column in the middle of a source line"

416 " character");

417

418

419

420

421

422

423 Bytes SourceStart = Map.columnToByte(std::min(CaretStart.V, Map.columns().V));

424 Bytes SourceEnd = Map.columnToByte(std::min(CaretEnd.V, Map.columns().V));

425

426 Columns CaretColumnsOutsideSource =

427 CaretEnd - CaretStart -

428 (Map.byteToColumn(SourceEnd) - Map.byteToColumn(SourceStart));

429

430 constexpr StringRef FrontEllipse = " ...";

431 constexpr StringRef FrontSpace = " ";

432 constexpr StringRef BackEllipse = "...";

433 Columns EllipsesColumns = Columns(FrontEllipse.size() + BackEllipse.size());

434

435 Columns TargetColumns = NonGutterColumns;

436

437

438 if (TargetColumns > EllipsesColumns + CaretColumnsOutsideSource)

439 TargetColumns -= EllipsesColumns + CaretColumnsOutsideSource;

440

441 while (SourceStart > 0 || SourceEnd < SourceLine.size()) {

442 bool ExpandedRegion = false;

443

444 if (SourceStart > 0) {

445 Bytes NewStart = Map.startOfPreviousColumn(SourceStart);

446

447

448

449

450 while (NewStart > 0 && isWhitespace(SourceLine[NewStart.V]))

451 NewStart = Map.startOfPreviousColumn(NewStart);

452

453

454 while (NewStart > 0) {

455 Bytes Prev = Map.startOfPreviousColumn(NewStart);

457 break;

458 NewStart = Prev;

459 }

460

461 assert(Map.byteToColumn(NewStart).isValid());

462 Columns NewColumns =

463 Map.byteToColumn(SourceEnd) - Map.byteToColumn(NewStart);

464 if (NewColumns <= TargetColumns) {

465 SourceStart = NewStart;

466 ExpandedRegion = true;

467 }

468 }

469

470 if (SourceEnd < SourceLine.size()) {

471 Bytes NewEnd = Map.startOfNextColumn(SourceEnd);

472

473

474

475

476 while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd.V]))

477 NewEnd = Map.startOfNextColumn(NewEnd);

478

479

480 while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd.V]))

481 NewEnd = Map.startOfNextColumn(NewEnd);

482

483 assert(Map.byteToColumn(NewEnd).isValid());

484 Columns NewColumns =

485 Map.byteToColumn(NewEnd) - Map.byteToColumn(SourceStart);

486 if (NewColumns <= TargetColumns) {

487 SourceEnd = NewEnd;

488 ExpandedRegion = true;

489 }

490 }

491

492 if (!ExpandedRegion)

493 break;

494 }

495

496 CaretStart = Map.byteToColumn(SourceStart);

497 CaretEnd = Map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;

498

499

500

501 assert(CaretStart.isValid() && CaretEnd.isValid() && SourceStart.isValid() &&

502 SourceEnd.isValid());

503 assert(SourceStart <= SourceEnd);

504 assert(CaretStart <= CaretEnd);

505

506 Columns BackColumnsRemoved =

507 Map.byteToColumn(Bytes{static_cast<int>(SourceLine.size())}) -

508 Map.byteToColumn(SourceEnd);

509 Columns FrontColumnsRemoved = CaretStart;

510 Columns ColumnsKept = CaretEnd - CaretStart;

511

512

513 assert(FrontColumnsRemoved + ColumnsKept + BackColumnsRemoved >

514 NonGutterColumns);

515

516

517

518

519

520

521

522

523

524 Bytes BytesRemoved =

525 FrontColumnsRemoved > FrontEllipse.size()

526 ? (Map.columnToByte(FrontColumnsRemoved) - Bytes(FrontEllipse.size()))

527 : 0;

528 Bytes CodeEnd =

529 CaretEnd < Map.columns() ? Map.columnToByte(CaretEnd.V) : CaretEnd.V;

531

532 if (R.Start >= static_cast<unsigned>(CodeEnd.V) ||

533 R.End < static_cast<unsigned>(BytesRemoved.V)) {

534 R.Start = R.End = std::numeric_limits::max();

535 continue;

536 }

537

538

539 R.Start -= BytesRemoved.V;

540 R.End -= BytesRemoved.V;

541

542

543 if (R.Start < static_cast<unsigned>(CodeEnd.V) &&

544 R.End > static_cast<unsigned>(CodeEnd.V))

545 R.End = CodeEnd.V + 1;

546 }

547

548

549

550 if (BackColumnsRemoved > Columns(BackEllipse.size()))

551 SourceLine.replace(SourceEnd.V, std:🧵:npos, BackEllipse);

552

553

554 if (FrontColumnsRemoved + ColumnsKept <= NonGutterColumns)

555 return;

556

557

558 if (FrontColumnsRemoved > Columns(FrontEllipse.size())) {

559 SourceLine.replace(0, SourceStart.V, FrontEllipse);

560 CaretLine.replace(0, CaretStart.V, FrontSpace);

561 if (!FixItInsertionLine.empty())

562 FixItInsertionLine.replace(0, CaretStart.V, FrontSpace);

563 }

564}

565

566

567

568

569

570

571

572static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {

573 while (Idx < Length && isWhitespace(Str[Idx]))

574 ++Idx;

575 return Idx;

576}

577

578

579

580

581

582

583

585 switch (c) {

586 case '\'': return '\'';

587 case '`': return '\'';

588 case '"': return '"';

589 case '(': return ')';

590 case '[': return ']';

591 case '{': return '}';

592 default: break;

593 }

594

595 return 0;

596}

597

598

599

600

601

602

604 unsigned Length, unsigned Column,

605 unsigned Columns) {

606 assert(Start < Str.size() && "Invalid start position!");

607 unsigned End = Start + 1;

608

609

610 if (End == Str.size())

611 return End;

612

613

614

616 if (!EndPunct) {

617

618 while (End < Length && isWhitespace(Str[End]))

619 ++End;

620 return End;

621 }

622

623

624

626 PunctuationEndStack.push_back(EndPunct);

627 while (End < Length && !PunctuationEndStack.empty()) {

628 if (Str[End] == PunctuationEndStack.back())

629 PunctuationEndStack.pop_back();

631 PunctuationEndStack.push_back(SubEndPunct);

632

633 ++End;

634 }

635

636

637 while (End < Length && isWhitespace(Str[End]))

638 ++End;

639

640 unsigned PunctWordLength = End - Start;

641 if (

642 Column + PunctWordLength <= Columns ||

643

644

645 PunctWordLength < Columns/3)

646 return End;

647

648

649

650

651

653}

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668static bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns,

669 unsigned Column, bool Bold) {

670 const unsigned Length = std::min(Str.find('\n'), Str.size());

671 bool TextNormal = true;

672

673 bool Wrapped = false;

674 for (unsigned WordStart = 0, WordEnd; WordStart < Length;

675 WordStart = WordEnd) {

676

678 if (WordStart == Length)

679 break;

680

681

683

684

685 unsigned WordLength = WordEnd - WordStart;

686 if (Column + WordLength < Columns) {

687

688 if (WordStart) {

689 OS << ' ';

691 }

693 TextNormal, Bold);

694 Column += WordLength;

695 continue;

696 }

697

698

699

700 OS << '\n';

703 TextNormal, Bold);

705 Wrapped = true;

706 }

707

708

710

711 assert(TextNormal && "Text highlighted at end of diagnostic message.");

712

713 return Wrapped;

714}

715

720

722

727 uint64_t StartOfLocationInfo = OS.getColumn();

728

729

732

734 OS.resetColor();

735

740 Message, OS.getColumn() - StartOfLocationInfo,

742

743

744 OS.flush();

745}

746

747 void

750 bool ShowColors) {

751 if (ShowColors) {

752

753 switch (Level) {

755 llvm_unreachable("Invalid diagnostic type");

758 break;

761 break;

764 break;

767 break;

770 break;

771 }

772 }

773

774 switch (Level) {

776 llvm_unreachable("Invalid diagnostic type");

782 }

783

784 if (ShowColors)

785 OS.resetColor();

786}

787

788

790 bool IsSupplemental,

791 StringRef Message,

792 unsigned CurrentColumn,

793 unsigned Columns, bool ShowColors) {

794 bool Bold = false;

795 if (ShowColors && !IsSupplemental) {

796

797

799 Bold = true;

800 }

801

802 if (Columns)

804 else {

807 assert(Normal && "Formatting should have returned to normal");

808 }

809

810 if (ShowColors)

811 OS.resetColor();

812 OS << '\n';

813}

814

815void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {

816#ifdef _WIN32

818#endif

820 auto File = SM.getFileManager().getOptionalFileRef(Filename);

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836#ifdef _WIN32

837 TmpFilename = File->getName();

838 llvm::sys::fs::make_absolute(TmpFilename);

839 llvm::sys::path::native(TmpFilename);

840 llvm::sys::path::remove_dots(TmpFilename, true);

841 Filename = StringRef(TmpFilename.data(), TmpFilename.size());

842#else

843 Filename = SM.getFileManager().getCanonicalName(*File);

844#endif

845 }

846 }

847

848 OS << Filename;

849}

850

851

852

853

854

855

856

861

864 emitFilename(FE->getName(), Loc.getManager());

865 OS << ": ";

866 }

867 }

868 return;

869 }

870 unsigned LineNo = PLoc.getLine();

871

873 return;

874

877

879 switch (DiagOpts.getFormat()) {

883 OS << ':' << LineNo;

884 break;

887 }

888

890

891 if (unsigned ColNo = PLoc.getColumn()) {

893 OS << ',';

894

895 if (LangOpts.MSCompatibilityVersion &&

897 ColNo--;

898 } else

899 OS << ':';

900 OS << ColNo;

901 }

902 switch (DiagOpts.getFormat()) {

907

908

909 OS << ')';

910 if (LangOpts.MSCompatibilityVersion &&

912 OS << ' ';

913 OS << ':';

914 break;

915 }

916

917 if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {

919 bool PrintedRange = false;

921

922 for (const auto &R : Ranges) {

923

924 if (!R.isValid())

925 continue;

926

930

931

932

933 if (SM.getFileID(B) != CaretFileID || SM.getFileID(E) != CaretFileID)

934 continue;

935

936

937

938 unsigned TokSize = 0;

941

943 OS << '{'

944 << BF.getLineNumber() << ':' << BF.getColumnNumber() << '-'

946 << '}';

947 PrintedRange = true;

948 }

949

950 if (PrintedRange)

951 OS << ':';

952 }

953 OS << ' ';

954}

955

958 OS << "In file included from ";

960 OS << ':' << PLoc.getLine() << ":\n";

961 } else

962 OS << "In included file:\n";

963}

964

966 StringRef ModuleName) {

968 OS << "In module '" << ModuleName << "' imported from "

970 else

971 OS << "In module '" << ModuleName << "':\n";

972}

973

976 StringRef ModuleName) {

978 OS << "While building module '" << ModuleName << "' imported from "

980 else

981 OS << "While building module '" << ModuleName << "':\n";

982}

983

984

985static std::optional<std::pair<unsigned, unsigned>>

989 return std::nullopt;

990

993 if (SM.getFileID(Begin) != FID || SM.getFileID(End) != FID)

994 return std::nullopt;

995

996 return std::make_pair(SM.getExpansionLineNumber(Begin),

997 SM.getExpansionLineNumber(End));

998}

999

1000

1001

1002static std::pair<unsigned, unsigned>

1003maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,

1004 unsigned MaxRange) {

1005

1006 unsigned Slack = MaxRange - (A.second - A.first + 1);

1007 if (Slack == 0)

1008 return A;

1009

1010

1011 unsigned Min = std::min(A.first, B.first);

1012 unsigned Max = std::max(A.second, B.second);

1013 if (Max - Min + 1 <= MaxRange)

1015

1016

1017

1018 if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||

1019 (B.second < A.second && A.second - B.second + 1 > MaxRange))

1020 return A;

1021

1022

1023

1024

1025

1026

1027

1028 A.second = std::min(A.second + (Slack + 1) / 2, Max);

1029 Slack = MaxRange - (A.second - A.first + 1);

1030 A.first = std::max(Min + Slack, A.first) - Slack;

1031 A.second = std::min(A.first + MaxRange - 1, Max);

1032 return A;

1033}

1034

1040

1041

1043 std::string &CaretLine) {

1044

1046 while (StartByte < Map.bytes() && (Map.getSourceLine()[StartByte.V] == ' ' ||

1047 Map.getSourceLine()[StartByte.V] == '\t'))

1048 StartByte = Map.startOfNextColumn(StartByte);

1049

1050

1051 Bytes EndByte = std::min(R.EndByte.V, Map.bytes().V);

1052 while (EndByte.V != 0 && (Map.getSourceLine()[EndByte.V - 1] == ' ' ||

1053 Map.getSourceLine()[EndByte.V - 1] == '\t'))

1054 EndByte = Map.startOfPreviousColumn(EndByte);

1055

1056

1057

1058

1059 if (StartByte > EndByte)

1060 return;

1061

1062 assert(StartByte <= EndByte && "Invalid range!");

1063

1064 Columns StartCol = Map.byteToContainingColumn(StartByte);

1065 Columns EndCol = Map.byteToContainingColumn(EndByte);

1066

1067 if (CaretLine.size() < static_cast<size_t>(EndCol.V))

1068 CaretLine.resize(EndCol.V, ' ');

1069

1070 std::fill(CaretLine.begin() + StartCol.V, CaretLine.begin() + EndCol.V, '~');

1071}

1072

1074 const SourceColumnMap &map,

1078 std::string FixItInsertionLine;

1079 if (Hints.empty() || !DiagOpts.ShowFixits)

1080 return FixItInsertionLine;

1081 Columns PrevHintEndCol = 0;

1082

1083 for (const auto &H : Hints) {

1084 if (H.CodeToInsert.empty())

1085 continue;

1086

1087

1088

1090 SM.getDecomposedExpansionLoc(H.RemoveRange.getBegin());

1091 if (FID == HintLocInfo.first &&

1092 LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&

1093 StringRef(H.CodeToInsert).find_first_of("\n\r") == StringRef::npos) {

1094

1095

1096

1097

1098

1099 Bytes HintByteOffset =

1100 Bytes(SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second))

1101 .prev();

1102

1103

1104 assert(HintByteOffset < map.bytes().next());

1105 Columns HintCol = map.byteToContainingColumn(HintByteOffset);

1106

1107

1108

1109

1110

1111

1112

1113

1114 if (HintCol < PrevHintEndCol)

1115 HintCol = PrevHintEndCol + 1;

1116

1117

1118

1119 Columns NewFixItLineSize = Columns(FixItInsertionLine.size()) +

1120 (HintCol - PrevHintEndCol) +

1121 Columns(H.CodeToInsert.size());

1122 if (NewFixItLineSize > FixItInsertionLine.size())

1123 FixItInsertionLine.resize(NewFixItLineSize.V, ' ');

1124

1125 std::copy(H.CodeToInsert.begin(), H.CodeToInsert.end(),

1126 FixItInsertionLine.end() - H.CodeToInsert.size());

1127

1128 PrevHintEndCol = HintCol + llvm::sys::locale::columnWidth(H.CodeToInsert);

1129 }

1130 }

1131

1132 expandTabs(FixItInsertionLine, DiagOpts.TabStop);

1133

1134 return FixItInsertionLine;

1135}

1136

1138 unsigned L = 1u, M = 10u;

1139 while (M <= N && ++L != std::numeric_limits::digits10 + 1)

1140 M *= 10u;

1141

1142 return L;

1143}

1144

1145

1146

1147

1148

1149

1153 const std::pair<unsigned, unsigned> &Lines, FileID FID,

1156

1158 if (R.isInvalid())

1159 continue;

1162

1163 unsigned StartLineNo = SM.getExpansionLineNumber(Begin);

1164 if (StartLineNo > Lines.second || SM.getFileID(Begin) != FID)

1165 continue;

1166

1167 unsigned EndLineNo = SM.getExpansionLineNumber(End);

1168 if (EndLineNo < Lines.first || SM.getFileID(End) != FID)

1169 continue;

1170

1171 Bytes StartByte = SM.getExpansionColumnNumber(Begin);

1172 Bytes EndByte = SM.getExpansionColumnNumber(End);

1173 assert(StartByte.V != 0 && "StartByte must be valid, 0 is invalid");

1174 assert(EndByte.V != 0 && "EndByte must be valid, 0 is invalid");

1175 if (R.isTokenRange())

1177

1178

1179 if (StartLineNo == EndLineNo) {

1180 LineRanges.push_back({StartLineNo, StartByte.prev(), EndByte.prev()});

1181 continue;

1182 }

1183

1184

1185 LineRanges.push_back(

1186 {StartLineNo, StartByte.prev(), std::numeric_limits::max()});

1187

1188

1189 for (unsigned S = StartLineNo + 1; S != EndLineNo; ++S)

1190 LineRanges.push_back({S, 0, std::numeric_limits::max()});

1191

1192

1193 LineRanges.push_back({EndLineNo, 0, EndByte.prev()});

1194 }

1195

1196 return LineRanges;

1197}

1198

1199

1200

1201

1202

1203

1204

1205

1206static std::unique_ptr<llvm::SmallVectorTextDiagnostic::StyleRange[]>

1208 unsigned EndLineNumber, const Preprocessor *PP,

1211 assert(StartLineNumber <= EndLineNumber);

1212 auto SnippetRanges =

1213 std::make_unique<SmallVectorTextDiagnostic::StyleRange[]>(

1214 EndLineNumber - StartLineNumber + 1);

1215

1216 if (!PP || !ShowColors)

1217 return SnippetRanges;

1218

1219

1221 return SnippetRanges;

1222

1223 auto Buff = llvm::MemoryBuffer::getMemBuffer(FileData);

1224 Lexer L{FID, *Buff, SM, LangOpts};

1226

1227 const char *FirstLineStart =

1228 FileData.data() +

1229 SM.getDecomposedLoc(SM.translateLineCol(FID, StartLineNumber, 1)).second;

1230 if (const char *CheckPoint = PP->getCheckPoint(FID, FirstLineStart)) {

1231 assert(CheckPoint >= Buff->getBufferStart() &&

1232 CheckPoint <= Buff->getBufferEnd());

1233 assert(CheckPoint <= FirstLineStart);

1234 size_t Offset = CheckPoint - Buff->getBufferStart();

1235 L.seek(Offset, false);

1236 }

1237

1238

1239 auto appendStyle =

1241 const Token &T, unsigned Start, unsigned Length) -> void {

1242 if (T.is(tok::raw_identifier)) {

1243 StringRef RawIdent = T.getRawIdentifier();

1244

1245

1246

1247

1248 if (llvm::StringSwitch(RawIdent)

1249 .Case("true", true)

1250 .Case("false", true)

1251 .Case("nullptr", true)

1252 .Case("__func__", true)

1253 .Case("__objc_yes__", true)

1254 .Case("__objc_no__", true)

1255 .Case("__null", true)

1256 .Case("__FUNCDNAME__", true)

1257 .Case("__FUNCSIG__", true)

1258 .Case("__FUNCTION__", true)

1259 .Case("__FUNCSIG__", true)

1261 Vec.emplace_back(Start, Start + Length, LiteralColor);

1262 } else {

1264 assert(II);

1266 Vec.emplace_back(Start, Start + Length, KeywordColor);

1267 }

1269 Vec.emplace_back(Start, Start + Length, LiteralColor);

1270 } else {

1271 assert(T.is(tok::comment));

1272 Vec.emplace_back(Start, Start + Length, CommentColor);

1273 }

1274 };

1275

1276 bool Stop = false;

1277 while (!Stop) {

1280 if (T.is(tok::unknown))

1281 continue;

1282

1283

1284 if (T.is(tok::raw_identifier) && T.is(tok::comment) &&

1286 continue;

1287

1289 unsigned TokenEndLine = SM.getSpellingLineNumber(T.getEndLoc(), &Invalid);

1290 if (Invalid || TokenEndLine < StartLineNumber)

1291 continue;

1292

1293 assert(TokenEndLine >= StartLineNumber);

1294

1295 unsigned TokenStartLine =

1296 SM.getSpellingLineNumber(T.getLocation(), &Invalid);

1298 continue;

1299

1300 if (TokenStartLine > EndLineNumber)

1301 break;

1302

1303 Bytes StartCol = SM.getSpellingColumnNumber(T.getLocation(), &Invalid) - 1;

1305 continue;

1306

1307

1308 if (TokenStartLine == TokenEndLine) {

1310 SnippetRanges[TokenStartLine - StartLineNumber];

1311 appendStyle(LineRanges, T, StartCol.V, T.getLength());

1312 continue;

1313 }

1314 assert((TokenEndLine - TokenStartLine) >= 1);

1315

1316

1317

1318 Bytes EndCol = SM.getSpellingColumnNumber(T.getEndLoc(), &Invalid) - 1;

1320 continue;

1321

1323

1324 unsigned L = TokenStartLine;

1325 unsigned LineLength = 0;

1326 for (unsigned I = 0; I <= Spelling.size(); ++I) {

1327

1329 if (L >= StartLineNumber) {

1331 SnippetRanges[L - StartLineNumber];

1332

1333 if (L == TokenStartLine)

1334 appendStyle(LineRanges, T, StartCol.V, LineLength);

1335 else if (L == TokenEndLine)

1336 appendStyle(LineRanges, T, 0, EndCol.V);

1337 else

1338 appendStyle(LineRanges, T, 0, LineLength);

1339 }

1340

1341 ++L;

1342 if (L > EndLineNumber)

1343 break;

1344 LineLength = 0;

1345 continue;

1346 }

1347 ++LineLength;

1348 }

1349 }

1350

1351 return SnippetRanges;

1352}

1353

1354

1355

1356

1357

1358

1359

1360

1361void TextDiagnostic::emitSnippetAndCaret(

1364 assert(Loc.isValid() && "must have a valid source location here");

1365 assert(Loc.isFileID() && "must have a file location here");

1366

1367

1368

1369

1370

1371

1372

1374 return;

1375 if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&

1377 return;

1378

1381

1382

1386 return;

1387 const char *BufStart = BufData.data();

1388 const char *BufEnd = BufStart + BufData.size();

1389

1392

1393

1394 static const size_t MaxLineLengthToPrint = 4096;

1395 if (CaretByte > MaxLineLengthToPrint)

1396 return;

1397

1398

1399 const unsigned MaxLines = DiagOpts.SnippetLineLimit;

1400 std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};

1402 for (const auto &I : Ranges) {

1404 Lines = maybeAddRange(Lines, *OptionalRange, MaxLines);

1405

1406 DisplayLineNo =

1407 std::min(DisplayLineNo, SM.getPresumedLineNumber(I.getBegin()));

1408 }

1409

1410

1411

1412

1413

1414 unsigned MaxLineNoDisplayWidth =

1417 : 0;

1418 auto indentForLineNumbers = [&] {

1419 if (MaxLineNoDisplayWidth > 0)

1420 OS.indent(MaxLineNoDisplayWidth + 2) << "| ";

1421 };

1422

1423 Columns MessageLength = DiagOpts.MessageLength;

1424

1425 if (MessageLength != 0 && MessageLength <= Columns(MaxLineNoDisplayWidth + 4))

1426 return;

1427

1428

1429

1430 std::unique_ptr<SmallVector[]> SourceStyles =

1433

1434 SmallVector LineRanges =

1436

1437 for (unsigned LineNo = Lines.first; LineNo != Lines.second + 1;

1438 ++LineNo, ++DisplayLineNo) {

1439

1440 const char *LineStart =

1441 BufStart +

1442 SM.getDecomposedLoc(SM.translateLineCol(FID, LineNo, 1)).second;

1443 if (LineStart == BufEnd)

1444 break;

1445

1446

1447 const char *LineEnd = LineStart;

1448 while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd)

1449 ++LineEnd;

1450

1451

1452

1453 if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint)

1454 return;

1455

1456

1457 std::string SourceLine(LineStart, LineEnd);

1458

1459 while (!SourceLine.empty() && SourceLine.back() == '\0' &&

1460 (LineNo != CaretLineNo ||

1461 SourceLine.size() > static_cast<size_t>(CaretByte.V)))

1462 SourceLine.pop_back();

1463

1464

1465 const SourceColumnMap SourceColMap(SourceLine, DiagOpts.TabStop);

1466

1467 std::string CaretLine;

1468

1469 for (const auto &LR : LineRanges) {

1470 if (LR.LineNo == LineNo)

1472 }

1473

1474

1475 if (CaretLineNo == LineNo) {

1476 Columns Col = SourceColMap.byteToContainingColumn(CaretByte.prev());

1477 CaretLine.resize(

1478 std::max(static_cast<size_t>(Col.V) + 1, CaretLine.size()), ' ');

1479 CaretLine[Col.V] = '^';

1480 }

1481

1482 std::string FixItInsertionLine =

1484

1485

1486

1487 if (MessageLength != 0) {

1488 Columns NonGutterColumns = MessageLength;

1489 if (MaxLineNoDisplayWidth != 0)

1490 NonGutterColumns -= Columns(MaxLineNoDisplayWidth + 4);

1492 NonGutterColumns, SourceColMap,

1493 SourceStyles[LineNo - Lines.first]);

1494 }

1495

1496

1497

1498

1499

1500 if (DiagOpts.ShowSourceRanges && !SourceLine.empty()) {

1501 SourceLine = ' ' + SourceLine;

1502 CaretLine = ' ' + CaretLine;

1503 }

1504

1505

1506 emitSnippet(SourceLine, MaxLineNoDisplayWidth, LineNo, DisplayLineNo,

1507 SourceStyles[LineNo - Lines.first]);

1508

1509 if (!CaretLine.empty()) {

1510 indentForLineNumbers();

1513 OS << CaretLine << '\n';

1515 OS.resetColor();

1516 }

1517

1518 if (!FixItInsertionLine.empty()) {

1519 indentForLineNumbers();

1521

1523 if (DiagOpts.ShowSourceRanges)

1524 OS << ' ';

1525 OS << FixItInsertionLine << '\n';

1527 OS.resetColor();

1528 }

1529 }

1530

1531

1532 emitParseableFixits(Hints, SM);

1533}

1534

1535void TextDiagnostic::emitSnippet(StringRef SourceLine,

1536 unsigned MaxLineNoDisplayWidth,

1537 unsigned LineNo, unsigned DisplayLineNo,

1539

1540 if (MaxLineNoDisplayWidth > 0) {

1542 OS.indent(MaxLineNoDisplayWidth - LineNoDisplayWidth + 1)

1543 << DisplayLineNo << " | ";

1544 }

1545

1546

1547 bool PrintReversed = false;

1548 std::optionalllvm::raw\_ostream::Colors CurrentColor;

1549 size_t I = 0;

1550 while (I < SourceLine.size()) {

1551 auto [Str, WasPrintable] =

1553

1554

1556 if (WasPrintable == PrintReversed) {

1557 PrintReversed = !PrintReversed;

1558 if (PrintReversed)

1559 OS.reverseColor();

1560 else {

1561 OS.resetColor();

1562 CurrentColor = std::nullopt;

1563 }

1564 }

1565

1566

1567 const auto *CharStyle = llvm::find_if(Styles, [I](const StyleRange &R) {

1568 return (R.Start < I && R.End >= I);

1569 });

1570

1571 if (CharStyle != Styles.end()) {

1572 if (!CurrentColor ||

1573 (CurrentColor && *CurrentColor != CharStyle->Color)) {

1574 OS.changeColor(CharStyle->Color);

1575 CurrentColor = CharStyle->Color;

1576 }

1577 } else if (CurrentColor) {

1578 OS.resetColor();

1579 CurrentColor = std::nullopt;

1580 }

1581 }

1582

1583 OS << Str;

1584 }

1585

1587 OS.resetColor();

1588

1589 OS << '\n';

1590}

1591

1594 if (DiagOpts.ShowParseableFixits)

1595 return;

1596

1597

1598

1599 for (const auto &H : Hints) {

1600 if (H.RemoveRange.isInvalid() || H.RemoveRange.getBegin().isMacroID() ||

1601 H.RemoveRange.getEnd().isMacroID())

1602 return;

1603 }

1604

1605 for (const auto &H : Hints) {

1606 SourceLocation BLoc = H.RemoveRange.getBegin();

1607 SourceLocation ELoc = H.RemoveRange.getEnd();

1608

1611

1612

1613 if (H.RemoveRange.isTokenRange())

1615

1616

1617

1618 PresumedLoc PLoc = SM.getPresumedLoc(BLoc);

1620 break;

1621

1622 OS << "fix-it:\"";

1624 OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)

1625 << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)

1626 << '-' << SM.getLineNumber(EInfo.first, EInfo.second)

1627 << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)

1628 << "}:\"";

1629 OS.write_escaped(H.CodeToInsert);

1630 OS << "\"\n";

1631 }

1632}

static StringRef bytes(const std::vector< T, Allocator > &v)

static size_t getNumDisplayWidth(size_t N)

Defines the clang::FileManager interface and associated types.

static SmallVectorImpl< char > & operator+=(SmallVectorImpl< char > &Includes, StringRef RHS)

Defines the clang::Preprocessor interface.

Defines the SourceManager interface.

static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i)

Definition TextDiagnostic.cpp:105

static constexpr raw_ostream::Colors SavedColor

Definition TextDiagnostic.cpp:34

static std::pair< unsigned, unsigned > maybeAddRange(std::pair< unsigned, unsigned > A, std::pair< unsigned, unsigned > B, unsigned MaxRange)

Add as much of range B into range A as possible without exceeding a maximum size of MaxRange.

Definition TextDiagnostic.cpp:1003

static void genColumnByteMapping(StringRef SourceLine, unsigned TabStop, SmallVectorImpl< Bytes > &BytesOut, SmallVectorImpl< Columns > &ColumnsOut)

BytesOut: A mapping from columns to the byte of the source line that produced the character displayin...

Definition TextDiagnostic.cpp:253

static void selectInterestingSourceRegion(std::string &SourceLine, std::string &CaretLine, std::string &FixItInsertionLine, Columns NonGutterColumns, const SourceColumnMap &Map, SmallVectorImpl< clang::TextDiagnostic::StyleRange > &Styles)

When the source code line we want to print is too long for the terminal, select the "interesting" reg...

Definition TextDiagnostic.cpp:352

static constexpr raw_ostream::Colors LiteralColor

Definition TextDiagnostic.cpp:41

static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, bool &Normal, bool Bold)

Add highlights to differences in template strings.

Definition TextDiagnostic.cpp:82

static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length)

Skip over whitespace in the string, starting at the given index.

Definition TextDiagnostic.cpp:572

static bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns, unsigned Column, bool Bold)

Print the given string to a stream, word-wrapping it to some number of columns in the process.

Definition TextDiagnostic.cpp:668

static unsigned findEndOfWord(unsigned Start, StringRef Str, unsigned Length, unsigned Column, unsigned Columns)

Find the end of the word starting at the given offset within a string.

Definition TextDiagnostic.cpp:603

static std::pair< SmallString< 16 >, bool > printableTextForNextCharacter(StringRef SourceLine, size_t *I, unsigned TabStop)

returns a printable representation of first item from input range

Definition TextDiagnostic.cpp:135

static constexpr raw_ostream::Colors TemplateColor

Definition TextDiagnostic.cpp:30

static constexpr raw_ostream::Colors ErrorColor

Definition TextDiagnostic.cpp:31

static std::unique_ptr< llvm::SmallVector< TextDiagnostic::StyleRange >[]> highlightLines(StringRef FileData, unsigned StartLineNumber, unsigned EndLineNumber, const Preprocessor *PP, const LangOptions &LangOpts, bool ShowColors, FileID FID, const SourceManager &SM)

Creates syntax highlighting information in form of StyleRanges.

Definition TextDiagnostic.cpp:1207

static constexpr raw_ostream::Colors FatalColor

Definition TextDiagnostic.cpp:32

static constexpr raw_ostream::Colors KeywordColor

Definition TextDiagnostic.cpp:42

static std::optional< std::pair< unsigned, unsigned > > findLinesForRange(const CharSourceRange &R, FileID FID, const SourceManager &SM)

Find the suitable set of lines to show to include a set of ranges.

Definition TextDiagnostic.cpp:986

static char findMatchingPunctuation(char c)

If the given character is the start of some kind of balanced punctuation (e.g., quotes or parentheses...

Definition TextDiagnostic.cpp:584

static constexpr raw_ostream::Colors CaretColor

Definition TextDiagnostic.cpp:28

static constexpr raw_ostream::Colors FixitColor

Definition TextDiagnostic.cpp:27

static void expandTabs(std::string &SourceLine, unsigned TabStop)

Definition TextDiagnostic.cpp:204

static constexpr raw_ostream::Colors WarningColor

Definition TextDiagnostic.cpp:29

static void highlightRange(const LineRange &R, const SourceColumnMap &Map, std::string &CaretLine)

Highlight R (with ~'s) on the current source line.

Definition TextDiagnostic.cpp:1042

const unsigned WordWrapIndentation

Number of spaces to indent when word-wrapping.

Definition TextDiagnostic.cpp:103

static std::string buildFixItInsertionLine(FileID FID, unsigned LineNo, const SourceColumnMap &map, ArrayRef< FixItHint > Hints, const SourceManager &SM, const DiagnosticOptions &DiagOpts)

Definition TextDiagnostic.cpp:1073

static constexpr raw_ostream::Colors RemarkColor

Definition TextDiagnostic.cpp:26

static constexpr raw_ostream::Colors NoteColor

Definition TextDiagnostic.cpp:25

static SmallVector< LineRange > prepareAndFilterRanges(const SmallVectorImpl< CharSourceRange > &Ranges, const SourceManager &SM, const std::pair< unsigned, unsigned > &Lines, FileID FID, const LangOptions &LangOpts)

Filter out invalid ranges, ranges that don't fit into the window of source lines we will print,...

Definition TextDiagnostic.cpp:1151

__device__ __2f16 float c

Represents a character-granular source range.

bool isTokenRange() const

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

SourceLocation getEnd() const

SourceLocation getBegin() const

Options for controlling the compiler diagnostics engine.

const LangOptions & LangOpts

SourceLocation LastLoc

The location of the previous diagnostic if known.

DiagnosticOptions & DiagOpts

DiagnosticsEngine::Level LastLevel

The level of the last diagnostic emitted.

DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions &DiagOpts)

Level

The level of the diagnostic, after it has been through mapping.

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

A SourceLocation and its associated SourceManager.

unsigned getColumnNumber(bool *Invalid=nullptr) const

FullSourceLoc getExpansionLoc() const

unsigned getLineNumber(bool *Invalid=nullptr) const

OptionalFileEntryRef getFileEntryRef() const

StringRef getBufferData(bool *Invalid=nullptr) const

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

PresumedLoc getPresumedLoc(bool UseLineDirectives=true) const

const SourceManager & getManager() const

One of these records is kept for each identifier that is lexed.

bool isKeyword(const LangOptions &LangOpts) const

Return true if this token is a keyword in the specified language.

IdentifierInfoLookup * getExternalIdentifierLookup() const

Retrieve the external identifier lookup object, if any.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.

void SetKeepWhitespaceMode(bool Val)

SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode.

bool LexFromRawLexer(Token &Result)

LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...

void seek(unsigned Offset, bool IsAtStartOfLine)

Set the lexer's buffer pointer to Offset.

static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid=nullptr)

getSpelling - This method is used to get the spelling of a token into a preallocated buffer,...

static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)

MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...

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

const char * getCheckPoint(FileID FID, const char *Start) const

Returns a pointer into the given file's buffer that's guaranteed to be between tokens.

IdentifierInfo * getIdentifierInfo(StringRef Name) const

Return information about the specified preprocessor identifier token.

IdentifierTable & getIdentifierTable()

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

unsigned getColumn() const

Return the presumed column number of this location.

const char * getFilename() const

Return the presumed filename of this location.

unsigned getLine() const

Return the presumed line number of this location.

bool isInvalid() const

Return true if this object is invalid or uninitialized.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

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

static void printDiagnosticMessage(raw_ostream &OS, bool IsSupplemental, StringRef Message, unsigned CurrentColumn, unsigned Columns, bool ShowColors)

Pretty-print a diagnostic message to a raw_ostream.

Definition TextDiagnostic.cpp:789

~TextDiagnostic() override

Definition TextDiagnostic.cpp:721

void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override

Definition TextDiagnostic.cpp:965

void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override

Definition TextDiagnostic.cpp:956

TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, DiagnosticOptions &DiagOpts, const Preprocessor *PP=nullptr)

Definition TextDiagnostic.cpp:716

static void printDiagnosticLevel(raw_ostream &OS, DiagnosticsEngine::Level Level, bool ShowColors)

Print the diagonstic level to a raw_ostream.

Definition TextDiagnostic.cpp:748

void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef< CharSourceRange > Ranges) override

Print out the file/line/column information and include trace.

Definition TextDiagnostic.cpp:857

void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, DiagOrStoredDiag D) override

Definition TextDiagnostic.cpp:723

void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override

Definition TextDiagnostic.cpp:974

Token - This structure provides full information about a lexed token.

bool isLiteral(TokenKind K)

Return true if this is a "literal" kind, like a numeric constant, string, etc.

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

static const TerminalColor CommentColor

LLVM_READONLY bool isVerticalWhitespace(unsigned char c)

Returns true if this character is vertical ASCII whitespace: '\n', '\r'.

CustomizableOptional< FileEntryRef > OptionalFileEntryRef

llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag

std::pair< FileID, unsigned > FileIDAndOffset

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

const FunctionProtoType * T

LLVM_READONLY bool isWhitespace(unsigned char c)

Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...

const char ToggleHighlight

Special character that the diagnostic printer will use to toggle the bold attribute.

bool operator!=(CanQual< T > x, CanQual< U > y)

bool operator<=(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

bool operator>(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

Bytes EndByte

Definition TextDiagnostic.cpp:1038

unsigned LineNo

Definition TextDiagnostic.cpp:1036

Bytes StartByte

Definition TextDiagnostic.cpp:1037