Skip to content

Commit 9a49ea2

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

File tree

11 files changed

+131
-17
lines changed

11 files changed

+131
-17
lines changed

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

Lines changed: 15 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: 15 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: 13 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: 13 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: 13 additions & 1 deletion
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: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@ 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(ctx: &BindgenContext, layout: Layout, ffi_safe: bool) -> syn::Type {
8388
let opaque = layout.opaque();
8489

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

99104
if data_len == 1 {
100105
ty
106+
} else if ffi_safe && ctx.options().rust_features().min_const_generics {
107+
ctx.generated_opaque_array();
108+
syn::parse_quote! { __BindgenOpaqueArray<#ty, #data_len> }
101109
} else {
110+
// This is not FFI safe as an argument; the struct above is
111+
// preferable.
102112
syn::parse_quote! { [ #ty ; #data_len ] }
103113
}
104114
}

bindgen/codegen/mod.rs

Lines changed: 31 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,27 @@ 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, Hash, Debug)]
5452+
#[repr(C)]
5453+
pub struct __BindgenOpaqueArray<T, const N: usize>(pub [T; N]);
5454+
/// `Default` is only implemented for zero-sized opaque types, since
5455+
/// Bindgen does not know what contents make sense as a default.
5456+
impl<T> Default for __BindgenOpaqueArray<T, 0> {
5457+
fn default() -> Self {
5458+
Self([])
5459+
}
5460+
}
5461+
};
5462+
5463+
result.insert(0, ty);
5464+
}
5465+
54415466
pub(crate) fn build_path(
54425467
item: &Item,
54435468
ctx: &BindgenContext,

bindgen/codegen/struct_layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ impl<'a> StructLayoutTracker<'a> {
401401
}
402402

403403
fn padding_field(&mut self, layout: Layout) -> proc_macro2::TokenStream {
404-
let ty = helpers::blob(self.ctx, layout);
404+
let ty = helpers::blob(self.ctx, layout, false);
405405
let padding_count = self.padding_count;
406406

407407
self.padding_count += 1;

bindgen/features.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ define_rust_targets! {
104104
Stable_1_71(71) => { c_unwind_abi: #106075 },
105105
Stable_1_68(68) => { abi_efiapi: #105795 },
106106
Stable_1_64(64) => { core_ffi_c: #94503 },
107+
Stable_1_51(51) => { min_const_generics: #74878 },
107108
Stable_1_59(59) => { const_cstr: #54745 },
108109
Stable_1_47(47) => { larger_arrays: #74060 },
109110
Stable_1_43(43) => { associated_constants: #68952 },

0 commit comments

Comments
 (0)