mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 17:59:39 +00:00
[vm/ffi] Add Opaque
type
Issue: https://github.com/dart-lang/sdk/issues/44622 Issue: https://github.com/dart-lang/sdk/issues/43974 TEST=samples/ffi/sqlite/lib/src/bindings/types.dart TEST=tests/ffi/vmspecific_static_checks_test.dart Change-Id: Ib9e72df6a07b1bc2b72a7db66f945652814baf51 Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-arm-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,analyzer-nnbd-linux-release-try,front-end-linux-release-x64-try,front-end-nnbd-linux-release-x64-try,benchmark-linux-try,dart-sdk-linux-try,pkg-linux-release-try,vm-ffi-android-release-arm-try,vm-ffi-android-release-arm64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-win-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178984 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Clement Skau <cskau@google.com>
This commit is contained in:
parent
4e2343c290
commit
5d40d52fca
|
@ -18,6 +18,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
|||
static const _allocateExtensionMethodName = 'call';
|
||||
static const _allocatorExtensionName = 'AllocatorAlloc';
|
||||
static const _dartFfiLibraryName = 'dart.ffi';
|
||||
static const _opaqueClassName = 'Opaque';
|
||||
|
||||
static const List<String> _primitiveIntegerNativeTypes = [
|
||||
'Int8',
|
||||
|
@ -54,7 +55,7 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
|||
@override
|
||||
void visitClassDeclaration(ClassDeclaration node) {
|
||||
inStruct = false;
|
||||
// Only the Struct class may be extended.
|
||||
// Only the Allocator, Opaque and Struct class may be extended.
|
||||
ExtendsClause extendsClause = node.extendsClause;
|
||||
if (extendsClause != null) {
|
||||
final TypeName superclass = extendsClause.superclass;
|
||||
|
@ -62,7 +63,8 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
|||
final className = superclass.name.staticElement.name;
|
||||
if (className == _structClassName) {
|
||||
inStruct = true;
|
||||
} else if (className != _allocatorClassName) {
|
||||
} else if (className != _allocatorClassName &&
|
||||
className != _opaqueClassName) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS,
|
||||
superclass.name,
|
||||
|
@ -245,6 +247,21 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Returns `true` iff [nativeType] is a opaque type, i.e. a subtype of `Opaque`.
|
||||
bool _isOpaqueClass(DartType nativeType) {
|
||||
if (nativeType is InterfaceType) {
|
||||
final superType = nativeType.element.supertype;
|
||||
if (superType == null) {
|
||||
return false;
|
||||
}
|
||||
final superClassElement = superType.element;
|
||||
if (superClassElement.library.name == _dartFfiLibraryName) {
|
||||
return superClassElement.name == _opaqueClassName;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return `true` if the given [element] represents the class `Pointer`.
|
||||
bool _isPointer(Element element) =>
|
||||
element.name == 'Pointer' && element.library.name == _dartFfiLibraryName;
|
||||
|
@ -345,6 +362,9 @@ class FfiVerifier extends RecursiveAstVisitor<void> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if (_isOpaqueClass(nativeType)) {
|
||||
return true;
|
||||
}
|
||||
} else if (nativeType is FunctionType) {
|
||||
return _isValidFfiNativeFunctionType(nativeType);
|
||||
}
|
||||
|
|
|
@ -41,4 +41,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -72,4 +72,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -35,4 +35,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -66,4 +66,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -35,4 +35,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -66,4 +66,4 @@ constants {
|
|||
|
||||
Constructor coverage from constants:
|
||||
org-dartlang-testcase:///ffi_sample.dart:
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:116:9)
|
||||
- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
|
||||
|
|
|
@ -34,6 +34,7 @@ enum NativeType {
|
|||
kFloat,
|
||||
kDouble,
|
||||
kVoid,
|
||||
kOpaque,
|
||||
kStruct,
|
||||
kHandle,
|
||||
}
|
||||
|
@ -60,6 +61,7 @@ const List<String> nativeTypeClassNames = [
|
|||
'Float',
|
||||
'Double',
|
||||
'Void',
|
||||
'Opaque',
|
||||
'Struct',
|
||||
'Handle'
|
||||
];
|
||||
|
@ -86,6 +88,7 @@ const List<int> nativeTypeSizes = [
|
|||
4, // Float
|
||||
8, // Double
|
||||
UNKNOWN, // Void
|
||||
UNKNOWN, // Opaque
|
||||
UNKNOWN, // Struct
|
||||
WORD_SIZE, // Handle
|
||||
];
|
||||
|
@ -207,6 +210,7 @@ class FfiTransformer extends Transformer {
|
|||
final Library ffiLibrary;
|
||||
final Class allocatorClass;
|
||||
final Class nativeFunctionClass;
|
||||
final Class opaqueClass;
|
||||
final Class pointerClass;
|
||||
final Class structClass;
|
||||
final Procedure allocateMethod;
|
||||
|
@ -263,6 +267,7 @@ class FfiTransformer extends Transformer {
|
|||
ffiLibrary = index.getLibrary('dart:ffi'),
|
||||
allocatorClass = index.getClass('dart:ffi', 'Allocator'),
|
||||
nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
|
||||
opaqueClass = index.getClass('dart:ffi', 'Opaque'),
|
||||
pointerClass = index.getClass('dart:ffi', 'Pointer'),
|
||||
structClass = index.getClass('dart:ffi', 'Struct'),
|
||||
allocateMethod = index.getMember('dart:ffi', 'AllocatorAlloc', 'call'),
|
||||
|
|
|
@ -488,10 +488,15 @@ class _FfiUseSiteTransformer extends FfiTransformer {
|
|||
Class _extendsOrImplementsSealedClass(Class klass) {
|
||||
final Class superClass = klass.supertype?.classNode;
|
||||
|
||||
// The Struct class can be extended, but subclasses of Struct cannot be (nor
|
||||
// implemented).
|
||||
if (klass != structClass && hierarchy.isSubtypeOf(klass, structClass)) {
|
||||
return superClass != structClass ? superClass : null;
|
||||
// The Opaque and Struct classes can be extended, but subclasses
|
||||
// cannot be (nor implemented).
|
||||
if (klass != opaqueClass &&
|
||||
klass != structClass &&
|
||||
(hierarchy.isSubtypeOf(klass, opaqueClass) ||
|
||||
hierarchy.isSubtypeOf(klass, structClass))) {
|
||||
return superClass != opaqueClass && superClass != structClass
|
||||
? superClass
|
||||
: null;
|
||||
}
|
||||
|
||||
if (!nativeTypesClasses.contains(klass)) {
|
||||
|
|
|
@ -105,7 +105,7 @@ final stopWorkSimulator =
|
|||
final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
|
||||
void Function(Pointer<Work>)>('ExecuteCallback');
|
||||
|
||||
class Work extends Struct {}
|
||||
class Work extends Opaque {}
|
||||
|
||||
Future asyncSleep(int ms) {
|
||||
return new Future.delayed(Duration(milliseconds: ms));
|
||||
|
|
|
@ -86,4 +86,4 @@ final releaseResource = ffiTestDynamicLibrary.lookupFunction<
|
|||
void Function(Pointer<SomeResource>)>("ReleaseResource");
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -110,4 +110,4 @@ main() {
|
|||
}
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -111,4 +111,4 @@ main() {
|
|||
}
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -13,7 +13,7 @@ import "dart:ffi";
|
|||
/// is its destructor. There are many other interfaces (such as
|
||||
/// [sqlite3_prepare_v2()], [sqlite3_create_function()], and
|
||||
/// [sqlite3_busy_timeout()] to name but three) that are methods on an
|
||||
class Database extends Struct {}
|
||||
class Database extends Opaque {}
|
||||
|
||||
/// SQL Statement Object
|
||||
///
|
||||
|
@ -36,7 +36,7 @@ class Database extends Struct {}
|
|||
///
|
||||
/// Refer to documentation on individual methods above for additional
|
||||
/// information.
|
||||
class Statement extends Struct {}
|
||||
class Statement extends Opaque {}
|
||||
|
||||
/// Dynamically Typed Value Object
|
||||
///
|
||||
|
@ -72,4 +72,4 @@ class Statement extends Struct {}
|
|||
/// [sqlite3_result_value()] and [sqlite3_bind_value()].
|
||||
/// The [sqlite3_value_blob | sqlite3_value_type()] family of
|
||||
/// interfaces require protected sqlite3_value objects.
|
||||
class Value extends Struct {}
|
||||
class Value extends Opaque {}
|
||||
|
|
|
@ -107,7 +107,7 @@ final stopWorkSimulator =
|
|||
final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
|
||||
void Function(Pointer<Work>)>('ExecuteCallback');
|
||||
|
||||
class Work extends Struct {}
|
||||
class Work extends Opaque {}
|
||||
|
||||
Future asyncSleep(int ms) {
|
||||
return new Future.delayed(Duration(milliseconds: ms));
|
||||
|
|
|
@ -88,4 +88,4 @@ final releaseResource = ffiTestDynamicLibrary.lookupFunction<
|
|||
void Function(Pointer<SomeResource>)>("ReleaseResource");
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -112,4 +112,4 @@ main() {
|
|||
}
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -113,4 +113,4 @@ main() {
|
|||
}
|
||||
|
||||
/// Represents some opaque resource being managed by a library.
|
||||
class SomeResource extends Struct {}
|
||||
class SomeResource extends Opaque {}
|
||||
|
|
|
@ -15,7 +15,7 @@ import "dart:ffi";
|
|||
/// is its destructor. There are many other interfaces (such as
|
||||
/// [sqlite3_prepare_v2()], [sqlite3_create_function()], and
|
||||
/// [sqlite3_busy_timeout()] to name but three) that are methods on an
|
||||
class Database extends Struct {}
|
||||
class Database extends Opaque {}
|
||||
|
||||
/// SQL Statement Object
|
||||
///
|
||||
|
@ -38,7 +38,7 @@ class Database extends Struct {}
|
|||
///
|
||||
/// Refer to documentation on individual methods above for additional
|
||||
/// information.
|
||||
class Statement extends Struct {}
|
||||
class Statement extends Opaque {}
|
||||
|
||||
/// Dynamically Typed Value Object
|
||||
///
|
||||
|
@ -74,4 +74,4 @@ class Statement extends Struct {}
|
|||
/// [sqlite3_result_value()] and [sqlite3_bind_value()].
|
||||
/// The [sqlite3_value_blob | sqlite3_value_type()] family of
|
||||
/// interfaces require protected sqlite3_value objects.
|
||||
class Value extends Struct {}
|
||||
class Value extends Opaque {}
|
||||
|
|
|
@ -559,7 +559,7 @@ extension NativePort on SendPort {
|
|||
}
|
||||
|
||||
/// Opaque, not exposing it's members.
|
||||
class Dart_CObject extends Struct {}
|
||||
class Dart_CObject extends Opaque {}
|
||||
|
||||
typedef Dart_NativeMessageHandler = Void Function(Int64, Pointer<Dart_CObject>);
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@ abstract class NativeType {
|
|||
const NativeType();
|
||||
}
|
||||
|
||||
/// [Opaque]'s subtypes represent opaque types in C.
|
||||
///
|
||||
/// [Opaque]'s subtypes are not constructible in the Dart code and serve purely
|
||||
/// as markers in type signatures.
|
||||
abstract class Opaque extends NativeType {}
|
||||
|
||||
/// [_NativeInteger]'s subtypes represent a native integer in C.
|
||||
///
|
||||
/// [_NativeInteger]'s subtypes are not constructible in the Dart code and serve
|
||||
|
|
|
@ -477,6 +477,8 @@ class IPointer implements Pointer {} //# 814: compile-time error
|
|||
|
||||
class IStruct implements Struct {} //# 815: compile-time error
|
||||
|
||||
class IOpaque implements Opaque {} //# 816: compile-time error
|
||||
|
||||
class MyClass {
|
||||
int x;
|
||||
MyClass(this.x);
|
||||
|
|
|
@ -477,6 +477,8 @@ class IPointer implements Pointer {} //# 814: compile-time error
|
|||
|
||||
class IStruct implements Struct {} //# 815: compile-time error
|
||||
|
||||
class IOpaque implements Opaque {} //# 816: compile-time error
|
||||
|
||||
class MyClass {
|
||||
int x;
|
||||
MyClass(this.x);
|
||||
|
|
Loading…
Reference in a new issue