Skip to content

Commit 0267b0e

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

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
@@ -581,6 +581,9 @@ impl CodeGenerator for Module {
581581
if ctx.need_bindgen_complex_type() {
582582
utils::prepend_complex_type(&mut *result);
583583
}
584+
if ctx.need_opaque_array_type() {
585+
utils::prepend_opaque_array_type(&mut *result);
586+
}
584587
if result.saw_objc {
585588
utils::prepend_objc_header(ctx, &mut *result);
586589
}
@@ -2275,7 +2278,7 @@ impl CodeGenerator for CompInfo {
22752278

22762279
if has_address {
22772280
let layout = Layout::new(1, 1);
2278-
let ty = helpers::blob(Layout::new(1, 1));
2281+
let ty = helpers::blob(ctx, Layout::new(1, 1), false);
22792282
struct_layout.saw_field_with_layout(
22802283
"_address",
22812284
layout,
@@ -2292,7 +2295,7 @@ impl CodeGenerator for CompInfo {
22922295
Some(l) => {
22932296
explicit_align = Some(l.align);
22942297

2295-
let ty = helpers::blob(l);
2298+
let ty = helpers::blob(ctx, l, false);
22962299
fields.push(quote! {
22972300
pub _bindgen_opaque_blob: #ty ,
22982301
});
@@ -2326,7 +2329,7 @@ impl CodeGenerator for CompInfo {
23262329
}
23272330

23282331
if !struct_layout.is_rust_union() {
2329-
let ty = helpers::blob(layout);
2332+
let ty = helpers::blob(ctx, layout, false);
23302333
fields.push(quote! {
23312334
pub bindgen_union_field: #ty ,
23322335
});
@@ -4048,7 +4051,8 @@ pub(crate) trait TryToOpaque {
40484051
ctx: &BindgenContext,
40494052
extra: &Self::Extra,
40504053
) -> error::Result<syn::Type> {
4051-
self.try_get_layout(ctx, extra).map(helpers::blob)
4054+
self.try_get_layout(ctx, extra)
4055+
.map(|layout| helpers::blob(ctx, layout, true))
40524056
}
40534057
}
40544058

@@ -4074,7 +4078,7 @@ pub(crate) trait ToOpaque: TryToOpaque {
40744078
extra: &Self::Extra,
40754079
) -> syn::Type {
40764080
let layout = self.get_layout(ctx, extra);
4077-
helpers::blob(layout)
4081+
helpers::blob(ctx, layout, true)
40784082
}
40794083
}
40804084

@@ -4125,7 +4129,7 @@ where
41254129
) -> error::Result<syn::Type> {
41264130
self.try_to_rust_ty(ctx, extra).or_else(|_| {
41274131
if let Ok(layout) = self.try_get_layout(ctx, extra) {
4128-
Ok(helpers::blob(layout))
4132+
Ok(helpers::blob(ctx, layout, true))
41294133
} else {
41304134
Err(Error::NoLayoutForOpaqueBlob)
41314135
}
@@ -5573,6 +5577,25 @@ pub(crate) mod utils {
55735577
result.extend(old_items);
55745578
}
55755579

5580+
pub(crate) fn prepend_opaque_array_type(
5581+
result: &mut Vec<proc_macro2::TokenStream>,
5582+
) {
5583+
let ty = quote! {
5584+
/// If Bindgen could only determine the size and alignment of a
5585+
/// type, it is represented like this.
5586+
#[derive(PartialEq, Copy, Clone, Debug, Hash)]
5587+
#[repr(C)]
5588+
pub struct __BindgenOpaqueArray<T: Copy, const N: usize>(pub [T; N]);
5589+
impl<T: Copy + Default, const N: usize> Default for __BindgenOpaqueArray<T, N> {
5590+
fn default() -> Self {
5591+
Self([<T as Default>::default(); N])
5592+
}
5593+
}
5594+
};
5595+
5596+
result.insert(0, ty);
5597+
}
5598+
55765599
pub(crate) fn build_path(
55775600
item: &Item,
55785601
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)