[clang-tools-extra] e65d323 - [clang-tidy] Improve integer comparison by matching valid expressions outside implicitCastExpr (#134188)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 10 00:57:15 PDT 2025
Author: David Rivera
Date: 2025-06-10T10:57:11+03:00
New Revision: e65d32316646e6203a3f4d4c9921edcddbb1c57d
URL: https://github.com/llvm/llvm-project/commit/e65d32316646e6203a3f4d4c9921edcddbb1c57d
DIFF: https://github.com/llvm/llvm-project/commit/e65d32316646e6203a3f4d4c9921edcddbb1c57d.diff
LOG: [clang-tidy] Improve integer comparison by matching valid expressions outside implicitCastExpr (#134188)
Aims to fix #127471
Covered the edge case where an int expression is not necessarily
directly wrapped around an 'ImplicitCastExpr' which seemed to be a
requirement in 'use-integer-sign-comparison.cpp' check to trigger.
**For instance**:
```cpp
#include <vector>
bool f() {
std::vector<int> v;
unsigned int i = 0;
return i >= v.size();
}
```
Added:
Modified:
clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
index eeba5cce80da5..c02c5dfa8756d 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseIntegerSignComparisonCheck.cpp
@@ -39,21 +39,28 @@ intCastExpression(bool IsSigned,
// std::cmp_{} functions trigger a compile-time error if either LHS or RHS
// is a non-integer type, char, enum or bool
// (unsigned char/ signed char are Ok and can be used).
- auto IntTypeExpr = expr(hasType(hasCanonicalType(qualType(
+ const auto HasIntegerType = hasType(hasCanonicalType(qualType(
isInteger(), IsSigned ? isSignedInteger() : isUnsignedInteger(),
- unless(isActualChar()), unless(booleanType()), unless(enumType())))));
+ unless(isActualChar()), unless(booleanType()), unless(enumType()))));
+
+ const auto IntTypeExpr = expr(HasIntegerType);
const auto ImplicitCastExpr =
CastBindName.empty() ? implicitCastExpr(hasSourceExpression(IntTypeExpr))
: implicitCastExpr(hasSourceExpression(IntTypeExpr))
.bind(CastBindName);
- const auto CStyleCastExpr = cStyleCastExpr(has(ImplicitCastExpr));
- const auto StaticCastExpr = cxxStaticCastExpr(has(ImplicitCastExpr));
- const auto FunctionalCastExpr = cxxFunctionalCastExpr(has(ImplicitCastExpr));
+ const auto ExplicitCastExpr =
+ anyOf(explicitCastExpr(has(ImplicitCastExpr)),
+ ignoringImpCasts(explicitCastExpr(has(ImplicitCastExpr))));
+
+ // Match function calls or variable references not directly wrapped by an
+ // implicit cast
+ const auto CallIntExpr = CastBindName.empty()
+ ? callExpr(HasIntegerType)
+ : callExpr(HasIntegerType).bind(CastBindName);
- return expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr,
- FunctionalCastExpr));
+ return expr(anyOf(ImplicitCastExpr, ExplicitCastExpr, CallIntExpr));
}
static StringRef parseOpCode(BinaryOperator::Opcode Code) {
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 19ccd1790e757..882ee0015df17 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -237,6 +237,10 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-designated-initializers>` check by avoiding
diagnosing designated initializers for ``std::array`` initializations.
+- Improved :doc:`modernize-use-integer-sign-comparison
+ <clang-tidy/checks/modernize/use-integer-sign-comparison>` check by matching
+ valid integer expressions not directly wrapped around an implicit cast.
+
- Improved :doc:`modernize-use-ranges
<clang-tidy/checks/modernize/use-ranges>` check by updating suppress
warnings logic for ``nullptr`` in ``std::find``.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
index e0a84ef5aed26..d93a05ac38050 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-integer-sign-comparison.cpp
@@ -121,3 +121,81 @@ int AllComparisons() {
return 0;
}
+
+namespace PR127471 {
+ int getSignedValue();
+ unsigned int getUnsignedValue();
+
+ void callExprTest() {
+
+ if (getSignedValue() < getUnsignedValue())
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_less(getSignedValue() , getUnsignedValue()))
+
+ int sVar = 0;
+ if (getUnsignedValue() > sVar)
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_greater(getUnsignedValue() , sVar))
+
+ unsigned int uVar = 0;
+ if (getSignedValue() > uVar)
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_greater(getSignedValue() , uVar))
+
+ }
+
+ // Add a class with member functions for testing member function calls
+ class TestClass {
+ public:
+ int getSignedValue() { return -5; }
+ unsigned int getUnsignedValue() { return 5; }
+ };
+
+ void memberFunctionTests() {
+ TestClass obj;
+
+ if (obj.getSignedValue() < obj.getUnsignedValue())
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_less(obj.getSignedValue() , obj.getUnsignedValue()))
+ }
+
+ void castFunctionTests() {
+ // C-style casts with function calls
+ if ((int)getUnsignedValue() < (unsigned int)getSignedValue())
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_less(getUnsignedValue(),getSignedValue()))
+
+
+ // Static casts with function calls
+ if (static_cast<int>(getUnsignedValue()) < static_cast<unsigned int>(getSignedValue()))
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_less(getUnsignedValue(),getSignedValue()))
+ }
+
+ // Define tests
+ #define SIGNED_FUNC getSignedValue()
+ #define UNSIGNED_FUNC getUnsignedValue()
+
+ void defineTests() {
+ if (SIGNED_FUNC < UNSIGNED_FUNC)
+ return;
+// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: comparison between 'signed' and 'unsigned' integers [modernize-use-integer-sign-comparison]
+// CHECK-FIXES: if (std::cmp_less(SIGNED_FUNC , UNSIGNED_FUNC))
+ }
+
+ // Template tests (should not warn)
+ template <typename T1>
+ void templateFunctionTest(T1 value) {
+ if (value() < getUnsignedValue())
+ return;
+
+ if (value() < (getSignedValue() || getUnsignedValue()))
+ return;
+ }
+} // namespace PR127471
More information about the cfe-commits
mailing list