[cfe/ffi]: Removing `.address` invalid expression in leaf call to prevent errors
Closes https://github.com/dart-lang/sdk/pull/56594
GitOrigin-RevId: e673d9b13aa00a263632bb25b1ae30b143bdc9fe
Change-Id: If7f9dd27846c0cddb19b3e89acd9fb3cd25dc77f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382681
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
diff --git a/pkg/vm/lib/modular/transformations/ffi/use_sites.dart b/pkg/vm/lib/modular/transformations/ffi/use_sites.dart
index e3a6059..1c92a52 100644
--- a/pkg/vm/lib/modular/transformations/ffi/use_sites.dart
+++ b/pkg/vm/lib/modular/transformations/ffi/use_sites.dart
@@ -1510,6 +1510,13 @@
return ('', parameterType, argument);
}
+ // If an argument is an invalid expression, ffi don't need to report
+ // any error further, so skipping transformation for its descendants of the
+ // argument by transforming into empty expression (which is invalid)
+ if ((argument is AsExpression && argument.operand is InvalidExpression) ||
+ argument is InvalidExpression) {
+ return ('E', parameterType, InvalidExpression('Invalid Type'));
+ }
if (argument is InstanceInvocation &&
argument.interfaceTarget == castMethod &&
argument.functionType.returnType == parameterType) {
diff --git a/tests/ffi/static_checks/address_of_cast_test.dart b/tests/ffi/static_checks/address_of_cast_test.dart
index 1deb853..ab8cc80 100644
--- a/tests/ffi/static_checks/address_of_cast_test.dart
+++ b/tests/ffi/static_checks/address_of_cast_test.dart
@@ -23,13 +23,6 @@
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^^^^^
// [cfe] The argument type 'Pointer<Int32>' can't be assigned to the parameter type 'Pointer<Void>'.
- // [cfe] The '.address' expression can only be used as argument to a leaf native external call.
-
- // The second[cfe] error is not expected actually,
- // its a bug. Reported here https://github.com/dart-lang/sdk/issues/56462
- // once it fixed the second error can be removed.
- // This is same across remaining test cases (testStructField, testUnionField),
- // where in every `myNative()` call the second error is not expected.
}
void testStructField() {
@@ -43,7 +36,6 @@
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^^^^^
// [cfe] The argument type 'Pointer<Int32>' can't be assigned to the parameter type 'Pointer<Void>'.
- // [cfe] The '.address' expression can only be used as argument to a leaf native external call.
myNativeNonLeaf(myStruct.value.address.cast());
// ^^^^^^^
@@ -55,8 +47,6 @@
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^^^^^^^^^^^
// [cfe] The argument type 'Pointer<Int32>' can't be assigned to the parameter type 'Pointer<Void>'.
- // ^^^^^^^
- // [cfe] The '.address' expression can only be used as argument to a leaf native external call.
}
void testUnionField() {
@@ -71,7 +61,6 @@
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^^^^^
// [cfe] The argument type 'Pointer<Int32>' can't be assigned to the parameter type 'Pointer<Void>'.
- // [cfe] The '.address' expression can only be used as argument to a leaf native external call.
myNativeNonLeaf(myUnion.value.address.cast());
// ^^^^^^^
@@ -83,8 +72,6 @@
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^^^^^^^^^^^
// [cfe] The argument type 'Pointer<Int32>' can't be assigned to the parameter type 'Pointer<Void>'.
- // ^^^^^^^
- // [cfe] The '.address' expression can only be used as argument to a leaf native external call.
}
void main() {
diff --git a/tests/ffi/static_checks/regress_56462_test.dart b/tests/ffi/static_checks/regress_56462_test.dart
new file mode 100644
index 0000000..28cb24e
--- /dev/null
+++ b/tests/ffi/static_checks/regress_56462_test.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:typed_data';
+
+@Native<Void Function(Pointer<Void>, Pointer<Int8>)>(isLeaf: true)
+external void myNativeWith2Param(Pointer<Void> buffer, Pointer<Int8> buffer2);
+
+@Native<Void Function(Pointer<Void>, Pointer<Int8>, Pointer<Void>)>(
+ isLeaf: true)
+external void myNativeWith3Param(
+ Pointer<Void> buffer, Pointer<Int8> buffer2, Pointer<Void> buffer3);
+
+void test_wrong_type() {
+ final buffer = Int8List.fromList([1]);
+ myNativeWith2Param(buffer.address, buffer.address);
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+
+ myNativeWith2Param(buffer.address.cast(), buffer.address.cast<Void>());
+ // ^^^^^^^^^^^^
+ // [cfe] The argument type 'Pointer<Void>' can't be assigned to the parameter type 'Pointer<Int8>'.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+
+ myNativeWith3Param(buffer.address, buffer.address, buffer.address.cast());
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+
+ myNativeWith3Param(
+ buffer.address.cast(),
+ /* */ buffer.address.cast<Void>(),
+ // ^^^^^^^^^^^^
+ // [cfe] The argument type 'Pointer<Void>' can't be assigned to the parameter type 'Pointer<Int8>'.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ buffer.address.cast());
+
+ myNativeWith3Param(buffer.address.cast(), buffer.address, buffer.address);
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+
+ myNativeWith3Param(
+ /**/ buffer.address,
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ /**/ buffer.address.cast<Void>(),
+ // ^^^^^^^^^^^^
+ // [cfe] The argument type 'Pointer<Void>' can't be assigned to the parameter type 'Pointer<Int8>'.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ buffer.address.cast());
+
+ myNativeWith3Param(
+ buffer.address.cast(),
+ /**/ buffer.address.cast<Void>(),
+ // ^^^^^^^^^^^^
+ // [cfe] The argument type 'Pointer<Void>' can't be assigned to the parameter type 'Pointer<Int8>'.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ buffer.address);
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ myNativeWith3Param(
+ /**/ buffer.address
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ ,
+ buffer.address,
+ buffer.address);
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+
+ myNativeWith3Param(
+ /**/ buffer.address,
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ /**/ buffer.address.cast<Void>(),
+ // ^^^^^^^^^^^^
+ // [cfe] The argument type 'Pointer<Void>' can't be assigned to the parameter type 'Pointer<Int8>'.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ buffer.address);
+ // ^^^^^^^
+ // [cfe] The argument type 'Pointer<Int8>' can't be assigned to the parameter type 'Pointer<Void>'.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
+}
+
+void test_undefined_arguments() {
+ final buffer = Int8List.fromList([1]);
+ myNativeWith2Param(buffer.address.cast(), buffer.address.cd);
+ // ^^
+ // [cfe] The getter 'cd' isn't defined for the class 'Pointer<Int8>'.
+ // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ADDRESS_POSITION
+
+ // This address position error is not expected which is a bug,
+ // https://github.com/dart-lang/sdk/issues/56613
+
+ myNativeWith2Param(buffer.address.cast<Int8>().cd, buffer.address);
+ // ^^
+ // [cfe] The getter 'cd' isn't defined for the class 'Pointer<Int8>'.
+ // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ADDRESS_POSITION
+
+ // This address position error is not expected which is a bug,
+ // https://github.com/dart-lang/sdk/issues/56613
+}
+
+void main() {
+ test_undefined_arguments();
+ test_wrong_type();
+}