Skip to content

Commit f56fbce

Browse files
csmulhernemilio
authored andcommitted
Improves bindings for typed and anonymous enums
1 parent 1f1766d commit f56fbce

37 files changed

+147
-82
lines changed

src/clang.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
44
#![allow(non_upper_case_globals, dead_code)]
55

6-
76
use crate::ir::context::BindgenContext;
87
use cexpr;
98
use clang_sys::*;
@@ -498,6 +497,19 @@ impl Cursor {
498497
}
499498
}
500499

500+
/// Get the boolean constant value for this cursor's enum variant referent.
501+
///
502+
/// Returns None if the cursor's referent is not an enum variant.
503+
pub fn enum_val_boolean(&self) -> Option<bool> {
504+
unsafe {
505+
if self.kind() == CXCursor_EnumConstantDecl {
506+
Some(clang_getEnumConstantDeclValue(self.x) != 0)
507+
} else {
508+
None
509+
}
510+
}
511+
}
512+
501513
/// Get the signed constant value for this cursor's enum variant referent.
502514
///
503515
/// Returns None if the cursor's referent is not an enum variant.

src/codegen/mod.rs

+42-12
Original file line numberDiff line numberDiff line change
@@ -2438,6 +2438,7 @@ enum EnumBuilder<'a> {
24382438
is_bitfield: bool,
24392439
},
24402440
Consts {
2441+
repr: proc_macro2::TokenStream,
24412442
variants: Vec<proc_macro2::TokenStream>,
24422443
codegen_depth: usize,
24432444
},
@@ -2459,6 +2460,14 @@ impl<'a> EnumBuilder<'a> {
24592460
}
24602461
}
24612462

2463+
/// Returns true if the builder is for a rustified enum.
2464+
fn is_rust_enum(&self) -> bool {
2465+
match *self {
2466+
EnumBuilder::Rust { .. } => true,
2467+
_ => false,
2468+
}
2469+
}
2470+
24622471
/// Create a new enum given an item builder, a canonical name, a name for
24632472
/// the representation, and which variation it should be generated as.
24642473
fn new(
@@ -2467,6 +2476,7 @@ impl<'a> EnumBuilder<'a> {
24672476
repr: proc_macro2::TokenStream,
24682477
enum_variation: EnumVariation,
24692478
enum_codegen_depth: usize,
2479+
is_ty_named: bool,
24702480
) -> Self {
24712481
let ident = Ident::new(name, Span::call_site());
24722482

@@ -2492,13 +2502,22 @@ impl<'a> EnumBuilder<'a> {
24922502
}
24932503
}
24942504

2495-
EnumVariation::Consts => EnumBuilder::Consts {
2496-
variants: vec![quote! {
2497-
#( #attrs )*
2498-
pub type #ident = #repr;
2499-
}],
2500-
codegen_depth: enum_codegen_depth,
2501-
},
2505+
EnumVariation::Consts => {
2506+
let mut variants = Vec::new();
2507+
2508+
if is_ty_named {
2509+
variants.push(quote! {
2510+
#( #attrs )*
2511+
pub type #ident = #repr;
2512+
});
2513+
}
2514+
2515+
EnumBuilder::Consts {
2516+
repr: repr,
2517+
variants: variants,
2518+
codegen_depth: enum_codegen_depth,
2519+
}
2520+
}
25022521

25032522
EnumVariation::ModuleConsts => {
25042523
let ident = Ident::new(
@@ -2530,7 +2549,12 @@ impl<'a> EnumBuilder<'a> {
25302549
is_ty_named: bool,
25312550
) -> Self {
25322551
let variant_name = ctx.rust_mangle(variant.name());
2552+
let is_rust_enum = self.is_rust_enum();
25332553
let expr = match variant.val() {
2554+
EnumVariantValue::Boolean(v) if is_rust_enum => {
2555+
helpers::ast_ty::uint_expr(v as u64)
2556+
}
2557+
EnumVariantValue::Boolean(v) => quote!(#v),
25342558
EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
25352559
EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
25362560
};
@@ -2593,18 +2617,20 @@ impl<'a> EnumBuilder<'a> {
25932617
self
25942618
}
25952619

2596-
EnumBuilder::Consts { .. } => {
2620+
EnumBuilder::Consts { ref repr, .. } => {
25972621
let constant_name = match mangling_prefix {
25982622
Some(prefix) => {
25992623
Cow::Owned(format!("{}_{}", prefix, variant_name))
26002624
}
26012625
None => variant_name,
26022626
};
26032627

2628+
let ty = if is_ty_named { &rust_ty } else { repr };
2629+
26042630
let ident = ctx.rust_ident(constant_name);
26052631
result.push(quote! {
26062632
#doc
2607-
pub const #ident : #rust_ty = #expr ;
2633+
pub const #ident : #ty = #expr ;
26082634
});
26092635

26102636
self
@@ -2859,9 +2885,12 @@ impl CodeGenerator for Enum {
28592885
});
28602886
}
28612887

2862-
let repr = {
2863-
let repr_name = ctx.rust_ident_raw(repr_name);
2864-
quote! { #repr_name }
2888+
let repr = match self.repr() {
2889+
Some(ty) => ty.to_rust_ty_or_opaque(ctx, &()),
2890+
None => {
2891+
let repr_name = ctx.rust_ident_raw(repr_name);
2892+
quote! { #repr_name }
2893+
}
28652894
};
28662895

28672896
let mut builder = EnumBuilder::new(
@@ -2870,6 +2899,7 @@ impl CodeGenerator for Enum {
28702899
repr,
28712900
variation,
28722901
item.codegen_depth(ctx),
2902+
enum_ty.name().is_some(),
28732903
);
28742904

28752905
// A map where we keep a value -> variant relation.

src/ir/enum_ty.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use super::super::codegen::EnumVariation;
44
use super::context::{BindgenContext, TypeId};
55
use super::item::Item;
6-
use super::ty::TypeKind;
6+
use super::ty::{Type, TypeKind};
77
use crate::clang;
88
use crate::ir::annotations::Annotations;
99
use crate::ir::item::ItemCanonicalPath;
@@ -69,15 +69,17 @@ impl Enum {
6969
.and_then(|et| Item::from_ty(&et, declaration, None, ctx).ok());
7070
let mut variants = vec![];
7171

72+
let variant_ty =
73+
repr.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx));
74+
let is_bool = variant_ty.map_or(false, Type::is_bool);
75+
7276
// Assume signedness since the default type by the C standard is an int.
73-
let is_signed = repr
74-
.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx))
75-
.map_or(true, |ty| match *ty.kind() {
76-
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
77-
ref other => {
78-
panic!("Since when enums can be non-integers? {:?}", other)
79-
}
80-
});
77+
let is_signed = variant_ty.map_or(true, |ty| match *ty.kind() {
78+
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
79+
ref other => {
80+
panic!("Since when enums can be non-integers? {:?}", other)
81+
}
82+
});
8183

8284
let type_name = ty.spelling();
8385
let type_name = if type_name.is_empty() {
@@ -90,7 +92,9 @@ impl Enum {
9092
let definition = declaration.definition().unwrap_or(declaration);
9193
definition.visit(|cursor| {
9294
if cursor.kind() == CXCursor_EnumConstantDecl {
93-
let value = if is_signed {
95+
let value = if is_bool {
96+
cursor.enum_val_boolean().map(EnumVariantValue::Boolean)
97+
} else if is_signed {
9498
cursor.enum_val_signed().map(EnumVariantValue::Signed)
9599
} else {
96100
cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned)
@@ -234,6 +238,9 @@ pub struct EnumVariant {
234238
/// A constant value assigned to an enumeration variant.
235239
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
236240
pub enum EnumVariantValue {
241+
/// A boolean constant.
242+
Boolean(bool),
243+
237244
/// A signed constant.
238245
Signed(i64),
239246

tests/expectations/tests/bitfield-enum-basic.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ::std::ops::BitAndAssign for Foo {
4545
}
4646
#[repr(transparent)]
4747
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
48-
pub struct Foo(pub i32);
48+
pub struct Foo(pub ::std::os::raw::c_int);
4949
impl Buz {
5050
pub const Bar: Buz = Buz(2);
5151
}
@@ -86,7 +86,7 @@ impl ::std::ops::BitAndAssign for Buz {
8686
}
8787
#[repr(transparent)]
8888
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
89-
pub struct Buz(pub i8);
89+
pub struct Buz(pub ::std::os::raw::c_schar);
9090
pub const NS_FOO: _bindgen_ty_1 = _bindgen_ty_1(1);
9191
pub const NS_BAR: _bindgen_ty_1 = _bindgen_ty_1(2);
9292
impl ::std::ops::BitOr<_bindgen_ty_1> for _bindgen_ty_1 {
@@ -117,7 +117,7 @@ impl ::std::ops::BitAndAssign for _bindgen_ty_1 {
117117
}
118118
#[repr(transparent)]
119119
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
120-
pub struct _bindgen_ty_1(pub u32);
120+
pub struct _bindgen_ty_1(pub ::std::os::raw::c_uint);
121121
#[repr(C)]
122122
#[derive(Debug, Default, Copy, Clone)]
123123
pub struct Dummy {
@@ -153,7 +153,7 @@ impl ::std::ops::BitAndAssign for Dummy__bindgen_ty_1 {
153153
}
154154
#[repr(transparent)]
155155
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
156-
pub struct Dummy__bindgen_ty_1(pub u32);
156+
pub struct Dummy__bindgen_ty_1(pub ::std::os::raw::c_uint);
157157
#[test]
158158
fn bindgen_test_layout_Dummy() {
159159
assert_eq!(

tests/expectations/tests/bitfield-enum-repr-c.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ impl ::std::ops::BitAndAssign for Foo {
4545
}
4646
#[repr(C)]
4747
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
48-
pub struct Foo(pub i32);
48+
pub struct Foo(pub ::std::os::raw::c_int);

tests/expectations/tests/bitfield-enum-repr-transparent.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ impl ::std::ops::BitAndAssign for Foo {
4545
}
4646
#[repr(transparent)]
4747
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
48-
pub struct Foo(pub i32);
48+
pub struct Foo(pub ::std::os::raw::c_int);

tests/expectations/tests/constify-all-enums.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
pub const foo_THIS: foo = 0;
99
pub const foo_SHOULD_BE: foo = 1;
1010
pub const foo_A_CONSTANT: foo = 2;
11-
pub type foo = u32;
11+
pub type foo = ::std::os::raw::c_uint;
1212
#[repr(C)]
1313
#[derive(Debug, Copy, Clone)]
1414
pub struct bar {

tests/expectations/tests/constify-module-enums-basic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
)]
77

88
pub mod foo {
9-
pub type Type = u32;
9+
pub type Type = ::std::os::raw::c_uint;
1010
pub const THIS: Type = 0;
1111
pub const SHOULD_BE: Type = 1;
1212
pub const A_CONSTANT: Type = 2;

tests/expectations/tests/constify-module-enums-namespace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub mod root {
1616
#[allow(unused_imports)]
1717
use self::super::super::super::root;
1818
pub mod foo {
19-
pub type Type = u32;
19+
pub type Type = ::std::os::raw::c_uint;
2020
pub const THIS: Type = 0;
2121
pub const SHOULD_BE: Type = 1;
2222
pub const A_CONSTANT: Type = 2;

tests/expectations/tests/constify-module-enums-shadow-name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
)]
77

88
pub mod foo {
9-
pub type Type = u32;
9+
pub type Type = ::std::os::raw::c_uint;
1010
pub const Type: Type = 0;
1111
pub const Type_: Type = 1;
1212
pub const Type1: Type = 2;

tests/expectations/tests/constify-module-enums-simple-alias.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
)]
77

88
pub mod Foo {
9-
pub type Type = i32;
9+
pub type Type = ::std::os::raw::c_int;
1010
pub const Variant1: Type = 0;
1111
pub const Variant2: Type = 1;
1212
pub const Variant3: Type = 2;

tests/expectations/tests/constify-module-enums-simple-nonamespace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
)]
77

88
pub mod one_Foo {
9-
pub type Type = i32;
9+
pub type Type = ::std::os::raw::c_int;
1010
pub const Variant1: Type = 0;
1111
pub const Variant2: Type = 1;
1212
}

tests/expectations/tests/constify-module-enums-types.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@
66
)]
77

88
pub mod foo {
9-
pub type Type = u32;
9+
pub type Type = ::std::os::raw::c_uint;
1010
pub const THIS: Type = 0;
1111
pub const SHOULD_BE: Type = 1;
1212
pub const A_CONSTANT: Type = 2;
1313
pub const ALSO_THIS: Type = 42;
1414
pub const AND_ALSO_THIS: Type = 42;
1515
}
1616
pub mod anon_enum {
17-
pub type Type = u32;
17+
pub type Type = ::std::os::raw::c_uint;
1818
pub const Variant1: Type = 0;
1919
pub const Variant2: Type = 1;
2020
pub const Variant3: Type = 2;
2121
}
2222
pub mod ns1_foo {
23-
pub type Type = u32;
23+
pub type Type = ::std::os::raw::c_uint;
2424
pub const THIS: Type = 0;
2525
pub const SHOULD_BE: Type = 1;
2626
pub const A_CONSTANT: Type = 2;
2727
pub const ALSO_THIS: Type = 42;
2828
}
2929
pub mod ns2_Foo {
30-
pub type Type = i32;
30+
pub type Type = ::std::os::raw::c_int;
3131
pub const Variant1: Type = 0;
3232
pub const Variant2: Type = 1;
3333
}
@@ -205,7 +205,7 @@ impl Default for Baz {
205205
}
206206
}
207207
pub mod one_Foo {
208-
pub type Type = i32;
208+
pub type Type = ::std::os::raw::c_int;
209209
pub const Variant1: Type = 0;
210210
pub const Variant2: Type = 1;
211211
}

tests/expectations/tests/default-enum-style-constified-module.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
)]
77

88
pub mod Foo {
9-
pub type Type = u32;
9+
pub type Type = ::std::os::raw::c_uint;
1010
pub const bar: Type = 0;
1111
pub const baz: Type = 1;
1212
pub const blap: Type = 2;

tests/expectations/tests/empty-enum.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@
55
non_upper_case_globals
66
)]
77

8-
pub type EmptyConstified = u32;
8+
pub type EmptyConstified = ::std::os::raw::c_uint;
99
#[repr(u32)]
1010
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1111
pub enum EmptyRustified {
1212
__bindgen_cannot_repr_c_on_empty_enum = 0,
1313
}
1414
pub mod EmptyModule {
15-
pub type Type = u32;
15+
pub type Type = ::std::os::raw::c_uint;
1616
}
1717
#[repr(i8)]
1818
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1919
pub enum EmptyClassRustified {
2020
__bindgen_cannot_repr_c_on_empty_enum = 0,
2121
}
22-
pub type EmptyClassConstified = i8;
22+
pub type EmptyClassConstified = ::std::os::raw::c_char;
2323
pub mod EmptyClassModule {
24-
pub type Type = i8;
24+
pub type Type = ::std::os::raw::c_char;
2525
}
2626
#[repr(i8)]
2727
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2828
pub enum ForwardClassRustified {
2929
__bindgen_cannot_repr_c_on_empty_enum = 0,
3030
}
31-
pub type ForwardClassConstified = i8;
31+
pub type ForwardClassConstified = ::std::os::raw::c_char;
3232
pub mod ForwardClassModule {
33-
pub type Type = i8;
33+
pub type Type = ::std::os::raw::c_char;
3434
}

0 commit comments

Comments
 (0)