Skip to content

Commit

Permalink
Auto merge of #1381 - emilio:integer-eval, r=nox
Browse files Browse the repository at this point in the history
ir: Handle overflowing integer constant evaluation properly.

Fixes #1380
  • Loading branch information
bors-servo authored Sep 4, 2018
2 parents 0db9588 + 2319708 commit 36c087b
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ readme = "README.md"
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
documentation = "https://docs.rs/bindgen"
homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
version = "0.39.0"
version = "0.40.0"
build = "build.rs"

include = [
Expand Down
33 changes: 27 additions & 6 deletions src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::ffi::{CStr, CString};
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::os::raw::{c_char, c_int, c_uint, c_ulong};
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_longlong, c_ulonglong};

/// A cursor into the Clang AST, pointing to an AST node.
///
Expand Down Expand Up @@ -1786,13 +1786,34 @@ impl EvalResult {
}

/// Try to get back the result as an integer.
pub fn as_int(&self) -> Option<i32> {
match self.kind() {
CXEval_Int => {
Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32)
pub fn as_int(&self) -> Option<i64> {
if self.kind() != CXEval_Int {
return None;
}

if !clang_EvalResult_isUnsignedInt::is_loaded() {
// FIXME(emilio): There's no way to detect underflow here, and clang
// will just happily give us a value.
return Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i64)
}

if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
if value > i64::max_value() as c_ulonglong {
return None;
}
_ => None,

return Some(value as i64)
}

let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
if value > i64::max_value() as c_longlong {
return None;
}
if value < i64::min_value() as c_longlong {
return None;
}
Some(value as i64)
}

/// Evaluates the expression as a literal string, that may or may not be
Expand Down
3 changes: 1 addition & 2 deletions src/ir/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,7 @@ impl ClangSubItemParser for Var {

let mut val = cursor
.evaluate()
.and_then(|v| v.as_int())
.map(|val| val as i64);
.and_then(|v| v.as_int());
if val.is_none() || !kind.signedness_matches(val.unwrap()) {
let tu = ctx.translation_unit();
val = get_integer_literal_from_cursor(&cursor, tu);
Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/tests/derive-debug-bitfield-core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
non_upper_case_globals
)]

extern crate core;

#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align>
Expand Down

This file was deleted.

4 changes: 4 additions & 0 deletions tests/expectations/tests/libclang-3.8/constant-evaluate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ extern "C" {
#[link_name = "\u{1}k_expr"]
pub static mut k_expr: EasyToOverflow;
}
extern "C" {
#[link_name = "\u{1}wow"]
pub static mut wow: EasyToOverflow;
}
extern "C" {
#[link_name = "\u{1}BAZ"]
pub static mut BAZ: ::std::os::raw::c_longlong;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* automatically generated by rust-bindgen */

#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const a: u32 = 18446744073709551611;
4 changes: 4 additions & 0 deletions tests/expectations/tests/libclang-3.9/constant-evaluate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub enum _bindgen_ty_1 {
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
pub const k: EasyToOverflow = 2147483648;
pub const k_expr: EasyToOverflow = 0;
extern "C" {
#[link_name = "\u{1}wow"]
pub static mut wow: EasyToOverflow;
}
pub const BAZ: ::std::os::raw::c_longlong = 24;
pub const fuzz: f64 = 51.0;
pub const BAZZ: ::std::os::raw::c_char = 53;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* automatically generated by rust-bindgen */

#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const a: u32 = 18446744073709551611;
10 changes: 8 additions & 2 deletions tests/expectations/tests/libclang-4/constant-evaluate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
Expand All @@ -12,7 +17,8 @@ pub enum _bindgen_ty_1 {
}
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
pub const k: EasyToOverflow = 2147483648;
pub const k_expr: EasyToOverflow = 0;
pub const k_expr: EasyToOverflow = 1152921504606846976;
pub const wow: EasyToOverflow = 2147483648;
pub const BAZ: ::std::os::raw::c_longlong = 24;
pub const fuzz: f64 = 51.0;
pub const BAZZ: ::std::os::raw::c_char = 53;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* automatically generated by rust-bindgen */

#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const a: u32 = 4294967291;
10 changes: 8 additions & 2 deletions tests/expectations/tests/libclang-5/constant-evaluate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
Expand All @@ -12,7 +17,8 @@ pub enum _bindgen_ty_1 {
}
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
pub const k: EasyToOverflow = 2147483648;
pub const k_expr: EasyToOverflow = 0;
pub const k_expr: EasyToOverflow = 1152921504606846976;
pub const wow: EasyToOverflow = 2147483648;
pub const BAZ: ::std::os::raw::c_longlong = 24;
pub const fuzz: f64 = 51.0;
pub const BAZZ: ::std::os::raw::c_char = 53;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* automatically generated by rust-bindgen */

#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const a: u32 = 4294967291;
1 change: 1 addition & 0 deletions tests/headers/constant-evaluate.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef unsigned long long EasyToOverflow;
const EasyToOverflow k = 0x80000000;

const EasyToOverflow k_expr = 1ULL << 60;
const EasyToOverflow wow = 1ULL << 31;

const long long BAZ = (1 << foo) | bar;
const double fuzz = (1 + 50.0f);
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-bitfield-core.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug --use-core
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;"

class C {
bool a: 1;
Expand Down

0 comments on commit 36c087b

Please sign in to comment.