Skip to content

Commit e2d16d0

Browse files
GKFXpvdrz
authored andcommitted
Wrap the array representation of opaque types in a #[repr(C)] struct
1 parent d9576ea commit e2d16d0

15 files changed

+157
-23
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/issue-544-stylo-creduce-2.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/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-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,16 @@ pub(crate) mod attributes {
7575
}
7676
}
7777

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

8390
// FIXME(emilio, #412): We fall back to byte alignment, but there are
@@ -93,7 +100,12 @@ pub(crate) fn blob(layout: Layout) -> syn::Type {
93100

94101
if data_len == 1 {
95102
ty
103+
} else if ffi_safe && ctx.options().rust_features().min_const_generics {
104+
ctx.generated_opaque_array();
105+
syn::parse_quote! { __BindgenOpaqueArray<#ty, #data_len> }
96106
} else {
107+
// This is not FFI safe as an argument; the struct above is
108+
// preferable.
97109
syn::parse_quote! { [ #ty ; #data_len ] }
98110
}
99111
}

bindgen/codegen/mod.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,9 @@ impl CodeGenerator for Module {
580580
if ctx.need_bindgen_complex_type() {
581581
utils::prepend_complex_type(&mut *result);
582582
}
583+
if ctx.need_opaque_array_type() {
584+
utils::prepend_opaque_array_type(&mut *result);
585+
}
583586
if result.saw_objc {
584587
utils::prepend_objc_header(ctx, &mut *result);
585588
}
@@ -2262,7 +2265,7 @@ impl CodeGenerator for CompInfo {
22622265

22632266
if has_address {
22642267
let layout = Layout::new(1, 1);
2265-
let ty = helpers::blob(Layout::new(1, 1));
2268+
let ty = helpers::blob(ctx, Layout::new(1, 1), false);
22662269
struct_layout.saw_field_with_layout(
22672270
"_address",
22682271
layout,
@@ -2279,7 +2282,7 @@ impl CodeGenerator for CompInfo {
22792282
Some(l) => {
22802283
explicit_align = Some(l.align);
22812284

2282-
let ty = helpers::blob(l);
2285+
let ty = helpers::blob(ctx, l, false);
22832286
fields.push(quote! {
22842287
pub _bindgen_opaque_blob: #ty ,
22852288
});
@@ -2313,7 +2316,7 @@ impl CodeGenerator for CompInfo {
23132316
}
23142317

23152318
if !struct_layout.is_rust_union() {
2316-
let ty = helpers::blob(layout);
2319+
let ty = helpers::blob(ctx, layout, false);
23172320
fields.push(quote! {
23182321
pub bindgen_union_field: #ty ,
23192322
});
@@ -4009,7 +4012,8 @@ pub(crate) trait TryToOpaque {
40094012
ctx: &BindgenContext,
40104013
extra: &Self::Extra,
40114014
) -> error::Result<syn::Type> {
4012-
self.try_get_layout(ctx, extra).map(helpers::blob)
4015+
self.try_get_layout(ctx, extra)
4016+
.map(|layout| helpers::blob(ctx, layout, true))
40134017
}
40144018
}
40154019

@@ -4035,7 +4039,7 @@ pub(crate) trait ToOpaque: TryToOpaque {
40354039
extra: &Self::Extra,
40364040
) -> syn::Type {
40374041
let layout = self.get_layout(ctx, extra);
4038-
helpers::blob(layout)
4042+
helpers::blob(ctx, layout, true)
40394043
}
40404044
}
40414045

@@ -4086,7 +4090,7 @@ where
40864090
) -> error::Result<syn::Type> {
40874091
self.try_to_rust_ty(ctx, extra).or_else(|_| {
40884092
if let Ok(layout) = self.try_get_layout(ctx, extra) {
4089-
Ok(helpers::blob(layout))
4093+
Ok(helpers::blob(ctx, layout, true))
40904094
} else {
40914095
Err(Error::NoLayoutForOpaqueBlob)
40924096
}
@@ -5534,6 +5538,25 @@ pub(crate) mod utils {
55345538
result.extend(old_items);
55355539
}
55365540

5541+
pub(crate) fn prepend_opaque_array_type(
5542+
result: &mut Vec<proc_macro2::TokenStream>,
5543+
) {
5544+
let ty = quote! {
5545+
/// If Bindgen could only determine the size and alignment of a
5546+
/// type, it is represented like this.
5547+
#[derive(PartialEq, Copy, Clone, Debug, Hash)]
5548+
#[repr(C)]
5549+
pub struct __BindgenOpaqueArray<T: Copy, const N: usize>(pub [T; N]);
5550+
impl<T: Copy + Default, const N: usize> Default for __BindgenOpaqueArray<T, N> {
5551+
fn default() -> Self {
5552+
Self([<T as Default>::default(); N])
5553+
}
5554+
}
5555+
};
5556+
5557+
result.insert(0, ty);
5558+
}
5559+
55375560
pub(crate) fn build_path(
55385561
item: &Item,
55395562
ctx: &BindgenContext,

bindgen/codegen/struct_layout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl<'a> StructLayoutTracker<'a> {
393393
}
394394

395395
fn padding_field(&mut self, layout: Layout) -> proc_macro2::TokenStream {
396-
let ty = helpers::blob(layout);
396+
let ty = helpers::blob(self.ctx, layout, false);
397397
let padding_count = self.padding_count;
398398

399399
self.padding_count += 1;

bindgen/features.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ define_rust_targets! {
263263
Stable_1_71(71) => { c_unwind_abi: #106075 },
264264
Stable_1_68(68) => { abi_efiapi: #105795 },
265265
Stable_1_64(64) => { core_ffi_c: #94503 },
266-
Stable_1_51(51) => { raw_ref_macros: #80886 },
266+
Stable_1_51(51) => {
267+
raw_ref_macros: #80886,
268+
min_const_generics: #74878,
269+
},
267270
Stable_1_59(59) => { const_cstr: #54745 },
268271
Stable_1_47(47) => { larger_arrays: #74060 },
269272
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,
@@ -2607,6 +2611,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
26072611
}
26082612
}
26092613

2614+
/// Call if an opaque array is generated
2615+
pub(crate) fn generated_opaque_array(&self) {
2616+
self.generated_opaque_array.set(true)
2617+
}
2618+
2619+
/// Whether we need to generate the opaque array type
2620+
pub(crate) fn need_opaque_array_type(&self) -> bool {
2621+
self.generated_opaque_array.get()
2622+
}
2623+
26102624
/// Call if a bindgen complex is generated
26112625
pub(crate) fn generated_bindgen_complex(&self) {
26122626
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)