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/Path.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);
118 unsigned char const *begin, *end;
119 begin =
reinterpret_cast<unsigned char const *
>(&*(SourceLine.begin() + *i));
120 end = begin + (SourceLine.size() - *i);
122 if (llvm::isLegalUTF8Sequence(begin, end)) {
124 llvm::UTF32 *cptr = &c;
125 unsigned char const *original_begin = begin;
126 unsigned char const *cp_end =
127 begin + llvm::getNumBytesForUTF8(SourceLine[*i]);
129 llvm::ConversionResult res = llvm::ConvertUTF8toUTF32(
130 &begin, cp_end, &cptr, cptr + 1, llvm::strictConversion);
132 assert(llvm::conversionOK == res);
133 assert(0 < begin-original_begin
134 &&
"we must be further along in the string now");
135 *i += begin-original_begin;
137 if (!llvm::sys::locale::isPrint(c)) {
141 expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
144 while (expandedCP.size() < 8)
145 expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
146 return std::make_pair(expandedCP,
false);
156 unsigned char byte = SourceLine[*i];
157 expandedByte[1] = llvm::hexdigit(byte / 16);
158 expandedByte[2] = llvm::hexdigit(byte % 16);
160 return std::make_pair(expandedByte,
false);
163 static void expandTabs(std::string &SourceLine,
unsigned TabStop) {
164 size_t i = SourceLine.size();
167 if (SourceLine[i]!=
'\t')
170 std::pair<SmallString<16>,
bool> res
172 SourceLine.replace(i, 1, res.first.c_str());
202 if (SourceLine.empty()) {
207 out.resize(SourceLine.size()+1, -1);
211 while (i<SourceLine.size()) {
213 std::pair<SmallString<16>,
bool> res
217 out.back() = columns;
236 if (SourceLine.empty()) {
243 while (i<SourceLine.size()) {
244 out.resize(columns+1, -1);
246 std::pair<SmallString<16>,
bool> res
250 out.resize(columns+1, -1);
255 struct SourceColumnMap {
256 SourceColumnMap(StringRef SourceLine,
unsigned TabStop)
257 : m_SourceLine(SourceLine) {
262 assert(m_byteToColumn.size()==SourceLine.size()+1);
263 assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
264 assert(m_byteToColumn.size()
265 ==
static_cast<unsigned>(m_columnToByte.back()+1));
266 assert(static_cast<unsigned>(m_byteToColumn.back()+1)
267 == m_columnToByte.size());
269 int columns()
const {
return m_byteToColumn.back(); }
270 int bytes()
const {
return m_columnToByte.back(); }
275 assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
276 return m_byteToColumn[n];
280 int byteToContainingColumn(
int N)
const {
281 assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
282 while (m_byteToColumn[N] == -1)
284 return m_byteToColumn[N];
291 assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
292 return m_columnToByte[n];
296 int startOfNextColumn(
int N)
const {
297 assert(0 <= N && N < static_cast<int>(m_byteToColumn.size() - 1));
303 int startOfPreviousColumn(
int N)
const {
304 assert(0 < N && N < static_cast<int>(m_byteToColumn.size()));
309 StringRef getSourceLine()
const {
314 const std::string m_SourceLine;
323 std::string &CaretLine,
324 std::string &FixItInsertionLine,
326 const SourceColumnMap &map) {
327 unsigned CaretColumns = CaretLine.size();
329 unsigned MaxColumns =
std::max(static_cast<unsigned>(map.columns()),
330 std::max(CaretColumns, FixItColumns));
332 if (MaxColumns <= Columns)
336 assert(CaretLine.end() ==
337 std::find_if(CaretLine.begin(), CaretLine.end(),
338 [](
char c) {
return c <
' ' ||
'~' < c; }));
342 unsigned CaretStart = 0, CaretEnd = CaretLine.size();
343 for (; CaretStart != CaretEnd; ++CaretStart)
347 for (; CaretEnd != CaretStart; --CaretEnd)
356 if (!FixItInsertionLine.empty()) {
357 unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
358 for (; FixItStart != FixItEnd; ++FixItStart)
362 for (; FixItEnd != FixItStart; --FixItEnd)
369 unsigned FixItStartCol = FixItStart;
373 CaretStart =
std::min(FixItStartCol, CaretStart);
374 CaretEnd =
std::max(FixItEndCol, CaretEnd);
380 while (static_cast<int>(CaretEnd) < map.columns() &&
381 -1 == map.columnToByte(CaretEnd))
384 assert((static_cast<int>(CaretStart) > map.columns() ||
385 -1!=map.columnToByte(CaretStart)) &&
386 "CaretStart must not point to a column in the middle of a source" 388 assert((static_cast<int>(CaretEnd) > map.columns() ||
389 -1!=map.columnToByte(CaretEnd)) &&
390 "CaretEnd must not point to a column in the middle of a source line" 398 unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
400 unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
403 unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
404 - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
406 char const *front_ellipse =
" ...";
407 char const *front_space =
" ";
408 char const *back_ellipse =
"...";
409 unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
411 unsigned TargetColumns = Columns;
414 if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
415 TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
417 while (SourceStart>0 || SourceEnd<SourceLine.size()) {
418 bool ExpandedRegion =
false;
421 unsigned NewStart = map.startOfPreviousColumn(SourceStart);
427 NewStart = map.startOfPreviousColumn(NewStart);
431 unsigned Prev = map.startOfPreviousColumn(NewStart);
437 assert(map.byteToColumn(NewStart) != -1);
438 unsigned NewColumns = map.byteToColumn(SourceEnd) -
439 map.byteToColumn(NewStart);
440 if (NewColumns <= TargetColumns) {
441 SourceStart = NewStart;
442 ExpandedRegion =
true;
446 if (SourceEnd<SourceLine.size()) {
447 unsigned NewEnd = map.startOfNextColumn(SourceEnd);
452 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
453 NewEnd = map.startOfNextColumn(NewEnd);
456 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
457 NewEnd = map.startOfNextColumn(NewEnd);
459 assert(map.byteToColumn(NewEnd) != -1);
460 unsigned NewColumns = map.byteToColumn(NewEnd) -
461 map.byteToColumn(SourceStart);
462 if (NewColumns <= TargetColumns) {
464 ExpandedRegion =
true;
472 CaretStart = map.byteToColumn(SourceStart);
473 CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
479 assert(CaretStart!=(
unsigned)-1 && CaretEnd!=(
unsigned)-1 &&
480 SourceStart!=(
unsigned)-1 && SourceEnd!=(
unsigned)-1);
481 assert(SourceStart <= SourceEnd);
482 assert(CaretStart <= CaretEnd);
484 unsigned BackColumnsRemoved
485 = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
486 unsigned FrontColumnsRemoved = CaretStart;
487 unsigned ColumnsKept = CaretEnd-CaretStart;
490 assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
494 if (BackColumnsRemoved > strlen(back_ellipse))
495 SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
498 if (FrontColumnsRemoved+ColumnsKept <= Columns)
502 if (FrontColumnsRemoved > strlen(front_ellipse)) {
503 SourceLine.replace(0, SourceStart, front_ellipse);
504 CaretLine.replace(0, CaretStart, front_space);
505 if (!FixItInsertionLine.empty())
506 FixItInsertionLine.replace(0, CaretStart, front_space);
530 case '\'':
return '\'';
531 case '`':
return '\'';
532 case '"':
return '"';
533 case '(':
return ')';
534 case '[':
return ']';
535 case '{':
return '}';
548 unsigned Length,
unsigned Column,
550 assert(Start < Str.size() &&
"Invalid start position!");
551 unsigned End = Start + 1;
554 if (End == Str.size())
570 PunctuationEndStack.push_back(EndPunct);
571 while (End < Length && !PunctuationEndStack.empty()) {
572 if (Str[End] == PunctuationEndStack.back())
573 PunctuationEndStack.pop_back();
575 PunctuationEndStack.push_back(SubEndPunct);
584 unsigned PunctWordLength = End - Start;
586 Column + PunctWordLength <= Columns ||
589 PunctWordLength < Columns/3)
596 return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
619 const unsigned Length =
std::min(Str.find(
'\n'), Str.size());
620 bool TextNormal =
true;
624 IndentStr.assign(Indentation,
' ');
625 bool Wrapped =
false;
626 for (
unsigned WordStart = 0, WordEnd; WordStart < Length;
627 WordStart = WordEnd) {
630 if (WordStart == Length)
634 WordEnd =
findEndOfWord(WordStart, Str, Length, Column, Columns);
637 unsigned WordLength = WordEnd - WordStart;
638 if (Column + WordLength < Columns) {
646 Column += WordLength;
653 OS.write(&IndentStr[0], Indentation);
656 Column = Indentation + WordLength;
663 assert(TextNormal &&
"Text highlighted at end of diagnostic message.");
679 uint64_t StartOfLocationInfo = OS.tell();
692 Message, OS.tell() - StartOfLocationInfo,
700 bool CLFallbackMode) {
705 llvm_unreachable(
"Invalid diagnostic type");
716 llvm_unreachable(
"Invalid diagnostic type");
741 unsigned CurrentColumn,
742 unsigned Columns,
bool ShowColors) {
744 if (ShowColors && !IsSupplemental) {
756 assert(Normal &&
"Formatting should have returned to normal");
768 llvm::sys::path::parent_path(
Filename));
771 llvm::sys::path::append(AbsoluteFilename, DirName,
772 llvm::sys::path::filename(
Filename));
773 Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size());
803 unsigned LineNo = PLoc.
getLine();
824 if (
LangOpts.MSCompatibilityVersion &&
838 if (
LangOpts.MSCompatibilityVersion &&
845 if (
DiagOpts->ShowSourceRanges && !Ranges.empty()) {
847 bool PrintedRange =
false;
853 if (!RI->isValid())
continue;
875 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
880 unsigned TokSize = 0;
881 if (RI->isTokenRange())
897 OS <<
"In file included from " << PLoc.
getFilename() <<
':' 900 OS <<
"In included file:\n";
904 StringRef ModuleName) {
906 OS <<
"In module '" << ModuleName <<
"' imported from " 909 OS <<
"In module '" << ModuleName <<
"':\n";
914 StringRef ModuleName) {
916 OS <<
"While building module '" << ModuleName <<
"' imported from " 919 OS <<
"While building module '" << ModuleName <<
"':\n";
939 static std::pair<unsigned, unsigned>
940 maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
943 unsigned Slack = MaxRange - (A.second - A.first + 1);
948 unsigned Min =
std::min(A.first, B.first);
949 unsigned Max =
std::max(A.second, B.second);
950 if (Max - Min + 1 <= MaxRange)
955 if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||
956 (B.second < A.second && A.second - B.second + 1 > MaxRange))
965 A.second =
std::min(A.second + (Slack + 1) / 2, Max);
966 Slack = MaxRange - (A.second - A.first + 1);
967 A.first =
std::max(Min + Slack, A.first) - Slack;
968 A.second =
std::min(A.first + MaxRange - 1, Max);
974 unsigned LineNo,
FileID FID,
975 const SourceColumnMap &map,
976 std::string &CaretLine,
985 if (StartLineNo > LineNo || SM.
getFileID(Begin) != FID)
989 if (EndLineNo < LineNo || SM.
getFileID(End) != FID)
993 unsigned StartColNo = 0;
994 if (StartLineNo == LineNo) {
996 if (StartColNo) --StartColNo;
1000 unsigned EndColNo = map.getSourceLine().size();
1001 if (EndLineNo == LineNo) {
1011 EndColNo = CaretLine.size();
1015 assert(StartColNo <= EndColNo &&
"Invalid range!");
1020 while (StartColNo < map.getSourceLine().size() &&
1021 (map.getSourceLine()[StartColNo] ==
' ' ||
1022 map.getSourceLine()[StartColNo] ==
'\t'))
1023 StartColNo = map.startOfNextColumn(StartColNo);
1026 if (EndColNo > map.getSourceLine().size())
1027 EndColNo = map.getSourceLine().size();
1029 (map.getSourceLine()[EndColNo-1] ==
' ' ||
1030 map.getSourceLine()[EndColNo-1] ==
'\t'))
1031 EndColNo = map.startOfPreviousColumn(EndColNo);
1036 if (StartColNo > EndColNo) {
1037 assert(StartLineNo != EndLineNo &&
"trying to highlight whitespace");
1038 StartColNo = EndColNo;
1042 assert(StartColNo <= map.getSourceLine().size() &&
"Invalid range!");
1043 assert(EndColNo <= map.getSourceLine().size() &&
"Invalid range!");
1046 StartColNo = map.byteToContainingColumn(StartColNo);
1047 EndColNo = map.byteToContainingColumn(EndColNo);
1049 assert(StartColNo <= EndColNo &&
"Invalid range!");
1050 if (CaretLine.size() < EndColNo)
1051 CaretLine.resize(EndColNo,
' ');
1052 std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,
'~');
1057 const SourceColumnMap &map,
1061 std::string FixItInsertionLine;
1062 if (Hints.empty() || !DiagOpts->ShowFixits)
1063 return FixItInsertionLine;
1064 unsigned PrevHintEndCol = 0;
1068 if (!I->CodeToInsert.empty()) {
1071 std::pair<FileID, unsigned> HintLocInfo
1073 if (FID == HintLocInfo.first &&
1074 LineNo == SM.
getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1075 StringRef(I->CodeToInsert).find_first_of(
"\n\r") == StringRef::npos) {
1081 unsigned HintByteOffset
1085 assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1086 unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1095 if (HintCol < PrevHintEndCol)
1096 HintCol = PrevHintEndCol + 1;
1100 unsigned NewFixItLineSize = FixItInsertionLine.size() +
1101 (HintCol - PrevHintEndCol) + I->CodeToInsert.size();
1102 if (NewFixItLineSize > FixItInsertionLine.size())
1103 FixItInsertionLine.resize(NewFixItLineSize,
' ');
1105 std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1106 FixItInsertionLine.end() - I->CodeToInsert.size());
1114 expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1116 return FixItInsertionLine;
1126 void TextDiagnostic::emitSnippetAndCaret(
1129 assert(Loc.
isValid() &&
"must have a valid source location here");
1130 assert(Loc.
isFileID() &&
"must have a file location here");
1140 if (Loc ==
LastLoc && Ranges.empty() && Hints.empty() &&
1146 FileID FID = LocInfo.first;
1150 bool Invalid =
false;
1159 static const size_t MaxLineLengthToPrint = 4096;
1160 if (CaretColNo > MaxLineLengthToPrint)
1164 const unsigned MaxLines =
DiagOpts->SnippetLineLimit;
1165 std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
1172 for (
unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) {
1173 const char *BufStart = BufData.data();
1174 const char *BufEnd = BufStart + BufData.size();
1177 const char *LineStart =
1180 if (LineStart == BufEnd)
1184 const char *LineEnd = LineStart;
1185 while (*LineEnd !=
'\n' && *LineEnd !=
'\r' && LineEnd != BufEnd)
1190 if (
size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
1194 StringRef
Line(LineStart, LineEnd - LineStart);
1195 while (!Line.empty() && Line.back() ==
'\0' &&
1196 (LineNo != CaretLineNo || Line.size() > CaretColNo))
1197 Line = Line.drop_back();
1200 std::string SourceLine(Line.begin(), Line.end());
1203 const SourceColumnMap sourceColMap(SourceLine,
DiagOpts->TabStop);
1207 std::string CaretLine(sourceColMap.columns(),
' ');
1216 if (CaretLineNo == LineNo) {
1217 CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1);
1218 if (CaretLine.size() < CaretColNo + 1)
1219 CaretLine.resize(CaretColNo + 1,
' ');
1220 CaretLine[CaretColNo] =
'^';
1224 FID, LineNo, sourceColMap, Hints, SM,
DiagOpts.get());
1228 unsigned Columns =
DiagOpts->MessageLength;
1231 Columns, sourceColMap);
1238 SourceLine =
' ' + SourceLine;
1239 CaretLine =
' ' + CaretLine;
1243 while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] ==
' ')
1244 CaretLine.erase(CaretLine.end() - 1);
1247 emitSnippet(SourceLine);
1249 if (!CaretLine.empty()) {
1252 OS << CaretLine <<
'\n';
1257 if (!FixItInsertionLine.empty()) {
1263 OS << FixItInsertionLine <<
'\n';
1270 emitParseableFixits(Hints, SM);
1273 void TextDiagnostic::emitSnippet(StringRef line) {
1279 std::string to_print;
1280 bool print_reversed =
false;
1282 while (i<line.size()) {
1283 std::pair<SmallString<16>,
bool> res
1285 bool was_printable = res.second;
1287 if (
DiagOpts->ShowColors && was_printable == print_reversed) {
1296 print_reversed = !was_printable;
1297 to_print += res.first.str();
1300 if (print_reversed &&
DiagOpts->ShowColors)
1303 if (print_reversed &&
DiagOpts->ShowColors)
1311 if (!
DiagOpts->ShowParseableFixits)
1318 if (I->RemoveRange.isInvalid() ||
1319 I->RemoveRange.getBegin().isMacroID() ||
1320 I->RemoveRange.getEnd().isMacroID())
1333 if (I->RemoveRange.isTokenRange())
1349 OS.write_escaped(I->CodeToInsert);
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
Defines the clang::FileManager interface and associated types.
FullSourceLoc getExpansionLoc() const
Defines the SourceManager interface.
static enum raw_ostream::Colors fatalColor
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
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
FileManager & getFileManager() const
SourceLocation getBegin() const
static std::pair< SmallString< 16 >, bool > printableTextForNextCharacter(StringRef SourceLine, size_t *i, unsigned TabStop)
returns a printable representation of first item from input range
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.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
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 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...
void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, DiagOrStoredDiag D) override
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.
TextDiagnostic(raw_ostream &OS, const LangOptions &LangOpts, DiagnosticOptions *DiagOpts)
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length)
Skip over whitespace in the string, starting at the given index.
~TextDiagnostic() override
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override
unsigned getColumnNumber(bool *Invalid=nullptr) const
const DirectoryEntry * getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
Represents a character-granular source range.
const FileEntry * getFileEntry() const
bool isInvalid() const
Return true if this object is invalid or uninitialized.
std::pair< FileID, unsigned > getDecomposedLoc() const
Decompose the specified location into a raw FileID + Offset pair.
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 ...
const AnnotatedLine * Line
unsigned getLine() const
Return the presumed line number of this location.
unsigned getLineNumber(bool *Invalid=nullptr) const
static llvm::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.
const SourceManager & getManager() const
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef< CharSourceRange > Ranges) override
Print out the file/line/column information and include trace.
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Represents an unpacked "presumed" location which can be presented to the user.
static std::string buildFixItInsertionLine(FileID FID, unsigned LineNo, const SourceColumnMap &map, ArrayRef< FixItHint > Hints, const SourceManager &SM, const DiagnosticOptions *DiagOpts)
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i)
static enum raw_ostream::Colors warningColor
static enum raw_ostream::Colors noteColor
const char * getFilename() const
Return the presumed filename of this location.
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
unsigned getColumn() const
Return the presumed column number of this location.
Encodes a location in the source.
StringRef getName() const
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.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
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...
StringRef getBufferData(bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
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...
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
static void expandTabs(std::string &SourceLine, unsigned TabStop)
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
StringRef getCanonicalName(const DirectoryEntry *Dir)
Retrieve the canonical name for a given directory.
SourceLocation LastLoc
The location of the previous diagnostic if known.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, bool &Normal, bool Bold)
Add highlights to differences in template strings.
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...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getEnd() const
Cached information about one directory (either on disk or in the virtual file system).
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
Level
The level of the diagnostic, after it has been through mapping.
static enum raw_ostream::Colors remarkColor
A SourceLocation and its associated SourceManager.
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
static enum raw_ostream::Colors savedColor
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.