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

14 files changed

+143
-19
lines changed

bindgen-integration/src/lib.rs

+1-1
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

+13-3
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

+13-3
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

+11-1
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

+11-1
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

+11-1
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

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
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

+15-1
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

+29-6
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,

bindgen/codegen/struct_layout.rs

+1-1
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

+1
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 },

bindgen/ir/context.rs

+14
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ pub(crate) struct BindgenContext {
388388
/// The options given by the user via cli or other medium.
389389
options: BindgenOptions,
390390

391+
/// Whether an opaque array was generated
392+
generated_opaque_array: Cell<bool>,
393+
391394
/// Whether a bindgen complex was generated
392395
generated_bindgen_complex: Cell<bool>,
393396

@@ -595,6 +598,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
595598
options,
596599
generated_bindgen_complex: Cell::new(false),
597600
generated_bindgen_float16: Cell::new(false),
601+
generated_opaque_array: Cell::new(false),
598602
allowlisted: None,
599603
blocklisted_types_implement_traits: Default::default(),
600604
codegen_items: None,
@@ -2646,6 +2650,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
26462650
}
26472651
}
26482652

2653+
/// Call if an opaque array is generated
2654+
pub(crate) fn generated_opaque_array(&self) {
2655+
self.generated_opaque_array.set(true)
2656+
}
2657+
2658+
/// Whether we need to generate the opaque array type
2659+
pub(crate) fn need_opaque_array_type(&self) -> bool {
2660+
self.generated_opaque_array.get()
2661+
}
2662+
26492663
/// Call if a bindgen complex is generated
26502664
pub(crate) fn generated_bindgen_complex(&self) {
26512665
self.generated_bindgen_complex.set(true)

bindgen/ir/ty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ pub(crate) enum TypeKind {
582582
/// A compound type, that is, a class, struct, or union.
583583
Comp(CompInfo),
584584

585-
/// An opaque type that we just don't understand. All usage of this shoulf
585+
/// An opaque type that we just don't understand. All usage of this should
586586
/// result in an opaque blob of bytes generated from the containing type's
587587
/// layout.
588588
Opaque,

0 commit comments

Comments
 (0)