summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-04 17:55:47 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-04 17:55:47 +0200
commit0ea208b7e6ef54fa1f40efb7912d7040cf2e4fa9 (patch)
treee6d5ac219178ad3330bb2e12543fbe080a7db22f
parenteb64428b3efd78fcded7a299534da08785f3b7b4 (diff)
Wrap C++ `mutable` types in rust *Cells
-rw-r--r--src/clang.rs6
-rw-r--r--src/clangll.rs1
-rw-r--r--src/gen.rs22
-rw-r--r--src/parser.rs9
-rw-r--r--src/types.rs9
-rw-r--r--tests/expectations/mutable.rs43
-rw-r--r--tests/headers/mutable.hpp14
7 files changed, 97 insertions, 7 deletions
diff --git a/src/clang.rs b/src/clang.rs
index ed2ec3cd..b7d6b5c7 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -205,6 +205,12 @@ impl Cursor {
}
}
+ pub fn is_mutable_field(&self) -> bool {
+ unsafe {
+ clang_CXXField_isMutable(self.x) != 0
+ }
+ }
+
// CXX method
pub fn method_is_static(&self) -> bool {
unsafe {
diff --git a/src/clangll.rs b/src/clangll.rs
index 984f0aa5..dfd92cee 100644
--- a/src/clangll.rs
+++ b/src/clangll.rs
@@ -1235,6 +1235,7 @@ extern "C" {
pub fn clang_CXXMethod_isPureVirtual(C: CXCursor) -> c_uint;
pub fn clang_CXXMethod_isStatic(C: CXCursor) -> c_uint;
pub fn clang_CXXMethod_isVirtual(C: CXCursor) -> c_uint;
+ pub fn clang_CXXField_isMutable(C: CXCursor) -> c_uint;
pub fn clang_getTemplateCursorKind(C: CXCursor) -> Enum_CXCursorKind;
pub fn clang_getSpecializedCursorTemplate(C: CXCursor) -> CXCursor;
pub fn clang_getCursorReferenceNameRange(C: CXCursor,
diff --git a/src/gen.rs b/src/gen.rs
index 47133c43..ab1eaa6f 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -1049,7 +1049,25 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
}
}
- let f_ty = P(cty_to_rs(ctx, &f_ty, f.bitfields.is_none(), needs_full_path));
+ let rust_ty = P(cty_to_rs(ctx, &f_ty, f.bitfields.is_none(), needs_full_path));
+
+ // Wrap mutable fields in a Cell/UnsafeCell
+ let rust_ty = if f.mutable {
+ if !f_ty.can_derive_copy() {
+ quote_ty!(&ctx.ext_cx, ::std::cell::UnsafeCell<$rust_ty>)
+ // We can only wrap in a cell for non-copiable types, since
+ // Cell<T>: Clone, but not Copy.
+ //
+ // It's fine though, since mutating copiable types is trivial
+ // and doesn't make a lot of sense marking fields as `mutable`.
+ } else if !ci.can_derive_copy() {
+ quote_ty!(&ctx.ext_cx, ::std::cell::Cell<$rust_ty>)
+ } else {
+ rust_ty
+ }
+ } else {
+ rust_ty
+ };
fields.push(respan(ctx.span, ast::StructField_ {
kind: ast::NamedField(
@@ -1057,7 +1075,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
ast::Visibility::Public,
),
id: ast::DUMMY_NODE_ID,
- ty: f_ty,
+ ty: rust_ty,
attrs: mk_doc_attr(ctx, &f.comment)
}));
if bypass {
diff --git a/src/parser.rs b/src/parser.rs
index 32f46dff..774ebbbb 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -558,6 +558,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
}
let is_class_typedef = cursor.cur_type().sanitized_spelling_in(&ci.typedefs);
+ let mutable = cursor.is_mutable_field();
// NB: Overwritten in the case of non-integer bitfield
let mut ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef);
@@ -661,13 +662,13 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
};
if should_replace {
- *info = FieldInfo::new(name, ty, comment, bitfields);
+ *info = FieldInfo::new(name, ty, comment, bitfields, mutable);
return CXChildVisit_Continue;
}
}
}
- let field = FieldInfo::new(name, ty, comment, bitfields);
+ let field = FieldInfo::new(name, ty, comment, bitfields, mutable);
ci.members.push(CompMember::Field(field));
}
CXCursor_StructDecl |
@@ -700,7 +701,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
// Anonymous structs are legal in both C++ and C11
if ci2.borrow().was_unnamed {
let ci2b = ci2.borrow();
- let field = FieldInfo::new(ci2b.name.clone(), TComp(ci2.clone()), ci2b.comment.clone(), None);
+ let field = FieldInfo::new(ci2b.name.clone(), TComp(ci2.clone()), ci2b.comment.clone(), None, false);
ci.members.push(CompMember::Field(field));
}
});
@@ -758,7 +759,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
ci.typedefs.extend(info.borrow().typedefs.clone().into_iter());
}
- let field = FieldInfo::new(fieldname, ty, "".to_owned(), None);
+ let field = FieldInfo::new(fieldname, ty, "".to_owned(), None, false);
if !found_virtual_base && cursor.is_virtual_base() {
ci.members.insert(0, CompMember::Field(field));
ci.has_vtable = true;
diff --git a/src/types.rs b/src/types.rs
index cc335d41..c7b9e530 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -580,15 +580,22 @@ pub struct FieldInfo {
pub ty: Type,
pub comment: String,
pub bitfields: Option<Vec<(String, u32)>>,
+ /// If the C++ field is marked as `mutable`
+ pub mutable: bool,
}
impl FieldInfo {
- pub fn new(name: String, ty: Type, comment: String, bitfields: Option<Vec<(String, u32)>>) -> FieldInfo {
+ pub fn new(name: String,
+ ty: Type,
+ comment: String,
+ bitfields: Option<Vec<(String, u32)>>,
+ mutable: bool) -> FieldInfo {
FieldInfo {
name: name,
ty: ty,
comment: comment,
bitfields: bitfields,
+ mutable: mutable,
}
}
}
diff --git a/tests/expectations/mutable.rs b/tests/expectations/mutable.rs
new file mode 100644
index 00000000..62b4c524
--- /dev/null
+++ b/tests/expectations/mutable.rs
@@ -0,0 +1,43 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Struct_C {
+ pub m_member: ::std::os::raw::c_int,
+ pub m_other: ::std::os::raw::c_int,
+}
+impl ::std::clone::Clone for Struct_C {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_Struct_C() {
+ assert_eq!(::std::mem::size_of::<Struct_C>() , 8usize);
+ assert_eq!(::std::mem::align_of::<Struct_C>() , 4usize);
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_NonCopiable {
+ pub m_member: ::std::cell::Cell<::std::os::raw::c_int>,
+}
+#[test]
+fn bindgen_test_layout_Struct_NonCopiable() {
+ assert_eq!(::std::mem::size_of::<Struct_NonCopiable>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Struct_NonCopiable>() , 4usize);
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_NonCopiableWithNonCopiableMutableMember {
+ pub m_member: ::std::cell::UnsafeCell<Struct_NonCopiable>,
+}
+#[test]
+fn bindgen_test_layout_Struct_NonCopiableWithNonCopiableMutableMember() {
+ assert_eq!(::std::mem::size_of::<Struct_NonCopiableWithNonCopiableMutableMember>()
+ , 4usize);
+ assert_eq!(::std::mem::align_of::<Struct_NonCopiableWithNonCopiableMutableMember>()
+ , 4usize);
+}
diff --git a/tests/headers/mutable.hpp b/tests/headers/mutable.hpp
new file mode 100644
index 00000000..b61a1031
--- /dev/null
+++ b/tests/headers/mutable.hpp
@@ -0,0 +1,14 @@
+class C {
+ mutable int m_member;
+ int m_other;
+};
+
+class NonCopiable {
+ mutable int m_member;
+
+ ~NonCopiable() {};
+};
+
+class NonCopiableWithNonCopiableMutableMember {
+ mutable NonCopiable m_member;
+};