[Clang] Add machinery to catch overflow in unary minus outside of a constant expression context
We provide several diagnostics for various undefined behaviors due to signed integer overflow outside of a constant expression context. We were missing the machinery to catch overflows due to unary minus. Fixes: https://github.com/llvm/llvm-project/issues/31643 Differential Revision: https://reviews.llvm.org/D142867
This commit is contained in:
parent
c53eff55e5
commit
67ee18cc7a
|
@ -63,6 +63,9 @@ Bug Fixes
|
|||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- We now generate a diagnostic for signed integer overflow due to unary minus
|
||||
in a non-constant expression context. This fixes
|
||||
`Issue 31643 <https://github.com/llvm/llvm-project/issues/31643>`_
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
-------------------------------------------------
|
||||
|
|
|
@ -13502,10 +13502,16 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
|
|||
return false;
|
||||
if (!Result.isInt()) return Error(E);
|
||||
const APSInt &Value = Result.getInt();
|
||||
if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow() &&
|
||||
!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
|
||||
E->getType()))
|
||||
return false;
|
||||
if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
|
||||
if (Info.checkingForUndefinedBehavior())
|
||||
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
|
||||
diag::warn_integer_constant_overflow)
|
||||
<< toString(Value, 10) << E->getType();
|
||||
|
||||
if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
|
||||
E->getType()))
|
||||
return false;
|
||||
}
|
||||
return Success(-Value, E);
|
||||
}
|
||||
case UO_Not: {
|
||||
|
|
|
@ -14876,7 +14876,7 @@ void Sema::CheckForIntOverflow (Expr *E) {
|
|||
Expr *OriginalE = Exprs.pop_back_val();
|
||||
Expr *E = OriginalE->IgnoreParenCasts();
|
||||
|
||||
if (isa<BinaryOperator>(E)) {
|
||||
if (isa<BinaryOperator, UnaryOperator>(E)) {
|
||||
E->EvaluateForOverflow(Context);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -146,6 +146,7 @@ namespace UndefinedBehavior {
|
|||
|
||||
constexpr int int_min = ~0x7fffffff;
|
||||
constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
constexpr int minus_int_min_from_shift = -(1<<31); // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}}
|
||||
constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}}
|
||||
constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
|
|
|
@ -208,3 +208,9 @@ namespace EvaluationCrashes {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace GH31643 {
|
||||
void f() {
|
||||
int a = -(1<<31); // expected-warning {{overflow in expression; result is -2147483648 with type 'int'}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,6 +179,7 @@ constexpr int slow_init_list[] = {1, 1, 2, 3, 5, 8, 13, 21}; // 25th line
|
|||
Frontend
|
||||
| EvaluateAsRValue (<test.cc:8:21>)
|
||||
| EvaluateForOverflow (<test.cc:8:21, col:25>)
|
||||
| EvaluateForOverflow (<test.cc:8:30, col:32>)
|
||||
| EvaluateAsRValue (<test.cc:9:14>)
|
||||
| EvaluateForOverflow (<test.cc:9:9, col:14>)
|
||||
| isPotentialConstantExpr (slow_namespace::slow_func)
|
||||
|
|
Loading…
Reference in New Issue
Block a user