Skip to content

[clang-tidy] avoid 64-bit truncation in redundant bitwise checks#201363

Open
unterumarmung wants to merge 2 commits into
llvm:mainfrom
unterumarmung:misc-redundant-expression
Open

[clang-tidy] avoid 64-bit truncation in redundant bitwise checks#201363
unterumarmung wants to merge 2 commits into
llvm:mainfrom
unterumarmung:misc-redundant-expression

Conversation

@unterumarmung
Copy link
Copy Markdown
Contributor

Fixes #201115

@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-clang-tidy

Author: Daniil Dudkin (unterumarmung)

Changes

Fixes #201115


Full diff: https://github.com/llvm/llvm-project/pull/201363.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp (+4-2)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp (+45)
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
index 9db297990b274..de489da96de3b 100644
--- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -1178,8 +1178,10 @@ void RedundantExpressionCheck::checkBitwiseExpr(
         !retrieveIntegerConstantExpr(Result, "rhs", RhsValue))
       return;
 
-    const uint64_t LhsConstant = LhsValue.getZExtValue();
-    const uint64_t RhsConstant = RhsValue.getZExtValue();
+    const unsigned ConstantWidth =
+        std::max(LhsValue.getBitWidth(), RhsValue.getBitWidth());
+    const llvm::APInt LhsConstant = LhsValue.extOrTrunc(ConstantWidth);
+    const llvm::APInt RhsConstant = RhsValue.extOrTrunc(ConstantWidth);
     const SourceLocation Loc = ComparisonOperator->getOperatorLoc();
 
     // Check expression: x & k1 == k2  (i.e. x & 0xFF == 0xF00)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
index 4ff0ba867ebb9..4bd2d2df343dc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
@@ -572,6 +572,51 @@ int TestBitwise(int X, int Y) {
   return 0;
 }
 
+bool TestBitwiseUInt128(unsigned __int128 Value) {
+  constexpr unsigned __int128 BigBit =
+      static_cast<unsigned __int128>(1) << 100;
+
+  if ((Value & BigBit) == BigBit) return true;
+
+  constexpr unsigned __int128 LowMask = static_cast<unsigned __int128>(0xFF);
+
+  if ((Value & LowMask) == BigBit) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: logical expression is always false
+  if ((Value & LowMask) != BigBit) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: logical expression is always true
+  if ((Value | BigBit) == LowMask) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: logical expression is always false
+  if ((Value | BigBit) != LowMask) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: logical expression is always true
+
+  return false;
+}
+
+#define UINT128_BIG_BIT (static_cast<unsigned __int128>(1) << 100)
+
+bool TestBitwiseUInt128Macro(unsigned __int128 Value) {
+  return (Value & UINT128_BIG_BIT) == UINT128_BIG_BIT;
+}
+
+template <int N>
+bool TestBitwiseUInt128Template(unsigned __int128 Value) {
+  constexpr unsigned __int128 Mask = static_cast<unsigned __int128>(1) << N;
+  return (Value & Mask) == Mask;
+}
+
+bool UseBitwiseUInt128Template(unsigned __int128 Value) {
+  return TestBitwiseUInt128Template<100>(Value);
+}
+
+using RedundantExpressionU128 = unsigned __int128;
+typedef unsigned __int128 RedundantExpressionTypedefU128;
+
+bool TestBitwiseUInt128AliasCvRef(const RedundantExpressionU128 &Value) {
+  constexpr RedundantExpressionTypedefU128 Mask =
+      static_cast<RedundantExpressionU128>(1) << 100;
+  return (Value & Mask) == Mask;
+}
+
 // Overloaded operators that compare an instance of a struct and an integer
 // constant.
 struct S {

@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-clang-tools-extra

Author: Daniil Dudkin (unterumarmung)

Changes

Fixes #201115


Full diff: https://github.com/llvm/llvm-project/pull/201363.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp (+4-2)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp (+45)
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
index 9db297990b274..de489da96de3b 100644
--- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -1178,8 +1178,10 @@ void RedundantExpressionCheck::checkBitwiseExpr(
         !retrieveIntegerConstantExpr(Result, "rhs", RhsValue))
       return;
 
-    const uint64_t LhsConstant = LhsValue.getZExtValue();
-    const uint64_t RhsConstant = RhsValue.getZExtValue();
+    const unsigned ConstantWidth =
+        std::max(LhsValue.getBitWidth(), RhsValue.getBitWidth());
+    const llvm::APInt LhsConstant = LhsValue.extOrTrunc(ConstantWidth);
+    const llvm::APInt RhsConstant = RhsValue.extOrTrunc(ConstantWidth);
     const SourceLocation Loc = ComparisonOperator->getOperatorLoc();
 
     // Check expression: x & k1 == k2  (i.e. x & 0xFF == 0xF00)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
index 4ff0ba867ebb9..4bd2d2df343dc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp
@@ -572,6 +572,51 @@ int TestBitwise(int X, int Y) {
   return 0;
 }
 
+bool TestBitwiseUInt128(unsigned __int128 Value) {
+  constexpr unsigned __int128 BigBit =
+      static_cast<unsigned __int128>(1) << 100;
+
+  if ((Value & BigBit) == BigBit) return true;
+
+  constexpr unsigned __int128 LowMask = static_cast<unsigned __int128>(0xFF);
+
+  if ((Value & LowMask) == BigBit) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: logical expression is always false
+  if ((Value & LowMask) != BigBit) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: logical expression is always true
+  if ((Value | BigBit) == LowMask) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: logical expression is always false
+  if ((Value | BigBit) != LowMask) return true;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: logical expression is always true
+
+  return false;
+}
+
+#define UINT128_BIG_BIT (static_cast<unsigned __int128>(1) << 100)
+
+bool TestBitwiseUInt128Macro(unsigned __int128 Value) {
+  return (Value & UINT128_BIG_BIT) == UINT128_BIG_BIT;
+}
+
+template <int N>
+bool TestBitwiseUInt128Template(unsigned __int128 Value) {
+  constexpr unsigned __int128 Mask = static_cast<unsigned __int128>(1) << N;
+  return (Value & Mask) == Mask;
+}
+
+bool UseBitwiseUInt128Template(unsigned __int128 Value) {
+  return TestBitwiseUInt128Template<100>(Value);
+}
+
+using RedundantExpressionU128 = unsigned __int128;
+typedef unsigned __int128 RedundantExpressionTypedefU128;
+
+bool TestBitwiseUInt128AliasCvRef(const RedundantExpressionU128 &Value) {
+  constexpr RedundantExpressionTypedefU128 Mask =
+      static_cast<RedundantExpressionU128>(1) << 100;
+  return (Value & Mask) == Mask;
+}
+
 // Overloaded operators that compare an instance of a struct and an integer
 // constant.
 struct S {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clang-tidy] Assertion failure in misc-redundant-expression

1 participant