Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ name = "bindgen"
readme = "README.md"
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
documentation = "https://docs.rs/bindgen"
version = "0.33.2"
version = "0.34.0"
build = "build.rs"

include = [
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/impl_partialeq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn gen_partialeq_impl(
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
});
} else if comp_info.kind() == CompKind::Union {
assert!(!ctx.options().rust_features().untagged_union());
assert!(!ctx.options().rust_features().untagged_union);
tokens.push(quote! {
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
});
Expand Down
24 changes: 20 additions & 4 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1527,13 +1527,16 @@ impl CodeGenerator for CompInfo {
});
}

let mut explicit_align = None;
if is_opaque {
// Opaque item should not have generated methods, fields.
debug_assert!(fields.is_empty());
debug_assert!(methods.is_empty());

match layout {
Some(l) => {
explicit_align = Some(l.align);

let ty = helpers::blob(l);
fields.push(quote! {
pub _bindgen_opaque_blob: #ty ,
Expand All @@ -1555,6 +1558,7 @@ impl CodeGenerator for CompInfo {
if layout.align == 1 {
packed = true;
} else {
explicit_align = Some(layout.align);
let ty = helpers::blob(Layout::new(0, layout.align));
fields.push(quote! {
pub __bindgen_align: #ty ,
Expand Down Expand Up @@ -1637,6 +1641,18 @@ impl CodeGenerator for CompInfo {
attributes.push(attributes::repr("C"));
}

if ctx.options().rust_features().repr_align {
if let Some(explicit) = explicit_align {
// Ensure that the struct has the correct alignment even in
// presence of alignas.
let explicit = helpers::ast_ty::int_expr(explicit as i64);
attributes.push(quote! {
#[repr(align(#explicit))]
});
}
}


let mut derives = vec![];
if item.can_derive_debug(ctx) {
derives.push("Debug");
Expand All @@ -1655,7 +1671,7 @@ impl CodeGenerator for CompInfo {
if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
derives.push("Copy");

if ctx.options().rust_features().builtin_clone_impls() ||
if ctx.options().rust_features().builtin_clone_impls ||
used_template_params.is_some()
{
// FIXME: This requires extra logic if you have a big array in a
Expand Down Expand Up @@ -1996,7 +2012,7 @@ impl MethodCodegen for Method {
_ => panic!("How in the world?"),
};

if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi) {
return;
}

Expand Down Expand Up @@ -3167,7 +3183,7 @@ impl TryToRustTy for FunctionSig {
let abi = self.abi();

match abi {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
Ok(quote::Tokens::new())
}
Expand Down Expand Up @@ -3264,7 +3280,7 @@ impl CodeGenerator for Function {
}

let abi = match signature.abi() {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
return;
}
Expand Down
23 changes: 13 additions & 10 deletions src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ macro_rules! rust_target_base {
=> Stable_1_19 => 1.19;
/// Rust stable 1.21
=> Stable_1_21 => 1.21;
/// Rust stable 1.25
=> Stable_1_25 => 1.25;
/// Nightly rust
=> Nightly => nightly;
);
Expand All @@ -111,7 +113,10 @@ macro_rules! rust_feature_def {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct RustFeatures {
$(
$feature: bool,
$(
#[$attr]
)*
pub $feature: bool,
)*
}

Expand All @@ -124,15 +129,6 @@ macro_rules! rust_feature_def {
)*
}
}

$(
$(
#[$attr]
)*
pub fn $feature(&self) -> bool {
self.$feature
}
)*
}
}
}
Expand All @@ -144,6 +140,8 @@ rust_feature_def!(
=> thiscall_abi;
/// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
=> builtin_clone_impls;
/// repr(align) https://github.com/rust-lang/rust/pull/47006
=> repr_align;
);

impl From<RustTarget> for RustFeatures {
Expand All @@ -158,6 +156,10 @@ impl From<RustTarget> for RustFeatures {
features.builtin_clone_impls = true;
}

if rust_target >= RustTarget::Stable_1_25 {
features.repr_align = true;
}

if rust_target >= RustTarget::Nightly {
features.thiscall_abi = true;
}
Expand Down Expand Up @@ -189,6 +191,7 @@ mod test {
test_target("1.0", RustTarget::Stable_1_0);
test_target("1.19", RustTarget::Stable_1_19);
test_target("1.21", RustTarget::Stable_1_21);
test_target("1.25", RustTarget::Stable_1_25);
test_target("nightly", RustTarget::Nightly);
}
}
2 changes: 1 addition & 1 deletion src/ir/analysis/derive_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
}

if info.kind() == CompKind::Union {
if !self.ctx.options().rust_features().untagged_union() {
if !self.ctx.options().rust_features().untagged_union {
// NOTE: If there's no template parameters we can derive
// copy unconditionally, since arrays are magical for
// rustc, and __BindgenUnionField always implements
Expand Down
4 changes: 2 additions & 2 deletions src/ir/analysis/derive_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
});
return if layout_can_derive &&
!(ty.is_union() &&
self.ctx.options().rust_features().untagged_union()) {
self.ctx.options().rust_features().untagged_union) {
trace!(" we can trivially derive Debug for the layout");
ConstrainResult::Same
} else {
Expand Down Expand Up @@ -235,7 +235,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
);

if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
if self.ctx.options().rust_features().untagged_union {
trace!(" cannot derive Debug for Rust unions");
return self.insert(id);
}
Expand Down
4 changes: 2 additions & 2 deletions src/ir/analysis/derive_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
});
return if layout_can_derive &&
!(ty.is_union() &&
self.ctx.options().rust_features().untagged_union()) {
self.ctx.options().rust_features().untagged_union) {
trace!(" we can trivially derive Default for the layout");
ConstrainResult::Same
} else {
Expand Down Expand Up @@ -271,7 +271,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
}

if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
if self.ctx.options().rust_features().untagged_union {
trace!(" cannot derive Default for Rust unions");
return self.insert(id);
}
Expand Down
4 changes: 2 additions & 2 deletions src/ir/analysis/derive_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
});
return if layout_can_derive &&
!(ty.is_union() &&
self.ctx.options().rust_features().untagged_union()) {
self.ctx.options().rust_features().untagged_union) {
trace!(" we can trivially derive Hash for the layout");
ConstrainResult::Same
} else {
Expand Down Expand Up @@ -257,7 +257,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
}

if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
if self.ctx.options().rust_features().untagged_union {
trace!(" cannot derive Hash for Rust unions");
return self.insert(id);
}
Expand Down
4 changes: 2 additions & 2 deletions src/ir/analysis/derive_partialeq_or_partialord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
trace!("ty: {:?}", ty);
if item.is_opaque(self.ctx, &()) {
if ty.is_union()
&& self.ctx.options().rust_features().untagged_union()
&& self.ctx.options().rust_features().untagged_union
{
trace!(
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
Expand Down Expand Up @@ -242,7 +242,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
}

if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
if self.ctx.options().rust_features().untagged_union {
trace!(
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
);
Expand Down
2 changes: 1 addition & 1 deletion src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1543,7 +1543,7 @@ impl CompInfo {
/// 1. Current RustTarget allows for `untagged_union`
/// 2. Each field can derive `Copy`
pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool {
if !ctx.options().rust_features().untagged_union() {
if !ctx.options().rust_features().untagged_union {
return false;
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,12 @@ impl Builder {
self
}

/// Disable support for native Rust unions, if supported.
pub fn disable_untagged_union(mut self) -> Self {
self.options.rust_features.untagged_union = false;
self
}

/// Set the output graphviz file.
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
let path = path.into();
Expand Down
67 changes: 67 additions & 0 deletions tests/expectations/tests/repr-align.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
#![cfg(feature = "nightly")]

#[repr(C)]
#[repr(align(8))]
#[derive(Debug, Default, Copy, Clone)]
pub struct a {
pub b: ::std::os::raw::c_int,
pub c: ::std::os::raw::c_int,
pub __bindgen_align: [u64; 0usize],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to generate this, then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, but it doesn't hurt and avoids having the extra codepath and conditionals.

}
#[test]
fn bindgen_test_layout_a() {
assert_eq!(
::std::mem::size_of::<a>(),
8usize,
concat!("Size of: ", stringify!(a))
);
assert_eq!(
::std::mem::align_of::<a>(),
8usize,
concat!("Alignment of ", stringify!(a))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<a>())).b as *const _ as usize },
0usize,
concat!("Offset of field: ", stringify!(a), "::", stringify!(b))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<a>())).c as *const _ as usize },
4usize,
concat!("Offset of field: ", stringify!(a), "::", stringify!(c))
);
}
#[repr(C)]
#[repr(align(8))]
#[derive(Debug, Default, Copy, Clone)]
pub struct b {
pub b: ::std::os::raw::c_int,
pub c: ::std::os::raw::c_int,
pub __bindgen_align: [u64; 0usize],
}
#[test]
fn bindgen_test_layout_b() {
assert_eq!(
::std::mem::size_of::<b>(),
8usize,
concat!("Size of: ", stringify!(b))
);
assert_eq!(
::std::mem::align_of::<b>(),
8usize,
concat!("Alignment of ", stringify!(b))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<b>())).b as *const _ as usize },
0usize,
concat!("Offset of field: ", stringify!(b), "::", stringify!(b))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<b>())).c as *const _ as usize },
4usize,
concat!("Offset of field: ", stringify!(b), "::", stringify!(c))
);
}
11 changes: 11 additions & 0 deletions tests/headers/repr-align.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// bindgen-flags: --raw-line '#![cfg(feature = "nightly")]' --rust-target 1.25 -- -std=c++11

struct alignas(8) a {
int b;
int c;
};

struct alignas(double) b {
int b;
int c;
};