aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
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);