diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-21 05:03:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-21 05:03:08 -0700 |
commit | 480c2d197199e7b1f824a01cc63acd33d81f6622 (patch) | |
tree | a244ca35506dc52f8a965a797dedeaa5715a5e82 | |
parent | 232a21ebc4a4ddc2468aed8e54d165c613037038 (diff) | |
parent | 814d28e0f256a24865f633b5992ced6f035d6f4c (diff) |
Auto merge of #741 - tmfink:feature-699-constified-enum-module, r=emilio
Feature 699 constified enum module
This is a work in progress for issue #699 that adds the `--constified-enum-module` option to bindgen.
@emilio, could you give me some guidance on fixing the uses of the enum variant types? In the example below, `foo` should be replaced with `foo::Type`. I'm not sure of the proper way to rename `Item`s after the structures have been defined. My initial thought was to redefine the `CodeGenerator` trait to take a mutable reference to `item`, but that will not work because of the borrow checker. Thoughts?
Todo:
- [x] put constified enum variants in a `mod`
- [x] ensure references to constified enum `foo` are changed to `foo::Type`
- [x] handle `typedef` enums
-----
Given the input header `tests/headers/constify-module-enums.h`:
~~~c
// bindgen-flags: --constified-enum-module foo
enum foo {
THIS,
SHOULD_BE,
A_CONSTANT,
};
struct bar {
enum foo this_should_work;
};
~~~
`$ cargo run -- tests/headers/constify-module-enums.h --constified-enum-module foo --no-layout-tests` will output:
~~~rust
/* automatically generated by rust-bindgen */
pub mod foo {
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct bar {
pub this_should_work: foo,
}
impl Clone for bar {
fn clone(&self) -> Self { *self }
}
~~~
-rw-r--r-- | src/codegen/mod.rs | 74 | ||||
-rw-r--r-- | src/ir/enum_ty.rs | 15 | ||||
-rw-r--r-- | src/ir/item.rs | 54 | ||||
-rw-r--r-- | src/lib.rs | 29 | ||||
-rw-r--r-- | src/options.rs | 18 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-basic.rs | 45 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-namespace.rs | 52 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-shadow-name.rs | 36 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-simple-alias.rs | 80 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-simple-nonamespace.rs | 40 | ||||
-rw-r--r-- | tests/expectations/tests/constify-module-enums-types.rs | 193 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-basic.h | 17 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-namespace.hpp | 17 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-shadow-name.h | 12 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-simple-alias.hpp | 21 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-simple-nonamespace.hpp | 12 | ||||
-rw-r--r-- | tests/headers/constify-module-enums-types.hpp | 78 |
17 files changed, 776 insertions, 17 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 3aff1b68..d926f02b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -36,9 +36,12 @@ use std::mem; use std::ops; use syntax::abi; use syntax::ast; -use syntax::codemap::{Span, respan}; +use syntax::codemap::{DUMMY_SP, Span, respan}; use syntax::ptr::P; +// Name of type defined in constified enum module +pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type"; + fn root_import_depth(ctx: &BindgenContext, item: &Item) -> usize { if !ctx.options().enable_cxx_namespaces { return 0; @@ -244,7 +247,6 @@ impl ForeignModBuilder { } fn build(self, ctx: &BindgenContext) -> P<ast::Item> { - use syntax::codemap::DUMMY_SP; P(ast::Item { ident: ctx.rust_ident(""), id: ast::DUMMY_NODE_ID, @@ -2049,6 +2051,10 @@ enum EnumBuilder<'a> { aster: P<ast::Item>, }, Consts { aster: P<ast::Item> }, + ModuleConsts { + module_name: &'a str, + module_items: Vec<P<ast::Item>>, + }, } impl<'a> EnumBuilder<'a> { @@ -2058,7 +2064,8 @@ impl<'a> EnumBuilder<'a> { name: &'a str, repr: P<ast::Ty>, bitfield_like: bool, - constify: bool) + constify: bool, + constify_module: bool) -> Self { if bitfield_like { EnumBuilder::Bitfield { @@ -2070,8 +2077,20 @@ impl<'a> EnumBuilder<'a> { .build(), } } else if constify { - EnumBuilder::Consts { - aster: aster.type_(name).build_ty(repr), + if constify_module { + let type_definition = aster::item::ItemBuilder::new() + .pub_() + .type_(CONSTIFIED_ENUM_MODULE_REPR_NAME) + .build_ty(repr); + + EnumBuilder::ModuleConsts { + module_name: name, + module_items: vec![type_definition], + } + } else { + EnumBuilder::Consts { + aster: aster.type_(name).build_ty(repr), + } } } else { EnumBuilder::Rust(aster.enum_(name)) @@ -2143,6 +2162,27 @@ impl<'a> EnumBuilder<'a> { result.push(constant); self } + EnumBuilder::ModuleConsts { module_name, module_items, .. } => { + // Variant type + let inside_module_type = + aster::AstBuilder::new().ty().id(CONSTIFIED_ENUM_MODULE_REPR_NAME); + + let constant = aster::AstBuilder::new() + .item() + .pub_() + .const_(&*variant_name) + .expr() + .build(expr) + .build(inside_module_type.clone()); + + let mut module_items = module_items.clone(); + module_items.push(constant); + + EnumBuilder::ModuleConsts { + module_name, + module_items, + } + } } } @@ -2208,6 +2248,22 @@ impl<'a> EnumBuilder<'a> { aster } EnumBuilder::Consts { aster, .. } => aster, + EnumBuilder::ModuleConsts { module_items, module_name, .. } => { + // Create module item with type and variant definitions + let module_item = P(ast::Item { + ident: ast::Ident::from_str(module_name), + attrs: vec![], + id: ast::DUMMY_NODE_ID, + node: ast::ItemKind::Mod(ast::Mod { + inner: DUMMY_SP, + items: module_items, + }), + vis: ast::Visibility::Public, + span: DUMMY_SP, + }); + + module_item + } } } } @@ -2273,7 +2329,10 @@ impl CodeGenerator for Enum { .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) }; - let is_constified_enum = { + let is_constified_enum_module = self.is_constified_enum_module(ctx, item); + + let is_constified_enum = { + is_constified_enum_module || ctx.options().constified_enums.matches(&name) || (enum_ty.name().is_none() && self.variants() @@ -2353,7 +2412,8 @@ impl CodeGenerator for Enum { &name, repr, is_bitfield, - is_constified_enum); + is_constified_enum, + is_constified_enum_module); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, String>::new(); diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs index e64354fb..38de01d9 100644 --- a/src/ir/enum_ty.rs +++ b/src/ir/enum_ty.rs @@ -5,11 +5,14 @@ use super::item::Item; use super::ty::TypeKind; use clang; use ir::annotations::Annotations; +use ir::item::ItemCanonicalName; use parse::{ClangItemParser, ParseError}; /// An enum representing custom handling that can be given to a variant. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum EnumVariantCustomBehavior { + /// This variant will be a module containing constants. + ModuleConstify, /// This variant will be constified, that is, forced to generate a constant. Constify, /// This variant will be hidden entirely from the resulting enum. @@ -121,6 +124,18 @@ impl Enum { }); Ok(Enum::new(repr, variants)) } + + /// Whether the enum should be an constified enum module + pub fn is_constified_enum_module(&self, ctx: &BindgenContext, item: &Item) -> bool { + let name = item.canonical_name(ctx); + let enum_ty = item.expect_type(); + + ctx.options().constified_enum_modules.matches(&name) || + (enum_ty.name().is_none() && + self.variants() + .iter() + .any(|v| ctx.options().constified_enum_modules.matches(&v.name()))) + } } /// A single enum variant, to be contained only in an enum. diff --git a/src/ir/item.rs b/src/ir/item.rs index d41fe54a..b80ddbd9 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1,5 +1,6 @@ //! Bindgen's core intermediate representation type. +use super::super::codegen::CONSTIFIED_ENUM_MODULE_REPR_NAME; use super::annotations::Annotations; use super::context::{BindgenContext, ItemId, PartialType}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; @@ -825,6 +826,36 @@ impl Item { _ => None, } } + + /// Returns whether the item is a constified module enum + fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool { + // Do not jump through aliases, except for aliases that point to a type + // with the same name, since we dont generate coe for them. + let item = self.id.into_resolver().through_type_refs().resolve(ctx); + let type_ = match *item.kind() { + ItemKind::Type(ref type_) => type_, + _ => return false, + }; + + match *type_.kind() { + TypeKind::Enum(ref enum_) => { + enum_.is_constified_enum_module(ctx, self) + } + TypeKind::Alias(inner_id) => { + // TODO(emilio): Make this "hop through type aliases that aren't + // really generated" an option in `ItemResolver`? + let inner_item = ctx.resolve_item(inner_id); + let name = item.canonical_name(ctx); + + if inner_item.canonical_name(ctx) == name { + inner_item.is_constified_enum_module(ctx) + } else { + false + } + } + _ => false, + } + } } /// A set of items. @@ -1443,14 +1474,25 @@ impl ItemCanonicalPath for Item { fn namespace_aware_canonical_path(&self, ctx: &BindgenContext) -> Vec<String> { - let path = self.canonical_path(ctx); - if ctx.options().enable_cxx_namespaces { - return path; - } + let mut path = self.canonical_path(ctx); + + // ASSUMPTION: (disable_name_namespacing && cxx_namespaces) + // is equivalent to + // disable_name_namespacing if ctx.options().disable_name_namespacing { - return vec![path.last().unwrap().clone()]; + // Only keep the last item in path + let split_idx = path.len() - 1; + path = path.split_off(split_idx); + } else if !ctx.options().enable_cxx_namespaces { + // Ignore first item "root" + path = vec![path[1..].join("_")]; } - return vec![path[1..].join("_")]; + + if self.is_constified_enum_module(ctx) { + path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into()); + } + + return path; } fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> { @@ -206,6 +206,16 @@ impl Builder { .count(); self.options + .constified_enum_modules + .get_items() + .iter() + .map(|item| { + output_vector.push("--constified-enum-module".into()); + output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); + }) + .count(); + + self.options .hidden_types .get_items() .iter() @@ -562,8 +572,8 @@ impl Builder { self } - /// Mark the given enum (or set of enums, if using a pattern) as being - /// constant. + /// Mark the given enum (or set of enums, if using a pattern) as a set of + /// constants. /// /// This makes bindgen generate constants instead of enums. Regular /// expressions are supported. @@ -572,6 +582,16 @@ impl Builder { self } + /// Mark the given enum (or set of enums, if using a pattern) as a set of + /// constants that should be put into a module. + /// + /// This makes bindgen generate a modules containing constants instead of + /// enums. Regular expressions are supported. + pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.constified_enum_modules.insert(arg); + self + } + /// Add a string to prepend to the generated bindings. The string is passed /// through without any modification. pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder { @@ -813,6 +833,9 @@ pub struct BindgenOptions { /// The enum patterns to mark an enum as constant. pub constified_enums: RegexSet, + /// The enum patterns to mark an enum as a module of constants. + pub constified_enum_modules: RegexSet, + /// Whether we should generate builtins or not. pub builtins: bool, @@ -935,6 +958,7 @@ impl BindgenOptions { self.hidden_types.build(); self.opaque_types.build(); self.bitfield_enums.build(); + self.constified_enum_modules.build(); self.constified_enums.build(); } } @@ -949,6 +973,7 @@ impl Default for BindgenOptions { whitelisted_vars: Default::default(), bitfield_enums: Default::default(), constified_enums: Default::default(), + constified_enum_modules: Default::default(), builtins: false, links: vec![], emit_ast: false, diff --git a/src/options.rs b/src/options.rs index fc0dd247..6a6fde81 100644 --- a/src/options.rs +++ b/src/options.rs @@ -33,6 +33,15 @@ pub fn builder_from_flags<I> .takes_value(true) .multiple(true) .number_of_values(1), + Arg::with_name("constified-enum-module") + .long("constified-enum-module") + .help("Mark any enum whose name matches <regex> as a module of \ + constants instead of an enumeration. This option \ + implies \"--constified-enum.\"") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), Arg::with_name("blacklist-type") .long("blacklist-type") .help("Mark <type> as hidden.") @@ -222,12 +231,17 @@ pub fn builder_from_flags<I> } } - if let Some(bitfields) = matches.values_of("constified-enum") { - for regex in bitfields { + if let Some(constifieds) = matches.values_of("constified-enum") { + for regex in constifieds { builder = builder.constified_enum(regex); } } + if let Some(constified_mods) = matches.values_of("constified-enum-module") { + for regex in constified_mods { + builder = builder.constified_enum_module(regex); + } + } if let Some(hidden_types) = matches.values_of("blacklist-type") { for ty in hidden_types { builder = builder.hide_type(ty); diff --git a/tests/expectations/tests/constify-module-enums-basic.rs b/tests/expectations/tests/constify-module-enums-basic.rs new file mode 100644 index 00000000..803c804b --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-basic.rs @@ -0,0 +1,45 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub mod foo { + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; +} +pub use self::foo::Type as foo_alias1; +pub use self::foo_alias1 as foo_alias2; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct bar { + pub this_should_work: foo::Type, +} +#[test] +fn bindgen_test_layout_bar() { + assert_eq!(::std::mem::size_of::<bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( bar ) )); + assert_eq! (::std::mem::align_of::<bar>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . this_should_work as * const _ + as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( this_should_work ) )); +} +impl Clone for bar { + fn clone(&self) -> Self { *self } +} +impl Default for bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +extern "C" { + pub fn func1(arg1: foo::Type, arg2: *mut foo::Type, + arg3: *mut *mut foo::Type) -> *mut foo::Type; +} +extern "C" { + pub fn func2(arg1: foo_alias1, arg2: *mut foo_alias1, + arg3: *mut *mut foo_alias1) -> *mut foo_alias1; +} diff --git a/tests/expectations/tests/constify-module-enums-namespace.rs b/tests/expectations/tests/constify-module-enums-namespace.rs new file mode 100644 index 00000000..4db009be --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-namespace.rs @@ -0,0 +1,52 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod ns1 { + #[allow(unused_imports)] + use self::super::super::root; + pub mod ns2 { + #[allow(unused_imports)] + use self::super::super::super::root; + pub mod foo { + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + } + } + pub mod ns3 { + #[allow(unused_imports)] + use self::super::super::super::root; + #[repr(C)] + #[derive(Debug, Copy)] + pub struct bar { + pub this_should_work: root::ns1::ns2::foo::Type, + } + #[test] + fn bindgen_test_layout_bar() { + assert_eq!(::std::mem::size_of::<bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( bar ) )); + assert_eq! (::std::mem::align_of::<bar>() , 4usize , concat ! + ( "Alignment of " , stringify ! ( bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . this_should_work as + * const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , + "::" , stringify ! ( this_should_work ) )); + } + impl Clone for bar { + fn clone(&self) -> Self { *self } + } + impl Default for bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } + } + } + } +} diff --git a/tests/expectations/tests/constify-module-enums-shadow-name.rs b/tests/expectations/tests/constify-module-enums-shadow-name.rs new file mode 100644 index 00000000..9b5fd7b8 --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-shadow-name.rs @@ -0,0 +1,36 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub mod foo { + pub type Type = ::std::os::raw::c_uint; + pub const Type: Type = 0; + pub const Type_: Type = 1; + pub const Type1: Type = 2; + pub const Type__: Type = 3; +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct bar { + pub member: foo::Type, +} +#[test] +fn bindgen_test_layout_bar() { + assert_eq!(::std::mem::size_of::<bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( bar ) )); + assert_eq! (::std::mem::align_of::<bar>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member ) )); +} +impl Clone for bar { + fn clone(&self) -> Self { *self } +} +impl Default for bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/constify-module-enums-simple-alias.rs b/tests/expectations/tests/constify-module-enums-simple-alias.rs new file mode 100644 index 00000000..709a6947 --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-simple-alias.rs @@ -0,0 +1,80 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub mod Foo { + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; + pub const Variant3: Type = 2; +} +pub use self::Foo::Type as Foo_alias1; +pub use self::Foo_alias1 as Foo_alias2; +pub use self::Foo_alias2 as Foo_alias3; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Bar { + pub baz1: Foo::Type, + pub baz2: Foo_alias1, + pub baz3: Foo_alias2, + pub baz4: Foo_alias3, + pub baz_ptr1: *mut Foo::Type, + pub baz_ptr2: *mut Foo_alias1, + pub baz_ptr3: *mut Foo_alias2, + pub baz_ptr4: *mut Foo_alias3, +} +#[test] +fn bindgen_test_layout_Bar() { + assert_eq!(::std::mem::size_of::<Bar>() , 48usize , concat ! ( + "Size of: " , stringify ! ( Bar ) )); + assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz1 as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz2 as * const _ as usize } , + 4usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz2 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz3 as * const _ as usize } , + 8usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz3 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz4 as * const _ as usize } , + 12usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz4 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz_ptr1 as * const _ as usize + } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz_ptr1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz_ptr2 as * const _ as usize + } , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz_ptr2 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz_ptr3 as * const _ as usize + } , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz_ptr3 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz_ptr4 as * const _ as usize + } , 40usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz_ptr4 ) )); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} +impl Default for Bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs b/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs new file mode 100644 index 00000000..4f8d46c5 --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-simple-nonamespace.rs @@ -0,0 +1,40 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub mod one_Foo { + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Bar { + pub baz1: one_Foo::Type, + pub baz2: *mut one_Foo::Type, +} +#[test] +fn bindgen_test_layout_Bar() { + assert_eq!(::std::mem::size_of::<Bar>() , 16usize , concat ! ( + "Size of: " , stringify ! ( Bar ) )); + assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz1 as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz2 as * const _ as usize } , + 8usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz2 ) )); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} +impl Default for Bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/constify-module-enums-types.rs b/tests/expectations/tests/constify-module-enums-types.rs new file mode 100644 index 00000000..4eb100c4 --- /dev/null +++ b/tests/expectations/tests/constify-module-enums-types.rs @@ -0,0 +1,193 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +pub mod foo { + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + pub const ALSO_THIS: Type = 42; + pub const AND_ALSO_THIS: Type = 42; +} +pub mod anon_enum { + pub type Type = ::std::os::raw::c_uint; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; + pub const Variant3: Type = 2; +} +pub mod ns1_foo { + pub type Type = ::std::os::raw::c_uint; + pub const THIS: Type = 0; + pub const SHOULD_BE: Type = 1; + pub const A_CONSTANT: Type = 2; + pub const ALSO_THIS: Type = 42; +} +pub mod ns2_Foo { + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +pub use self::foo::Type as foo_alias1; +pub use self::foo_alias1 as foo_alias2; +pub use self::foo_alias2 as foo_alias3; +pub use self::anon_enum::Type as anon_enum_alias1; +pub use self::anon_enum_alias1 as anon_enum_alias2; +pub use self::anon_enum_alias2 as anon_enum_alias3; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct bar { + pub member1: foo::Type, + pub member2: foo_alias1, + pub member3: foo_alias2, + pub member4: foo_alias3, + pub member5: ns1_foo::Type, + pub member6: *mut ns2_Foo::Type, + pub member7: anon_enum::Type, + pub member8: anon_enum_alias1, + pub member9: anon_enum_alias2, + pub member10: anon_enum_alias3, +} +#[test] +fn bindgen_test_layout_bar() { + assert_eq!(::std::mem::size_of::<bar>() , 48usize , concat ! ( + "Size of: " , stringify ! ( bar ) )); + assert_eq! (::std::mem::align_of::<bar>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member1 as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member1 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member2 as * const _ as usize } + , 4usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member2 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member3 as * const _ as usize } + , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member3 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member4 as * const _ as usize } + , 12usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member4 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member5 as * const _ as usize } + , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member5 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member6 as * const _ as usize } + , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member6 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member7 as * const _ as usize } + , 32usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member7 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member8 as * const _ as usize } + , 36usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member8 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member9 as * const _ as usize } + , 40usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member9 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const bar ) ) . member10 as * const _ as usize + } , 44usize , concat ! ( + "Alignment of field: " , stringify ! ( bar ) , "::" , + stringify ! ( member10 ) )); +} +impl Clone for bar { + fn clone(&self) -> Self { *self } +} +impl Default for bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Baz { + pub member1: ns2_Foo::Type, +} +#[test] +fn bindgen_test_layout_Baz() { + assert_eq!(::std::mem::size_of::<Baz>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Baz ) )); + assert_eq! (::std::mem::align_of::<Baz>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Baz ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Baz ) ) . member1 as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Baz ) , "::" , + stringify ! ( member1 ) )); +} +impl Clone for Baz { + fn clone(&self) -> Self { *self } +} +impl Default for Baz { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +pub mod one_Foo { + pub type Type = ::std::os::raw::c_int; + pub const Variant1: Type = 0; + pub const Variant2: Type = 1; +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Bar { + pub baz: *mut one_Foo::Type, +} +#[test] +fn bindgen_test_layout_Bar() { + assert_eq!(::std::mem::size_of::<Bar>() , 8usize , concat ! ( + "Size of: " , stringify ! ( Bar ) )); + assert_eq! (::std::mem::align_of::<Bar>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Bar ) ) . baz as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Bar ) , "::" , + stringify ! ( baz ) )); +} +impl Clone for Bar { + fn clone(&self) -> Self { *self } +} +impl Default for Bar { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +extern "C" { + #[link_name = "_Z5func13fooPS_PS0_"] + pub fn func1(arg1: foo::Type, arg2: *mut foo::Type, + arg3: *mut *mut foo::Type) -> *mut foo::Type; +} +extern "C" { + #[link_name = "_Z5func23fooPS_PS0_"] + pub fn func2(arg1: foo_alias1, arg2: *mut foo_alias1, + arg3: *mut *mut foo_alias1) -> *mut foo_alias1; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Thing<T> { + pub thing: T, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, +} +impl <T> Default for Thing<T> { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +extern "C" { + #[link_name = "_Z5func35ThingI3fooE"] + pub fn func3(arg1: Thing<foo::Type>) -> foo::Type; +} +extern "C" { + #[link_name = "_Z5func45ThingIS_I3fooEE"] + pub fn func4(arg1: Thing<Thing<foo::Type>>) -> foo::Type; +} diff --git a/tests/headers/constify-module-enums-basic.h b/tests/headers/constify-module-enums-basic.h new file mode 100644 index 00000000..631e8847 --- /dev/null +++ b/tests/headers/constify-module-enums-basic.h @@ -0,0 +1,17 @@ +// bindgen-flags: --constified-enum-module foo + +enum foo { + THIS, + SHOULD_BE, + A_CONSTANT, +}; + +typedef enum foo foo_alias1; +typedef foo_alias1 foo_alias2; + +struct bar { + enum foo this_should_work; +}; + +enum foo *func1(enum foo arg1, enum foo *arg2, enum foo **arg3); +foo_alias1 *func2(foo_alias1 arg1, foo_alias1 *arg2, foo_alias1 **arg3);
\ No newline at end of file diff --git a/tests/headers/constify-module-enums-namespace.hpp b/tests/headers/constify-module-enums-namespace.hpp new file mode 100644 index 00000000..397f700f --- /dev/null +++ b/tests/headers/constify-module-enums-namespace.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: --enable-cxx-namespaces --constified-enum-module foo + +namespace ns1 { + namespace ns2 { + enum foo { + THIS, + SHOULD_BE, + A_CONSTANT, + }; + } + + namespace ns3 { + struct bar { + enum ns2::foo this_should_work; + }; + } +}
\ No newline at end of file diff --git a/tests/headers/constify-module-enums-shadow-name.h b/tests/headers/constify-module-enums-shadow-name.h new file mode 100644 index 00000000..38b26106 --- /dev/null +++ b/tests/headers/constify-module-enums-shadow-name.h @@ -0,0 +1,12 @@ +// bindgen-flags: --constified-enum-module foo + +enum foo { + Type, + Type_, + Type1, + Type__, +}; + +struct bar { + enum foo member; +}; diff --git a/tests/headers/constify-module-enums-simple-alias.hpp b/tests/headers/constify-module-enums-simple-alias.hpp new file mode 100644 index 00000000..35ac4be3 --- /dev/null +++ b/tests/headers/constify-module-enums-simple-alias.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --constified-enum-module Foo + +enum class Foo { + Variant1, Variant2, Variant3, +}; + +typedef Foo Foo_alias1; +typedef Foo_alias1 Foo_alias2; +typedef Foo_alias2 Foo_alias3; + +class Bar { + Foo baz1; + Foo_alias1 baz2; + Foo_alias2 baz3; + Foo_alias3 baz4; + + Foo *baz_ptr1; + Foo_alias1 *baz_ptr2; + Foo_alias2 *baz_ptr3; + Foo_alias3 *baz_ptr4; +}; diff --git a/tests/headers/constify-module-enums-simple-nonamespace.hpp b/tests/headers/constify-module-enums-simple-nonamespace.hpp new file mode 100644 index 00000000..54631451 --- /dev/null +++ b/tests/headers/constify-module-enums-simple-nonamespace.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --constified-enum-module one_Foo + +namespace one { + enum class Foo { + Variant1, Variant2, + }; +} + +class Bar { + one::Foo baz1; + one::Foo* baz2; +}; diff --git a/tests/headers/constify-module-enums-types.hpp b/tests/headers/constify-module-enums-types.hpp new file mode 100644 index 00000000..2c652499 --- /dev/null +++ b/tests/headers/constify-module-enums-types.hpp @@ -0,0 +1,78 @@ +// bindgen-flags: --constified-enum-module .* + +typedef enum foo { + THIS, + SHOULD_BE, + A_CONSTANT, + ALSO_THIS = 42, + AND_ALSO_THIS = 42, +} foo; + + +typedef enum { + Variant1, Variant2, Variant3, +} anon_enum; + + +namespace ns1 { + typedef enum { + THIS, + SHOULD_BE, + A_CONSTANT, + ALSO_THIS = 42, + } foo; +} + +namespace ns2 { + enum class Foo { + Variant1, + Variant2, + }; +} + +typedef foo foo_alias1; +typedef foo_alias1 foo_alias2; +typedef foo_alias2 foo_alias3; + +typedef anon_enum anon_enum_alias1; +typedef anon_enum_alias1 anon_enum_alias2; +typedef anon_enum_alias2 anon_enum_alias3; + +typedef struct bar { + foo member1; + foo_alias1 member2; + foo_alias2 member3; + foo_alias3 member4; + ns1::foo member5; + ns2::Foo *member6; + anon_enum member7; + anon_enum_alias1 member8; + anon_enum_alias2 member9; + anon_enum_alias3 member10; +} bar; + +class Baz { + ns2::Foo member1; +}; + +namespace one { + enum class Foo { + Variant1, Variant2, + }; +} + +class Bar { + one::Foo* baz; +}; + +foo *func1(foo arg1, foo *arg2, foo **arg3); +foo_alias1 *func2(foo_alias1 arg1, foo_alias1 *arg2, foo_alias1 **arg3); + +template <class T> +class Thing { + T thing; + T& get_thing(); +}; + +foo func3(Thing<foo> arg1); +foo func4(Thing< Thing<foo> > arg1);
\ No newline at end of file |