Refuse to negate a literal if it would over/underflow its type.

Previously, we would create a Literal with the negated value even if it
was outside the type's minimum/maximum values. Error reporting would
happen elsewhere, if at all (e.g. during assignment or coercion).

Change-Id: I020a93daf2b0f5741fb805a58a690489d7578dab
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/464123
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-10-27 11:24:09 -04:00 committed by SkCQ
parent 5c905c94f0
commit 2bdb65dcf2
3 changed files with 19 additions and 11 deletions

View File

@ -1,4 +1,4 @@
// Expect 10 errors
// Expect 8 errors
const int intMin = -2147483648;
const int intMinMinusOne = -2147483649; // error
@ -17,12 +17,12 @@ void main() {
32767);
int4 i4 = int4(intMin,
intMinMinusOne, // error
intMinMinusOne,
intMax,
intMaxPlusOne); // error
uint4 ui4 = uint4(intMin, // error
intMinMinusOne, // error
intMinMinusOne,
intMax,
intMaxPlusOne);
}

View File

@ -27,12 +27,22 @@ static std::unique_ptr<Expression> simplify_negation(const Context& context,
const Expression& originalExpr) {
const Expression* value = ConstantFolder::GetConstantValueForVariable(originalExpr);
switch (value->kind()) {
case Expression::Kind::kLiteral:
case Expression::Kind::kLiteral: {
// Convert -literal(1) to literal(-1).
return Literal::Make(originalExpr.fLine,
-value->as<Literal>().value(),
&value->type());
double negated = -value->as<Literal>().value();
// Don't simplify the expression if the type can't hold the negated value.
const Type& type = value->type();
if (type.isInteger()) {
if (negated < type.minimumValue() || negated > type.maximumValue()) {
context.fErrors->error(originalExpr.fLine,
String("integer is out of range for type '") +
type.displayName().c_str() + "': -" +
to_string(value->as<Literal>().intValue()));
return nullptr;
}
}
return Literal::Make(originalExpr.fLine, negated, &type);
}
case Expression::Kind::kPrefix:
if (context.fConfig->fSettings.fOptimize) {
// Convert `-(-expression)` into `expression`.

View File

@ -6,8 +6,6 @@ error: 9: integer is out of range for type 'ushort4': -1
error: 9: integer is out of range for type 'ushort4': 65536
error: 14: integer is out of range for type 'short4': -32769
error: 14: integer is out of range for type 'short4': 32768
error: 20: unknown identifier 'intMinMinusOne'
error: 22: unknown identifier 'intMaxPlusOne'
error: 25: unknown identifier 'intMinMinusOne'
error: 27: unknown identifier 'intMaxPlusOne'
10 errors
8 errors