aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorYutong Zhu <115899167+YutongZhuu@users.noreply.github.com>2025-03-10 09:08:50 -0400
committerGitHub <noreply@github.com>2025-03-10 14:08:50 +0100
commit773e88f9d61399c566fed45bf7858922f09b8063 (patch)
tree4ddc8c456565cd3299d9e51a902154bee8c51b63 /clang/lib/Sema/SemaChecking.cpp
parenta1a6a839763079b54d8910599549b9e6d4dd5fe6 (diff)
downloadllvm-773e88f9d61399c566fed45bf7858922f09b8063.zip
llvm-773e88f9d61399c566fed45bf7858922f09b8063.tar.gz
llvm-773e88f9d61399c566fed45bf7858922f09b8063.tar.bz2
[Clang] Force expressions with UO_Not to not be non-negative (#126846)
This PR addresses the bug of not throwing warnings for the following code: ```c++ int test13(unsigned a, int *b) { return a > ~(95 != *b); // expected-warning {{comparison of integers of different signs}} } ``` However, in the original issue, a comment mentioned that negation, pre-increment, and pre-decrement operators are also incorrect in this case. Fixes #18878
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 9cac9cf..a6cdbbaf 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -10620,6 +10620,42 @@ static std::optional<IntRange> TryGetExprRange(ASTContext &C, const Expr *E,
case UO_AddrOf: // should be impossible
return IntRange::forValueOfType(C, GetExprType(E));
+ case UO_Minus: {
+ if (E->getType()->isUnsignedIntegerType()) {
+ return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
+ Approximate);
+ }
+
+ std::optional<IntRange> SubRange = TryGetExprRange(
+ C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
+
+ if (!SubRange)
+ return std::nullopt;
+
+ // If the range was previously non-negative, we need an extra bit for the
+ // sign bit. If the range was not non-negative, we need an extra bit
+ // because the negation of the most-negative value is one bit wider than
+ // that value.
+ return IntRange(SubRange->Width + 1, false);
+ }
+
+ case UO_Not: {
+ if (E->getType()->isUnsignedIntegerType()) {
+ return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
+ Approximate);
+ }
+
+ std::optional<IntRange> SubRange = TryGetExprRange(
+ C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);
+
+ if (!SubRange)
+ return std::nullopt;
+
+ // The width increments by 1 if the sub-expression cannot be negative
+ // since it now can be.
+ return IntRange(SubRange->Width + (int)SubRange->NonNegative, false);
+ }
+
default:
return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
Approximate);