summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs133
-rw-r--r--src/codegen/struct_layout.rs10
-rw-r--r--src/ir/comp.rs35
3 files changed, 84 insertions, 94 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 98ab922a..843d5111 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1231,7 +1231,7 @@ trait FieldCodegen<'a> {
}
impl<'a> FieldCodegen<'a> for Field {
- type Extra = &'a str;
+ type Extra = ();
fn codegen<F, M>(
&self,
@@ -1244,7 +1244,7 @@ impl<'a> FieldCodegen<'a> for Field {
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
methods: &mut M,
- parent_canonical_name: Self::Extra,
+ _: (),
) where
F: Extend<proc_macro2::TokenStream>,
M: Extend<proc_macro2::TokenStream>,
@@ -1261,7 +1261,7 @@ impl<'a> FieldCodegen<'a> for Field {
struct_layout,
fields,
methods,
- parent_canonical_name,
+ (),
);
}
Field::Bitfields(ref unit) => {
@@ -1275,15 +1275,44 @@ impl<'a> FieldCodegen<'a> for Field {
struct_layout,
fields,
methods,
- parent_canonical_name,
+ (),
);
}
}
}
}
+fn wrap_union_field_if_needed(
+ ctx: &BindgenContext,
+ struct_layout: &StructLayoutTracker,
+ ty: proc_macro2::TokenStream,
+ result: &mut CodegenResult,
+) -> proc_macro2::TokenStream {
+ if struct_layout.is_rust_union() {
+ if struct_layout.can_copy_union_fields() {
+ ty
+ } else {
+ let prefix = ctx.trait_prefix();
+ quote! {
+ ::#prefix::mem::ManuallyDrop<#ty>
+ }
+ }
+ } else {
+ result.saw_bindgen_union();
+ if ctx.options().enable_cxx_namespaces {
+ quote! {
+ root::__BindgenUnionField<#ty>
+ }
+ } else {
+ quote! {
+ __BindgenUnionField<#ty>
+ }
+ }
+ }
+}
+
impl<'a> FieldCodegen<'a> for FieldData {
- type Extra = &'a str;
+ type Extra = ();
fn codegen<F, M>(
&self,
@@ -1296,7 +1325,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
methods: &mut M,
- parent_canonical_name: Self::Extra,
+ _: (),
) where
F: Extend<proc_macro2::TokenStream>,
M: Extend<proc_macro2::TokenStream>,
@@ -1312,8 +1341,8 @@ impl<'a> FieldCodegen<'a> for FieldData {
ty.append_implicit_template_params(ctx, field_item);
// NB: If supported, we use proper `union` types.
- let ty = if parent.is_union() && !struct_layout.is_rust_union() {
- wrap_non_copy_type_for_union(ctx, parent_canonical_name, result, ty)
+ let ty = if parent.is_union() {
+ wrap_union_field_if_needed(ctx, struct_layout, ty, result)
} else if let Some(item) = field_ty.is_incomplete_array(ctx) {
result.saw_incomplete_array();
@@ -1424,54 +1453,6 @@ impl<'a> FieldCodegen<'a> for FieldData {
}
}
-fn wrap_non_copy_type_for_union(
- ctx: &BindgenContext,
- parent_canonical_name: &str,
- result: &mut CodegenResult,
- field_ty: proc_macro2::TokenStream,
-) -> proc_macro2::TokenStream {
- let union_style = union_style_from_ctx_and_name(ctx, parent_canonical_name);
-
- match union_style {
- NonCopyUnionStyle::ManuallyDrop => {
- if ctx.options().use_core {
- quote! {
- ::core::mem::ManuallyDrop<#field_ty>
- }
- } else {
- quote! {
- ::std::mem::ManuallyDrop<#field_ty>
- }
- }
- }
- NonCopyUnionStyle::BindgenWrapper => {
- result.saw_bindgen_union();
- if ctx.options().enable_cxx_namespaces {
- quote! {
- root::__BindgenUnionField<#field_ty>
- }
- } else {
- quote! {
- __BindgenUnionField<#field_ty>
- }
- }
- }
- }
-}
-
-fn union_style_from_ctx_and_name(
- ctx: &BindgenContext,
- canonical_name: &str,
-) -> NonCopyUnionStyle {
- if ctx.options().bindgen_wrapper_union.matches(canonical_name) {
- NonCopyUnionStyle::BindgenWrapper
- } else if ctx.options().manually_drop_union.matches(canonical_name) {
- NonCopyUnionStyle::ManuallyDrop
- } else {
- ctx.options().default_non_copy_union_style
- }
-}
-
impl BitfieldUnit {
/// Get the constructor name for this bitfield unit.
fn ctor_name(&self) -> proc_macro2::TokenStream {
@@ -1538,7 +1519,7 @@ fn access_specifier(
}
impl<'a> FieldCodegen<'a> for BitfieldUnit {
- type Extra = &'a str;
+ type Extra = ();
fn codegen<F, M>(
&self,
@@ -1551,7 +1532,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
struct_layout: &mut StructLayoutTracker,
fields: &mut F,
methods: &mut M,
- parent_canonical_name: Self::Extra,
+ _: (),
) where
F: Extend<proc_macro2::TokenStream>,
M: Extend<proc_macro2::TokenStream>,
@@ -1562,17 +1543,15 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
let layout = self.layout();
let unit_field_ty = helpers::bitfield_unit(ctx, layout);
- let field_ty = {
- if parent.is_union() && !struct_layout.is_rust_union() {
- wrap_non_copy_type_for_union(
- ctx,
- parent_canonical_name,
- result,
- unit_field_ty.clone(),
- )
- } else {
- unit_field_ty.clone()
- }
+ let field_ty = if parent.is_union() {
+ wrap_union_field_if_needed(
+ ctx,
+ struct_layout,
+ unit_field_ty.clone(),
+ result,
+ )
+ } else {
+ unit_field_ty.clone()
};
{
@@ -1894,7 +1873,7 @@ impl CodeGenerator for CompInfo {
&mut struct_layout,
&mut fields,
&mut methods,
- &canonical_name,
+ (),
);
}
// Check whether an explicit padding field is needed
@@ -2000,10 +1979,7 @@ impl CodeGenerator for CompInfo {
explicit_align = Some(layout.align);
}
- if !struct_layout.is_rust_union() &&
- union_style_from_ctx_and_name(ctx, &canonical_name) ==
- NonCopyUnionStyle::BindgenWrapper
- {
+ if !struct_layout.is_rust_union() {
let ty = helpers::blob(ctx, layout);
fields.push(quote! {
pub bindgen_union_field: #ty ,
@@ -2130,15 +2106,6 @@ impl CodeGenerator for CompInfo {
#( #attributes )*
pub union #canonical_ident
}
- } else if is_union &&
- !struct_layout.is_rust_union() &&
- union_style_from_ctx_and_name(ctx, &canonical_name) ==
- NonCopyUnionStyle::ManuallyDrop
- {
- quote! {
- #( #attributes )*
- pub union #canonical_ident
- }
} else {
quote! {
#( #attributes )*
diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs
index 657be0b4..ddac1b0a 100644
--- a/src/codegen/struct_layout.rs
+++ b/src/codegen/struct_layout.rs
@@ -20,6 +20,7 @@ pub struct StructLayoutTracker<'a> {
is_packed: bool,
known_type_layout: Option<Layout>,
is_rust_union: bool,
+ can_copy_union_fields: bool,
latest_offset: usize,
padding_count: usize,
latest_field_layout: Option<Layout>,
@@ -90,8 +91,8 @@ impl<'a> StructLayoutTracker<'a> {
) -> Self {
let known_type_layout = ty.layout(ctx);
let is_packed = comp.is_packed(ctx, known_type_layout.as_ref());
- let is_rust_union = comp.is_union() &&
- comp.can_be_rust_union(ctx, known_type_layout.as_ref());
+ let (is_rust_union, can_copy_union_fields) =
+ comp.is_rust_union(ctx, known_type_layout.as_ref(), name);
StructLayoutTracker {
name,
ctx,
@@ -99,6 +100,7 @@ impl<'a> StructLayoutTracker<'a> {
is_packed,
known_type_layout,
is_rust_union,
+ can_copy_union_fields,
latest_offset: 0,
padding_count: 0,
latest_field_layout: None,
@@ -107,6 +109,10 @@ impl<'a> StructLayoutTracker<'a> {
}
}
+ pub fn can_copy_union_fields(&self) -> bool {
+ self.can_copy_union_fields
+ }
+
pub fn is_rust_union(&self) -> bool {
self.is_rust_union
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index fdf6a963..f44c5d67 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -14,6 +14,7 @@ use crate::codegen::struct_layout::{align_to, bytes_from_bits_pow2};
use crate::ir::derive::CanDeriveCopy;
use crate::parse::{ClangItemParser, ParseError};
use crate::HashMap;
+use crate::NonCopyUnionStyle;
use peeking_take_while::PeekableExt;
use std::cmp;
use std::io;
@@ -1680,21 +1681,37 @@ impl CompInfo {
///
/// Requirements:
/// 1. Current RustTarget allows for `untagged_union`
- /// 2. Each field can derive `Copy`
+ /// 2. Each field can derive `Copy` or we use ManuallyDrop.
/// 3. It's not zero-sized.
- pub fn can_be_rust_union(
+ ///
+ /// Second boolean returns whether all fields can be copied (and thus
+ /// ManuallyDrop is not needed).
+ pub fn is_rust_union(
&self,
ctx: &BindgenContext,
layout: Option<&Layout>,
- ) -> bool {
+ name: &str,
+ ) -> (bool, bool) {
+ if !self.is_union() {
+ return (false, false);
+ }
+
if !ctx.options().rust_features().untagged_union {
- return false;
+ return (false, false);
}
if self.is_forward_declaration() {
- return false;
+ return (false, false);
}
+ let union_style = if ctx.options().bindgen_wrapper_union.matches(name) {
+ NonCopyUnionStyle::BindgenWrapper
+ } else if ctx.options().manually_drop_union.matches(name) {
+ NonCopyUnionStyle::ManuallyDrop
+ } else {
+ ctx.options().default_non_copy_union_style
+ };
+
let all_can_copy = self.fields().iter().all(|f| match *f {
Field::DataMember(ref field_data) => {
field_data.ty().can_derive_copy(ctx)
@@ -1702,15 +1719,15 @@ impl CompInfo {
Field::Bitfields(_) => true,
});
- if !all_can_copy {
- return false;
+ if !all_can_copy && union_style == NonCopyUnionStyle::BindgenWrapper {
+ return (false, false);
}
if layout.map_or(false, |l| l.size == 0) {
- return false;
+ return (false, false);
}
- true
+ (true, all_can_copy)
}
}