ir: Add support for negative enum discriminants.

Pretty straight-forward, but it bit me today :)
This commit is contained in:
Emilio Cobos Álvarez
2018-11-24 19:11:02 +01:00
committed by Ryan Hunt
parent 68246af8e8
commit e08fb32d74
6 changed files with 68 additions and 18 deletions
+28 -14
View File
@@ -24,11 +24,31 @@ use bindgen::writer::{ListType, Source, SourceWriter};
pub struct EnumVariant {
pub name: String,
pub export_name: String,
pub discriminant: Option<u64>,
pub discriminant: Option<i64>,
pub body: Option<(String, Struct)>,
pub documentation: Documentation,
}
fn value_from_expr(val: &syn::Expr) -> Option<i64> {
match *val {
syn::Expr::Lit(ref lit) => match lit.lit {
syn::Lit::Int(ref lit) if lit.value() <= ::std::i64::MAX as u64 => {
Some(lit.value() as i64)
}
_ => None,
},
syn::Expr::Unary(ref unary) => {
let v = value_from_expr(&unary.expr)?;
match unary.op {
syn::UnOp::Deref(..) => None,
syn::UnOp::Neg(..) => v.checked_mul(-1),
syn::UnOp::Not(..) => v.checked_neg(),
}
}
_ => None,
}
}
impl EnumVariant {
pub fn load(
is_tagged: bool,
@@ -36,18 +56,12 @@ impl EnumVariant {
generic_params: GenericParams,
mod_cfg: &Option<Cfg>,
) -> Result<Self, String> {
let discriminant = match &variant.discriminant {
&Some((
_,
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Int(ref lit),
..
}),
)) => Some(lit.value()),
&Some(_) => {
return Err("Unsupported discriminant.".to_owned());
}
&None => None,
let discriminant = match variant.discriminant {
Some((_, ref expr)) => match value_from_expr(expr) {
Some(v) => Some(v),
None => return Err(format!("Unsupported discriminant {:?}.", expr)),
},
None => None,
};
fn parse_fields(
@@ -132,7 +146,7 @@ impl EnumVariant {
pub fn new(
name: String,
discriminant: Option<u64>,
discriminant: Option<i64>,
body: Option<(String, Struct)>,
documentation: Documentation,
) -> Self {
+8 -1
View File
@@ -49,6 +49,13 @@ typedef enum K {
k4,
} K;
enum L {
l1 = -1,
l2 = 0,
l3 = 1,
};
typedef int8_t L;
typedef struct I I;
typedef struct J J;
@@ -126,4 +133,4 @@ typedef struct H {
};
} H;
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
+8 -1
View File
@@ -49,6 +49,13 @@ typedef enum {
k4,
} K;
enum L {
l1 = -1,
l2 = 0,
l3 = 1,
};
typedef int8_t L;
typedef struct I I;
typedef struct J J;
@@ -126,4 +133,4 @@ typedef struct {
};
} H;
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
+7 -1
View File
@@ -43,6 +43,12 @@ enum class K {
k4,
};
enum class L : int8_t {
l1 = -1,
l2 = 0,
l3 = 1,
};
struct I;
struct J;
@@ -122,6 +128,6 @@ struct H {
extern "C" {
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
} // extern "C"
+9 -1
View File
@@ -49,6 +49,13 @@ enum K {
k4,
};
enum L {
l1 = -1,
l2 = 0,
l3 = 1,
};
typedef int8_t L;
struct I;
struct J;
@@ -137,4 +144,5 @@ void root(struct Opaque *o,
struct H h,
struct I i,
struct J j,
enum K k);
enum K k,
L l);
+8
View File
@@ -88,6 +88,13 @@ enum K {
k4,
}
#[repr(i8)]
enum L {
l1 = -1,
l2 = 0,
l3 = 1,
}
#[no_mangle]
pub extern "C" fn root(
o: *mut Opaque,
@@ -102,4 +109,5 @@ pub extern "C" fn root(
i: I,
j: J,
k: K,
l: L,
) { }