summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poveda <christian.poveda@ferrous-systems.com>2022-10-06 14:52:29 -0500
committerChristian Poveda <christian.poveda@ferrous-systems.com>2022-10-06 14:52:29 -0500
commit4dd91ff6d72fb5df122e5957f31d1368e84d80a2 (patch)
tree1481911049423b9af30b28cf5acc48036d83c215
parent576fd8d424c8248726542b0951c594a9734cd02a (diff)
Make postprocessing more robust
This is done by merging extern blocks and sorting items in every module instead of just in the root module. The tests were changed to use `cxx` namespaces so they effectively check that items are manipulated correctly in every single module.
-rw-r--r--bindgen-tests/tests/expectations/tests/merge-extern-blocks.rs113
-rw-r--r--bindgen-tests/tests/expectations/tests/sort-items.rs220
-rw-r--r--bindgen-tests/tests/expectations/tests/sorted-items.rs82
-rw-r--r--bindgen-tests/tests/expectations/tests/sorted_items.rs220
-rw-r--r--bindgen-tests/tests/headers/merge-extern-blocks.h6
-rw-r--r--bindgen-tests/tests/headers/merge-extern-blocks.hpp14
-rw-r--r--bindgen-tests/tests/headers/sorted-items.h17
-rw-r--r--bindgen-tests/tests/headers/sorted_items.hpp35
-rw-r--r--bindgen/Cargo.toml2
-rw-r--r--bindgen/codegen/postprocessing/merge_extern_blocks.rs94
-rw-r--r--bindgen/codegen/postprocessing/mod.rs28
-rw-r--r--bindgen/codegen/postprocessing/sort_semantically.rs58
12 files changed, 681 insertions, 208 deletions
diff --git a/bindgen-tests/tests/expectations/tests/merge-extern-blocks.rs b/bindgen-tests/tests/expectations/tests/merge-extern-blocks.rs
index 66ceeff0..ae9799d2 100644
--- a/bindgen-tests/tests/expectations/tests/merge-extern-blocks.rs
+++ b/bindgen-tests/tests/expectations/tests/merge-extern-blocks.rs
@@ -5,33 +5,88 @@
non_upper_case_globals
)]
-#[repr(C)]
-#[derive(Debug, Default, Copy, Clone)]
-pub struct Point {
- pub x: ::std::os::raw::c_int,
-}
-#[test]
-fn bindgen_test_layout_Point() {
- const UNINIT: ::std::mem::MaybeUninit<Point> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<Point>(),
- 4usize,
- concat!("Size of: ", stringify!(Point))
- );
- assert_eq!(
- ::std::mem::align_of::<Point>(),
- 4usize,
- concat!("Alignment of ", stringify!(Point))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
- 0usize,
- concat!("Offset of field: ", stringify!(Point), "::", stringify!(x))
- );
-}
-extern "C" {
- pub fn foo() -> ::std::os::raw::c_int;
- pub fn bar() -> ::std::os::raw::c_int;
+#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
+pub mod root {
+ #[allow(unused_imports)]
+ use self::super::root;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: ::std::os::raw::c_int,
+ }
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 4usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ }
+ pub mod ns {
+ #[allow(unused_imports)]
+ use self::super::super::root;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: ::std::os::raw::c_int,
+ }
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 4usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ }
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3fooEv"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ #[link_name = "\u{1}_ZN2ns3barEv"]
+ pub fn bar() -> ::std::os::raw::c_int;
+ }
+ }
+ extern "C" {
+ #[link_name = "\u{1}_Z3foov"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ #[link_name = "\u{1}_Z3barv"]
+ pub fn bar() -> ::std::os::raw::c_int;
+ }
}
diff --git a/bindgen-tests/tests/expectations/tests/sort-items.rs b/bindgen-tests/tests/expectations/tests/sort-items.rs
new file mode 100644
index 00000000..e04e3b60
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/sort-items.rs
@@ -0,0 +1,220 @@
+#![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 {
+ pub type number = ::std::os::raw::c_int;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: root::number,
+ pub y: root::number,
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Angle {
+ pub a: root::number,
+ pub b: root::number,
+ }
+ pub const NUMBER: root::number = 42;
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(y)
+ )
+ );
+ }
+ #[test]
+ fn bindgen_test_layout_Angle() {
+ const UNINIT: ::std::mem::MaybeUninit<Angle> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Angle>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Angle))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Angle>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Angle))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(a)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(b)
+ )
+ );
+ }
+ pub mod ns {
+ pub type number = ::std::os::raw::c_int;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: root::ns::number,
+ pub y: root::ns::number,
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Angle {
+ pub a: root::ns::number,
+ pub b: root::ns::number,
+ }
+ pub const NUMBER: root::ns::number = 42;
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize
+ },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(y)
+ )
+ );
+ }
+ #[test]
+ fn bindgen_test_layout_Angle() {
+ const UNINIT: ::std::mem::MaybeUninit<Angle> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Angle>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Angle))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Angle>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Angle))
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(a)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize
+ },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(b)
+ )
+ );
+ }
+ #[allow(unused_imports)]
+ use self::super::super::root;
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3fooEv"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3barEi"]
+ pub fn bar(x: root::ns::number) -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3bazENS_5PointE"]
+ pub fn baz(point: root::ns::Point) -> ::std::os::raw::c_int;
+ }
+ }
+ #[allow(unused_imports)]
+ use self::super::root;
+ extern "C" {
+ #[link_name = "\u{1}_Z3foov"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_Z3bari"]
+ pub fn bar(x: root::number) -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_Z3baz5Point"]
+ pub fn baz(point: root::Point) -> ::std::os::raw::c_int;
+ }
+}
diff --git a/bindgen-tests/tests/expectations/tests/sorted-items.rs b/bindgen-tests/tests/expectations/tests/sorted-items.rs
deleted file mode 100644
index 7df7c3d7..00000000
--- a/bindgen-tests/tests/expectations/tests/sorted-items.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-#![allow(
- dead_code,
- non_snake_case,
- non_camel_case_types,
- non_upper_case_globals
-)]
-
-pub type number = ::std::os::raw::c_int;
-#[repr(C)]
-#[derive(Debug, Default, Copy, Clone)]
-pub struct Point {
- pub x: number,
- pub y: number,
-}
-#[repr(C)]
-#[derive(Debug, Default, Copy, Clone)]
-pub struct Angle {
- pub a: number,
- pub b: number,
-}
-pub const NUMBER: number = 42;
-#[test]
-fn bindgen_test_layout_Point() {
- const UNINIT: ::std::mem::MaybeUninit<Point> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<Point>(),
- 8usize,
- concat!("Size of: ", stringify!(Point))
- );
- assert_eq!(
- ::std::mem::align_of::<Point>(),
- 4usize,
- concat!("Alignment of ", stringify!(Point))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
- 0usize,
- concat!("Offset of field: ", stringify!(Point), "::", stringify!(x))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize },
- 4usize,
- concat!("Offset of field: ", stringify!(Point), "::", stringify!(y))
- );
-}
-#[test]
-fn bindgen_test_layout_Angle() {
- const UNINIT: ::std::mem::MaybeUninit<Angle> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<Angle>(),
- 8usize,
- concat!("Size of: ", stringify!(Angle))
- );
- assert_eq!(
- ::std::mem::align_of::<Angle>(),
- 4usize,
- concat!("Alignment of ", stringify!(Angle))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize },
- 0usize,
- concat!("Offset of field: ", stringify!(Angle), "::", stringify!(a))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize },
- 4usize,
- concat!("Offset of field: ", stringify!(Angle), "::", stringify!(b))
- );
-}
-extern "C" {
- pub fn foo() -> ::std::os::raw::c_int;
-}
-extern "C" {
- pub fn bar(x: number) -> ::std::os::raw::c_int;
-}
-extern "C" {
- pub fn baz(point: Point) -> ::std::os::raw::c_int;
-}
diff --git a/bindgen-tests/tests/expectations/tests/sorted_items.rs b/bindgen-tests/tests/expectations/tests/sorted_items.rs
new file mode 100644
index 00000000..e04e3b60
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/sorted_items.rs
@@ -0,0 +1,220 @@
+#![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 {
+ pub type number = ::std::os::raw::c_int;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: root::number,
+ pub y: root::number,
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Angle {
+ pub a: root::number,
+ pub b: root::number,
+ }
+ pub const NUMBER: root::number = 42;
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(y)
+ )
+ );
+ }
+ #[test]
+ fn bindgen_test_layout_Angle() {
+ const UNINIT: ::std::mem::MaybeUninit<Angle> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Angle>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Angle))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Angle>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Angle))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(a)
+ )
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(b)
+ )
+ );
+ }
+ pub mod ns {
+ pub type number = ::std::os::raw::c_int;
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Point {
+ pub x: root::ns::number,
+ pub y: root::ns::number,
+ }
+ #[repr(C)]
+ #[derive(Debug, Default, Copy, Clone)]
+ pub struct Angle {
+ pub a: root::ns::number,
+ pub b: root::ns::number,
+ }
+ pub const NUMBER: root::ns::number = 42;
+ #[test]
+ fn bindgen_test_layout_Point() {
+ const UNINIT: ::std::mem::MaybeUninit<Point> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Point>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Point))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Point>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Point))
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(x)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize
+ },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Point),
+ "::",
+ stringify!(y)
+ )
+ );
+ }
+ #[test]
+ fn bindgen_test_layout_Angle() {
+ const UNINIT: ::std::mem::MaybeUninit<Angle> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<Angle>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Angle))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Angle>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(Angle))
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize
+ },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(a)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ ::std::ptr::addr_of!((*ptr).b) as usize - ptr as usize
+ },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(Angle),
+ "::",
+ stringify!(b)
+ )
+ );
+ }
+ #[allow(unused_imports)]
+ use self::super::super::root;
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3fooEv"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3barEi"]
+ pub fn bar(x: root::ns::number) -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_ZN2ns3bazENS_5PointE"]
+ pub fn baz(point: root::ns::Point) -> ::std::os::raw::c_int;
+ }
+ }
+ #[allow(unused_imports)]
+ use self::super::root;
+ extern "C" {
+ #[link_name = "\u{1}_Z3foov"]
+ pub fn foo() -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_Z3bari"]
+ pub fn bar(x: root::number) -> ::std::os::raw::c_int;
+ }
+ extern "C" {
+ #[link_name = "\u{1}_Z3baz5Point"]
+ pub fn baz(point: root::Point) -> ::std::os::raw::c_int;
+ }
+}
diff --git a/bindgen-tests/tests/headers/merge-extern-blocks.h b/bindgen-tests/tests/headers/merge-extern-blocks.h
deleted file mode 100644
index 1d46b7d4..00000000
--- a/bindgen-tests/tests/headers/merge-extern-blocks.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// bindgen-flags: --merge-extern-blocks -- --target=x86_64-unknown-linux
-int foo();
-typedef struct Point {
- int x;
-} Point;
-int bar();
diff --git a/bindgen-tests/tests/headers/merge-extern-blocks.hpp b/bindgen-tests/tests/headers/merge-extern-blocks.hpp
new file mode 100644
index 00000000..392e34a3
--- /dev/null
+++ b/bindgen-tests/tests/headers/merge-extern-blocks.hpp
@@ -0,0 +1,14 @@
+// bindgen-flags: --merge-extern-blocks --enable-cxx-namespaces -- --target=x86_64-unknown-linux
+int foo();
+typedef struct Point {
+ int x;
+} Point;
+int bar();
+
+namespace ns {
+ int foo();
+ typedef struct Point {
+ int x;
+ } Point;
+ int bar();
+}
diff --git a/bindgen-tests/tests/headers/sorted-items.h b/bindgen-tests/tests/headers/sorted-items.h
deleted file mode 100644
index 11fc2ef4..00000000
--- a/bindgen-tests/tests/headers/sorted-items.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// bindgen-flags: --sort-semantically -- --target=x86_64-unknown-linux
-
-int foo();
-typedef int number;
-int bar(number x);
-struct Point
-{
- number x;
- number y;
-};
-struct Angle
-{
- number a;
- number b;
-};
-int baz(struct Point point);
-const number NUMBER = 42;
diff --git a/bindgen-tests/tests/headers/sorted_items.hpp b/bindgen-tests/tests/headers/sorted_items.hpp
new file mode 100644
index 00000000..9b5ced96
--- /dev/null
+++ b/bindgen-tests/tests/headers/sorted_items.hpp
@@ -0,0 +1,35 @@
+// bindgen-flags: --sort-semantically --enable-cxx-namespaces -- --target=x86_64-unknown-linux
+
+int foo();
+typedef int number;
+int bar(number x);
+struct Point
+{
+ number x;
+ number y;
+};
+struct Angle
+{
+ number a;
+ number b;
+};
+int baz(struct Point point);
+const number NUMBER = 42;
+
+namespace ns {
+ int foo();
+ typedef int number;
+ int bar(number x);
+ struct Point
+ {
+ number x;
+ number y;
+ };
+ struct Angle
+ {
+ number a;
+ number b;
+ };
+ int baz(struct Point point);
+ const number NUMBER = 42;
+}
diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml
index dca779bd..3965ad4d 100644
--- a/bindgen/Cargo.toml
+++ b/bindgen/Cargo.toml
@@ -45,7 +45,7 @@ lazycell = "1"
lazy_static = "1"
peeking_take_while = "0.1.2"
quote = { version = "1", default-features = false }
-syn = { version = "1.0.99", features = ["full", "extra-traits"]}
+syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
which = { version = "4.2.1", optional = true, default-features = false }
shlex = "1"
diff --git a/bindgen/codegen/postprocessing/merge_extern_blocks.rs b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
index 2b761494..05e7e9ef 100644
--- a/bindgen/codegen/postprocessing/merge_extern_blocks.rs
+++ b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
@@ -1,46 +1,66 @@
-use syn::{Item, ItemForeignMod};
+use syn::{
+ visit_mut::{visit_item_mod_mut, VisitMut},
+ Item, ItemForeignMod, ItemMod,
+};
-pub(super) fn merge_extern_blocks(items: &mut Vec<Item>) {
- // Keep all the extern blocks in a different `Vec` for faster search.
- let mut foreign_mods = Vec::<ItemForeignMod>::new();
+pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
+ Visitor.visit_item_mod_mut(item_mod)
+}
+
+struct Visitor;
- for item in std::mem::take(items) {
- match item {
- Item::ForeignMod(ItemForeignMod {
- attrs,
- abi,
- brace_token,
- items: foreign_items,
- }) => {
- let mut exists = false;
- for foreign_mod in &mut foreign_mods {
- // Check if there is a extern block with the same ABI and
- // attributes.
- if foreign_mod.attrs == attrs && foreign_mod.abi == abi {
- // Merge the items of the two blocks.
- foreign_mod.items.extend_from_slice(&foreign_items);
- exists = true;
- break;
+impl VisitMut for Visitor {
+ fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
+ if let Some((_, ref mut items)) = item_mod.content {
+ // Keep all the extern blocks in a different `Vec` for faster search.
+ let mut extern_blocks = Vec::<ItemForeignMod>::new();
+
+ for item in std::mem::take(items) {
+ if let Item::ForeignMod(ItemForeignMod {
+ attrs,
+ abi,
+ brace_token,
+ items: extern_block_items,
+ }) = item
+ {
+ let mut exists = false;
+ for extern_block in &mut extern_blocks {
+ // Check if there is a extern block with the same ABI and
+ // attributes.
+ if extern_block.attrs == attrs &&
+ extern_block.abi == abi
+ {
+ // Merge the items of the two blocks.
+ extern_block
+ .items
+ .extend_from_slice(&extern_block_items);
+ exists = true;
+ break;
+ }
}
+ // If no existing extern block had the same ABI and attributes, store
+ // it.
+ if !exists {
+ extern_blocks.push(ItemForeignMod {
+ attrs,
+ abi,
+ brace_token,
+ items: extern_block_items,
+ });
+ }
+ } else {
+ // If the item is not an extern block, we don't have to do anything and just
+ // push it back.
+ items.push(item);
}
- // If no existing extern block had the same ABI and attributes, store
- // it.
- if !exists {
- foreign_mods.push(ItemForeignMod {
- attrs,
- abi,
- brace_token,
- items: foreign_items,
- });
- }
}
- // If the item is not an extern block, we don't have to do anything.
- _ => items.push(item),
+
+ // Move all the extern blocks alongside the rest of the items.
+ for extern_block in extern_blocks {
+ items.push(Item::ForeignMod(extern_block));
+ }
}
- }
- // Move all the extern blocks alongside the rest of the items.
- for foreign_mod in foreign_mods {
- items.push(Item::ForeignMod(foreign_mod));
+ visit_item_mod_mut(self, item_mod)
}
}
diff --git a/bindgen/codegen/postprocessing/mod.rs b/bindgen/codegen/postprocessing/mod.rs
index c6612f2b..1d5a4983 100644
--- a/bindgen/codegen/postprocessing/mod.rs
+++ b/bindgen/codegen/postprocessing/mod.rs
@@ -1,6 +1,6 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
-use syn::Item;
+use syn::{parse2, ItemMod};
use crate::BindgenOptions;
@@ -12,7 +12,7 @@ use sort_semantically::sort_semantically;
struct PostProcessingPass {
should_run: fn(&BindgenOptions) -> bool,
- run: fn(&mut Vec<Item>),
+ run: fn(&mut ItemMod),
}
// TODO: This can be a const fn when mutable references are allowed in const
@@ -21,7 +21,7 @@ macro_rules! pass {
($pass:ident) => {
PostProcessingPass {
should_run: |options| options.$pass,
- run: |items| $pass(items),
+ run: |item_mod| $pass(item_mod),
}
};
}
@@ -38,29 +38,29 @@ pub(crate) fn postprocessing(
return items.into_iter().collect();
}
let module_wrapped_tokens =
- quote!(mod wrapper_for_sorting_hack { #( #items )* });
+ quote!(mod wrapper_for_postprocessing_hack { #( #items )* });
// This syn business is a hack, for now. This means that we are re-parsing already
// generated code using `syn` (as opposed to `quote`) because `syn` provides us more
// control over the elements.
// One caveat is that some of the items coming from `quote`d output might have
// multiple items within them. Hence, we have to wrap the incoming in a `mod`.
- // The two `unwrap`s here are deliberate because
- // The first one won't panic because we build the `mod` and know it is there
- // The second one won't panic because we know original output has something in
- // it already.
- let (_, mut items) = syn::parse2::<syn::ItemMod>(module_wrapped_tokens)
- .unwrap()
- .content
- .unwrap();
+ // The `unwrap` here is deliberate because bindgen should generate valid rust items at all
+ // times.
+ let mut item_mod = parse2::<ItemMod>(module_wrapped_tokens).unwrap();
for pass in PASSES {
if (pass.should_run)(options) {
- (pass.run)(&mut items);
+ (pass.run)(&mut item_mod);
}
}
- let synful_items = items.into_iter().map(|item| item.into_token_stream());
+ let synful_items = item_mod
+ .content
+ .map(|(_, items)| items)
+ .unwrap_or_default()
+ .into_iter()
+ .map(|item| item.into_token_stream());
quote! { #( #synful_items )* }
}
diff --git a/bindgen/codegen/postprocessing/sort_semantically.rs b/bindgen/codegen/postprocessing/sort_semantically.rs
index 96596cb0..4f23ab73 100644
--- a/bindgen/codegen/postprocessing/sort_semantically.rs
+++ b/bindgen/codegen/postprocessing/sort_semantically.rs
@@ -1,24 +1,38 @@
-use syn::Item;
+use syn::{
+ visit_mut::{visit_item_mod_mut, VisitMut},
+ Item, ItemMod,
+};
-pub(super) fn sort_semantically(items: &mut [Item]) {
- items.sort_by_key(|item| match item {
- Item::Type(_) => 0,
- Item::Struct(_) => 1,
- Item::Const(_) => 2,
- Item::Fn(_) => 3,
- Item::Enum(_) => 4,
- Item::Union(_) => 5,
- Item::Static(_) => 6,
- Item::Trait(_) => 7,
- Item::TraitAlias(_) => 8,
- Item::Impl(_) => 9,
- Item::Mod(_) => 10,
- Item::Use(_) => 11,
- Item::Verbatim(_) => 12,
- Item::ExternCrate(_) => 13,
- Item::ForeignMod(_) => 14,
- Item::Macro(_) => 15,
- Item::Macro2(_) => 16,
- _ => 18,
- });
+pub(super) fn sort_semantically(item_mod: &mut ItemMod) {
+ Visitor.visit_item_mod_mut(item_mod)
+}
+
+struct Visitor;
+
+impl VisitMut for Visitor {
+ fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
+ if let Some((_, ref mut items)) = item_mod.content {
+ items.sort_by_key(|item| match item {
+ Item::Type(_) => 0,
+ Item::Struct(_) => 1,
+ Item::Const(_) => 2,
+ Item::Fn(_) => 3,
+ Item::Enum(_) => 4,
+ Item::Union(_) => 5,
+ Item::Static(_) => 6,
+ Item::Trait(_) => 7,
+ Item::TraitAlias(_) => 8,
+ Item::Impl(_) => 9,
+ Item::Mod(_) => 10,
+ Item::Use(_) => 11,
+ Item::Verbatim(_) => 12,
+ Item::ExternCrate(_) => 13,
+ Item::ForeignMod(_) => 14,
+ Item::Macro(_) => 15,
+ Item::Macro2(_) => 16,
+ _ => 18,
+ });
+ }
+ visit_item_mod_mut(self, item_mod)
+ }
}