2007-06-07 17:34:54 +08:00
|
|
|
//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-06-07 17:34:54 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This diagnostic client prints out their diagnostic messages.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-03-02 14:16:29 +08:00
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
2007-06-07 17:34:54 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Lex/Lexer.h"
|
2008-11-19 14:56:25 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-11-19 14:51:40 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
#include <algorithm>
|
2007-06-07 17:34:54 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
void TextDiagnosticPrinter::
|
2009-01-27 15:57:44 +08:00
|
|
|
PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) {
|
|
|
|
if (Loc.isInvalid()) return;
|
2007-07-21 00:37:10 +08:00
|
|
|
|
2009-01-27 15:57:44 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
2007-07-21 00:37:10 +08:00
|
|
|
|
2007-06-07 17:34:54 +08:00
|
|
|
// Print out the other include frames first.
|
2009-01-27 15:57:44 +08:00
|
|
|
PrintIncludeStack(PLoc.getIncludeLoc(), SM);
|
2007-06-07 17:34:54 +08:00
|
|
|
|
2009-01-27 15:57:44 +08:00
|
|
|
OS << "In file included from " << PLoc.getFilename()
|
|
|
|
<< ':' << PLoc.getLine() << ":\n";
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
|
|
|
|
/// any characters in LineNo that intersect the SourceRange.
|
2007-12-12 05:27:55 +08:00
|
|
|
void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
|
2009-01-27 15:57:44 +08:00
|
|
|
const SourceManager &SM,
|
2009-01-17 16:45:21 +08:00
|
|
|
unsigned LineNo, FileID FID,
|
2008-08-10 03:58:22 +08:00
|
|
|
std::string &CaretLine,
|
2008-08-06 03:40:20 +08:00
|
|
|
const std::string &SourceLine) {
|
2008-08-10 03:58:22 +08:00
|
|
|
assert(CaretLine.size() == SourceLine.size() &&
|
|
|
|
"Expect a correspondence between source and caret line!");
|
2007-06-07 17:34:54 +08:00
|
|
|
if (!R.isValid()) return;
|
|
|
|
|
2009-01-27 15:57:44 +08:00
|
|
|
SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
|
|
|
|
SourceLocation End = SM.getInstantiationLoc(R.getEnd());
|
|
|
|
|
2009-02-17 13:19:10 +08:00
|
|
|
// If the End location and the start location are the same and are a macro
|
|
|
|
// location, then the range was something that came from a macro expansion
|
|
|
|
// or _Pragma. If this is an object-like macro, the best we can do is to
|
|
|
|
// highlight the range. If this is a function-like macro, we'd also like to
|
|
|
|
// highlight the arguments.
|
|
|
|
if (Begin == End && R.getEnd().isMacroID())
|
|
|
|
End = SM.getInstantiationRange(R.getEnd()).second;
|
|
|
|
|
2009-02-04 09:06:56 +08:00
|
|
|
unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
|
2009-01-27 15:57:44 +08:00
|
|
|
if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
|
2008-01-12 14:43:35 +08:00
|
|
|
return; // No intersection.
|
2007-06-07 17:34:54 +08:00
|
|
|
|
2009-02-04 09:06:56 +08:00
|
|
|
unsigned EndLineNo = SM.getInstantiationLineNumber(End);
|
2009-01-27 15:57:44 +08:00
|
|
|
if (EndLineNo < LineNo || SM.getFileID(End) != FID)
|
2008-01-12 14:43:35 +08:00
|
|
|
return; // No intersection.
|
2007-06-07 17:34:54 +08:00
|
|
|
|
|
|
|
// Compute the column number of the start.
|
|
|
|
unsigned StartColNo = 0;
|
|
|
|
if (StartLineNo == LineNo) {
|
2009-02-04 08:55:58 +08:00
|
|
|
StartColNo = SM.getInstantiationColumnNumber(Begin);
|
2007-06-07 17:34:54 +08:00
|
|
|
if (StartColNo) --StartColNo; // Zero base the col #.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pick the first non-whitespace column.
|
|
|
|
while (StartColNo < SourceLine.size() &&
|
|
|
|
(SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
|
|
|
|
++StartColNo;
|
|
|
|
|
|
|
|
// Compute the column number of the end.
|
2008-08-10 03:58:22 +08:00
|
|
|
unsigned EndColNo = CaretLine.size();
|
2007-06-07 17:34:54 +08:00
|
|
|
if (EndLineNo == LineNo) {
|
2009-02-04 08:55:58 +08:00
|
|
|
EndColNo = SM.getInstantiationColumnNumber(End);
|
2007-06-07 17:34:54 +08:00
|
|
|
if (EndColNo) {
|
|
|
|
--EndColNo; // Zero base the col #.
|
|
|
|
|
|
|
|
// Add in the length of the token, so that we cover multi-char tokens.
|
2009-04-15 07:22:57 +08:00
|
|
|
EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
|
2007-06-07 17:34:54 +08:00
|
|
|
} else {
|
2008-08-10 03:58:22 +08:00
|
|
|
EndColNo = CaretLine.size();
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pick the last non-whitespace column.
|
2008-08-06 03:40:20 +08:00
|
|
|
if (EndColNo <= SourceLine.size())
|
|
|
|
while (EndColNo-1 &&
|
|
|
|
(SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
|
|
|
|
--EndColNo;
|
|
|
|
else
|
|
|
|
EndColNo = SourceLine.size();
|
2007-06-07 17:34:54 +08:00
|
|
|
|
|
|
|
// Fill the range with ~'s.
|
|
|
|
assert(StartColNo <= EndColNo && "Invalid range!");
|
2008-08-06 03:40:20 +08:00
|
|
|
for (unsigned i = StartColNo; i < EndColNo; ++i)
|
2008-08-10 03:58:22 +08:00
|
|
|
CaretLine[i] = '~';
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
|
2009-02-20 08:18:51 +08:00
|
|
|
void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
|
2009-02-20 08:25:28 +08:00
|
|
|
SourceRange *Ranges,
|
2009-02-20 08:18:51 +08:00
|
|
|
unsigned NumRanges,
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
SourceManager &SM,
|
|
|
|
const CodeModificationHint *Hints,
|
|
|
|
unsigned NumHints) {
|
2009-02-17 16:44:50 +08:00
|
|
|
assert(!Loc.isInvalid() && "must have a valid source location here");
|
|
|
|
|
2009-02-17 15:54:55 +08:00
|
|
|
// We always emit diagnostics about the instantiation points, not the spelling
|
|
|
|
// points. This more closely correlates to what the user writes.
|
2009-02-17 16:44:50 +08:00
|
|
|
if (!Loc.isFileID()) {
|
2009-02-19 02:50:45 +08:00
|
|
|
SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
|
2009-02-20 08:18:51 +08:00
|
|
|
EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM);
|
2009-02-17 16:44:50 +08:00
|
|
|
|
2009-02-20 08:25:28 +08:00
|
|
|
// Map the location through the macro.
|
2009-02-17 16:44:50 +08:00
|
|
|
Loc = SM.getInstantiationLoc(SM.getImmediateSpellingLoc(Loc));
|
2009-02-20 08:25:28 +08:00
|
|
|
|
|
|
|
// Map the ranges.
|
|
|
|
for (unsigned i = 0; i != NumRanges; ++i) {
|
|
|
|
SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd();
|
|
|
|
if (S.isMacroID())
|
|
|
|
S = SM.getInstantiationLoc(SM.getImmediateSpellingLoc(S));
|
|
|
|
if (E.isMacroID())
|
|
|
|
E = SM.getInstantiationLoc(SM.getImmediateSpellingLoc(E));
|
|
|
|
Ranges[i] = SourceRange(S, E);
|
|
|
|
}
|
2009-02-17 16:44:50 +08:00
|
|
|
|
|
|
|
// Emit the file/line/column that this expansion came from.
|
|
|
|
OS << SM.getBufferName(Loc) << ':' << SM.getInstantiationLineNumber(Loc)
|
|
|
|
<< ':';
|
|
|
|
if (ShowColumn)
|
|
|
|
OS << SM.getInstantiationColumnNumber(Loc) << ':';
|
|
|
|
OS << " note: instantiated from:\n";
|
|
|
|
}
|
2009-02-17 15:51:53 +08:00
|
|
|
|
|
|
|
// Decompose the location into a FID/Offset pair.
|
|
|
|
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
|
|
|
|
FileID FID = LocInfo.first;
|
|
|
|
unsigned FileOffset = LocInfo.second;
|
|
|
|
|
|
|
|
// Get information about the buffer it points into.
|
|
|
|
std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID);
|
|
|
|
const char *BufStart = BufferInfo.first;
|
|
|
|
|
|
|
|
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
|
2009-02-17 15:38:37 +08:00
|
|
|
|
|
|
|
// Rewind from the current position to the start of the line.
|
2009-02-17 15:51:53 +08:00
|
|
|
const char *TokPtr = BufStart+FileOffset;
|
|
|
|
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
|
|
|
|
|
2009-02-17 15:38:37 +08:00
|
|
|
|
|
|
|
// Compute the line end. Scan forward from the error position to the end of
|
|
|
|
// the line.
|
2009-02-17 15:51:53 +08:00
|
|
|
const char *LineEnd = TokPtr;
|
2009-03-08 16:11:22 +08:00
|
|
|
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
|
2009-02-17 15:38:37 +08:00
|
|
|
++LineEnd;
|
|
|
|
|
|
|
|
// Copy the line of code into an std::string for ease of manipulation.
|
|
|
|
std::string SourceLine(LineStart, LineEnd);
|
|
|
|
|
|
|
|
// Create a line for the caret that is filled with spaces that is the same
|
|
|
|
// length as the line of source code.
|
|
|
|
std::string CaretLine(LineEnd-LineStart, ' ');
|
|
|
|
|
|
|
|
// Highlight all of the characters covered by Ranges with ~ characters.
|
2009-02-20 08:18:51 +08:00
|
|
|
if (NumRanges) {
|
2009-02-17 15:51:53 +08:00
|
|
|
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
|
|
|
|
|
2009-02-20 08:18:51 +08:00
|
|
|
for (unsigned i = 0, e = NumRanges; i != e; ++i)
|
|
|
|
HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
|
2009-02-17 15:51:53 +08:00
|
|
|
}
|
2009-02-17 15:38:37 +08:00
|
|
|
|
|
|
|
// Next, insert the caret itself.
|
|
|
|
if (ColNo-1 < CaretLine.size())
|
|
|
|
CaretLine[ColNo-1] = '^';
|
|
|
|
else
|
|
|
|
CaretLine.push_back('^');
|
|
|
|
|
|
|
|
// Scan the source line, looking for tabs. If we find any, manually expand
|
|
|
|
// them to 8 characters and update the CaretLine to match.
|
|
|
|
for (unsigned i = 0; i != SourceLine.size(); ++i) {
|
|
|
|
if (SourceLine[i] != '\t') continue;
|
|
|
|
|
|
|
|
// Replace this tab with at least one space.
|
|
|
|
SourceLine[i] = ' ';
|
|
|
|
|
|
|
|
// Compute the number of spaces we need to insert.
|
|
|
|
unsigned NumSpaces = ((i+8)&~7) - (i+1);
|
|
|
|
assert(NumSpaces < 8 && "Invalid computation of space amt");
|
|
|
|
|
|
|
|
// Insert spaces into the SourceLine.
|
|
|
|
SourceLine.insert(i+1, NumSpaces, ' ');
|
|
|
|
|
|
|
|
// Insert spaces or ~'s into CaretLine.
|
|
|
|
CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, remove any blank spaces from the end of CaretLine.
|
|
|
|
while (CaretLine[CaretLine.size()-1] == ' ')
|
|
|
|
CaretLine.erase(CaretLine.end()-1);
|
|
|
|
|
|
|
|
// Emit what we have computed.
|
|
|
|
OS << SourceLine << '\n';
|
|
|
|
OS << CaretLine << '\n';
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
|
|
|
|
if (NumHints) {
|
|
|
|
std::string InsertionLine;
|
|
|
|
for (const CodeModificationHint *Hint = Hints,
|
|
|
|
*LastHint = Hints + NumHints;
|
|
|
|
Hint != LastHint; ++Hint) {
|
|
|
|
if (Hint->InsertionLoc.isValid()) {
|
|
|
|
// We have an insertion hint. Determine whether the inserted
|
|
|
|
// code is on the same line as the caret.
|
|
|
|
std::pair<FileID, unsigned> HintLocInfo
|
2009-03-03 04:58:48 +08:00
|
|
|
= SM.getDecomposedInstantiationLoc(Hint->InsertionLoc);
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) ==
|
|
|
|
SM.getLineNumber(FID, FileOffset)) {
|
|
|
|
// Insert the new code into the line just below the code
|
|
|
|
// that the user wrote.
|
|
|
|
unsigned HintColNo
|
|
|
|
= SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
|
|
|
|
unsigned LastColumnModified
|
|
|
|
= HintColNo - 1 + Hint->CodeToInsert.size();
|
|
|
|
if (LastColumnModified > InsertionLine.size())
|
|
|
|
InsertionLine.resize(LastColumnModified, ' ');
|
|
|
|
std::copy(Hint->CodeToInsert.begin(), Hint->CodeToInsert.end(),
|
|
|
|
InsertionLine.begin() + HintColNo - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!InsertionLine.empty())
|
|
|
|
OS << InsertionLine << '\n';
|
|
|
|
}
|
2009-02-17 15:38:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
This reworks some of the Diagnostic interfaces a bit to change how diagnostics
are formed. In particular, a diagnostic with all its strings and ranges is now
packaged up and sent to DiagnosticClients as a DiagnosticInfo instead of as a
ton of random stuff. This has the benefit of simplifying the interface, making
it more extensible, and allowing us to do more checking for things like access
past the end of the various arrays passed in.
In addition to introducing DiagnosticInfo, this also substantially changes how
Diagnostic::Report works. Instead of being passed in all of the info required
to issue a diagnostic, Report now takes only the required info (a location and
ID) and returns a fresh DiagnosticInfo *by value*. The caller is then free to
stuff strings and ranges into the DiagnosticInfo with the << operator. When
the dtor runs on the DiagnosticInfo object (which should happen at the end of
the statement), the diagnostic is actually emitted with all of the accumulated
information. This is a somewhat tricky dance, but it means that the
accumulated DiagnosticInfo is allowed to keep pointers to other expression
temporaries without those pointers getting invalidated.
This is just the minimal change to get this stuff working, but this will allow
us to eliminate the zillions of variant "Diag" methods scattered throughout
(e.g.) sema. For example, instead of calling:
Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
SourceRange(BuiltinLoc, RParenLoc));
We will soon be able to just do:
Diag(BuiltinLoc, diag::err_overload_no_match)
<< typeNames << SourceRange(BuiltinLoc, RParenLoc));
This scales better to support arbitrary types being passed in (not just
strings) in a type-safe way. Go operator overloading?!
llvm-svn: 59502
2008-11-18 15:04:44 +08:00
|
|
|
void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
|
|
|
|
const DiagnosticInfo &Info) {
|
2009-01-27 15:57:44 +08:00
|
|
|
// If the location is specified, print out a file/line/col and include trace
|
|
|
|
// if enabled.
|
|
|
|
if (Info.getLocation().isValid()) {
|
2009-01-29 04:47:47 +08:00
|
|
|
const SourceManager &SM = Info.getLocation().getManager();
|
2009-01-27 15:57:44 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
|
|
|
|
unsigned LineNo = PLoc.getLine();
|
2007-06-07 17:34:54 +08:00
|
|
|
|
|
|
|
// First, if this diagnostic is not in the main file, print out the
|
|
|
|
// "included from" lines.
|
2009-01-27 15:57:44 +08:00
|
|
|
if (LastWarningLoc != PLoc.getIncludeLoc()) {
|
|
|
|
LastWarningLoc = PLoc.getIncludeLoc();
|
|
|
|
PrintIncludeStack(LastWarningLoc, SM);
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
|
2009-01-27 15:57:44 +08:00
|
|
|
// Compute the column number.
|
2009-01-31 01:41:53 +08:00
|
|
|
if (ShowLocation) {
|
|
|
|
OS << PLoc.getFilename() << ':' << LineNo << ':';
|
2009-02-17 15:34:34 +08:00
|
|
|
if (ShowColumn)
|
|
|
|
if (unsigned ColNo = PLoc.getColumn())
|
|
|
|
OS << ColNo << ':';
|
2009-03-13 09:08:23 +08:00
|
|
|
|
|
|
|
if (PrintRangeInfo && Info.getNumRanges()) {
|
|
|
|
FileID CaretFileID =
|
|
|
|
SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
|
|
|
|
bool PrintedRange = false;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) {
|
|
|
|
SourceLocation B = Info.getRange(i).getBegin();
|
|
|
|
SourceLocation E = Info.getRange(i).getEnd();
|
|
|
|
std::pair<FileID, unsigned> BInfo=SM.getDecomposedInstantiationLoc(B);
|
|
|
|
|
|
|
|
E = SM.getInstantiationLoc(E);
|
|
|
|
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
|
|
|
|
|
|
|
|
// If the start or end of the range is in another file, just discard
|
|
|
|
// it.
|
|
|
|
if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Add in the length of the token, so that we cover multi-char tokens.
|
2009-04-15 07:22:57 +08:00
|
|
|
unsigned TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
|
2009-03-13 09:08:23 +08:00
|
|
|
|
|
|
|
OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
|
|
|
|
<< SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
|
|
|
|
<< SM.getLineNumber(EInfo.first, EInfo.second) << ':'
|
|
|
|
<< (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) << '}';
|
|
|
|
PrintedRange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PrintedRange)
|
|
|
|
OS << ':';
|
|
|
|
}
|
2009-01-31 01:41:53 +08:00
|
|
|
OS << ' ';
|
|
|
|
}
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (Level) {
|
2009-02-06 11:57:44 +08:00
|
|
|
case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
|
2008-04-18 02:06:57 +08:00
|
|
|
case Diagnostic::Note: OS << "note: "; break;
|
|
|
|
case Diagnostic::Warning: OS << "warning: "; break;
|
|
|
|
case Diagnostic::Error: OS << "error: "; break;
|
2009-02-06 11:57:44 +08:00
|
|
|
case Diagnostic::Fatal: OS << "fatal error: "; break;
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
|
|
|
|
2008-11-19 14:51:40 +08:00
|
|
|
llvm::SmallString<100> OutStr;
|
|
|
|
Info.FormatDiagnostic(OutStr);
|
|
|
|
OS.write(OutStr.begin(), OutStr.size());
|
|
|
|
OS << '\n';
|
2007-06-07 17:34:54 +08:00
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
// If caret diagnostics are enabled and we have location, we want to
|
|
|
|
// emit the caret. However, we only do this if the location moved
|
|
|
|
// from the last diagnostic, if the last diagnostic was a note that
|
|
|
|
// was part of a different warning or error diagnostic, or if the
|
|
|
|
// diagnostic has ranges. We don't want to emit the same caret
|
|
|
|
// multiple times if one loc has multiple diagnostics.
|
2009-01-27 15:57:44 +08:00
|
|
|
if (CaretDiagnostics && Info.getLocation().isValid() &&
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
|
2009-03-11 04:44:00 +08:00
|
|
|
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
Info.getNumCodeModificationHints())) {
|
2008-02-09 06:06:17 +08:00
|
|
|
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
|
2009-01-27 15:57:44 +08:00
|
|
|
LastLoc = Info.getLocation();
|
2009-03-11 04:44:00 +08:00
|
|
|
LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
|
2009-01-27 15:57:44 +08:00
|
|
|
|
2009-02-20 08:18:51 +08:00
|
|
|
// Get the ranges into a local array we can hack on.
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
SourceRange Ranges[20];
|
2009-02-20 08:18:51 +08:00
|
|
|
unsigned NumRanges = Info.getNumRanges();
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
assert(NumRanges < 20 && "Out of space");
|
2009-02-20 08:18:51 +08:00
|
|
|
for (unsigned i = 0; i != NumRanges; ++i)
|
|
|
|
Ranges[i] = Info.getRange(i);
|
|
|
|
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
unsigned NumHints = Info.getNumCodeModificationHints();
|
|
|
|
for (unsigned idx = 0; idx < NumHints; ++idx) {
|
|
|
|
const CodeModificationHint &Hint = Info.getCodeModificationHint(idx);
|
|
|
|
if (Hint.RemoveRange.isValid()) {
|
|
|
|
assert(NumRanges < 20 && "Out of space");
|
|
|
|
Ranges[NumRanges++] = Hint.RemoveRange;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(),
|
|
|
|
Info.getCodeModificationHints(),
|
|
|
|
Info.getNumCodeModificationHints());
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|
2008-11-19 14:56:25 +08:00
|
|
|
|
|
|
|
OS.flush();
|
2007-06-07 17:34:54 +08:00
|
|
|
}
|