Skip to content

Commit 728a5d3

Browse files
committed
Wrap the array representation of opaque types in a #[repr(C)] struct
1 parent bd67942 commit 728a5d3

File tree

14 files changed

+143
-19
lines changed

14 files changed

+143
-19
lines changed

bindgen-integration/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ fn test_item_rename() {
254254
#[test]
255255
fn test_matching_with_rename() {
256256
assert_eq!(bindings::enum_to_be_constified_THREE, 3);
257-
assert_eq!(unsafe { bindings::TEMPLATED_CONST_VALUE.len() }, 30);
257+
assert_eq!(unsafe { bindings::TEMPLATED_CONST_VALUE.0.len() }, 30);
258258
}
259259

260260
#[test]

bindgen-tests/tests/expectations/tests/libclang-9/issue-544-stylo-creduce-2.rs

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/non-type-params.rs

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/nsBaseHashtable.rs

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/partial-specialization-and-inheritance.rs

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/size_t_template.rs

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/va_list_aarch64_linux.rs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// bindgen-flags: -- --target=aarch64-unknown-linux-gnu
2+
3+
typedef __builtin_va_list va_list;
4+
int vprintf(const char* format, va_list vlist);

bindgen/codegen/helpers.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,16 @@ pub(crate) mod attributes {
7979

8080
/// Generates a proper type for a field or type with a given `Layout`, that is,
8181
/// a type with the correct size and alignment restrictions.
82-
pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> syn::Type {
82+
/// The `ffi_safe` argument should be true if this is a type that the user might
83+
/// reasonably use, e.g. not struct padding, where the __BindgenOpaqueArray is
84+
/// just noise.
85+
/// TODO: Should this be `MaybeUninit`, since padding bytes are effectively
86+
/// uninitialized?
87+
pub(crate) fn blob(
88+
ctx: &BindgenContext,
89+
layout: Layout,
90+
ffi_safe: bool,
91+
) -> syn::Type {
8392
let opaque = layout.opaque();
8493

8594
// FIXME(emilio, #412): We fall back to byte alignment, but there are
@@ -98,7 +107,12 @@ pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> syn::Type {
98107

99108
if data_len == 1 {
100109
ty
110+
} else if ffi_safe && ctx.options().rust_features().min_const_generics {
111+
ctx.generated_opaque_array();
112+
syn::parse_quote! { __BindgenOpaqueArray<#ty, #data_len> }
101113
} else {
114+
// This is not FFI safe as an argument; the struct above is
115+
// preferable.
102116
syn::parse_quote! { [ #ty ; #data_len ] }
103117
}
104118
}

bindgen/codegen/mod.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ impl CodeGenerator for Module {
584584
if ctx.need_bindgen_complex_type() {
585585
utils::prepend_complex_type(&mut *result);
586586
}
587+
if ctx.need_opaque_array_type() {
588+
utils::prepend_opaque_array_type(&mut *result);
589+
}
587590
if result.saw_objc {
588591
utils::prepend_objc_header(ctx, &mut *result);
589592
}
@@ -2162,7 +2165,7 @@ impl CodeGenerator for CompInfo {
21622165

21632166
if has_address {
21642167
let layout = Layout::new(1, 1);
2165-
let ty = helpers::blob(ctx, Layout::new(1, 1));
2168+
let ty = helpers::blob(ctx, Layout::new(1, 1), false);
21662169
struct_layout.saw_field_with_layout(
21672170
"_address",
21682171
layout,
@@ -2179,7 +2182,7 @@ impl CodeGenerator for CompInfo {
21792182
Some(l) => {
21802183
explicit_align = Some(l.align);
21812184

2182-
let ty = helpers::blob(ctx, l);
2185+
let ty = helpers::blob(ctx, l, false);
21832186
fields.push(quote! {
21842187
pub _bindgen_opaque_blob: #ty ,
21852188
});
@@ -2205,6 +2208,7 @@ impl CodeGenerator for CompInfo {
22052208
let ty = helpers::blob(
22062209
ctx,
22072210
Layout::new(0, layout.align),
2211+
false,
22082212
);
22092213
fields.push(quote! {
22102214
pub __bindgen_align: #ty ,
@@ -2222,7 +2226,7 @@ impl CodeGenerator for CompInfo {
22222226
}
22232227

22242228
if !struct_layout.is_rust_union() {
2225-
let ty = helpers::blob(ctx, layout);
2229+
let ty = helpers::blob(ctx, layout, false);
22262230
fields.push(quote! {
22272231
pub bindgen_union_field: #ty ,
22282232
})
@@ -3903,7 +3907,7 @@ pub(crate) trait TryToOpaque {
39033907
extra: &Self::Extra,
39043908
) -> error::Result<syn::Type> {
39053909
self.try_get_layout(ctx, extra)
3906-
.map(|layout| helpers::blob(ctx, layout))
3910+
.map(|layout| helpers::blob(ctx, layout, true))
39073911
}
39083912
}
39093913

@@ -3929,7 +3933,7 @@ pub(crate) trait ToOpaque: TryToOpaque {
39293933
extra: &Self::Extra,
39303934
) -> syn::Type {
39313935
let layout = self.get_layout(ctx, extra);
3932-
helpers::blob(ctx, layout)
3936+
helpers::blob(ctx, layout, true)
39333937
}
39343938
}
39353939

@@ -3980,7 +3984,7 @@ where
39803984
) -> error::Result<syn::Type> {
39813985
self.try_to_rust_ty(ctx, extra).or_else(|_| {
39823986
if let Ok(layout) = self.try_get_layout(ctx, extra) {
3983-
Ok(helpers::blob(ctx, layout))
3987+
Ok(helpers::blob(ctx, layout, true))
39843988
} else {
39853989
Err(error::Error::NoLayoutForOpaqueBlob)
39863990
}
@@ -5438,6 +5442,25 @@ pub(crate) mod utils {
54385442
result.extend(old_items);
54395443
}
54405444

5445+
pub(crate) fn prepend_opaque_array_type(
5446+
result: &mut Vec<proc_macro2::TokenStream>,
5447+
) {
5448+
let ty = quote! {
5449+
/// If Bindgen could only determine the size and alignment of a
5450+
/// type, it is represented like this.
5451+
#[derive(PartialEq, Copy, Clone, Debug, Hash)]
5452+
#[repr(C)]
5453+
struct __BindgenOpaqueArray<T: Copy, const N: usize>(pub [T; N]);
5454+
impl<T: Copy + Default, const N: usize> Default for __BindgenOpaqueArray<T, N> {
5455+
fn default() -> Self {
5456+
Self([<T as Default>::default(); N])
5457+
}
5458+
}
5459+
};
5460+
5461+
result.insert(0, ty);
5462+
}
5463+
54415464
pub(crate) fn build_path(
54425465
item: &Item,
54435466
ctx: &BindgenContext,

0 commit comments

Comments
 (0)