Skip to content

Commit 2deeabe

Browse files
committed
fix: C++ namespaces mangling
1 parent 25b321a commit 2deeabe

File tree

1 file changed

+22
-20
lines changed

1 file changed

+22
-20
lines changed

bindgen/codegen/mod.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ impl CodeGenerator for Var {
786786
&canonical_name,
787787
link_name,
788788
None,
789+
ctx.options().enable_cxx_namespaces,
789790
) {
790791
canonical_name.as_str()
791792
} else {
@@ -4657,6 +4658,7 @@ impl CodeGenerator for Function {
46574658
&canonical_name,
46584659
mangled_name,
46594660
Some(abi),
4661+
ctx.options().enable_cxx_namespaces,
46604662
))
46614663
.then(|| mangled_name)
46624664
});
@@ -5851,6 +5853,7 @@ pub(crate) mod utils {
58515853
canonical_name: &str,
58525854
mangled_name: &str,
58535855
call_conv: Option<ClangAbi>,
5856+
enable_cxx_namespaces: bool,
58545857
) -> bool {
58555858
// If the mangled name and the canonical name are the same then no
58565859
// mangling can have happened between the two versions.
@@ -5859,29 +5862,28 @@ pub(crate) mod utils {
58595862
}
58605863

58615864
// Check if the mangled name is a valid C++ symbol
5862-
if let Ok(demangled) = cpp_demangle::Symbol::new(mangled_name) {
5863-
let demangled_name = demangled.to_string().replace("::", "_");
5864-
5865-
// Check that the demangled name is longer than the canonical name
5866-
if demangled_name.len() <= canonical_name.len() {
5867-
return false;
5868-
}
5869-
5870-
// Check that the demangled name starts with the canonical name
5871-
if !demangled_name.starts_with(canonical_name) {
5872-
return false;
5873-
}
5865+
if let Ok(demangled) = ::cpp_demangle::Symbol::new(mangled_name) {
5866+
let demangled_name = match demangled.demangle(
5867+
&::cpp_demangle::DemangleOptions::default()
5868+
.no_params()
5869+
.no_return_type(),
5870+
) {
5871+
Ok(name) => name,
5872+
Err(_) => demangled.to_string(),
5873+
};
58745874

5875-
// Check that the suffix is a signature
5876-
if let Some(suffix) = demangled_name.get(canonical_name.len()..) {
5877-
if !suffix.starts_with('(') || !suffix.ends_with(')') {
5878-
return false;
5879-
}
5875+
// Either remove the namespace or replace "::" with "_" if cxx namespaces are enabled
5876+
let demangled_name = if enable_cxx_namespaces {
5877+
demangled_name
5878+
.rsplit_once("::")
5879+
.map(|(_, name)| name.to_string())
5880+
.unwrap_or(demangled_name)
58805881
} else {
5881-
return false;
5882-
}
5882+
demangled_name.replace("::", "_")
5883+
};
58835884

5884-
return true;
5885+
// Now that we processed the demangled name, we can compare it with the canonical name
5886+
return canonical_name == demangled_name;
58855887
}
58865888

58875889
// Working with &[u8] makes indexing simpler than with &str

0 commit comments

Comments
 (0)