16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/ConvertUTF.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/Locale.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
39 static const enum raw_ostream::Colors
errorColor = raw_ostream::RED;
40 static const enum raw_ostream::Colors
fatalColor = raw_ostream::RED;
43 raw_ostream::SAVEDCOLOR;
47 bool &Normal,
bool Bold) {
50 OS << Str.slice(0, Pos);
51 if (Pos == StringRef::npos)
54 Str = Str.substr(Pos + 1);
72 if (SourceLine[--i]==
'\t')
98 static 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);
119 begin =
reinterpret_cast<unsigned char const *
>(&*(SourceLine.begin() + *i));
120 end = begin + (SourceLine.size() - *i);
122 if (isLegalUTF8Sequence(begin, end)) {
125 unsigned char const *original_begin =
begin;
126 unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]);
128 ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
131 assert(conversionOK==res);
132 assert(0 < begin-original_begin
133 &&
"we must be further along in the string now");
134 *i += begin-original_begin;
136 if (!llvm::sys::locale::isPrint(c)) {
140 expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
143 while (expandedCP.size() < 8)
144 expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
145 return std::make_pair(expandedCP,
false);
155 unsigned char byte = SourceLine[*i];
156 expandedByte[1] = llvm::hexdigit(byte / 16);
157 expandedByte[2] = llvm::hexdigit(byte % 16);
159 return std::make_pair(expandedByte,
false);
162 static void expandTabs(std::string &SourceLine,
unsigned TabStop) {
163 size_t i = SourceLine.size();
166 if (SourceLine[i]!=
'\t')
169 std::pair<SmallString<16>,
bool> res
171 SourceLine.replace(i, 1, res.first.c_str());
201 if (SourceLine.empty()) {
206 out.resize(SourceLine.size()+1, -1);
210 while (i<SourceLine.size()) {
212 std::pair<SmallString<16>,
bool> res
216 out.back() = columns;
235 if (SourceLine.empty()) {
242 while (i<SourceLine.size()) {
243 out.resize(columns+1, -1);
245 std::pair<SmallString<16>,
bool> res
249 out.resize(columns+1, -1);
254 struct SourceColumnMap {
255 SourceColumnMap(StringRef SourceLine,
unsigned TabStop)
256 : m_SourceLine(SourceLine) {
261 assert(m_byteToColumn.size()==SourceLine.size()+1);
262 assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
263 assert(m_byteToColumn.size()
264 ==
static_cast<unsigned>(m_columnToByte.back()+1));
265 assert(static_cast<unsigned>(m_byteToColumn.back()+1)
266 == m_columnToByte.size());
268 int columns()
const {
return m_byteToColumn.back(); }
269 int bytes()
const {
return m_columnToByte.back(); }
274 assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
275 return m_byteToColumn[n];
279 int byteToContainingColumn(
int N)
const {
280 assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
281 while (m_byteToColumn[N] == -1)
283 return m_byteToColumn[N];
290 assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
291 return m_columnToByte[n];
295 int startOfNextColumn(
int N)
const {
296 assert(0 <= N && N < static_cast<int>(m_byteToColumn.size() - 1));
302 int startOfPreviousColumn(
int N)
const {
303 assert(0 < N && N < static_cast<int>(m_byteToColumn.size()));
308 StringRef getSourceLine()
const {
313 const std::string m_SourceLine;
322 std::string &CaretLine,
323 std::string &FixItInsertionLine,
325 const SourceColumnMap &map) {
326 unsigned CaretColumns = CaretLine.size();
328 unsigned MaxColumns =
std::max(static_cast<unsigned>(map.columns()),
329 std::max(CaretColumns, FixItColumns));
331 if (MaxColumns <= Columns)
335 assert(CaretLine.end() ==
336 std::find_if(CaretLine.begin(), CaretLine.end(),
337 [](
char c) {
return c <
' ' ||
'~' < c; }));
341 unsigned CaretStart = 0, CaretEnd = CaretLine.size();
342 for (; CaretStart != CaretEnd; ++CaretStart)
346 for (; CaretEnd != CaretStart; --CaretEnd)
355 if (!FixItInsertionLine.empty()) {
356 unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
357 for (; FixItStart != FixItEnd; ++FixItStart)
361 for (; FixItEnd != FixItStart; --FixItEnd)
368 unsigned FixItStartCol = FixItStart;
372 CaretStart =
std::min(FixItStartCol, CaretStart);
373 CaretEnd =
std::max(FixItEndCol, CaretEnd);
379 while (static_cast<int>(CaretEnd) < map.columns() &&
380 -1 == map.columnToByte(CaretEnd))
383 assert((static_cast<int>(CaretStart) > map.columns() ||
384 -1!=map.columnToByte(CaretStart)) &&
385 "CaretStart must not point to a column in the middle of a source"
387 assert((static_cast<int>(CaretEnd) > map.columns() ||
388 -1!=map.columnToByte(CaretEnd)) &&
389 "CaretEnd must not point to a column in the middle of a source line"
397 unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
399 unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
402 unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
403 - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
405 char const *front_ellipse =
" ...";
406 char const *front_space =
" ";
407 char const *back_ellipse =
"...";
408 unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
410 unsigned TargetColumns = Columns;
413 if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
414 TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
416 while (SourceStart>0 || SourceEnd<SourceLine.size()) {
417 bool ExpandedRegion =
false;
420 unsigned NewStart = map.startOfPreviousColumn(SourceStart);
426 NewStart = map.startOfPreviousColumn(NewStart);
430 unsigned Prev = map.startOfPreviousColumn(NewStart);
436 assert(map.byteToColumn(NewStart) != -1);
437 unsigned NewColumns = map.byteToColumn(SourceEnd) -
438 map.byteToColumn(NewStart);
439 if (NewColumns <= TargetColumns) {
440 SourceStart = NewStart;
441 ExpandedRegion =
true;
445 if (SourceEnd<SourceLine.size()) {
446 unsigned NewEnd = map.startOfNextColumn(SourceEnd);
451 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
452 NewEnd = map.startOfNextColumn(NewEnd);
455 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
456 NewEnd = map.startOfNextColumn(NewEnd);
458 assert(map.byteToColumn(NewEnd) != -1);
459 unsigned NewColumns = map.byteToColumn(NewEnd) -
460 map.byteToColumn(SourceStart);
461 if (NewColumns <= TargetColumns) {
463 ExpandedRegion =
true;
471 CaretStart = map.byteToColumn(SourceStart);
472 CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
478 assert(CaretStart!=(
unsigned)-1 && CaretEnd!=(
unsigned)-1 &&
479 SourceStart!=(
unsigned)-1 && SourceEnd!=(
unsigned)-1);
480 assert(SourceStart <= SourceEnd);
481 assert(CaretStart <= CaretEnd);
483 unsigned BackColumnsRemoved
484 = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
485 unsigned FrontColumnsRemoved = CaretStart;
486 unsigned ColumnsKept = CaretEnd-CaretStart;
489 assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
493 if (BackColumnsRemoved > strlen(back_ellipse))
494 SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
497 if (FrontColumnsRemoved+ColumnsKept <= Columns)
501 if (FrontColumnsRemoved > strlen(front_ellipse)) {
502 SourceLine.replace(0, SourceStart, front_ellipse);
503 CaretLine.replace(0, CaretStart, front_space);
504 if (!FixItInsertionLine.empty())
505 FixItInsertionLine.replace(0, CaretStart, front_space);
529 case '\'':
return '\'';
530 case '`':
return '\'';
531 case '"':
return '"';
532 case '(':
return ')';
533 case '[':
return ']';
534 case '{':
return '}';
547 unsigned Length,
unsigned Column,
549 assert(Start < Str.size() &&
"Invalid start position!");
550 unsigned End = Start + 1;
553 if (End == Str.size())
569 PunctuationEndStack.push_back(EndPunct);
570 while (End < Length && !PunctuationEndStack.empty()) {
571 if (Str[End] == PunctuationEndStack.back())
572 PunctuationEndStack.pop_back();
574 PunctuationEndStack.push_back(SubEndPunct);
583 unsigned PunctWordLength = End - Start;
585 Column + PunctWordLength <= Columns ||
588 PunctWordLength < Columns/3)
595 return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
619 bool TextNormal =
true;
623 IndentStr.assign(Indentation,
' ');
624 bool Wrapped =
false;
625 for (
unsigned WordStart = 0, WordEnd; WordStart <
Length;
626 WordStart = WordEnd) {
629 if (WordStart == Length)
633 WordEnd =
findEndOfWord(WordStart, Str, Length, Column, Columns);
636 unsigned WordLength = WordEnd - WordStart;
637 if (Column + WordLength < Columns) {
645 Column += WordLength;
652 OS.write(&IndentStr[0], Indentation);
655 Column = Indentation + WordLength;
662 assert(TextNormal &&
"Text highlighted at end of diagnostic message.");
682 uint64_t StartOfLocationInfo = OS.tell();
695 Message, OS.tell() - StartOfLocationInfo,
703 bool CLFallbackMode) {
708 llvm_unreachable(
"Invalid diagnostic type");
719 llvm_unreachable(
"Invalid diagnostic type");
744 unsigned CurrentColumn,
745 unsigned Columns,
bool ShowColors) {
747 if (ShowColors && !IsSupplemental) {
759 assert(Normal &&
"Formatting should have returned to normal");
791 unsigned LineNo = PLoc.
getLine();
812 if (
LangOpts.MSCompatibilityVersion &&
826 if (
LangOpts.MSCompatibilityVersion &&
833 if (
DiagOpts->ShowSourceRanges && !Ranges.empty()) {
836 bool PrintedRange =
false;
842 if (!RI->isValid())
continue;
860 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
865 unsigned TokSize = 0;
866 if (RI->isTokenRange())
869 OS <<
'{' << SM.
getLineNumber(BInfo.first, BInfo.second) <<
':'
887 OS <<
"In file included from " << PLoc.
getFilename() <<
':'
890 OS <<
"In included file:\n";
894 StringRef ModuleName,
897 OS <<
"In module '" << ModuleName <<
"' imported from "
900 OS <<
"In module '" << ModuleName <<
"':\n";
905 StringRef ModuleName,
908 OS <<
"While building module '" << ModuleName <<
"' imported from "
911 OS <<
"While building module '" << ModuleName <<
"':\n";
916 unsigned LineNo,
FileID FID,
917 const SourceColumnMap &map,
918 std::string &CaretLine,
927 if (StartLineNo > LineNo || SM.
getFileID(Begin) != FID)
931 if (EndLineNo < LineNo || SM.
getFileID(End) != FID)
935 unsigned StartColNo = 0;
936 if (StartLineNo == LineNo) {
938 if (StartColNo) --StartColNo;
942 unsigned EndColNo = map.getSourceLine().size();
943 if (EndLineNo == LineNo) {
953 EndColNo = CaretLine.size();
957 assert(StartColNo <= EndColNo &&
"Invalid range!");
962 while (StartColNo < map.getSourceLine().size() &&
963 (map.getSourceLine()[StartColNo] ==
' ' ||
964 map.getSourceLine()[StartColNo] ==
'\t'))
965 StartColNo = map.startOfNextColumn(StartColNo);
968 if (EndColNo > map.getSourceLine().size())
969 EndColNo = map.getSourceLine().size();
971 (map.getSourceLine()[EndColNo-1] ==
' ' ||
972 map.getSourceLine()[EndColNo-1] ==
'\t'))
973 EndColNo = map.startOfPreviousColumn(EndColNo);
978 assert(StartColNo <= EndColNo &&
"Trying to highlight whitespace??");
981 assert(StartColNo <= map.getSourceLine().size() &&
"Invalid range!");
982 assert(EndColNo <= map.getSourceLine().size() &&
"Invalid range!");
985 StartColNo = map.byteToContainingColumn(StartColNo);
986 EndColNo = map.byteToContainingColumn(EndColNo);
988 assert(StartColNo <= EndColNo &&
"Invalid range!");
989 if (CaretLine.size() < EndColNo)
990 CaretLine.resize(EndColNo,
' ');
991 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;
1006 if (!
I->CodeToInsert.empty()) {
1009 std::pair<FileID, unsigned> HintLocInfo
1011 if (LineNo == SM.
getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1012 StringRef(
I->CodeToInsert).find_first_of(
"\n\r") == StringRef::npos) {
1018 unsigned HintByteOffset
1022 assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1023 unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1032 if (HintCol < PrevHintEndCol)
1033 HintCol = PrevHintEndCol + 1;
1037 unsigned NewFixItLineSize = FixItInsertionLine.size() +
1038 (HintCol - PrevHintEndCol) +
I->CodeToInsert.size();
1039 if (NewFixItLineSize > FixItInsertionLine.size())
1040 FixItInsertionLine.resize(NewFixItLineSize,
' ');
1042 std::copy(
I->CodeToInsert.begin(),
I->CodeToInsert.end(),
1043 FixItInsertionLine.end() -
I->CodeToInsert.size());
1048 FixItInsertionLine.clear();
1054 expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1056 return FixItInsertionLine;
1066 void TextDiagnostic::emitSnippetAndCaret(
1071 assert(Loc.
isValid() &&
"must have a valid source location here");
1072 assert(Loc.
isFileID() &&
"must have a file location here");
1082 if (Loc ==
LastLoc && Ranges.empty() && Hints.empty() &&
1088 FileID FID = LocInfo.first;
1089 unsigned FileOffset = LocInfo.second;
1097 const char *BufStart = BufData.data();
1098 const char *BufEnd = BufStart + BufData.size();
1104 static const size_t MaxLineLengthToPrint = 4096;
1105 if (ColNo > MaxLineLengthToPrint)
1109 const char *TokPtr = BufStart+FileOffset;
1110 const char *LineStart = TokPtr-ColNo+1;
1114 const char *LineEnd = TokPtr;
1115 while (*LineEnd !=
'\n' && *LineEnd !=
'\r' && LineEnd != BufEnd)
1119 if (
size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
1123 StringRef
Line(LineStart, LineEnd - LineStart);
1124 while (
Line.size() > ColNo &&
Line.back() ==
'\0')
1128 std::string SourceLine(
Line.begin(),
Line.end());
1131 const SourceColumnMap sourceColMap(SourceLine,
DiagOpts->TabStop);
1135 std::string CaretLine(sourceColMap.columns(),
' ');
1144 ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
1145 if (CaretLine.size()<ColNo+1)
1146 CaretLine.resize(ColNo+1,
' ');
1147 CaretLine[ColNo] =
'^';
1156 unsigned Columns =
DiagOpts->MessageLength;
1159 Columns, sourceColMap);
1166 SourceLine =
' ' + SourceLine;
1167 CaretLine =
' ' + CaretLine;
1171 while (CaretLine[CaretLine.size()-1] ==
' ')
1172 CaretLine.erase(CaretLine.end()-1);
1175 emitSnippet(SourceLine);
1179 OS << CaretLine <<
'\n';
1183 if (!FixItInsertionLine.empty()) {
1189 OS << FixItInsertionLine <<
'\n';
1195 emitParseableFixits(Hints, SM);
1198 void TextDiagnostic::emitSnippet(StringRef line) {
1204 std::string to_print;
1205 bool print_reversed =
false;
1207 while (i<line.size()) {
1208 std::pair<SmallString<16>,
bool> res
1210 bool was_printable = res.second;
1212 if (
DiagOpts->ShowColors && was_printable == print_reversed) {
1221 print_reversed = !was_printable;
1222 to_print += res.first.str();
1225 if (print_reversed &&
DiagOpts->ShowColors)
1228 if (print_reversed &&
DiagOpts->ShowColors)
1236 if (!
DiagOpts->ShowParseableFixits)
1243 if (
I->RemoveRange.isInvalid() ||
1244 I->RemoveRange.getBegin().isMacroID() ||
1245 I->RemoveRange.getEnd().isMacroID())
1258 if (
I->RemoveRange.isTokenRange())
1274 OS.write_escaped(
I->CodeToInsert);
SourceLocation getBegin() const
unsigned getColumn() const
Return the presumed column number of this location.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Defines the clang::FileManager interface and associated types.
static LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef< CharSourceRange > Ranges, const SourceManager &SM) override
Print out the file/line/column information and include trace.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
Defines the SourceManager interface.
static enum raw_ostream::Colors fatalColor
const LangOptions & LangOpts
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 enum raw_ostream::Colors caretColor
static enum raw_ostream::Colors templateColor
static enum raw_ostream::Colors errorColor
static StringRef bytes(const std::vector< T, Allocator > &v)
static enum raw_ostream::Colors fixitColor
void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) override
static std::pair< SmallString< 16 >, bool > printableTextForNextCharacter(StringRef SourceLine, size_t *i, unsigned TabStop)
returns a printable representation of first item from input range
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
std::pair< SourceLocation, SourceLocation > getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Class to encapsulate the logic for formatting a diagnostic message.
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
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 bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns, unsigned Column=0, bool Bold=false, unsigned Indentation=WordWrapIndentation)
Print the given string to a stream, word-wrapping it to some number of columns in the process...
DiagnosticsEngine::Level LastLevel
The level of the last diagnostic emitted.
unsigned getLine() const
Return the presumed line number of this location.
TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, DiagnosticOptions *DiagOpts)
detail::InMemoryDirectory::const_iterator I
static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length)
Skip over whitespace in the string, starting at the given index.
~TextDiagnostic() override
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Represents a character-granular source range.
SourceLocation getEnd() 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 ...
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Represents an unpacked "presumed" location which can be presented to the user.
static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i)
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, const SourceManager *SM, DiagOrStoredDiag D) override
static enum raw_ostream::Colors warningColor
static enum raw_ostream::Colors noteColor
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
const char * getFilename() const
Return the presumed filename of this location.
const char * getName() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
static void highlightRange(const CharSourceRange &R, unsigned LineNo, FileID FID, const SourceColumnMap &map, std::string &CaretLine, const SourceManager &SM, const LangOptions &LangOpts)
Highlight a SourceRange (with ~'s) for any characters on LineNo.
static void printDiagnosticLevel(raw_ostream &OS, DiagnosticsEngine::Level Level, bool ShowColors, bool CLFallbackMode=false)
Print the diagonstic level to a raw_ostream.
Cached information about one file (either on disk or in the virtual file system). ...
const char ToggleHighlight
Special character that the diagnostic printer will use to toggle the bold attribute.
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.
static void byteToColumn(StringRef SourceLine, unsigned TabStop, SmallVectorImpl< int > &out)
This function takes a raw source line and produces a mapping from the bytes of the printable represen...
const unsigned WordWrapIndentation
Number of spaces to indent when word-wrapping.
static char findMatchingPunctuation(char c)
If the given character is the start of some kind of balanced punctuation (e.g., quotes or parentheses...
static void expandTabs(std::string &SourceLine, unsigned TabStop)
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
SourceLocation LastLoc
The location of the previous diagnostic if known.
static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, bool &Normal, bool Bold)
Add highlights to differences in template strings.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
static void columnToByte(StringRef SourceLine, unsigned TabStop, SmallVectorImpl< int > &out)
This function takes a raw source line and produces a mapping from columns to the byte of the source l...
void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM) override
detail::InMemoryDirectory::const_iterator E
static std::string buildFixItInsertionLine(unsigned LineNo, const SourceColumnMap &map, ArrayRef< FixItHint > Hints, const SourceManager &SM, const DiagnosticOptions *DiagOpts)
void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) override
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
Level
The level of the diagnostic, after it has been through mapping.
static enum raw_ostream::Colors remarkColor
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
static enum raw_ostream::Colors savedColor
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.