summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-13 12:37:46 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-13 12:37:46 +0000
commit9ad41b82f62c94f822190536e6b537ceca1cef8a (patch)
tree4749f74252ae76cf097bf33d9bcceaac246f8c3c
parent6bebbaceefa0e150b5c56265b43880029f98193f (diff)
Merging r367303:
------------------------------------------------------------------------ r367303 | kadircet | 2019-07-30 12:26:51 +0200 (Tue, 30 Jul 2019) | 15 lines [clangd] Ignore diags from builtin files Summary: This fixes a case where we show diagnostics on arbitrary lines, in an internal codebase. Open for ideas on unittesting this. Reviewers: ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64863 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/branches/release_90@368682 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--clangd/Diagnostics.cpp36
-rw-r--r--clangd/Diagnostics.h2
-rw-r--r--clangd/unittests/DiagnosticsTests.cpp14
3 files changed, 37 insertions, 15 deletions
diff --git a/clangd/Diagnostics.cpp b/clangd/Diagnostics.cpp
index 53192711..919182d5 100644
--- a/clangd/Diagnostics.cpp
+++ b/clangd/Diagnostics.cpp
@@ -20,6 +20,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Capacity.h"
@@ -107,8 +108,13 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
return halfOpenToRange(M, R);
}
-void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
+// Returns whether the \p D is modified.
+bool adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
const LangOptions &LangOpts) {
+ // We only report diagnostics with at least error severity from headers.
+ if (D.Severity < DiagnosticsEngine::Level::Error)
+ return false;
+
const SourceLocation &DiagLoc = Info.getLocation();
const SourceManager &SM = Info.getSourceManager();
SourceLocation IncludeInMainFile;
@@ -119,13 +125,14 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
IncludeLocation = GetIncludeLoc(IncludeLocation))
IncludeInMainFile = IncludeLocation;
if (IncludeInMainFile.isInvalid())
- return;
+ return false;
// Update diag to point at include inside main file.
D.File = SM.getFileEntryForID(SM.getMainFileID())->getName().str();
D.Range.start = sourceLocToPosition(SM, IncludeInMainFile);
D.Range.end = sourceLocToPosition(
SM, Lexer::getLocForEndOfToken(IncludeInMainFile, 0, SM, LangOpts));
+ D.InsideMainFile = true;
// Add a note that will point to real diagnostic.
const auto *FE = SM.getFileEntryForID(SM.getFileID(DiagLoc));
@@ -138,6 +145,7 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info,
// Update message to mention original file.
D.Message = llvm::Twine("in included file: ", D.Message).str();
+ return true;
}
bool isInsideMainFile(const clang::Diagnostic &D) {
@@ -465,6 +473,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
}
bool InsideMainFile = isInsideMainFile(Info);
+ SourceManager &SM = Info.getSourceManager();
auto FillDiagBase = [&](DiagBase &D) {
D.Range = diagnosticRange(Info, *LangOpts);
@@ -472,8 +481,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Info.FormatDiagnostic(Message);
D.Message = Message.str();
D.InsideMainFile = InsideMainFile;
- D.File = Info.getSourceManager().getFilename(Info.getLocation());
- auto &SM = Info.getSourceManager();
+ D.File = SM.getFilename(Info.getLocation());
D.AbsFile = getCanonicalPath(
SM.getFileEntryForID(SM.getFileID(Info.getLocation())), SM);
D.Severity = DiagLevel;
@@ -496,10 +504,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
if (FixIt.RemoveRange.getBegin().isMacroID() ||
FixIt.RemoveRange.getEnd().isMacroID())
return false;
- if (!isInsideMainFile(FixIt.RemoveRange.getBegin(),
- Info.getSourceManager()))
+ if (!isInsideMainFile(FixIt.RemoveRange.getBegin(), SM))
return false;
- Edits.push_back(toTextEdit(FixIt, Info.getSourceManager(), *LangOpts));
+ Edits.push_back(toTextEdit(FixIt, SM, *LangOpts));
}
llvm::SmallString<64> Message;
@@ -507,8 +514,8 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
if (SyntheticMessage && Info.getNumFixItHints() == 1) {
const auto &FixIt = Info.getFixItHint(0);
bool Invalid = false;
- llvm::StringRef Remove = Lexer::getSourceText(
- FixIt.RemoveRange, Info.getSourceManager(), *LangOpts, &Invalid);
+ llvm::StringRef Remove =
+ Lexer::getSourceText(FixIt.RemoveRange, SM, *LangOpts, &Invalid);
llvm::StringRef Insert = FixIt.CodeToInsert;
if (!Invalid) {
llvm::raw_svector_ostream M(Message);
@@ -553,7 +560,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
LastDiag = Diag();
LastDiag->ID = Info.getID();
FillDiagBase(*LastDiag);
- adjustDiagFromHeader(*LastDiag, Info, *LangOpts);
+ LastDiagWasAdjusted = false;
+ if (!InsideMainFile)
+ LastDiagWasAdjusted = adjustDiagFromHeader(*LastDiag, Info, *LangOpts);
if (!Info.getFixItHints().empty())
AddFix(true /* try to invent a message instead of repeating the diag */);
@@ -595,10 +604,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
void StoreDiags::flushLastDiag() {
if (!LastDiag)
return;
- // Only keeps diagnostics inside main file or the first one coming from a
- // header.
- if (mentionsMainFile(*LastDiag) ||
- (LastDiag->Severity >= DiagnosticsEngine::Level::Error &&
+ if (mentionsMainFile(*LastDiag) &&
+ (!LastDiagWasAdjusted ||
+ // Only report the first diagnostic coming from each particular header.
IncludeLinesWithErrors.insert(LastDiag->Range.start.line).second)) {
Output.push_back(std::move(*LastDiag));
} else {
diff --git a/clangd/Diagnostics.h b/clangd/Diagnostics.h
index b6cfe895..6d848ce2 100644
--- a/clangd/Diagnostics.h
+++ b/clangd/Diagnostics.h
@@ -145,6 +145,8 @@ private:
std::vector<Diag> Output;
llvm::Optional<LangOptions> LangOpts;
llvm::Optional<Diag> LastDiag;
+ /// Set iff adjustDiagFromHeader resulted in changes to LastDiag.
+ bool LastDiagWasAdjusted = false;
llvm::DenseSet<int> IncludeLinesWithErrors;
bool LastPrimaryDiagnosticWasSuppressed = false;
};
diff --git a/clangd/unittests/DiagnosticsTests.cpp b/clangd/unittests/DiagnosticsTests.cpp
index 7cf0e277..c80dafee 100644
--- a/clangd/unittests/DiagnosticsTests.cpp
+++ b/clangd/unittests/DiagnosticsTests.cpp
@@ -928,7 +928,6 @@ TEST(DiagsInHeaders, OnlyErrorOrFatal) {
int x = 5/0;)cpp");
TestTU TU = TestTU::withCode(Main.code());
TU.AdditionalFiles = {{"a.h", Header.code()}};
- auto diags = TU.build().getDiagnostics();
EXPECT_THAT(TU.build().getDiagnostics(),
UnorderedElementsAre(AllOf(
Diag(Main.range(), "in included file: C++ requires "
@@ -936,6 +935,19 @@ TEST(DiagsInHeaders, OnlyErrorOrFatal) {
WithNote(Diag(Header.range(), "error occurred here")))));
}
+TEST(IgnoreDiags, FromNonWrittenSources) {
+ Annotations Main(R"cpp(
+ #include [["a.h"]]
+ void foo() {})cpp");
+ Annotations Header(R"cpp(
+ int x = 5/0;
+ int b = [[FOO]];)cpp");
+ TestTU TU = TestTU::withCode(Main.code());
+ TU.AdditionalFiles = {{"a.h", Header.code()}};
+ TU.ExtraArgs = {"-DFOO=NOOO"};
+ EXPECT_THAT(TU.build().getDiagnostics(), UnorderedElementsAre());
+}
+
} // namespace
} // namespace clangd