diff options
-rw-r--r-- | libbindgen/src/codegen/mod.rs | 6 | ||||
-rw-r--r-- | libbindgen/src/ir/enum_ty.rs | 16 | ||||
-rw-r--r-- | libbindgen/src/ir/int.rs | 15 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/enum_in_template_with_typedef.rs | 18 | ||||
-rw-r--r-- | libbindgen/tests/headers/enum_in_template_with_typedef.hpp | 16 |
5 files changed, 60 insertions, 11 deletions
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index e9141b9c..6213a068 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -1562,7 +1562,11 @@ 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", diff --git a/libbindgen/src/ir/enum_ty.rs b/libbindgen/src/ir/enum_ty.rs index d7e4de09..b65d3c06 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() { + // 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 179ebb96..89068e0f 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<usize> { + 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/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 00000000..66a304aa --- /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<Char> { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData<Char>, +} +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/headers/enum_in_template_with_typedef.hpp b/libbindgen/tests/headers/enum_in_template_with_typedef.hpp new file mode 100644 index 00000000..ac19b781 --- /dev/null +++ b/libbindgen/tests/headers/enum_in_template_with_typedef.hpp @@ -0,0 +1,16 @@ +// bindgen-flags: -- -std=c++11 + +namespace std { + template <typename Char> class fbstring_core; +} + +typedef unsigned char uint8_t; +namespace std { + template <typename Char> class fbstring_core { + typedef uint8_t category_type; + enum Category : category_type { + Foo = 1, + Bar = 4, + }; + }; +} |