summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gen.rs16
-rw-r--r--tests/support.rs171
-rw-r--r--tests/test_builtins.rs8
-rw-r--r--tests/test_func.rs5
-rw-r--r--tests/test_struct.rs66
-rw-r--r--tests/test_union.rs27
6 files changed, 116 insertions, 177 deletions
diff --git a/src/gen.rs b/src/gen.rs
index 4d331c9e..0b2c7f5c 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -556,6 +556,8 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: String, members: Vec<CompMember>) -> Ve
vis: ast::Inherited,
span: ctx.span}));
}
+
+ items.push(mk_default_impl(ctx, name.as_slice()));
items.extend(extra.into_iter());
items
}
@@ -609,7 +611,7 @@ fn cunion_to_rs(ctx: &mut GenCtx, name: String, layout: Layout, members: Vec<Com
}),
empty_generics()
);
- let union_id = rust_type_id(ctx, name);
+ let union_id = rust_type_id(ctx, name.clone());
let union_attrs = vec!(mk_repr_attr(ctx), mk_deriving_copy_attr(ctx));
let union_def = mk_item(ctx, union_id, def, ast::Public, union_attrs);
@@ -625,6 +627,8 @@ fn cunion_to_rs(ctx: &mut GenCtx, name: String, layout: Layout, members: Vec<Com
union_def,
mk_item(ctx, "".to_string(), union_impl, ast::Inherited, Vec::new())
);
+
+ items.push(mk_default_impl(ctx, name.as_slice()));
items.extend(extra.into_iter());
items
}
@@ -729,6 +733,16 @@ fn gen_comp_methods(ctx: &mut GenCtx, data_field: &str, data_offset: uint,
methods
}
+// Implements std::default::Default using std::mem::zeroed.
+fn mk_default_impl(ctx: &GenCtx, ty_name: &str) -> P<ast::Item> {
+ let name_ident = ctx.ext_cx.ident_of(ty_name);
+ quote_item!(&ctx.ext_cx,
+ impl ::std::default::Default for $name_ident {
+ fn default() -> $name_ident { unsafe { ::std::mem::zeroed() } }
+ }
+ ).unwrap()
+}
+
fn mk_blob_field(ctx: &GenCtx, name: &str, layout: Layout) -> Spanned<ast::StructField_> {
let ty_name = match layout.align {
1 => "u8",
diff --git a/tests/support.rs b/tests/support.rs
index a9b6dc4d..d837786a 100644
--- a/tests/support.rs
+++ b/tests/support.rs
@@ -1,15 +1,15 @@
use bindgen;
use bindgen::{Logger, BindgenOptions};
+
use std::default::Default;
-use std::fmt;
-use syntax::ast;
-use syntax::print::pprust;
-use syntax::ptr::P;
+use syntax::ast;
use syntax::codemap;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::parse;
use syntax::parse::token;
+use syntax::print::pprust;
+use syntax::ptr::P;
struct TestLogger;
@@ -33,10 +33,13 @@ pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> {
pub fn test_bind_eq(filename: &str, f:|ext_cx: DummyExtCtxt| -> Vec<Option<P<ast::Item>>>) {
let ext_cx = mk_dummy_ext_ctxt();
- let items = normalize_attr_ids(generate_bindings(filename).unwrap());
- let quoted = normalize_attr_ids(f(ext_cx).into_iter().map(|x| x.unwrap()).collect());
- assert_eq!(PrettyItems { items: items },
- PrettyItems { items: quoted });
+ let items = generate_bindings(filename).unwrap();
+ let quoted =f(ext_cx).into_iter().map(|x| x.unwrap()).collect();
+
+ // The ast::Items themselves have insignificant (for our purposes)
+ // differences that make them difficult to compare directly. So, compare
+ // rendered versions, which is not beautiful, but should work.
+ assert_eq!(render_items(&quoted), render_items(&items));
}
macro_rules! assert_bind_eq {
@@ -48,6 +51,17 @@ macro_rules! assert_bind_eq {
}
}
+fn render_items(items: &Vec<P<ast::Item>>) -> String {
+ pprust::to_string(|s| {
+ let module = ast::Mod {
+ inner: DUMMY_SP,
+ view_items: Vec::new(),
+ items: items.clone(),
+ };
+ s.print_mod(&module, &[])
+ })
+}
+
pub struct DummyExtCtxt {
sess: parse::ParseSess,
}
@@ -77,144 +91,3 @@ impl DummyExtCtxt {
fn mk_dummy_ext_ctxt<'a>() -> DummyExtCtxt {
DummyExtCtxt { sess: parse::new_parse_sess() }
}
-
-#[deriving(PartialEq)]
-struct PrettyItems {
- pub items: Vec<P<ast::Item>>,
-}
-
-impl fmt::Show for PrettyItems {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let output = pprust::to_string(|s| {
- let module = ast::Mod {
- inner: DUMMY_SP,
- view_items: Vec::new(),
- items: self.items.clone(),
- };
- s.print_mod(&module, &[])
- });
- write!(f, "\n{}\n", output)
- }
-}
-
-// libsyntax uses a thread-local variable to create unique AttrId values during
-// parsing and quoting. normalize_attr_ids makes sure that all AttrId values
-// for the passed `items` start at zero and proceed upward. This is necessary
-// to correctly compare otherwise-identical ASTs.
-fn normalize_attr_ids(items: Vec<P<ast::Item>>) -> Vec<P<ast::Item>> {
- use std::mem;
- use syntax::visit::*;
-
- struct Vis<'a> {
- attr_id: uint,
- items: Vec<P<ast::Item>>,
- }
-
- impl<'a> Vis<'a> {
- // TODO: visit_crate? ast::visit::Visitor does not deal with them directly,
- // but concievably, it could eventually come up.
-
- fn rewrite_attrs(&mut self, attrs: Vec<ast::Attribute>) -> Vec<ast::Attribute> {
- attrs.into_iter().map(|mut attr| {
- attr.node.id = ast::AttrId(self.attr_id);
- self.attr_id += 1;
- attr
- }).collect()
- }
- }
-
- unsafe fn force_mutable<T>(x: &T) -> &mut T {
- mem::transmute(x)
- }
-
- macro_rules! rewrite_attrs {
- ($self_:ident, $item:expr) => {
- unsafe {
- let unsafe_item = force_mutable($item);
- let new_attrs = mem::replace(&mut unsafe_item.attrs, vec!());
- let new_attrs = $self_.rewrite_attrs(new_attrs);
- mem::replace(&mut unsafe_item.attrs, new_attrs);
- }
- }
- }
-
- impl<'a, 'v> Visitor<'v> for Vis<'a> {
- fn visit_item(&mut self, i: &ast::Item) {
- rewrite_attrs!(self, i);
-
- match i.node {
- ast::ItemImpl(_, _, _, _, ref impl_items) => {
- for impl_item in impl_items.iter() {
- match *impl_item {
- ast::ImplItem::MethodImplItem(_) => { }
- ast::ImplItem::TypeImplItem(ref typedef) => {
- rewrite_attrs!(self, typedef.deref());
- }
- }
- }
- }
- _ => { }
- }
-
- walk_item(self, i);
- }
-
- fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
- rewrite_attrs!(self, i);
- walk_foreign_item(self, i);
- }
-
- fn visit_fn(&mut self, fk: FnKind, fd: &ast::FnDecl, b: &ast::Block, s: Span, _: ast::NodeId) {
- match fk {
- FkItemFn(_, _, _, _) | FkFnBlock => { }
- FkMethod(_, _, method) => {
- rewrite_attrs!(self, method);
- }
- }
- walk_fn(self, fk, fd, b, s);
- }
-
- fn visit_arm(&mut self, a: &ast::Arm) {
- rewrite_attrs!(self, a);
- walk_arm(self, a);
- }
-
- fn visit_ty_method(&mut self, t: &ast::TypeMethod) {
- rewrite_attrs!(self, t);
- walk_ty_method(self, t);
- }
-
- fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
- rewrite_attrs!(self, &v.node);
- walk_variant(self, v, g);
- }
-
- fn visit_view_item(&mut self, i: &ast::ViewItem) {
- rewrite_attrs!(self, i);
- walk_view_item(self, i);
- }
-
- fn visit_struct_field(&mut self, s: &ast::StructField) {
- rewrite_attrs!(self, &s.node);
- walk_struct_field(self, s);
- }
-
- fn visit_trait_item(&mut self, t: &ast::TraitItem) {
- match *t {
- ast::TraitItem::RequiredMethod(_) |
- ast::TraitItem::ProvidedMethod(_) => { }
- ast::TraitItem::TypeTraitItem(ref assoc_ty) => {
- rewrite_attrs!(self, assoc_ty.deref());
- }
- }
- walk_trait_item(self, t);
- }
- }
-
- let mut visitor = Vis { attr_id: 0, items: vec!() };
- for item in items.into_iter() {
- visitor.visit_item(item.deref());
- visitor.items.push(item);
- }
- visitor.items
-}
diff --git a/tests/test_builtins.rs b/tests/test_builtins.rs
index 35cd573c..1df562c8 100644
--- a/tests/test_builtins.rs
+++ b/tests/test_builtins.rs
@@ -1,12 +1,6 @@
-#![feature(phase)]
-
-#[phase(plugin)]
-extern crate bindgen;
-
-extern crate libc;
-
#[test]
fn test_builtin_va_list() {
+ #[allow(dead_code, non_camel_case_types, raw_pointer_deriving)]
mod ffi { bindgen!("headers/builtin_va_list.h", emit_builtins = true); }
// Should test for more than compilation.
}
diff --git a/tests/test_func.rs b/tests/test_func.rs
index 83bc2696..8a0f2584 100644
--- a/tests/test_func.rs
+++ b/tests/test_func.rs
@@ -22,6 +22,11 @@ fn func_ptr_in_struct() {
extern "C" fn(x: ::libc::c_int,
y: ::libc::c_int) -> Enum_baz>,
}
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_Foo {
+ fn default() -> Struct_Foo { unsafe { ::std::mem::zeroed() } }
+ }
)
);
}
diff --git a/tests/test_struct.rs b/tests/test_struct.rs
index 2d30174c..c6f6836f 100644
--- a/tests/test_struct.rs
+++ b/tests/test_struct.rs
@@ -1,7 +1,9 @@
+use std::default::Default;
+
#[test]
fn with_anon_struct() {
mod ffi { bindgen!("headers/struct_with_anon_struct.h"); }
- let mut x = ffi::Struct_foo { bar: ffi::Struct_Unnamed1 { a: 0, b: 0 } };
+ let mut x: ffi::Struct_foo = Default::default();
x.bar.a = 1;
x.bar.b = 2;
@@ -13,10 +15,7 @@ fn with_anon_struct() {
#[test]
fn with_anon_struct_array() {
mod ffi { bindgen!("headers/struct_with_anon_struct_array.h"); }
- let mut x = ffi::Struct_foo { bar: [
- ffi::Struct_Unnamed1 { a: 0, b: 0 },
- ffi::Struct_Unnamed1 { a: 1, b: 1 } ]
- };
+ let mut x: ffi::Struct_foo = Default::default();
x.bar[1].a = 1;
x.bar[1].b = 2;
@@ -27,11 +26,13 @@ fn with_anon_struct_array() {
#[test]
fn with_anon_struct_pointer() {
+ #[allow(raw_pointer_deriving)]
mod ffi { bindgen!("headers/struct_with_anon_struct_pointer.h"); }
- let mut unnamed = box ffi::Struct_Unnamed1 { a: 0, b: 0 };
+ let mut x: ffi::Struct_foo = Default::default();
+ let mut unnamed: ffi::Struct_Unnamed1 = Default::default();
unsafe {
- let mut x = ffi::Struct_foo { bar: ::std::mem::transmute(unnamed) };
+ x.bar = &mut unnamed;
(*x.bar).a = 1;
(*x.bar).b = 2;
@@ -46,7 +47,7 @@ fn with_anon_struct_pointer() {
#[test]
fn with_anon_union() {
mod ffi { bindgen!("headers/struct_with_anon_union.h"); }
- let mut x = ffi::Struct_foo { bar: ffi::Union_Unnamed1 { _bindgen_data_: [0] } };
+ let mut x: ffi::Struct_foo = Default::default();
unsafe {
*x.bar.a() = 0x12345678;
@@ -58,7 +59,7 @@ fn with_anon_union() {
#[test]
fn with_anon_unnamed_struct() {
mod ffi { bindgen!("headers/struct_with_anon_unnamed_struct.h"); }
- let mut x = ffi::Struct_foo { _bindgen_data_1_: [0, 0] };
+ let mut x: ffi::Struct_foo = Default::default();
unsafe {
*x.a() = 0x12345678;
@@ -71,7 +72,7 @@ fn with_anon_unnamed_struct() {
#[test]
fn with_anon_unnamed_union() {
mod ffi { bindgen!("headers/struct_with_anon_unnamed_union.h"); }
- let mut x = ffi::Struct_foo { _bindgen_data_1_: [0] };
+ let mut x: ffi::Struct_foo = Default::default();
unsafe {
*x.a() = 0x12345678;
@@ -83,7 +84,7 @@ fn with_anon_unnamed_union() {
#[test]
fn with_nesting() {
mod ffi { bindgen!("headers/struct_with_nesting.h"); }
- let mut x = ffi::Struct_foo { a: 0, _bindgen_data_1_: [0] };
+ let mut x: ffi::Struct_foo = Default::default();
unsafe {
x.a = 0x12345678;
@@ -111,12 +112,23 @@ fn containing_fwd_decl_struct() {
}
),
quote_item!(cx,
+ impl ::std::default::Default for Struct_a {
+ fn default() -> Struct_a { unsafe { ::std::mem::zeroed() } }
+ }
+ ),
+ quote_item!(cx,
#[repr(C)]
#[deriving(Copy)]
pub struct Struct_b {
pub val_b: ::libc::c_int,
}
- ));
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_b {
+ fn default() -> Struct_b { unsafe { ::std::mem::zeroed() } }
+ }
+ )
+ );
}
#[test]
@@ -133,7 +145,13 @@ fn with_unnamed_bitfields() {
pub unnamed_field2: ::libc::c_ushort,
pub d: ::libc::c_ushort,
}
- ));
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_bitfield {
+ fn default() -> Struct_bitfield { unsafe { ::std::mem::zeroed() } }
+ }
+ )
+ );
}
#[test]
@@ -143,6 +161,24 @@ fn with_fwd_decl_struct() {
let a = ffi::Struct_a { b: 1 };
let c = ffi::Struct_c { d: 1 };
- a.b;
- c.d;
+ assert_eq!(a.b, 1);
+ assert_eq!(c.d, 1);
+}
+
+#[test]
+fn default_impl() {
+ mod ffi { bindgen!("headers/struct_with_nesting.h"); }
+
+ let mut x: ffi::Struct_foo = Default::default();
+
+ unsafe {
+ assert_eq!(x.a, 0);
+ assert_eq!(*x.b(), 0);
+ assert_eq!(*x.c1(), 0);
+ assert_eq!(*x.c2(), 0);
+ assert_eq!(*x.d1(), 0);
+ assert_eq!(*x.d2(), 0);
+ assert_eq!(*x.d3(), 0);
+ assert_eq!(*x.d4(), 0);
+ }
}
diff --git a/tests/test_union.rs b/tests/test_union.rs
index 33a3713d..15759e7f 100644
--- a/tests/test_union.rs
+++ b/tests/test_union.rs
@@ -1,9 +1,11 @@
+use std::default::Default;
+
#[test]
fn with_anon_struct() {
// XXX: Rustc thinks that the anonymous struct, bar, is unused.
#[allow(dead_code)]
mod ffi { bindgen!("headers/union_with_anon_struct.h"); }
- let mut x = ffi::Union_foo { _bindgen_data_: [0, 0] };
+ let mut x: ffi::Union_foo = Default::default();
unsafe {
(*x.bar()).a = 0x12345678;
@@ -17,7 +19,7 @@ fn with_anon_struct() {
#[test]
fn with_anon_union() {
mod ffi { bindgen!("headers/union_with_anon_union.h"); }
- let mut x = ffi::Union_foo { _bindgen_data_: [0] };
+ let mut x: ffi::Union_foo = Default::default();
unsafe {
*(*x.bar()).a() = 0x12345678;
@@ -30,7 +32,7 @@ fn with_anon_union() {
#[test]
fn with_anon_unnamed_struct() {
mod ffi { bindgen!("headers/union_with_anon_unnamed_struct.h"); }
- let mut x = ffi::Union_pixel { _bindgen_data_: [0] };
+ let mut x: ffi::Union_pixel = Default::default();
unsafe {
*x.r() = 0xca;
@@ -49,7 +51,7 @@ fn with_anon_unnamed_struct() {
#[test]
fn with_anon_unnamed_union() {
mod ffi { bindgen!("headers/union_with_anon_unnamed_union.h"); }
- let mut x = ffi::Union_foo { _bindgen_data_: [0] };
+ let mut x: ffi::Union_foo = Default::default();
unsafe {
*x.a() = 0x12345678;
@@ -63,7 +65,7 @@ fn with_anon_unnamed_union() {
#[test]
fn with_nesting() {
mod ffi { bindgen!("headers/union_with_nesting.h"); }
- let mut x = ffi::Union_foo { _bindgen_data_: [0] };
+ let mut x: ffi::Union_foo = Default::default();
unsafe {
*x.a() = 0x12345678;
@@ -75,3 +77,18 @@ fn with_nesting() {
assert_eq!(*x.c2(), 0x1234);
}
}
+
+#[test]
+fn default_impl() {
+ mod ffi { bindgen!("headers/Union_with_nesting.h"); }
+
+ let mut x: ffi::Union_foo = Default::default();
+
+ unsafe {
+ assert_eq!(*x.a(), 0);
+ assert_eq!(*x.b1(), 0);
+ assert_eq!(*x.b2(), 0);
+ assert_eq!(*x.c1(), 0);
+ assert_eq!(*x.c2(), 0);
+ }
+}