Skip to content

Commit ecf1657

Browse files
committed
ir: Be more resistent to failure when parsing enums.
1 parent 3fbb4fa commit ecf1657

File tree

5 files changed

+60
-11
lines changed

5 files changed

+60
-11
lines changed

libbindgen/src/codegen/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,11 @@ impl CodeGenerator for Enum {
15621562
};
15631563

15641564
let signed = repr.is_signed();
1565-
let size = layout.map(|l| l.size).unwrap_or(0);
1565+
let size = layout
1566+
.map(|l| l.size)
1567+
.or_else(|| repr.known_size())
1568+
.unwrap_or(0);
1569+
15661570
let repr_name = match (signed, size) {
15671571
(true, 1) => "i8",
15681572
(false, 1) => "u8",

libbindgen/src/ir/enum_ty.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,18 @@ impl Enum {
5353
.and_then(|et| Item::from_ty(&et, None, None, ctx).ok());
5454
let mut variants = vec![];
5555

56-
let is_signed = match repr {
57-
Some(repr) => {
58-
let repr_type = ctx.resolve_type(repr);
59-
match *repr_type.canonical_type(ctx).kind() {
56+
// Assume signedness since the default type by the C standard is an int.
57+
let is_signed = repr
58+
.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx))
59+
.map_or(true, |ty| {
60+
match *ty.kind() {
6061
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
6162
ref other => {
6263
panic!("Since when enums can be non-integers? {:?}",
6364
other)
6465
}
6566
}
66-
}
67-
// Assume signedness since the default type by the C
68-
// standard is an
69-
// int.
70-
None => true,
71-
};
67+
});
7268

7369
declaration.visit(|cursor| {
7470
if cursor.kind() == CXCursor_EnumConstantDecl {

libbindgen/src/ir/int.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,21 @@ impl IntKind {
9191
}
9292
}
9393

94+
/// If this type has a known size, return it (in bytes). This is to
95+
/// alleviate libclang sometimes not giving us a layout (like in the case
96+
/// when an enum is defined inside a class with template parameters).
97+
pub fn known_size(&self) -> Option<usize> {
98+
use self::IntKind::*;
99+
Some(match *self {
100+
Bool | UChar | Char | U8 | I8 => 1,
101+
U16 | I16 => 2,
102+
U32 | I32 => 4,
103+
U64 | I64 => 8,
104+
I128 | U128 => 16,
105+
_ => return None,
106+
})
107+
}
108+
94109
/// Whether this type's signedness matches the value.
95110
pub fn signedness_matches(&self, val: i64) -> bool {
96111
val >= 0 || self.is_signed()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Copy, Clone)]
9+
pub struct std_fbstring_core<Char> {
10+
pub _address: u8,
11+
pub _phantom_0: ::std::marker::PhantomData<Char>,
12+
}
13+
pub type std_fbstring_core_category_type = u8;
14+
pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
15+
std_fbstring_core_Category::Foo;
16+
#[repr(u8)]
17+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
18+
pub enum std_fbstring_core_Category { Foo = 0, }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// bindgen-flags: -- -std=c++11
2+
3+
namespace std {
4+
template <typename Char> class fbstring_core;
5+
}
6+
7+
typedef unsigned char uint8_t;
8+
namespace std {
9+
template <typename Char> class fbstring_core {
10+
typedef uint8_t category_type;
11+
enum Category : category_type {
12+
Foo = 1,
13+
Bar = 4,
14+
};
15+
};
16+
}

0 commit comments

Comments
 (0)