From 5a1ef6089c7b9b0c1120dbf8a845c7ff7774deb3 Mon Sep 17 00:00:00 2001 From: Oleh Prypin Date: Mon, 22 Jan 2024 12:20:48 +0000 Subject: [PATCH] Revert "[ffi]: Remove pointer elementAt method." This reverts commit f706ff4ee2ecbf7818999723c68f77de514f1222. Reason for revert: b/321667799 - package:win32 uses this method - https://github.com/dart-windows/win32/blob/a78ff108fbf54927b0334c1bab8f15526c24cbf8/lib/src/com/iapplicationactivationmanager.dart#L46 Original change's description: > [ffi]: Remove pointer elementAt method. > > Closes #54250 > > TEST=test/ffi > > R=dacoharkes@google.com > Change-Id: I0e88adfcfe3caef0ad3bb6814ad8f27dce5dc7f4 > CoreLibraryReviewExempt: FFI only > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346380 > Reviewed-by: Daco Harkes > Commit-Queue: Martin Kustermann > Reviewed-by: Martin Kustermann > Auto-Submit: Shikhar Change-Id: I1b7a48d14e9b85676a27f76a926e21cac9c76c85 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/347600 Reviewed-by: Martin Kustermann Reviewed-by: Daco Harkes Commit-Queue: Daco Harkes --- DEPS | 4 +- .../FfiCall/dart/benchmark_generated.dart | 192 +++++++++--------- benchmarks/FfiCall/generate_benchmarks.dart | 4 +- pkg/mmap/lib/src/mmap_impl.dart | 2 +- pkg/vm/lib/transformations/ffi/common.dart | 20 ++ pkg/vm/lib/transformations/ffi/use_sites.dart | 10 +- runtime/tools/ffi/sdk_lib_ffi_generator.dart | 4 + .../ffi/resource_management/arena_sample.dart | 4 +- .../arena_zoned_sample.dart | 4 +- .../resource_management/unmanaged_sample.dart | 2 +- samples/ffi/sample_ffi_data.dart | 6 +- samples/ffi/sample_ffi_functions.dart | 2 +- samples/ffi/sample_ffi_functions_structs.dart | 4 +- samples/ffi/sample_ffi_structs.dart | 4 +- sdk/lib/_internal/vm/lib/ffi_patch.dart | 16 ++ sdk/lib/ffi/ffi.dart | 71 +++++++ .../abi_specific_int_incomplete_jit_test.dart | 2 +- tests/ffi/abi_specific_int_test.dart | 4 +- tests/ffi/aliasing_test.dart | 14 +- tests/ffi/data_test.dart | 8 +- tests/ffi/extension_methods_test.dart | 10 +- tests/ffi/function_callbacks_test.dart | 4 +- tests/ffi/function_structs_test.dart | 18 +- tests/ffi/function_test.dart | 2 +- tests/ffi/regress_39885_test.dart | 2 +- tests/ffi/structs_nnbd_workaround_test.dart | 4 +- tests/ffi/structs_test.dart | 58 ++++++ tests/ffi/unaligned_test.dart | 2 +- tests/ffi/vmspecific_regress_37511_test.dart | 1 + tests/ffi/vmspecific_static_checks_test.dart | 29 +++ 30 files changed, 356 insertions(+), 151 deletions(-) diff --git a/DEPS b/DEPS index 140e95fd17f..a2608274f73 100644 --- a/DEPS +++ b/DEPS @@ -50,7 +50,7 @@ vars = { # Checked-in SDK version. The checked-in SDK is a Dart SDK distribution # in a cipd package used to run Dart scripts in the build and test # infrastructure, which is automatically built on the release commits. - "sdk_tag": "version:3.3.0-279.1.beta", + "sdk_tag": "version:3.2.4", # co19 is a cipd package automatically generated for each co19 commit. # Use tests/co19/update.sh to update this hash. @@ -142,7 +142,7 @@ vars = { "dart_style_rev": "8b1f24a8475a0116757172cd9acca4acbf87d973", # disable rev_sdk_deps.dart "dartdoc_rev": "b04c9c127fea5f3fdf600aa205f50d81d1c779c5", # https://github.com/dart-lang/dartdoc/issues/3562 "ecosystem_rev": "1e2785d6900b4d709a31f4c669381dc340cad605", - "ffi_rev": "76c581a0ad0cfe585cc8d7084c6afaa95a9696f5", + "ffi_rev": "c926657618443ff4821411ede01684096b503f84", "file_rev": "cd3a9324f6483f313ba1f0f3ff382ea4e6982ef2", "fixnum_rev": "3e08c0d7ce1a0cd832a17391444898ec610b5f89", "flute_rev": "f42b09f77132210499ec8ed819a60c260af03db6", diff --git a/benchmarks/FfiCall/dart/benchmark_generated.dart b/benchmarks/FfiCall/dart/benchmark_generated.dart index 1484fadaeea..5505d3371da 100644 --- a/benchmarks/FfiCall/dart/benchmark_generated.dart +++ b/benchmarks/FfiCall/dart/benchmark_generated.dart @@ -2135,7 +2135,7 @@ class PointerUint8x02 extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; + p2 = p1.elementAt(1); } @override @@ -2168,7 +2168,7 @@ class PointerUint8x02Native extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; + p2 = p1.elementAt(1); } @override @@ -2201,7 +2201,7 @@ class PointerUint8x02NativeLeaf extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; + p2 = p1.elementAt(1); } @override @@ -2238,9 +2238,9 @@ class PointerUint8x04 extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); } @override @@ -2275,9 +2275,9 @@ class PointerUint8x04Native extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); } @override @@ -2312,9 +2312,9 @@ class PointerUint8x04NativeLeaf extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); } @override @@ -2358,15 +2358,15 @@ class PointerUint8x10 extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); } @override @@ -2416,15 +2416,15 @@ class PointerUint8x10Native extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); } @override @@ -2474,15 +2474,15 @@ class PointerUint8x10NativeLeaf extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); } @override @@ -2536,25 +2536,25 @@ class PointerUint8x20 extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; - p11 = p1 + 10; - p12 = p1 + 11; - p13 = p1 + 12; - p14 = p1 + 13; - p15 = p1 + 14; - p16 = p1 + 15; - p17 = p1 + 16; - p18 = p1 + 17; - p19 = p1 + 18; - p20 = p1 + 19; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); + p11 = p1.elementAt(10); + p12 = p1.elementAt(11); + p13 = p1.elementAt(12); + p14 = p1.elementAt(13); + p15 = p1.elementAt(14); + p16 = p1.elementAt(15); + p17 = p1.elementAt(16); + p18 = p1.elementAt(17); + p19 = p1.elementAt(18); + p20 = p1.elementAt(19); } @override @@ -2625,25 +2625,25 @@ class PointerUint8x20Native extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; - p11 = p1 + 10; - p12 = p1 + 11; - p13 = p1 + 12; - p14 = p1 + 13; - p15 = p1 + 14; - p16 = p1 + 15; - p17 = p1 + 16; - p18 = p1 + 17; - p19 = p1 + 18; - p20 = p1 + 19; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); + p11 = p1.elementAt(10); + p12 = p1.elementAt(11); + p13 = p1.elementAt(12); + p14 = p1.elementAt(13); + p15 = p1.elementAt(14); + p16 = p1.elementAt(15); + p17 = p1.elementAt(16); + p18 = p1.elementAt(17); + p19 = p1.elementAt(18); + p20 = p1.elementAt(19); } @override @@ -2714,25 +2714,25 @@ class PointerUint8x20NativeLeaf extends FfiBenchmarkBase { @override void setup() { p1 = calloc(N + 1); - p2 = p1 + 1; - p3 = p1 + 2; - p4 = p1 + 3; - p5 = p1 + 4; - p6 = p1 + 5; - p7 = p1 + 6; - p8 = p1 + 7; - p9 = p1 + 8; - p10 = p1 + 9; - p11 = p1 + 10; - p12 = p1 + 11; - p13 = p1 + 12; - p14 = p1 + 13; - p15 = p1 + 14; - p16 = p1 + 15; - p17 = p1 + 16; - p18 = p1 + 17; - p19 = p1 + 18; - p20 = p1 + 19; + p2 = p1.elementAt(1); + p3 = p1.elementAt(2); + p4 = p1.elementAt(3); + p5 = p1.elementAt(4); + p6 = p1.elementAt(5); + p7 = p1.elementAt(6); + p8 = p1.elementAt(7); + p9 = p1.elementAt(8); + p10 = p1.elementAt(9); + p11 = p1.elementAt(10); + p12 = p1.elementAt(11); + p13 = p1.elementAt(12); + p14 = p1.elementAt(13); + p15 = p1.elementAt(14); + p16 = p1.elementAt(15); + p17 = p1.elementAt(16); + p18 = p1.elementAt(17); + p19 = p1.elementAt(18); + p20 = p1.elementAt(19); } @override diff --git a/benchmarks/FfiCall/generate_benchmarks.dart b/benchmarks/FfiCall/generate_benchmarks.dart index 665b34cbf59..91e5398f3ce 100644 --- a/benchmarks/FfiCall/generate_benchmarks.dart +++ b/benchmarks/FfiCall/generate_benchmarks.dart @@ -230,8 +230,8 @@ void generateBenchmarkPointer(StringBuffer buffer, List types) { List.generate(number, (i) => 'p${i + 1}'); final String pointers = pointerNames.map((n) => '$type $n = nullptr;').join('\n'); - final String setup = - List.generate(number - 1, (i) => 'p${i + 2} = p1 + ${i + 1};').join(); + final String setup = List.generate( + number - 1, (i) => 'p${i + 2} = p1.elementAt(${i + 1});').join(); final String functionType = 'Function$number$dartTypeName'; final String functionNativeType = 'NativeFunction$number$typeName'; final String functionNameC = 'Function$number$typeName'; diff --git a/pkg/mmap/lib/src/mmap_impl.dart b/pkg/mmap/lib/src/mmap_impl.dart index 721f6f45453..4081b42487a 100644 --- a/pkg/mmap/lib/src/mmap_impl.dart +++ b/pkg/mmap/lib/src/mmap_impl.dart @@ -140,7 +140,7 @@ final finalizerAddress = () { throw 'Failed to write executable code to the memory.'; } - return (finalizerStub + offset).cast(); + return finalizerStub.elementAt(offset).cast(); }(); base class PeerData extends Struct { diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart index a1e683fd1b0..e03894373f5 100644 --- a/pkg/vm/lib/transformations/ffi/common.dart +++ b/pkg/vm/lib/transformations/ffi/common.dart @@ -212,14 +212,18 @@ class FfiTransformer extends Transformer { final Procedure structPointerSetRef; final Procedure structPointerGetElemAt; final Procedure structPointerSetElemAt; + final Procedure structPointerElementAt; final Procedure structPointerPlusOperator; final Procedure structPointerMinusOperator; + final Procedure structPointerElementAtTearoff; final Procedure unionPointerGetRef; final Procedure unionPointerSetRef; final Procedure unionPointerGetElemAt; final Procedure unionPointerSetElemAt; + final Procedure unionPointerElementAt; final Procedure unionPointerPlusOperator; final Procedure unionPointerMinusOperator; + final Procedure unionPointerElementAtTearoff; final Procedure structArrayElemAt; final Procedure unionArrayElemAt; final Procedure arrayArrayElemAt; @@ -228,8 +232,10 @@ class FfiTransformer extends Transformer { final Procedure abiSpecificIntegerPointerSetValue; final Procedure abiSpecificIntegerPointerElemAt; final Procedure abiSpecificIntegerPointerSetElemAt; + final Procedure abiSpecificIntegerPointerElementAt; final Procedure abiSpecificIntegerPointerPlusOperator; final Procedure abiSpecificIntegerPointerMinusOperator; + final Procedure abiSpecificIntegerPointerElementAtTearoff; final Procedure abiSpecificIntegerArrayElemAt; final Procedure abiSpecificIntegerArraySetElemAt; final Procedure asFunctionMethod; @@ -427,10 +433,14 @@ class FfiTransformer extends Transformer { index.getProcedure('dart:ffi', 'StructPointer', '[]'), structPointerSetElemAt = index.getProcedure('dart:ffi', 'StructPointer', '[]='), + structPointerElementAt = + index.getProcedure('dart:ffi', 'StructPointer', 'elementAt'), structPointerPlusOperator = index.getProcedure('dart:ffi', 'StructPointer', '+'), structPointerMinusOperator = index.getProcedure('dart:ffi', 'StructPointer', '-'), + structPointerElementAtTearoff = index.getProcedure('dart:ffi', + 'StructPointer', LibraryIndex.tearoffPrefix + 'elementAt'), unionPointerGetRef = index.getProcedure('dart:ffi', 'UnionPointer', 'get:ref'), unionPointerSetRef = @@ -439,10 +449,14 @@ class FfiTransformer extends Transformer { index.getProcedure('dart:ffi', 'UnionPointer', '[]'), unionPointerSetElemAt = index.getProcedure('dart:ffi', 'UnionPointer', '[]='), + unionPointerElementAt = + index.getProcedure('dart:ffi', 'UnionPointer', 'elementAt'), unionPointerPlusOperator = index.getProcedure('dart:ffi', 'UnionPointer', '+'), unionPointerMinusOperator = index.getProcedure('dart:ffi', 'UnionPointer', '-'), + unionPointerElementAtTearoff = index.getProcedure('dart:ffi', + 'UnionPointer', LibraryIndex.tearoffPrefix + 'elementAt'), structArrayElemAt = index.getProcedure('dart:ffi', 'StructArray', '[]'), unionArrayElemAt = index.getProcedure('dart:ffi', 'UnionArray', '[]'), arrayArrayElemAt = index.getProcedure('dart:ffi', 'ArrayArray', '[]'), @@ -456,10 +470,16 @@ class FfiTransformer extends Transformer { index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]'), abiSpecificIntegerPointerSetElemAt = index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '[]='), + abiSpecificIntegerPointerElementAt = index.getProcedure( + 'dart:ffi', 'AbiSpecificIntegerPointer', 'elementAt'), abiSpecificIntegerPointerPlusOperator = index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '+'), abiSpecificIntegerPointerMinusOperator = index.getProcedure('dart:ffi', 'AbiSpecificIntegerPointer', '-'), + abiSpecificIntegerPointerElementAtTearoff = index.getProcedure( + 'dart:ffi', + 'AbiSpecificIntegerPointer', + LibraryIndex.tearoffPrefix + 'elementAt'), abiSpecificIntegerArrayElemAt = index.getProcedure('dart:ffi', 'AbiSpecificIntegerArray', '[]'), abiSpecificIntegerArraySetElemAt = diff --git a/pkg/vm/lib/transformations/ffi/use_sites.dart b/pkg/vm/lib/transformations/ffi/use_sites.dart index 913de78ca50..5b7434f6884 100644 --- a/pkg/vm/lib/transformations/ffi/use_sites.dart +++ b/pkg/vm/lib/transformations/ffi/use_sites.dart @@ -151,7 +151,10 @@ mixin _FfiUseSiteTransformer on FfiTransformer { node.isExtensionMember && (node == allocationTearoff || node == asFunctionTearoff || - node == lookupFunctionTearoff))) || + node == lookupFunctionTearoff || + node == abiSpecificIntegerPointerElementAtTearoff || + node == structPointerElementAtTearoff || + node == unionPointerElementAtTearoff))) || // Dart2wasm uses enabledConstructorTearOffLowerings but these are not // users trying to call constructors. isConstructorTearOffLowering(node); @@ -271,7 +274,10 @@ mixin _FfiUseSiteTransformer on FfiTransformer { ensureNativeTypeValid(nativeType, node, allowCompounds: true); return _replaceSetRef(node); - } else if (target == abiSpecificIntegerPointerPlusOperator || + } else if (target == abiSpecificIntegerPointerElementAt || + target == structPointerElementAt || + target == unionPointerElementAt || + target == abiSpecificIntegerPointerPlusOperator || target == structPointerPlusOperator || target == unionPointerPlusOperator || target == abiSpecificIntegerPointerMinusOperator || diff --git a/runtime/tools/ffi/sdk_lib_ffi_generator.dart b/runtime/tools/ffi/sdk_lib_ffi_generator.dart index 22f2dd710b5..66ab886912b 100644 --- a/runtime/tools/ffi/sdk_lib_ffi_generator.dart +++ b/runtime/tools/ffi/sdk_lib_ffi_generator.dart @@ -224,6 +224,10 @@ $platform$truncate$alignment external $dartType operator [](int index); /// The $property at `address + sizeOf<$nativeType>() * index`. $platform$truncate$alignment external void operator []=(int index, $dartType value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer<$nativeType> elementAt(int index) => Pointer.fromAddress(address + sizeOf<$nativeType>() * index); + /// A pointer to the [offset]th [$nativeType] after this one. /// /// Returns a pointer to the [$nativeType] whose address is diff --git a/samples/ffi/resource_management/arena_sample.dart b/samples/ffi/resource_management/arena_sample.dart index 8dcdfda81dc..94b1f6d8361 100644 --- a/samples/ffi/resource_management/arena_sample.dart +++ b/samples/ffi/resource_management/arena_sample.dart @@ -25,7 +25,7 @@ main() async { using((Arena arena) { final p = arena(2); p[0] = 24; - MemMove((p + 1).cast(), p.cast(), sizeOf()); + MemMove(p.elementAt(1).cast(), p.cast(), sizeOf()); print(p[1]); Expect.equals(24, p[1]); }); @@ -35,7 +35,7 @@ main() async { using((Arena arena) { final p = arena(2); p[0] = 25; - MemMove((p + 1).cast(), p.cast(), 8); + MemMove(p.elementAt(1).cast(), p.cast(), 8); print(p[1]); Expect.equals(25, p[1]); throw Exception("Some random exception"); diff --git a/samples/ffi/resource_management/arena_zoned_sample.dart b/samples/ffi/resource_management/arena_zoned_sample.dart index f3bdf44e645..39d15f19697 100644 --- a/samples/ffi/resource_management/arena_zoned_sample.dart +++ b/samples/ffi/resource_management/arena_zoned_sample.dart @@ -24,7 +24,7 @@ main() async { withZoneArena(() { final p = zoneArena(2); p[0] = 24; - MemMove((p + 1).cast(), p.cast(), sizeOf()); + MemMove(p.elementAt(1).cast(), p.cast(), sizeOf()); print(p[1]); Expect.equals(24, p[1]); }); @@ -34,7 +34,7 @@ main() async { withZoneArena(() { final p = zoneArena(2); p[0] = 25; - MemMove((p + 1).cast(), p.cast(), 8); + MemMove(p.elementAt(1).cast(), p.cast(), 8); print(p[1]); Expect.equals(25, p[1]); throw Exception("Some random exception"); diff --git a/samples/ffi/resource_management/unmanaged_sample.dart b/samples/ffi/resource_management/unmanaged_sample.dart index ac38f3e1ca0..495564df2bb 100644 --- a/samples/ffi/resource_management/unmanaged_sample.dart +++ b/samples/ffi/resource_management/unmanaged_sample.dart @@ -25,7 +25,7 @@ main() { // For automatic management use a Arena. final p = calloc(2); p[0] = 24; - memMove((p + 1).cast(), p.cast(), sizeOf()); + memMove(p.elementAt(1).cast(), p.cast(), sizeOf()); print(p[1]); Expect.equals(24, p[1]); calloc.free(p); diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart index be4ef59288a..ef7ee074c47 100644 --- a/samples/ffi/sample_ffi_data.dart +++ b/samples/ffi/sample_ffi_data.dart @@ -71,7 +71,7 @@ main() { Pointer p2 = p1.cast(); print('${p2.runtimeType} value: ${p2.value}'); // -1 - Pointer p3 = p2 + 1; + Pointer p3 = p2.elementAt(1); print('${p3.runtimeType} value: ${p3.value}'); // 2^31 - 1 calloc.free(p1); @@ -81,10 +81,10 @@ main() { // Data can be tightly packed in memory. Pointer p = calloc(8); for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) { - (p + i).value = i * 3; + p.elementAt(i).value = i * 3; } for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) { - print('(p + $i) value: ${(p + i).value}'); + print('p.elementAt($i) value: ${p.elementAt(i).value}'); } calloc.free(p); } diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart index 4630bf972fb..51376e18fbb 100644 --- a/samples/ffi/sample_ffi_functions.dart +++ b/samples/ffi/sample_ffi_functions.dart @@ -197,7 +197,7 @@ main() { Pointer p2 = calloc(2); p2.value = 42; p2[1] = 1000; - print((p2 + 1).address.toRadixString(16)); + print(p2.elementAt(1).address.toRadixString(16)); print(p2[1]); Pointer result = assign1337Index1(p2); print(p2[1]); diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart index 9d12a137c7c..bf9c0ca4bae 100644 --- a/samples/ffi/sample_ffi_functions_structs.dart +++ b/samples/ffi/sample_ffi_functions_structs.dart @@ -50,8 +50,8 @@ main() { NativeCoordinateOp f1 = p1.asFunction(); Pointer c1 = calloc(3); - Pointer c2 = c1 + 1; - Pointer c3 = c1 + 2; + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); c1.ref.x = 10.0; c1.ref.y = 10.0; c1.ref.next = c3; diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart index 5a0c8506fe2..5f02c1f11b0 100644 --- a/samples/ffi/sample_ffi_structs.dart +++ b/samples/ffi/sample_ffi_structs.dart @@ -40,8 +40,8 @@ main() { { // Allocates coordinates consecutively in c memory. Pointer c1 = calloc(3); - Pointer c2 = c1 + 1; - Pointer c3 = c1 + 2; + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); c1.ref.x = 10.0; c1.ref.y = 10.0; c1.ref.next = c3; diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart index fe035f7d14c..e22aa88240f 100644 --- a/sdk/lib/_internal/vm/lib/ffi_patch.dart +++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart @@ -1094,6 +1094,10 @@ extension PointerPointer on Pointer> { @patch Pointer operator [](int index) => _loadPointer(this, _intPtrSize * index); + @patch + Pointer> elementAt(int index) => + Pointer.fromAddress(address + _intPtrSize * index); + @patch Pointer> operator +(int offset) => Pointer.fromAddress(address + _intPtrSize * offset); @@ -1125,6 +1129,10 @@ extension StructPointer on Pointer { void operator []=(int index, T value) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch + Pointer elementAt(int index) => + throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch Pointer operator +(int offset) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; @@ -1152,6 +1160,10 @@ extension UnionPointer on Pointer { void operator []=(int index, T value) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch + Pointer elementAt(int index) => + throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch Pointer operator +(int offset) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; @@ -1180,6 +1192,10 @@ extension AbiSpecificIntegerPointer void operator []=(int index, int value) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch + Pointer elementAt(int index) => + throw "UNREACHABLE: This case should have been rewritten in the CFE."; + @patch Pointer operator +(int offset) => throw "UNREACHABLE: This case should have been rewritten in the CFE."; diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart index a6e704f09b7..866318825bb 100644 --- a/sdk/lib/ffi/ffi.dart +++ b/sdk/lib/ffi/ffi.dart @@ -321,6 +321,11 @@ extension Int8Pointer on Pointer { /// being stored, and the 8-bit value is sign-extended when it is loaded. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Int8] after this one. /// /// Returns a pointer to the [Int8] whose address is @@ -393,6 +398,11 @@ extension Int16Pointer on Pointer { /// The [address] must be 2-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Int16] after this one. /// /// Returns a pointer to the [Int16] whose address is @@ -467,6 +477,11 @@ extension Int32Pointer on Pointer { /// The [address] must be 4-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Int32] after this one. /// /// Returns a pointer to the [Int32] whose address is @@ -532,6 +547,11 @@ extension Int64Pointer on Pointer { /// The [address] must be 8-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Int64] after this one. /// /// Returns a pointer to the [Int64] whose address is @@ -600,6 +620,11 @@ extension Uint8Pointer on Pointer { /// being stored, and the 8-bit value is zero-extended when it is loaded. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Uint8] after this one. /// /// Returns a pointer to the [Uint8] whose address is @@ -672,6 +697,11 @@ extension Uint16Pointer on Pointer { /// The [address] must be 2-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Uint16] after this one. /// /// Returns a pointer to the [Uint16] whose address is @@ -746,6 +776,11 @@ extension Uint32Pointer on Pointer { /// The [address] must be 4-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Uint32] after this one. /// /// Returns a pointer to the [Uint32] whose address is @@ -811,6 +846,11 @@ extension Uint64Pointer on Pointer { /// The [address] must be 8-byte aligned. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Uint64] after this one. /// /// Returns a pointer to the [Uint64] whose address is @@ -885,6 +925,11 @@ extension FloatPointer on Pointer { /// The [address] must be 4-byte aligned. external void operator []=(int index, double value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Float] after this one. /// /// Returns a pointer to the [Float] whose address is @@ -950,6 +995,11 @@ extension DoublePointer on Pointer { /// The [address] must be 8-byte aligned. external void operator []=(int index, double value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Double] after this one. /// /// Returns a pointer to the [Double] whose address is @@ -1010,6 +1060,11 @@ extension BoolPointer on Pointer { /// The bool at `address + sizeOf() * index`. external void operator []=(int index, bool value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + Pointer elementAt(int index) => + Pointer.fromAddress(address + sizeOf() * index); + /// A pointer to the [offset]th [Bool] after this one. /// /// Returns a pointer to the [Bool] whose address is @@ -1160,6 +1215,10 @@ extension PointerPointer on Pointer> { /// platforms the [address] must be 8-byte aligned. external void operator []=(int index, Pointer value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + external Pointer> elementAt(int index); + /// A pointer to the [offset]th [Pointer] after this one. /// /// Returns a pointer to the [Pointer] whose address is @@ -1218,6 +1277,10 @@ extension StructPointer on Pointer { /// where `T` is a compile-time constant type. external void operator []=(int index, T value); + /// Pointer arithmetic (takes element size into account) + @Deprecated('Use operator + instead') + external Pointer elementAt(int index); + /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is @@ -1276,6 +1339,10 @@ extension UnionPointer on Pointer { /// where `T` is a compile-time constant type. external void operator []=(int index, T value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + external Pointer elementAt(int index); + /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is @@ -1315,6 +1382,10 @@ extension AbiSpecificIntegerPointer /// The integer at `address + sizeOf() * index`. external void operator []=(int index, int value); + /// Pointer arithmetic (takes element size into account). + @Deprecated('Use operator + instead') + external Pointer elementAt(int index); + /// A pointer to the [offset]th [T] after this one. /// /// Returns a pointer to the [T] whose address is diff --git a/tests/ffi/abi_specific_int_incomplete_jit_test.dart b/tests/ffi/abi_specific_int_incomplete_jit_test.dart index 1417ba5cb23..9038f6e0c4b 100644 --- a/tests/ffi/abi_specific_int_incomplete_jit_test.dart +++ b/tests/ffi/abi_specific_int_incomplete_jit_test.dart @@ -107,7 +107,7 @@ final class IncompleteArrayArrayStruct extends Struct { void testInlineArray2() { final p = calloc(100).cast(); Expect.throws(() { - p + 3; + p.elementAt(3); }); Expect.throws(() { (p + 3); diff --git a/tests/ffi/abi_specific_int_test.dart b/tests/ffi/abi_specific_int_test.dart index d7ccf93c7f2..098cb4cb6ac 100644 --- a/tests/ffi/abi_specific_int_test.dart +++ b/tests/ffi/abi_specific_int_test.dart @@ -90,7 +90,7 @@ void testInlineArray2() { int someValue(int a, int b, int c) => a * 1337 + b * 42 + c; final p = calloc(_dim0); for (int i0 = 0; i0 < _dim0; i0++) { - final array = (p + i0).ref.a0; + final array = p.elementAt(i0).ref.a0; for (int i1 = 0; i1 < _dim1; i1++) { final array2 = array[i1]; for (int i2 = 0; i2 < _dim2; i2++) { @@ -99,7 +99,7 @@ void testInlineArray2() { } } for (int i0 = 0; i0 < _dim0; i0++) { - final array = (p + i0).ref.a0; + final array = p.elementAt(i0).ref.a0; for (int i1 = 0; i1 < _dim1; i1++) { final array2 = array[i1]; for (int i2 = 0; i2 < _dim2; i2++) { diff --git a/tests/ffi/aliasing_test.dart b/tests/ffi/aliasing_test.dart index 9bc35d60633..5cace63f9fd 100644 --- a/tests/ffi/aliasing_test.dart +++ b/tests/ffi/aliasing_test.dart @@ -22,8 +22,8 @@ void main() { testAliasCast2(); testAliasOffsetBy(); testAliasOffsetBy2(); - testAliasOperator(); - testAliasOperator2(); + testAliasElementAt(); + testAliasElementAt2(); testAliasFromAddress(); testAliasFromAddress2(); testAliasFromAddressViaMemory(); @@ -90,9 +90,9 @@ void testAliasOffsetBy2() { calloc.free(source); } -void testAliasOperator() { +void testAliasElementAt() { final source = calloc(2); - final alias = source + 1 - 1; + final alias = source.elementAt(1).elementAt(-1); source.value = 42; final int a = source.value; alias.value = 1984; @@ -101,10 +101,10 @@ void testAliasOperator() { calloc.free(source); } -void testAliasOperator2() { +void testAliasElementAt2() { final source = calloc(3); - final alias = source + 2 - 2; - final alias2 = source + 1 - 1; + final alias = source.elementAt(2).elementAt(-2); + final alias2 = source.elementAt(1).elementAt(-1); alias.value = 42; final int a = alias.value; alias2.value = 1984; diff --git a/tests/ffi/data_test.dart b/tests/ffi/data_test.dart index 6b694ea2f22..306a3445141 100644 --- a/tests/ffi/data_test.dart +++ b/tests/ffi/data_test.dart @@ -67,7 +67,7 @@ void testPointerFromPointer() { void testPointerPointerArithmetic() { Pointer p = calloc(2); - Pointer p2 = p + 1; + Pointer p2 = p.elementAt(1); p2.value = 100; Pointer p3 = p.offsetBy(8); Expect.equals(100, p3.value); @@ -83,13 +83,13 @@ void testPointerPointerArithmetic() { void testPointerPointerArithmeticSizes() { Pointer p = calloc(2); - Pointer p2 = p + 1; + Pointer p2 = p.elementAt(1); int addr = p.address; Expect.equals(addr + 8, p2.address); calloc.free(p); Pointer p3 = calloc(2); - Pointer p4 = p3 + 1; + Pointer p4 = p3.elementAt(1); addr = p3.address; Expect.equals(addr + 4, p4.address); calloc.free(p3); @@ -439,7 +439,7 @@ void testDynamicInvocation() { final int i = p.value; }); Expect.throws(() => p.value = 1); - Expect.throws(() => p + 5); + Expect.throws(() => p.elementAt(5)); Expect.throws(() => p += 5); final int addr = p.address; final Pointer p2 = p.cast(); diff --git a/tests/ffi/extension_methods_test.dart b/tests/ffi/extension_methods_test.dart index 7ea94c6d5a1..6f50cf58e64 100644 --- a/tests/ffi/extension_methods_test.dart +++ b/tests/ffi/extension_methods_test.dart @@ -23,12 +23,12 @@ testStoreLoad() { Expect.equals(20, p[1]); if (sizeOf() == 4) { // Test round tripping. - Expect.equals(20, (p + 0x100000001).value); + Expect.equals(20, p.elementAt(0x100000001).value); Expect.equals(20, p[0x100000001]); } // Test negative index. - final pUseNegative = p + 1; + final pUseNegative = p.elementAt(1); Expect.equals(10, pUseNegative[-1]); // Test negative index using operators @@ -80,8 +80,8 @@ testCompoundLoadAndStore() { foos[i] = reference; Expect.isTrue(foos[i].a == 10); - (foos + i).ref = reference; - Expect.isTrue((foos + i).ref.a == 10); + foos.elementAt(i).ref = reference; + Expect.isTrue(foos.elementAt(i).ref.a == 10); } for (var i = 1; i < 9; i++) { @@ -97,7 +97,7 @@ testCompoundLoadAndStore() { for (var i = 1; i < 9; i++) { bars[i] = bars[0]; - Expect.isTrue((bars + i).ref.foo.a == 10); + Expect.isTrue(bars.elementAt(i).ref.foo.a == 10); Expect.isTrue((bars + i).ref.foo.a == 10); } diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart index 56ec71074a3..4f7a070245f 100644 --- a/tests/ffi/function_callbacks_test.dart +++ b/tests/ffi/function_callbacks_test.dart @@ -137,10 +137,10 @@ double manyArgs( } typedef StoreType = Pointer Function(Pointer); -Pointer store(Pointer ptr) => (ptr + 1)..value = 1337; +Pointer store(Pointer ptr) => ptr.elementAt(1)..value = 1337; typedef NullPointersType = Pointer Function(Pointer); -Pointer nullPointers(Pointer ptr) => (ptr + 1); +Pointer nullPointers(Pointer ptr) => ptr.elementAt(1); typedef ReturnVoid = Void Function(); void returnVoid() {} diff --git a/tests/ffi/function_structs_test.dart b/tests/ffi/function_structs_test.dart index efb1d488f91..a4255c05566 100644 --- a/tests/ffi/function_structs_test.dart +++ b/tests/ffi/function_structs_test.dart @@ -71,15 +71,15 @@ void testFunctionWithStructArray({bool isLeaf = false}) { Coordinate c3 = coordinateArray[2]; c1.x = 10.0; c1.y = 10.0; - c1.next = coordinateArray + 2; + c1.next = coordinateArray.elementAt(2); c2.x = 20.0; c2.y = 20.0; - c2.next = coordinateArray + 0; + c2.next = coordinateArray.elementAt(0); c3.x = 30.0; c3.y = 30.0; - c3.next = coordinateArray + 1; + c3.next = coordinateArray.elementAt(1); - Coordinate result = f1(coordinateArray).ref; + Coordinate result = f1(coordinateArray.elementAt(0)).ref; Expect.approxEquals(20.0, result.x); Expect.approxEquals(20.0, result.y); @@ -114,18 +114,18 @@ void testFunctionWithVeryLargeStruct({bool isLeaf = false}) { struct.k = 1024; struct.smallLastField = 1; } - vls1.parent = vlsArray + 1; + vls1.parent = vlsArray.elementAt(1); vls1.numChildren = 2; - vls1.children = vlsArray; - vls2.parent = vlsArray + 1; + vls1.children = vlsArray.elementAt(0); + vls2.parent = vlsArray.elementAt(1); vls2.parent = nullptr; vls2.numChildren = 0; vls2.children = nullptr; - int result = f(vlsArray); + int result = f(vlsArray.elementAt(0)); Expect.equals(2051, result); - result = f(vlsArray + 1); + result = f(vlsArray.elementAt(1)); Expect.equals(2048, result); calloc.free(vlsArray); diff --git a/tests/ffi/function_test.dart b/tests/ffi/function_test.dart index bad315642d5..c441044b051 100644 --- a/tests/ffi/function_test.dart +++ b/tests/ffi/function_test.dart @@ -398,7 +398,7 @@ void testNativeFunctionPointer() { Pointer result = assign1337Index1(p2); Expect.equals(1337, result.value); Expect.equals(1337, p2[1]); - Expect.equals((p2 + 1).address, result.address); + Expect.equals(p2.elementAt(1).address, result.address); calloc.free(p2); } diff --git a/tests/ffi/regress_39885_test.dart b/tests/ffi/regress_39885_test.dart index 18e664cadd7..77de64f3ec9 100644 --- a/tests/ffi/regress_39885_test.dart +++ b/tests/ffi/regress_39885_test.dart @@ -9,7 +9,7 @@ import "package:ffi/ffi.dart"; main() { final data = calloc(3); for (int i = 0; i < 3; ++i) { - (data + i).value = 1; + data.elementAt(i).value = 1; } calloc.free(data); } diff --git a/tests/ffi/structs_nnbd_workaround_test.dart b/tests/ffi/structs_nnbd_workaround_test.dart index cd2d4358afb..a354563f2b7 100644 --- a/tests/ffi/structs_nnbd_workaround_test.dart +++ b/tests/ffi/structs_nnbd_workaround_test.dart @@ -56,8 +56,8 @@ void testStructAllocate() { /// allocates coordinates consecutively in c memory void testStructFromAddress() { Pointer c1 = calloc(3); - Pointer c2 = c1 + 1; - Pointer c3 = c1 + 2; + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); c1.ref ..x = 10.0 ..y = 10.0 diff --git a/tests/ffi/structs_test.dart b/tests/ffi/structs_test.dart index ca756f310b2..6b0064171a4 100644 --- a/tests/ffi/structs_test.dart +++ b/tests/ffi/structs_test.dart @@ -17,7 +17,9 @@ void main() { for (int i = 0; i < 100; i++) { testStructAllocate(); testStructFromAddress(); + testStructFromAddressWithOperator(); testStructIndexedAccess(); + testStructIndexedAccessWithOperator(); testStructWithNulls(); testTypeTest(); testUtf8(); @@ -56,6 +58,35 @@ void testStructAllocate() { /// Allocates coordinates consecutively in c memory. void testStructFromAddress() { + Pointer c1 = calloc(3); + Pointer c2 = c1.elementAt(1); + Pointer c3 = c1.elementAt(2); + c1.ref + ..x = 10.0 + ..y = 10.0 + ..next = c3; + c2.ref + ..x = 20.0 + ..y = 20.0 + ..next = c1; + c3.ref + ..x = 30.0 + ..y = 30.0 + ..next = c2; + + Coordinate currentCoordinate = c1.ref; + Expect.equals(10.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(30.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(20.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(10.0, currentCoordinate.x); + + calloc.free(c1); +} + +void testStructFromAddressWithOperator() { Pointer c1 = calloc(3); Pointer c2 = c1 + 1; Pointer c3 = c1 + 2; @@ -86,6 +117,33 @@ void testStructFromAddress() { /// Allocates coordinates consecutively in c memory. void testStructIndexedAccess() { + Pointer cs = calloc(3); + cs[0] + ..x = 10.0 + ..y = 10.0 + ..next = cs.elementAt(2); + cs[1] + ..x = 20.0 + ..y = 20.0 + ..next = cs; + cs[2] + ..x = 30.0 + ..y = 30.0 + ..next = cs.elementAt(1); + + Coordinate currentCoordinate = cs.ref; + Expect.equals(10.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(30.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(20.0, currentCoordinate.x); + currentCoordinate = currentCoordinate.next.ref; + Expect.equals(10.0, currentCoordinate.x); + + calloc.free(cs); +} + +void testStructIndexedAccessWithOperator() { Pointer cs = calloc(3); cs[0] ..x = 10.0 diff --git a/tests/ffi/unaligned_test.dart b/tests/ffi/unaligned_test.dart index 0080fd601b2..ba30b7732d2 100644 --- a/tests/ffi/unaligned_test.dart +++ b/tests/ffi/unaligned_test.dart @@ -90,7 +90,7 @@ void _freeAll() { Pointer _allocateUnaligned() { final pointer = calloc(16); _pool.add(pointer); - final misaligned = (pointer + 1).cast(); + final misaligned = pointer.elementAt(1).cast(); Expect.equals(1, misaligned.address % 2); return misaligned; } diff --git a/tests/ffi/vmspecific_regress_37511_test.dart b/tests/ffi/vmspecific_regress_37511_test.dart index 56b4724a956..ed1046a30e3 100644 --- a/tests/ffi/vmspecific_regress_37511_test.dart +++ b/tests/ffi/vmspecific_regress_37511_test.dart @@ -32,6 +32,7 @@ final List functionsToTest = [ () => highAddressPointer.cast(), () => Pointer.fromAddress(highAddressPointer.address), () => highAddressPointer.address, + () => highAddressPointer.elementAt(1), () => highAddressPointer + 1, () => highAddressPointer.offsetBy(1), () => highAddressPointer.asTypedList(1), diff --git a/tests/ffi/vmspecific_static_checks_test.dart b/tests/ffi/vmspecific_static_checks_test.dart index 3c294fe7774..52b70d9d810 100644 --- a/tests/ffi/vmspecific_static_checks_test.dart +++ b/tests/ffi/vmspecific_static_checks_test.dart @@ -68,6 +68,8 @@ void main() { testRefStruct(); testSizeOfGeneric(); testSizeOfInvalidType(); + testElementAtGeneric(); + testElementAtNativeType(); testLookupFunctionIsLeafMustBeConst(); testAsFunctionIsLeafMustBeConst(); testLookupFunctionTakesHandle(); @@ -1131,6 +1133,33 @@ void testSizeOfInvalidType() { // [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_TYPE_ARGUMENT } +void testElementAtGeneric() { + Pointer generic(Pointer pointer) { + Pointer returnValue = pointer; + returnValue = returnValue.elementAt(1); + // ^^^^^^^^^ + // [cfe] The method 'elementAt' isn't defined for the class 'Pointer'. + // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD + return returnValue; + } + + Pointer p = calloc(); + p.elementAt(1); + generic(p); + calloc.free(p); +} + +void testElementAtNativeType() { + Pointer p = calloc(); + p.elementAt(1); + Pointer p2 = p; + p2.elementAt(1); + // ^^^^^^^^^ + // [cfe] The method 'elementAt' isn't defined for the class 'Pointer'. + // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD + calloc.free(p); +} + final class TestStruct1400 extends Struct { @Array(8) @Array(8)