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;
866 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
871 unsigned TokSize = 0;
877 << BF.getLineNumber() <<
':' << BF.getColumnNumber() <<
'-' 891 OS <<
"In file included from " << PLoc.
getFilename() <<
':' 894 OS <<
"In included file:\n";
898 StringRef ModuleName) {
900 OS <<
"In module '" << ModuleName <<
"' imported from " 903 OS <<
"In module '" << ModuleName <<
"':\n";
908 StringRef ModuleName) {
910 OS <<
"While building module '" << ModuleName <<
"' imported from " 913 OS <<
"While building module '" << ModuleName <<
"':\n";
933 static std::pair<unsigned, unsigned>
934 maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B,
937 unsigned Slack = MaxRange - (A.second - A.first + 1);
942 unsigned Min =
std::min(A.first, B.first);
943 unsigned Max =
std::max(A.second, B.second);
944 if (Max - Min + 1 <= MaxRange)
949 if ((B.first > A.first && B.first - A.first + 1 > MaxRange) ||
950 (B.second < A.second && A.second - B.second + 1 > MaxRange))
959 A.second =
std::min(A.second + (Slack + 1) / 2, Max);
960 Slack = MaxRange - (A.second - A.first + 1);
961 A.first =
std::max(Min + Slack, A.first) - Slack;
962 A.second =
std::min(A.first + MaxRange - 1, Max);
968 unsigned LineNo,
FileID FID,
969 const SourceColumnMap &map,
970 std::string &CaretLine,
979 if (StartLineNo > LineNo || SM.
getFileID(Begin) != FID)
983 if (EndLineNo < LineNo || SM.
getFileID(End) != FID)
987 unsigned StartColNo = 0;
988 if (StartLineNo == LineNo) {
990 if (StartColNo) --StartColNo;
994 unsigned EndColNo = map.getSourceLine().size();
995 if (EndLineNo == LineNo) {
1005 EndColNo = CaretLine.size();
1009 assert(StartColNo <= EndColNo &&
"Invalid range!");
1014 while (StartColNo < map.getSourceLine().size() &&
1015 (map.getSourceLine()[StartColNo] ==
' ' ||
1016 map.getSourceLine()[StartColNo] ==
'\t'))
1017 StartColNo = map.startOfNextColumn(StartColNo);
1020 if (EndColNo > map.getSourceLine().size())
1021 EndColNo = map.getSourceLine().size();
1023 (map.getSourceLine()[EndColNo-1] ==
' ' ||
1024 map.getSourceLine()[EndColNo-1] ==
'\t'))
1025 EndColNo = map.startOfPreviousColumn(EndColNo);
1030 if (StartColNo > EndColNo) {
1031 assert(StartLineNo != EndLineNo &&
"trying to highlight whitespace");
1032 StartColNo = EndColNo;
1036 assert(StartColNo <= map.getSourceLine().size() &&
"Invalid range!");
1037 assert(EndColNo <= map.getSourceLine().size() &&
"Invalid range!");
1040 StartColNo = map.byteToContainingColumn(StartColNo);
1041 EndColNo = map.byteToContainingColumn(EndColNo);
1043 assert(StartColNo <= EndColNo &&
"Invalid range!");
1044 if (CaretLine.size() < EndColNo)
1045 CaretLine.resize(EndColNo,
' ');
1046 std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,
'~');
1051 const SourceColumnMap &map,
1055 std::string FixItInsertionLine;
1056 if (Hints.empty() || !DiagOpts->ShowFixits)
1057 return FixItInsertionLine;
1058 unsigned PrevHintEndCol = 0;
1062 if (!I->CodeToInsert.empty()) {
1065 std::pair<FileID, unsigned> HintLocInfo
1067 if (FID == HintLocInfo.first &&
1068 LineNo == SM.
getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1069 StringRef(I->CodeToInsert).find_first_of(
"\n\r") == StringRef::npos) {
1075 unsigned HintByteOffset
1079 assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1080 unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1089 if (HintCol < PrevHintEndCol)
1090 HintCol = PrevHintEndCol + 1;
1094 unsigned NewFixItLineSize = FixItInsertionLine.size() +
1095 (HintCol - PrevHintEndCol) + I->CodeToInsert.size();
1096 if (NewFixItLineSize > FixItInsertionLine.size())
1097 FixItInsertionLine.resize(NewFixItLineSize,
' ');
1099 std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1100 FixItInsertionLine.end() - I->CodeToInsert.size());
1108 expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1110 return FixItInsertionLine;
1120 void TextDiagnostic::emitSnippetAndCaret(
1123 assert(Loc.
isValid() &&
"must have a valid source location here");
1124 assert(Loc.
isFileID() &&
"must have a file location here");
1134 if (Loc ==
LastLoc && Ranges.empty() && Hints.empty() &&
1140 FileID FID = LocInfo.first;
1144 bool Invalid =
false;
1153 static const size_t MaxLineLengthToPrint = 4096;
1154 if (CaretColNo > MaxLineLengthToPrint)
1158 const unsigned MaxLines =
DiagOpts->SnippetLineLimit;
1159 std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo};
1166 for (
unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) {
1167 const char *BufStart = BufData.data();
1168 const char *BufEnd = BufStart + BufData.size();
1171 const char *LineStart =
1174 if (LineStart == BufEnd)
1178 const char *LineEnd = LineStart;
1179 while (*LineEnd !=
'\n' && *LineEnd !=
'\r' && LineEnd != BufEnd)
1184 if (
size_t(LineEnd - LineStart) > MaxLineLengthToPrint)
1188 StringRef
Line(LineStart, LineEnd - LineStart);
1189 while (!Line.empty() && Line.back() ==
'\0' &&
1190 (LineNo != CaretLineNo || Line.size() > CaretColNo))
1191 Line = Line.drop_back();
1194 std::string SourceLine(Line.begin(), Line.end());
1197 const SourceColumnMap sourceColMap(SourceLine,
DiagOpts->TabStop);
1201 std::string CaretLine(sourceColMap.columns(),
' ');
1210 if (CaretLineNo == LineNo) {
1211 CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1);
1212 if (CaretLine.size() < CaretColNo + 1)
1213 CaretLine.resize(CaretColNo + 1,
' ');
1214 CaretLine[CaretColNo] =
'^';
1218 FID, LineNo, sourceColMap, Hints, SM,
DiagOpts.get());
1222 unsigned Columns =
DiagOpts->MessageLength;
1225 Columns, sourceColMap);
1232 SourceLine =
' ' + SourceLine;
1233 CaretLine =
' ' + CaretLine;
1237 while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] ==
' ')
1238 CaretLine.erase(CaretLine.end() - 1);
1241 emitSnippet(SourceLine);
1243 if (!CaretLine.empty()) {
1246 OS << CaretLine <<
'\n';
1251 if (!FixItInsertionLine.empty()) {
1257 OS << FixItInsertionLine <<
'\n';
1264 emitParseableFixits(Hints, SM);
1267 void TextDiagnostic::emitSnippet(StringRef line) {
1273 std::string to_print;
1274 bool print_reversed =
false;
1276 while (i<line.size()) {
1277 std::pair<SmallString<16>,
bool> res
1279 bool was_printable = res.second;
1281 if (
DiagOpts->ShowColors && was_printable == print_reversed) {
1290 print_reversed = !was_printable;
1291 to_print += res.first.str();
1294 if (print_reversed &&
DiagOpts->ShowColors)
1297 if (print_reversed &&
DiagOpts->ShowColors)
1305 if (!
DiagOpts->ShowParseableFixits)
1312 if (I->RemoveRange.isInvalid() ||
1313 I->RemoveRange.getBegin().isMacroID() ||
1314 I->RemoveRange.getEnd().isMacroID())
1327 if (I->RemoveRange.isTokenRange())
1343 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
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
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
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.
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...
Cached information about one directory (either on disk or in the virtual file system).
Level
The level of the diagnostic, after it has been through mapping.
static enum raw_ostream::Colors remarkColor
A SourceLocation and its associated SourceManager.
__DEVICE__ int max(int __a, int __b)
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
__DEVICE__ int min(int __a, int __b)
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.