summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/clang.rs52
-rw-r--r--src/clangll.rs1
-rw-r--r--src/gen.rs373
-rw-r--r--src/lib.rs1
-rw-r--r--src/parser.rs351
-rw-r--r--src/types.rs62
-rw-r--r--tests/expectations/class.rs1
-rw-r--r--tests/expectations/class_static.rs21
-rw-r--r--tests/expectations/class_with_inner_struct.rs3
-rw-r--r--tests/expectations/enum.rs4
-rw-r--r--tests/expectations/enum_and_vtable_mangling.rs2
-rw-r--r--tests/expectations/enum_dupe.rs2
-rw-r--r--tests/expectations/enum_explicit_type.rs10
-rw-r--r--tests/expectations/enum_negative.rs2
-rw-r--r--tests/expectations/enum_packed.rs6
-rw-r--r--tests/expectations/func_ptr_in_struct.rs2
-rw-r--r--tests/expectations/inner_template_self.rs26
-rw-r--r--tests/expectations/jsval_layout_opaque.rs29
-rw-r--r--tests/expectations/mutable.rs43
-rw-r--r--tests/expectations/namespace.rs2
-rw-r--r--tests/expectations/no_copy.rs14
-rw-r--r--tests/expectations/nsStyleAutoArray.rs23
-rw-r--r--tests/expectations/only_bitfields.rs14
-rw-r--r--tests/expectations/opaque_typedef.rs17
-rw-r--r--tests/expectations/overflowed_enum.rs4
-rw-r--r--tests/expectations/struct_with_anon_union.rs1
-rw-r--r--tests/expectations/struct_with_anon_unnamed_union.rs1
-rw-r--r--tests/expectations/struct_with_bitfields.rs97
-rw-r--r--tests/expectations/struct_with_nesting.rs1
-rw-r--r--tests/expectations/template.rs75
-rw-r--r--tests/expectations/union_fields.rs1
-rw-r--r--tests/expectations/union_with_anon_struct.rs1
-rw-r--r--tests/expectations/union_with_anon_struct_bitfield.rs26
-rw-r--r--tests/expectations/union_with_anon_union.rs1
-rw-r--r--tests/expectations/union_with_anon_unnamed_struct.rs1
-rw-r--r--tests/expectations/union_with_anon_unnamed_union.rs1
-rw-r--r--tests/expectations/union_with_big_member.rs1
-rw-r--r--tests/expectations/union_with_nesting.rs1
-rw-r--r--tests/expectations/weird_bitfields.rs72
-rw-r--r--tests/headers/class_static.hpp7
-rw-r--r--tests/headers/inner_template_self.hpp10
-rw-r--r--tests/headers/mutable.hpp14
-rw-r--r--tests/headers/no_copy.hpp6
-rw-r--r--tests/headers/nsStyleAutoArray.hpp57
-rw-r--r--tests/headers/opaque_typedef.hpp17
-rw-r--r--tests/headers/template.hpp87
-rwxr-xr-xtests/tools/run-bindgen.py3
48 files changed, 1221 insertions, 327 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 9141ba6d..c3f31686 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ build = "build.rs"
clippy = { version = "*", optional = true }
log = "0.3.*"
libc = "0.2.*"
-syntex_syntax = "0.29.*"
+syntex_syntax = "0.32"
[features]
static = []
diff --git a/src/clang.rs b/src/clang.rs
index d60de336..9c46a94e 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -25,6 +25,12 @@ impl Cursor {
}
}
+ pub fn display_name(&self) -> String {
+ unsafe {
+ String_ { x: clang_getCursorDisplayName(self.x) }.to_string()
+ }
+ }
+
pub fn mangling(&self) -> String {
let mut mangling = unsafe {
String_ { x: clang_Cursor_getMangling(self.x) }.to_string()
@@ -37,6 +43,12 @@ impl Cursor {
mangling
}
+ pub fn lexical_parent(&self) -> Cursor {
+ unsafe {
+ Cursor { x: clang_getCursorLexicalParent(self.x) }
+ }
+ }
+
pub fn semantic_parent(&self) -> Cursor {
unsafe {
Cursor { x: clang_getCursorSemanticParent(self.x) }
@@ -203,6 +215,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 {
@@ -272,6 +290,30 @@ pub struct Type {
x: CXType
}
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum LayoutError {
+ Invalid,
+ Incomplete,
+ Dependent,
+ NotConstantSize,
+ InvalidFieldName,
+ Unknown,
+}
+
+impl ::std::convert::From<i32> for LayoutError {
+ fn from(val: i32) -> Self {
+ use self::LayoutError::*;
+ match val {
+ CXTypeLayoutError_Invalid => Invalid,
+ CXTypeLayoutError_Incomplete => Incomplete,
+ CXTypeLayoutError_Dependent => Dependent,
+ CXTypeLayoutError_NotConstantSize => NotConstantSize,
+ CXTypeLayoutError_InvalidFieldName => InvalidFieldName,
+ _ => Unknown,
+ }
+ }
+}
+
impl Type {
// common
pub fn kind(&self) -> Enum_CXTypeKind {
@@ -290,6 +332,7 @@ impl Type {
}
}
+
// XXX make it more consistent
//
// This is currently only used to detect typedefs,
@@ -319,6 +362,15 @@ impl Type {
}
}
+ pub fn fallible_size(&self) -> Result<usize, LayoutError> {
+ let val = unsafe { clang_Type_getSizeOf(self.x) };
+ if val < 0 {
+ Err(LayoutError::from(val as i32))
+ } else {
+ Ok(val as usize)
+ }
+ }
+
pub fn align(&self) -> usize {
unsafe {
let val = clang_Type_getAlignOf(self.x);
diff --git a/src/clangll.rs b/src/clangll.rs
index 4d2ae32d..4877ea70 100644
--- a/src/clangll.rs
+++ b/src/clangll.rs
@@ -1236,6 +1236,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 b819c516..7393ac43 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -1,18 +1,16 @@
use std;
-use std::cmp;
use std::cell::RefCell;
use std::vec::Vec;
use std::rc::Rc;
use std::collections::HashMap;
use syntax::abi::Abi;
use syntax::ast;
-use syntax::codemap::{Span, Spanned, respan, ExpnInfo, NameAndSpan, MacroBang};
+use syntax::codemap::{Span, respan, ExpnInfo, NameAndSpan, MacroBang};
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::quote::rt::ToTokens;
use syntax::feature_gate::Features;
-use syntax::owned_slice::OwnedSlice;
use syntax::parse;
use syntax::parse::token::{InternedString, intern};
use syntax::attr::mk_attr_id;
@@ -71,17 +69,17 @@ fn ref_eq<T>(thing: &T, other: &T) -> bool {
fn empty_generics() -> ast::Generics {
ast::Generics {
- lifetimes: Vec::new(),
- ty_params: OwnedSlice::empty(),
+ lifetimes: vec![],
+ ty_params: P::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
- predicates: Vec::new()
+ predicates: vec![]
}
}
}
fn rust_id(ctx: &mut GenCtx, name: &str) -> (String, bool) {
- let token = parse::token::Ident(ctx.ext_cx.ident_of(name), parse::token::Plain);
+ let token = parse::token::Ident(ctx.ext_cx.ident_of(name));
if token.is_any_keyword() || "bool" == name {
let mut s = name.to_owned();
s.push_str("_");
@@ -155,7 +153,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
self_kind: ast::SelfKind)
-> ast::ImplItem {
let fndecl;
- let mut args = vec!();
+ let mut args = vec![];
match self_kind {
ast::SelfKind::Static => (),
@@ -217,7 +215,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
};
let block = ast::Block {
- stmts: vec!(),
+ stmts: vec![],
expr: Some(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Call(
@@ -272,6 +270,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
vis: ast::Visibility::Public,
attrs: attrs,
node: ast::ImplItemKind::Method(sig, P(block)),
+ defaultness: ast::Defaultness::Final,
span: ctx.span
}
}
@@ -282,7 +281,7 @@ pub fn gen_mods(links: &[(String, LinkType)],
span: Span) -> Vec<P<ast::Item>> {
// Create a dummy ExtCtxt. We only need this for string interning and that uses TLS.
let mut features = Features::new();
- features.allow_quote = true;
+ features.quote = true;
let cfg = ExpansionConfig {
crate_name: "xxx".to_owned(),
features: Some(&features),
@@ -292,7 +291,7 @@ pub fn gen_mods(links: &[(String, LinkType)],
let sess = &parse::ParseSess::new();
let mut feature_gated_cfgs = vec![];
let mut ctx = GenCtx {
- ext_cx: base::ExtCtxt::new(sess, Vec::new(), cfg, &mut feature_gated_cfgs),
+ ext_cx: base::ExtCtxt::new(sess, vec![], cfg, &mut feature_gated_cfgs),
options: options,
span: span,
module_map: map,
@@ -385,10 +384,21 @@ fn gen_global(mut ctx: &mut GenCtx,
defs.extend(ctypedef_to_rs(&mut ctx, t).into_iter())
},
GCompDecl(ci) => {
- let c = ci.borrow().clone();
+ let mut c = ci.borrow().clone();
let name = comp_name(&ctx, c.kind, &c.name);
-
- defs.push(opaque_to_rs(&mut ctx, &name, c.layout));
+ // Use the reference template if any
+ while let Some(TComp(ref_template)) = c.ref_template.clone() {
+ if c.name != ref_template.borrow().name {
+ break;
+ }
+ c = ref_template.borrow().clone();
+ }
+ if !c.args.is_empty() &&
+ !c.args.iter().any(|a| a.name().map(|name| name.is_empty()).unwrap_or(true)) {
+ defs.extend(comp_to_rs(&mut ctx, &name, c).into_iter());
+ } else {
+ defs.push(opaque_to_rs(&mut ctx, &name, c.layout));
+ }
},
GComp(ci) => {
let c = ci.borrow().clone();
@@ -421,9 +431,9 @@ fn gen_globals(mut ctx: &mut GenCtx,
globs: &[Global]) -> Vec<P<ast::Item>> {
let uniq_globs = tag_dup_decl(globs);
- let mut fs = vec!();
- let mut vs = vec!();
- let mut gs = vec!();
+ let mut fs = vec![];
+ let mut vs = vec![];
+ let mut gs = vec![];
for g in uniq_globs.into_iter() {
match g {
GOther => {}
@@ -448,7 +458,7 @@ fn gen_globals(mut ctx: &mut GenCtx,
}
}
- let mut defs = vec!();
+ let mut defs = vec![];
gs = remove_redundant_decl(gs);
for mut g in gs.into_iter() {
@@ -566,7 +576,7 @@ fn mk_extern(ctx: &mut GenCtx, links: &[(String, LinkType)],
})
}).collect();
- let mut items = Vec::new();
+ let mut items = vec![];
items.extend(foreign_items.into_iter());
let ext = ast::ItemKind::ForeignMod(ast::ForeignMod {
abi: abi,
@@ -597,7 +607,7 @@ fn mk_impl(ctx: &mut GenCtx, ty: P<ast::Ty>,
P(ast::Item {
ident: ctx.ext_cx.ident_of(""),
- attrs: vec!(),
+ attrs: vec![],
id: ast::DUMMY_NODE_ID,
node: ext,
vis: ast::Visibility::Inherited,
@@ -704,7 +714,7 @@ fn tag_dup_decl(gs: &[Global]) -> Vec<Global> {
return vec![];
}
- let mut step: Vec<Global> = vec!();
+ let mut step: Vec<Global> = vec![];
step.push(gs[0].clone());
for (i, _gsi) in gs.iter().enumerate().skip(1) {
@@ -724,7 +734,7 @@ fn tag_dup_decl(gs: &[Global]) -> Vec<Global> {
}
let len = step.len();
- let mut res: Vec<Global> = vec!();
+ let mut res: Vec<Global> = vec![];
for i in 0..len {
let mut dup = false;
match &step[i] {
@@ -854,53 +864,46 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
let members = &ci.members;
let template_args = &ci.args;
let methodlist = &ci.methods;
- let mut fields = vec!();
- let mut methods = vec!();
+ let mut fields = vec![];
+ let mut methods = vec![];
// Nested composites may need to emit declarations and implementations as
// they are encountered. The declarations end up in 'extra' and are emitted
// after the current struct.
- let mut extra = vec!();
+ let mut extra = vec![];
let mut unnamed: u32 = 0;
let mut bitfields: u32 = 0;
if ci.has_non_type_template_params ||
template_args.iter().any(|f| f == &TVoid) {
- return vec!();
+ return vec![];
}
let id = rust_type_id(ctx, name);
let id_ty = P(mk_ty(ctx, false, &[id.clone()]));
if ci.has_vtable {
- let mut vffields = vec!();
- let base_vftable = if !members.is_empty() {
- if let CompMember::Field(ref fi) = members[0] {
- match fi.ty {
- TComp(ref ci2) => {
- let ci2 = ci2.borrow();
- if ci2.has_vtable {
- Some(format!("_vftable_{}", ci2.name))
- } else {
- None
- }
- },
- _ => None
+ let mut vffields = vec![];
+ let base_vftable = match members.get(0) {
+ Some(&CompMember::Field(FieldInfo { ty: TComp(ref ci2), .. })) => {
+ let ci2 = ci2.borrow();
+ if ci2.has_vtable {
+ Some(format!("_vftable_{}", ci2.name))
+ } else {
+ None
}
- } else {
- None
- }
- } else {
- None
+ },
+ _ => None,
};
if let Some(ref base) = base_vftable {
- let field = ast::StructField_ {
- kind: ast::NamedField(ctx.ext_cx.ident_of("_base"), ast::Visibility::Public),
+ vffields.push(ast::StructField {
+ span: ctx.span,
+ vis: ast::Visibility::Public,
+ ident: Some(ctx.ext_cx.ident_of("_base")),
id: ast::DUMMY_NODE_ID,
ty: P(mk_ty(ctx, false, &[base.clone()])),
- attrs: vec!(),
- };
- vffields.push(respan(ctx.span, field));
+ attrs: vec![],
+ });
}
for vm in ci.vmethods.iter() {
@@ -914,13 +917,14 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
let name = first(rust_id(ctx, &vm.name));
- let field = ast::StructField_ {
- kind: ast::NamedField(ctx.ext_cx.ident_of(&name), ast::Visibility::Public),
+ vffields.push(ast::StructField {
+ span: ctx.span,
+ vis: ast::Visibility::Public,
+ ident: Some(ctx.ext_cx.ident_of(&name)),
id: ast::DUMMY_NODE_ID,
ty: P(ty),
- attrs: vec!(),
- };
- vffields.push(respan(ctx.span, field));
+ attrs: vec![],
+ });
}
// FIXME: rustc actually generates tons of warnings
@@ -947,17 +951,19 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
if base_vftable.is_none() {
let vf_type = mk_ty(ctx, false, &[vf_name]);
- fields.push(respan(ctx.span, ast::StructField_ {
- kind: ast::NamedField(ctx.ext_cx.ident_of("_vftable"), ast::Visibility::Public),
+ fields.push(ast::StructField {
+ span: ctx.span,
+ ident: Some(ctx.ext_cx.ident_of("_vftable")),
+ vis: ast::Visibility::Public,
id: ast::DUMMY_NODE_ID,
ty: P(mk_ptrty(ctx, &vf_type, true)),
- attrs: Vec::new()
- }));
+ attrs: vec![]
+ });
}
}
let mut anon_enum_count = 0;
- let mut setters = vec!();
+ let mut setters = vec![];
let mut template_args_used = vec![false; template_args.len()];
for m in members.iter() {
@@ -987,7 +993,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
if let Some(f) = opt_f {
let f_name = match f.bitfields {
- Some(ref v) => {
+ Some(_) => {
bitfields += 1;
format!("_bitfield_{}", bitfields)
}
@@ -1011,7 +1017,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
let mut offset: u32 = 0;
if let Some(ref bitfields) = f.bitfields {
for &(ref bf_name, bf_size) in bitfields.iter() {
- setters.push(gen_bitfield_method(ctx, &f_name, bf_name, &f_ty, offset as usize, bf_size));
+ setters.extend(gen_bitfield_methods(ctx, &f_name, bf_name, &f_ty, offset as usize, bf_size).into_iter());
offset += bf_size;
}
setters.push(gen_fullbitfield_method(ctx, &f_name, &f_ty, bitfields))
@@ -1037,29 +1043,47 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
// If the member is not a template argument, it needs the full path.
let mut needs_full_path = true;
for (index, arg) in template_args.iter().enumerate() {
- let used = f_ty == *arg || match f_ty {
- TPtr(ref t, _, _, _) => **t == *arg,
- TArray(ref t, _, _) => **t == *arg,
- _ => false,
- };
+ let used = f_ty.signature_contains_type(arg);
+
if used {
template_args_used[index] = true;
- needs_full_path = false;
+ needs_full_path = *arg == f_ty || match f_ty {
+ TPtr(ref t, _, _, _) => **t != *arg,
+ TArray(ref t, _, _) => **t != *arg,
+ _ => true,
+ };
break;
}
}
- 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(
- ctx.ext_cx.ident_of(&f_name),
- ast::Visibility::Public,
- ),
+ fields.push(ast::StructField {
+ span: ctx.span,
+ ident: Some(ctx.ext_cx.ident_of(&f_name)),
+ vis: ast::Visibility::Public,
id: ast::DUMMY_NODE_ID,
- ty: f_ty,
+ ty: rust_ty,
attrs: mk_doc_attr(ctx, &f.comment)
- }));
+ });
if bypass {
continue;
}
@@ -1090,21 +1114,20 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
let f_name = format!("_phantom{}", phantom_count);
phantom_count += 1;
let inner_type = P(cty_to_rs(ctx, &arg, true, false));
- fields.push(respan(ctx.span, ast::StructField_ {
- kind: ast::NamedField(
- ctx.ext_cx.ident_of(&f_name),
- ast::Visibility::Public,
- ),
+ fields.push(ast::StructField {
+ span: ctx.span,
+ ident: Some(ctx.ext_cx.ident_of(&f_name)),
+ vis: ast::Visibility::Public,
id: ast::DUMMY_NODE_ID,
ty: quote_ty!(&ctx.ext_cx, ::std::marker::PhantomData<$inner_type>),
- attrs: vec!(),
- }));
+ attrs: vec![],
+ });
}
if !setters.is_empty() {
extra.push(P(ast::Item {
ident: ctx.ext_cx.ident_of(""),
- attrs: vec!(),
+ attrs: vec![],
id: ast::DUMMY_NODE_ID,
node: ast::ItemKind::Impl(
ast::Unsafety::Normal,
@@ -1125,30 +1148,17 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
} else {
ast::VariantData::Struct(fields, ast::DUMMY_NODE_ID)
};
- let ty_params = template_args.iter().map(|gt| {
- let name = match gt {
- &TNamed(ref ti) => {
- ctx.ext_cx.ident_of(&ti.borrow().name)
- },
- _ => ctx.ext_cx.ident_of("")
- };
- ast::TyParam {
- ident: name,
- id: ast::DUMMY_NODE_ID,
- bounds: OwnedSlice::empty(),
- default: None,
- span: ctx.span
- }
- }).collect();
+
+ let ty_params = mk_ty_params(ctx, &template_args);
let def = ast::ItemKind::Struct(
variant_data,
ast::Generics {
- lifetimes: vec!(),
- ty_params: OwnedSlice::from_vec(ty_params),
+ lifetimes: vec![],
+ ty_params: P::from_vec(ty_params),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
- predicates: vec!()
+ predicates: vec![]
}
}
);
@@ -1177,7 +1187,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
items.push(
P(ast::Item {
ident: ctx.ext_cx.ident_of(&name),
- attrs: vec!(),
+ attrs: vec![],
id: ast::DUMMY_NODE_ID,
node: impl_,
vis: ast::Visibility::Inherited,
@@ -1201,8 +1211,8 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
items.extend(extra.into_iter());
- let mut mangledlist = vec!();
- let mut unmangledlist = vec!();
+ let mut mangledlist = vec![];
+ let mut unmangledlist = vec![];
let mut unmangle_count: HashMap<String, isize> = HashMap::new();
for v in methodlist {
let v = v.clone();
@@ -1224,17 +1234,31 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
_ => unreachable!()
}
}
- if mangledlist.len() > 0 {
- items.push(mk_extern(ctx, &vec!(), mangledlist, Abi::C));
+ if !mangledlist.is_empty() {
+ items.push(mk_extern(ctx, &[], mangledlist, Abi::C));
items.push(mk_impl(ctx, id_ty, unmangledlist));
}
+
+ if !ci.vars.is_empty() && template_args.is_empty() {
+ let vars = ci.vars.into_iter().map(|v| {
+ let vi = v.varinfo();
+ let v = vi.borrow_mut();
+ let mut var_name = v.name.clone();
+ if !v.mangled.is_empty() {
+ var_name = format!("{}_consts_{}", name, v.name);
+ }
+ cvar_to_rs(ctx, var_name, v.mangled.clone(), &v.ty, v.is_const)
+ }).collect();
+
+ items.push(mk_extern(ctx, &[], vars, Abi::C));
+ }
items
}
fn opaque_to_rs(ctx: &mut GenCtx, name: &str, _layout: Layout) -> P<ast::Item> {
let def = ast::ItemKind::Enum(
ast::EnumDef {
- variants: vec!()
+ variants: vec![]
},
empty_generics()
);
@@ -1277,9 +1301,9 @@ fn cunion_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>>
// Nested composites may need to emit declarations and implementations as
// they are encountered. The declarations end up in 'extra' and are emitted
// after the current union.
- let mut extra = vec!();
+ let mut extra = vec![];
- fn mk_union_field(ctx: &GenCtx, name: &str, ty: ast::Ty) -> Spanned<ast::StructField_> {
+ fn mk_union_field(ctx: &GenCtx, name: &str, ty: ast::Ty) -> ast::StructField {
let field_ty = if !ctx.options.enable_cxx_namespaces ||
ctx.current_module_id == ROOT_MODULE_ID {
quote_ty!(&ctx.ext_cx, __BindgenUnionField<$ty>)
@@ -1287,15 +1311,14 @@ fn cunion_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>>
quote_ty!(&ctx.ext_cx, root::__BindgenUnionField<$ty>)
};
- respan(ctx.span, ast::StructField_ {
- kind: ast::NamedField(
- ctx.ext_cx.ident_of(name),
- ast::Visibility::Public,
- ),
+ ast::StructField {
+ span: ctx.span,
+ ident: Some(ctx.ext_cx.ident_of(name)),
+ vis: ast::Visibility::Public,
id: ast::DUMMY_NODE_ID,
ty: field_ty,
attrs: vec![],
- })
+ }
}
let mut fields = members.iter()
@@ -1356,7 +1379,7 @@ fn const_to_rs(ctx: &mut GenCtx, name: String, val: i64, val_ty: ast::Ty) -> P<a
let id = first(rust_id(ctx, &name));
P(ast::Item {
ident: ctx.ext_cx.ident_of(&id[..]),
- attrs: Vec::new(),
+ attrs: vec![],
id: ast::DUMMY_NODE_ID,
node: cst,
vis: ast::Visibility::Public,
@@ -1428,7 +1451,7 @@ fn cenum_to_rs(ctx: &mut GenCtx,
// Rust is not happy with univariant enums
// if items.len() < 2 {
- // return vec!();
+ // return vec![];
// }
//
let mut items = vec![];
@@ -1491,9 +1514,9 @@ fn cenum_to_rs(ctx: &mut GenCtx,
}));
attrs.push(if ctx.options.derive_debug {
- mk_deriving_attr(ctx, &["Debug", "Copy", "Clone"])
+ mk_deriving_attr(ctx, &["Debug", "Copy", "Clone", "Eq", "PartialEq", "Hash"])
} else {
- mk_deriving_attr(ctx, &["Copy", "Clone"])
+ mk_deriving_attr(ctx, &["Copy", "Clone", "Eq", "PartialEq", "Hash"])
});
items.push(P(ast::Item {
@@ -1548,7 +1571,7 @@ fn gen_comp_methods(ctx: &mut GenCtx, data_field: &str, data_offset: usize,
};
let mut offset = data_offset;
- let mut methods = vec!();
+ let mut methods = vec![];
for m in members.into_iter() {
let advance_by = match *m {
CompMember::Field(ref f) => {
@@ -1600,13 +1623,13 @@ fn type_for_bitfield_width(ctx: &mut GenCtx, width: u32, is_arg: bool) -> ast::T
mk_ty(ctx, false, &[input_type.to_owned()])
}
-fn gen_bitfield_method(ctx: &mut GenCtx, bindgen_name: &str,
- field_name: &str, field_type: &Type,
- offset: usize, width: u32) -> ast::ImplItem {
+fn gen_bitfield_methods(ctx: &mut GenCtx, bindgen_name: &str,
+ field_name: &str, field_type: &Type,
+ offset: usize, width: u32) -> Vec<ast::ImplItem> {
let input_type = type_for_bitfield_width(ctx, width, true);
- let width = width % (field_type.layout().unwrap().size as u32 * 8);
+ let width = width as usize;
- let field_type = cty_to_rs(ctx, &field_type, false, true);
+ let field_type = cty_to_rs(ctx, field_type, false, true);
let real_field_name = if field_name.is_empty() {
format!("at_offset_{}", offset)
@@ -1615,20 +1638,28 @@ fn gen_bitfield_method(ctx: &mut GenCtx, bindgen_name: &str,
};
- let setter_name = ctx.ext_cx.ident_of(&format!("set_{}", real_field_name));
let bindgen_ident = ctx.ext_cx.ident_of(bindgen_name);
+ let setter_name = ctx.ext_cx.ident_of(&format!("set_{}", real_field_name));
+ let getter_name = ctx.ext_cx.ident_of(&real_field_name);
+ let mask = ((1usize << width) - 1) << offset;
let item = quote_item!(&ctx.ext_cx,
impl X {
+ #[inline]
+ pub fn $getter_name(&self) -> $field_type {
+ (self.$bindgen_ident & ($mask as $field_type)) >> $offset
+ }
+
+ #[inline]
pub fn $setter_name(&mut self, val: $input_type) {
- self.$bindgen_ident &= !(((1 << $width as $field_type) - 1) << $offset);
- self.$bindgen_ident |= (val as $field_type) << $offset;
+ self.$bindgen_ident &= !($mask as $field_type);
+ self.$bindgen_ident |= (val as $field_type << $offset) & ($mask as $field_type);
}
}
).unwrap();
- match &item.node {
- &ast::ItemKind::Impl(_, _, _, _, _, ref items) => items[0].clone(),
+ match item.node {
+ ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
_ => unreachable!()
}
}
@@ -1636,7 +1667,7 @@ fn gen_bitfield_method(ctx: &mut GenCtx, bindgen_name: &str,
fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
bitfield_type: &Type, bitfields: &[(String, u32)]) -> ast::ImplItem {
let field_type = cty_to_rs(ctx, bitfield_type, false, true);
- let mut args = vec!();
+ let mut args = vec![];
let mut unnamed: usize = 0;
for &(ref name, width) in bitfields.iter() {
let ident = if name.is_empty() {
@@ -1712,13 +1743,14 @@ fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
id: ast::DUMMY_NODE_ID,
ident: ctx.ext_cx.ident_of(&format!("new{}", bindgen_name)),
vis: ast::Visibility::Public,
- attrs: vec!(),
+ attrs: vec![],
node: node,
span: ctx.span,
+ defaultness: ast::Defaultness::Final,
}
}
-fn mk_blob_field(ctx: &GenCtx, name: &str, layout: &Layout) -> Spanned<ast::StructField_> {
+fn mk_blob_field(ctx: &GenCtx, name: &str, layout: &Layout) -> ast::StructField {
let ty_name = match layout.align {
8 => "u64",
4 => "u32",
@@ -1733,15 +1765,14 @@ fn mk_blob_field(ctx: &GenCtx, name: &str, layout: &Layout) -> Spanned<ast::Stru
} else {
P(mk_arrty(ctx, &base_ty, data_len))
};
- respan(ctx.span, ast::StructField_ {
- kind: ast::NamedField(
- ctx.ext_cx.ident_of(name),
- ast::Visibility::Public,
- ),
+ ast::StructField {
+ span: ctx.span,
+ vis: ast::Visibility::Public,
+ ident: Some(ctx.ext_cx.ident_of(name)),
id: ast::DUMMY_NODE_ID,
ty: data_ty,
- attrs: Vec::new()
- })
+ attrs: vec![]
+ }
}
fn mk_link_name_attr(ctx: &mut GenCtx, name: String) -> ast::Attribute {
@@ -1812,7 +1843,7 @@ fn mk_deriving_attr(ctx: &GenCtx, attrs: &[&'static str]) -> ast::Attribute {
fn mk_doc_attr(ctx: &GenCtx, doc: &str) -> Vec<ast::Attribute> {
if doc.is_empty() {
- return vec!();
+ return vec![];
}
let attr_val = P(respan(ctx.span, ast::MetaItemKind::NameValue(
@@ -1833,7 +1864,7 @@ fn cvar_to_rs(ctx: &mut GenCtx, name: String,
is_const: bool) -> ast::ForeignItem {
let (rust_name, was_mangled) = rust_id(ctx, &name);
- let mut attrs = Vec::new();
+ let mut attrs = vec![];
if !mangled.is_empty() {
attrs.push(mk_link_name_attr(ctx, mangled));
} else if was_mangled {
@@ -2051,7 +2082,7 @@ fn cty_is_translatable(ty: &Type) -> bool {
}
fn mk_ty(ctx: &GenCtx, global: bool, segments: &[String]) -> ast::Ty {
- mk_ty_args(ctx, global, segments, vec!())
+ mk_ty_args(ctx, global, segments, vec![])
}
fn mk_ty_args(ctx: &GenCtx, global: bool, segments: &[String], args: Vec<P<ast::Ty>>) -> ast::Ty {
@@ -2065,9 +2096,9 @@ fn mk_ty_args(ctx: &GenCtx, global: bool, segments: &[String], args: Vec<P<ast::
ast::PathSegment {
identifier: ctx.ext_cx.ident_of(s),
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: vec!(),
- types: OwnedSlice::from_vec(if i == segment_count - 1 { args.clone() } else { vec![] }),
- bindings: OwnedSlice::empty(),
+ lifetimes: vec![],
+ types: if i == segment_count - 1 { P::from_vec(args.clone()) } else { P::new() },
+ bindings: P::new(),
}),
}
}).collect()
@@ -2137,7 +2168,7 @@ fn mk_fn_proto_ty(ctx: &mut GenCtx,
let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
unsafety: ast::Unsafety::Unsafe,
abi: abi,
- lifetimes: Vec::new(),
+ lifetimes: vec![],
decl: P(decl.clone())
}));
@@ -2152,7 +2183,7 @@ fn mk_fnty(ctx: &mut GenCtx, decl: &ast::FnDecl, abi: Abi) -> ast::Ty {
let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
unsafety: ast::Unsafety::Unsafe,
abi: abi,
- lifetimes: Vec::new(),
+ lifetimes: vec![],
decl: P(decl.clone())
}));
@@ -2160,31 +2191,31 @@ fn mk_fnty(ctx: &mut GenCtx, decl: &ast::FnDecl, abi: Abi) -> ast::Ty {
ast::PathSegment {
identifier: ctx.ext_cx.ident_of("std"),
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: OwnedSlice::empty(),
- bindings: OwnedSlice::empty(),
+ lifetimes: vec![],
+ types: P::new(),
+ bindings: P::new(),
}),
},
ast::PathSegment {
identifier: ctx.ext_cx.ident_of("option"),
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: OwnedSlice::empty(),
- bindings: OwnedSlice::empty(),
+ lifetimes: vec![],
+ types: P::new(),
+ bindings: P::new(),
}),
},
ast::PathSegment {
identifier: ctx.ext_cx.ident_of("Option"),
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: OwnedSlice::from_vec(vec!(
+ lifetimes: vec![],
+ types: P::from_vec(vec![
P(ast::Ty {
id: ast::DUMMY_NODE_ID,
node: fnty,
span: ctx.span
})
- )),
- bindings: OwnedSlice::empty(),
+ ]),
+ bindings: P::new(),
}),
}
];
@@ -2230,11 +2261,11 @@ fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> Vec<P<ast::Ite
let def = ast::ItemKind::Struct(
variant_data,
ast::Generics {
- lifetimes: vec!(),
- ty_params: OwnedSlice::empty(),
+ lifetimes: vec![],
+ ty_params: P::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
- predicates: vec!()
+ predicates: vec![]
}
}
);
@@ -2258,6 +2289,25 @@ fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> Vec<P<ast::Ite
ret
}
+/// Generates a vector of rust's ty params from a list of types
+fn mk_ty_params(ctx: &GenCtx, template_args: &[Type]) -> Vec<ast::TyParam> {
+ template_args.iter().map(|gt| {
+ let name = match *gt {
+ TNamed(ref ti) => {
+ ctx.ext_cx.ident_of(&ti.borrow().name)
+ },
+ _ => ctx.ext_cx.ident_of("")
+ };
+ ast::TyParam {
+ ident: name,
+ id: ast::DUMMY_NODE_ID,
+ bounds: P::new(),
+ default: None,
+ span: ctx.span
+ }
+ }).collect()
+}
+
fn gen_union_field_definitions_if_necessary(ctx: &mut GenCtx, mut root_mod: &mut ast::Item) {
if !ctx.saw_union {
return;
@@ -2265,6 +2315,7 @@ fn gen_union_field_definitions_if_necessary(ctx: &mut GenCtx, mut root_mod: &mut
let union_fields_decl = quote_item!(&ctx.ext_cx,
#[derive(Copy, Debug)]
+ #[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
).unwrap();
diff --git a/src/lib.rs b/src/lib.rs
index 0934a772..a42fa2ae 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
#![crate_name = "bindgen"]
#![crate_type = "dylib"]
#![feature(quote)]
+#![feature(borrow_state)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
diff --git a/src/parser.rs b/src/parser.rs
index be91d769..6b942b2a 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -37,6 +37,7 @@ struct ClangParserCtx<'a> {
builtin_defs: Vec<Cursor>,
module_map: ModuleMap,
current_module_id: ModuleId,
+ current_translation_unit: TranslationUnit,
logger: &'a (Logger+'a),
err_count: i32,
anonymous_modules_found: usize,
@@ -71,6 +72,13 @@ fn match_pattern(ctx: &mut ClangParserCtx, cursor: &Cursor) -> bool {
ctx.options.match_pat.iter().any(|pat| name.contains(pat))
}
+fn conv_template_type_parameter(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Type {
+ assert_eq!(cursor.kind(), CXCursor_TemplateTypeParameter);
+ let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
+ let layout = Layout::new(ty.size(), ty.align());
+ TNamed(Rc::new(RefCell::new(TypeInfo::new(cursor.spelling(), ctx.current_module_id, TVoid, layout))))
+}
+
fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
let cursor = cursor.canonical();
let override_enum_ty = ctx.options.override_enum_ty;
@@ -101,29 +109,35 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
let mut has_non_type_template_params = false;
- let args = match cursor.kind() {
- CXCursor_ClassDecl => {
- match ty.num_template_args() {
- -1 => vec![],
- len => {
- let mut list = Vec::with_capacity(len as usize);
- for i in 0..len {
- let arg_type = ty.template_arg_type(i);
- if arg_type.kind() != CXType_Invalid {
- list.push(conv_ty(ctx, &arg_type, &cursor));
- } else {
- has_non_type_template_params = true;
- ctx.logger.warn("warning: Template parameter is not a type");
- }
- }
- list
+ let args = match ty.num_template_args() {
+ // In forward declarations, etc, they are in the ast... sigh
+ -1 => {
+ let mut args = vec![];
+ cursor.visit(|c, _| {
+ if c.kind() == CXCursor_TemplateTypeParameter {
+ args.push(conv_template_type_parameter(ctx, c));
+ }
+ CXChildVisit_Continue
+ });
+ args
+ }
+ len => {
+ let mut list = Vec::with_capacity(len as usize);
+ for i in 0..len {
+ let arg_type = ty.template_arg_type(i);
+ if arg_type.kind() != CXType_Invalid {
+ list.push(conv_ty(ctx, &arg_type, &cursor));
+ } else {
+ has_non_type_template_params = true;
+ ctx.logger.warn("warning: Template parameter is not a type");
}
}
+ list
}
- _ => vec![],
};
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout);
+ ci.parser_cursor = Some(cursor);
// If it's an instantiation of another template,
// find the canonical declaration to find the module
@@ -172,8 +186,15 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
}
CXCursor_VarDecl => {
let mangled = cursor.mangling();
- let vi = Rc::new(RefCell::new(VarInfo::new(spelling, mangled, comment, TVoid)));
- GVar(vi)
+ let is_const = ty.is_const();
+ let ty = conv_ty_resolving_typedefs(ctx, &ty, &cursor, true);
+ let mut vi = VarInfo::new(spelling, mangled, comment, ty);
+ vi.is_const = is_const;
+ cursor.visit(|c, _: &Cursor| {
+ vi.val = visit_literal(c, &ctx.current_translation_unit);
+ CXChildVisit_Continue
+ });
+ GVar(Rc::new(RefCell::new(vi)))
}
CXCursor_MacroDefinition => {
let vi = Rc::new(RefCell::new(VarInfo::new(spelling, String::new(), comment, TVoid)));
@@ -201,13 +222,20 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
}
fn opaque_decl(ctx: &mut ClangParserCtx, decl: &Cursor) {
+ let spelling = decl.spelling();
+ let hide = ctx.options.blacklist_type.iter().any(|name| *name == spelling);
+
+ if hide {
+ return;
+ }
+
let name = decl_name(ctx, decl);
ctx.current_module_mut().globals.push(name);
}
-fn fwd_decl<F:FnOnce(&mut ClangParserCtx)->()>(ctx: &mut ClangParserCtx, cursor: &Cursor, f: F) {
- let def = &cursor.definition();
- if cursor == def {
+fn fwd_decl<F: FnOnce(&mut ClangParserCtx)->()>(ctx: &mut ClangParserCtx, cursor: &Cursor, f: F) {
+ let def = cursor.definition();
+ if cursor == &def {
f(ctx);
} else if def.kind() == CXCursor_NoDeclFound ||
def.kind() == CXCursor_InvalidFile {
@@ -316,12 +344,6 @@ fn mk_fn_sig_resolving_typedefs(ctx: &mut ClangParserCtx,
}
}
-fn conv_decl_ty(ctx: &mut ClangParserCtx,
- ty: &cx::Type,
- cursor: &Cursor) -> il::Type {
- conv_decl_ty_resolving_typedefs(ctx, ty, cursor, false)
-}
-
fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
ty: &cx::Type,
cursor: &Cursor,
@@ -358,20 +380,25 @@ fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
let ci = decl.compinfo();
// NB: Args might be filled from decl_name,
// it's important not to override
- if !args.is_empty() {
+ //
+ // We might incur in double borrows here. If that's the case, we're
+ // already scanning the compinfo, and we'd get the args from the
+ // ast.
+ use std::cell::BorrowState;
+ if !args.is_empty() && ci.borrow_state() == BorrowState::Unused {
ci.borrow_mut().args = args;
+
// XXX: This is a super-dumb way to get the spesialisation,
// but it seems to be the only one that'd work here...
cursor.visit(|c, _: &Cursor| {
if c.kind() == CXCursor_TemplateRef {
- let decl = decl_name(ctx, &c.referenced());
+ let decl = decl_name(ctx, &c.referenced());
ci.borrow_mut().ref_template = Some(decl.to_type());
}
CXChildVisit_Continue
});
}
-
TComp(ci)
}
CXCursor_EnumDecl => {
@@ -451,7 +478,9 @@ fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
CXType_Pointer => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, false, layout, resolve_typedefs),
CXType_LValueReference => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, true, layout, resolve_typedefs),
// XXX DependentSizedArray is wrong
- CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => {
+ CXType_VariableArray |
+ CXType_DependentSizedArray |
+ CXType_IncompleteArray => {
conv_ptr_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, false, layout, resolve_typedefs)
}
CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)),
@@ -488,6 +517,8 @@ struct Annotations {
opaque: bool,
hide: bool,
use_as: Option<String>,
+ /// Disable deriving copy/clone on this struct.
+ no_copy: bool,
}
impl Annotations {
@@ -496,6 +527,7 @@ impl Annotations {
opaque: false,
hide: false,
use_as: None,
+ no_copy: false,
};
anno.parse(&cursor.comment());
@@ -513,6 +545,7 @@ impl Annotations {
"opaque" => self.opaque = true,
"hide" => self.hide = true,
"replaces" => self.use_as = Some(comment.get_tag_attr_value(i)),
+ "nocopy" => self.no_copy = true,
_ => (),
}
}
@@ -530,6 +563,7 @@ impl Annotations {
fn visit_composite(cursor: &Cursor, parent: &Cursor,
ctx: &mut ClangParserCtx,
ci: &mut CompInfo) -> Enum_CXVisitorResult {
+ assert!(ci.parser_cursor.is_some());
fn is_bitfield_continuation(field: &il::FieldInfo, _ty: &il::Type, width: u32) -> bool {
match (&field.bitfields, field.ty.layout()) {
(&Some(ref bitfields), Some(layout)) => {
@@ -551,9 +585,86 @@ 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();
+
+ let cursor_ty = cursor.cur_type();
// NB: Overwritten in the case of non-integer bitfield
- let mut ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef);
+ let mut ty = conv_ty_resolving_typedefs(ctx,
+ &cursor_ty,
+ cursor,
+ is_class_typedef);
+
+
+ use std::cell::BorrowState;
+ if let Some(child_ci) = ty.get_outermost_composite() {
+ if let BorrowState::Unused = child_ci.borrow_state() {
+ let mut child_ci = child_ci.borrow_mut();
+ let child_cursor = child_ci.parser_cursor.unwrap();
+
+ // TODO: This is lame, ideally we should use cursors.
+ // The problem this loop is trying to solve is
+ // tests/headers/inner_template_self.hpp, and templates with
+ // incomplete types.
+ //
+ // The problem with this is that, in the first case (see the
+ // CXCursor_ClassDecl branch below) clang treats the *prev*
+ // field as a Class Declaration instead of a Class Template,
+ // so we have to check now for the name and the module id.
+ //
+ // Ideally, some method like `semantic_parent` or
+ // `lexical_parent` should return the reference to the
+ // class, but I've tried everything I could think about and
+ // failed miserably.
+ //
+ // Also, there could be more complex cases, like a templated
+ // type in an inner type declaration, that this is
+ // completely unable to catch.
+ //
+ // In the second case (the CXCursor_ClassTemplate branch),
+ // we're not able to retrieve the template parameters of an
+ // incomplete type via the declaration or anything like
+ // that. We can inspect the AST and deduct them though,
+ // since there's a leading CXCursor_TemplateRef.
+ if child_ci.args.is_empty() && child_cursor.kind() == CXCursor_ClassDecl {
+ // println!("child: {:?} {:?}, {:?}, {:?}", cursor.spelling(),
+ // type_to_str(cursor_ty.kind()),
+ // type_to_str(child_cursor.cur_type().kind()),
+ // kind_to_str(child_cursor.kind()));
+ if child_ci.name == ci.name &&
+ child_ci.module_id == ci.module_id {
+ child_ci.args = ci.args.clone();
+ }
+ }
+
+ if child_cursor.kind() == CXCursor_ClassTemplate {
+ // We need to take into account the possibly different
+ // type template names, so we need to clear them and
+ // re-scan.
+ child_ci.args.clear();
+ let mut found_invalid_template_ref = false;
+ cursor.visit(|c, _| {
+ // println!("ichild: {:?} {:?}, {:?}", c.spelling(),
+ // kind_to_str(c.kind()),
+ // type_to_str(c.cur_type().kind()));
+ if c.kind() == CXCursor_TemplateRef &&
+ c.cur_type().kind() == CXType_Invalid {
+ found_invalid_template_ref = true;
+ }
+ if found_invalid_template_ref &&
+ c.kind() == CXCursor_TypeRef {
+ child_ci.args.push(TNamed(Rc::new(RefCell::new(
+ TypeInfo::new(c.spelling(),
+ ctx.current_module_id,
+ TVoid,
+ Layout::zero())))));
+ }
+ CXChildVisit_Continue
+ })
+ }
+ }
+ }
+
let comment = cursor.raw_comment();
let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) {
@@ -570,11 +681,12 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
(Some(width), _) => {
// Bitfields containing enums are not supported by the c standard
// https://stackoverflow.com/questions/11983231/is-it-safe-to-use-an-enum-in-a-bit-field
+
match ty {
- il::TInt(_, _) => (),
+ il::TInt(..) => {},
_ => {
- // NOTE: We rely on the name of the type converted to rust types,
- // and on the alignment.
+ // NOTE: We rely on the name of the type converted
+ // to rust types, and on the alignment.
let bits = cmp::max(width, ty.size() as u32 * 8);
let layout_size = cmp::max(1, bits.next_power_of_two() / 8) as usize;
@@ -599,7 +711,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
ty = TNamed(Rc::new(RefCell::new(ti)))
}
}
- ("".to_owned(), Some(vec!((cursor.spelling(), width))))
+ ("".to_owned(), Some(vec![(cursor.spelling(), width)]))
},
// The field is not a bitfield
(None, _) => (cursor.spelling(), None)
@@ -654,13 +766,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 |
@@ -679,6 +791,13 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
let new_name = [&*ci.name, &*ci2.borrow().name].join("_").to_owned();
ci2.borrow_mut().name = new_name;
+ // This clear() is needed because of the speculation we do on
+ // incomplete types inside visit_composite() members.
+ //
+ // If this type ends up being complete, we're going to really
+ // parse them now, so we should reset them.
+ ci2.borrow_mut().args.clear();
+
// Propagate template arguments and typedefs to inner structs
ci2.borrow_mut().args.extend(ci.args.clone().into_iter());
ci2.borrow_mut().typedefs.extend(ci.typedefs.clone().into_iter());
@@ -693,7 +812,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));
}
});
@@ -702,9 +821,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
ci.layout.packed = true;
}
CXCursor_TemplateTypeParameter => {
- let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
- let layout = Layout::new(ty.size(), ty.align());
- ci.args.push(TNamed(Rc::new(RefCell::new(TypeInfo::new(cursor.spelling(), ctx.current_module_id, TVoid, layout)))));
+ ci.args.push(conv_template_type_parameter(ctx, cursor));
}
CXCursor_EnumDecl => {
let anno = Annotations::new(cursor);
@@ -751,7 +868,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;
@@ -872,13 +989,26 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
cursor.location()), false);
ci.has_non_type_template_params = true;
}
+ CXCursor_VarDecl => {
+ let linkage = cursor.linkage();
+ if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
+ return CXChildVisit_Continue;
+ }
+
+ let visibility = cursor.visibility();
+ if visibility != CXVisibility_Default {
+ return CXChildVisit_Continue;
+ }
+
+ let var = decl_name(ctx, cursor);
+ ci.vars.push(var);
+ }
// Intentionally not handled
CXCursor_CXXAccessSpecifier |
CXCursor_CXXFinalAttr |
CXCursor_Constructor |
CXCursor_FunctionTemplate |
- CXCursor_ConversionFunction |
- CXCursor_VarDecl => {}
+ CXCursor_ConversionFunction => {}
_ => {
// XXX: Some kind of warning would be nice, but this produces far
// too many.
@@ -935,8 +1065,7 @@ fn visit_literal(cursor: &Cursor, unit: &TranslationUnit) -> Option<i64> {
}
fn visit_top(cursor: &Cursor,
- mut ctx: &mut ClangParserCtx,
- unit: &TranslationUnit) -> Enum_CXVisitorResult {
+ mut ctx: &mut ClangParserCtx) -> Enum_CXVisitorResult {
if !match_pattern(ctx, cursor) {
return CXChildVisit_Continue;
}
@@ -953,6 +1082,9 @@ fn visit_top(cursor: &Cursor,
fwd_decl(ctx, cursor, move |ctx_| {
let decl = decl_name(ctx_, cursor);
let ci = decl.compinfo();
+ // This clear() is needed because of the speculation we do
+ // on incomplete types inside visit_composite() members.
+ ci.borrow_mut().args.clear();
cursor.visit(|c, p| {
let mut ci_ = ci.borrow_mut();
visit_composite(c, p, ctx_, &mut ci_)
@@ -966,9 +1098,76 @@ fn visit_top(cursor: &Cursor,
ci.borrow_mut().hide = true;
}
+ if anno.no_copy {
+ ci.borrow_mut().no_copy = true;
+ }
+
+ // If we find a previous translation, we take it now and carry
+ // on.
+ //
+ // XXX: This clone is spurious and could be avoided with another
+ // scope I think.
+ let name = ci.borrow().name.clone();
+ if let Some(translation) = ctx_.current_module_mut().translations.remove(&name) {
+ println!("*** {}: found previous translation", name);
+ if let GComp(ref translated) = translation {
+ *ci.borrow_mut() = translated.borrow().clone();
+ }
+ }
+
if let Some(other_type_name) = anno.use_as {
ci.borrow_mut().name = other_type_name.clone();
- ctx_.current_module_mut().translations.insert(other_type_name, GComp(ci));
+ // if the translated type already existed, and we can
+ // replace it, just do it (tm).
+ //
+ // We'll still need the translations map for not found
+ // translations and stuff like that.
+ //
+ // This is a linear search, which is crap, but fwiw it's not
+ // too common (just when a type marked as translation is
+ // found).
+ //
+ // NB: We have to also loop through the `name` map to take
+ // declarations in files that haven't been matched into
+ // account (since they won't appear in globals).
+ let mut found_in_globals = false;
+ for v in ctx_.current_module_mut().globals.iter_mut() {
+ match *v {
+ GComp(ref mut other_ci) => {
+ if other_ci.borrow().name == other_type_name {
+ *other_ci.borrow_mut() = ci.borrow().clone();
+ found_in_globals = true;
+ }
+ },
+ _ => {},
+ }
+ }
+
+ for (cursor, v) in ctx_.name.iter_mut() {
+ // We can find ourselves here, and that's no fun at
+ // all.
+ if *cursor == ci.borrow().parser_cursor.unwrap() {
+ continue;
+ }
+ match *v {
+ GComp(ref mut other_ci) |
+ GCompDecl(ref mut other_ci) => {
+ if other_ci.borrow().name == other_type_name {
+ // We have to preserve template parameter
+ // names here if we want to survive.
+ let args = other_ci.borrow().args.clone();
+ *other_ci.borrow_mut() = ci.borrow().clone();
+ other_ci.borrow_mut().args = args;
+ }
+ }
+ _ => {}
+ }
+ }
+
+ if !found_in_globals {
+ ctx_.current_module_mut().translations
+ .insert(other_type_name, GComp(ci));
+ }
} else {
ctx_.current_module_mut().globals.push(GComp(ci));
}
@@ -1032,17 +1231,8 @@ fn visit_top(cursor: &Cursor,
if visibility != CXVisibility_Default {
return CXChildVisit_Continue;
}
- let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
- let var = decl_name(ctx, cursor);
- let vi = var.varinfo();
- let mut vi = vi.borrow_mut();
- vi.ty = ty.clone();
- vi.is_const = cursor.cur_type().is_const();
- cursor.visit(|c, _: &Cursor| {
- vi.val = visit_literal(c, unit);
- CXChildVisit_Continue
- });
- ctx.current_module_mut().globals.push(var);
+ let val = decl_name(ctx, cursor);
+ ctx.current_module_mut().globals.push(val);
CXChildVisit_Continue
}
@@ -1093,7 +1283,7 @@ fn visit_top(cursor: &Cursor,
return CXChildVisit_Recurse;
}
- let namespace_name = match unit.tokens(cursor) {
+ let namespace_name = match ctx.current_translation_unit.tokens(cursor) {
None => None,
Some(tokens) => {
if tokens.len() <= 1 {
@@ -1130,13 +1320,13 @@ fn visit_top(cursor: &Cursor,
let previous_id = ctx.current_module_id;
ctx.current_module_id = mod_id;
- cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx, &unit));
+ cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx));
ctx.current_module_id = previous_id;
return CXChildVisit_Continue;
}
CXCursor_MacroDefinition => {
- let val = parse_int_literal_tokens(cursor, unit, 1);
+ let val = parse_int_literal_tokens(cursor, &ctx.current_translation_unit, 1);
if val.is_none() {
// Not an integer literal.
return CXChildVisit_Continue;
@@ -1172,12 +1362,25 @@ fn log_err_warn(ctx: &mut ClangParserCtx, msg: &str, is_err: bool) {
}
pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap, ()> {
+ let ix = cx::Index::create(false, true);
+ if ix.is_null() {
+ logger.error("Clang failed to create index");
+ return Err(())
+ }
+
+ let unit = TranslationUnit::parse(&ix, "", &options.clang_args, &[], CXTranslationUnit_DetailedPreprocessingRecord);
+ if unit.is_null() {
+ logger.error("No input files given");
+ return Err(())
+ }
+
let mut ctx = ClangParserCtx {
options: options,
name: HashMap::new(),
builtin_defs: vec!(),
module_map: ModuleMap::new(),
current_module_id: ROOT_MODULE_ID,
+ current_translation_unit: unit,
logger: logger,
err_count: 0,
anonymous_modules_found: 0,
@@ -1185,19 +1388,7 @@ pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap,
ctx.module_map.insert(ROOT_MODULE_ID, Module::new("root".to_owned(), None));
- let ix = cx::Index::create(false, true);
- if ix.is_null() {
- ctx.logger.error("Clang failed to create index");
- return Err(())
- }
-
- let unit = TranslationUnit::parse(&ix, "", &ctx.options.clang_args[..], &[], CXTranslationUnit_DetailedPreprocessingRecord);
- if unit.is_null() {
- ctx.logger.error("No input files given");
- return Err(())
- }
-
- let diags = unit.diags();
+ let diags = ctx.current_translation_unit.diags();
for d in &diags {
let msg = d.format(Diagnostic::default_opts());
let is_err = d.severity() >= CXDiagnostic_Error;
@@ -1208,20 +1399,20 @@ pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap,
return Err(())
}
- let cursor = unit.cursor();
+ let cursor = ctx.current_translation_unit.cursor();
if ctx.options.emit_ast {
cursor.visit(|cur, _: &Cursor| ast_dump(cur, 0));
}
- cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx, &unit));
+ cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx));
while !ctx.builtin_defs.is_empty() {
let c = ctx.builtin_defs.remove(0);
- visit_top(&c.definition(), &mut ctx, &unit);
+ visit_top(&c.definition(), &mut ctx);
}
- unit.dispose();
+ ctx.current_translation_unit.dispose();
ix.dispose();
if ctx.err_count > 0 {
diff --git a/src/types.rs b/src/types.rs
index cc335d41..4527d710 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -10,6 +10,7 @@ pub use self::Global::*;
pub use self::Type::*;
pub use self::IKind::*;
pub use self::FKind::*;
+use clang::Cursor;
static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
@@ -54,7 +55,7 @@ impl Module {
}
}
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
pub enum Global {
GType(Rc<RefCell<TypeInfo>>),
GComp(Rc<RefCell<CompInfo>>),
@@ -190,6 +191,15 @@ impl Type {
}
}
+ pub fn signature_contains_type(&self, other: &Type) -> bool {
+ self == other || match *self {
+ TPtr(ref t, _, _, _) => t.signature_contains_type(other),
+ TArray(ref t, _, _) => t.signature_contains_type(other),
+ TComp(ref info) => info.borrow().signature_contains_type(other),
+ _ => false,
+ }
+ }
+
// XXX Add this info to enums?
pub fn was_unnamed(&self) -> bool {
match *self {
@@ -200,6 +210,15 @@ impl Type {
}
}
+ pub fn get_outermost_composite(&self) -> Option<Rc<RefCell<CompInfo>>> {
+ match *self {
+ TComp(ref ci) => Some(ci.clone()),
+ TArray(ref t, _, _) => t.get_outermost_composite(),
+ TPtr(ref t, _, _, _) => t.get_outermost_composite(),
+ _ => None,
+ }
+ }
+
pub fn size(&self) -> usize {
self.layout().map(|l| l.size).unwrap_or(0)
}
@@ -281,6 +300,7 @@ impl Type {
}
}
+ #[allow(dead_code)]
pub fn is_union_like(&self) -> bool {
match *self {
TArray(ref t, _, _) => t.is_union_like(),
@@ -401,6 +421,7 @@ pub struct CompInfo {
pub has_destructor: bool,
pub has_nonempty_base: bool,
pub hide: bool,
+ pub parser_cursor: Option<Cursor>,
/// If this struct should be replaced by an opaque blob.
///
/// This is useful if for some reason we can't generate
@@ -408,12 +429,16 @@ pub struct CompInfo {
pub opaque: bool,
pub base_members: usize,
pub layout: Layout,
+ /// If this struct is explicitely marked as non-copiable.
+ pub no_copy: bool,
/// Typedef'd types names, that we'll resolve early to avoid name conflicts
pub typedefs: Vec<String>,
/// If this type has a template parameter which is not a type (e.g.: a size_t)
pub has_non_type_template_params: bool,
/// If this type was unnamed when parsed
pub was_unnamed: bool,
+ /// Set of static vars declared inside this class.
+ pub vars: Vec<Global>,
/// Used to detect if we've run in a can_derive_debug cycle while
/// cycling around the template arguments.
detect_derive_debug_cycle: Cell<bool>,
@@ -431,7 +456,13 @@ fn unnamed_name(name: String, filename: &String) -> String {
}
impl CompInfo {
- pub fn new(name: String, module_id: ModuleId, filename: String, comment: String, kind: CompKind, members: Vec<CompMember>, layout: Layout) -> CompInfo {
+ pub fn new(name: String,
+ module_id: ModuleId,
+ filename: String,
+ comment: String,
+ kind: CompKind,
+ members: Vec<CompMember>,
+ layout: Layout) -> CompInfo {
let was_unnamed = name.is_empty();
CompInfo {
kind: kind,
@@ -440,18 +471,21 @@ impl CompInfo {
filename: filename,
comment: comment,
members: members,
- args: vec!(),
- methods: vec!(),
- vmethods: vec!(),
+ args: vec![],
+ methods: vec![],
+ vmethods: vec![],
ref_template: None,
has_vtable: false,
has_destructor: false,
has_nonempty_base: false,
hide: false,
+ parser_cursor: None,
opaque: false,
+ no_copy: false,
base_members: 0,
layout: layout,
- typedefs: vec!(),
+ typedefs: vec![],
+ vars: vec![],
has_non_type_template_params: false,
was_unnamed: was_unnamed,
detect_derive_debug_cycle: Cell::new(false),
@@ -539,6 +573,9 @@ impl CompInfo {
}
pub fn can_derive_copy(&self) -> bool {
+ if self.no_copy {
+ return false;
+ }
match self.kind {
CompKind::Union => true,
CompKind::Struct => {
@@ -566,6 +603,10 @@ impl CompInfo {
}
}
}
+
+ pub fn signature_contains_type(&self, other: &Type) -> bool {
+ self.args.iter().any(|t| t.signature_contains_type(other))
+ }
}
impl fmt::Debug for CompInfo {
@@ -580,15 +621,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/class.rs b/tests/expectations/class.rs
index 244e98a4..560c315c 100644
--- a/tests/expectations/class.rs
+++ b/tests/expectations/class.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/class_static.rs b/tests/expectations/class_static.rs
new file mode 100644
index 00000000..f97875e9
--- /dev/null
+++ b/tests/expectations/class_static.rs
@@ -0,0 +1,21 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Struct_MyClass;
+impl ::std::clone::Clone for Struct_MyClass {
+ fn clone(&self) -> Self { *self }
+}
+extern "C" {
+ #[link_name = "_ZN7MyClass7exampleE"]
+ pub static mut Struct_MyClass_consts_example:
+ *const ::std::os::raw::c_int;
+ #[link_name = "_ZN7MyClass26example_check_no_collisionE"]
+ pub static mut Struct_MyClass_consts_example_check_no_collision:
+ *const ::std::os::raw::c_int;
+}
diff --git a/tests/expectations/class_with_inner_struct.rs b/tests/expectations/class_with_inner_struct.rs
index 85954397..d045e911 100644
--- a/tests/expectations/class_with_inner_struct.rs
+++ b/tests/expectations/class_with_inner_struct.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
@@ -124,7 +125,7 @@ fn bindgen_test_layout_Struct_B() {
assert_eq!(::std::mem::align_of::<Struct_B>() , 4usize);
}
#[repr(i32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_StepSyntax {
Keyword = 0,
FunctionalWithoutKeyword = 1,
diff --git a/tests/expectations/enum.rs b/tests/expectations/enum.rs
index 0b426196..23a599b9 100644
--- a/tests/expectations/enum.rs
+++ b/tests/expectations/enum.rs
@@ -6,8 +6,8 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo { Bar = 0, Qux = 1, }
#[repr(i32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Neg { MinusOne = -1, One = 1, }
diff --git a/tests/expectations/enum_and_vtable_mangling.rs b/tests/expectations/enum_and_vtable_mangling.rs
index 63e66991..f6b1385a 100644
--- a/tests/expectations/enum_and_vtable_mangling.rs
+++ b/tests/expectations/enum_and_vtable_mangling.rs
@@ -6,7 +6,7 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_enum_and_vtable_mangling_hpp_unnamed_1 {
match_ = 0,
whatever_else = 1,
diff --git a/tests/expectations/enum_dupe.rs b/tests/expectations/enum_dupe.rs
index 2d691b69..28d7b63d 100644
--- a/tests/expectations/enum_dupe.rs
+++ b/tests/expectations/enum_dupe.rs
@@ -7,5 +7,5 @@
pub const Dupe: Enum_Foo = Enum_Foo::Bar;
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo { Bar = 1, }
diff --git a/tests/expectations/enum_explicit_type.rs b/tests/expectations/enum_explicit_type.rs
index a5a92d99..cfc1f41d 100644
--- a/tests/expectations/enum_explicit_type.rs
+++ b/tests/expectations/enum_explicit_type.rs
@@ -6,17 +6,17 @@
#[repr(u8)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo { Bar = 0, Qux = 1, }
#[repr(i8)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Neg { MinusOne = -1, One = 1, }
#[repr(u16)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Bigger { Much = 255, Larger = 256, }
#[repr(i64)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_MuchLong { MuchLow = -4294967296, }
#[repr(u64)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_MuchLongLong { MuchHigh = 4294967296, }
diff --git a/tests/expectations/enum_negative.rs b/tests/expectations/enum_negative.rs
index 24b009e9..0a7a36f7 100644
--- a/tests/expectations/enum_negative.rs
+++ b/tests/expectations/enum_negative.rs
@@ -6,5 +6,5 @@
#[repr(i32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo { Bar = -2, Qux = 1, }
diff --git a/tests/expectations/enum_packed.rs b/tests/expectations/enum_packed.rs
index 12f0bd49..6b3f1b57 100644
--- a/tests/expectations/enum_packed.rs
+++ b/tests/expectations/enum_packed.rs
@@ -6,11 +6,11 @@
#[repr(u8)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo { Bar = 0, Qux = 1, }
#[repr(i8)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Neg { MinusOne = -1, One = 1, }
#[repr(u16)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Bigger { Much = 255, Larger = 256, }
diff --git a/tests/expectations/func_ptr_in_struct.rs b/tests/expectations/func_ptr_in_struct.rs
index 970e3122..c177116d 100644
--- a/tests/expectations/func_ptr_in_struct.rs
+++ b/tests/expectations/func_ptr_in_struct.rs
@@ -6,7 +6,7 @@
#[repr(i32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_baz { _BindgenOpaqueEnum = 0, }
#[repr(C)]
#[derive(Debug, Copy)]
diff --git a/tests/expectations/inner_template_self.rs b/tests/expectations/inner_template_self.rs
new file mode 100644
index 00000000..ec8bf6b1
--- /dev/null
+++ b/tests/expectations/inner_template_self.rs
@@ -0,0 +1,26 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_LinkedList<T> {
+ pub next: *mut Struct_LinkedList<T>,
+ pub prev: *mut Struct_LinkedList<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Struct_InstantiateIt {
+ pub m_list: Struct_LinkedList<::std::os::raw::c_int>,
+}
+impl ::std::clone::Clone for Struct_InstantiateIt {
+ fn clone(&self) -> Self { *self }
+}
+#[test]
+fn bindgen_test_layout_Struct_InstantiateIt() {
+ assert_eq!(::std::mem::size_of::<Struct_InstantiateIt>() , 16usize);
+ assert_eq!(::std::mem::align_of::<Struct_InstantiateIt>() , 8usize);
+}
diff --git a/tests/expectations/jsval_layout_opaque.rs b/tests/expectations/jsval_layout_opaque.rs
index 33c2ce32..760ac1f2 100644
--- a/tests/expectations/jsval_layout_opaque.rs
+++ b/tests/expectations/jsval_layout_opaque.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
@@ -25,7 +26,7 @@ impl <T> ::std::clone::Clone for __BindgenUnionField<T> {
}
pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47;
#[repr(u8)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum JSValueType {
JSVAL_TYPE_DOUBLE = 0,
JSVAL_TYPE_INT32 = 1,
@@ -40,7 +41,7 @@ pub enum JSValueType {
JSVAL_TYPE_MISSING = 33,
}
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum JSValueTag {
JSVAL_TAG_MAX_DOUBLE = 131056,
JSVAL_TAG_INT32 = 131057,
@@ -53,7 +54,7 @@ pub enum JSValueTag {
JSVAL_TAG_OBJECT = 131064,
}
#[repr(u64)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663,
JSVAL_SHIFTED_TAG_INT32 = 18444633011384221696,
@@ -66,7 +67,7 @@ pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992,
}
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum JSWhyMagic {
JS_ELEMENTS_HOLE = 0,
JS_NO_ITER_VALUE = 1,
@@ -146,13 +147,25 @@ pub struct jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
pub _bitfield_1: u64,
}
impl jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
+ #[inline]
+ pub fn payload47(&self) -> u64 {
+ (self._bitfield_1 & (140737488355327usize as u64)) >> 0usize
+ }
+ #[inline]
pub fn set_payload47(&mut self, val: u32) {
- self._bitfield_1 &= !(((1 << (47u32 as u64)) - 1) << 0usize);
- self._bitfield_1 |= (val as u64) << 0usize;
+ self._bitfield_1 &= !(140737488355327usize as u64);
+ self._bitfield_1 |=
+ ((val as u64) << 0usize) & (140737488355327usize as u64);
}
+ #[inline]
+ pub fn tag(&self) -> u64 {
+ (self._bitfield_1 & (18446603336221196288usize as u64)) >> 47usize
+ }
+ #[inline]
pub fn set_tag(&mut self, val: u32) {
- self._bitfield_1 &= !(((1 << (17u32 as u64)) - 1) << 47usize);
- self._bitfield_1 |= (val as u64) << 47usize;
+ self._bitfield_1 &= !(18446603336221196288usize as u64);
+ self._bitfield_1 |=
+ ((val as u64) << 47usize) & (18446603336221196288usize as u64);
}
pub const fn new_bitfield_1(payload47: u32, tag: u32) -> u64 {
0 | ((payload47 as u64) << 0u32) | ((tag as u64) << 47u32)
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/expectations/namespace.rs b/tests/expectations/namespace.rs
index 59c6c349..4d9225f3 100644
--- a/tests/expectations/namespace.rs
+++ b/tests/expectations/namespace.rs
@@ -14,6 +14,7 @@ pub mod root {
pub m_c: T,
pub m_c_ptr: *mut T,
pub m_c_arr: [T; 10usize],
+ pub _phantom0: ::std::marker::PhantomData<T>,
}
extern "C" {
#[link_name = "_Z9top_levelv"]
@@ -57,7 +58,6 @@ pub mod root {
#[derive(Debug)]
pub struct Struct_D<T> {
pub m_c: root::Struct_C<T>,
- pub _phantom0: ::std::marker::PhantomData<T>,
}
extern "C" {
#[link_name = "_ZN1w3hehEv"]
diff --git a/tests/expectations/no_copy.rs b/tests/expectations/no_copy.rs
new file mode 100644
index 00000000..95a733b6
--- /dev/null
+++ b/tests/expectations/no_copy.rs
@@ -0,0 +1,14 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+/** <div rustbindgen nocopy></div> */
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_CopiableButWait<T> {
+ pub whatever: ::std::os::raw::c_int,
+ pub _phantom0: ::std::marker::PhantomData<T>,
+}
diff --git a/tests/expectations/nsStyleAutoArray.rs b/tests/expectations/nsStyleAutoArray.rs
new file mode 100644
index 00000000..28207639
--- /dev/null
+++ b/tests/expectations/nsStyleAutoArray.rs
@@ -0,0 +1,23 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_nsTArray<T> {
+ pub mBuff: *mut T,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_nsStyleAutoArray<T> {
+ pub mFirstElement: T,
+ pub mOtherElements: Struct_nsTArray<T>,
+}
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum nsStyleAutoArray_WithSingleInitialElement {
+ WITH_SINGLE_INITIAL_ELEMENT = 0,
+}
diff --git a/tests/expectations/only_bitfields.rs b/tests/expectations/only_bitfields.rs
index 86ed8564..88345373 100644
--- a/tests/expectations/only_bitfields.rs
+++ b/tests/expectations/only_bitfields.rs
@@ -11,13 +11,19 @@ pub struct Struct_C {
pub _bitfield_1: u8,
}
impl Struct_C {
+ #[inline]
+ pub fn a(&self) -> u8 { (self._bitfield_1 & (1usize as u8)) >> 0usize }
+ #[inline]
pub fn set_a(&mut self, val: bool) {
- self._bitfield_1 &= !(((1 << (1u32 as u8)) - 1) << 0usize);
- self._bitfield_1 |= (val as u8) << 0usize;
+ self._bitfield_1 &= !(1usize as u8);
+ self._bitfield_1 |= ((val as u8) << 0usize) & (1usize as u8);
}
+ #[inline]
+ pub fn b(&self) -> u8 { (self._bitfield_1 & (254usize as u8)) >> 1usize }
+ #[inline]
pub fn set_b(&mut self, val: u8) {
- self._bitfield_1 &= !(((1 << (7u32 as u8)) - 1) << 1usize);
- self._bitfield_1 |= (val as u8) << 1usize;
+ self._bitfield_1 &= !(254usize as u8);
+ self._bitfield_1 |= ((val as u8) << 1usize) & (254usize as u8);
}
pub const fn new_bitfield_1(a: bool, b: u8) -> u8 {
0 | ((a as u8) << 0u32) | ((b as u8) << 1u32)
diff --git a/tests/expectations/opaque_typedef.rs b/tests/expectations/opaque_typedef.rs
new file mode 100644
index 00000000..7dfa0ff9
--- /dev/null
+++ b/tests/expectations/opaque_typedef.rs
@@ -0,0 +1,17 @@
+/* automatically generated by rust-bindgen */
+
+
+#![feature(const_fn)]
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_RandomTemplate<T> {
+ pub _phantom0: ::std::marker::PhantomData<T>,
+}
+pub enum Struct_Wat { }
+pub enum Struct_Wat3 { }
+#[repr(C)]
+pub struct ShouldBeOpaque;
+pub type ShouldNotBeOpaque = Struct_RandomTemplate<::std::os::raw::c_int>;
diff --git a/tests/expectations/overflowed_enum.rs b/tests/expectations/overflowed_enum.rs
index e32db0ae..7b6de96b 100644
--- a/tests/expectations/overflowed_enum.rs
+++ b/tests/expectations/overflowed_enum.rs
@@ -6,12 +6,12 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Foo {
BAP_ARM = 9698489,
BAP_X86 = 11960045,
BAP_X86_64 = 3128633167,
}
#[repr(u16)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_Bar { One = 1, Big = 2, }
diff --git a/tests/expectations/struct_with_anon_union.rs b/tests/expectations/struct_with_anon_union.rs
index ce5d6357..668b1273 100644
--- a/tests/expectations/struct_with_anon_union.rs
+++ b/tests/expectations/struct_with_anon_union.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/struct_with_anon_unnamed_union.rs b/tests/expectations/struct_with_anon_unnamed_union.rs
index d5871b1a..5df5f61b 100644
--- a/tests/expectations/struct_with_anon_unnamed_union.rs
+++ b/tests/expectations/struct_with_anon_unnamed_union.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/struct_with_bitfields.rs b/tests/expectations/struct_with_bitfields.rs
index ab2acf2a..26003ebd 100644
--- a/tests/expectations/struct_with_bitfields.rs
+++ b/tests/expectations/struct_with_bitfields.rs
@@ -14,35 +14,71 @@ pub struct Struct_bitfield {
pub _bitfield_3: ::std::os::raw::c_uint,
}
impl Struct_bitfield {
+ #[inline]
+ pub fn a(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (1usize as ::std::os::raw::c_ushort)) >> 0usize
+ }
+ #[inline]
pub fn set_a(&mut self, val: bool) {
- self._bitfield_1 &=
- !(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 0usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 0usize;
+ self._bitfield_1 &= !(1usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 0usize) &
+ (1usize as ::std::os::raw::c_ushort);
+ }
+ #[inline]
+ pub fn b(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (2usize as ::std::os::raw::c_ushort)) >> 1usize
}
+ #[inline]
pub fn set_b(&mut self, val: bool) {
- self._bitfield_1 &=
- !(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 1usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 1usize;
+ self._bitfield_1 &= !(2usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 1usize) &
+ (2usize as ::std::os::raw::c_ushort);
}
+ #[inline]
+ pub fn c(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (4usize as ::std::os::raw::c_ushort)) >> 2usize
+ }
+ #[inline]
pub fn set_c(&mut self, val: bool) {
- self._bitfield_1 &=
- !(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 2usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 2usize;
+ self._bitfield_1 &= !(4usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 2usize) &
+ (4usize as ::std::os::raw::c_ushort);
+ }
+ #[inline]
+ pub fn at_offset_3(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (8usize as ::std::os::raw::c_ushort)) >> 3usize
}
+ #[inline]
pub fn set_at_offset_3(&mut self, val: bool) {
- self._bitfield_1 &=
- !(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 3usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 3usize;
+ self._bitfield_1 &= !(8usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 3usize) &
+ (8usize as ::std::os::raw::c_ushort);
}
+ #[inline]
+ pub fn at_offset_4(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (48usize as ::std::os::raw::c_ushort)) >> 4usize
+ }
+ #[inline]
pub fn set_at_offset_4(&mut self, val: u8) {
- self._bitfield_1 &=
- !(((1 << (2u32 as ::std::os::raw::c_ushort)) - 1) << 4usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 4usize;
+ self._bitfield_1 &= !(48usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 4usize) &
+ (48usize as ::std::os::raw::c_ushort);
+ }
+ #[inline]
+ pub fn d(&self) -> ::std::os::raw::c_ushort {
+ (self._bitfield_1 & (192usize as ::std::os::raw::c_ushort)) >> 6usize
}
+ #[inline]
pub fn set_d(&mut self, val: u8) {
- self._bitfield_1 &=
- !(((1 << (2u32 as ::std::os::raw::c_ushort)) - 1) << 6usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 6usize;
+ self._bitfield_1 &= !(192usize as ::std::os::raw::c_ushort);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_ushort) << 6usize) &
+ (192usize as ::std::os::raw::c_ushort);
}
pub const fn new_bitfield_1(a: bool, b: bool, c: bool,
unnamed_bitfield1: bool,
@@ -55,18 +91,31 @@ impl Struct_bitfield {
((unnamed_bitfield2 as ::std::os::raw::c_ushort) << 4u32) |
((d as ::std::os::raw::c_ushort) << 6u32)
}
+ #[inline]
+ pub fn f(&self) -> ::std::os::raw::c_uint {
+ (self._bitfield_2 & (3usize as ::std::os::raw::c_uint)) >> 0usize
+ }
+ #[inline]
pub fn set_f(&mut self, val: u8) {
- self._bitfield_2 &=
- !(((1 << (2u32 as ::std::os::raw::c_uint)) - 1) << 0usize);
- self._bitfield_2 |= (val as ::std::os::raw::c_uint) << 0usize;
+ self._bitfield_2 &= !(3usize as ::std::os::raw::c_uint);
+ self._bitfield_2 |=
+ ((val as ::std::os::raw::c_uint) << 0usize) &
+ (3usize as ::std::os::raw::c_uint);
}
pub const fn new_bitfield_2(f: u8) -> ::std::os::raw::c_uint {
0 | ((f as ::std::os::raw::c_uint) << 0u32)
}
+ #[inline]
+ pub fn g(&self) -> ::std::os::raw::c_uint {
+ (self._bitfield_3 & (4294967295usize as ::std::os::raw::c_uint)) >>
+ 0usize
+ }
+ #[inline]
pub fn set_g(&mut self, val: u32) {
- self._bitfield_3 &=
- !(((1 << (0u32 as ::std::os::raw::c_uint)) - 1) << 0usize);
- self._bitfield_3 |= (val as ::std::os::raw::c_uint) << 0usize;
+ self._bitfield_3 &= !(4294967295usize as ::std::os::raw::c_uint);
+ self._bitfield_3 |=
+ ((val as ::std::os::raw::c_uint) << 0usize) &
+ (4294967295usize as ::std::os::raw::c_uint);
}
pub const fn new_bitfield_3(g: u32) -> ::std::os::raw::c_uint {
0 | ((g as ::std::os::raw::c_uint) << 0u32)
diff --git a/tests/expectations/struct_with_nesting.rs b/tests/expectations/struct_with_nesting.rs
index 2e023c33..787a174d 100644
--- a/tests/expectations/struct_with_nesting.rs
+++ b/tests/expectations/struct_with_nesting.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/template.rs b/tests/expectations/template.rs
index 63f2d952..02e683a8 100644
--- a/tests/expectations/template.rs
+++ b/tests/expectations/template.rs
@@ -74,6 +74,81 @@ fn bindgen_test_layout_Struct_POD() {
assert_eq!(::std::mem::size_of::<Struct_POD>() , 4usize);
assert_eq!(::std::mem::align_of::<Struct_POD>() , 4usize);
}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_NestedBase<T, U> {
+ pub buff: *mut T,
+ pub _phantom0: ::std::marker::PhantomData<U>,
+}
+/**
+ * <div rustbindgen replaces="NestedReplaced"></div>
+ */
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_NestedReplaced<T> {
+ pub buff: *mut T,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_NestedContainer<T> {
+ pub c: T,
+ pub nested: Struct_NestedReplaced<T>,
+ pub inc: Struct_Incomplete<T>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_Incomplete<T> {
+ pub d: T,
+}
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct Struct_Untemplated;
+impl ::std::clone::Clone for Struct_Untemplated {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_Templated<T> {
+ pub m_untemplated: Struct_Untemplated,
+ pub _phantom0: ::std::marker::PhantomData<T>,
+}
+/**
+ * If the replacement doesn't happen at the parse level the container would be
+ * copy and the replacement wouldn't, so this wouldn't compile.
+ *
+ * <div rustbindgen replaces="ReplacedWithoutDestructor"></div>
+ */
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_ReplacedWithoutDestructor<T> {
+ pub buff: *mut T,
+}
+/**
+ * If the replacement doesn't happen at the parse level the container would be
+ * copy and the replacement wouldn't, so this wouldn't compile.
+ *
+ * <div rustbindgen replaces="ReplacedWithoutDestructorFwd"></div>
+ */
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_ReplacedWithoutDestructorFwd<T> {
+ pub buff: *mut T,
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_ShouldNotBeCopiable<T> {
+ pub m_member: Struct_ReplacedWithoutDestructor<T>,
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct Struct_ShouldNotBeCopiableAsWell<U> {
+ pub m_member: Struct_ReplacedWithoutDestructorFwd<U>,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Struct_TemplateWithVar<T> {
+ pub _phantom0: ::std::marker::PhantomData<T>,
+}
extern "C" {
#[link_name = "_Z3bar3FooIiiE"]
pub fn bar(foo: Struct_Foo<::std::os::raw::c_int, ::std::os::raw::c_int>);
diff --git a/tests/expectations/union_fields.rs b/tests/expectations/union_fields.rs
index cf750844..974a8f71 100644
--- a/tests/expectations/union_fields.rs
+++ b/tests/expectations/union_fields.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_anon_struct.rs b/tests/expectations/union_with_anon_struct.rs
index 076e263f..3f78fb85 100644
--- a/tests/expectations/union_with_anon_struct.rs
+++ b/tests/expectations/union_with_anon_struct.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_anon_struct_bitfield.rs b/tests/expectations/union_with_anon_struct_bitfield.rs
index dc96c5c8..26b428f5 100644
--- a/tests/expectations/union_with_anon_struct_bitfield.rs
+++ b/tests/expectations/union_with_anon_struct_bitfield.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
@@ -55,15 +56,28 @@ pub struct Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
pub _bitfield_1: ::std::os::raw::c_int,
}
impl Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
+ #[inline]
+ pub fn b(&self) -> ::std::os::raw::c_int {
+ (self._bitfield_1 & (127usize as ::std::os::raw::c_int)) >> 0usize
+ }
+ #[inline]
pub fn set_b(&mut self, val: u8) {
- self._bitfield_1 &=
- !(((1 << (7u32 as ::std::os::raw::c_int)) - 1) << 0usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_int) << 0usize;
+ self._bitfield_1 &= !(127usize as ::std::os::raw::c_int);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_int) << 0usize) &
+ (127usize as ::std::os::raw::c_int);
}
+ #[inline]
+ pub fn c(&self) -> ::std::os::raw::c_int {
+ (self._bitfield_1 & (4294967168usize as ::std::os::raw::c_int)) >>
+ 7usize
+ }
+ #[inline]
pub fn set_c(&mut self, val: u32) {
- self._bitfield_1 &=
- !(((1 << (25u32 as ::std::os::raw::c_int)) - 1) << 7usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_int) << 7usize;
+ self._bitfield_1 &= !(4294967168usize as ::std::os::raw::c_int);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_int) << 7usize) &
+ (4294967168usize as ::std::os::raw::c_int);
}
pub const fn new_bitfield_1(b: u8, c: u32) -> ::std::os::raw::c_int {
0 | ((b as ::std::os::raw::c_int) << 0u32) |
diff --git a/tests/expectations/union_with_anon_union.rs b/tests/expectations/union_with_anon_union.rs
index fc354db4..9ea9b841 100644
--- a/tests/expectations/union_with_anon_union.rs
+++ b/tests/expectations/union_with_anon_union.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_anon_unnamed_struct.rs b/tests/expectations/union_with_anon_unnamed_struct.rs
index d75c120f..80e28512 100644
--- a/tests/expectations/union_with_anon_unnamed_struct.rs
+++ b/tests/expectations/union_with_anon_unnamed_struct.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_anon_unnamed_union.rs b/tests/expectations/union_with_anon_unnamed_union.rs
index 4f26bfc9..a502f1f3 100644
--- a/tests/expectations/union_with_anon_unnamed_union.rs
+++ b/tests/expectations/union_with_anon_unnamed_union.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_big_member.rs b/tests/expectations/union_with_big_member.rs
index 44fc317b..122d5a64 100644
--- a/tests/expectations/union_with_big_member.rs
+++ b/tests/expectations/union_with_big_member.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/union_with_nesting.rs b/tests/expectations/union_with_nesting.rs
index 0a884d4a..070cc045 100644
--- a/tests/expectations/union_with_nesting.rs
+++ b/tests/expectations/union_with_nesting.rs
@@ -6,6 +6,7 @@
#[derive(Copy, Debug)]
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
diff --git a/tests/expectations/weird_bitfields.rs b/tests/expectations/weird_bitfields.rs
index 405c2490..d2ae1f96 100644
--- a/tests/expectations/weird_bitfields.rs
+++ b/tests/expectations/weird_bitfields.rs
@@ -6,7 +6,7 @@
#[repr(u32)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Enum_nsStyleSVGOpacitySource {
eStyleSVGOpacitySource_Normal = 0,
eStyleSVGOpacitySource_ContextFillOpacity = 1,
@@ -31,40 +31,78 @@ pub struct Struct_Weird {
pub _bitfield_2: u32,
}
impl Struct_Weird {
+ #[inline]
+ pub fn bitTest(&self) -> ::std::os::raw::c_uint {
+ (self._bitfield_1 & (65535usize as ::std::os::raw::c_uint)) >> 0usize
+ }
+ #[inline]
pub fn set_bitTest(&mut self, val: u16) {
- self._bitfield_1 &=
- !(((1 << (16u32 as ::std::os::raw::c_uint)) - 1) << 0usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_uint) << 0usize;
+ self._bitfield_1 &= !(65535usize as ::std::os::raw::c_uint);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_uint) << 0usize) &
+ (65535usize as ::std::os::raw::c_uint);
+ }
+ #[inline]
+ pub fn bitTest2(&self) -> ::std::os::raw::c_uint {
+ (self._bitfield_1 & (2147418112usize as ::std::os::raw::c_uint)) >>
+ 16usize
}
+ #[inline]
pub fn set_bitTest2(&mut self, val: u16) {
- self._bitfield_1 &=
- !(((1 << (15u32 as ::std::os::raw::c_uint)) - 1) << 16usize);
- self._bitfield_1 |= (val as ::std::os::raw::c_uint) << 16usize;
+ self._bitfield_1 &= !(2147418112usize as ::std::os::raw::c_uint);
+ self._bitfield_1 |=
+ ((val as ::std::os::raw::c_uint) << 16usize) &
+ (2147418112usize as ::std::os::raw::c_uint);
}
pub const fn new_bitfield_1(bitTest: u16, bitTest2: u16)
-> ::std::os::raw::c_uint {
0 | ((bitTest as ::std::os::raw::c_uint) << 0u32) |
((bitTest2 as ::std::os::raw::c_uint) << 16u32)
}
+ #[inline]
+ pub fn mFillOpacitySource(&self) -> u32 {
+ (self._bitfield_2 & (7usize as u32)) >> 0usize
+ }
+ #[inline]
pub fn set_mFillOpacitySource(&mut self, val: u8) {
- self._bitfield_2 &= !(((1 << (3u32 as u32)) - 1) << 0usize);
- self._bitfield_2 |= (val as u32) << 0usize;
+ self._bitfield_2 &= !(7usize as u32);
+ self._bitfield_2 |= ((val as u32) << 0usize) & (7usize as u32);
+ }
+ #[inline]
+ pub fn mStrokeOpacitySource(&self) -> u32 {
+ (self._bitfield_2 & (56usize as u32)) >> 3usize
}
+ #[inline]
pub fn set_mStrokeOpacitySource(&mut self, val: u8) {
- self._bitfield_2 &= !(((1 << (3u32 as u32)) - 1) << 3usize);
- self._bitfield_2 |= (val as u32) << 3usize;
+ self._bitfield_2 &= !(56usize as u32);
+ self._bitfield_2 |= ((val as u32) << 3usize) & (56usize as u32);
}
+ #[inline]
+ pub fn mStrokeDasharrayFromObject(&self) -> u32 {
+ (self._bitfield_2 & (64usize as u32)) >> 6usize
+ }
+ #[inline]
pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(((1 << (1u32 as u32)) - 1) << 6usize);
- self._bitfield_2 |= (val as u32) << 6usize;
+ self._bitfield_2 &= !(64usize as u32);
+ self._bitfield_2 |= ((val as u32) << 6usize) & (64usize as u32);
+ }
+ #[inline]
+ pub fn mStrokeDashoffsetFromObject(&self) -> u32 {
+ (self._bitfield_2 & (128usize as u32)) >> 7usize
}
+ #[inline]
pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(((1 << (1u32 as u32)) - 1) << 7usize);
- self._bitfield_2 |= (val as u32) << 7usize;
+ self._bitfield_2 &= !(128usize as u32);
+ self._bitfield_2 |= ((val as u32) << 7usize) & (128usize as u32);
+ }
+ #[inline]
+ pub fn mStrokeWidthFromObject(&self) -> u32 {
+ (self._bitfield_2 & (256usize as u32)) >> 8usize
}
+ #[inline]
pub fn set_mStrokeWidthFromObject(&mut self, val: bool) {
- self._bitfield_2 &= !(((1 << (1u32 as u32)) - 1) << 8usize);
- self._bitfield_2 |= (val as u32) << 8usize;
+ self._bitfield_2 &= !(256usize as u32);
+ self._bitfield_2 |= ((val as u32) << 8usize) & (256usize as u32);
}
pub const fn new_bitfield_2(mFillOpacitySource: u8,
mStrokeOpacitySource: u8,
diff --git a/tests/headers/class_static.hpp b/tests/headers/class_static.hpp
new file mode 100644
index 00000000..21ab2321
--- /dev/null
+++ b/tests/headers/class_static.hpp
@@ -0,0 +1,7 @@
+class MyClass {
+public:
+ static const int* example;
+ static const int* example_check_no_collision;
+};
+
+static const int* example_check_no_collision;
diff --git a/tests/headers/inner_template_self.hpp b/tests/headers/inner_template_self.hpp
new file mode 100644
index 00000000..1ae5af06
--- /dev/null
+++ b/tests/headers/inner_template_self.hpp
@@ -0,0 +1,10 @@
+
+template <typename T>
+class LinkedList {
+ LinkedList<T>* next;
+ LinkedList* prev;
+};
+
+class InstantiateIt {
+ LinkedList<int> m_list;
+};
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;
+};
diff --git a/tests/headers/no_copy.hpp b/tests/headers/no_copy.hpp
new file mode 100644
index 00000000..349e428e
--- /dev/null
+++ b/tests/headers/no_copy.hpp
@@ -0,0 +1,6 @@
+
+/** <div rustbindgen nocopy></div> */
+template<typename T>
+class CopiableButWait {
+ int whatever;
+};
diff --git a/tests/headers/nsStyleAutoArray.hpp b/tests/headers/nsStyleAutoArray.hpp
new file mode 100644
index 00000000..950152c0
--- /dev/null
+++ b/tests/headers/nsStyleAutoArray.hpp
@@ -0,0 +1,57 @@
+
+template<typename T>
+class nsTArray {
+ T* mBuff;
+};
+
+template<typename T>
+class nsStyleAutoArray
+{
+public:
+ // This constructor places a single element in mFirstElement.
+ enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT };
+ explicit nsStyleAutoArray(WithSingleInitialElement) {}
+ nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; }
+ nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) {
+ mFirstElement = aOther.mFirstElement;
+ mOtherElements = aOther.mOtherElements;
+ return *this;
+ }
+
+ bool operator==(const nsStyleAutoArray& aOther) const {
+ return Length() == aOther.Length() &&
+ mFirstElement == aOther.mFirstElement &&
+ mOtherElements == aOther.mOtherElements;
+ }
+ bool operator!=(const nsStyleAutoArray& aOther) const {
+ return !(*this == aOther);
+ }
+
+ unsigned long Length() const {
+ return mOtherElements.Length() + 1;
+ }
+ const T& operator[](unsigned long aIndex) const {
+ return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
+ }
+ T& operator[](unsigned long aIndex) {
+ return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
+ }
+
+ void EnsureLengthAtLeast(unsigned long aMinLen) {
+ if (aMinLen > 0) {
+ mOtherElements.EnsureLengthAtLeast(aMinLen - 1);
+ }
+ }
+
+ void SetLengthNonZero(unsigned long aNewLen) {
+ mOtherElements.SetLength(aNewLen - 1);
+ }
+
+ void TruncateLengthNonZero(unsigned long aNewLen) {
+ mOtherElements.TruncateLength(aNewLen - 1);
+ }
+
+private:
+ T mFirstElement;
+ nsTArray<T> mOtherElements;
+};
diff --git a/tests/headers/opaque_typedef.hpp b/tests/headers/opaque_typedef.hpp
new file mode 100644
index 00000000..23bb363a
--- /dev/null
+++ b/tests/headers/opaque_typedef.hpp
@@ -0,0 +1,17 @@
+// bindgen-flags: -std=c++11
+template<typename T>
+class RandomTemplate;
+
+template<int i>
+class Wat;
+
+template<int i>
+class Wat3;
+
+template<>
+class Wat3<3>;
+
+/** <div rustbindgen opaque></div> */
+typedef RandomTemplate<int> ShouldBeOpaque;
+
+typedef RandomTemplate<int> ShouldNotBeOpaque;
diff --git a/tests/headers/template.hpp b/tests/headers/template.hpp
index e53ecbc8..c13643c3 100644
--- a/tests/headers/template.hpp
+++ b/tests/headers/template.hpp
@@ -55,3 +55,90 @@ class Opaque {
class POD {
Opaque<int> opaque_member;
};
+
+/**
+ * <div rustbindgen replaces="NestedReplaced"></div>
+ */
+template<typename T>
+class Nested {
+ T* buff;
+};
+
+template<typename T, typename U>
+class NestedBase {
+ T* buff;
+};
+
+template<typename T>
+class NestedReplaced: public NestedBase<T, int> {
+};
+
+template<typename T>
+class Incomplete;
+
+template<typename T>
+class NestedContainer {
+ T c;
+private:
+ NestedReplaced<T> nested;
+ Incomplete<T> inc;
+};
+
+template<typename T>
+class Incomplete {
+ T d;
+};
+
+class Untemplated {};
+
+template<typename T>
+class Templated {
+ Untemplated m_untemplated;
+};
+
+/**
+ * If the replacement doesn't happen at the parse level the container would be
+ * copy and the replacement wouldn't, so this wouldn't compile.
+ *
+ * <div rustbindgen replaces="ReplacedWithoutDestructor"></div>
+ */
+template<typename T>
+class ReplacedWithDestructor {
+ T* buff;
+ ~ReplacedWithDestructor() {};
+};
+
+template<typename T>
+class ReplacedWithoutDestructor {
+ T* buff;
+};
+
+template<typename T>
+class ReplacedWithoutDestructorFwd;
+
+template<typename T>
+class ShouldNotBeCopiable {
+ ReplacedWithoutDestructor<T> m_member;
+};
+
+template<typename U>
+class ShouldNotBeCopiableAsWell {
+ ReplacedWithoutDestructorFwd<U> m_member;
+};
+
+/**
+ * If the replacement doesn't happen at the parse level the container would be
+ * copy and the replacement wouldn't, so this wouldn't compile.
+ *
+ * <div rustbindgen replaces="ReplacedWithoutDestructorFwd"></div>
+ */
+template<typename T>
+class ReplacedWithDestructorDeclaredAfter {
+ T* buff;
+ ~ReplacedWithDestructorDeclaredAfter() {};
+};
+
+template<typename T>
+class TemplateWithVar {
+ static T var = 0;
+};
diff --git a/tests/tools/run-bindgen.py b/tests/tools/run-bindgen.py
index 0e3252ee..5fde6739 100755
--- a/tests/tools/run-bindgen.py
+++ b/tests/tools/run-bindgen.py
@@ -20,13 +20,14 @@ with open(sys.argv[2]) as f:
if line.startswith(BINDGEN_FLAGS_PREFIX):
flags = line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(' ')
-base_command = [sys.argv[1], sys.argv[2], "-o", sys.argv[3]]
+base_command = [sys.argv[1], "-o", sys.argv[3]]
for line in COMMON_PRELUDE.split('\n'):
flags.append("-raw-line")
flags.append(line)
base_command.extend(flags);
+base_command.append(sys.argv[2]);
subprocess.check_call(base_command, cwd=os.getcwd())