diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 4f239510f4..5c4b43083f 100644 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -7,9 +7,7 @@ use std::ffi::CStr; #[test] fn test_static_method() { let c_str = unsafe { bindings::Test::name() }; - let name = unsafe { - CStr::from_ptr(c_str).to_string_lossy().into_owned() - }; + let name = unsafe { CStr::from_ptr(c_str).to_string_lossy().into_owned() }; assert_eq!(name, "Test", "Calling a static C++ method works!"); } diff --git a/bindgen/src/options.rs b/bindgen/src/options.rs index a783696ec4..41a8a90574 100644 --- a/bindgen/src/options.rs +++ b/bindgen/src/options.rs @@ -1,5 +1,5 @@ use clap::{App, Arg}; -use libbindgen::{Builder, builder, CodegenConfig}; +use libbindgen::{Builder, CodegenConfig, builder}; use std::fs::File; use std::io::{self, Error, ErrorKind}; @@ -200,8 +200,8 @@ pub fn builder_from_flags(args: I) "vars" => config.vars = true, "methods" => config.methods = true, _ => { - return Err( - Error::new(ErrorKind::Other, "Unknown generate item")); + return Err(Error::new(ErrorKind::Other, + "Unknown generate item")); } } } diff --git a/libbindgen/src/clang.rs b/libbindgen/src/clang.rs index fc5575b38c..de0ebf156c 100644 --- a/libbindgen/src/clang.rs +++ b/libbindgen/src/clang.rs @@ -832,8 +832,8 @@ impl SourceLocation { &mut col, &mut off); (File { - x: file, - }, + x: file, + }, line as usize, col as usize, off as usize) diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index 192eb674a1..69d5f65136 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -727,14 +727,15 @@ impl CodeGenerator for CompInfo { let layout = item.kind().expect_type().layout(ctx); if let Some(layout) = layout { - let fn_name = format!("__bindgen_test_layout_template_{}", result.next_id()); + let fn_name = format!("__bindgen_test_layout_template_{}", + result.next_id()); let fn_name = ctx.rust_ident_raw(&fn_name); let ident = item.to_rust_ty(ctx); let prefix = ctx.trait_prefix(); let size_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::size_of::<$ident>()); + ::$prefix::mem::size_of::<$ident>()); let align_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::align_of::<$ident>()); + ::$prefix::mem::align_of::<$ident>()); let size = layout.size; let align = layout.align; let item = quote_item!(ctx.ext_cx(), @@ -894,7 +895,7 @@ impl CodeGenerator for CompInfo { // Try to catch a bitfield contination early. if let (Some(ref mut bitfield_width), Some(width)) = - (current_bitfield_width, field.bitfield()) { + (current_bitfield_width, field.bitfield()) { let layout = current_bitfield_layout.unwrap(); debug!("Testing bitfield continuation {} {} {:?}", *bitfield_width, width, layout); @@ -1562,7 +1563,10 @@ impl CodeGenerator for Enum { }; let signed = repr.is_signed(); - let size = layout.map(|l| l.size).unwrap_or(0); + let size = layout.map(|l| l.size) + .or_else(|| repr.known_size()) + .unwrap_or(0); + let repr_name = match (signed, size) { (true, 1) => "i8", (false, 1) => "u8", @@ -1617,7 +1621,8 @@ impl CodeGenerator for Enum { // Only to avoid recomputing every time. enum_canonical_name: &str, // May be the same as "variant" if it's because the - // enum is unnamed and we still haven't seen the value. + // enum is unnamed and we still haven't seen the + // value. variant_name: &str, referenced_name: &str, enum_rust_ty: P, @@ -2010,14 +2015,10 @@ impl CodeGenerator for Function { } let signature_item = ctx.resolve_item(self.signature()); - let signature = signature_item.kind().expect_type(); + let signature = signature_item.kind().expect_type().canonical_type(ctx); let signature = match *signature.kind() { TypeKind::Function(ref sig) => sig, - TypeKind::ResolvedTypeRef(ref item_id) => { - let item = ctx.resolve_item(*item_id); - return self.codegen(ctx, result, _whitelisted_items, item); - }, - _ => panic!("How?") + _ => panic!("Signature kind is not a Function: {:?}", signature), }; let fndecl = utils::rust_fndecl_from_signature(ctx, signature_item); @@ -2268,7 +2269,7 @@ mod utils { -> P { use codegen::ToRustTy; - let signature = sig.kind().expect_type(); + let signature = sig.kind().expect_type().canonical_type(ctx); let signature = match *signature.kind() { TypeKind::Function(ref sig) => sig, _ => panic!("How?"), diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs index ba8ffe8226..3ffe50c835 100644 --- a/libbindgen/src/ir/context.rs +++ b/libbindgen/src/ir/context.rs @@ -1135,7 +1135,8 @@ impl<'ctx, 'gen> Iterator for WhitelistedItemsIter<'ctx, 'gen> /// An iterator to find any dangling items. /// -/// See `BindgenContext::assert_no_dangling_item_traversal` for more information. +/// See `BindgenContext::assert_no_dangling_item_traversal` for more +/// information. pub struct AssertNoDanglingItemIter<'ctx, 'gen> where 'gen: 'ctx, { @@ -1152,8 +1153,8 @@ impl<'ctx, 'gen> Iterator for AssertNoDanglingItemIter<'ctx, 'gen> fn next(&mut self) -> Option { let id = match self.to_iterate.pop_front() { None => { - // We've traversed everything reachable from the previous root(s), see if - // we have any more roots. + // We've traversed everything reachable from the previous + // root(s), see if we have any more roots. match self.ctx .items() .filter(|&(id, _)| !self.seen.contains_key(id)) @@ -1177,8 +1178,10 @@ impl<'ctx, 'gen> Iterator for AssertNoDanglingItemIter<'ctx, 'gen> let mut path = vec![]; let mut current = id; loop { - let predecessor = *self.seen.get(¤t) - .expect("We know we found this item id, so it must have a predecessor"); + let predecessor = *self.seen + .get(¤t) + .expect("We know we found this item id, so it must have a \ + predecessor"); if predecessor == current { break; } diff --git a/libbindgen/src/ir/enum_ty.rs b/libbindgen/src/ir/enum_ty.rs index d7e4de099b..5c1ead4587 100644 --- a/libbindgen/src/ir/enum_ty.rs +++ b/libbindgen/src/ir/enum_ty.rs @@ -53,22 +53,18 @@ impl Enum { .and_then(|et| Item::from_ty(&et, None, None, ctx).ok()); let mut variants = vec![]; - let is_signed = match repr { - Some(repr) => { - let repr_type = ctx.resolve_type(repr); - match *repr_type.canonical_type(ctx).kind() { - TypeKind::Int(ref int_kind) => int_kind.is_signed(), - ref other => { - panic!("Since when enums can be non-integers? {:?}", + // Assume signedness since the default type by the C standard is an int. + let is_signed = + repr.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx)) + .map_or(true, |ty| { + match *ty.kind() { + TypeKind::Int(ref int_kind) => int_kind.is_signed(), + ref other => { + panic!("Since when enums can be non-integers? {:?}", other) + } } - } - } - // Assume signedness since the default type by the C - // standard is an - // int. - None => true, - }; + }); declaration.visit(|cursor| { if cursor.kind() == CXCursor_EnumConstantDecl { diff --git a/libbindgen/src/ir/int.rs b/libbindgen/src/ir/int.rs index 179ebb96ce..89068e0fab 100644 --- a/libbindgen/src/ir/int.rs +++ b/libbindgen/src/ir/int.rs @@ -91,6 +91,21 @@ impl IntKind { } } + /// If this type has a known size, return it (in bytes). This is to + /// alleviate libclang sometimes not giving us a layout (like in the case + /// when an enum is defined inside a class with template parameters). + pub fn known_size(&self) -> Option { + use self::IntKind::*; + Some(match *self { + Bool | UChar | Char | U8 | I8 => 1, + U16 | I16 => 2, + U32 | I32 => 4, + U64 | I64 => 8, + I128 | U128 => 16, + _ => return None, + }) + } + /// Whether this type's signedness matches the value. pub fn signedness_matches(&self, val: i64) -> bool { val >= 0 || self.is_signed() diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index b330291924..0d5e6ba2ad 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -696,7 +696,9 @@ impl Item { } ItemKind::Type(ref ty) => { let name = match *ty.kind() { - TypeKind::ResolvedTypeRef(..) => panic!("should have resolved this in name_target()"), + TypeKind::ResolvedTypeRef(..) => { + panic!("should have resolved this in name_target()") + } _ => ty.name(), }; name.map(ToOwned::to_owned) @@ -1075,7 +1077,7 @@ impl ClangItemParser for Item { } if let Some(ty) = - ctx.builtin_or_resolved_ty(id, parent_id, ty, location) { + ctx.builtin_or_resolved_ty(id, parent_id, ty, location) { return Ok(ty); } @@ -1093,9 +1095,10 @@ impl ClangItemParser for Item { }; if valid_decl { - if let Some(&(_, item_id)) = ctx.currently_parsed_types - .iter() - .find(|&&(d, _)| d == declaration_to_look_for) { + if let Some(&(_, item_id)) = + ctx.currently_parsed_types + .iter() + .find(|&&(d, _)| d == declaration_to_look_for) { debug!("Avoiding recursion parsing type: {:?}", ty); return Ok(item_id); } diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs index 1878471dc2..60092d5449 100644 --- a/libbindgen/src/ir/ty.rs +++ b/libbindgen/src/ir/ty.rs @@ -696,8 +696,8 @@ impl Type { let inner_type = match inner { Ok(inner) => inner, Err(..) => { - error!("Failed to parse template alias {:?}", - location); + error!("Failed to parse template alias \ + {:?}", location); return Err(ParseError::Continue); } }; diff --git a/libbindgen/src/lib.rs b/libbindgen/src/lib.rs index 473dcf2997..a74c1799e1 100644 --- a/libbindgen/src/lib.rs +++ b/libbindgen/src/lib.rs @@ -517,7 +517,8 @@ fn ensure_libclang_is_loaded() { // TODO(emilio): Return meaningful error (breaking). clang_sys::load().expect("Unable to find libclang"); *libclang = Some(clang_sys::get_library() - .expect("We just loaded libclang and it had better still be here!")); + .expect("We just loaded libclang and it had \ + better still be here!")); } else { clang_sys::set_library(libclang.clone()); } @@ -630,16 +631,16 @@ impl<'ctx> Bindings<'ctx> { /// /// See the `uses` module for more information. pub fn write_dummy_uses(&mut self) -> io::Result<()> { - let file = - if let Some(ref dummy_path) = self.context.options().dummy_uses { - Some(try!(OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(dummy_path))) - } else { - None - }; + let file = if let Some(ref dummy_path) = + self.context.options().dummy_uses { + Some(try!(OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(dummy_path))) + } else { + None + }; if let Some(file) = file { try!(uses::generate_dummy_uses(&mut self.context, file)); diff --git a/libbindgen/tests/expectations/tests/enum_in_template_with_typedef.rs b/libbindgen/tests/expectations/tests/enum_in_template_with_typedef.rs new file mode 100644 index 0000000000..66a304aa95 --- /dev/null +++ b/libbindgen/tests/expectations/tests/enum_in_template_with_typedef.rs @@ -0,0 +1,18 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct std_fbstring_core { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData, +} +pub type std_fbstring_core_category_type = u8; +pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category = + std_fbstring_core_Category::Foo; +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum std_fbstring_core_Category { Foo = 0, } diff --git a/libbindgen/tests/expectations/tests/resolved_type_def_function.rs b/libbindgen/tests/expectations/tests/resolved_type_def_function.rs index fb308fa47d..83f07dd0c8 100644 --- a/libbindgen/tests/expectations/tests/resolved_type_def_function.rs +++ b/libbindgen/tests/expectations/tests/resolved_type_def_function.rs @@ -5,3 +5,6 @@ pub type FuncType = ::std::option::Option; +extern "C" { + pub fn Func(); +} diff --git a/libbindgen/tests/headers/enum_in_template_with_typedef.hpp b/libbindgen/tests/headers/enum_in_template_with_typedef.hpp new file mode 100644 index 0000000000..ac19b7813c --- /dev/null +++ b/libbindgen/tests/headers/enum_in_template_with_typedef.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: -- -std=c++11 + +namespace std { + template class fbstring_core; +} + +typedef unsigned char uint8_t; +namespace std { + template class fbstring_core { + typedef uint8_t category_type; + enum Category : category_type { + Foo = 1, + Bar = 4, + }; + }; +} diff --git a/libbindgen/tests/tests.rs b/libbindgen/tests/tests.rs index 12816c1b0b..014308794f 100644 --- a/libbindgen/tests/tests.rs +++ b/libbindgen/tests/tests.rs @@ -43,7 +43,7 @@ fn compare_generated_header(header: &PathBuf, return Ok(()); } return Err(Error::new(ErrorKind::Other, - "Something's gone really wrong!")) + "Something's gone really wrong!")); } println!("diff expected generated"); @@ -79,10 +79,13 @@ fn create_bindgen_builder(header: &PathBuf) let line = try!(line); if line.contains("bindgen-flags: ") { let extra_flags = line.split("bindgen-flags: ") - .last().and_then(shlex::split).unwrap(); + .last() + .and_then(shlex::split) + .unwrap(); flags.extend(extra_flags.into_iter()); - } else if line.contains("bindgen-unstable") && cfg!(feature = "llvm_stable") { - return Ok(None) + } else if line.contains("bindgen-unstable") && + cfg!(feature = "llvm_stable") { + return Ok(None); } } @@ -94,13 +97,14 @@ fn create_bindgen_builder(header: &PathBuf) let header_str = try!(header.to_str() .ok_or(Error::new(ErrorKind::Other, "Invalid header file name"))); - let prepend = [ - "bindgen", - header_str, - "--raw-line", "", - "--raw-line", "#![allow(non_snake_case)]", - "--raw-line", "", - ]; + let prepend = ["bindgen", + header_str, + "--raw-line", + "", + "--raw-line", + "#![allow(non_snake_case)]", + "--raw-line", + ""]; let args = prepend.into_iter() .map(ToString::to_string)