diff options
author | Yutong Zhu <115899167+YutongZhuu@users.noreply.github.com> | 2025-03-10 09:08:50 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-10 14:08:50 +0100 |
commit | 773e88f9d61399c566fed45bf7858922f09b8063 (patch) | |
tree | 4ddc8c456565cd3299d9e51a902154bee8c51b63 /clang/lib/Sema/SemaChecking.cpp | |
parent | a1a6a839763079b54d8910599549b9e6d4dd5fe6 (diff) | |
download | llvm-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.cpp | 36 |
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); |