Skip to content

Commit 36c087b

Browse files
author
bors-servo
authored
Auto merge of #1381 - emilio:integer-eval, r=nox
ir: Handle overflowing integer constant evaluation properly. Fixes #1380
2 parents 0db9588 + 2319708 commit 36c087b

16 files changed

+98
-22
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ readme = "README.md"
1414
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
1515
documentation = "https://docs.rs/bindgen"
1616
homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
17-
version = "0.39.0"
17+
version = "0.40.0"
1818
build = "build.rs"
1919

2020
include = [

src/clang.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::ffi::{CStr, CString};
1212
use std::fmt;
1313
use std::hash::Hash;
1414
use std::hash::Hasher;
15-
use std::os::raw::{c_char, c_int, c_uint, c_ulong};
15+
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_longlong, c_ulonglong};
1616

1717
/// A cursor into the Clang AST, pointing to an AST node.
1818
///
@@ -1786,13 +1786,34 @@ impl EvalResult {
17861786
}
17871787

17881788
/// Try to get back the result as an integer.
1789-
pub fn as_int(&self) -> Option<i32> {
1790-
match self.kind() {
1791-
CXEval_Int => {
1792-
Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32)
1789+
pub fn as_int(&self) -> Option<i64> {
1790+
if self.kind() != CXEval_Int {
1791+
return None;
1792+
}
1793+
1794+
if !clang_EvalResult_isUnsignedInt::is_loaded() {
1795+
// FIXME(emilio): There's no way to detect underflow here, and clang
1796+
// will just happily give us a value.
1797+
return Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i64)
1798+
}
1799+
1800+
if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
1801+
let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
1802+
if value > i64::max_value() as c_ulonglong {
1803+
return None;
17931804
}
1794-
_ => None,
1805+
1806+
return Some(value as i64)
1807+
}
1808+
1809+
let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
1810+
if value > i64::max_value() as c_longlong {
1811+
return None;
1812+
}
1813+
if value < i64::min_value() as c_longlong {
1814+
return None;
17951815
}
1816+
Some(value as i64)
17961817
}
17971818

17981819
/// Evaluates the expression as a literal string, that may or may not be

src/ir/var.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,7 @@ impl ClangSubItemParser for Var {
265265

266266
let mut val = cursor
267267
.evaluate()
268-
.and_then(|v| v.as_int())
269-
.map(|val| val as i64);
268+
.and_then(|v| v.as_int());
270269
if val.is_none() || !kind.signedness_matches(val.unwrap()) {
271270
let tu = ctx.translation_unit();
272271
val = get_integer_literal_from_cursor(&cursor, tu);

tests/expectations/tests/derive-debug-bitfield-core.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
non_upper_case_globals
88
)]
99

10+
extern crate core;
11+
1012
#[repr(C)]
1113
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
1214
pub struct __BindgenBitfieldUnit<Storage, Align>

tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs

Lines changed: 0 additions & 7 deletions
This file was deleted.

tests/expectations/tests/libclang-3.8/constant-evaluate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ extern "C" {
1515
#[link_name = "\u{1}k_expr"]
1616
pub static mut k_expr: EasyToOverflow;
1717
}
18+
extern "C" {
19+
#[link_name = "\u{1}wow"]
20+
pub static mut wow: EasyToOverflow;
21+
}
1822
extern "C" {
1923
#[link_name = "\u{1}BAZ"]
2024
pub static mut BAZ: ::std::os::raw::c_longlong;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
10+
pub const a: u32 = 18446744073709551611;

tests/expectations/tests/libclang-3.9/constant-evaluate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ pub enum _bindgen_ty_1 {
1515
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
1616
pub const k: EasyToOverflow = 2147483648;
1717
pub const k_expr: EasyToOverflow = 0;
18+
extern "C" {
19+
#[link_name = "\u{1}wow"]
20+
pub static mut wow: EasyToOverflow;
21+
}
1822
pub const BAZ: ::std::os::raw::c_longlong = 24;
1923
pub const fuzz: f64 = 51.0;
2024
pub const BAZZ: ::std::os::raw::c_char = 53;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
10+
pub const a: u32 = 18446744073709551611;

tests/expectations/tests/libclang-4/constant-evaluate.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/* automatically generated by rust-bindgen */
22

3-
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
49

510
pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
611
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
@@ -12,7 +17,8 @@ pub enum _bindgen_ty_1 {
1217
}
1318
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
1419
pub const k: EasyToOverflow = 2147483648;
15-
pub const k_expr: EasyToOverflow = 0;
20+
pub const k_expr: EasyToOverflow = 1152921504606846976;
21+
pub const wow: EasyToOverflow = 2147483648;
1622
pub const BAZ: ::std::os::raw::c_longlong = 24;
1723
pub const fuzz: f64 = 51.0;
1824
pub const BAZZ: ::std::os::raw::c_char = 53;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
10+
pub const a: u32 = 4294967291;

tests/expectations/tests/libclang-5/constant-evaluate.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
/* automatically generated by rust-bindgen */
22

3-
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
49

510
pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
611
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
@@ -12,7 +17,8 @@ pub enum _bindgen_ty_1 {
1217
}
1318
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
1419
pub const k: EasyToOverflow = 2147483648;
15-
pub const k_expr: EasyToOverflow = 0;
20+
pub const k_expr: EasyToOverflow = 1152921504606846976;
21+
pub const wow: EasyToOverflow = 2147483648;
1622
pub const BAZ: ::std::os::raw::c_longlong = 24;
1723
pub const fuzz: f64 = 51.0;
1824
pub const BAZZ: ::std::os::raw::c_char = 53;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
10+
pub const a: u32 = 4294967291;

tests/headers/constant-evaluate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ typedef unsigned long long EasyToOverflow;
1010
const EasyToOverflow k = 0x80000000;
1111

1212
const EasyToOverflow k_expr = 1ULL << 60;
13+
const EasyToOverflow wow = 1ULL << 31;
1314

1415
const long long BAZ = (1 << foo) | bar;
1516
const double fuzz = (1 + 50.0f);

tests/headers/derive-debug-bitfield-core.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug --use-core
1+
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;"
22

33
class C {
44
bool a: 1;

0 commit comments

Comments
 (0)