Skip to content

Commit 185a5f3

Browse files
authored
Merge pull request #1531 from emilio/ref-layout
Work around a libclang bug / limitation.
2 parents 3a6864c + 9b6d0e8 commit 185a5f3

File tree

10 files changed

+225
-33
lines changed

10 files changed

+225
-33
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ Released YYYY/MM/DD
9292

9393
* TODO (or remove section if none)
9494

95+
--------------------------------------------------------------------------------
96+
97+
# 0.48.1
98+
99+
Released 2019/03/06
100+
101+
## Fixed
102+
103+
* Bindgen will properly lay out types that use reference members. [#1531][]
104+
105+
[#1531]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1531
95106

96107
--------------------------------------------------------------------------------
97108

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ readme = "README.md"
1414
repository = "https://github.com/rust-lang/rust-bindgen"
1515
documentation = "https://docs.rs/bindgen"
1616
homepage = "https://rust-lang.github.io/rust-bindgen/"
17-
version = "0.48.0"
17+
version = "0.48.1"
1818
build = "build.rs"
1919

2020
include = [

src/clang.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use cexpr;
88
use clang_sys::*;
99
use regex;
10+
use ir::context::BindgenContext;
1011
use std::{mem, ptr, slice};
1112
use std::ffi::{CStr, CString};
1213
use std::fmt;
@@ -933,35 +934,44 @@ impl Type {
933934

934935
#[inline]
935936
fn is_non_deductible_auto_type(&self) -> bool {
936-
self.kind() == CXType_Auto && self.canonical_type() == *self
937+
debug_assert_eq!(self.kind(), CXType_Auto);
938+
self.canonical_type() == *self
937939
}
938940

939941
#[inline]
940-
fn clang_size_of(&self) -> c_longlong {
941-
if self.is_non_deductible_auto_type() {
942-
return -6; // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
942+
fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong {
943+
match self.kind() {
944+
// Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
945+
CXType_RValueReference |
946+
CXType_LValueReference => ctx.target_pointer_size() as c_longlong,
947+
// Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
948+
CXType_Auto if self.is_non_deductible_auto_type() => return -6,
949+
_ => unsafe { clang_Type_getSizeOf(self.x) },
943950
}
944-
unsafe { clang_Type_getSizeOf(self.x) }
945951
}
946952

947953
#[inline]
948-
fn clang_align_of(&self) -> c_longlong {
949-
if self.is_non_deductible_auto_type() {
950-
return -6; // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
954+
fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong {
955+
match self.kind() {
956+
// Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
957+
CXType_RValueReference |
958+
CXType_LValueReference => ctx.target_pointer_size() as c_longlong,
959+
// Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
960+
CXType_Auto if self.is_non_deductible_auto_type() => return -6,
961+
_ => unsafe { clang_Type_getAlignOf(self.x) },
951962
}
952-
unsafe { clang_Type_getAlignOf(self.x) }
953963
}
954964

955965
/// What is the size of this type? Paper over invalid types by returning `0`
956966
/// for them.
957-
pub fn size(&self) -> usize {
958-
let val = self.clang_size_of();
967+
pub fn size(&self, ctx: &BindgenContext) -> usize {
968+
let val = self.clang_size_of(ctx);
959969
if val < 0 { 0 } else { val as usize }
960970
}
961971

962972
/// What is the size of this type?
963-
pub fn fallible_size(&self) -> Result<usize, LayoutError> {
964-
let val = self.clang_size_of();
973+
pub fn fallible_size(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> {
974+
let val = self.clang_size_of(ctx);
965975
if val < 0 {
966976
Err(LayoutError::from(val as i32))
967977
} else {
@@ -971,14 +981,14 @@ impl Type {
971981

972982
/// What is the alignment of this type? Paper over invalid types by
973983
/// returning `0`.
974-
pub fn align(&self) -> usize {
975-
let val = self.clang_align_of();
984+
pub fn align(&self, ctx: &BindgenContext) -> usize {
985+
let val = self.clang_align_of(ctx);
976986
if val < 0 { 0 } else { val as usize }
977987
}
978988

979989
/// What is the alignment of this type?
980-
pub fn fallible_align(&self) -> Result<usize, LayoutError> {
981-
let val = self.clang_align_of();
990+
pub fn fallible_align(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> {
991+
let val = self.clang_align_of(ctx);
982992
if val < 0 {
983993
Err(LayoutError::from(val as i32))
984994
} else {
@@ -988,10 +998,10 @@ impl Type {
988998

989999
/// Get the layout for this type, or an error describing why it does not
9901000
/// have a valid layout.
991-
pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> {
1001+
pub fn fallible_layout(&self, ctx: &BindgenContext) -> Result<::ir::layout::Layout, LayoutError> {
9921002
use ir::layout::Layout;
993-
let size = self.fallible_size()?;
994-
let align = self.fallible_align()?;
1003+
let size = self.fallible_size(ctx)?;
1004+
let align = self.fallible_align(ctx)?;
9951005
Ok(Layout::new(size, align))
9961006
}
9971007

src/ir/context.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,7 +1755,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
17551755
sub_name,
17561756
template_decl_cursor
17571757
.cur_type()
1758-
.fallible_layout()
1758+
.fallible_layout(self)
17591759
.ok(),
17601760
sub_kind,
17611761
false,
@@ -1821,7 +1821,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
18211821
let name = if name.is_empty() { None } else { Some(name) };
18221822
let ty = Type::new(
18231823
name,
1824-
ty.fallible_layout().ok(),
1824+
ty.fallible_layout(self).ok(),
18251825
type_kind,
18261826
ty.is_const(),
18271827
);
@@ -1977,7 +1977,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19771977
is_const: bool,
19781978
) -> TypeId {
19791979
let spelling = ty.spelling();
1980-
let layout = ty.fallible_layout().ok();
1980+
let layout = ty.fallible_layout(self).ok();
19811981
let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
19821982
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
19831983
let item = Item::new(
@@ -2018,7 +2018,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20182018
CXType_UShort => TypeKind::Int(IntKind::UShort),
20192019
CXType_WChar => {
20202020
TypeKind::Int(IntKind::WChar {
2021-
size: ty.fallible_size().expect("Couldn't compute size of wchar_t?"),
2021+
size: ty.fallible_size(self).expect("Couldn't compute size of wchar_t?"),
20222022
})
20232023
},
20242024
CXType_Char16 => TypeKind::Int(IntKind::U16),
@@ -2056,7 +2056,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20562056

20572057
let spelling = ty.spelling();
20582058
let is_const = ty.is_const();
2059-
let layout = ty.fallible_layout().ok();
2059+
let layout = ty.fallible_layout(self).ok();
20602060
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
20612061
let id = self.next_item_id();
20622062
let item =

src/ir/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ impl Item {
454454
ty: &clang::Type,
455455
ctx: &mut BindgenContext,
456456
) -> TypeId {
457-
let ty = Opaque::from_clang_ty(ty);
457+
let ty = Opaque::from_clang_ty(ty, ctx);
458458
let kind = ItemKind::Type(ty);
459459
let parent = ctx.root_module().into();
460460
ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None);

src/ir/layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ pub struct Opaque(pub Layout);
100100

101101
impl Opaque {
102102
/// Construct a new opaque type from the given clang type.
103-
pub fn from_clang_ty(ty: &clang::Type) -> Type {
104-
let layout = Layout::new(ty.size(), ty.align());
103+
pub fn from_clang_ty(ty: &clang::Type, ctx: &BindgenContext) -> Type {
104+
let layout = Layout::new(ty.size(ctx), ty.align(ctx));
105105
let ty_kind = TypeKind::Opaque;
106106
let is_const = ty.is_const();
107107
Type::new(None, Some(layout), ty_kind, is_const)

src/ir/ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ impl Type {
730730
}
731731
}
732732

733-
let layout = ty.fallible_layout().ok();
733+
let layout = ty.fallible_layout(ctx).ok();
734734
let cursor = ty.declaration();
735735
let mut name = cursor.spelling();
736736

@@ -780,7 +780,7 @@ impl Type {
780780
opaque type instead."
781781
);
782782
return Ok(
783-
ParseResult::New(Opaque::from_clang_ty(&canonical_ty), None),
783+
ParseResult::New(Opaque::from_clang_ty(&canonical_ty, ctx), None),
784784
);
785785
}
786786

@@ -912,7 +912,7 @@ impl Type {
912912
from class template or base \
913913
specifier, using opaque blob"
914914
);
915-
let opaque = Opaque::from_clang_ty(ty);
915+
let opaque = Opaque::from_clang_ty(ty, ctx);
916916
return Ok(
917917
ParseResult::New(opaque, None),
918918
);
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
10+
#[repr(C)]
11+
#[derive(Debug, Copy, Clone)]
12+
pub struct Foo {
13+
_unused: [u8; 0],
14+
}
15+
#[repr(C)]
16+
#[derive(Debug, Copy, Clone)]
17+
pub struct Bar {
18+
pub f: *const Foo,
19+
pub m: ::std::os::raw::c_uint,
20+
}
21+
#[test]
22+
fn bindgen_test_layout_Bar() {
23+
assert_eq!(
24+
::std::mem::size_of::<Bar>(),
25+
16usize,
26+
concat!("Size of: ", stringify!(Bar))
27+
);
28+
assert_eq!(
29+
::std::mem::align_of::<Bar>(),
30+
8usize,
31+
concat!("Alignment of ", stringify!(Bar))
32+
);
33+
assert_eq!(
34+
unsafe { &(*(::std::ptr::null::<Bar>())).f as *const _ as usize },
35+
0usize,
36+
concat!("Offset of field: ", stringify!(Bar), "::", stringify!(f))
37+
);
38+
assert_eq!(
39+
unsafe { &(*(::std::ptr::null::<Bar>())).m as *const _ as usize },
40+
8usize,
41+
concat!("Offset of field: ", stringify!(Bar), "::", stringify!(m))
42+
);
43+
}
44+
impl Default for Bar {
45+
fn default() -> Self {
46+
unsafe { ::std::mem::zeroed() }
47+
}
48+
}
49+
#[repr(C)]
50+
#[derive(Debug, Copy, Clone)]
51+
pub struct Baz {
52+
pub f: *mut Foo,
53+
pub m: ::std::os::raw::c_uint,
54+
}
55+
#[test]
56+
fn bindgen_test_layout_Baz() {
57+
assert_eq!(
58+
::std::mem::size_of::<Baz>(),
59+
16usize,
60+
concat!("Size of: ", stringify!(Baz))
61+
);
62+
assert_eq!(
63+
::std::mem::align_of::<Baz>(),
64+
8usize,
65+
concat!("Alignment of ", stringify!(Baz))
66+
);
67+
assert_eq!(
68+
unsafe { &(*(::std::ptr::null::<Baz>())).f as *const _ as usize },
69+
0usize,
70+
concat!("Offset of field: ", stringify!(Baz), "::", stringify!(f))
71+
);
72+
assert_eq!(
73+
unsafe { &(*(::std::ptr::null::<Baz>())).m as *const _ as usize },
74+
8usize,
75+
concat!("Offset of field: ", stringify!(Baz), "::", stringify!(m))
76+
);
77+
}
78+
impl Default for Baz {
79+
fn default() -> Self {
80+
unsafe { ::std::mem::zeroed() }
81+
}
82+
}
83+
#[repr(C)]
84+
#[derive(Debug, Copy, Clone)]
85+
pub struct Tar {
86+
pub f: *const Foo,
87+
pub m: ::std::os::raw::c_uint,
88+
}
89+
#[test]
90+
fn bindgen_test_layout_Tar() {
91+
assert_eq!(
92+
::std::mem::size_of::<Tar>(),
93+
16usize,
94+
concat!("Size of: ", stringify!(Tar))
95+
);
96+
assert_eq!(
97+
::std::mem::align_of::<Tar>(),
98+
8usize,
99+
concat!("Alignment of ", stringify!(Tar))
100+
);
101+
assert_eq!(
102+
unsafe { &(*(::std::ptr::null::<Tar>())).f as *const _ as usize },
103+
0usize,
104+
concat!("Offset of field: ", stringify!(Tar), "::", stringify!(f))
105+
);
106+
assert_eq!(
107+
unsafe { &(*(::std::ptr::null::<Tar>())).m as *const _ as usize },
108+
8usize,
109+
concat!("Offset of field: ", stringify!(Tar), "::", stringify!(m))
110+
);
111+
}
112+
impl Default for Tar {
113+
fn default() -> Self {
114+
unsafe { ::std::mem::zeroed() }
115+
}
116+
}
117+
#[repr(C)]
118+
#[derive(Debug, Copy, Clone)]
119+
pub struct Taz {
120+
pub f: *mut Foo,
121+
pub m: ::std::os::raw::c_uint,
122+
}
123+
#[test]
124+
fn bindgen_test_layout_Taz() {
125+
assert_eq!(
126+
::std::mem::size_of::<Taz>(),
127+
16usize,
128+
concat!("Size of: ", stringify!(Taz))
129+
);
130+
assert_eq!(
131+
::std::mem::align_of::<Taz>(),
132+
8usize,
133+
concat!("Alignment of ", stringify!(Taz))
134+
);
135+
assert_eq!(
136+
unsafe { &(*(::std::ptr::null::<Taz>())).f as *const _ as usize },
137+
0usize,
138+
concat!("Offset of field: ", stringify!(Taz), "::", stringify!(f))
139+
);
140+
assert_eq!(
141+
unsafe { &(*(::std::ptr::null::<Taz>())).m as *const _ as usize },
142+
8usize,
143+
concat!("Offset of field: ", stringify!(Taz), "::", stringify!(m))
144+
);
145+
}
146+
impl Default for Taz {
147+
fn default() -> Self {
148+
unsafe { ::std::mem::zeroed() }
149+
}
150+
}

tests/headers/issue-1443.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct Foo;
2+
3+
struct Bar {
4+
const Foo& f;
5+
unsigned m;
6+
};
7+
8+
struct Baz {
9+
Foo& f;
10+
unsigned m;
11+
};
12+
13+
struct Tar {
14+
const Foo&& f;
15+
unsigned m;
16+
};
17+
18+
struct Taz {
19+
Foo&& f;
20+
unsigned m;
21+
};

0 commit comments

Comments
 (0)