Skip to content

Commit 84cfacc

Browse files
committed
Fix packed structs with flexible array members
Wrap the FAM generic parameter in `ManuallyDrop` when the parent struct is packed. This satisfies Rust's requirement that DST fields in packed structs must not need `Drop` to be run. The fix automatically detects packed structs and generates: pub field: ::std::mem::ManuallyDrop<FAM> instead of: pub field: FAM Fixes #2936
1 parent d23fcd2 commit 84cfacc

File tree

3 files changed

+232
-1
lines changed

3 files changed

+232
-1
lines changed

bindgen-tests/tests/expectations/tests/packed_flexarray.rs

Lines changed: 200 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// bindgen-flags: --rust-target nightly --flexarray-dst --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(ptr_metadata, layout_for_ptr)]'
2+
3+
#pragma pack(1)
4+
5+
typedef struct PackedTest
6+
{
7+
short int Head;
8+
long int Tail[];
9+
}
10+
PackedTest;
11+
12+
#pragma pack()
13+
14+
typedef struct UnpackedTest
15+
{
16+
short int Head;
17+
long int Tail[];
18+
}
19+
UnpackedTest;

bindgen/codegen/mod.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,8 +1515,20 @@ impl FieldCodegen<'_> for FieldData {
15151515
} else if let Some(item) = field_ty.is_incomplete_array(ctx) {
15161516
// Only FAM if its the last field
15171517
if ctx.options().flexarray_dst && last_field {
1518+
// Check if parent struct is packed to determine if we need ManuallyDrop
1519+
let layout = parent_item.expect_type().layout(ctx);
1520+
let is_packed = parent.is_packed(ctx, layout.as_ref());
15181521
struct_layout.saw_flexible_array();
1519-
syn::parse_quote! { FAM }
1522+
1523+
// For packed structs, we need to wrap FAM in ManuallyDrop
1524+
// because Rust requires that DST fields in packed structs
1525+
// don't need Drop to be run.
1526+
if is_packed {
1527+
let prefix = ctx.trait_prefix();
1528+
syn::parse_quote! { ::#prefix::mem::ManuallyDrop<FAM> }
1529+
} else {
1530+
syn::parse_quote! { FAM }
1531+
}
15201532
} else {
15211533
result.saw_incomplete_array();
15221534

0 commit comments

Comments
 (0)