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 && (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 && (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 (.is(tok::raw_identifier) &&
.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 (.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