Skip to content

Commit 5982cd3

Browse files
committed
codegen: Don't assume unsized structs have address.
Per C semantics, they may not.
1 parent 17275f8 commit 5982cd3

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

src/codegen/mod.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -1286,17 +1286,25 @@ impl CodeGenerator for CompInfo {
12861286
}
12871287
}
12881288

1289-
// C requires every struct to be addressable, so what C compilers do is
1290-
// making the struct 1-byte sized.
1289+
// C++ requires every struct to be addressable, so what C++ compilers do
1290+
// is making the struct 1-byte sized.
1291+
//
1292+
// This is apparently not the case for C, see:
1293+
// https://github.com/servo/rust-bindgen/issues/551
1294+
//
1295+
// Just get the layout, and assume C++ if not.
12911296
//
12921297
// NOTE: This check is conveniently here to avoid the dummy fields we
12931298
// may add for unused template parameters.
12941299
if self.is_unsized(ctx) {
1295-
let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
1296-
let field = StructFieldBuilder::named("_address")
1297-
.pub_()
1298-
.build_ty(ty);
1299-
fields.push(field);
1300+
let has_address = layout.map_or(true, |l| l.size != 0);
1301+
if has_address {
1302+
let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
1303+
let field = StructFieldBuilder::named("_address")
1304+
.pub_()
1305+
.build_ty(ty);
1306+
fields.push(field);
1307+
}
13001308
}
13011309

13021310
// Append any extra template arguments that nobody has used so far.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct Foo {
10+
}
11+
#[test]
12+
fn bindgen_test_layout_Foo() {
13+
assert_eq!(::std::mem::size_of::<Foo>() , 0usize , concat ! (
14+
"Size of: " , stringify ! ( Foo ) ));
15+
assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
16+
"Alignment of " , stringify ! ( Foo ) ));
17+
}
18+
impl Clone for Foo {
19+
fn clone(&self) -> Self { *self }
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct Foo {
10+
pub _address: u8,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_Foo() {
14+
assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! (
15+
"Size of: " , stringify ! ( Foo ) ));
16+
assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! (
17+
"Alignment of " , stringify ! ( Foo ) ));
18+
}
19+
impl Clone for Foo {
20+
fn clone(&self) -> Self { *self }
21+
}

tests/headers/c-empty-layout.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct Foo {};

tests/headers/cpp-empty-layout.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct Foo {};

0 commit comments

Comments
 (0)