kadircet created this revision.
kadircet added a reviewer: sammccall.
Herald added subscribers: usaxena95, arphaman.
kadircet requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

It is not great to list diag ids by hand, but I don't see any other
solution unless diagnostics are annotated with these explicitly, which is a
bigger change in clang and I am not sure if would be worth it.

Diagnostics handled by this patch is by no means exhaustive, there might be
other checks that don't mention "unused"/"deprecated" in their names. But it
feels like this should be enough to catch common diagnostics and can be extended
over time.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107040

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp

Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -65,6 +65,11 @@
   return Field(&Diag::Notes, UnorderedElementsAre(NoteMatcher1, NoteMatcher2));
 }
 
+::testing::Matcher<const Diag &>
+WithTag(::testing::Matcher<DiagnosticTag> TagMatcher) {
+  return Field(&Diag::Tags, Contains(TagMatcher));
+}
+
 MATCHER_P2(Diag, Range, Message,
            "Diag at " + llvm::to_string(Range) + " = [" + Message + "]") {
   return arg.Range == Range && arg.Message == Message;
@@ -665,6 +670,7 @@
 
   clangd::Diag D;
   D.ID = clang::diag::err_undeclared_var_use;
+  D.Tags = {DiagnosticTag::Unnecessary};
   D.Name = "undeclared_var_use";
   D.Source = clangd::Diag::Clang;
   D.Message = "something terrible happened";
@@ -710,6 +716,7 @@
 
 ../foo/baz/header.h:10:11:
 note: declared somewhere in the header file)";
+  MainLSP.tags = {DiagnosticTag::Unnecessary};
 
   clangd::Diagnostic NoteInMainLSP;
   NoteInMainLSP.range = NoteInMain.Range;
@@ -1419,6 +1426,24 @@
         testing::Contains(Diag(Code.range(), "no newline at end of file")));
   }
 }
+
+TEST(Diagnostics, Tags) {
+  TestTU TU;
+  TU.ExtraArgs = {"-Wunused", "-Wdeprecated"};
+  Annotations Test(R"cpp(
+  void bar() __attribute__((deprecated));
+  void foo() {
+    int $unused[[x]];
+    $deprecated[[bar]]();
+  })cpp");
+  TU.Code = Test.code().str();
+  EXPECT_THAT(*TU.build().getDiagnostics(),
+              UnorderedElementsAre(
+                  AllOf(Diag(Test.range("unused"), "unused variable 'x'"),
+                        WithTag(DiagnosticTag::Unnecessary)),
+                  AllOf(Diag(Test.range("deprecated"), "'bar' is deprecated"),
+                        WithTag(DiagnosticTag::Deprecated))));
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -822,6 +822,8 @@
   /// Clients are allowed to rendered diagnostics with this tag strike through.
   Deprecated = 2,
 };
+llvm::json::Value toJSON(DiagnosticTag Tag);
+
 struct CodeAction;
 struct Diagnostic {
   /// The range at which the message applies.
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -1452,5 +1452,6 @@
   return OS;
 }
 
+llvm::json::Value toJSON(DiagnosticTag Tag) { return static_cast<int>(Tag); }
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Diagnostics.cpp
===================================================================
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -36,6 +36,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cstddef>
+#include <vector>
 
 namespace clang {
 namespace clangd {
@@ -326,24 +327,56 @@
   return capitalize(std::move(Result));
 }
 
-llvm::SmallVector<DiagnosticTag, 1>
-getDiagnosticTags(const clang::Diagnostic &D) {
-  llvm::SmallVector<DiagnosticTag, 1> Result;
-  if ((diag::warn_deprecated <= D.getID() &&
-       D.getID() <= diag::warn_deprecated_volatile_structured_binding) ||
-      D.getID() == diag::warn_access_decl_deprecated ||
-      D.getID() == diag::warn_atl_uuid_deprecated ||
-      D.getID() == diag::warn_opencl_attr_deprecated_ignored ||
-      D.getID() == diag::warn_property_method_deprecated ||
-      D.getID() == diag::warn_vector_mode_deprecated) {
+std::vector<DiagnosticTag> getDiagnosticTags(unsigned DiagID) {
+  static const llvm::DenseSet<unsigned> DeprecatedDiags = {
+      diag::warn_access_decl_deprecated,
+      diag::warn_atl_uuid_deprecated,
+      diag::warn_deprecated,
+      diag::warn_deprecated_altivec_src_compat,
+      diag::warn_deprecated_comma_subscript,
+      diag::warn_deprecated_compound_assign_volatile,
+      diag::warn_deprecated_copy,
+      diag::warn_deprecated_copy_with_dtor,
+      diag::warn_deprecated_copy_with_user_provided_copy,
+      diag::warn_deprecated_copy_with_user_provided_dtor,
+      diag::warn_deprecated_def,
+      diag::warn_deprecated_increment_decrement_volatile,
+      diag::warn_deprecated_message,
+      diag::warn_deprecated_redundant_constexpr_static_def,
+      diag::warn_deprecated_register,
+      diag::warn_deprecated_simple_assign_volatile,
+      diag::warn_deprecated_string_literal_conversion,
+      diag::warn_deprecated_this_capture,
+      diag::warn_deprecated_volatile_param,
+      diag::warn_deprecated_volatile_return,
+      diag::warn_deprecated_volatile_structured_binding,
+      diag::warn_opencl_attr_deprecated_ignored,
+      diag::warn_property_method_deprecated,
+      diag::warn_vector_mode_deprecated,
+  };
+  static const llvm::DenseSet<unsigned> UnusedDiags = {
+      diag::warn_opencl_attr_deprecated_ignored,
+      diag::warn_pragma_attribute_unused,
+      diag::warn_unused_but_set_parameter,
+      diag::warn_unused_but_set_variable,
+      diag::warn_unused_comparison,
+      diag::warn_unused_const_variable,
+      diag::warn_unused_exception_param,
+      diag::warn_unused_function,
+      diag::warn_unused_label,
+      diag::warn_unused_lambda_capture,
+      diag::warn_unused_local_typedef,
+      diag::warn_unused_member_function,
+      diag::warn_unused_parameter,
+      diag::warn_unused_private_field,
+      diag::warn_unused_property_backing_ivar,
+      diag::warn_unused_template,
+      diag::warn_unused_variable,
+  };
+  std::vector<DiagnosticTag> Result;
+  if (DeprecatedDiags.contains(DiagID)) {
     Result.push_back(DiagnosticTag::Deprecated);
-  } else if (
-      // Warnings about unused function results can be semantically important,
-      // e.g. an llvm::Error that needs to be checked.
-      D.getID() != diag::warn_unused_call &&
-      ((diag::warn_unused_but_set_parameter <= D.getID() &&
-        D.getID() <= diag::warn_unused_volatile) ||
-       D.getID() == diag::warn_pragma_attribute_unused)) {
+  } else if (UnusedDiags.contains(DiagID)) {
     Result.push_back(DiagnosticTag::Unnecessary);
   }
   return Result;
@@ -485,6 +518,7 @@
       Main.relatedInformation->push_back(std::move(RelInfo));
     }
   }
+  Main.tags = D.Tags;
   OutFn(std::move(Main), D.Fixes);
 
   // If we didn't emit the notes as relatedLocations, emit separate diagnostics
@@ -541,6 +575,7 @@
         Diag.Name = std::string(Name);
       }
       Diag.Source = Diag::Clang;
+      Diag.Tags = getDiagnosticTags(Diag.ID);
       continue;
     }
     if (Tidy != nullptr) {
@@ -548,6 +583,7 @@
       if (!TidyDiag.empty()) {
         Diag.Name = std::move(TidyDiag);
         Diag.Source = Diag::ClangTidy;
+        // FIXME: Set diagnostic tags based on check names.
         // clang-tidy bakes the name into diagnostic messages. Strip it out.
         // It would be much nicer to make clang-tidy not do this.
         auto CleanMessage = [&](std::string &Msg) {
@@ -764,7 +800,6 @@
     if (LastDiag->Severity == DiagnosticsEngine::Ignored)
       return;
 
-    LastDiag->Tags = getDiagnosticTags(Info);
     LastDiagLoc.emplace(Info.getLocation(), Info.getSourceManager());
     LastDiagOriginallyError = OriginallyError;
     if (!Info.getFixItHints().empty())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to