[clang-tools-extra] [clang-tidy] Add new check `readability-use-numeric-limits` (PR #127430)

Katherine Whitlock via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 28 08:35:00 PST 2025


https://github.com/stellar-aria updated https://github.com/llvm/llvm-project/pull/127430

>From ba0eef9808b42b01e356cd5c87745f7477e07c68 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Sun, 16 Feb 2025 22:45:06 -0500
Subject: [PATCH 01/10] [clang-tidy] Add new check
 `readability-use-numeric-limits`

---
 .../clang-tidy/readability/CMakeLists.txt     |   1 +
 .../readability/ReadabilityTidyModule.cpp     |   3 +
 .../readability/UseNumericLimitsCheck.cpp     | 135 ++++++++++++++++++
 .../readability/UseNumericLimitsCheck.h       |  41 ++++++
 clang-tools-extra/docs/ReleaseNotes.rst       |   5 +
 .../docs/clang-tidy/checks/list.rst           |   1 +
 .../checks/readability/use-numeric-limits.rst |  22 +++
 .../readability/use-numeric-limits.cpp        |  85 +++++++++++
 8 files changed, 293 insertions(+)
 create mode 100644 clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 8f303c51e1b0d..e06f68bdda73f 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -57,6 +57,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
   UniqueptrDeleteReleaseCheck.cpp
   UppercaseLiteralSuffixCheck.cpp
   UseAnyOfAllOfCheck.cpp
+  UseNumericLimitsCheck.cpp
   UseStdMinMaxCheck.cpp
 
   LINK_LIBS
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index d61c0ba39658e..054083d25952a 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -60,6 +60,7 @@
 #include "UniqueptrDeleteReleaseCheck.h"
 #include "UppercaseLiteralSuffixCheck.h"
 #include "UseAnyOfAllOfCheck.h"
+#include "UseNumericLimitsCheck.h"
 #include "UseStdMinMaxCheck.h"
 
 namespace clang::tidy {
@@ -170,6 +171,8 @@ class ReadabilityModule : public ClangTidyModule {
         "readability-uppercase-literal-suffix");
     CheckFactories.registerCheck<UseAnyOfAllOfCheck>(
         "readability-use-anyofallof");
+    CheckFactories.registerCheck<UseNumericLimitsCheck>(
+        "readability-use-numeric-limits");
     CheckFactories.registerCheck<UseStdMinMaxCheck>(
         "readability-use-std-min-max");
   }
diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
new file mode 100644
index 0000000000000..b26ae008cbdd5
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -0,0 +1,135 @@
+//===--- UseNumericLimitsCheck.cpp - clang-tidy ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseNumericLimitsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Preprocessor.h"
+#include <cmath>
+#include <limits>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+UseNumericLimitsCheck::UseNumericLimitsCheck(StringRef Name,
+                                             ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      SignedConstants{
+          {std::numeric_limits<int8_t>::min(),
+           "std::numeric_limits<int8_t>::min()"},
+          {std::numeric_limits<int8_t>::max(),
+           "std::numeric_limits<int8_t>::max()"},
+          {std::numeric_limits<int16_t>::min(),
+           "std::numeric_limits<int16_t>::min()"},
+          {std::numeric_limits<int16_t>::max(),
+           "std::numeric_limits<int16_t>::max()"},
+          {std::numeric_limits<int32_t>::min(),
+           "std::numeric_limits<int32_t>::min()"},
+          {std::numeric_limits<int32_t>::max(),
+           "std::numeric_limits<int32_t>::max()"},
+          {std::numeric_limits<int64_t>::min(),
+           "std::numeric_limits<int64_t>::min()"},
+          {std::numeric_limits<int64_t>::max(),
+           "std::numeric_limits<int64_t>::max()"},
+
+      },
+      UnsignedConstants{
+          {std::numeric_limits<uint8_t>::max(),
+           "std::numeric_limits<uint8_t>::max()"},
+          {std::numeric_limits<uint16_t>::max(),
+           "std::numeric_limits<uint16_t>::max()"},
+          {std::numeric_limits<uint32_t>::max(),
+           "std::numeric_limits<uint32_t>::max()"},
+          {std::numeric_limits<uint64_t>::max(),
+           "std::numeric_limits<uint64_t>::max()"},
+      },
+      Inserter(Options.getLocalOrGlobal("IncludeStyle",
+                                        utils::IncludeSorter::IS_LLVM),
+               areDiagsSelfContained()) {}
+
+void UseNumericLimitsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      expr(anyOf(unaryOperator(hasOperatorName("-"),
+                               hasUnaryOperand(integerLiteral().bind(
+                                   "negative-integer-literal"))),
+                 unaryOperator(hasOperatorName("+"),
+                               hasUnaryOperand(integerLiteral().bind(
+                                   "positive-integer-literal"))),
+                 integerLiteral(unless(hasParent(unaryOperator(
+                                    hasAnyOperatorName("-", "+")))))
+                     .bind("bare-integer-literal")))
+          .bind("unary-op-exp"),
+      this);
+}
+
+void UseNumericLimitsCheck::registerPPCallbacks(
+    const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+  Inserter.registerPreprocessor(PP);
+}
+
+void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
+  const IntegerLiteral *MatchedDecl = nullptr;
+
+  const IntegerLiteral *NegativeMatchedDecl =
+      Result.Nodes.getNodeAs<IntegerLiteral>("negative-integer-literal");
+  const IntegerLiteral *PositiveMatchedDecl =
+      Result.Nodes.getNodeAs<IntegerLiteral>("positive-integer-literal");
+  const IntegerLiteral *BareMatchedDecl =
+      Result.Nodes.getNodeAs<IntegerLiteral>("bare-integer-literal");
+
+  if (NegativeMatchedDecl != nullptr) {
+    MatchedDecl = NegativeMatchedDecl;
+  } else if (PositiveMatchedDecl != nullptr) {
+    MatchedDecl = PositiveMatchedDecl;
+  } else if (BareMatchedDecl != nullptr) {
+    MatchedDecl = BareMatchedDecl;
+  }
+
+  // Only valid if unary operator is present
+  const UnaryOperator *UnaryOpExpr =
+      Result.Nodes.getNodeAs<UnaryOperator>("unary-op-exp");
+
+  const llvm::APInt MatchedIntegerConstant = MatchedDecl->getValue();
+  const auto Language = getLangOpts();
+
+  auto Fixer = [&](auto SourceValue, auto Value,
+                   const std::string &Replacement) {
+    SourceLocation Location = MatchedDecl->getExprLoc();
+    SourceRange Range{MatchedDecl->getBeginLoc(), MatchedDecl->getEndLoc()};
+
+    if (MatchedDecl == NegativeMatchedDecl && -SourceValue == Value) {
+      Range = SourceRange(UnaryOpExpr->getBeginLoc(), UnaryOpExpr->getEndLoc());
+      Location = UnaryOpExpr->getExprLoc();
+      SourceValue = -SourceValue;
+    } else if (MatchedDecl == PositiveMatchedDecl && SourceValue == Value) {
+      Range = SourceRange(UnaryOpExpr->getBeginLoc(), UnaryOpExpr->getEndLoc());
+      Location = UnaryOpExpr->getExprLoc();
+    } else if (MatchedDecl != BareMatchedDecl || SourceValue != Value) {
+      return;
+    }
+
+    diag(Location, "The constant " + std::to_string(SourceValue) +
+                       " is being utilized. "
+                       "Consider using " +
+                       Replacement + " instead")
+        << FixItHint::CreateReplacement(Range, Replacement)
+        << Inserter.createIncludeInsertion(
+               Result.SourceManager->getFileID(Location), "<limits>");
+  };
+
+  for (const auto &[Value, Replacement] : SignedConstants) {
+    Fixer(MatchedIntegerConstant.getSExtValue(), Value, Replacement);
+  }
+
+  for (const auto &[Value, Replacement] : UnsignedConstants) {
+    Fixer(MatchedIntegerConstant.getZExtValue(), Value, Replacement);
+  }
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
new file mode 100644
index 0000000000000..d7231132ef5dd
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
@@ -0,0 +1,41 @@
+//===--- UseNumericLimitsCheck.h - clang-tidy -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USENUMERICLIMITSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USENUMERICLIMITSCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "../utils/IncludeInserter.h"
+#include <vector>
+
+namespace clang::tidy::readability {
+
+/// Replaces certain integer literals with equivalent calls to
+/// ``std::numeric_limits``.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/use-numeric-limits.html
+class UseNumericLimitsCheck : public ClangTidyCheck {
+public:
+  UseNumericLimitsCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+                           Preprocessor *ModuleExpanderPP) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus11;
+  }
+
+private:
+  const std::vector<std::tuple<int64_t, std::string>> SignedConstants;
+  const std::vector<std::tuple<uint64_t, std::string>> UnsignedConstants;
+  utils::IncludeInserter Inserter;
+};
+
+} // namespace clang::tidy::readability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USENUMERICLIMITSCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 6b8fe22242417..b2dfb0de6ae68 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -91,6 +91,11 @@ Improvements to clang-tidy
 New checks
 ^^^^^^^^^^
 
+- New :doc:`readability-use-numeric-limits
+  <clang-tidy/checks/readability/use-numeric-limits>` check to replace certain
+  integer literals with ``std::numeric_limits`` calls.
+
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 7b9b905ef7671..e69ab96cf4bf9 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -403,6 +403,7 @@ Clang-Tidy Checks
    :doc:`readability-uniqueptr-delete-release <readability/uniqueptr-delete-release>`, "Yes"
    :doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes"
    :doc:`readability-use-anyofallof <readability/use-anyofallof>`,
+   :doc:`readability-use-numeric-limits <readability/use-numeric-limits>`, "Yes"
    :doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
    :doc:`zircon-temporary-objects <zircon/temporary-objects>`,
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
new file mode 100644
index 0000000000000..ed50d00f1085d
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - readability-use-numeric-limits
+
+readability-use-numeric-limits
+==============================
+
+Replaces certain integer literals with ``std::numeric_limits`` calls.
+
+Before:
+
+.. code-block:: c++
+
+  void foo() {
+    int32_t a = 2147483647;
+  }
+
+After:
+
+.. code-block:: c++
+
+  void foo() {
+    int32_t a = std::numeric_limits<int32_t>::max();
+  }
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
new file mode 100644
index 0000000000000..2f1d5190148b0
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
@@ -0,0 +1,85 @@
+// RUN: %check_clang_tidy -std=c++11-or-later %s readability-use-numeric-limits %t
+#include <stdint.h>
+
+void constants() {
+  // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant -128 is being utilized. Consider using std::numeric_limits<int8_t>::min() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::min();
+  int8_t _ = -128;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant 127 is being utilized. Consider using std::numeric_limits<int8_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::max();
+  int8_t _ = +127;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant 127 is being utilized. Consider using std::numeric_limits<int8_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::max();
+  int8_t _ = 127;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -32768 is being utilized. Consider using std::numeric_limits<int16_t>::min() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::min();
+  int16_t _ = -32768;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 32767 is being utilized. Consider using std::numeric_limits<int16_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::max();
+  int16_t _ = +32767;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 32767 is being utilized. Consider using std::numeric_limits<int16_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::max();
+  int16_t _ = 32767;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -2147483648 is being utilized. Consider using std::numeric_limits<int32_t>::min() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::min();
+  int32_t _ = -2147483648;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 2147483647 is being utilized. Consider using std::numeric_limits<int32_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::max();
+  int32_t _ = +2147483647;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 2147483647 is being utilized. Consider using std::numeric_limits<int32_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::max();
+  int32_t _ = 2147483647;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -9223372036854775808 is being utilized. Consider using std::numeric_limits<int64_t>::min() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::min();
+  int64_t _ = -9223372036854775808;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 9223372036854775807 is being utilized. Consider using std::numeric_limits<int64_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::max();
+  int64_t _ = +9223372036854775807;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 9223372036854775807 is being utilized. Consider using std::numeric_limits<int64_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::max();
+  int64_t _ = 9223372036854775807;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 255 is being utilized. Consider using std::numeric_limits<uint8_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint8_t _ = std::numeric_limits<uint8_t>::max();
+  uint8_t _ = 255;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 255 is being utilized. Consider using std::numeric_limits<uint8_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint8_t _ = std::numeric_limits<uint8_t>::max();
+  uint8_t _ = +255;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 65535 is being utilized. Consider using std::numeric_limits<uint16_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint16_t _ = std::numeric_limits<uint16_t>::max();
+  uint16_t _ = 65535;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 65535 is being utilized. Consider using std::numeric_limits<uint16_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint16_t _ = std::numeric_limits<uint16_t>::max();
+  uint16_t _ = +65535;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 4294967295 is being utilized. Consider using std::numeric_limits<uint32_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint32_t _ = std::numeric_limits<uint32_t>::max();
+  uint32_t _ = 4294967295;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 4294967295 is being utilized. Consider using std::numeric_limits<uint32_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint32_t _ = std::numeric_limits<uint32_t>::max();
+  uint32_t _ = +4294967295;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 18446744073709551615 is being utilized. Consider using std::numeric_limits<uint64_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint64_t _ = std::numeric_limits<uint64_t>::max();
+  uint64_t _ = 18446744073709551615;
+
+  // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 18446744073709551615 is being utilized. Consider using std::numeric_limits<uint64_t>::max() instead [readability-use-numeric-limits]
+  // CHECK-FIXES: uint64_t _ = std::numeric_limits<uint64_t>::max();
+  uint64_t _ = +18446744073709551615;
+}
+

>From b649d723835e45df7788f2c0d9a8ad95179edd57 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Mon, 17 Feb 2025 11:07:31 -0500
Subject: [PATCH 02/10] Fix issues from code review

---
 .../clang-tidy/readability/UseNumericLimitsCheck.cpp        | 1 -
 clang-tools-extra/docs/ReleaseNotes.rst                     | 6 ++++--
 .../clang-tidy/checkers/readability/use-numeric-limits.cpp  | 1 -
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index b26ae008cbdd5..7f14c0337ce18 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -96,7 +96,6 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
       Result.Nodes.getNodeAs<UnaryOperator>("unary-op-exp");
 
   const llvm::APInt MatchedIntegerConstant = MatchedDecl->getValue();
-  const auto Language = getLangOpts();
 
   auto Fixer = [&](auto SourceValue, auto Value,
                    const std::string &Replacement) {
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b2dfb0de6ae68..4a0de02a8a77e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -92,8 +92,10 @@ New checks
 ^^^^^^^^^^
 
 - New :doc:`readability-use-numeric-limits
-  <clang-tidy/checks/readability/use-numeric-limits>` check to replace certain
-  integer literals with ``std::numeric_limits`` calls.
+  <clang-tidy/checks/readability/use-numeric-limits>` check.
+
+  Replaces certain integer literals with equivalent calls to
+  ``std::numeric_limits<T>::min()`` or ``std::numeric_limits<T>::max()``.
 
 
 New check aliases
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
index 2f1d5190148b0..9ad745c7c62c9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
@@ -82,4 +82,3 @@ void constants() {
   // CHECK-FIXES: uint64_t _ = std::numeric_limits<uint64_t>::max();
   uint64_t _ = +18446744073709551615;
 }
-

>From 15ded5eb660e6a2e9107cc4c1ddbaef6ccb8dd17 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Mon, 17 Feb 2025 11:16:27 -0500
Subject: [PATCH 03/10] Synchronize release note and docs

---
 .../docs/clang-tidy/checks/readability/use-numeric-limits.rst  | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
index ed50d00f1085d..d24df618a3018 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
@@ -3,7 +3,8 @@
 readability-use-numeric-limits
 ==============================
 
-Replaces certain integer literals with ``std::numeric_limits`` calls.
+ Replaces certain integer literals with equivalent calls to
+ ``std::numeric_limits<T>::min()`` or ``std::numeric_limits<T>::max()``.
 
 Before:
 

>From fa054327530fdf019fc6272cc8011fa5e53970fe Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Tue, 18 Feb 2025 10:40:53 -0500
Subject: [PATCH 04/10] Fix small things

---
 .../readability/UseNumericLimitsCheck.cpp     | 15 ++--
 .../readability/UseNumericLimitsCheck.h       |  3 -
 .../readability/use-numeric-limits.cpp        | 82 +++++++++----------
 3 files changed, 48 insertions(+), 52 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index 7f14c0337ce18..b2806138f12a2 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -91,10 +91,6 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
     MatchedDecl = BareMatchedDecl;
   }
 
-  // Only valid if unary operator is present
-  const UnaryOperator *UnaryOpExpr =
-      Result.Nodes.getNodeAs<UnaryOperator>("unary-op-exp");
-
   const llvm::APInt MatchedIntegerConstant = MatchedDecl->getValue();
 
   auto Fixer = [&](auto SourceValue, auto Value,
@@ -102,6 +98,10 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
     SourceLocation Location = MatchedDecl->getExprLoc();
     SourceRange Range{MatchedDecl->getBeginLoc(), MatchedDecl->getEndLoc()};
 
+    // Only valid if unary operator is present
+    const UnaryOperator *UnaryOpExpr =
+        Result.Nodes.getNodeAs<UnaryOperator>("unary-op-exp");
+
     if (MatchedDecl == NegativeMatchedDecl && -SourceValue == Value) {
       Range = SourceRange(UnaryOpExpr->getBeginLoc(), UnaryOpExpr->getEndLoc());
       Location = UnaryOpExpr->getExprLoc();
@@ -113,10 +113,9 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
       return;
     }
 
-    diag(Location, "The constant " + std::to_string(SourceValue) +
-                       " is being utilized. "
-                       "Consider using " +
-                       Replacement + " instead")
+    diag(Location,
+         "The constant %0 is being utilized. Consider using %1 instead")
+        << std::to_string(SourceValue) << Replacement
         << FixItHint::CreateReplacement(Range, Replacement)
         << Inserter.createIncludeInsertion(
                Result.SourceManager->getFileID(Location), "<limits>");
diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
index d7231132ef5dd..cce45deda2394 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
@@ -26,9 +26,6 @@ class UseNumericLimitsCheck : public ClangTidyCheck {
   void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
                            Preprocessor *ModuleExpanderPP) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
-    return LangOpts.CPlusPlus11;
-  }
 
 private:
   const std::vector<std::tuple<int64_t, std::string>> SignedConstants;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
index 9ad745c7c62c9..8053332fc2dee 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
@@ -1,84 +1,84 @@
-// RUN: %check_clang_tidy -std=c++11-or-later %s readability-use-numeric-limits %t
+// RUN: %check_clang_tidy %s readability-use-numeric-limits %t
 #include <stdint.h>
 
 void constants() {
   // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant -128 is being utilized. Consider using std::numeric_limits<int8_t>::min() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::min();
-  int8_t _ = -128;
+  // CHECK-FIXES: int8_t a = std::numeric_limits<int8_t>::min();
+  int8_t a = -128;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant 127 is being utilized. Consider using std::numeric_limits<int8_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::max();
-  int8_t _ = +127;
+  // CHECK-FIXES: int8_t b = std::numeric_limits<int8_t>::max();
+  int8_t b = +127;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant 127 is being utilized. Consider using std::numeric_limits<int8_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int8_t _ = std::numeric_limits<int8_t>::max();
-  int8_t _ = 127;
+  // CHECK-FIXES: int8_t c = std::numeric_limits<int8_t>::max();
+  int8_t c = 127;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -32768 is being utilized. Consider using std::numeric_limits<int16_t>::min() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::min();
-  int16_t _ = -32768;
+  // CHECK-FIXES: int16_t d = std::numeric_limits<int16_t>::min();
+  int16_t d = -32768;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 32767 is being utilized. Consider using std::numeric_limits<int16_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::max();
-  int16_t _ = +32767;
+  // CHECK-FIXES: int16_t e = std::numeric_limits<int16_t>::max();
+  int16_t e = +32767;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 32767 is being utilized. Consider using std::numeric_limits<int16_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int16_t _ = std::numeric_limits<int16_t>::max();
-  int16_t _ = 32767;
+  // CHECK-FIXES: int16_t f = std::numeric_limits<int16_t>::max();
+  int16_t f = 32767;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -2147483648 is being utilized. Consider using std::numeric_limits<int32_t>::min() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::min();
-  int32_t _ = -2147483648;
+  // CHECK-FIXES: int32_t g = std::numeric_limits<int32_t>::min();
+  int32_t g = -2147483648;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 2147483647 is being utilized. Consider using std::numeric_limits<int32_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::max();
-  int32_t _ = +2147483647;
+  // CHECK-FIXES: int32_t h = std::numeric_limits<int32_t>::max();
+  int32_t h = +2147483647;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 2147483647 is being utilized. Consider using std::numeric_limits<int32_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int32_t _ = std::numeric_limits<int32_t>::max();
-  int32_t _ = 2147483647;
+  // CHECK-FIXES: int32_t i = std::numeric_limits<int32_t>::max();
+  int32_t i = 2147483647;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant -9223372036854775808 is being utilized. Consider using std::numeric_limits<int64_t>::min() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::min();
-  int64_t _ = -9223372036854775808;
+  // CHECK-FIXES: int64_t j = std::numeric_limits<int64_t>::min();
+  int64_t j = -9223372036854775808;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 9223372036854775807 is being utilized. Consider using std::numeric_limits<int64_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::max();
-  int64_t _ = +9223372036854775807;
+  // CHECK-FIXES: int64_t k = std::numeric_limits<int64_t>::max();
+  int64_t k = +9223372036854775807;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 9223372036854775807 is being utilized. Consider using std::numeric_limits<int64_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: int64_t _ = std::numeric_limits<int64_t>::max();
-  int64_t _ = 9223372036854775807;
+  // CHECK-FIXES: int64_t l = std::numeric_limits<int64_t>::max();
+  int64_t l = 9223372036854775807;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 255 is being utilized. Consider using std::numeric_limits<uint8_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint8_t _ = std::numeric_limits<uint8_t>::max();
-  uint8_t _ = 255;
+  // CHECK-FIXES: uint8_t m = std::numeric_limits<uint8_t>::max();
+  uint8_t m = 255;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:15: warning: The constant 255 is being utilized. Consider using std::numeric_limits<uint8_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint8_t _ = std::numeric_limits<uint8_t>::max();
-  uint8_t _ = +255;
+  // CHECK-FIXES: uint8_t n = std::numeric_limits<uint8_t>::max();
+  uint8_t n = +255;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 65535 is being utilized. Consider using std::numeric_limits<uint16_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint16_t _ = std::numeric_limits<uint16_t>::max();
-  uint16_t _ = 65535;
+  // CHECK-FIXES: uint16_t o = std::numeric_limits<uint16_t>::max();
+  uint16_t o = 65535;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 65535 is being utilized. Consider using std::numeric_limits<uint16_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint16_t _ = std::numeric_limits<uint16_t>::max();
-  uint16_t _ = +65535;
+  // CHECK-FIXES: uint16_t p = std::numeric_limits<uint16_t>::max();
+  uint16_t p = +65535;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 4294967295 is being utilized. Consider using std::numeric_limits<uint32_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint32_t _ = std::numeric_limits<uint32_t>::max();
-  uint32_t _ = 4294967295;
+  // CHECK-FIXES: uint32_t q = std::numeric_limits<uint32_t>::max();
+  uint32_t q = 4294967295;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 4294967295 is being utilized. Consider using std::numeric_limits<uint32_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint32_t _ = std::numeric_limits<uint32_t>::max();
-  uint32_t _ = +4294967295;
+  // CHECK-FIXES: uint32_t r = std::numeric_limits<uint32_t>::max();
+  uint32_t r = +4294967295;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 18446744073709551615 is being utilized. Consider using std::numeric_limits<uint64_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint64_t _ = std::numeric_limits<uint64_t>::max();
-  uint64_t _ = 18446744073709551615;
+  // CHECK-FIXES: uint64_t s = std::numeric_limits<uint64_t>::max();
+  uint64_t s = 18446744073709551615;
 
   // CHECK-MESSAGES: :[[@LINE+2]]:16: warning: The constant 18446744073709551615 is being utilized. Consider using std::numeric_limits<uint64_t>::max() instead [readability-use-numeric-limits]
-  // CHECK-FIXES: uint64_t _ = std::numeric_limits<uint64_t>::max();
-  uint64_t _ = +18446744073709551615;
+  // CHECK-FIXES: uint64_t t = std::numeric_limits<uint64_t>::max();
+  uint64_t t = +18446744073709551615;
 }

>From 261cfcb9dd4ab5b66018b943a76a1ffc8d6c35c3 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Tue, 18 Feb 2025 11:08:49 -0500
Subject: [PATCH 05/10] Store (and document) IncludeStyle option

---
 .../clang-tidy/readability/UseNumericLimitsCheck.cpp      | 4 ++++
 .../clang-tidy/readability/UseNumericLimitsCheck.h        | 1 +
 .../clang-tidy/checks/readability/use-numeric-limits.rst  | 8 ++++++++
 3 files changed, 13 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index b2806138f12a2..ec9a74885c28b 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -53,6 +53,10 @@ UseNumericLimitsCheck::UseNumericLimitsCheck(StringRef Name,
                                         utils::IncludeSorter::IS_LLVM),
                areDiagsSelfContained()) {}
 
+void UseNumericLimitsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
 void UseNumericLimitsCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
       expr(anyOf(unaryOperator(hasOperatorName("-"),
diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
index cce45deda2394..c6fe568086014 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
@@ -22,6 +22,7 @@ namespace clang::tidy::readability {
 class UseNumericLimitsCheck : public ClangTidyCheck {
 public:
   UseNumericLimitsCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
                            Preprocessor *ModuleExpanderPP) override;
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
index d24df618a3018..0dfc29c4b95ae 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst
@@ -21,3 +21,11 @@ After:
   void foo() {
     int32_t a = std::numeric_limits<int32_t>::max();
   }
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.

>From 3c4a272496b70f6a3ce4fac0d818ec5da27d948c Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Tue, 18 Feb 2025 11:30:23 -0500
Subject: [PATCH 06/10] Explicitly match only against specific values

---
 .../readability/UseNumericLimitsCheck.cpp     | 51 ++++++++++++++-----
 1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index ec9a74885c28b..0903e864b0959 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -58,18 +58,45 @@ void UseNumericLimitsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
 }
 
 void UseNumericLimitsCheck::registerMatchers(MatchFinder *Finder) {
-  Finder->addMatcher(
-      expr(anyOf(unaryOperator(hasOperatorName("-"),
-                               hasUnaryOperand(integerLiteral().bind(
-                                   "negative-integer-literal"))),
-                 unaryOperator(hasOperatorName("+"),
-                               hasUnaryOperand(integerLiteral().bind(
-                                   "positive-integer-literal"))),
-                 integerLiteral(unless(hasParent(unaryOperator(
-                                    hasAnyOperatorName("-", "+")))))
-                     .bind("bare-integer-literal")))
-          .bind("unary-op-exp"),
-      this);
+  auto PositiveIntegerMatcher = [](auto Value) {
+    return unaryOperator(
+        hasOperatorName("+"),
+        hasUnaryOperand(
+            integerLiteral(equals(Value)).bind("positive-integer-literal")));
+  };
+
+  auto NegativeIntegerMatcher = [](auto Value) {
+    return unaryOperator(
+        hasOperatorName("-"),
+        hasUnaryOperand(
+            integerLiteral(equals(-Value)).bind("negative-integer-literal")));
+  };
+
+  auto BareIntegerMatcher = [](auto Value) {
+    return integerLiteral(allOf(unless(hasParent(unaryOperator(
+                                    hasAnyOperatorName("-", "+")))),
+                                equals(Value)))
+        .bind("bare-integer-literal");
+  };
+
+  for (const auto &[Value, _] : SignedConstants) {
+    if (Value < 0) {
+      Finder->addMatcher(
+          expr(NegativeIntegerMatcher(Value)).bind("unary-op-exp"), this);
+    } else {
+      Finder->addMatcher(
+          expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value)))
+              .bind("unary-op-exp"),
+          this);
+    }
+  }
+
+  for (const auto &[Value, _] : UnsignedConstants) {
+    Finder->addMatcher(
+        expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value)))
+            .bind("unary-op-exp"),
+        this);
+  }
 }
 
 void UseNumericLimitsCheck::registerPPCallbacks(

>From 01452a15489b65d955bc257ed50b03ed9cfb2646 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Fri, 21 Feb 2025 14:26:17 -0500
Subject: [PATCH 07/10] Fix small comments

---
 .../clang-tidy/readability/UseNumericLimitsCheck.cpp         | 1 -
 .../clang-tidy/readability/UseNumericLimitsCheck.h           | 5 ++---
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index 0903e864b0959..d2203ea579a9e 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -37,7 +37,6 @@ UseNumericLimitsCheck::UseNumericLimitsCheck(StringRef Name,
            "std::numeric_limits<int64_t>::min()"},
           {std::numeric_limits<int64_t>::max(),
            "std::numeric_limits<int64_t>::max()"},
-
       },
       UnsignedConstants{
           {std::numeric_limits<uint8_t>::max(),
diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
index c6fe568086014..62fb181258ae4 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h
@@ -11,7 +11,6 @@
 
 #include "../ClangTidyCheck.h"
 #include "../utils/IncludeInserter.h"
-#include <vector>
 
 namespace clang::tidy::readability {
 
@@ -29,8 +28,8 @@ class UseNumericLimitsCheck : public ClangTidyCheck {
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
 
 private:
-  const std::vector<std::tuple<int64_t, std::string>> SignedConstants;
-  const std::vector<std::tuple<uint64_t, std::string>> UnsignedConstants;
+  const llvm::SmallVector<std::pair<int64_t, std::string>> SignedConstants;
+  const llvm::SmallVector<std::pair<uint64_t, std::string>> UnsignedConstants;
   utils::IncludeInserter Inserter;
 };
 

>From be01b74029e13477f246cedceb1cc44d15090910 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Fri, 28 Feb 2025 11:02:58 -0500
Subject: [PATCH 08/10] Bind unary-op only in the required matchers

---
 .../readability/UseNumericLimitsCheck.cpp     | 27 +++++++++----------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index d2203ea579a9e..0f666392b9442 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -58,17 +58,17 @@ void UseNumericLimitsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
 
 void UseNumericLimitsCheck::registerMatchers(MatchFinder *Finder) {
   auto PositiveIntegerMatcher = [](auto Value) {
-    return unaryOperator(
-        hasOperatorName("+"),
-        hasUnaryOperand(
-            integerLiteral(equals(Value)).bind("positive-integer-literal")));
+    return unaryOperator(hasOperatorName("+"),
+                         hasUnaryOperand(integerLiteral(equals(Value))
+                                             .bind("positive-integer-literal")))
+        .bind("unary-op");
   };
 
   auto NegativeIntegerMatcher = [](auto Value) {
-    return unaryOperator(
-        hasOperatorName("-"),
-        hasUnaryOperand(
-            integerLiteral(equals(-Value)).bind("negative-integer-literal")));
+    return unaryOperator(hasOperatorName("-"),
+                         hasUnaryOperand(integerLiteral(equals(-Value))
+                                             .bind("negative-integer-literal")))
+        .bind("unary-op");
   };
 
   auto BareIntegerMatcher = [](auto Value) {
@@ -80,20 +80,17 @@ void UseNumericLimitsCheck::registerMatchers(MatchFinder *Finder) {
 
   for (const auto &[Value, _] : SignedConstants) {
     if (Value < 0) {
-      Finder->addMatcher(
-          expr(NegativeIntegerMatcher(Value)).bind("unary-op-exp"), this);
+      Finder->addMatcher(NegativeIntegerMatcher(Value), this);
     } else {
       Finder->addMatcher(
-          expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value)))
-              .bind("unary-op-exp"),
+          expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value))),
           this);
     }
   }
 
   for (const auto &[Value, _] : UnsignedConstants) {
     Finder->addMatcher(
-        expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value)))
-            .bind("unary-op-exp"),
+        expr(anyOf(PositiveIntegerMatcher(Value), BareIntegerMatcher(Value))),
         this);
   }
 }
@@ -130,7 +127,7 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
 
     // Only valid if unary operator is present
     const UnaryOperator *UnaryOpExpr =
-        Result.Nodes.getNodeAs<UnaryOperator>("unary-op-exp");
+        Result.Nodes.getNodeAs<UnaryOperator>("unary-op");
 
     if (MatchedDecl == NegativeMatchedDecl && -SourceValue == Value) {
       Range = SourceRange(UnaryOpExpr->getBeginLoc(), UnaryOpExpr->getEndLoc());

>From f3460537fb599bef5a9a157bd25d9c6afcc07f86 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Fri, 28 Feb 2025 11:31:19 -0500
Subject: [PATCH 09/10] Add Valid checks

---
 .../checkers/readability/use-numeric-limits.cpp           | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
index 8053332fc2dee..794dfcea00a52 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp
@@ -1,7 +1,7 @@
 // RUN: %check_clang_tidy %s readability-use-numeric-limits %t
 #include <stdint.h>
 
-void constants() {
+void Invalid() {
   // CHECK-MESSAGES: :[[@LINE+2]]:14: warning: The constant -128 is being utilized. Consider using std::numeric_limits<int8_t>::min() instead [readability-use-numeric-limits]
   // CHECK-FIXES: int8_t a = std::numeric_limits<int8_t>::min();
   int8_t a = -128;
@@ -82,3 +82,9 @@ void constants() {
   // CHECK-FIXES: uint64_t t = std::numeric_limits<uint64_t>::max();
   uint64_t t = +18446744073709551615;
 }
+
+void Valid(){
+  int16_t a = +128;
+
+  int16_t b = -127;
+}

>From b790ab1aafb22e784a06ca4faf75bd91c357f346 Mon Sep 17 00:00:00 2001
From: Katherine Whitlock <kate at skylinesynths.nyc>
Date: Fri, 28 Feb 2025 11:34:42 -0500
Subject: [PATCH 10/10] Fail compilation if the SourceValue and Value are not
 the same types

---
 .../clang-tidy/readability/UseNumericLimitsCheck.cpp           | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
index 0f666392b9442..b263d12738ce2 100644
--- a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp
@@ -122,6 +122,9 @@ void UseNumericLimitsCheck::check(const MatchFinder::MatchResult &Result) {
 
   auto Fixer = [&](auto SourceValue, auto Value,
                    const std::string &Replacement) {
+    static_assert(std::is_same_v<decltype(SourceValue), decltype(Value)>,
+                  "The types of SourceValue and Value must match");
+
     SourceLocation Location = MatchedDecl->getExprLoc();
     SourceRange Range{MatchedDecl->getBeginLoc(), MatchedDecl->getEndLoc()};
 



More information about the cfe-commits mailing list