summaryrefslogtreecommitdiff
path: root/src/clang.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-09-04 08:26:52 -0400
committerGitHub <noreply@github.com>2018-09-04 08:26:52 -0400
commit36c087bb4a22ae37d96a7a711293f5ee2d98015f (patch)
treee393ffaf062cc1c62becfe0053aeb37e62fa58d9 /src/clang.rs
parent0db9588e84463c211340f0bc2cb6da2b3a99c441 (diff)
parent2319708814878e7b102b5223fa762e0f464a3f96 (diff)
Auto merge of #1381 - emilio:integer-eval, r=noxv0.40.0
ir: Handle overflowing integer constant evaluation properly. Fixes #1380
Diffstat (limited to 'src/clang.rs')
-rw-r--r--src/clang.rs33
1 files changed, 27 insertions, 6 deletions
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