[clang-tools-extra] [clang-tidy] Add check hicpp-ignored-remove-result (PR #73119)

Björn Svensson via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 23 00:50:30 PST 2023


https://github.com/bjosv updated https://github.com/llvm/llvm-project/pull/73119

>From 91cf412abcfd231ab399c3e44c6a9bc14109537c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <bjorn.a.svensson at est.tech>
Date: Tue, 21 Nov 2023 23:30:07 +0100
Subject: [PATCH 1/2] [clang-tidy] Add check hicpp-ignored-remove-result

This check implements the rule 17.5.1 of the HICPP standard
which states:

- Do not ignore the result of std::remove, std::remove_if or std::unique

  The mutating algorithms std::remove, std::remove_if and both overloads of
  std::unique operate by swapping or moving elements of the range they are
  operating over. On completion, they return an iterator to the last valid element.
  In the majority of cases the correct behavior is to use this result as the
  first operand in a call to std::erase.

Suppressing issues by casting to `void` is enabled by default, but can be
disabled by setting `AllowCastToVoid` option to `false`.
---
 .../clang-tidy/hicpp/HICPPTidyModule.cpp      | 20 ++++++++
 clang-tools-extra/docs/ReleaseNotes.rst       |  4 ++
 .../checks/hicpp/ignored-remove-result.rst    | 20 ++++++++
 .../docs/clang-tidy/checks/list.rst           |  1 +
 .../checkers/hicpp/ignored-remove-result.cpp  | 47 +++++++++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp

diff --git a/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp b/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp
index 3749796877120ed..09d15ccab3f29c2 100644
--- a/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/hicpp/HICPPTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "../bugprone/UndelegatedConstructorCheck.h"
+#include "../bugprone/UnusedReturnValueCheck.h"
 #include "../bugprone/UseAfterMoveCheck.h"
 #include "../cppcoreguidelines/AvoidGotoCheck.h"
 #include "../cppcoreguidelines/NoMallocCheck.h"
@@ -41,6 +42,15 @@
 #include "NoAssemblerCheck.h"
 #include "SignedBitwiseCheck.h"
 
+namespace {
+
+// Checked functions for hicpp-ignored-remove-result.
+const llvm::StringRef CheckedFunctions = "::std::remove;"
+                                         "::std::remove_if;"
+                                         "::std::unique;";
+
+} // namespace
+
 namespace clang::tidy {
 namespace hicpp {
 
@@ -64,6 +74,8 @@ class HICPPModule : public ClangTidyModule {
         "hicpp-explicit-conversions");
     CheckFactories.registerCheck<readability::FunctionSizeCheck>(
         "hicpp-function-size");
+    CheckFactories.registerCheck<bugprone::UnusedReturnValueCheck>(
+        "hicpp-ignored-remove-result");
     CheckFactories.registerCheck<readability::NamedParameterCheck>(
         "hicpp-named-parameter");
     CheckFactories.registerCheck<bugprone::UseAfterMoveCheck>(
@@ -107,6 +119,14 @@ class HICPPModule : public ClangTidyModule {
     CheckFactories.registerCheck<cppcoreguidelines::ProTypeVarargCheck>(
         "hicpp-vararg");
   }
+
+  ClangTidyOptions getModuleOptions() override {
+    ClangTidyOptions Options;
+    ClangTidyOptions::OptionMap &Opts = Options.CheckOptions;
+    Opts["hicpp-ignored-remove-result.CheckedFunctions"] = CheckedFunctions;
+    Opts["hicpp-ignored-remove-result.AllowCastToVoid"] = "true";
+    return Options;
+  }
 };
 
 // Register the HICPPModule using this statically initialized variable.
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 6d5f49dc0625451..c940025df1c63cd 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -205,6 +205,10 @@ New check aliases
   <clang-tidy/checks/cppcoreguidelines/macro-to-enum>` to :doc:`modernize-macro-to-enum
   <clang-tidy/checks/modernize/macro-to-enum>` was added.
 
+- New alias :doc:`hicpp-ignored-remove-result
+  <clang-tidy/checks/hicpp/ignored-remove-result>` to :doc:`bugprone-unused-return-value
+  <clang-tidy/checks/bugprone/unused-return-value>` was added.
+
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
new file mode 100644
index 000000000000000..4b6188b886db124
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - hicpp-ignored-remove-result
+
+hicpp-ignored-remove-result
+===========================
+
+Ensure that the result of ``std::remove``, ``std::remove_if`` and ``std::unique``
+are not ignored according to
+`rule 17.5.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/standard-library>`_.
+
+The mutating algorithms ``std::remove``, ``std::remove_if`` and both overloads
+of ``std::unique`` operate by swapping or moving elements of the range they are
+operating over. On completion, they return an iterator to the last valid
+element. In the majority of cases the correct behavior is to use this result as
+the first operand in a call to std::erase.
+
+This check is an alias of check :doc:`bugprone-unused-return-value <../bugprone/unused-return-value>`
+with a fixed set of functions.
+
+Suppressing issues by casting to ``void`` is enabled by default and can be
+disabled by setting `AllowCastToVoid` option to ``false``.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 6f987ba1672e3f2..417513b2f2aaa3a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -226,6 +226,7 @@ Clang-Tidy Checks
    :doc:`google-runtime-operator <google/runtime-operator>`,
    :doc:`google-upgrade-googletest-case <google/upgrade-googletest-case>`, "Yes"
    :doc:`hicpp-exception-baseclass <hicpp/exception-baseclass>`,
+   :doc:`hicpp-ignored-remove-result <hicpp/ignored-remove-result>`,
    :doc:`hicpp-multiway-paths-covered <hicpp/multiway-paths-covered>`,
    :doc:`hicpp-no-assembler <hicpp/no-assembler>`,
    :doc:`hicpp-signed-bitwise <hicpp/signed-bitwise>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp b/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp
new file mode 100644
index 000000000000000..86deb96216a687a
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/hicpp/ignored-remove-result.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s hicpp-ignored-remove-result %t
+
+namespace std {
+
+template <typename ForwardIt, typename T>
+ForwardIt remove(ForwardIt, ForwardIt, const T &);
+
+template <typename ForwardIt, typename UnaryPredicate>
+ForwardIt remove_if(ForwardIt, ForwardIt, UnaryPredicate);
+
+template <typename ForwardIt>
+ForwardIt unique(ForwardIt, ForwardIt);
+
+template <class InputIt, class T>
+InputIt find(InputIt, InputIt, const T&);
+
+} // namespace std
+
+void warning() {
+  std::remove(nullptr, nullptr, 1);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
+
+  std::remove_if(nullptr, nullptr, nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
+
+  std::unique(nullptr, nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors
+  // CHECK-MESSAGES: [[@LINE-2]]:3: note: cast the expression to void to silence this warning
+}
+
+void noWarning() {
+
+  auto RemoveRetval = std::remove(nullptr, nullptr, 1);
+
+  auto RemoveIfRetval = std::remove_if(nullptr, nullptr, nullptr);
+
+  auto UniqueRetval = std::unique(nullptr, nullptr);
+
+  // cast to void should allow ignoring the return value
+  (void)std::remove(nullptr, nullptr, 1);
+
+  // no warning on std::find since the checker overrides
+  // bugprone-unused-return-value's checked functions.
+  std::find(nullptr, nullptr, 1);
+}

>From 46179bdf862a531f45b44f03de0803cec089e9b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <bjorn.a.svensson at est.tech>
Date: Thu, 23 Nov 2023 09:49:00 +0100
Subject: [PATCH 2/2] fixup: missing double back-ticks in docs

---
 .../docs/clang-tidy/checks/hicpp/ignored-remove-result.rst      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
index 4b6188b886db124..ff1d25d31f52c7b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst
@@ -11,7 +11,7 @@ The mutating algorithms ``std::remove``, ``std::remove_if`` and both overloads
 of ``std::unique`` operate by swapping or moving elements of the range they are
 operating over. On completion, they return an iterator to the last valid
 element. In the majority of cases the correct behavior is to use this result as
-the first operand in a call to std::erase.
+the first operand in a call to ``std::erase``.
 
 This check is an alias of check :doc:`bugprone-unused-return-value <../bugprone/unused-return-value>`
 with a fixed set of functions.



More information about the cfe-commits mailing list