Move all int literal parsing and checking code together.
Report error for negated hex literals > 2^63.
Optimized common case of web int literal exactness check.
Fixes https://github.com/dart-lang/sdk/issues/33311
Change-Id: Ib72b2dbb21e42489ee2d06b17302daf83d560df1
Reviewed-on: https://dart-review.googlesource.com/72802
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 92aeaeb..87570fa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -75,7 +75,7 @@
IncompletePropertyAccessGenerator,
IncompleteSendGenerator,
IndexedAccessGenerator,
- LargeIntAccessGenerator,
+ IntAccessGenerator,
LoadLibraryGenerator,
ParenthesizedExpressionGenerator,
PrefixUseGenerator,
@@ -136,8 +136,6 @@
final bool stringExpectedAfterNative;
- final bool errorOnUnexactWebIntLiterals;
-
/// Whether to ignore an unresolved reference to `main` within the body of
/// `_getMainClosure` when compiling the current library.
///
@@ -231,8 +229,6 @@
library.loader.target.backendTarget.enableNative(library.uri),
stringExpectedAfterNative =
library.loader.target.backendTarget.nativeExtensionExpectsString,
- errorOnUnexactWebIntLiterals =
- library.loader.target.backendTarget.errorOnUnexactWebIntLiterals,
ignoreMainInGetMainClosure = library.uri.scheme == 'dart' &&
(library.uri.path == "_builtin" || library.uri.path == "ui"),
needsImplicitSuperInitializer =
@@ -1806,15 +1802,7 @@
@override
void handleLiteralInt(Token token) {
debugEvent("LiteralInt");
- int value = int.parse(token.lexeme, onError: (_) => null);
- if (value == null) {
- push(new LargeIntAccessGenerator(this, token));
- } else {
- if (errorOnUnexactWebIntLiterals) {
- checkWebIntLiteralsErrorIfUnexact(value, token);
- }
- push(forest.literalInt(value, token));
- }
+ push(IntAccessGenerator.parseIntLiteral(this, token));
}
@override
@@ -2757,14 +2745,8 @@
if (optional("-", token)) {
operator = "unary-";
- if (receiver is LargeIntAccessGenerator) {
- int value = int.tryParse("-" + receiver.token.lexeme);
- if (value != null) {
- receiverValue = forest.literalInt(value, receiver.token);
- if (errorOnUnexactWebIntLiterals) {
- checkWebIntLiteralsErrorIfUnexact(value, token);
- }
- }
+ if (receiver is IntAccessGenerator) {
+ receiverValue = receiver.buildNegatedRead();
}
}
bool isSuper = false;
@@ -4489,26 +4471,6 @@
forest.isErroneousNode(node);
}
- void checkWebIntLiteralsErrorIfUnexact(int value, Token token) {
- BigInt asInt = new BigInt.from(value).toUnsigned(64);
- BigInt asDouble = new BigInt.from(asInt.toDouble());
- if (asInt != asDouble) {
- String nearest;
- if (token.lexeme.startsWith("0x") || token.lexeme.startsWith("0X")) {
- nearest = '0x${asDouble.toRadixString(16)}';
- } else {
- nearest = '$asDouble';
- }
- library.addProblem(
- fasta.templateWebLiteralCannotBeRepresentedExactly
- .withArguments(token.lexeme, nearest),
- token.charOffset,
- token.charCount,
- uri,
- wasHandled: true);
- }
- }
-
@override
DartType buildDartType(UnresolvedType<KernelTypeBuilder> unresolvedType,
{bool nonInstanceAccessIsError: false}) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index f81b7ef..ba11d9f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -25,7 +25,8 @@
templateMissingExplicitTypeArguments,
templateNotAPrefixInTypeAnnotation,
templateNotAType,
- templateUnresolvedPrefixInTypeAnnotation;
+ templateUnresolvedPrefixInTypeAnnotation,
+ templateWebLiteralCannotBeRepresentedExactly;
import '../names.dart'
show
@@ -663,10 +664,9 @@
String get debugName => "ReadOnlyAccessGenerator";
}
-abstract class LargeIntAccessGenerator implements Generator {
- factory LargeIntAccessGenerator(
- ExpressionGeneratorHelper helper, Token token) {
- return helper.forest.largeIntAccessGenerator(helper, token);
+abstract class IntAccessGenerator implements Generator {
+ factory IntAccessGenerator(ExpressionGeneratorHelper helper, Token token) {
+ return helper.forest.intAccessGenerator(helper, token);
}
// TODO(ahe): This should probably be calling unhandled.
@@ -674,7 +674,66 @@
String get plainNameForRead => null;
@override
- String get debugName => "LargeIntAccessGenerator";
+ String get debugName => "IntAccessGenerator";
+
+ static void checkWebIntLiteralsErrorIfUnexact(
+ ExpressionGeneratorHelper helper, int value, Token token) {
+ if (value >= 0 && value <= (1 << 53)) return;
+ if (!helper.library.loader.target.backendTarget
+ .errorOnUnexactWebIntLiterals) return;
+ BigInt asInt = new BigInt.from(value).toUnsigned(64);
+ BigInt asDouble = new BigInt.from(asInt.toDouble());
+ if (asInt != asDouble) {
+ String nearest;
+ if (token.lexeme.startsWith("0x") || token.lexeme.startsWith("0X")) {
+ nearest = '0x${asDouble.toRadixString(16)}';
+ } else {
+ nearest = '$asDouble';
+ }
+ helper.addProblem(
+ templateWebLiteralCannotBeRepresentedExactly.withArguments(
+ token.lexeme, nearest),
+ token.charOffset,
+ token.charCount);
+ }
+ }
+
+ static Object parseIntLiteral(ExpressionGeneratorHelper helper, Token token) {
+ int value = int.tryParse(token.lexeme);
+ // Postpone parsing of literals resulting in a negative value
+ // (hex literals >= 2^63). These are only allowed when not negated.
+ if (value == null || value < 0) {
+ return new IntAccessGenerator(helper, token);
+ } else {
+ checkWebIntLiteralsErrorIfUnexact(helper, value, token);
+ return helper.forest.literalInt(value, token);
+ }
+ }
+
+ Expression parseOrError(String literal, Token token) {
+ int value = int.tryParse(literal);
+ if (value != null) {
+ checkWebIntLiteralsErrorIfUnexact(helper, value, token);
+ return helper.forest.literalInt(value, token);
+ } else {
+ return buildError();
+ }
+ }
+
+ @override
+ Expression buildSimpleRead() {
+ // Called when literal that previously failed to parse, or resulted in
+ // a negative value (hex literals >= 2^63), is not negated.
+ // Try parsing again, this time accepting negative values.
+ return parseOrError(token.lexeme, token);
+ }
+
+ Expression buildNegatedRead() {
+ // Called when literal that previously failed to parse, or resulted in
+ // a negative value (hex literals >= 2^63), is negated.
+ // Try parsing with a '-' in front.
+ return parseOrError("-" + token.lexeme, token);
+ }
SyntheticExpressionJudgment buildError() {
return helper.buildProblem(
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index fd18029..f0f16e5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -44,7 +44,7 @@
KernelDelayedAssignment,
KernelDelayedPostfixIncrement,
KernelIndexedAccessGenerator,
- KernelLargeIntAccessGenerator,
+ KernelIntAccessGenerator,
KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelPrefixUseGenerator,
@@ -697,9 +697,9 @@
}
@override
- KernelLargeIntAccessGenerator largeIntAccessGenerator(
+ KernelIntAccessGenerator intAccessGenerator(
ExpressionGeneratorHelper helper, Token token) {
- return new KernelLargeIntAccessGenerator(helper, token);
+ return new KernelIntAccessGenerator(helper, token);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 86f4e31..ffb30fa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -386,7 +386,7 @@
Generator readOnlyAccessGenerator(ExpressionGeneratorHelper helper,
Token location, Expression expression, String plainNameForRead);
- Generator largeIntAccessGenerator(
+ Generator intAccessGenerator(
ExpressionGeneratorHelper helper, Token location);
Generator unresolvedNameGenerator(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index 403b63e..a3de284 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -45,7 +45,7 @@
ExpressionGenerator,
Generator,
IndexedAccessGenerator,
- LargeIntAccessGenerator,
+ IntAccessGenerator,
LoadLibraryGenerator,
NullAwarePropertyAccessGenerator,
PrefixUseGenerator,
@@ -1390,9 +1390,8 @@
}
}
-class KernelLargeIntAccessGenerator extends KernelGenerator
- with LargeIntAccessGenerator {
- KernelLargeIntAccessGenerator(ExpressionGeneratorHelper helper, Token token)
+class KernelIntAccessGenerator extends KernelGenerator with IntAccessGenerator {
+ KernelIntAccessGenerator(ExpressionGeneratorHelper helper, Token token)
: super(helper, token);
@override
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index b8baa33..cd77f74 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -59,7 +59,7 @@
KernelDelayedAssignment,
KernelDelayedPostfixIncrement,
KernelIndexedAccessGenerator,
- KernelLargeIntAccessGenerator,
+ KernelIntAccessGenerator,
KernelLoadLibraryGenerator,
KernelNullAwarePropertyAccessGenerator,
KernelPrefixUseGenerator,
@@ -222,8 +222,8 @@
"ReadOnlyAccessGenerator(offset: 4, expression: expression,"
" plainNameForRead: foo, value: null)",
new KernelReadOnlyAccessGenerator(helper, token, expression, "foo"));
- check("LargeIntAccessGenerator(offset: 4, lexeme: myToken)",
- new KernelLargeIntAccessGenerator(helper, token));
+ check("IntAccessGenerator(offset: 4, lexeme: myToken)",
+ new KernelIntAccessGenerator(helper, token));
check(
"ParenthesizedExpressionGenerator(offset: 4, expression: expression,"
" plainNameForRead: null, value: null)",
diff --git a/runtime/tests/vm/dart/byte_array_optimized_test.dart b/runtime/tests/vm/dart/byte_array_optimized_test.dart
index 827b93c..ca3b432 100644
--- a/runtime/tests/vm/dart/byte_array_optimized_test.dart
+++ b/runtime/tests/vm/dart/byte_array_optimized_test.dart
@@ -899,9 +899,9 @@
Expect.isTrue(copy is Uint64List);
Expect.equals(4, region.length);
Expect.listEquals([3, 4, 5, 6], region);
- array.setRange(3, 7, [-0x8000000000000001, 0, 1, 0xFFFFFFFFFFFFFFFF]);
+ array.setRange(3, 7, [-0x8000000000000000, 0, 1, 0xFFFFFFFFFFFFFFFF]);
Expect.listEquals(
- [0, 1, 2, -0x8000000000000001, 0, 1, 0xFFFFFFFFFFFFFFFF, 7, 8, 9],
+ [0, 1, 2, -0x8000000000000000, 0, 1, 0xFFFFFFFFFFFFFFFF, 7, 8, 9],
array);
}
diff --git a/runtime/tests/vm/dart/byte_array_test.dart b/runtime/tests/vm/dart/byte_array_test.dart
index d3dc4b2..a476301 100644
--- a/runtime/tests/vm/dart/byte_array_test.dart
+++ b/runtime/tests/vm/dart/byte_array_test.dart
@@ -1022,9 +1022,9 @@
Expect.isTrue(copy is Uint64List);
Expect.equals(4, region.length);
Expect.listEquals([3, 4, 5, 6], region);
- array.setRange(3, 7, [-0x8000000000000001, 0, 1, 0xFFFFFFFFFFFFFFFF]);
+ array.setRange(3, 7, [-0x8000000000000000, 0, 1, 0xFFFFFFFFFFFFFFFF]);
Expect.listEquals(
- [0, 1, 2, -0x8000000000000001, 0, 1, 0xFFFFFFFFFFFFFFFF, 7, 8, 9],
+ [0, 1, 2, -0x8000000000000000, 0, 1, 0xFFFFFFFFFFFFFFFF, 7, 8, 9],
array);
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 3fd79b0..9170ada 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -35,10 +35,6 @@
dart/redirection_type_shuffling_test/none: RuntimeError
dart/snapshot_version_test: RuntimeError
-[ $compiler == dart2analyzer ]
-dart/byte_array_optimized_test: CompileTimeError # int64
-dart/byte_array_test: CompileTimeError # int64
-
[ $compiler == dart2js ]
dart/byte_array_optimized_test: Skip # compilers not aware of byte arrays
dart/byte_array_test: Skip # compilers not aware of byte arrays
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 8d25bec..e276dd0 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -1318,6 +1318,7 @@
LibTest/core/AssertionError/AssertionError_A01_t01: CompileTimeError
LibTest/core/AssertionError/message_A01_t01: CompileTimeError
LibTest/core/AssertionError/toString_A01_t01: CompileTimeError
+LibTest/core/Duration/Duration_A02_t01: CompileTimeError
LibTest/core/FallThroughError/toString_A01_t02: CompileTimeError
LibTest/core/Invocation/isAccessor_A01_t01: CompileTimeError
LibTest/core/Invocation/isAccessor_A01_t02: CompileTimeError
diff --git a/tests/language_2/int64_literal_test.dart b/tests/language_2/int64_literal_test.dart
index 9c0cb77..5c54736 100644
--- a/tests/language_2/int64_literal_test.dart
+++ b/tests/language_2/int64_literal_test.dart
@@ -3,22 +3,30 @@
const String realMaxInt64Value = '9223372036854775807';
const String realMinInt64Value = '-9223372036854775808';
+const int i21 = 2097152;
+
main() {
- int minInt64Value = (-9223372036854775807) - 1;
- minInt64Value = -(1 << 63); /// 01: ok
+ int minInt64Value = -1 * i21 * i21 * i21;
+ minInt64Value = -9223372036854775807 - 1; /// 01: ok
minInt64Value = -9223372036854775808; /// 02: ok
minInt64Value = -(9223372036854775808); /// 03: compile-time error
minInt64Value = -(0x8000000000000000); /// 04: ok
minInt64Value = 0x8000000000000000; /// 05: ok
+ minInt64Value = -0x8000000000000000; /// 06: ok
Expect.equals('$minInt64Value', realMinInt64Value);
Expect.equals('${minInt64Value - 1}', realMaxInt64Value);
- int maxInt64Value = 9223372036854775807;
- maxInt64Value = (1 << 63) - 1; /// 10: ok
- maxInt64Value = 9223372036854775807; /// 20: ok
- maxInt64Value = 9223372036854775808 - 1; /// 30: compile-time error
- maxInt64Value = 0x8000000000000000 - 1; /// 40: ok
+ int maxInt64Value = 1 * i21 * i21 * i21 - 1;
+ maxInt64Value = 9223372036854775807; /// 11: ok
+ maxInt64Value = 9223372036854775807; /// 12: ok
+ maxInt64Value = 9223372036854775808 - 1; /// 13: compile-time error
+ maxInt64Value = -9223372036854775808 - 1; /// 14: ok
+ maxInt64Value = -9223372036854775809; /// 15: compile-time error
+ maxInt64Value = 0x8000000000000000 - 1; /// 16: ok
+ maxInt64Value = -0x8000000000000000 - 1; /// 17: ok
+ maxInt64Value = -0x8000000000000001; /// 18: compile-time error
+ maxInt64Value = -(0x8000000000000001); /// 19: ok
Expect.equals('$maxInt64Value', realMaxInt64Value);
Expect.equals('${maxInt64Value + 1}', realMinInt64Value);
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 708b760..228a5bd 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -36,13 +36,17 @@
instantiate_tearoff_of_call_test: RuntimeError
int2_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
int64_literal_test/01: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/02: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/04: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/05: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/10: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/20: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/40: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
-int64_literal_test/none: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/02: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/04: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/05: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/06: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/11: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/12: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/14: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/16: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/17: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/19: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
+int64_literal_test/none: RuntimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
issue32353_test: CompileTimeError
issue34404_flutter_test: CompileTimeError # --supermixin not supported
@@ -589,14 +593,6 @@
infinity_test: RuntimeError # non JS number semantics - Issue 4984
instance_creation_in_function_annotation_test: RuntimeError
instantiate_tearoff_of_call_test: CompileTimeError
-int64_literal_test/01: RuntimeError
-int64_literal_test/02: RuntimeError
-int64_literal_test/04: RuntimeError
-int64_literal_test/05: RuntimeError
-int64_literal_test/10: RuntimeError
-int64_literal_test/20: RuntimeError
-int64_literal_test/40: RuntimeError
-int64_literal_test/none: RuntimeError
integer_division_by_zero_test: RuntimeError # Issue 8301
internal_library_test/02: Crash
invocation_mirror_invoke_on2_test: RuntimeError