Skip to content

Commit 5317392

Browse files
author
bors-servo
authored
Auto merge of #276 - emilio:vartype-fixes, r=fitzgen
ir: Avoid generating out-of-range values in constants. Partially addresses #274 until my patch or a similar one gets accepted and we can use it. r? @fitzgen or @upsuper
2 parents 3761ada + 06e5f6c commit 5317392

File tree

7 files changed

+42
-19
lines changed

7 files changed

+42
-19
lines changed

libbindgen/src/codegen/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ impl CodeGenerator for Item {
228228
result: &mut CodegenResult,
229229
_extra: &()) {
230230
if self.is_hidden(ctx) || result.seen(self.id()) {
231-
debug!("<Item as CodeGenerator>::codegen: Ignoring hidden or seen: self = {:?}", self);
231+
debug!("<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \
232+
self = {:?}", self);
232233
return;
233234
}
234235

@@ -328,8 +329,7 @@ impl CodeGenerator for Var {
328329
.build(ty)
329330
}
330331
VarType::Int(val) => {
331-
const_item.build(helpers::ast_ty::int_expr(val))
332-
.build(ty)
332+
const_item.build(helpers::ast_ty::int_expr(val)).build(ty)
333333
}
334334
VarType::String(ref bytes) => {
335335
// Account the trailing zero.

libbindgen/src/ir/int.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,9 @@ impl IntKind {
9090
Custom { is_signed, .. } => is_signed,
9191
}
9292
}
93+
94+
/// Whether this type's signedness matches the value.
95+
pub fn signedness_matches(&self, val: i64) -> bool {
96+
val >= 0 || self.is_signed()
97+
}
9398
}

libbindgen/src/ir/item.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,8 @@ impl ClangItemParser for Item {
10321032
// It's harmless, but if we restrict that, then
10331033
// tests/headers/nsStyleAutoArray.hpp crashes.
10341034
if let Err(ParseError::Recurse) = result {
1035-
warn!("Unknown type, assuming named template type: id = {:?}; spelling = {}",
1035+
warn!("Unknown type, assuming named template type: \
1036+
id = {:?}; spelling = {}",
10361037
id,
10371038
ty.spelling());
10381039
Ok(Self::named_type_with_id(id,

libbindgen/src/ir/ty.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,9 @@ impl TypeCollector for Type {
878878
}
879879
// FIXME: Pending types!
880880
ref other @ _ => {
881-
debug!("<Type as TypeCollector>::collect_types: Ignoring: {:?}", other);
881+
debug!("<Type as TypeCollector>::collect_types: Ignoring: \
882+
{:?}",
883+
other);
882884
}
883885
}
884886
}

libbindgen/src/ir/var.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use super::ty::{FloatKind, TypeKind};
1313
/// The type for a constant variable.
1414
#[derive(Debug)]
1515
pub enum VarType {
16-
/// An boolean.
16+
/// A boolean.
1717
Bool(bool),
1818
/// An integer.
1919
Int(i64),
@@ -196,26 +196,33 @@ impl ClangSubItemParser for Var {
196196
let canonical_ty = ctx.safe_resolve_type(ty)
197197
.and_then(|t| t.safe_canonical_type(ctx));
198198

199-
let is_bool = canonical_ty.map_or(false, |t| t.is_bool());
200199
let is_integer = canonical_ty.map_or(false, |t| t.is_integer());
201200
let is_float = canonical_ty.map_or(false, |t| t.is_float());
202201

203202
// TODO: We could handle `char` more gracefully.
204203
// TODO: Strings, though the lookup is a bit more hard (we need
205204
// to look at the canonical type of the pointee too, and check
206205
// is char, u8, or i8 I guess).
207-
let value = if is_bool {
208-
cursor.evaluate().as_int()
209-
.map(|val| VarType::Bool(val != 0))
210-
} else if is_integer {
211-
cursor.evaluate()
212-
.as_int()
213-
.map(|val| val as i64)
214-
.or_else(|| {
215-
let tu = ctx.translation_unit();
216-
get_integer_literal_from_cursor(&cursor, tu)
217-
})
218-
.map(VarType::Int)
206+
let value = if is_integer {
207+
let kind = match *canonical_ty.unwrap().kind() {
208+
TypeKind::Int(kind) => kind,
209+
_ => unreachable!(),
210+
};
211+
212+
let mut val =
213+
cursor.evaluate().as_int().map(|val| val as i64);
214+
if val.is_none() || !kind.signedness_matches(val.unwrap()) {
215+
let tu = ctx.translation_unit();
216+
val = get_integer_literal_from_cursor(&cursor, tu);
217+
}
218+
219+
val.map(|val| {
220+
if kind == IntKind::Bool {
221+
VarType::Bool(val != 0)
222+
} else {
223+
VarType::Int(val)
224+
}
225+
})
219226
} else if is_float {
220227
cursor.evaluate()
221228
.as_double()

libbindgen/tests/expectations/tests/constant-evaluate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
99
#[repr(u32)]
1010
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1111
pub enum _bindgen_ty_1 { foo = 4, bar = 8, }
12+
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
13+
pub const k: EasyToOverflow = 2147483648;
14+
pub const k_expr: EasyToOverflow = 0;
1215
pub const BAZ: ::std::os::raw::c_longlong = 24;
1316
pub const fuzz: f64 = 51.;
1417
pub const BAZZ: ::std::os::raw::c_char = 53;

libbindgen/tests/headers/constant-evaluate.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ enum {
55
bar = 8,
66
};
77

8+
typedef unsigned long long EasyToOverflow;
9+
const EasyToOverflow k = 0x80000000;
10+
11+
const EasyToOverflow k_expr = 1ULL << 60;
12+
813
const long long BAZ = (1 << foo) | bar;
914
const double fuzz = (1 + 50.0f);
1015
const char BAZZ = '5';

0 commit comments

Comments
 (0)