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" 24 using namespace clang;
38 static const enum raw_ostream::Colors
errorColor = raw_ostream::RED;
39 static const enum raw_ostream::Colors
fatalColor = raw_ostream::RED;
42 raw_ostream::SAVEDCOLOR;
46 bool &Normal,
bool Bold) {
49 OS << Str.slice(0, Pos);
50 if (Pos == StringRef::npos)
53 Str = Str.substr(Pos + 1);
71 if (SourceLine[--i]==
'\t')
97 static std::pair<SmallString<16>,
bool>
100 assert(i &&
"i must not be null");
101 assert(*i<SourceLine.size() &&
"must point to a valid index");
103 if (SourceLine[*i]==
'\t') {
105 "Invalid -ftabstop value");
107 unsigned NumSpaces = TabStop - col%TabStop;
108 assert(0 < NumSpaces && NumSpaces <= TabStop
109 &&
"Invalid computation of space amt");
113 expandedTab.assign(NumSpaces,
' ');
114 return std::make_pair(expandedTab,
true);
117 unsigned char const *begin, *end;
118 begin =
reinterpret_cast<unsigned char const *
>(&*(SourceLine.begin() + *i));
119 end = begin + (SourceLine.size() - *i);
121 if (llvm::isLegalUTF8Sequence(begin, end)) {
123 llvm::UTF32 *cptr = &c;
124 unsigned char const *original_begin = begin;
125 unsigned char const *cp_end =
126 begin + llvm::getNumBytesForUTF8(SourceLine[*i]);
128 llvm::ConversionResult res = llvm::ConvertUTF8toUTF32(
129 &begin, cp_end, &cptr, cptr + 1, llvm::strictConversion);
131 assert(llvm::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 llvm::find_if(CaretLine, [](
char c) {
return c <
' ' ||
'~' < c; }));
340 unsigned CaretStart = 0, CaretEnd = CaretLine.size();
341 for (; CaretStart != CaretEnd; ++CaretStart)
345 for (; CaretEnd != CaretStart; --CaretEnd)
354 if (!FixItInsertionLine.empty()) {
355 unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
356 for (; FixItStart != FixItEnd; ++FixItStart)
360 for (; FixItEnd != FixItStart; --FixItEnd)
367 unsigned FixItStartCol = FixItStart;
371 CaretStart =
std::min(FixItStartCol, CaretStart);
372 CaretEnd =
std::max(FixItEndCol, CaretEnd);
378 while (static_cast<int>(CaretEnd) < map.columns() &&
379 -1 == map.columnToByte(CaretEnd))
382 assert((static_cast<int>(CaretStart) > map.columns() ||
383 -1!=map.columnToByte(CaretStart)) &&
384 "CaretStart must not point to a column in the middle of a source" 386 assert((static_cast<int>(CaretEnd) > map.columns() ||
387 -1!=map.columnToByte(CaretEnd)) &&
388 "CaretEnd must not point to a column in the middle of a source line" 396 unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
398 unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
401 unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
402 - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
404 char const *front_ellipse =
" ...";
405 char const *front_space =
" ";
406 char const *back_ellipse =
"...";
407 unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
409 unsigned TargetColumns = Columns;
412 if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
413 TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
415 while (SourceStart>0 || SourceEnd<SourceLine.size()) {
416 bool ExpandedRegion =
false;
419 unsigned NewStart = map.startOfPreviousColumn(SourceStart);
425 NewStart = map.startOfPreviousColumn(NewStart);
429 unsigned Prev = map.startOfPreviousColumn(NewStart);
435 assert(map.byteToColumn(NewStart) != -1);
436 unsigned NewColumns = map.byteToColumn(SourceEnd) -
437 map.byteToColumn(NewStart);
438 if (NewColumns <= TargetColumns) {
439 SourceStart = NewStart;
440 ExpandedRegion =
true;
444 if (SourceEnd<SourceLine.size()) {
445 unsigned NewEnd = map.startOfNextColumn(SourceEnd);
450 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
451 NewEnd = map.startOfNextColumn(NewEnd);
454 while (NewEnd < SourceLine.size() &&
isWhitespace(SourceLine[NewEnd]))
455 NewEnd = map.startOfNextColumn(NewEnd);
457 assert(map.byteToColumn(NewEnd) != -1);
458 unsigned NewColumns = map.byteToColumn(NewEnd) -
459 map.byteToColumn(SourceStart);
460 if (NewColumns <= TargetColumns) {
462 ExpandedRegion =
true;
470 CaretStart = map.byteToColumn(SourceStart);
471 CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
477 assert(CaretStart!=(
unsigned)-1 && CaretEnd!=(
unsigned)-1 &&
478 SourceStart!=(
unsigned)-1 && SourceEnd!=(
unsigned)-1);
479 assert(SourceStart <= SourceEnd);
480 assert(CaretStart <= CaretEnd);
482 unsigned BackColumnsRemoved
483 = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
484 unsigned FrontColumnsRemoved = CaretStart;
485 unsigned ColumnsKept = CaretEnd-CaretStart;
488 assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
492 if (BackColumnsRemoved > strlen(back_ellipse))
493 SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
496 if (FrontColumnsRemoved+ColumnsKept <= Columns)
500 if (FrontColumnsRemoved > strlen(front_ellipse)) {
501 SourceLine.replace(0, SourceStart, front_ellipse);
502 CaretLine.replace(0, CaretStart, front_space);
503 if (!FixItInsertionLine.empty())
504 FixItInsertionLine.replace(0, CaretStart, front_space);
528 case '\'':
return '\'';
529 case '`':
return '\'';
530 case '"':
return '"';
531 case '(':
return ')';
532 case '[':
return ']';
533 case '{':
return '}';
546 unsigned Length,
unsigned Column,
548 assert(Start < Str.size() &&
"Invalid start position!");
549 unsigned End = Start + 1;
552 if (End == Str.size())
568 PunctuationEndStack.push_back(EndPunct);
569 while (End < Length && !PunctuationEndStack.empty()) {
570 if (Str[End] == PunctuationEndStack.back())
571 PunctuationEndStack.pop_back();
573 PunctuationEndStack.push_back(SubEndPunct);
582 unsigned PunctWordLength = End - Start;
584 Column + PunctWordLength <= Columns ||
587 PunctWordLength < Columns/3)
594 return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
617 const unsigned Length =
std::min(Str.find(
'\n'), Str.size());
618 bool TextNormal =
true;
622 IndentStr.assign(Indentation,
' ');
623 bool Wrapped =
false;
624 for (
unsigned WordStart = 0, WordEnd; WordStart < Length;
625 WordStart = WordEnd) {
628 if (WordStart == Length)
632 WordEnd =
findEndOfWord(WordStart, Str, Length, Column, Columns);
635 unsigned WordLength = WordEnd - WordStart;
636 if (Column + WordLength < Columns) {
644 Column += WordLength;
651 OS.write(&IndentStr[0], Indentation);
654 Column = Indentation + WordLength;
661 assert(TextNormal &&
"Text highlighted at end of diagnostic message.");
677 uint64_t StartOfLocationInfo = OS.tell();
691 Message, OS.tell() - StartOfLocationInfo,
699 bool CLFallbackMode) {
704 llvm_unreachable(
"Invalid diagnostic type");
715 llvm_unreachable(
"Invalid diagnostic type");
740 unsigned CurrentColumn,
741 unsigned Columns,
bool ShowColors) {
743 if (ShowColors && !IsSupplemental) {
755 assert(Normal &&
"Formatting should have returned to normal");
785 TmpFilename = (*File)->getName();
786 llvm::sys::fs::make_absolute(TmpFilename);
787 llvm::sys::path::native(TmpFilename);
788 llvm::sys::path::remove_dots(TmpFilename,
true);
789 Filename = StringRef(TmpFilename.data(), TmpFilename.size());
820 unsigned LineNo = PLoc.
getLine();
841 if (
LangOpts.MSCompatibilityVersion &&
855 if (
LangOpts.MSCompatibilityVersion &&
862 if (
DiagOpts->ShowSourceRanges && !Ranges.empty()) {
864 bool PrintedRange =
false;
870 if (!RI->isValid())
continue;
883 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
888 unsigned TokSize = 0;
894 << BF.getLineNumber() <<
':' << BF.getColumnNumber() <<
'-' 908 OS <<
"In file included from " << PLoc.
getFilename() <<
':' 911 OS <<
"In included file:\n";
915 StringRef ModuleName) {
917 OS <<
"In module '" << ModuleName <<
"' imported from " 920 OS <<
"In module '" << ModuleName <<
"':\n";
925 StringRef ModuleName) {
927 OS <<
"While building module '" << ModuleName <<
"' imported from " 930 OS <<
"While building module '" << ModuleName <<
"':\n";
950 static std::pair<unsigned, unsigned>
951 maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
954 unsigned Slack = MaxRange - (A.second - A.first + 1);
959 unsigned Min =
std::min(A.first, B.first);
960 unsigned Max =
std::max(A.second, B.second);
961 if (Max - Min + 1 <= MaxRange)
966 if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||
967 (B.second < A.second && A.second - B.second + 1 > MaxRange))
976 A.second =
std::min(A.second + (Slack + 1) / 2, Max);
977 Slack = MaxRange - (A.second - A.first + 1);
978 A.first =
std::max(Min + Slack, A.first) - Slack;
979 A.second =
std::min(A.first + MaxRange - 1, Max);
985 unsigned LineNo,
FileID FID,
986 const SourceColumnMap &map,
987 std::string &CaretLine,
996 if (StartLineNo > LineNo || SM.
getFileID(Begin) != FID)
1000 if (EndLineNo < LineNo || SM.
getFileID(End) != FID)
1004 unsigned StartColNo = 0;
1005 if (StartLineNo == LineNo) {
1007 if (StartColNo) --StartColNo;
1011 unsigned EndColNo = map.getSourceLine().size();
1012 if (EndLineNo == LineNo) {
1022 EndColNo = CaretLine.size();
1026 assert(StartColNo <= EndColNo &&
"Invalid range!");
1031 while (StartColNo < map.getSourceLine().size() &&
1032 (map.getSourceLine()[StartColNo] ==
' ' ||
1033 map.getSourceLine()[StartColNo] ==
'\t'))
1034 StartColNo = map.startOfNextColumn(StartColNo);
1037 if (EndColNo > map.getSourceLine().size())
1038 EndColNo = map.getSourceLine().size();
1040 (map.getSourceLine()[EndColNo-1] ==
' ' ||
1041 map.getSourceLine()[EndColNo-1] ==
'\t'))
1042 EndColNo = map.startOfPreviousColumn(EndColNo);
1047 if (StartColNo > EndColNo) {
1048 assert(StartLineNo != EndLineNo &&
"trying to highlight whitespace");
1049 StartColNo = EndColNo;
1053 assert(StartColNo <= map.getSourceLine().size() &&
"Invalid range!");
1054 assert(EndColNo <= map.getSourceLine().size() &&
"Invalid range!");
1057 StartColNo = map.byteToContainingColumn(StartColNo);
1058 EndColNo = map.byteToContainingColumn(EndColNo);
1060 assert(StartColNo <= EndColNo &&
"Invalid range!");
1061 if (CaretLine.size() < EndColNo)
1062 CaretLine.resize(EndColNo,
' ');
1063 std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,
'~');
1068 const SourceColumnMap &map,
1072 std::string FixItInsertionLine;
1073 if (Hints.empty() || !DiagOpts->ShowFixits)
1074 return FixItInsertionLine;
1075 unsigned PrevHintEndCol = 0;
1079 if (!I->CodeToInsert.empty()) {
1082 std::pair<FileID, unsigned> HintLocInfo
1084 if (FID == HintLocInfo.first &&
1085 LineNo == SM.
getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1086 StringRef(I->CodeToInsert).find_first_of(
"\n\r") == StringRef::npos) {
1092 unsigned HintByteOffset
1096 assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1097 unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1106 if (HintCol < PrevHintEndCol)
1107 HintCol = PrevHintEndCol + 1;
1111 unsigned NewFixItLineSize = FixItInsertionLine.size() +
1112 (HintCol - PrevHintEndCol) + I->CodeToInsert.size();
1113 if (NewFixItLineSize > FixItInsertionLine.size())
1114 FixItInsertionLine.resize(NewFixItLineSize,
' ');
1116 std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1117 FixItInsertionLine.end() - I->CodeToInsert.size());
1125 expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1127 return FixItInsertionLine;
1137 void TextDiagnostic::emitSnippetAndCaret(
1140 assert(Loc.
isValid() &&
"must have a valid source location here");
1141 assert(Loc.
isFileID() &&
"must have a file location here");
1151 if (Loc ==
LastLoc && Ranges.empty() && Hints.empty() &&
1157 FileID FID = LocInfo.first;
1161 bool Invalid =
false;
1170 static const size_t MaxLineLengthToPrint = 4096;
1171 if (CaretColNo > MaxLineLengthToPrint)
1175 const unsigned MaxLines =
DiagOpts->SnippetLineLimit;
1176 std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
1183 for (
unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) {
1184 const char *BufStart = BufData.data();
1185 const char *BufEnd = BufStart + BufData.size();
1188 const char *LineStart =
1191 if (LineStart == BufEnd)
1195 const char *LineEnd = LineStart;
1196 while (*LineEnd !=
'\n' && *LineEnd !=
'\r' && LineEnd != BufEnd)
1201 if (
size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
1205 StringRef
Line(LineStart, LineEnd - LineStart);
1206 while (!Line.empty() && Line.back() ==
'\0' &&
1207 (LineNo != CaretLineNo || Line.size() > CaretColNo))
1208 Line = Line.drop_back();
1211 std::string SourceLine(Line.begin(), Line.end());
1214 const SourceColumnMap sourceColMap(SourceLine,
DiagOpts->TabStop);
1218 std::string CaretLine(sourceColMap.columns(),
' ');
1227 if (CaretLineNo == LineNo) {
1228 CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1);
1229 if (CaretLine.size() < CaretColNo + 1)
1230 CaretLine.resize(CaretColNo + 1,
' ');
1231 CaretLine[CaretColNo] =
'^';
1235 FID, LineNo, sourceColMap, Hints, SM,
DiagOpts.get());
1239 unsigned Columns =
DiagOpts->MessageLength;
1242 Columns, sourceColMap);
1249 SourceLine =
' ' + SourceLine;
1250 CaretLine =
' ' + CaretLine;
1254 while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] ==
' ')
1255 CaretLine.erase(CaretLine.end() - 1);
1258 emitSnippet(SourceLine);
1260 if (!CaretLine.empty()) {
1263 OS << CaretLine <<
'\n';
1268 if (!FixItInsertionLine.empty()) {
1274 OS << FixItInsertionLine <<
'\n';
1281 emitParseableFixits(Hints, SM);
1284 void TextDiagnostic::emitSnippet(StringRef line) {
1290 std::string to_print;
1291 bool print_reversed =
false;
1293 while (i<line.size()) {
1294 std::pair<SmallString<16>,
bool> res
1296 bool was_printable = res.second;
1298 if (
DiagOpts->ShowColors && was_printable == print_reversed) {
1307 print_reversed = !was_printable;
1308 to_print += res.first.str();
1311 if (print_reversed &&
DiagOpts->ShowColors)
1314 if (print_reversed &&
DiagOpts->ShowColors)
1322 if (!
DiagOpts->ShowParseableFixits)
1329 if (I->RemoveRange.isInvalid() ||
1330 I->RemoveRange.getBegin().isMacroID() ||
1331 I->RemoveRange.getEnd().isMacroID())
1344 if (I->RemoveRange.isTokenRange())
1360 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.
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
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
__DEVICE__ int max(int __a, int __b)
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...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
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
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
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.
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.
llvm::ErrorOr< const FileEntry * > getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getEnd() const
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
Level
The level of the diagnostic, after it has been through mapping.
__DEVICE__ int min(int __a, int __b)
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.