Avoid error cascades when casting out-of-range scalar values.

Previously, when attempting to cast a huge value to an int, SkSL would
report an error, then return the IR for
`ScalarCast(Int, FloatLiteral(huge-value))` . Now, to minimize the blast
radius of the error, we report the error but return `IntLiteral(0)`.
We've already reported an error, so there's no need to preserve the
value, and zero is less likely to produce follow-up errors.

(A similar approach is used here and worked well: https://osscs.corp.google.com/skia/skia/+/main:src/sksl/ir/SkSLConstructorCompoundCast.cpp;l=57-59)

Change-Id: Ie8e8d48380cb963466d1f47d123d64e3301cf87c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/499563
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2022-01-25 13:06:47 -05:00 committed by SkCQ
parent de7193cd81
commit 4d1a935835
4 changed files with 13 additions and 12 deletions

View File

@ -70,12 +70,15 @@ std::unique_ptr<Expression> ConstructorScalarCast::Make(const Context& context,
arg = ConstantFolder::MakeConstantValueForVariable(std::move(arg));
// We can cast scalar literals at compile-time when possible. (If the resulting literal would be
// out of range for its type, we report an error and return the constructor. This can occur when
// code is inlined, so we can't necessarily catch it during Convert. As such, it's not safe to
// return null or assert.)
if (arg->is<Literal>() &&
!type.checkForOutOfRangeLiteral(context, arg->as<Literal>().value(), arg->fLine)) {
return Literal::Make(line, arg->as<Literal>().value(), &type);
// out of range for its type, we report an error and return zero to minimize error cascading.
// This can occur when code is inlined, so we can't necessarily catch it during Convert. As
// such, it's not safe to return null or assert.)
if (arg->is<Literal>()) {
double value = arg->as<Literal>().value();
if (type.checkForOutOfRangeLiteral(context, value, arg->fLine)) {
value = 0.0;
}
return Literal::Make(line, value, &type);
}
return std::make_unique<ConstructorScalarCast>(line, type, std::move(arg));
}

View File

@ -5,7 +5,7 @@ error: 2: array size must be positive
error: 3: array size must be positive
error: 4: expected 'int', but found 'float'
error: 5: integer is out of range for type 'int': 4000000000
error: 5: array size must be an integer
error: 5: array size must be positive
error: 6: expected 'int', but found 'bool'
error: 7: expected 'int', but found 'bool'
error: 8: expected 'int', but found 'int2'

View File

@ -4,7 +4,6 @@ error: 1: unknown identifier 'f'
error: 1: expected ')' to complete function arguments, but found '`'
error: 1: expected ')' to complete expression, but found '`'
error: 1: integer is out of range for type 'int': 3689348940
error: 1: integer is out of range for type 'int': 3689348940
error: 2: expected ']' to complete array access expression, but found ''
error: 2: expected ';', but found ''
7 errors
6 errors

View File

@ -1,6 +1,5 @@
### Compilation failed:
error: 1: integer is out of range for type 'int': 3976000000
error: 1: integer is out of range for type 'int': 3976000000
error: 1: array size must be an integer
3 errors
error: 1: array size must be positive
2 errors