diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs index 811d87c5ad..608f3f9e0e 100644 --- a/src/codegen/helpers.rs +++ b/src/codegen/helpers.rs @@ -158,17 +158,38 @@ pub mod ast_ty { .build_lit(aster::AstBuilder::new().lit().byte_str(string)) } - pub fn float_expr(f: f64) -> P { + pub fn float_expr(ctx: &BindgenContext, + f: f64) + -> Result, ()> { use aster::symbol::ToSymbol; - let mut string = f.to_string(); - // So it gets properly recognised as a floating point constant. - if !string.contains('.') { - string.push('.'); + if f.is_finite() { + let mut string = f.to_string(); + + // So it gets properly recognised as a floating point constant. + if !string.contains('.') { + string.push('.'); + } + + let kind = ast::LitKind::FloatUnsuffixed(string.as_str().to_symbol()); + return Ok(aster::AstBuilder::new().expr().lit().build_lit(kind)) + } + + let prefix = ctx.trait_prefix(); + if f.is_nan() { + return Ok(quote_expr!(ctx.ext_cx(), ::$prefix::f64::NAN)); + } + + if f.is_infinite() { + return Ok(if f.is_sign_positive() { + quote_expr!(ctx.ext_cx(), ::$prefix::f64::INFINITY) + } else { + quote_expr!(ctx.ext_cx(), ::$prefix::f64::NEG_INFINITY) + }); } - let kind = ast::LitKind::FloatUnsuffixed(string.as_str().to_symbol()); - aster::AstBuilder::new().expr().lit().build_lit(kind) + warn!("Unknown non-finite float number: {:?}", f); + return Err(()); } pub fn arguments_from_signature(signature: &FunctionSig, diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 2e404a5c73..1776914430 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -470,8 +470,12 @@ impl CodeGenerator for Var { } } VarType::Float(f) => { - const_item.build(helpers::ast_ty::float_expr(f)) - .build(ty) + match helpers::ast_ty::float_expr(ctx, f) { + Ok(expr) => { + const_item.build(expr).build(ty) + } + Err(..) => return, + } } VarType::Char(c) => { const_item @@ -2419,7 +2423,7 @@ impl ToRustTy for TemplateInstantiation { .map(|(arg, _)| arg.to_rust_ty(ctx)) .collect::>(); - path.segments.last_mut().unwrap().parameters = if + path.segments.last_mut().unwrap().parameters = if template_args.is_empty() { None } else { diff --git a/src/ir/var.rs b/src/ir/var.rs index 350bfe4ae7..2e56e9f53c 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -146,7 +146,7 @@ impl ClangSubItemParser for Var { let (type_kind, val) = match value { EvalResult::Invalid => return Err(ParseError::Continue), EvalResult::Float(f) => { - (TypeKind::Float(FloatKind::Float), VarType::Float(f)) + (TypeKind::Float(FloatKind::Double), VarType::Float(f)) } EvalResult::Char(c) => { let c = match c { @@ -178,9 +178,7 @@ impl ClangSubItemParser for Var { } else { IntKind::Int } - } else if value > - u32::max_value() as - i64 { + } else if value > u32::max_value() as i64 { IntKind::ULongLong } else { IntKind::UInt diff --git a/tests/expectations/tests/infinite-macro.rs b/tests/expectations/tests/infinite-macro.rs new file mode 100644 index 0000000000..4f74bf903c --- /dev/null +++ b/tests/expectations/tests/infinite-macro.rs @@ -0,0 +1,8 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const INFINITY: f64 = ::std::f64::INFINITY; +pub const NAN: f64 = ::std::f64::NAN; diff --git a/tests/expectations/tests/macro_const.rs b/tests/expectations/tests/macro_const.rs index 9e7eb420ed..383cedc788 100644 --- a/tests/expectations/tests/macro_const.rs +++ b/tests/expectations/tests/macro_const.rs @@ -7,6 +7,6 @@ pub const foo: &'static [u8; 4usize] = b"bar\x00"; pub const CHAR: u8 = b'b'; pub const CHARR: u8 = b'\x00'; -pub const FLOAT: f32 = 5.09; -pub const FLOAT_EXPR: f32 = 0.005; +pub const FLOAT: f64 = 5.09; +pub const FLOAT_EXPR: f64 = 0.005; pub const INVALID_UTF8: [u8; 5usize] = [240, 40, 140, 40, 0]; diff --git a/tests/headers/infinite-macro.h b/tests/headers/infinite-macro.h new file mode 100644 index 0000000000..ab352c5785 --- /dev/null +++ b/tests/headers/infinite-macro.h @@ -0,0 +1,2 @@ +#define INFINITY (1.0f/0.0f) +#define NAN (0.0f/0.0f)