diff options
author | Travis Finkenauer <tmfinken@gmail.com> | 2017-06-18 19:56:25 -0700 |
---|---|---|
committer | Travis Finkenauer <tmfinken@gmail.com> | 2017-06-18 19:56:25 -0700 |
commit | 4b10529701f89cc523c932bfe1a160864b3061ae (patch) | |
tree | 9674d5af5a8a37b8f54410f009f8d8d03e786998 | |
parent | 5f4b73051ab7895e085e4a8e57fc87e7df0120f7 (diff) |
Fix recursive aliases to const module enum
Item::is_constified_enum_module() only returns true for the base type, not for
"layers" of aliases.
Added a "simple alias" test and added content to the types test.
-rw-r--r-- | src/ir/item.rs | 60 | ||||
-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 | 90 | ||||
-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 | 33 |
7 files changed, 312 insertions, 24 deletions
diff --git a/src/ir/item.rs b/src/ir/item.rs index d0ad9674..7d033210 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -830,6 +830,37 @@ impl Item { /// Returns whether the item is a constified module enum fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool { if let ItemKind::Type(ref type_) = self.kind { + // Do not count an "alias of an alias" as a constified module enum; + // otherwise, we will get: + // pub mod foo { + // pub type Type = ::std::os::raw::c_uint; + // ... + // } + // pub use foo::Type as foo_alias1; + // pub use foo_alias1::Type as foo_alias2; + // pub use foo_alias2::Type as foo_alias3; + // ... + // + // (We do not want the '::Type' appended to the alias types; only the base type) + if let TypeKind::Alias(inner_id) = *type_.kind() { + let inner_item = ctx.resolve_item(inner_id); + if let ItemKind::Type(ref inner_type) = *inner_item.kind() { + match *inner_type.kind() { + TypeKind::Alias(..) => { return false; } + TypeKind::ResolvedTypeRef(resolved_id) => { + // We need to handle: + // Alias -> ResolvedTypeRef -> Alias + let resolved_item = ctx.resolve_item(resolved_id); + if let ItemKind::Type(ref resolved_type) = *resolved_item.kind() { + if let TypeKind::Alias(..) = *resolved_type.kind() { + return false; + } + } + } + _ => (), + } + } + } if let Some(ref type_) = type_.safe_canonical_type(ctx) { if let TypeKind::Enum(ref enum_) = *type_.kind() { return enum_.is_constified_enum_module(ctx, self); @@ -1458,21 +1489,24 @@ impl ItemCanonicalPath for Item { ctx: &BindgenContext) -> Vec<String> { let mut path = self.canonical_path(ctx); - let is_constified_module_enum = self.is_constified_enum_module(ctx); - if ctx.options().enable_cxx_namespaces { - if is_constified_module_enum { - path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into()); - } - return path; - } - if is_constified_module_enum { - return vec![path.last().unwrap().clone(), - CONSTIFIED_ENUM_MODULE_REPR_NAME.into()]; - } + + // 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> { 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 index 6f5d1a83..db236d6f 100644 --- a/tests/expectations/tests/constify-module-enums-types.rs +++ b/tests/expectations/tests/constify-module-enums-types.rs @@ -12,25 +12,36 @@ pub mod foo { pub const ALSO_THIS: Type = 42; pub const AND_ALSO_THIS: Type = 42; } -#[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum ns1_foo2 { THIS = 0, SHOULD_BE = 1, A_CONSTANT = 2, ALSO_THIS = 42, } -pub use self::ns1_foo2 as ns1_foo; +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; #[repr(C)] #[derive(Debug, Copy)] pub struct bar { pub member1: foo::Type, pub member2: foo_alias1, pub member3: foo_alias2, - pub member4: ns1_foo, + pub member4: foo_alias3, + pub member5: ns1_foo::Type, + pub member6: *mut ns2_Foo::Type, } #[test] fn bindgen_test_layout_bar() { - assert_eq!(::std::mem::size_of::<bar>() , 16usize , concat ! ( + assert_eq!(::std::mem::size_of::<bar>() , 32usize , concat ! ( "Size of: " , stringify ! ( bar ) )); - assert_eq! (::std::mem::align_of::<bar>() , 4usize , concat ! ( + 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 } @@ -52,6 +63,16 @@ fn bindgen_test_layout_bar() { , 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 ) )); } impl Clone for bar { fn clone(&self) -> Self { *self } @@ -59,6 +80,57 @@ impl Clone for bar { 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, @@ -82,3 +154,7 @@ 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-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 index b49dc038..1618b269 100644 --- a/tests/headers/constify-module-enums-types.hpp +++ b/tests/headers/constify-module-enums-types.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: --constified-enum-module foo +// bindgen-flags: --constified-enum-module .* typedef enum foo { THIS, @@ -9,7 +9,7 @@ typedef enum foo { } foo; namespace ns1 { - typedef enum foo2 { + typedef enum { THIS, SHOULD_BE, A_CONSTANT, @@ -17,16 +17,40 @@ namespace ns1 { } foo; } +namespace ns2 { + enum class Foo { + Variant1, + Variant2, + }; +} + typedef foo foo_alias1; typedef foo_alias1 foo_alias2; +typedef foo_alias2 foo_alias3; typedef struct bar { foo member1; foo_alias1 member2; foo_alias2 member3; - ns1::foo member4; + foo_alias3 member4; + ns1::foo member5; + ns2::Foo *member6; } 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); @@ -36,4 +60,5 @@ class Thing { T& get_thing(); }; -foo func3(Thing<foo> arg1);
\ No newline at end of file +foo func3(Thing<foo> arg1); +foo func4(Thing< Thing<foo> > arg1);
\ No newline at end of file |