Daniel599 created this revision.
Daniel599 added reviewers: alexfh, hokein.
Daniel599 added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, Charusso, xazax.hun.
Herald added a project: clang.

when both a check and its alias are enabled, we should only take the fixes of 
one of them and not both.
This patch fixes bug 45577
https://bugs.llvm.org/show_bug.cgi?id=45577


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80753

Files:
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
  
clang-tools-extra/test/clang-tidy/infrastructure/duplicate-fixes-of-alias-checkers.cpp

Index: clang-tools-extra/test/clang-tidy/infrastructure/duplicate-fixes-of-alias-checkers.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/infrastructure/duplicate-fixes-of-alias-checkers.cpp
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init,hicpp-member-init,modernize-use-emplace,hicpp-use-emplace %t
+
+#include <stdio.h>
+namespace std {
+template <typename>
+class initializer_list {
+public:
+  initializer_list() noexcept {}
+};
+
+template <typename T>
+class vector {
+public:
+  vector() = default;
+  vector(initializer_list<T>) {}
+
+  void push_back(const T &) {}
+  void push_back(T &&) {}
+
+  template <typename... Args>
+  void emplace_back(Args &&... args){};
+  ~vector();
+};
+} // namespace std
+
+class Foo {
+public:
+  Foo() : _num1(0)
+  // CHECK-MESSAGES: warning: constructor does not initialize these fields: _num2 [cppcoreguidelines-pro-type-member-init]
+  // CHECK-MESSAGES: warning: constructor does not initialize these fields: _num2 [hicpp-member-init]
+  // CHECK-MESSAGES: note: this fix will not be applied because an alias checker has already provided it, see 'cppcoreguidelines-pro-type-member-init'
+  {
+    printf("some code so it won't be a trival ctor\n");
+  }
+
+  int use_the_members() const {
+    return _num1 + _num2;
+  }
+
+private:
+  int _num1;
+  int _num2;
+  // CHECK-FIXES: _num2{};
+};
+
+int should_use_emplace(std::vector<Foo> &v) {
+  v.push_back(Foo());
+  // CHECK-FIXES: v.emplace_back();
+  // CHECK-MESSAGES: warning: use emplace_back instead of push_back [hicpp-use-emplace]
+  // CHECK-MESSAGES: warning: use emplace_back instead of push_back [modernize-use-emplace]
+  // CHECK-MESSAGES: note: this fix will not be applied because an alias checker has already provided it, see 'hicpp-use-emplace'
+}
\ No newline at end of file
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -246,6 +246,7 @@
 private:
   void finalizeLastError();
   void removeIncompatibleErrors();
+  void removeDuplicatedFixesOfAliasCheckers();
 
   /// Returns the \c HeaderFilter constructed for the options set in the
   /// context.
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -634,6 +634,8 @@
     std::tuple<unsigned, EventType, int, int, unsigned> Priority;
   };
 
+  removeDuplicatedFixesOfAliasCheckers();
+
   // Compute error sizes.
   std::vector<int> Sizes;
   std::vector<
@@ -728,3 +730,34 @@
     removeIncompatibleErrors();
   return std::move(Errors);
 }
+
+namespace {
+struct LessClangTidyErrorWithoutDiagnosticName {
+  bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const {
+    const tooling::DiagnosticMessage &M1 = LHS->Message;
+    const tooling::DiagnosticMessage &M2 = RHS->Message;
+
+    return std::tie(M1.FilePath, M1.FileOffset, M1.Message) <
+           std::tie(M2.FilePath, M2.FileOffset, M2.Message);
+  }
+};
+} // end anonymous namespace
+
+void ClangTidyDiagnosticConsumer::removeDuplicatedFixesOfAliasCheckers() {
+  std::set<ClangTidyError *, LessClangTidyErrorWithoutDiagnosticName>
+      UniqueErrors;
+  for (auto &Error : Errors) {
+    auto Inserted = UniqueErrors.insert(&Error);
+
+    // If we already have an error like this, just with the different
+    // DiagnosticName, Remove its Fix since we don't need same fix twice
+    if (!Inserted.second && !Error.Message.Fix.empty()) {
+      Error.Message.Fix.clear();
+      std::string FixAlreadyExists =
+          "this fix will not be applied because an alias checker has already "
+          "provided it, see '" +
+          (*Inserted.first)->DiagnosticName + "'";
+      Error.Notes.emplace_back(std::move(FixAlreadyExists));
+    }
+  }
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to