Skip to content

Commit 37cf177

Browse files
committed
Make bitfield unit allocation fallible
Instead of panicking when we see a bitfield that does not have a layout, return an error up the stack. If we get an error when allocating bitfields into units, then make the whole struct opaque. Fixes rust-lang#1140
1 parent 406b477 commit 37cf177

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

src/ir/comp.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl FieldMethods for RawField {
466466
fn raw_fields_to_fields_and_bitfield_units<I>(
467467
ctx: &BindgenContext,
468468
raw_fields: I,
469-
) -> Vec<Field>
469+
) -> Result<Vec<Field>, ()>
470470
where
471471
I: IntoIterator<Item = RawField>,
472472
{
@@ -503,15 +503,15 @@ where
503503
&mut bitfield_unit_count,
504504
&mut fields,
505505
bitfields,
506-
);
506+
)?;
507507
}
508508

509509
assert!(
510510
raw_fields.next().is_none(),
511511
"The above loop should consume all items in `raw_fields`"
512512
);
513513

514-
fields
514+
Ok(fields)
515515
}
516516

517517
/// Given a set of contiguous raw bitfields, group and allocate them into
@@ -521,7 +521,8 @@ fn bitfields_to_allocation_units<E, I>(
521521
bitfield_unit_count: &mut usize,
522522
fields: &mut E,
523523
raw_bitfields: I,
524-
) where
524+
) -> Result<(), ()>
525+
where
525526
E: Extend<Field>,
526527
I: IntoIterator<Item = RawField>,
527528
{
@@ -572,7 +573,7 @@ fn bitfields_to_allocation_units<E, I>(
572573
let bitfield_width = bitfield.bitfield_width().unwrap() as usize;
573574
let bitfield_layout = ctx.resolve_type(bitfield.ty())
574575
.layout(ctx)
575-
.expect("Bitfield without layout? Gah!");
576+
.ok_or(())?;
576577
let bitfield_size = bitfield_layout.size;
577578
let bitfield_align = bitfield_layout.align;
578579

@@ -649,6 +650,8 @@ fn bitfields_to_allocation_units<E, I>(
649650
bitfields_in_unit,
650651
);
651652
}
653+
654+
Ok(())
652655
}
653656

654657
/// A compound structure's fields are initially raw, and have bitfields that
@@ -662,6 +665,7 @@ fn bitfields_to_allocation_units<E, I>(
662665
enum CompFields {
663666
BeforeComputingBitfieldUnits(Vec<RawField>),
664667
AfterComputingBitfieldUnits(Vec<Field>),
668+
ErrorComputingBitfieldUnits,
665669
}
666670

667671
impl Default for CompFields {
@@ -676,7 +680,7 @@ impl CompFields {
676680
CompFields::BeforeComputingBitfieldUnits(ref mut raws) => {
677681
raws.push(raw);
678682
}
679-
CompFields::AfterComputingBitfieldUnits(_) => {
683+
_ => {
680684
panic!(
681685
"Must not append new fields after computing bitfield allocation units"
682686
);
@@ -689,22 +693,36 @@ impl CompFields {
689693
CompFields::BeforeComputingBitfieldUnits(ref mut raws) => {
690694
mem::replace(raws, vec![])
691695
}
692-
CompFields::AfterComputingBitfieldUnits(_) => {
696+
_ => {
693697
panic!("Already computed bitfield units");
694698
}
695699
};
696700

697-
let fields_and_units =
701+
let result =
698702
raw_fields_to_fields_and_bitfield_units(ctx, raws);
699-
mem::replace(
700-
self,
701-
CompFields::AfterComputingBitfieldUnits(fields_and_units),
702-
);
703+
704+
match result {
705+
Ok(fields_and_units) => {
706+
mem::replace(
707+
self,
708+
CompFields::AfterComputingBitfieldUnits(fields_and_units));
709+
}
710+
Err(()) => {
711+
mem::replace(
712+
self,
713+
CompFields::ErrorComputingBitfieldUnits
714+
);
715+
}
716+
}
703717
}
704718

705719
fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) {
706720
let fields = match *self {
707721
CompFields::AfterComputingBitfieldUnits(ref mut fields) => fields,
722+
CompFields::ErrorComputingBitfieldUnits => {
723+
// Nothing to do here.
724+
return;
725+
}
708726
CompFields::BeforeComputingBitfieldUnits(_) => {
709727
panic!("Not yet computed bitfield units.");
710728
}
@@ -787,6 +805,7 @@ impl Trace for CompFields {
787805
T: Tracer,
788806
{
789807
match *self {
808+
CompFields::ErrorComputingBitfieldUnits => {}
790809
CompFields::BeforeComputingBitfieldUnits(ref fields) => {
791810
for f in fields {
792811
tracer.visit_kind(f.ty().into(), EdgeKind::Field);
@@ -1046,6 +1065,7 @@ impl CompInfo {
10461065
/// Get this type's set of fields.
10471066
pub fn fields(&self) -> &[Field] {
10481067
match self.fields {
1068+
CompFields::ErrorComputingBitfieldUnits => &[][..],
10491069
CompFields::AfterComputingBitfieldUnits(ref fields) => fields,
10501070
CompFields::BeforeComputingBitfieldUnits(_) => {
10511071
panic!("Should always have computed bitfield units first");
@@ -1558,6 +1578,10 @@ impl IsOpaque for CompInfo {
15581578
return true
15591579
}
15601580

1581+
if let CompFields::ErrorComputingBitfieldUnits = self.fields {
1582+
return true;
1583+
}
1584+
15611585
// Bitfields with a width that is larger than their unit's width have
15621586
// some strange things going on, and the best we can do is make the
15631587
// whole struct opaque.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
7+
8+
/// We don't get a layout for this bitfield, since we don't know what `T` will
9+
/// be, so we cannot allocate bitfield units. The best thing we can do is make
10+
/// the struct opaque.
11+
#[repr(C)]
12+
#[derive(Debug, Default, Copy, Clone)]
13+
pub struct TemplatizedBitfield {
14+
pub _address: u8,
15+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/// We don't get a layout for this bitfield, since we don't know what `T` will
2+
/// be, so we cannot allocate bitfield units. The best thing we can do is make
3+
/// the struct opaque.
4+
template <class T>
5+
class TemplatizedBitfield {
6+
T t : 6;
7+
};

0 commit comments

Comments
 (0)