From c8c6d0925a8c7891b9d12b6b892ab3e9bba8f8de Mon Sep 17 00:00:00 2001 From: Evan Shaw Date: Sun, 12 Jan 2020 13:14:50 +1300 Subject: [PATCH] ty: Simplify Box to *T This simplifies Box to *T, which enables use cases not previously supported. Box is guaranteed to have the same layout as *T as long as T is sized. This is documented in the current Rust beta. This does mean that the headers we're emitting are incorrect for unsized types, but it still seems like a strict improvement over old behavior. This can also be a recipe for memory leaks if not handled carefully, but again, still seems better than previously. Test cases are shamelessly copied and modified from the NonNull simplification. --- src/bindgen/ir/ty.rs | 1 + tests/expectations/both/box.c | 19 +++++++++++++++++++ tests/expectations/both/box.compat.c | 27 +++++++++++++++++++++++++++ tests/expectations/box.c | 19 +++++++++++++++++++ tests/expectations/box.compat.c | 27 +++++++++++++++++++++++++++ tests/expectations/box.cpp | 24 ++++++++++++++++++++++++ tests/expectations/tag/box.c | 19 +++++++++++++++++++ tests/expectations/tag/box.compat.c | 27 +++++++++++++++++++++++++++ tests/rust/box.rs | 16 ++++++++++++++++ 9 files changed, 179 insertions(+) create mode 100644 tests/expectations/both/box.c create mode 100644 tests/expectations/both/box.compat.c create mode 100644 tests/expectations/box.c create mode 100644 tests/expectations/box.compat.c create mode 100644 tests/expectations/box.cpp create mode 100644 tests/expectations/tag/box.c create mode 100644 tests/expectations/tag/box.compat.c create mode 100644 tests/rust/box.rs diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index c674a8027..7646cf1a5 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -389,6 +389,7 @@ impl Type { generic.simplify_standard_types(); match path.name() { + "Box" => Some(Type::Ptr(Box::new(generic))), // FIXME(#223): This is not quite correct. "Option" if generic.is_repr_ptr() => Some(generic), "NonNull" => Some(Type::Ptr(Box::new(generic))), diff --git a/tests/expectations/both/box.c b/tests/expectations/both/box.c new file mode 100644 index 000000000..8de173917 --- /dev/null +++ b/tests/expectations/both/box.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +typedef struct Opaque Opaque; + +typedef struct Foo_u64 { + float *a; + uint64_t *b; + Opaque *c; + uint64_t **d; + float **e; + Opaque **f; + uint64_t *g; + int32_t *h; +} Foo_u64; + +void root(int32_t *arg, Foo_u64 *foo, Opaque **d); diff --git a/tests/expectations/both/box.compat.c b/tests/expectations/both/box.compat.c new file mode 100644 index 000000000..89e7b5249 --- /dev/null +++ b/tests/expectations/both/box.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +typedef struct Opaque Opaque; + +typedef struct Foo_u64 { + float *a; + uint64_t *b; + Opaque *c; + uint64_t **d; + float **e; + Opaque **f; + uint64_t *g; + int32_t *h; +} Foo_u64; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(int32_t *arg, Foo_u64 *foo, Opaque **d); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/box.c b/tests/expectations/box.c new file mode 100644 index 000000000..385cde176 --- /dev/null +++ b/tests/expectations/box.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +typedef struct Opaque Opaque; + +typedef struct { + float *a; + uint64_t *b; + Opaque *c; + uint64_t **d; + float **e; + Opaque **f; + uint64_t *g; + int32_t *h; +} Foo_u64; + +void root(int32_t *arg, Foo_u64 *foo, Opaque **d); diff --git a/tests/expectations/box.compat.c b/tests/expectations/box.compat.c new file mode 100644 index 000000000..080139218 --- /dev/null +++ b/tests/expectations/box.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +typedef struct Opaque Opaque; + +typedef struct { + float *a; + uint64_t *b; + Opaque *c; + uint64_t **d; + float **e; + Opaque **f; + uint64_t *g; + int32_t *h; +} Foo_u64; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(int32_t *arg, Foo_u64 *foo, Opaque **d); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/box.cpp b/tests/expectations/box.cpp new file mode 100644 index 000000000..1208cacae --- /dev/null +++ b/tests/expectations/box.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +struct Opaque; + +template +struct Foo { + float *a; + T *b; + Opaque *c; + T **d; + float **e; + Opaque **f; + T *g; + int32_t *h; +}; + +extern "C" { + +void root(int32_t *arg, Foo *foo, Opaque **d); + +} // extern "C" diff --git a/tests/expectations/tag/box.c b/tests/expectations/tag/box.c new file mode 100644 index 000000000..d0d710758 --- /dev/null +++ b/tests/expectations/tag/box.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +struct Opaque; + +struct Foo_u64 { + float *a; + uint64_t *b; + struct Opaque *c; + uint64_t **d; + float **e; + struct Opaque **f; + uint64_t *g; + int32_t *h; +}; + +void root(int32_t *arg, struct Foo_u64 *foo, struct Opaque **d); diff --git a/tests/expectations/tag/box.compat.c b/tests/expectations/tag/box.compat.c new file mode 100644 index 000000000..822a0c4df --- /dev/null +++ b/tests/expectations/tag/box.compat.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +struct Opaque; + +struct Foo_u64 { + float *a; + uint64_t *b; + struct Opaque *c; + uint64_t **d; + float **e; + struct Opaque **f; + uint64_t *g; + int32_t *h; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(int32_t *arg, struct Foo_u64 *foo, struct Opaque **d); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/rust/box.rs b/tests/rust/box.rs new file mode 100644 index 000000000..79319241c --- /dev/null +++ b/tests/rust/box.rs @@ -0,0 +1,16 @@ +struct Opaque; + +#[repr(C)] +pub struct Foo { + a: Box, + b: Box, + c: Box, + d: Box>, + e: Box>, + f: Box>, + g: Option>, + h: Option>, +} + +#[no_mangle] +pub extern "C" fn root(arg: Box, foo: *mut Foo, d: Box>) {}