Skip to content

Commit cb0ef01

Browse files
committed
codegen: Fix some sloppiness in our handling of opaque types.
Fixes #801
1 parent f19e576 commit cb0ef01

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

src/codegen/mod.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,8 @@ impl CodeGenerator for CompInfo {
15711571
}
15721572

15731573
// Yeah, sorry about that.
1574-
if item.is_opaque(ctx, &()) {
1574+
let is_opaque = item.is_opaque(ctx, &());
1575+
if is_opaque {
15751576
fields.clear();
15761577
methods.clear();
15771578

@@ -1613,7 +1614,14 @@ impl CodeGenerator for CompInfo {
16131614
// NOTE: This check is conveniently here to avoid the dummy fields we
16141615
// may add for unused template parameters.
16151616
if self.is_unsized(ctx) {
1616-
let has_address = layout.map_or(true, |l| l.size != 0);
1617+
let has_address = if is_opaque {
1618+
// Generate the address field if it's an opaque type and
1619+
// couldn't determine the layout of the blob.
1620+
layout.is_none()
1621+
} else {
1622+
layout.map_or(true, |l| l.size != 0)
1623+
};
1624+
16171625
if has_address {
16181626
let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
16191627
let field = StructFieldBuilder::named("_address")
@@ -1670,9 +1678,11 @@ impl CodeGenerator for CompInfo {
16701678
}
16711679

16721680
if used_template_params.is_none() {
1673-
for var in self.inner_vars() {
1674-
ctx.resolve_item(*var)
1675-
.codegen(ctx, result, whitelisted_items, &());
1681+
if !is_opaque {
1682+
for var in self.inner_vars() {
1683+
ctx.resolve_item(*var)
1684+
.codegen(ctx, result, whitelisted_items, &());
1685+
}
16761686
}
16771687

16781688
if ctx.options().layout_tests {
@@ -1707,8 +1717,8 @@ impl CodeGenerator for CompInfo {
17071717
})
17081718
.count() > 1;
17091719

1710-
let should_skip_field_offset_checks = item.is_opaque(ctx, &()) ||
1711-
too_many_base_vtables;
1720+
let should_skip_field_offset_checks =
1721+
is_opaque || too_many_base_vtables;
17121722

17131723
let check_field_offset = if should_skip_field_offset_checks {
17141724
None
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct B {
10+
pub _bindgen_opaque_blob: u8,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_B() {
14+
assert_eq!(::std::mem::size_of::<B>() , 1usize , concat ! (
15+
"Size of: " , stringify ! ( B ) ));
16+
assert_eq! (::std::mem::align_of::<B>() , 1usize , concat ! (
17+
"Alignment of " , stringify ! ( B ) ));
18+
}
19+
impl Clone for B {
20+
fn clone(&self) -> Self { *self }
21+
}
22+
#[repr(C)]
23+
#[derive(Debug, Default, Copy)]
24+
pub struct C {
25+
pub b: B,
26+
}
27+
#[test]
28+
fn bindgen_test_layout_C() {
29+
assert_eq!(::std::mem::size_of::<C>() , 1usize , concat ! (
30+
"Size of: " , stringify ! ( C ) ));
31+
assert_eq! (::std::mem::align_of::<C>() , 1usize , concat ! (
32+
"Alignment of " , stringify ! ( C ) ));
33+
assert_eq! (unsafe { & ( * ( 0 as * const C ) ) . b as * const _ as usize
34+
} , 0usize , concat ! (
35+
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
36+
! ( b ) ));
37+
}
38+
impl Clone for C {
39+
fn clone(&self) -> Self { *self }
40+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// bindgen-flags: --opaque-type "B" --whitelist-type "C"
2+
3+
class A;
4+
5+
class B {
6+
static A a;
7+
};
8+
9+
class C {
10+
B b;
11+
};

0 commit comments

Comments
 (0)