summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clang.rs7
-rw-r--r--src/ir/comp.rs13
-rw-r--r--src/ir/function.rs10
-rw-r--r--src/ir/var.rs2
-rw-r--r--src/lib.rs22
-rw-r--r--src/options.rs3
-rw-r--r--tests/expectations/tests/anon_struct_in_union.rs92
-rw-r--r--tests/headers/anon_struct_in_union.h7
8 files changed, 152 insertions, 4 deletions
diff --git a/src/clang.rs b/src/clang.rs
index a3919579..1a45eefa 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -1502,6 +1502,13 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
&specialized);
}
}
+
+ if let Some(parent) = c.fallible_semantic_parent() {
+ println!("");
+ print_cursor(depth,
+ String::from(prefix) + "semantic-parent.",
+ &parent);
+ }
}
fn print_type<S: AsRef<str>>(depth: isize, prefix: S, ty: &Type) {
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 492c1a98..b97879f7 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -625,8 +625,19 @@ impl CompInfo {
// StructDecl to note incomplete structs that hasn't been
// forward-declared before, see:
//
+ // Also, clang seems to scope struct definitions inside
+ // unions to the whole translation unit. Since those are
+ // anonymous, let's just assume that if the cursor we've
+ // found is a definition it's a valid inner type.
+ //
+ // Note that doing this could be always ok, but let's just
+ // keep the union check for now.
+ //
// https://github.com/servo/rust-bindgen/issues/482
- if cur.semantic_parent() != cursor {
+ let is_inner_struct = cur.semantic_parent() == cursor ||
+ (kind == CompKind::Union &&
+ cur.is_definition());
+ if !is_inner_struct {
return CXChildVisit_Continue;
}
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 2a13b9f0..5864bbf8 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -105,7 +105,13 @@ fn get_abi(cc: CXCallingConv) -> Option<abi::Abi> {
}
/// Get the mangled name for the cursor's referent.
-pub fn cursor_mangling(cursor: &clang::Cursor) -> Option<String> {
+pub fn cursor_mangling(ctx: &BindgenContext,
+ cursor: &clang::Cursor)
+ -> Option<String> {
+ if !ctx.options().enable_mangling {
+ return None;
+ }
+
// We early return here because libclang may crash in some case
// if we pass in a variable inside a partial specialized template.
// See servo/rust-bindgen#67, and servo/rust-bindgen#462.
@@ -318,7 +324,7 @@ impl ClangSubItemParser for Function {
let name = cursor.spelling();
assert!(!name.is_empty(), "Empty function name?");
- let mut mangled_name = cursor_mangling(&cursor);
+ let mut mangled_name = cursor_mangling(context, &cursor);
if mangled_name.as_ref() == Some(&name) {
mangled_name = None;
}
diff --git a/src/ir/var.rs b/src/ir/var.rs
index c6d7a1c5..7b610da4 100644
--- a/src/ir/var.rs
+++ b/src/ir/var.rs
@@ -256,7 +256,7 @@ impl ClangSubItemParser for Var {
.map(VarType::String)
};
- let mangling = cursor_mangling(&cursor);
+ let mangling = cursor_mangling(ctx, &cursor);
let var = Var::new(name, mangling, ty, value, is_const);
Ok(ParseResult::New(var, Some(cursor)))
diff --git a/src/lib.rs b/src/lib.rs
index 42363ebd..649be323 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -212,6 +212,18 @@ impl Builder {
self
}
+ /// Whether to use the clang-provided name mangling. This is true and
+ /// probably needed for C++ features.
+ ///
+ /// However, some old libclang versions seem to return incorrect results in
+ /// some cases for non-mangled functions, see [1], so we allow disabling it.
+ ///
+ /// [1]: https://github.com/servo/rust-bindgen/issues/528
+ pub fn trust_clang_mangling(mut self, doit: bool) -> Self {
+ self.options.enable_mangling = doit;
+ self
+ }
+
/// Generate a C/C++ file that includes the header and has dummy uses of
/// every type defined in the header.
pub fn dummy_uses<T: Into<String>>(mut self, dummy_uses: T) -> Builder {
@@ -572,6 +584,15 @@ pub struct BindgenOptions {
/// Intead of emitting 'use objc;' to files generated from objective c files,
/// generate '#[macro_use] extern crate objc;'
pub objc_extern_crate: bool,
+
+ /// Whether to use the clang-provided name mangling. This is true and
+ /// probably needed for C++ features.
+ ///
+ /// However, some old libclang versions seem to return incorrect results in
+ /// some cases for non-mangled functions, see [1], so we allow disabling it.
+ ///
+ /// [1]: https://github.com/servo/rust-bindgen/issues/528
+ pub enable_mangling: bool,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -626,6 +647,7 @@ impl Default for BindgenOptions {
generate_comments: true,
whitelist_recursively: true,
objc_extern_crate: false,
+ enable_mangling: true,
}
}
}
diff --git a/src/options.rs b/src/options.rs
index e54ee012..a62aa73d 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -60,6 +60,9 @@ pub fn builder_from_flags<I>
Arg::with_name("objc-extern-crate")
.long("objc-extern-crate")
.help("Use extern crate instead of use for objc"),
+ Arg::with_name("distrust-clang-mangling")
+ .long("distrust-clang-mangling")
+ .help("Do not trust the libclang-provided mangling"),
Arg::with_name("builtins")
.long("builtins")
.help("Output bindings for builtin definitions, e.g. \
diff --git a/tests/expectations/tests/anon_struct_in_union.rs b/tests/expectations/tests/anon_struct_in_union.rs
new file mode 100644
index 00000000..97a342cf
--- /dev/null
+++ b/tests/expectations/tests/anon_struct_in_union.rs
@@ -0,0 +1,92 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
+impl <T> __BindgenUnionField<T> {
+ #[inline]
+ pub fn new() -> Self { __BindgenUnionField(::std::marker::PhantomData) }
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T { ::std::mem::transmute(self) }
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T { ::std::mem::transmute(self) }
+}
+impl <T> ::std::default::Default for __BindgenUnionField<T> {
+ #[inline]
+ fn default() -> Self { Self::new() }
+}
+impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
+ #[inline]
+ fn clone(&self) -> Self { Self::new() }
+}
+impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
+impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ fmt.write_str("__BindgenUnionField")
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct s {
+ pub u: s__bindgen_ty_1,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct s__bindgen_ty_1 {
+ pub field: __BindgenUnionField<s__bindgen_ty_1_inner>,
+ pub bindgen_union_field: u32,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct s__bindgen_ty_1_inner {
+ pub b: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_s__bindgen_ty_1_inner() {
+ assert_eq!(::std::mem::size_of::<s__bindgen_ty_1_inner>() , 4usize ,
+ concat ! ( "Size of: " , stringify ! ( s__bindgen_ty_1_inner )
+ ));
+ assert_eq! (::std::mem::align_of::<s__bindgen_ty_1_inner>() , 4usize ,
+ concat ! (
+ "Alignment of " , stringify ! ( s__bindgen_ty_1_inner ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const s__bindgen_ty_1_inner ) ) . b as * const
+ _ as usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( s__bindgen_ty_1_inner )
+ , "::" , stringify ! ( b ) ));
+}
+impl Clone for s__bindgen_ty_1_inner {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_s__bindgen_ty_1() {
+ assert_eq!(::std::mem::size_of::<s__bindgen_ty_1>() , 4usize , concat ! (
+ "Size of: " , stringify ! ( s__bindgen_ty_1 ) ));
+ assert_eq! (::std::mem::align_of::<s__bindgen_ty_1>() , 4usize , concat !
+ ( "Alignment of " , stringify ! ( s__bindgen_ty_1 ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const s__bindgen_ty_1 ) ) . field as * const _
+ as usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( s__bindgen_ty_1 ) ,
+ "::" , stringify ! ( field ) ));
+}
+impl Clone for s__bindgen_ty_1 {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_s() {
+ assert_eq!(::std::mem::size_of::<s>() , 4usize , concat ! (
+ "Size of: " , stringify ! ( s ) ));
+ assert_eq! (::std::mem::align_of::<s>() , 4usize , concat ! (
+ "Alignment of " , stringify ! ( s ) ));
+ assert_eq! (unsafe { & ( * ( 0 as * const s ) ) . u as * const _ as usize
+ } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( s ) , "::" , stringify
+ ! ( u ) ));
+}
+impl Clone for s {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/headers/anon_struct_in_union.h b/tests/headers/anon_struct_in_union.h
new file mode 100644
index 00000000..880a8b54
--- /dev/null
+++ b/tests/headers/anon_struct_in_union.h
@@ -0,0 +1,7 @@
+struct s {
+ union {
+ struct inner {
+ int b;
+ } field;
+ } u;
+};