[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();
+}