forked from OSchip/llvm-project
Improve diagnostics range reporting.
Summary: If we have some range information coming from clang diagnostic, promote that one even if it doesn't contain diagnostic location inside. Reviewers: sammccall, ioeric Reviewed By: ioeric Subscribers: ilya-biryukov, jkorous, arphaman, cfe-commits Differential Revision: https://reviews.llvm.org/D52544 llvm-svn: 343197
This commit is contained in:
parent
fb5a5d09fe
commit
2e3f1f13b5
|
@ -52,17 +52,28 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
|
|||
auto &M = D.getSourceManager();
|
||||
auto Loc = M.getFileLoc(D.getLocation());
|
||||
// Accept the first range that contains the location.
|
||||
llvm::Optional<Range> FallbackRange;
|
||||
for (const auto &CR : D.getRanges()) {
|
||||
auto R = Lexer::makeFileCharRange(CR, M, L);
|
||||
if (locationInRange(Loc, R, M))
|
||||
return halfOpenToRange(M, R);
|
||||
// If there are no ranges that contain the location report the first range.
|
||||
if (!FallbackRange)
|
||||
FallbackRange = halfOpenToRange(M, R);
|
||||
}
|
||||
// The range may be given as a fixit hint instead.
|
||||
for (const auto &F : D.getFixItHints()) {
|
||||
auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
|
||||
if (locationInRange(Loc, R, M))
|
||||
return halfOpenToRange(M, R);
|
||||
// If there's a fixit that performs insertion, it has zero-width. Therefore
|
||||
// it can't contain the location of the diag, but it might be possible that
|
||||
// this should be reported as range. For example missing semicolon.
|
||||
if (!FallbackRange && R.getBegin() == R.getEnd())
|
||||
FallbackRange = halfOpenToRange(M, R);
|
||||
}
|
||||
if (FallbackRange)
|
||||
return *FallbackRange;
|
||||
// If no suitable range is found, just use the token at the location.
|
||||
auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
|
||||
if (!R.isValid()) // Fall back to location only, let the editor deal with it.
|
||||
|
|
|
@ -79,8 +79,9 @@ TEST(DiagnosticsTest, DiagnosticRanges) {
|
|||
int main() {
|
||||
$typo[[go\
|
||||
o]]();
|
||||
foo()$semicolon[[]]
|
||||
foo()$semicolon[[]]//with comments
|
||||
$unk[[unknown]]();
|
||||
double bar = $type[["foo"]];
|
||||
}
|
||||
)cpp");
|
||||
EXPECT_THAT(
|
||||
|
@ -93,11 +94,16 @@ o]]();
|
|||
Fix(Test.range("typo"), "foo", "change 'go\\ o' to 'foo'")),
|
||||
// This is a pretty normal range.
|
||||
WithNote(Diag(Test.range("decl"), "'foo' declared here"))),
|
||||
// This range is zero-width, and at the end of a line.
|
||||
// This range is zero-width and insertion. Therefore make sure we are
|
||||
// not expanding it into other tokens. Since we are not going to
|
||||
// replace those.
|
||||
AllOf(Diag(Test.range("semicolon"), "expected ';' after expression"),
|
||||
WithFix(Fix(Test.range("semicolon"), ";", "insert ';'"))),
|
||||
// This range isn't provided by clang, we expand to the token.
|
||||
Diag(Test.range("unk"), "use of undeclared identifier 'unknown'")));
|
||||
Diag(Test.range("unk"), "use of undeclared identifier 'unknown'"),
|
||||
Diag(Test.range("type"),
|
||||
"cannot initialize a variable of type 'double' with an lvalue "
|
||||
"of type 'const char [4]'")));
|
||||
}
|
||||
|
||||
TEST(DiagnosticsTest, FlagsMatter) {
|
||||
|
|
Loading…
Reference in New Issue