summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbindgen/src/codegen/mod.rs6
-rw-r--r--libbindgen/src/ir/enum_ty.rs16
-rw-r--r--libbindgen/src/ir/int.rs15
-rw-r--r--libbindgen/tests/expectations/tests/enum_in_template_with_typedef.rs18
-rw-r--r--libbindgen/tests/headers/enum_in_template_with_typedef.hpp16
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,
+ };
+ };
+}