summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Finkenauer <tmfinken@gmail.com>2017-06-18 19:56:25 -0700
committerTravis Finkenauer <tmfinken@gmail.com>2017-06-18 19:56:25 -0700
commit4b10529701f89cc523c932bfe1a160864b3061ae (patch)
tree9674d5af5a8a37b8f54410f009f8d8d03e786998
parent5f4b73051ab7895e085e4a8e57fc87e7df0120f7 (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.rs60
-rw-r--r--tests/expectations/tests/constify-module-enums-simple-alias.rs80
-rw-r--r--tests/expectations/tests/constify-module-enums-simple-nonamespace.rs40
-rw-r--r--tests/expectations/tests/constify-module-enums-types.rs90
-rw-r--r--tests/headers/constify-module-enums-simple-alias.hpp21
-rw-r--r--tests/headers/constify-module-enums-simple-nonamespace.hpp12
-rw-r--r--tests/headers/constify-module-enums-types.hpp33
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