Skip to content

Commit bb483f3

Browse files
halildurmusCommit Queue
authored andcommitted
[vm/ffi] Allow configuring the variable dimension of variable-length arrays
TEST=tests/ffi/* CoreLibraryReviewExempt: VM only Closes: #52366 Change-Id: I545a323f48d955b591cedf2dae7106d9004242e2 Cq-Include-Trybots: dart/try:vm-aot-android-release-arm64c-try,vm-aot-android-release-arm_x64-try,vm-aot-asan-linux-release-x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-msan-linux-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-tsan-linux-release-x64-try,vm-aot-ubsan-linux-release-x64-try,vm-aot-win-debug-arm64-try,vm-aot-win-debug-x64-try,vm-aot-win-debug-x64c-try,vm-appjit-linux-debug-x64-try,vm-asan-linux-release-arm64-try,vm-asan-linux-release-x64-try,vm-checked-mac-release-arm64-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64c-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-fuchsia-release-arm64-try,vm-fuchsia-release-x64-try,vm-linux-debug-ia32-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-mac-debug-x64-try,vm-msan-linux-release-arm64-try,vm-msan-linux-release-x64-try,vm-reload-linux-debug-x64-try,vm-reload-rollback-linux-debug-x64-try,vm-tsan-linux-release-arm64-try,vm-tsan-linux-release-x64-try,vm-ubsan-linux-release-arm64-try,vm-ubsan-linux-release-x64-try,vm-win-debug-arm64-try,vm-win-debug-x64-try,vm-win-debug-x64c-try,vm-win-release-ia32-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/398621 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Daco Harkes <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 17dc16e commit bb483f3

File tree

60 files changed

+4237
-573
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4237
-573
lines changed

BUILD.gn

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
22
# for details. All rights reserved. Use of this source code is governed by a
3-
# BSD-style license that can be found in the LICENSE file.
3+
# BSD-style license that can be found in the LICENSE file.
44

55
import("build/config/gclient_args.gni")
66
import("sdk_args.gni")
@@ -258,6 +258,7 @@ if (is_fuchsia) {
258258
"tests/ffi/function_structs_by_value_generated_args_native_leaf_test.dart",
259259
"tests/ffi/function_structs_by_value_generated_args_native_test.dart",
260260
"tests/ffi/function_structs_by_value_generated_args_test.dart",
261+
"tests/ffi/function_structs_by_value_generated_compounds_sizeof_test.dart",
261262
"tests/ffi/function_structs_by_value_generated_ret_arg_leaf_test.dart",
262263
"tests/ffi/function_structs_by_value_generated_ret_arg_native_leaf_test.dart",
263264
"tests/ffi/function_structs_by_value_generated_ret_arg_native_test.dart",

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13365,6 +13365,17 @@ const MessageCode messageNativeClauseShouldBeAnnotation = const MessageCode(
1336513365
r"""Try removing this native clause and adding @native() or @native('native-name') before the declaration.""",
1336613366
);
1336713367

13368+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
13369+
const Code<Null> codeNegativeVariableDimension =
13370+
messageNegativeVariableDimension;
13371+
13372+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
13373+
const MessageCode messageNegativeVariableDimension = const MessageCode(
13374+
"NegativeVariableDimension",
13375+
problemMessage:
13376+
r"""The variable dimension of a variable-length array must be non-negative.""",
13377+
);
13378+
1336813379
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1336913380
const Code<Null> codeNeverReachableSwitchDefaultError =
1337013381
messageNeverReachableSwitchDefaultError;

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1740,7 +1740,7 @@ FfiCode.FFI_NATIVE_MUST_BE_EXTERNAL:
17401740
since: ~2.15
17411741
notes: |-
17421742
The fix is to add the `external` keyword.
1743-
FfiCode.FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER:
1743+
FfiCode.FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER:
17441744
status: noFix
17451745
since: ~2.15
17461746
FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS:
@@ -1790,6 +1790,8 @@ FfiCode.NATIVE_FIELD_MISSING_TYPE:
17901790
status: needsEvaluation
17911791
FfiCode.NATIVE_FIELD_NOT_STATIC:
17921792
status: needsEvaluation
1793+
FfiCode.NEGATIVE_VARIABLE_DIMENSION:
1794+
status: noFix
17931795
FfiCode.NON_CONSTANT_TYPE_ARGUMENT:
17941796
status: noFix
17951797
FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER:

pkg/analyzer/lib/src/dart/error/ffi_code.g.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ class FfiCode extends ErrorCode {
386386
hasPublishedDocs: true,
387387
);
388388

389+
/// No parameters.
390+
static const FfiCode NEGATIVE_VARIABLE_DIMENSION = FfiCode(
391+
'NEGATIVE_VARIABLE_DIMENSION',
392+
"The variable dimension of a variable-length array must be non-negative.",
393+
correctionMessage: "Try using a value that is zero or greater.",
394+
);
395+
389396
/// Parameters:
390397
/// 0: the name of the function, method, or constructor having type arguments
391398
static const FfiCode NON_CONSTANT_TYPE_ARGUMENT = FfiCode(

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ const List<ErrorCode> errorCodeValues = [
631631
FfiCode.NATIVE_FIELD_INVALID_TYPE,
632632
FfiCode.NATIVE_FIELD_MISSING_TYPE,
633633
FfiCode.NATIVE_FIELD_NOT_STATIC,
634+
FfiCode.NEGATIVE_VARIABLE_DIMENSION,
634635
FfiCode.NON_CONSTANT_TYPE_ARGUMENT,
635636
FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER,
636637
FfiCode.NON_POSITIVE_ARRAY_DIMENSION,

pkg/analyzer/lib/src/generated/ffi_verifier.dart

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,28 +1991,54 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
19911991
}
19921992
}
19931993

1994-
// Check dimensions are positive.
1995-
List<AstNode>? getArgumentNodes() {
1996-
var arguments = annotation.arguments?.arguments;
1997-
if (arguments != null && arguments.length == 1) {
1998-
var firstArgument = arguments[0];
1999-
if (firstArgument is ListLiteral) {
2000-
return firstArgument.elements;
1994+
// Check dimensions are valid.
1995+
(List<AstNode>? dimensionsNodes, AstNode? variableDimensionNode)
1996+
getArgumentNodes() {
1997+
return switch (annotation.arguments) {
1998+
// `@Array.variableMulti([..], variableDimension: ..)`
1999+
ArgumentList(
2000+
arguments: [ListLiteral dimensions, NamedExpression variableDimension]
2001+
) =>
2002+
(dimensions.elements, variableDimension.expression),
2003+
// `@Array.variableMulti([..])`
2004+
ArgumentList(arguments: [ListLiteral dimensions]) => (
2005+
dimensions.elements,
2006+
null
2007+
),
2008+
// `@Array(..)`, `@Array.variable(..)`,
2009+
// `@Array.variableWithVariableDimension(..)`
2010+
ArgumentList(arguments: NodeList<AstNode> dimensions) => (
2011+
dimensions,
2012+
null
2013+
),
2014+
_ => (null, null)
2015+
};
2016+
}
2017+
2018+
var (dimensionsNodes, variableDimensionNode) = getArgumentNodes();
2019+
AstNode errorNode = variableDimensionNode ?? annotation;
2020+
2021+
for (int i = 0; i < dimensions.length; i++) {
2022+
if (dimensionsNodes case var dimensionsNodes?) {
2023+
if (dimensionsNodes.length > i && variableDimensionNode == null) {
2024+
var node = dimensionsNodes[i];
2025+
errorNode = node is NamedExpression ? node.expression : node;
20012026
}
20022027
}
2003-
return arguments;
2004-
}
20052028

2006-
for (int i = 0; i < dimensions.length; i++) {
2029+
// First dimension is variable.
20072030
if (i == 0 && variableLength) {
2008-
continue; // First dimension is variable.
2031+
// Variable dimension can't be negative.
2032+
if (dimensions[0] < 0) {
2033+
_errorReporter.atNode(
2034+
errorNode,
2035+
FfiCode.NEGATIVE_VARIABLE_DIMENSION,
2036+
);
2037+
}
2038+
continue;
20092039
}
2040+
20102041
if (dimensions[i] <= 0) {
2011-
AstNode errorNode = annotation;
2012-
var argumentNodes = getArgumentNodes();
2013-
if (argumentNodes != null && argumentNodes.isNotEmpty) {
2014-
errorNode = argumentNodes[i];
2015-
}
20162042
_errorReporter.atNode(
20172043
errorNode,
20182044
FfiCode.NON_POSITIVE_ARRAY_DIMENSION,
@@ -2093,8 +2119,8 @@ extension on ElementAnnotation {
20932119
assert(isArray);
20942120
var value = computeConstantValue();
20952121

2096-
var variableLength =
2097-
value?.getField('variableLength')?.toBoolValue() ?? false;
2122+
var variableDimension = value?.getField('variableDimension')?.toIntValue();
2123+
var variableLength = variableDimension != null;
20982124

20992125
// Element of `@Array.multi([1, 2, 3])`.
21002126
var listField = value?.getField('dimensions');
@@ -2105,7 +2131,10 @@ extension on ElementAnnotation {
21052131
.whereType<int>()
21062132
.toList();
21072133
if (listValues != null) {
2108-
return ([if (variableLength) 0, ...listValues], variableLength);
2134+
return (
2135+
[if (variableLength) variableDimension, ...listValues],
2136+
variableLength
2137+
);
21092138
}
21102139
}
21112140

pkg/analyzer/lib/src/test_utilities/mock_sdk.dart

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -902,20 +902,38 @@ final class DartRepresentationOf {
902902
903903
@Since('2.13')
904904
final class Array<T extends NativeType> extends _Compound {
905-
const factory Array(int dimension1,
906-
[int dimension2,
907-
int dimension3,
908-
int dimension4,
909-
int dimension5]) = _ArraySize<T>;
905+
const factory Array(
906+
int dimension1, [
907+
int dimension2,
908+
int dimension3,
909+
int dimension4,
910+
int dimension5,
911+
]) = _ArraySize<T>;
910912
911913
const factory Array.multi(List<int> dimensions) = _ArraySize<T>.multi;
912914
913915
@Since('3.6')
914-
const factory Array.variable() = _ArraySize<T>.variable;
916+
const factory Array.variable([
917+
int dimension2,
918+
int dimension3,
919+
int dimension4,
920+
int dimension5,
921+
]) = _ArraySize<T>.variable;
922+
923+
@Since('3.7')
924+
const factory Array.variableWithVariableDimension([
925+
int dimension1,
926+
int dimension2,
927+
int dimension3,
928+
int dimension4,
929+
int dimension5,
930+
]) = _ArraySize<T>.variableWithVariableDimension;
915931
916932
@Since('3.6')
917-
const factory Array.variableMulti(List<int> dimensions) =
918-
_ArraySize<T>.variableMulti;
933+
const factory Array.variableMulti(
934+
List<int> dimensions, {
935+
@Since('3.7') int variableDimension,
936+
}) = _ArraySize<T>.variableMulti;
919937
}
920938
921939
final class _ArraySize<T extends NativeType> implements Array<T> {
@@ -927,7 +945,7 @@ final class _ArraySize<T extends NativeType> implements Array<T> {
927945
928946
final List<int>? dimensions;
929947
930-
final bool variableLength;
948+
final int? variableDimension;
931949
932950
const _ArraySize(
933951
this.dimension1, [
@@ -936,35 +954,44 @@ final class _ArraySize<T extends NativeType> implements Array<T> {
936954
this.dimension4,
937955
this.dimension5,
938956
]) : dimensions = null,
939-
variableLength = false;
957+
variableDimension = null;
940958
941959
const _ArraySize.multi(this.dimensions)
942960
: dimension1 = null,
943961
dimension2 = null,
944962
dimension3 = null,
945963
dimension4 = null,
946964
dimension5 = null,
947-
variableLength = false;
948-
949-
static const variableLengthLength = 0;
965+
variableDimension = null;
950966
951967
const _ArraySize.variable([
952968
this.dimension2,
953969
this.dimension3,
954970
this.dimension4,
955971
this.dimension5,
956-
]) : dimension1 = variableLengthLength,
972+
]) : dimension1 = 0,
957973
dimensions = null,
958-
variableLength = true;
974+
variableDimension = 0;
975+
976+
const _ArraySize.variableWithVariableDimension([
977+
this.dimension1,
978+
this.dimension2,
979+
this.dimension3,
980+
this.dimension4,
981+
this.dimension5,
982+
]) : dimensions = null,
983+
variableDimension = dimension1;
959984
960-
const _ArraySize.variableMulti(List<int> nestedDimensions)
961-
: dimensions = nestedDimensions,
985+
const _ArraySize.variableMulti(
986+
List<int> nestedDimensions, {
987+
int variableDimension = 0,
988+
}) : dimensions = nestedDimensions,
962989
dimension1 = null,
963990
dimension2 = null,
964991
dimension3 = null,
965992
dimension4 = null,
966993
dimension5 = null,
967-
variableLength = true;
994+
variableDimension = variableDimension;
968995
}
969996
970997
extension StructPointer<T extends Struct> on Pointer<T> {

pkg/analyzer/messages.yaml

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20400,6 +20400,76 @@ FfiCode:
2040020400
NativeCallable<Void Function(Int32)>.listener(f);
2040120401
}
2040220402
```
20403+
NEGATIVE_VARIABLE_DIMENSION:
20404+
problemMessage: The variable dimension of a variable-length array must be non-negative.
20405+
correctionMessage: Try using a value that is zero or greater.
20406+
hasPublishedDocs: false
20407+
comment: No parameters.
20408+
documentation: |-
20409+
#### Description
20410+
20411+
The analyzer produces this diagnostic in two cases.
20412+
20413+
The first is when the variable dimension given in an
20414+
`Array.variableWithVariableDimension` annotation is negative. The variable
20415+
dimension is the first argument in the annotation.
20416+
20417+
The second is when the variable dimension given in an
20418+
`Array.variableMulti` annotation is negative. The variable dimension is
20419+
specified in the `variableDimension` argument of the annotation.
20420+
20421+
For more information about FFI, see [C interop using dart:ffi][ffi].
20422+
20423+
#### Examples
20424+
20425+
The following code produces this diagnostic because a variable dimension
20426+
of `-1` was provided in the `Array.variableWithVariableDimension`
20427+
annotation:
20428+
20429+
```dart
20430+
import 'dart:ffi';
20431+
20432+
final class MyStruct extends Struct {
20433+
@Array.variableWithVariableDimension([!-1!])
20434+
external Array<Uint8> a0;
20435+
}
20436+
```
20437+
20438+
The following code produces this diagnostic because a variable dimension
20439+
of `-1` was provided in the `Array.variableMulti` annotation:
20440+
20441+
```dart
20442+
import 'dart:ffi';
20443+
20444+
final class MyStruct2 extends Struct {
20445+
@Array.variableMulti(variableDimension: [!-1!], [1, 2])
20446+
external Array<Array<Array<Uint8>>> a0;
20447+
}
20448+
```
20449+
20450+
#### Common fixes
20451+
20452+
Change the variable dimension with zero (`0`) or a positive number:
20453+
20454+
```dart
20455+
import 'dart:ffi';
20456+
20457+
final class MyStruct extends Struct {
20458+
@Array.variableWithVariableDimension(1)
20459+
external Array<Uint8> a0;
20460+
}
20461+
```
20462+
20463+
Change the variable dimension with zero (`0`) or a positive number:
20464+
20465+
```dart
20466+
import 'dart:ffi';
20467+
20468+
final class MyStruct2 extends Struct {
20469+
@Array.variableMulti(variableDimension: 1, [1, 2])
20470+
external Array<Array<Array<Uint8>>> a0;
20471+
}
20472+
```
2040320473
NON_CONSTANT_TYPE_ARGUMENT:
2040420474
problemMessage: "The type arguments to '{0}' must be known at compile time, so they can't be type parameters."
2040520475
correctionMessage: Try changing the type argument to be a constant type.
@@ -20515,7 +20585,7 @@ FfiCode:
2051520585
#### Example
2051620586

2051720587
The following code produces this diagnostic because an array dimension of
20518-
`-1` was provided:
20588+
`-8` was provided:
2051920589

2052020590
```dart
2052120591
import 'dart:ffi';
@@ -20539,7 +20609,8 @@ FfiCode:
2053920609
}
2054020610
```
2054120611

20542-
If this is a variable length inline array, change the annotation to `Array.variable()`:
20612+
If this is a variable length inline array, change the annotation to
20613+
`Array.variable()`:
2054320614

2054420615
```dart
2054520616
import 'dart:ffi';

0 commit comments

Comments
 (0)