diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index f15b92d15e..5a54c113ef 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -228,7 +228,8 @@ impl CodeGenerator for Item { result: &mut CodegenResult, _extra: &()) { if self.is_hidden(ctx) || result.seen(self.id()) { - debug!("::codegen: Ignoring hidden or seen: self = {:?}", self); + debug!("::codegen: Ignoring hidden or seen: \ + self = {:?}", self); return; } @@ -328,8 +329,7 @@ impl CodeGenerator for Var { .build(ty) } VarType::Int(val) => { - const_item.build(helpers::ast_ty::int_expr(val)) - .build(ty) + const_item.build(helpers::ast_ty::int_expr(val)).build(ty) } VarType::String(ref bytes) => { // Account the trailing zero. diff --git a/libbindgen/src/ir/int.rs b/libbindgen/src/ir/int.rs index 2d85db8385..179ebb96ce 100644 --- a/libbindgen/src/ir/int.rs +++ b/libbindgen/src/ir/int.rs @@ -90,4 +90,9 @@ impl IntKind { Custom { is_signed, .. } => is_signed, } } + + /// 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/src/ir/item.rs b/libbindgen/src/ir/item.rs index 253db8c005..f464ce4a35 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -1032,7 +1032,8 @@ impl ClangItemParser for Item { // It's harmless, but if we restrict that, then // tests/headers/nsStyleAutoArray.hpp crashes. if let Err(ParseError::Recurse) = result { - warn!("Unknown type, assuming named template type: id = {:?}; spelling = {}", + warn!("Unknown type, assuming named template type: \ + id = {:?}; spelling = {}", id, ty.spelling()); Ok(Self::named_type_with_id(id, diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs index b87dd11bc2..60611b8d9f 100644 --- a/libbindgen/src/ir/ty.rs +++ b/libbindgen/src/ir/ty.rs @@ -878,7 +878,9 @@ impl TypeCollector for Type { } // FIXME: Pending types! ref other @ _ => { - debug!("::collect_types: Ignoring: {:?}", other); + debug!("::collect_types: Ignoring: \ + {:?}", + other); } } } diff --git a/libbindgen/src/ir/var.rs b/libbindgen/src/ir/var.rs index 98b94da313..bbaea93953 100644 --- a/libbindgen/src/ir/var.rs +++ b/libbindgen/src/ir/var.rs @@ -13,7 +13,7 @@ use super::ty::{FloatKind, TypeKind}; /// The type for a constant variable. #[derive(Debug)] pub enum VarType { - /// An boolean. + /// A boolean. Bool(bool), /// An integer. Int(i64), @@ -196,7 +196,6 @@ impl ClangSubItemParser for Var { let canonical_ty = ctx.safe_resolve_type(ty) .and_then(|t| t.safe_canonical_type(ctx)); - let is_bool = canonical_ty.map_or(false, |t| t.is_bool()); let is_integer = canonical_ty.map_or(false, |t| t.is_integer()); let is_float = canonical_ty.map_or(false, |t| t.is_float()); @@ -204,18 +203,26 @@ impl ClangSubItemParser for Var { // TODO: Strings, though the lookup is a bit more hard (we need // to look at the canonical type of the pointee too, and check // is char, u8, or i8 I guess). - let value = if is_bool { - cursor.evaluate().as_int() - .map(|val| VarType::Bool(val != 0)) - } else if is_integer { - cursor.evaluate() - .as_int() - .map(|val| val as i64) - .or_else(|| { - let tu = ctx.translation_unit(); - get_integer_literal_from_cursor(&cursor, tu) - }) - .map(VarType::Int) + let value = if is_integer { + let kind = match *canonical_ty.unwrap().kind() { + TypeKind::Int(kind) => kind, + _ => unreachable!(), + }; + + let mut val = + cursor.evaluate().as_int().map(|val| val as i64); + if val.is_none() || !kind.signedness_matches(val.unwrap()) { + let tu = ctx.translation_unit(); + val = get_integer_literal_from_cursor(&cursor, tu); + } + + val.map(|val| { + if kind == IntKind::Bool { + VarType::Bool(val != 0) + } else { + VarType::Int(val) + } + }) } else if is_float { cursor.evaluate() .as_double() diff --git a/libbindgen/tests/expectations/tests/constant-evaluate.rs b/libbindgen/tests/expectations/tests/constant-evaluate.rs index 27b8d8296c..6947be982b 100644 --- a/libbindgen/tests/expectations/tests/constant-evaluate.rs +++ b/libbindgen/tests/expectations/tests/constant-evaluate.rs @@ -9,6 +9,9 @@ pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum _bindgen_ty_1 { foo = 4, bar = 8, } +pub type EasyToOverflow = ::std::os::raw::c_ulonglong; +pub const k: EasyToOverflow = 2147483648; +pub const k_expr: EasyToOverflow = 0; pub const BAZ: ::std::os::raw::c_longlong = 24; pub const fuzz: f64 = 51.; pub const BAZZ: ::std::os::raw::c_char = 53; diff --git a/libbindgen/tests/headers/constant-evaluate.h b/libbindgen/tests/headers/constant-evaluate.h index 2790d603c1..b6a0492f17 100644 --- a/libbindgen/tests/headers/constant-evaluate.h +++ b/libbindgen/tests/headers/constant-evaluate.h @@ -5,6 +5,11 @@ enum { bar = 8, }; +typedef unsigned long long EasyToOverflow; +const EasyToOverflow k = 0x80000000; + +const EasyToOverflow k_expr = 1ULL << 60; + const long long BAZ = (1 << foo) | bar; const double fuzz = (1 + 50.0f); const char BAZZ = '5';