summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs40
-rw-r--r--src/features.rs8
-rw-r--r--src/ir/context.rs6
-rw-r--r--src/ir/traversal.rs12
4 files changed, 46 insertions, 20 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 63e1e11e..6483412e 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2127,7 +2127,7 @@ impl EnumVariation {
fn is_bitfield(&self) -> bool {
match *self {
- EnumVariation::Bitfield => true,
+ EnumVariation::Bitfield {..} => true,
_ => false
}
}
@@ -2248,6 +2248,7 @@ impl<'a> EnumBuilder<'a> {
mangling_prefix: Option<&str>,
rust_ty: quote::Tokens,
result: &mut CodegenResult<'b>,
+ is_ty_named: bool,
) -> Self {
let variant_name = ctx.rust_mangle(variant.name());
let expr = match variant.val() {
@@ -2279,19 +2280,28 @@ impl<'a> EnumBuilder<'a> {
}
}
- EnumBuilder::Bitfield { .. } => {
- let constant_name = match mangling_prefix {
- Some(prefix) => {
- Cow::Owned(format!("{}_{}", prefix, variant_name))
- }
- None => variant_name,
- };
-
- let ident = ctx.rust_ident(constant_name);
- result.push(quote! {
- #doc
- pub const #ident : #rust_ty = #rust_ty ( #expr );
- });
+ EnumBuilder::Bitfield { canonical_name, .. } => {
+ if ctx.options().rust_features().associated_const && is_ty_named {
+ let enum_ident = ctx.rust_ident(canonical_name);
+ let variant_ident = ctx.rust_ident(variant_name);
+ result.push(quote! {
+ impl #enum_ident {
+ #doc
+ pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
+ }
+ });
+ } else {
+ let ident = ctx.rust_ident(match mangling_prefix {
+ Some(prefix) => {
+ Cow::Owned(format!("{}_{}", prefix, variant_name))
+ }
+ None => variant_name,
+ });
+ result.push(quote! {
+ #doc
+ pub const #ident : #rust_ty = #rust_ty ( #expr );
+ });
+ }
self
}
@@ -2626,6 +2636,7 @@ impl CodeGenerator for Enum {
constant_mangling_prefix,
enum_rust_ty.clone(),
result,
+ enum_ty.name().is_some(),
);
}
}
@@ -2636,6 +2647,7 @@ impl CodeGenerator for Enum {
constant_mangling_prefix,
enum_rust_ty.clone(),
result,
+ enum_ty.name().is_some(),
);
let variant_name = ctx.rust_ident(variant.name());
diff --git a/src/features.rs b/src/features.rs
index 866d7126..93ebbc34 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -90,6 +90,8 @@ macro_rules! rust_target_base {
=> Stable_1_0 => 1.0;
/// Rust stable 1.19
=> Stable_1_19 => 1.19;
+ /// Rust stable 1.20
+ => Stable_1_20 => 1.20;
/// Rust stable 1.21
=> Stable_1_21 => 1.21;
/// Rust stable 1.25
@@ -142,6 +144,8 @@ rust_feature_def!(
=> builtin_clone_impls;
/// repr(align) https://github.com/rust-lang/rust/pull/47006
=> repr_align;
+ /// associated constants https://github.com/rust-lang/rust/issues/29646
+ => associated_const;
);
impl From<RustTarget> for RustFeatures {
@@ -152,6 +156,10 @@ impl From<RustTarget> for RustFeatures {
features.untagged_union = true;
}
+ if rust_target >= RustTarget::Stable_1_20 {
+ features.associated_const = true;
+ }
+
if rust_target >= RustTarget::Stable_1_21 {
features.builtin_clone_impls = true;
}
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 6ced43e8..58a90ba6 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -2316,7 +2316,11 @@ impl BindgenContext {
if self.options().whitelist_recursively {
traversal::all_edges
} else {
- traversal::no_edges
+ // Only follow InnerType edges from the whitelisted roots.
+ // Such inner types (e.g. anonymous structs/unions) are
+ // always emitted by codegen, and they need to be whitelisted
+ // to make sure they are processed by e.g. the derive analysis.
+ traversal::only_inner_type_edges
};
let whitelisted = WhitelistedItemsTraversal::new(
diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs
index 491a15f8..c37b0b5f 100644
--- a/src/ir/traversal.rs
+++ b/src/ir/traversal.rs
@@ -201,11 +201,13 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool {
true
}
-/// A `TraversalPredicate` implementation that never follows any edges, and
-/// therefore traversals using this predicate will only visit the traversal's
-/// roots.
-pub fn no_edges(_: &BindgenContext, _: Edge) -> bool {
- false
+/// A `TraversalPredicate` implementation that only follows
+/// `EdgeKind::InnerType` edges, and therefore traversals using this predicate
+/// will only visit the traversal's roots and their inner types. This is used
+/// in no-recursive-whitelist mode, where inner types such as anonymous
+/// structs/unions still need to be processed.
+pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool {
+ edge.kind == EdgeKind::InnerType
}
/// A `TraversalPredicate` implementation that only follows edges to items that