From 4ff0c5288076ea626d533e6ce27ab61bc5db483d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Wed, 26 Feb 2025 18:57:06 +0100 Subject: [PATCH 01/11] perf: small optimization !iter.all => iter.any! --- bindgen/codegen/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index f5518e432d..ddd40d972e 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -5906,7 +5906,8 @@ pub(crate) mod utils { // Check that the suffix starts with '@' and is all ASCII decimals // after that. - if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit) + if suffix[0] != b'@' || + suffix[1..].iter().any(|&c| !c.is_ascii_digit()) { return false; } From e1a1eed0428cb72314f4a0165bcc533a5ba409aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Wed, 26 Feb 2025 19:58:57 +0100 Subject: [PATCH 02/11] test: add test for wrap-static-fns in C++ mode --- .../tests/generated/wrap_static_fns.cpp | 33 +++++++ .../tests/headers/wrap-static-fns.hpp | 90 +++++++++++++++++++ bindgen-tests/tests/tests.rs | 38 ++++++++ 3 files changed, 161 insertions(+) create mode 100644 bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp create mode 100644 bindgen-tests/tests/headers/wrap-static-fns.hpp diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp new file mode 100644 index 0000000000..357acc9187 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp @@ -0,0 +1,33 @@ +#include "tests/headers/wrap-static-fns.hpp" + +// Static wrappers + +int foo__extern(void) { return foo(); } +int bar__extern(void) { return bar(); } +int takes_ptr__extern(int *arg) { return takes_ptr(arg); } +int takes_fn_ptr__extern(int (*f) (int)) { return takes_fn_ptr(f); } +int takes_fn__extern(int (f) (int)) { return takes_fn(f); } +int takes_alias__extern(func f) { return takes_alias(f); } +int takes_qualified__extern(const int *const *arg) { return takes_qualified(arg); } +enum foo takes_enum__extern(const enum foo f) { return takes_enum(f); } +void nevermore__extern(void) { nevermore(); } +int takes_fn_with_no_args__extern(int (f) (void)) { return takes_fn_with_no_args(f); } +void no_extra_argument__extern(__builtin_va_list va) { no_extra_argument(va); } +int many_va_list__extern(int i, __builtin_va_list va1, __builtin_va_list va2) { return many_va_list(i, va1, va2); } +int wrap_as_variadic_fn1__extern(int i, ...) { + int ret; + va_list ap; + + va_start(ap, i); + ret = wrap_as_variadic_fn1(i, ap); + va_end(ap); + return ret; +} +void wrap_as_variadic_fn2__extern(int i, ...) { + va_list ap; + + va_start(ap, i); + wrap_as_variadic_fn2(i, ap); + va_end(ap); +} +int foo__extern(void) { return foo(); } diff --git a/bindgen-tests/tests/headers/wrap-static-fns.hpp b/bindgen-tests/tests/headers/wrap-static-fns.hpp new file mode 100644 index 0000000000..0aca49912c --- /dev/null +++ b/bindgen-tests/tests/headers/wrap-static-fns.hpp @@ -0,0 +1,90 @@ +// bindgen-flags: --wrap-static-fns +// bindgen-parse-callbacks: wrap-as-variadic-fn + +// to avoid polluting the expectation tests we put the stdarg.h behind a conditional +// variable only used in bindgen-integration +#ifdef USE_VA_HEADER +#include <stdarg.h> +#endif + +static inline int foo() { + return 11; +} +static int bar(); +static int bar() { + return 1; +} +inline int baz() { + return 2; +} + +static inline int takes_ptr(int* arg) { + return *arg + 1; +} + +static inline int takes_fn_ptr(int (*f)(int)) { + return f(1); +} + +static inline int takes_fn(int (f)(int)) { + return f(2); +} + +typedef int (func)(int); + +static inline int takes_alias(func f) { + return f(3); +} + +static inline int takes_qualified(const int *const *arg) { + return **arg; +} + +enum foo { + BAR = 0x0, +}; + +static inline enum foo takes_enum(const enum foo f) { + return f; +} + +static inline void nevermore() { + while (1) { } +} + +static inline int takes_fn_with_no_args(int(f)(void)) { + return f(); +} + +static inline int variadic(int x, ...) { + return x; +} + +static inline void no_extra_argument(__builtin_va_list va) {} + +static inline int many_va_list(int i, __builtin_va_list va1, __builtin_va_list va2) { + return i; +} + +#ifndef USE_VA_HEADER +static inline int wrap_as_variadic_fn1(int i, __builtin_va_list va) { + return i; +} + +static inline void wrap_as_variadic_fn2(int i, __builtin_va_list va) {} +#else +static inline int wrap_as_variadic_fn1(int i, va_list va) { + int res = 0; + + for (int j = 0; j < i; j++) + res += (int) va_arg(va, int); + + return res; +} + +static inline void wrap_as_variadic_fn2(int i, va_list va) {} +#endif + +namespace qux { + static int foo(); +} diff --git a/bindgen-tests/tests/tests.rs b/bindgen-tests/tests/tests.rs index b808dfcd43..ad888a77bb 100644 --- a/bindgen-tests/tests/tests.rs +++ b/bindgen-tests/tests/tests.rs @@ -757,3 +757,41 @@ fn test_wrap_static_fns() { .unwrap(); } } + +#[test] +fn test_wrap_static_fns_cpp() { + // This test is for testing diffs of the generated C source and header files + // TODO: If another such feature is added, convert this test into a more generic + // test that looks at `tests/headers/generated` directory. + let expect_path = PathBuf::from("tests/expectations/tests/generated") + .join("wrap_static_fns"); + println!("In path is ::: {}", expect_path.display()); + + let generated_path = + PathBuf::from(env::var("OUT_DIR").unwrap()).join("wrap_static_fns"); + println!("Out path is ::: {}", generated_path.display()); + + let _bindings = Builder::default() + .header("tests/headers/wrap-static-fns.hpp") + .wrap_static_fns(true) + .wrap_static_fns_path(generated_path.display().to_string()) + .parse_callbacks(Box::new(parse_callbacks::WrapAsVariadicFn)) + .generate() + .expect("Failed to generate bindings"); + + let expected_cpp = fs::read_to_string(expect_path.with_extension("cpp")) + .expect("Could not read generated wrap_static_fns.cpp"); + + let actual_cpp = fs::read_to_string(generated_path.with_extension("cpp")) + .expect("Could not read actual wrap_static_fns.cpp"); + + if expected_cpp != actual_cpp { + error_diff_mismatch( + &actual_cpp, + &expected_cpp, + None, + &expect_path.with_extension("cpp"), + ) + .unwrap(); + } +} From 25b321a96891dfd0cda22dc37e4a26b8b69fba8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Wed, 26 Feb 2025 20:00:00 +0100 Subject: [PATCH 03/11] fix: name mangling check for C++ --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + bindgen/Cargo.toml | 1 + bindgen/codegen/mod.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 4e88c224f5..f6c31cd4b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,6 +43,7 @@ dependencies = [ "clang-sys", "clap", "clap_complete", + "cpp_demangle", "itertools", "log", "prettyplease", @@ -187,6 +188,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "cpp_demangle" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +dependencies = [ + "cfg-if", +] + [[package]] name = "either" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index b0a5bbb082..05aef7656c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ cexpr = "0.6" clang-sys = "1" clap = "4" clap_complete = "4" +cpp_demangle = "0.4.4" env_logger = "0.10.0" itertools = { version = ">=0.10,<0.14", default-features = false } libloading = "0.8" diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml index c01f8f0c44..8ca55b5959 100644 --- a/bindgen/Cargo.toml +++ b/bindgen/Cargo.toml @@ -32,6 +32,7 @@ cexpr.workspace = true clang-sys = { workspace = true, features = ["clang_11_0"] } clap = { workspace = true, features = ["derive"], optional = true } clap_complete = { workspace = true, optional = true } +cpp_demangle.workspace = true itertools = { workspace = true } log = { workspace = true, optional = true } prettyplease = { workspace = true, optional = true, features = ["verbatim"] } diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index ddd40d972e..09c870495b 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -5858,6 +5858,32 @@ pub(crate) mod utils { return true; } + // Check if the mangled name is a valid C++ symbol + if let Ok(demangled) = cpp_demangle::Symbol::new(mangled_name) { + let demangled_name = demangled.to_string().replace("::", "_"); + + // Check that the demangled name is longer than the canonical name + if demangled_name.len() <= canonical_name.len() { + return false; + } + + // Check that the demangled name starts with the canonical name + if !demangled_name.starts_with(canonical_name) { + return false; + } + + // Check that the suffix is a signature + if let Some(suffix) = demangled_name.get(canonical_name.len()..) { + if !suffix.starts_with('(') || !suffix.ends_with(')') { + return false; + } + } else { + return false; + } + + return true; + } + // Working with &[u8] makes indexing simpler than with &str let canonical_name = canonical_name.as_bytes(); let mangled_name = mangled_name.as_bytes(); From 2deeabe2be3c3e742fbe1d69e0c268af52daad93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Wed, 26 Feb 2025 21:14:06 +0100 Subject: [PATCH 04/11] fix: C++ namespaces mangling --- bindgen/codegen/mod.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 09c870495b..10715aa8d4 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -786,6 +786,7 @@ impl CodeGenerator for Var { &canonical_name, link_name, None, + ctx.options().enable_cxx_namespaces, ) { canonical_name.as_str() } else { @@ -4657,6 +4658,7 @@ impl CodeGenerator for Function { &canonical_name, mangled_name, Some(abi), + ctx.options().enable_cxx_namespaces, )) .then(|| mangled_name) }); @@ -5851,6 +5853,7 @@ pub(crate) mod utils { canonical_name: &str, mangled_name: &str, call_conv: Option<ClangAbi>, + enable_cxx_namespaces: bool, ) -> bool { // If the mangled name and the canonical name are the same then no // mangling can have happened between the two versions. @@ -5859,29 +5862,28 @@ pub(crate) mod utils { } // Check if the mangled name is a valid C++ symbol - if let Ok(demangled) = cpp_demangle::Symbol::new(mangled_name) { - let demangled_name = demangled.to_string().replace("::", "_"); - - // Check that the demangled name is longer than the canonical name - if demangled_name.len() <= canonical_name.len() { - return false; - } - - // Check that the demangled name starts with the canonical name - if !demangled_name.starts_with(canonical_name) { - return false; - } + if let Ok(demangled) = ::cpp_demangle::Symbol::new(mangled_name) { + let demangled_name = match demangled.demangle( + &::cpp_demangle::DemangleOptions::default() + .no_params() + .no_return_type(), + ) { + Ok(name) => name, + Err(_) => demangled.to_string(), + }; - // Check that the suffix is a signature - if let Some(suffix) = demangled_name.get(canonical_name.len()..) { - if !suffix.starts_with('(') || !suffix.ends_with(')') { - return false; - } + // Either remove the namespace or replace "::" with "_" if cxx namespaces are enabled + let demangled_name = if enable_cxx_namespaces { + demangled_name + .rsplit_once("::") + .map(|(_, name)| name.to_string()) + .unwrap_or(demangled_name) } else { - return false; - } + demangled_name.replace("::", "_") + }; - return true; + // Now that we processed the demangled name, we can compare it with the canonical name + return canonical_name == demangled_name; } // Working with &[u8] makes indexing simpler than with &str From 720293e7bdf60c75dd5c9980e7b1555b6d1f9915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Wed, 26 Feb 2025 22:22:08 +0100 Subject: [PATCH 05/11] test: fix expected generated static fn in namespace --- .../tests/expectations/tests/generated/wrap_static_fns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp index 357acc9187..f3b35c97da 100644 --- a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp @@ -30,4 +30,4 @@ void wrap_as_variadic_fn2__extern(int i, ...) { wrap_as_variadic_fn2(i, ap); va_end(ap); } -int foo__extern(void) { return foo(); } +int qux_foo__extern(void) { return qux::foo(); } From d0b13447a26a7a6955e6952515ca5fd41c32ec01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Thu, 27 Feb 2025 13:00:29 +0100 Subject: [PATCH 06/11] fix: wrap static function serialization --- bindgen/codegen/serialize.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs index c7bb6cecef..84a4e00750 100644 --- a/bindgen/codegen/serialize.rs +++ b/bindgen/codegen/serialize.rs @@ -79,7 +79,16 @@ impl<'a> CSerialize<'a> for Function { assert!(!signature.is_variadic()); - let name = self.name(); + // Get the function name + namespace + let name = { + let path = item.path_for_allowlisting(ctx).clone(); + if path.get(0).is_some_and(|part| part == "root") { + &path[1..] + } else { + &path[..] + } + .join("::") + }; // Function arguments stored as `(name, type_id)` tuples. let args = { @@ -114,7 +123,11 @@ impl<'a> CSerialize<'a> for Function { }; // The name used for the wrapper self. - let wrap_name = format!("{name}{}", ctx.wrap_static_fns_suffix()); + let wrap_name = format!( + "{}{}", + item.canonical_name(ctx), + ctx.wrap_static_fns_suffix() + ); // The function's return type let (ret_item, ret_ty) = { From de9de851ef6acc1c1f110de50313f726fd0fa895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Thu, 27 Feb 2025 15:34:53 +0100 Subject: [PATCH 07/11] Revert "fix: C++ namespaces mangling" This reverts commit 2deeabe2be3c3e742fbe1d69e0c268af52daad93. --- bindgen/codegen/mod.rs | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 10715aa8d4..09c870495b 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -786,7 +786,6 @@ impl CodeGenerator for Var { &canonical_name, link_name, None, - ctx.options().enable_cxx_namespaces, ) { canonical_name.as_str() } else { @@ -4658,7 +4657,6 @@ impl CodeGenerator for Function { &canonical_name, mangled_name, Some(abi), - ctx.options().enable_cxx_namespaces, )) .then(|| mangled_name) }); @@ -5853,7 +5851,6 @@ pub(crate) mod utils { canonical_name: &str, mangled_name: &str, call_conv: Option<ClangAbi>, - enable_cxx_namespaces: bool, ) -> bool { // If the mangled name and the canonical name are the same then no // mangling can have happened between the two versions. @@ -5862,28 +5859,29 @@ pub(crate) mod utils { } // Check if the mangled name is a valid C++ symbol - if let Ok(demangled) = ::cpp_demangle::Symbol::new(mangled_name) { - let demangled_name = match demangled.demangle( - &::cpp_demangle::DemangleOptions::default() - .no_params() - .no_return_type(), - ) { - Ok(name) => name, - Err(_) => demangled.to_string(), - }; + if let Ok(demangled) = cpp_demangle::Symbol::new(mangled_name) { + let demangled_name = demangled.to_string().replace("::", "_"); - // Either remove the namespace or replace "::" with "_" if cxx namespaces are enabled - let demangled_name = if enable_cxx_namespaces { - demangled_name - .rsplit_once("::") - .map(|(_, name)| name.to_string()) - .unwrap_or(demangled_name) + // Check that the demangled name is longer than the canonical name + if demangled_name.len() <= canonical_name.len() { + return false; + } + + // Check that the demangled name starts with the canonical name + if !demangled_name.starts_with(canonical_name) { + return false; + } + + // Check that the suffix is a signature + if let Some(suffix) = demangled_name.get(canonical_name.len()..) { + if !suffix.starts_with('(') || !suffix.ends_with(')') { + return false; + } } else { - demangled_name.replace("::", "_") - }; + return false; + } - // Now that we processed the demangled name, we can compare it with the canonical name - return canonical_name == demangled_name; + return true; } // Working with &[u8] makes indexing simpler than with &str From 32e478100cbfda5d06162598fb3e942a1ecca74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Thu, 27 Feb 2025 15:34:58 +0100 Subject: [PATCH 08/11] Revert "fix: name mangling check for C++" This reverts commit 25b321a96891dfd0cda22dc37e4a26b8b69fba8b. --- Cargo.lock | 10 ---------- Cargo.toml | 1 - bindgen/Cargo.toml | 1 - bindgen/codegen/mod.rs | 26 -------------------------- 4 files changed, 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6c31cd4b1..4e88c224f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,6 @@ dependencies = [ "clang-sys", "clap", "clap_complete", - "cpp_demangle", "itertools", "log", "prettyplease", @@ -188,15 +187,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cpp_demangle" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" -dependencies = [ - "cfg-if", -] - [[package]] name = "either" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index 05aef7656c..b0a5bbb082 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ cexpr = "0.6" clang-sys = "1" clap = "4" clap_complete = "4" -cpp_demangle = "0.4.4" env_logger = "0.10.0" itertools = { version = ">=0.10,<0.14", default-features = false } libloading = "0.8" diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml index 8ca55b5959..c01f8f0c44 100644 --- a/bindgen/Cargo.toml +++ b/bindgen/Cargo.toml @@ -32,7 +32,6 @@ cexpr.workspace = true clang-sys = { workspace = true, features = ["clang_11_0"] } clap = { workspace = true, features = ["derive"], optional = true } clap_complete = { workspace = true, optional = true } -cpp_demangle.workspace = true itertools = { workspace = true } log = { workspace = true, optional = true } prettyplease = { workspace = true, optional = true, features = ["verbatim"] } diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 09c870495b..ddd40d972e 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -5858,32 +5858,6 @@ pub(crate) mod utils { return true; } - // Check if the mangled name is a valid C++ symbol - if let Ok(demangled) = cpp_demangle::Symbol::new(mangled_name) { - let demangled_name = demangled.to_string().replace("::", "_"); - - // Check that the demangled name is longer than the canonical name - if demangled_name.len() <= canonical_name.len() { - return false; - } - - // Check that the demangled name starts with the canonical name - if !demangled_name.starts_with(canonical_name) { - return false; - } - - // Check that the suffix is a signature - if let Some(suffix) = demangled_name.get(canonical_name.len()..) { - if !suffix.starts_with('(') || !suffix.ends_with(')') { - return false; - } - } else { - return false; - } - - return true; - } - // Working with &[u8] makes indexing simpler than with &str let canonical_name = canonical_name.as_bytes(); let mangled_name = mangled_name.as_bytes(); From 694441dd64c3dfb6106c33949605d376e5ccf3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Thu, 27 Feb 2025 15:38:34 +0100 Subject: [PATCH 09/11] fix: generate wrapped static functions for C++ --- bindgen/codegen/mod.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index ddd40d972e..00a0e84aa4 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -4677,7 +4677,7 @@ impl CodeGenerator for Function { let should_wrap = is_internal && ctx.options().wrap_static_fns && - link_name_attr.is_none(); + (link_name_attr.is_none() || utils::is_cpp(ctx)); if should_wrap { let name = canonical_name.clone() + ctx.wrap_static_fns_suffix(); @@ -5201,6 +5201,15 @@ pub(crate) mod utils { use std::path::PathBuf; use std::str::FromStr; + pub(super) fn is_cpp(context: &BindgenContext) -> bool { + args_are_cpp(&context.options().clang_args) || + context + .options() + .input_headers + .iter() + .any(|h| file_is_cpp(h)) + } + pub(super) fn serialize_items( result: &CodegenResult, context: &BindgenContext, @@ -5220,14 +5229,8 @@ pub(crate) mod utils { std::fs::create_dir_all(dir)?; } - let is_cpp = args_are_cpp(&context.options().clang_args) || - context - .options() - .input_headers - .iter() - .any(|h| file_is_cpp(h)); - - let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" }); + let source_path = + path.with_extension(if is_cpp(context) { "cpp" } else { "c" }); let mut code = Vec::new(); From df94b915463e9e48212d22e57b77ff503917fe09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Thu, 27 Feb 2025 15:40:00 +0100 Subject: [PATCH 10/11] Revert "perf: small optimization !iter.all => iter.any!" This reverts commit 4ff0c5288076ea626d533e6ce27ab61bc5db483d. --- bindgen/codegen/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 00a0e84aa4..b64a4b1a36 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -5909,8 +5909,7 @@ pub(crate) mod utils { // Check that the suffix starts with '@' and is all ASCII decimals // after that. - if suffix[0] != b'@' || - suffix[1..].iter().any(|&c| !c.is_ascii_digit()) + if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit) { return false; } From 9bb551f5ba4ae42e914d367d15a48bde4eb2bd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=20M=C3=A9lois?= <youn@melois.dev> Date: Fri, 28 Feb 2025 19:27:02 +0100 Subject: [PATCH 11/11] test: rename files with cxx --- ...static_fns.cpp => wrap_static_fns_cxx.cpp} | 2 +- .../expectations/tests/wrap-static-fns-cxx.rs | 95 +++++++++++++++++++ ...static-fns.hpp => wrap-static-fns-cxx.hpp} | 0 bindgen-tests/tests/tests.rs | 12 +-- 4 files changed, 102 insertions(+), 7 deletions(-) rename bindgen-tests/tests/expectations/tests/generated/{wrap_static_fns.cpp => wrap_static_fns_cxx.cpp} (96%) create mode 100644 bindgen-tests/tests/expectations/tests/wrap-static-fns-cxx.rs rename bindgen-tests/tests/headers/{wrap-static-fns.hpp => wrap-static-fns-cxx.hpp} (100%) diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_cxx.cpp similarity index 96% rename from bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp rename to bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_cxx.cpp index f3b35c97da..0526b9791c 100644 --- a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.cpp +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns_cxx.cpp @@ -1,4 +1,4 @@ -#include "tests/headers/wrap-static-fns.hpp" +#include "tests/headers/wrap-static-fns-cxx.hpp" // Static wrappers diff --git a/bindgen-tests/tests/expectations/tests/wrap-static-fns-cxx.rs b/bindgen-tests/tests/expectations/tests/wrap-static-fns-cxx.rs new file mode 100644 index 0000000000..d5054bcec0 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/wrap-static-fns-cxx.rs @@ -0,0 +1,95 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +unsafe extern "C" { + #[link_name = "\u{1}_ZL3foov"] + pub fn foo() -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL3barv"] + pub fn bar() -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL9takes_ptrPi"] + pub fn takes_ptr(arg: *mut ::std::os::raw::c_int) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL12takes_fn_ptrPFiiE"] + pub fn takes_fn_ptr( + f: ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, + >, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL8takes_fnPFiiE"] + pub fn takes_fn( + f: ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, + >, + ) -> ::std::os::raw::c_int; +} +pub type func = ::std::option::Option< + unsafe extern "C" fn(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int, +>; +unsafe extern "C" { + #[link_name = "\u{1}_ZL11takes_aliasPFiiE"] + pub fn takes_alias(f: func) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL15takes_qualifiedPKPKi"] + pub fn takes_qualified( + arg: *const *const ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +pub const foo_BAR: foo = 0; +pub type foo = ::std::os::raw::c_uint; +unsafe extern "C" { + #[link_name = "\u{1}_ZL10takes_enum3foo"] + pub fn takes_enum(f: foo) -> foo; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL9nevermorev"] + pub fn nevermore(); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL21takes_fn_with_no_argsPFivE"] + pub fn takes_fn_with_no_args( + f: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL17no_extra_argumentP13__va_list_tag"] + pub fn no_extra_argument(va: *mut __va_list_tag); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL12many_va_listiP13__va_list_tagS0_"] + pub fn many_va_list( + i: ::std::os::raw::c_int, + va1: *mut __va_list_tag, + va2: *mut __va_list_tag, + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL20wrap_as_variadic_fn1iP13__va_list_tag"] + pub fn wrap_as_variadic_fn1_wrapped( + i: ::std::os::raw::c_int, + ... + ) -> ::std::os::raw::c_int; +} +unsafe extern "C" { + #[link_name = "\u{1}_ZL20wrap_as_variadic_fn2iP13__va_list_tag"] + pub fn wrap_as_variadic_fn2_wrapped(i: ::std::os::raw::c_int, ...); +} +unsafe extern "C" { + #[link_name = "\u{1}_ZN3quxL3fooEv"] + pub fn qux_foo() -> ::std::os::raw::c_int; +} +pub type __builtin_va_list = [__va_list_tag; 1usize]; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __va_list_tag { + pub gp_offset: ::std::os::raw::c_uint, + pub fp_offset: ::std::os::raw::c_uint, + pub overflow_arg_area: *mut ::std::os::raw::c_void, + pub reg_save_area: *mut ::std::os::raw::c_void, + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/headers/wrap-static-fns.hpp b/bindgen-tests/tests/headers/wrap-static-fns-cxx.hpp similarity index 100% rename from bindgen-tests/tests/headers/wrap-static-fns.hpp rename to bindgen-tests/tests/headers/wrap-static-fns-cxx.hpp diff --git a/bindgen-tests/tests/tests.rs b/bindgen-tests/tests/tests.rs index ad888a77bb..69d5e9af38 100644 --- a/bindgen-tests/tests/tests.rs +++ b/bindgen-tests/tests/tests.rs @@ -759,20 +759,20 @@ fn test_wrap_static_fns() { } #[test] -fn test_wrap_static_fns_cpp() { +fn test_wrap_static_fns_cxx() { // This test is for testing diffs of the generated C source and header files // TODO: If another such feature is added, convert this test into a more generic // test that looks at `tests/headers/generated` directory. let expect_path = PathBuf::from("tests/expectations/tests/generated") - .join("wrap_static_fns"); + .join("wrap_static_fns_cxx"); println!("In path is ::: {}", expect_path.display()); let generated_path = - PathBuf::from(env::var("OUT_DIR").unwrap()).join("wrap_static_fns"); + PathBuf::from(env::var("OUT_DIR").unwrap()).join("wrap_static_fns_cxx"); println!("Out path is ::: {}", generated_path.display()); let _bindings = Builder::default() - .header("tests/headers/wrap-static-fns.hpp") + .header("tests/headers/wrap-static-fns-cxx.hpp") .wrap_static_fns(true) .wrap_static_fns_path(generated_path.display().to_string()) .parse_callbacks(Box::new(parse_callbacks::WrapAsVariadicFn)) @@ -780,10 +780,10 @@ fn test_wrap_static_fns_cpp() { .expect("Failed to generate bindings"); let expected_cpp = fs::read_to_string(expect_path.with_extension("cpp")) - .expect("Could not read generated wrap_static_fns.cpp"); + .expect("Could not read generated wrap_static_fns_cxx.cpp"); let actual_cpp = fs::read_to_string(generated_path.with_extension("cpp")) - .expect("Could not read actual wrap_static_fns.cpp"); + .expect("Could not read actual wrap_static_fns_cxx.cpp"); if expected_cpp != actual_cpp { error_diff_mismatch(