Skip to content

Commit 603293f

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Regression test for dartbug.com/37254
Issue: #37254 Change-Id: Ic8ede0f8b7a6de0a6862ef8748a7330232950239 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107281 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Samir Jindel <[email protected]> Reviewed-by: Lasse R.H. Nielsen <[email protected]>
1 parent 523aa97 commit 603293f

File tree

2 files changed

+264
-0
lines changed

2 files changed

+264
-0
lines changed

tests/ffi/ffi.status

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# for details. All rights reserved. Use of this source code is governed by a
33
# BSD-style license that can be found in the LICENSE file.
44

5+
regress_37254_test:Skip # dartbug.com/37254
6+
57
[ $arch == simdbc ]
68
*: Skip # FFI not yet supported on SimDBC32: dartbug.com/36809
79

tests/ffi/regress_37254_test.dart

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// 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.
4+
//
5+
// This program tests interaction with generic Pointers.
6+
//
7+
// Notation used in following tables:
8+
// * static_type//dynamic_type
9+
// * P = Pointer
10+
// * I = Int8
11+
// * NT = NativeType
12+
//
13+
// Note #1: When NNBD is landed, implicit downcasts will be static errors.
14+
//
15+
// Note #2: When we switch to extension methods we will _only_ use the static
16+
// type of the container.
17+
//
18+
// ===== a.store(b) ======
19+
// Does a.store(b), where a and b have specific static and dynamic types: run
20+
// fine, fail at compile time, or fail at runtime?
21+
// =======================
22+
// b P<I>//P<I> P<NT>//P<I> P<NT>//P<NT>
23+
// a
24+
// P<P<I>>//P<P<I>> 1 ok 2 implicit downcast 3 implicit downcast
25+
// of argument: ok of argument: fail
26+
// at runtime
27+
//
28+
// P<P<NT>>//P<P<I>> 4 ok 5 ok 6 fail at runtime
29+
//
30+
// P<P<NT>>//P<P<NT>> 7 ok 8 ok 9 ok
31+
//
32+
// ====== final c = a.load() ======
33+
// What is the (inferred) static type and runtime type of `a.load()`. Note that
34+
// we assume extension method here: on Pointer<PointerT>> { Pointer<T> load(); }
35+
// ================================
36+
// a a.load()
37+
// inferred static type*//runtime type
38+
// P<P<I>>//P<P<I>> P<I>//P<I>
39+
//
40+
// P<P<NT>>//P<P<I>> P<NT>//P<I>
41+
//
42+
// P<P<NT>>//P<P<NT>> P<NT>//P<NT>
43+
//
44+
// * The inferred static type when we get extension methods.
45+
//
46+
// ====== b = a.load() ======
47+
// What happens when we try to assign the result of a.load() to variable b with
48+
// a specific static type: runs fine, fails at compile time, or fails at runtime.
49+
// ==========================
50+
// b P<I> P<NT>
51+
// a
52+
// P<P<I>>//P<P<I>> 1 ok 2 ok
53+
//
54+
// P<P<NT>>//P<P<I>> 3 implicit downcast 4 ok
55+
// of returnvalue: ok
56+
//
57+
// P<P<NT>>//P<P<NT>> 5 implicit downcast 6 ok
58+
// of returnvalue: fail
59+
// at runtime
60+
//
61+
// These are the normal Dart assignment rules.
62+
63+
import 'dart:ffi';
64+
65+
import "package:expect/expect.dart";
66+
67+
// ===== a.store(b) ======
68+
// The tests follow table cells left to right, top to bottom.
69+
void store1() {
70+
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
71+
final Pointer<Int8> b = allocate<Int8>();
72+
73+
a.store(b);
74+
75+
a.free();
76+
b.free();
77+
}
78+
79+
void store2() {
80+
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
81+
final Pointer<NativeType> b =
82+
allocate<Int8>(); // Reified Pointer<Int8> at runtime.
83+
84+
// Successful implicit downcast of argument at runtime.
85+
// Should succeed now, should statically be rejected when NNBD lands.
86+
// TODO(37254): Currently rejected by the frontend.
87+
a.store(b);
88+
89+
a.free();
90+
b.free();
91+
}
92+
93+
void store3() {
94+
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
95+
// TODO(37254): We currently disallow obtaining a Pointer<NativeType>.
96+
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
97+
98+
// Failing implicit downcast of argument at runtime.
99+
// Should fail now at runtime, should statically be rejected when NNBD lands.
100+
// TODO(37254): Currently rejected by the frontend.
101+
Expect.throws(() {
102+
a.store(b);
103+
});
104+
105+
a.free();
106+
b.free();
107+
}
108+
109+
void store4() {
110+
final Pointer<Pointer<NativeType>> a = allocate<
111+
Pointer<Int8>>(); // Reified as Pointer<Pointer<Int8>> at runtime.
112+
final Pointer<Int8> b = allocate<Int8>();
113+
114+
// TODO(37254): Currently rejected by the frontend.
115+
a.store(b);
116+
117+
a.free();
118+
b.free();
119+
}
120+
121+
void store5() {
122+
final Pointer<Pointer<NativeType>> a = allocate<
123+
Pointer<Int8>>(); // Reified as Pointer<Pointer<Int8>> at runtime.
124+
final Pointer<NativeType> b =
125+
allocate<Int8>(); // Reified as Pointer<Int8> at runtime.
126+
127+
a.store(b);
128+
129+
a.free();
130+
b.free();
131+
}
132+
133+
void store6() {
134+
final Pointer<Pointer<NativeType>> a = allocate<
135+
Pointer<Int8>>(); // Reified as Pointer<Pointer<Int8>> at runtime.
136+
// TODO(37254): We currently disallow obtaining a Pointer<NativeType>.
137+
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
138+
139+
// Fails on type check of argument.
140+
Expect.throws(() {
141+
a.store(b);
142+
});
143+
144+
a.free();
145+
b.free();
146+
}
147+
148+
void store7() {
149+
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
150+
final Pointer<Int8> b = allocate<Int8>();
151+
152+
// TODO(37254): Currently rejected by the frontend.
153+
a.store(b);
154+
155+
a.free();
156+
b.free();
157+
}
158+
159+
void store8() {
160+
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
161+
final Pointer<NativeType> b =
162+
allocate<Int8>(); // Reified as Pointer<Int8> at runtime.
163+
164+
// TODO(37254): Currently hits assertion in VM.
165+
a.store(b);
166+
167+
a.free();
168+
b.free();
169+
}
170+
171+
void store9() {
172+
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
173+
// TODO(37254): We currently disallow obtaining a Pointer<NativeType>.
174+
final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
175+
176+
a.store(b);
177+
178+
a.free();
179+
b.free();
180+
}
181+
182+
// ====== b = a.load() ======
183+
// The tests follow table cells left to right, top to bottom.
184+
void load1() {
185+
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
186+
187+
Pointer<Int8> b = a.load();
188+
Expect.type<Pointer<Int8>>(b);
189+
190+
a.free();
191+
}
192+
193+
void load2() {
194+
final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
195+
196+
Pointer<NativeType> b = a.load<Pointer<Int8>>();
197+
Expect.type<Pointer<Int8>>(b);
198+
199+
a.free();
200+
}
201+
202+
void load3() {
203+
final Pointer<Pointer<NativeType>> a = allocate<
204+
Pointer<Int8>>(); // Reified as Pointer<Pointer<Int8>> at runtime.
205+
206+
// TODO(37254): Currently hits assertion in VM.
207+
Pointer<Int8> b = a.load<Pointer<NativeType>>();
208+
Expect.type<Pointer<Int8>>(b);
209+
210+
a.free();
211+
}
212+
213+
void load4() {
214+
final Pointer<Pointer<NativeType>> a = allocate<
215+
Pointer<Int8>>(); // Reified as Pointer<Pointer<Int8>> at runtime.
216+
217+
// Return value runtime type is Pointer<Int8>.
218+
// TODO(37254): Currently hits assertion in VM.
219+
Pointer<NativeType> b = a.load();
220+
Expect.type<Pointer<Int8>>(b);
221+
222+
a.free();
223+
}
224+
225+
void load5() {
226+
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
227+
228+
// Failing implicit downcast of return value at runtime.
229+
// Should fail now at runtime, should statically be rejected when NNBD lands.
230+
Expect.throws(() {
231+
Pointer<Int8> b = a.load<Pointer<NativeType>>();
232+
});
233+
234+
a.free();
235+
}
236+
237+
void load6() {
238+
final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
239+
240+
Pointer<NativeType> b = a.load();
241+
Expect.type<Pointer<NativeType>>(b);
242+
243+
a.free();
244+
}
245+
246+
void main() {
247+
store1();
248+
store2();
249+
store3();
250+
store4();
251+
store5();
252+
store6();
253+
store7();
254+
store8();
255+
store9();
256+
load1();
257+
load2();
258+
load3();
259+
load4();
260+
load5();
261+
load6();
262+
}

0 commit comments

Comments
 (0)