15#include "llvm/ADT/SmallString.h"
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 "llvm/Support/Path.h"
21#include "llvm/Support/raw_ostream.h"
39static const enum raw_ostream::Colors
errorColor = raw_ostream::RED;
40static const enum raw_ostream::Colors
fatalColor = raw_ostream::RED;
43 raw_ostream::SAVEDCOLOR;
50 OS << Str.slice(0, Pos);
51 if (Pos == StringRef::npos)
54 Str = Str.substr(Pos + 1);
72 if (SourceLine[--i]==
'\t')
98static std::pair<SmallString<16>,
bool>
101 assert(I &&
"I must not be null");
102 assert(*I < SourceLine.size() &&
"must point to a valid index");
104 if (SourceLine[*I] ==
'\t') {
106 "Invalid -ftabstop value");
108 unsigned NumSpaces = TabStop - (Col % TabStop);
109 assert(0 < NumSpaces && NumSpaces <= TabStop
110 &&
"Invalid computation of space amt");
114 ExpandedTab.assign(NumSpaces,
' ');
115 return std::make_pair(ExpandedTab,
true);
118 const unsigned char *
Begin = SourceLine.bytes_begin() + *I;
121 if (*
Begin < 0x80 && llvm::sys::locale::isPrint(*
Begin)) {
125 unsigned CharSize = llvm::getNumBytesForUTF8(*
Begin);
126 const unsigned char *End =
Begin + CharSize;
129 if (End <= SourceLine.bytes_end() && llvm::isLegalUTF8Sequence(
Begin, End)) {
131 llvm::UTF32 *CPtr = &
C;
134 unsigned char const *OriginalBegin =
Begin;
135 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
136 &
Begin, End, &CPtr, CPtr + 1, llvm::strictConversion);
138 assert(Res == llvm::conversionOK);
139 assert(OriginalBegin <
Begin);
140 assert((
Begin - OriginalBegin) == CharSize);
142 (*I) += (
Begin - OriginalBegin);
145 if (llvm::sys::locale::isPrint(
C))
151 Str.insert(Str.begin() + 3, llvm::hexdigit(
C % 16));
154 while (Str.size() < 8)
155 Str.insert(Str.begin() + 3, llvm::hexdigit(0));
156 return std::make_pair(Str,
false);
161 unsigned char Byte = SourceLine[*I];
162 ExpandedByte[1] = llvm::hexdigit(Byte / 16);
163 ExpandedByte[2] = llvm::hexdigit(Byte % 16);
165 return std::make_pair(ExpandedByte,
false);
168static void expandTabs(std::string &SourceLine,
unsigned TabStop) {
169 size_t I = SourceLine.size();
172 if (SourceLine[I] !=
'\t')
175 auto [Str, Printable] =
177 SourceLine.replace(I, 1, Str.c_str());
220 assert(BytesOut.empty());
221 assert(ColumnsOut.empty());
223 if (SourceLine.empty()) {
224 BytesOut.resize(1u, 0);
225 ColumnsOut.resize(1u, 0);
229 ColumnsOut.resize(SourceLine.size() + 1, -1);
233 while (I < SourceLine.size()) {
234 ColumnsOut[I] = Columns;
235 BytesOut.resize(Columns + 1, -1);
237 auto [Str, Printable] =
239 Columns += llvm::sys::locale::columnWidth(Str);
242 ColumnsOut.back() = Columns;
243 BytesOut.resize(Columns + 1, -1);
248struct SourceColumnMap {
249 SourceColumnMap(StringRef SourceLine,
unsigned TabStop)
250 : m_SourceLine(SourceLine) {
254 assert(m_byteToColumn.size()==SourceLine.size()+1);
255 assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
256 assert(m_byteToColumn.size()
257 ==
static_cast<unsigned>(m_columnToByte.back()+1));
258 assert(
static_cast<unsigned>(m_byteToColumn.back()+1)
259 == m_columnToByte.size());
261 int columns()
const {
return m_byteToColumn.back(); }
262 int bytes()
const {
return m_columnToByte.back(); }
266 int byteToColumn(
int n)
const {
267 assert(0<=n && n<
static_cast<int>(m_byteToColumn.size()));
268 return m_byteToColumn[n];
272 int byteToContainingColumn(
int N)
const {
273 assert(0 <= N && N <
static_cast<int>(m_byteToColumn.size()));
274 while (m_byteToColumn[N] == -1)
276 return m_byteToColumn[N];
282 int columnToByte(
int n)
const {
283 assert(0<=n && n<
static_cast<int>(m_columnToByte.size()));
284 return m_columnToByte[n];
288 int startOfNextColumn(
int N)
const {
289 assert(0 <= N && N <
static_cast<int>(m_byteToColumn.size() - 1));
290 while (byteToColumn(++N) == -1) {}
295 int startOfPreviousColumn(
int N)
const {
296 assert(0 < N && N <
static_cast<int>(m_byteToColumn.size()));
297 while (byteToColumn(--N) == -1) {}
301 StringRef getSourceLine()
const {
306 const std::string m_SourceLine;
315 std::string &CaretLine,
316 std::string &FixItInsertionLine,
318 const SourceColumnMap &map) {
319 unsigned CaretColumns = CaretLine.size();
320 unsigned FixItColumns = llvm::sys::locale::columnWidth(FixItInsertionLine);
321 unsigned MaxColumns = std::max(
static_cast<unsigned>(map.columns()),
322 std::max(CaretColumns, FixItColumns));
324 if (MaxColumns <= Columns)
328 assert(llvm::none_of(CaretLine, [](
char c) {
return c <
' ' ||
'~' <
c; }));
332 unsigned CaretStart = 0, CaretEnd = CaretLine.size();
333 for (; CaretStart != CaretEnd; ++CaretStart)
337 for (; CaretEnd != CaretStart; --CaretEnd)
346 if (!FixItInsertionLine.empty()) {
347 unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
348 for (; FixItStart != FixItEnd; ++FixItStart)
352 for (; FixItEnd != FixItStart; --FixItEnd)
359 unsigned FixItStartCol = FixItStart;
361 = llvm::sys::locale::columnWidth(FixItInsertionLine.substr(0, FixItEnd));
363 CaretStart = std::min(FixItStartCol, CaretStart);
364 CaretEnd = std::max(FixItEndCol, CaretEnd);
370 while (
static_cast<int>(CaretEnd) < map.columns() &&
371 -1 == map.columnToByte(CaretEnd))
374 assert((
static_cast<int>(CaretStart) > map.columns() ||
375 -1!=map.columnToByte(CaretStart)) &&
376 "CaretStart must not point to a column in the middle of a source"
378 assert((
static_cast<int>(CaretEnd) > map.columns() ||
379 -1!=map.columnToByte(CaretEnd)) &&
380 "CaretEnd must not point to a column in the middle of a source line"
388 unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
390 unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
393 unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
394 - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
396 char const *front_ellipse =
" ...";
397 char const *front_space =
" ";
398 char const *back_ellipse =
"...";
399 unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
401 unsigned TargetColumns = Columns;
404 if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
405 TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
407 while (SourceStart>0 || SourceEnd<SourceLine.size()) {
408 bool ExpandedRegion =
false;
411 unsigned NewStart = map.startOfPreviousColumn(SourceStart);
417 NewStart = map.startOfPreviousColumn(NewStart);
421 unsigned Prev = map.startOfPreviousColumn(NewStart);
427 assert(map.byteToColumn(NewStart) != -1);
428 unsigned NewColumns = map.byteToColumn(SourceEnd) -
429 map.byteToColumn(NewStart);
430 if (NewColumns <= TargetColumns) {
431 SourceStart = NewStart;
432 ExpandedRegion =
true;
436 if (SourceEnd<SourceLine.size()) {
437 unsigned NewEnd = map.startOfNextColumn(SourceEnd);
442 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
443 NewEnd = map.startOfNextColumn(NewEnd);
446 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
447 NewEnd = map.startOfNextColumn(NewEnd);
449 assert(map.byteToColumn(NewEnd) != -1);
450 unsigned NewColumns = map.byteToColumn(NewEnd) -
451 map.byteToColumn(SourceStart);
452 if (NewColumns <= TargetColumns) {
454 ExpandedRegion =
true;
462 CaretStart = map.byteToColumn(SourceStart);
463 CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
467 assert(CaretStart!=(
unsigned)-1 && CaretEnd!=(
unsigned)-1 &&
468 SourceStart!=(
unsigned)-1 && SourceEnd!=(
unsigned)-1);
469 assert(SourceStart <= SourceEnd);
470 assert(CaretStart <= CaretEnd);
472 unsigned BackColumnsRemoved
473 = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
474 unsigned FrontColumnsRemoved = CaretStart;
475 unsigned ColumnsKept = CaretEnd-CaretStart;
478 assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
482 if (BackColumnsRemoved > strlen(back_ellipse))
483 SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
486 if (FrontColumnsRemoved+ColumnsKept <= Columns)
490 if (FrontColumnsRemoved > strlen(front_ellipse)) {
491 SourceLine.replace(0, SourceStart, front_ellipse);
492 CaretLine.replace(0, CaretStart, front_space);
493 if (!FixItInsertionLine.empty())
494 FixItInsertionLine.replace(0, CaretStart, front_space);
518 case '\'':
return '\'';
519 case '`':
return '\'';
520 case '"':
return '"';
521 case '(':
return ')';
522 case '[':
return ']';
523 case '{':
return '}';
536 unsigned Length,
unsigned Column,
538 assert(Start < Str.size() &&
"Invalid start position!");
539 unsigned End = Start + 1;
542 if (End == Str.size())
558 PunctuationEndStack.push_back(EndPunct);
559 while (End < Length && !PunctuationEndStack.empty()) {
560 if (Str[End] == PunctuationEndStack.back())
561 PunctuationEndStack.pop_back();
563 PunctuationEndStack.push_back(SubEndPunct);
572 unsigned PunctWordLength = End - Start;
574 Column + PunctWordLength <= Columns ||
577 PunctWordLength < Columns/3)
584 return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
601 unsigned Column,
bool Bold) {
602 const unsigned Length = std::min(Str.find(
'\n'), Str.size());
603 bool TextNormal =
true;
605 bool Wrapped =
false;
606 for (
unsigned WordStart = 0, WordEnd; WordStart < Length;
607 WordStart = WordEnd) {
610 if (WordStart == Length)
614 WordEnd =
findEndOfWord(WordStart, Str, Length, Column, Columns);
617 unsigned WordLength = WordEnd - WordStart;
618 if (Column + WordLength < Columns) {
626 Column += WordLength;
643 assert(TextNormal &&
"Text highlighted at end of diagnostic message.");
659 uint64_t StartOfLocationInfo = OS.tell();
672 Message, OS.tell() - StartOfLocationInfo,
684 llvm_unreachable(
"Invalid diagnostic type");
695 llvm_unreachable(
"Invalid diagnostic type");
711 unsigned CurrentColumn,
726 assert(
Normal &&
"Formatting should have returned to normal");
756 TmpFilename =
File->getName();
757 llvm::sys::fs::make_absolute(TmpFilename);
758 llvm::sys::path::native(TmpFilename);
759 llvm::sys::path::remove_dots(TmpFilename,
true);
760 Filename = StringRef(TmpFilename.data(), TmpFilename.size());
783 emitFilename(FE->getName(), Loc.
getManager());
789 unsigned LineNo = PLoc.
getLine();
814 if (
LangOpts.MSCompatibilityVersion &&
829 if (
LangOpts.MSCompatibilityVersion &&
836 if (
DiagOpts->ShowSourceRanges && !Ranges.empty()) {
838 bool PrintedRange =
false;
841 for (
const auto &R : Ranges) {
852 if (
SM.getFileID(B) != CaretFileID ||
SM.getFileID(E) != CaretFileID)
857 unsigned TokSize = 0;
863 << BF.getLineNumber() <<
':' << BF.getColumnNumber() <<
'-'
877 OS <<
"In file included from ";
879 OS <<
':' << PLoc.
getLine() <<
":\n";
881 OS <<
"In included file:\n";
885 StringRef ModuleName) {
887 OS <<
"In module '" << ModuleName <<
"' imported from "
890 OS <<
"In module '" << ModuleName <<
"':\n";
895 StringRef ModuleName) {
897 OS <<
"While building module '" << ModuleName <<
"' imported from "
900 OS <<
"While building module '" << ModuleName <<
"':\n";
904static std::optional<std::pair<unsigned, unsigned>>
912 if (
SM.getFileID(
Begin) != FID ||
SM.getFileID(End) != FID)
915 return std::make_pair(
SM.getExpansionLineNumber(
Begin),
916 SM.getExpansionLineNumber(End));
921static std::pair<unsigned, unsigned>
922maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
925 unsigned Slack = MaxRange - (A.second - A.first + 1);
930 unsigned Min = std::min(A.first, B.first);
931 unsigned Max = std::max(A.second, B.second);
932 if (Max - Min + 1 <= MaxRange)
937 if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||
938 (B.second < A.second && A.second - B.second + 1 > MaxRange))
947 A.second = std::min(A.second + (Slack + 1) / 2, Max);
948 Slack = MaxRange - (A.second - A.first + 1);
949 A.first = std::max(Min + Slack, A.first) - Slack;
950 A.second = std::min(A.first + MaxRange - 1, Max);
962 std::string &CaretLine) {
965 while (StartColNo < Map.getSourceLine().size() &&
966 (Map.getSourceLine()[StartColNo] ==
' ' ||
967 Map.getSourceLine()[StartColNo] ==
'\t'))
968 StartColNo = Map.startOfNextColumn(StartColNo);
972 std::min(
static_cast<size_t>(R.
EndCol), Map.getSourceLine().size());
973 while (EndColNo && (Map.getSourceLine()[EndColNo - 1] ==
' ' ||
974 Map.getSourceLine()[EndColNo - 1] ==
'\t'))
975 EndColNo = Map.startOfPreviousColumn(EndColNo);
980 if (StartColNo > EndColNo)
984 StartColNo = Map.byteToContainingColumn(StartColNo);
985 EndColNo = Map.byteToContainingColumn(EndColNo);
987 assert(StartColNo <= EndColNo &&
"Invalid range!");
988 if (CaretLine.size() < EndColNo)
989 CaretLine.resize(EndColNo,
' ');
990 std::fill(CaretLine.begin() + StartColNo, CaretLine.begin() + EndColNo,
'~');
995 const SourceColumnMap &map,
999 std::string FixItInsertionLine;
1000 if (Hints.empty() || !DiagOpts->ShowFixits)
1001 return FixItInsertionLine;
1002 unsigned PrevHintEndCol = 0;
1004 for (
const auto &H : Hints) {
1005 if (H.CodeToInsert.empty())
1010 std::pair<FileID, unsigned> HintLocInfo =
1011 SM.getDecomposedExpansionLoc(H.RemoveRange.getBegin());
1012 if (FID == HintLocInfo.first &&
1013 LineNo ==
SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1014 StringRef(H.CodeToInsert).find_first_of(
"\n\r") == StringRef::npos) {
1020 unsigned HintByteOffset =
1021 SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
1024 assert(HintByteOffset <
static_cast<unsigned>(map.bytes()) + 1);
1025 unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1034 if (HintCol < PrevHintEndCol)
1035 HintCol = PrevHintEndCol + 1;
1039 unsigned NewFixItLineSize = FixItInsertionLine.size() +
1040 (HintCol - PrevHintEndCol) +
1041 H.CodeToInsert.size();
1042 if (NewFixItLineSize > FixItInsertionLine.size())
1043 FixItInsertionLine.resize(NewFixItLineSize,
' ');
1045 std::copy(H.CodeToInsert.begin(), H.CodeToInsert.end(),
1046 FixItInsertionLine.end() - H.CodeToInsert.size());
1048 PrevHintEndCol = HintCol + llvm::sys::locale::columnWidth(H.CodeToInsert);
1052 expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1054 return FixItInsertionLine;
1058 unsigned L = 1u, M = 10u;
1059 while (M <= N && ++L != std::numeric_limits<unsigned>::digits10 + 1)
1073 const std::pair<unsigned, unsigned> &Lines,
FileID FID,
1083 unsigned StartLineNo =
SM.getExpansionLineNumber(
Begin);
1084 if (StartLineNo > Lines.second ||
SM.getFileID(
Begin) != FID)
1087 unsigned EndLineNo =
SM.getExpansionLineNumber(End);
1088 if (EndLineNo < Lines.first ||
SM.getFileID(End) != FID)
1091 unsigned StartColumn =
SM.getExpansionColumnNumber(
Begin);
1092 unsigned EndColumn =
SM.getExpansionColumnNumber(End);
1093 if (R.isTokenRange())
1097 if (StartLineNo == EndLineNo) {
1098 LineRanges.push_back({StartLineNo, StartColumn - 1, EndColumn - 1});
1103 LineRanges.push_back({StartLineNo, StartColumn - 1, ~0u});
1106 for (
unsigned S = StartLineNo + 1; S != EndLineNo; ++S)
1107 LineRanges.push_back({S, 0, ~0u});
1110 LineRanges.push_back({EndLineNo, 0, EndColumn - 1});
1123void TextDiagnostic::emitSnippetAndCaret(
1126 assert(Loc.
isValid() &&
"must have a valid source location here");
1127 assert(Loc.
isFileID() &&
"must have a file location here");
1137 if (Loc ==
LastLoc && Ranges.empty() && Hints.empty() &&
1149 const char *BufStart = BufData.data();
1150 const char *BufEnd = BufStart + BufData.size();
1156 static const size_t MaxLineLengthToPrint = 4096;
1157 if (CaretColNo > MaxLineLengthToPrint)
1161 const unsigned MaxLines =
DiagOpts->SnippetLineLimit;
1162 std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
1164 for (
const auto &I : Ranges) {
1169 std::min(DisplayLineNo,
SM.getPresumedLineNumber(I.getBegin()));
1176 unsigned MaxLineNoDisplayWidth =
1180 auto indentForLineNumbers = [&] {
1181 if (MaxLineNoDisplayWidth > 0)
1182 OS.indent(MaxLineNoDisplayWidth + 2) <<
"| ";
1188 for (
unsigned LineNo = Lines.first; LineNo != Lines.second + 1;
1189 ++LineNo, ++DisplayLineNo) {
1191 const char *LineStart =
1193 SM.getDecomposedLoc(
SM.translateLineCol(FID, LineNo, 1)).second;
1194 if (LineStart == BufEnd)
1198 const char *LineEnd = LineStart;
1199 while (*LineEnd !=
'\n' && *LineEnd !=
'\r' && LineEnd != BufEnd)
1204 if (
size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
1208 std::string SourceLine(LineStart, LineEnd);
1210 while (!SourceLine.empty() && SourceLine.back() ==
'\0' &&
1211 (LineNo != CaretLineNo || SourceLine.size() > CaretColNo))
1212 SourceLine.pop_back();
1215 const SourceColumnMap sourceColMap(SourceLine,
DiagOpts->TabStop);
1217 std::string CaretLine;
1219 for (
const auto &LR : LineRanges) {
1220 if (LR.LineNo == LineNo)
1225 if (CaretLineNo == LineNo) {
1226 size_t Col = sourceColMap.byteToContainingColumn(CaretColNo - 1);
1227 CaretLine.resize(std::max(Col + 1, CaretLine.size()),
' ');
1228 CaretLine[Col] =
'^';
1232 FID, LineNo, sourceColMap, Hints,
SM,
DiagOpts.get());
1236 unsigned Columns =
DiagOpts->MessageLength;
1239 Columns, sourceColMap);
1245 if (
DiagOpts->ShowSourceRanges && !SourceLine.empty()) {
1246 SourceLine =
' ' + SourceLine;
1247 CaretLine =
' ' + CaretLine;
1251 emitSnippet(SourceLine, MaxLineNoDisplayWidth, DisplayLineNo);
1253 if (!CaretLine.empty()) {
1254 indentForLineNumbers();
1257 OS << CaretLine <<
'\n';
1262 if (!FixItInsertionLine.empty()) {
1263 indentForLineNumbers();
1269 OS << FixItInsertionLine <<
'\n';
1276 emitParseableFixits(Hints,
SM);
1279void TextDiagnostic::emitSnippet(StringRef SourceLine,
1280 unsigned MaxLineNoDisplayWidth,
1283 if (MaxLineNoDisplayWidth > 0) {
1285 OS.indent(MaxLineNoDisplayWidth - LineNoDisplayWidth + 1)
1290 bool PrintReversed =
false;
1292 while (I < SourceLine.size()) {
1293 auto [Str, WasPrintable] =
1298 if (WasPrintable == PrintReversed) {
1299 PrintReversed = !PrintReversed;
1317 if (!
DiagOpts->ShowParseableFixits)
1322 for (
const auto &H : Hints) {
1323 if (H.RemoveRange.isInvalid() || H.RemoveRange.getBegin().isMacroID() ||
1324 H.RemoveRange.getEnd().isMacroID())
1328 for (
const auto &H : Hints) {
1332 std::pair<FileID, unsigned> BInfo =
SM.getDecomposedLoc(BLoc);
1333 std::pair<FileID, unsigned> EInfo =
SM.getDecomposedLoc(ELoc);
1336 if (H.RemoveRange.isTokenRange())
1347 OS <<
"\":{" <<
SM.getLineNumber(BInfo.first, BInfo.second)
1348 <<
':' <<
SM.getColumnNumber(BInfo.first, BInfo.second)
1349 <<
'-' <<
SM.getLineNumber(EInfo.first, EInfo.second)
1350 <<
':' <<
SM.getColumnNumber(EInfo.first, EInfo.second)
1352 OS.write_escaped(H.CodeToInsert);
static StringRef bytes(const std::vector< T, Allocator > &v)
Defines the clang::FileManager interface and associated types.
Defines the SourceManager interface.
static enum raw_ostream::Colors caretColor
static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i)
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.
static enum raw_ostream::Colors fixitColor
static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, bool &Normal, bool Bold)
Add highlights to differences in template strings.
static enum raw_ostream::Colors savedColor
static enum raw_ostream::Colors errorColor
static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length)
Skip over whitespace in the string, starting at the given index.
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.
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.
static std::pair< SmallString< 16 >, bool > printableTextForNextCharacter(StringRef SourceLine, size_t *I, unsigned TabStop)
returns a printable representation of first item from input range
static enum raw_ostream::Colors remarkColor
static enum raw_ostream::Colors fatalColor
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.
static void selectInterestingSourceRegion(std::string &SourceLine, std::string &CaretLine, std::string &FixItInsertionLine, unsigned Columns, const SourceColumnMap &map)
When the source code line we want to print is too long for the terminal, select the "interesting" reg...
static std::string buildFixItInsertionLine(FileID FID, unsigned LineNo, const SourceColumnMap &map, ArrayRef< FixItHint > Hints, const SourceManager &SM, const DiagnosticOptions *DiagOpts)
static enum raw_ostream::Colors warningColor
static char findMatchingPunctuation(char c)
If the given character is the start of some kind of balanced punctuation (e.g., quotes or parentheses...
static enum raw_ostream::Colors noteColor
static void expandTabs(std::string &SourceLine, unsigned TabStop)
static void genColumnByteMapping(StringRef SourceLine, unsigned TabStop, SmallVectorImpl< int > &BytesOut, SmallVectorImpl< int > &ColumnsOut)
BytesOut: A mapping from columns to the byte of the source line that produced the character displayin...
static void highlightRange(const LineRange &R, const SourceColumnMap &Map, std::string &CaretLine)
Highlight R (with ~'s) on the current source line.
const unsigned WordWrapIndentation
Number of spaces to indent when word-wrapping.
static unsigned getNumDisplayWidth(unsigned N)
static enum raw_ostream::Colors templateColor
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,...
__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.
Class to encapsulate the logic for formatting a diagnostic message.
const LangOptions & LangOpts
SourceLocation LastLoc
The location of the previous diagnostic if known.
DiagnosticsEngine::Level LastLevel
The level of the last diagnostic emitted.
IntrusiveRefCntPtr< 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
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
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 ...
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.
~TextDiagnostic() override
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override
static void printDiagnosticLevel(raw_ostream &OS, DiagnosticsEngine::Level Level, bool ShowColors)
Print the diagonstic level to a raw_ostream.
void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef< CharSourceRange > Ranges) override
Print out the file/line/column information and include trace.
void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, DiagOrStoredDiag D) override
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, DiagnosticOptions *DiagOpts)
@ C
Languages that the frontend can parse and compile.
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
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.