diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/comp.rs | 88 | ||||
-rw-r--r-- | src/ir/context.rs | 9 |
2 files changed, 63 insertions, 34 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index d57c272a..e554f9a8 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1113,21 +1113,17 @@ impl CompInfo { } // empty union case - if self.fields().is_empty() { + if !self.has_fields() { return None; } let mut max_size = 0; // Don't allow align(0) let mut max_align = 1; - for field in self.fields() { - let field_layout = field.layout(ctx); - - if let Some(layout) = field_layout { - max_size = cmp::max(max_size, layout.size); - max_align = cmp::max(max_align, layout.align); - } - } + self.each_known_field_layout(ctx, |layout| { + max_size = cmp::max(max_size, layout.size); + max_align = cmp::max(max_align, layout.align); + }); Some(Layout::new(max_size, max_align)) } @@ -1139,12 +1135,49 @@ impl CompInfo { CompFields::AfterComputingBitfieldUnits { ref fields, .. } => { fields } - CompFields::BeforeComputingBitfieldUnits(_) => { + CompFields::BeforeComputingBitfieldUnits(..) => { panic!("Should always have computed bitfield units first"); } } } + fn has_fields(&self) -> bool { + match self.fields { + CompFields::ErrorComputingBitfieldUnits => false, + CompFields::AfterComputingBitfieldUnits { ref fields, .. } => { + !fields.is_empty() + } + CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => { + !raw_fields.is_empty() + } + } + } + + fn each_known_field_layout( + &self, + ctx: &BindgenContext, + mut callback: impl FnMut(Layout), + ) { + match self.fields { + CompFields::ErrorComputingBitfieldUnits => return, + CompFields::AfterComputingBitfieldUnits { ref fields, .. } => { + for field in fields.iter() { + if let Some(layout) = field.layout(ctx) { + callback(layout); + } + } + } + CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => { + for field in raw_fields.iter() { + let field_ty = ctx.resolve_type(field.0.ty); + if let Some(layout) = field_ty.layout(ctx) { + callback(layout); + } + } + } + } + } + fn has_bitfields(&self) -> bool { match self.fields { CompFields::ErrorComputingBitfieldUnits => false, @@ -1598,23 +1631,17 @@ impl CompInfo { // Even though `libclang` doesn't expose `#pragma packed(...)`, we can // detect it through its effects. if let Some(parent_layout) = layout { - if self.fields().iter().any(|f| match *f { - Field::Bitfields(ref unit) => { - unit.layout().align > parent_layout.align - } - Field::DataMember(ref data) => { - let field_ty = ctx.resolve_type(data.ty()); - field_ty.layout(ctx).map_or(false, |field_ty_layout| { - field_ty_layout.align > parent_layout.align - }) - } - }) { + let mut packed = false; + self.each_known_field_layout(ctx, |layout| { + packed = packed || layout.align > parent_layout.align; + }); + if packed { info!("Found a struct that was defined within `#pragma packed(...)`"); return true; - } else if self.has_own_virtual_method { - if parent_layout.align == 1 { - return true; - } + } + + if self.has_own_virtual_method && parent_layout.align == 1 { + return true; } } @@ -1627,10 +1654,13 @@ impl CompInfo { } /// Compute this compound structure's bitfield allocation units. - pub fn compute_bitfield_units(&mut self, ctx: &BindgenContext) { - // TODO(emilio): If we could detect #pragma packed here we'd fix layout - // tests in divide-by-zero-in-struct-layout.rs - self.fields.compute_bitfield_units(ctx, self.packed_attr) + pub fn compute_bitfield_units( + &mut self, + ctx: &BindgenContext, + layout: Option<&Layout>, + ) { + let packed = self.is_packed(ctx, layout); + self.fields.compute_bitfield_units(ctx, packed) } /// Assign for each anonymous field a generated name. diff --git a/src/ir/context.rs b/src/ir/context.rs index 4faf6cd1..72ce06b1 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -981,12 +981,11 @@ If you encounter an error missing from this list, please file an issue or a PR!" mem::replace(&mut self.need_bitfield_allocation, vec![]); for id in need_bitfield_allocation { self.with_loaned_item(id, |ctx, item| { - item.kind_mut() - .as_type_mut() - .unwrap() - .as_comp_mut() + let ty = item.kind_mut().as_type_mut().unwrap(); + let layout = ty.layout(ctx); + ty.as_comp_mut() .unwrap() - .compute_bitfield_units(ctx); + .compute_bitfield_units(ctx, layout.as_ref()); }); } } |