summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Legnitto <christian@legnitto.com>2019-01-07 20:06:34 -0800
committerChristian Legnitto <christian@legnitto.com>2019-01-08 08:56:19 -0800
commit3994a9a3a75245fcec59a2a3e62f163c1fa2e24b (patch)
treeba331e1ce2f9216896394783085003da86526ea8 /src
parent28c0eb4505865220d6f2a8f779f5876dc753feac (diff)
Support #[repr(packed(N))] on Rust 1.33+
Fixes https://github.com/rust-lang/rust-bindgen/issues/537.
Diffstat (limited to 'src')
-rw-r--r--src/codegen/helpers.rs3
-rw-r--r--src/codegen/mod.rs5
-rw-r--r--src/features.rs6
-rw-r--r--src/ir/comp.rs23
4 files changed, 25 insertions, 12 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
index d6377194..457979b6 100644
--- a/src/codegen/helpers.rs
+++ b/src/codegen/helpers.rs
@@ -7,6 +7,7 @@ use quote::TokenStreamExt;
pub mod attributes {
use proc_macro2::{Ident, Span, TokenStream};
+ use std::str::FromStr;
pub fn repr(which: &str) -> TokenStream {
let which = Ident::new(which, Span::call_site());
@@ -16,7 +17,7 @@ pub mod attributes {
}
pub fn repr_list(which_ones: &[&str]) -> TokenStream {
- let which_ones = which_ones.iter().cloned().map(|one| Ident::new(one, Span::call_site()));
+ let which_ones = which_ones.iter().cloned().map(|one| TokenStream::from_str(one).expect("repr to be valid"));
quote! {
#[repr( #( #which_ones ),* )]
}
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 6fd7e7d3..d3395edf 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1673,7 +1673,10 @@ impl CodeGenerator for CompInfo {
attributes.push(attributes::doc(comment));
}
if packed && !is_opaque {
- attributes.push(attributes::repr_list(&["C", "packed"]));
+ let n = layout.map_or(1, |l| l.align);
+ assert!(ctx.options().rust_features().repr_packed_n || n == 1);
+ let packed_repr = if n == 1 { "packed".to_string() } else { format!("packed({})", n) };
+ attributes.push(attributes::repr_list(&["C", &packed_repr]));
} else {
attributes.push(attributes::repr("C"));
}
diff --git a/src/features.rs b/src/features.rs
index 1f700039..b5a63402 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -102,6 +102,8 @@ macro_rules! rust_target_base {
=> Stable_1_27 => 1.27;
/// Rust stable 1.28
=> Stable_1_28 => 1.28;
+ /// Rust stable 1.33
+ => Stable_1_33 => 1.33;
/// Nightly rust
=> Nightly => nightly;
);
@@ -190,6 +192,10 @@ rust_feature_def!(
/// repr(transparent) ([PR](https://github.com/rust-lang/rust/pull/51562))
=> repr_transparent;
}
+ Stable_1_33 {
+ /// repr(packed(N)) ([PR](https://github.com/rust-lang/rust/pull/57049))
+ => repr_packed_n;
+ }
Nightly {
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
=> thiscall_abi;
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index fd4c8274..12a8fa32 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -1649,16 +1649,19 @@ impl IsOpaque for CompInfo {
return true;
}
- // We don't have `#[repr(packed = "N")]` in Rust yet, so the best we can
- // do is make this struct opaque.
- //
- // See https://github.com/rust-lang-nursery/rust-bindgen/issues/537 and
- // https://github.com/rust-lang/rust/issues/33158
- if self.is_packed(ctx, layout) && layout.map_or(false, |l| l.align > 1) {
- warn!("Found a type that is both packed and aligned to greater than \
- 1; Rust doesn't have `#[repr(packed = \"N\")]` yet, so we \
- are treating it as opaque");
- return true;
+ if !ctx.options().rust_features().repr_packed_n {
+ // If we don't have `#[repr(packed(N)]`, the best we can
+ // do is make this struct opaque.
+ //
+ // See https://github.com/rust-lang-nursery/rust-bindgen/issues/537 and
+ // https://github.com/rust-lang/rust/issues/33158
+ if self.is_packed(ctx, layout) && layout.map_or(false, |l| l.align > 1) {
+ warn!("Found a type that is both packed and aligned to greater than \
+ 1; Rust before version 1.33 doesn't have `#[repr(packed(N))]`, so we \
+ are treating it as opaque. You may wish to set bindgen's rust target \
+ version to 1.33 or later to enable `#[repr(packed(N))]` support.");
+ return true;
+ }
}
false