diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-09-04 08:26:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-04 08:26:52 -0400 |
commit | 36c087bb4a22ae37d96a7a711293f5ee2d98015f (patch) | |
tree | e393ffaf062cc1c62becfe0053aeb37e62fa58d9 | |
parent | 0db9588e84463c211340f0bc2cb6da2b3a99c441 (diff) | |
parent | 2319708814878e7b102b5223fa762e0f464a3f96 (diff) |
Auto merge of #1381 - emilio:integer-eval, r=noxv0.40.0
ir: Handle overflowing integer constant evaluation properly.
Fixes #1380
16 files changed, 98 insertions, 22 deletions
@@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.39.0" +version = "0.40.0" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -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 = [ diff --git a/src/clang.rs b/src/clang.rs index bac29ee3..78bbd07c 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -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. /// @@ -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 diff --git a/src/ir/var.rs b/src/ir/var.rs index 25ac56d2..78455c9b 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -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); diff --git a/tests/expectations/tests/derive-debug-bitfield-core.rs b/tests/expectations/tests/derive-debug-bitfield-core.rs index 11522bcb..8c47fce0 100644 --- a/tests/expectations/tests/derive-debug-bitfield-core.rs +++ b/tests/expectations/tests/derive-debug-bitfield-core.rs @@ -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> diff --git a/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs deleted file mode 100644 index 9613a7f2..00000000 --- a/tests/expectations/tests/error-E0600-cannot-apply-unary-negation-to-u32.rs +++ /dev/null @@ -1,7 +0,0 @@ -/* automatically generated by rust-bindgen */ - - -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - - -pub const a: u32 = 18446744073709551611; diff --git a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs b/tests/expectations/tests/libclang-3.8/constant-evaluate.rs index 8faddfe9..7df4e918 100644 --- a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs +++ b/tests/expectations/tests/libclang-3.8/constant-evaluate.rs @@ -16,6 +16,10 @@ extern "C" { 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; } diff --git a/tests/expectations/tests/libclang-3.8/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/libclang-3.8/error-E0600-cannot-apply-unary-negation-to-u32.rs new file mode 100644 index 00000000..68eab7a2 --- /dev/null +++ b/tests/expectations/tests/libclang-3.8/error-E0600-cannot-apply-unary-negation-to-u32.rs @@ -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; diff --git a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs b/tests/expectations/tests/libclang-3.9/constant-evaluate.rs index 159dba7c..69501c64 100644 --- a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs +++ b/tests/expectations/tests/libclang-3.9/constant-evaluate.rs @@ -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; diff --git a/tests/expectations/tests/libclang-3.9/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/libclang-3.9/error-E0600-cannot-apply-unary-negation-to-u32.rs new file mode 100644 index 00000000..68eab7a2 --- /dev/null +++ b/tests/expectations/tests/libclang-3.9/error-E0600-cannot-apply-unary-negation-to-u32.rs @@ -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; diff --git a/tests/expectations/tests/libclang-4/constant-evaluate.rs b/tests/expectations/tests/libclang-4/constant-evaluate.rs index 045710f9..07df8114 100644 --- a/tests/expectations/tests/libclang-4/constant-evaluate.rs +++ b/tests/expectations/tests/libclang-4/constant-evaluate.rs @@ -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; @@ -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; diff --git a/tests/expectations/tests/libclang-4/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/libclang-4/error-E0600-cannot-apply-unary-negation-to-u32.rs new file mode 100644 index 00000000..7ad2fc1c --- /dev/null +++ b/tests/expectations/tests/libclang-4/error-E0600-cannot-apply-unary-negation-to-u32.rs @@ -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; diff --git a/tests/expectations/tests/libclang-5/constant-evaluate.rs b/tests/expectations/tests/libclang-5/constant-evaluate.rs index 045710f9..07df8114 100644 --- a/tests/expectations/tests/libclang-5/constant-evaluate.rs +++ b/tests/expectations/tests/libclang-5/constant-evaluate.rs @@ -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; @@ -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; diff --git a/tests/expectations/tests/libclang-5/error-E0600-cannot-apply-unary-negation-to-u32.rs b/tests/expectations/tests/libclang-5/error-E0600-cannot-apply-unary-negation-to-u32.rs new file mode 100644 index 00000000..7ad2fc1c --- /dev/null +++ b/tests/expectations/tests/libclang-5/error-E0600-cannot-apply-unary-negation-to-u32.rs @@ -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; diff --git a/tests/headers/constant-evaluate.h b/tests/headers/constant-evaluate.h index e8d0a5ba..812553ed 100644 --- a/tests/headers/constant-evaluate.h +++ b/tests/headers/constant-evaluate.h @@ -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); diff --git a/tests/headers/derive-debug-bitfield-core.hpp b/tests/headers/derive-debug-bitfield-core.hpp index 7a5694ec..5d78e743 100644 --- a/tests/headers/derive-debug-bitfield-core.hpp +++ b/tests/headers/derive-debug-bitfield-core.hpp @@ -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; |