Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

Commit

Permalink
Auto merge of #122 - emilio:min, r=erickt
Browse files Browse the repository at this point in the history
expr: Handle correctly the minimum value of integers.

Otherwise we underflow.
  • Loading branch information
homu committed Nov 17, 2016
2 parents a351ab9 + 4d5fcf7 commit 876600a
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 63 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aster"
version = "0.33.1"
version = "0.34.0"
authors = ["Erick Tryzelaar <[email protected]>"]
license = "MIT/Apache-2.0"
description = "A libsyntax ast builder"
Expand Down
66 changes: 24 additions & 42 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ impl ExprBuilder {
}
}

macro_rules! signed_int_method {
($ty:ident, $unsigned:ident) => {
pub fn $ty(self, val: $ty) -> F::Result {
if val == ::std::$ty::MIN {
self.neg().lit().$ty(val as $unsigned)
} else if val < 0 {
self.neg().lit().$ty(-val as $unsigned)
} else {
self.lit().$ty(val as $unsigned)
}
}
};
}

impl<F> ExprBuilder<F>
where F: Invoke<P<ast::Expr>>,
{
Expand Down Expand Up @@ -118,56 +132,24 @@ impl<F> ExprBuilder<F>
}

pub fn int(self, value: i64) -> F::Result {
if value < 0 {
self.neg().lit().int(-value)
if value == ::std::i64::MIN {
self.neg().lit().int(value as u64)
} else if value < 0 {
self.neg().lit().int(-value as u64)
} else {
self.lit().int(value)
self.lit().int(value as u64)
}
}

pub fn uint(self, value: u64) -> F::Result {
self.lit().uint(value as u64)
}

pub fn isize(self, value: isize) -> F::Result {
if value < 0 {
self.neg().lit().isize(-value)
} else {
self.lit().isize(value)
}
}

pub fn i8(self, value: i8) -> F::Result {
if value < 0 {
self.neg().lit().i8(-value)
} else {
self.lit().i8(value)
}
}

pub fn i16(self, value: i16) -> F::Result {
if value < 0 {
self.neg().lit().i16(-value)
} else {
self.lit().i16(value)
}
}

pub fn i32(self, value: i32) -> F::Result {
if value < 0 {
self.neg().lit().i32(-value)
} else {
self.lit().i32(value)
}
}

pub fn i64(self, value: i64) -> F::Result {
if value < 0 {
self.neg().lit().i64(-value)
} else {
self.lit().i64(value)
}
}
signed_int_method!(i8, u8);
signed_int_method!(i16, u16);
signed_int_method!(i32, u32);
signed_int_method!(i64, u64);
signed_int_method!(isize, usize);

pub fn usize(self, value: usize) -> F::Result {
self.lit().usize(value)
Expand Down
34 changes: 14 additions & 20 deletions src/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,32 @@ impl<F> LitBuilder<F>
self.bool(false)
}

pub fn int(self, value: i64) -> F::Result {
assert!(value >= 0);
self.build_lit(ast::LitKind::Int(value as u64, ast::LitIntType::Unsuffixed))
pub fn int(self, value: u64) -> F::Result {
self.build_lit(ast::LitKind::Int(value, ast::LitIntType::Unsuffixed))
}

fn build_int(self, value: i64, ty: ast::IntTy) -> F::Result {
assert!(value >= 0);
self.build_lit(ast::LitKind::Int(value as u64, ast::LitIntType::Signed(ty)))
fn build_int(self, value: u64, ty: ast::IntTy) -> F::Result {
self.build_lit(ast::LitKind::Int(value, ast::LitIntType::Signed(ty)))
}

pub fn isize(self, value: isize) -> F::Result {
self.build_int(value as i64, ast::IntTy::Is)
pub fn isize(self, value: usize) -> F::Result {
self.build_int(value as u64, ast::IntTy::Is)
}

pub fn i8(self, value: i8) -> F::Result {
assert!(value >= 0);
self.build_int(value as i64, ast::IntTy::I8)
pub fn i8(self, value: u8) -> F::Result {
self.build_int(value as u64, ast::IntTy::I8)
}

pub fn i16(self, value: i16) -> F::Result {
assert!(value >= 0);
self.build_int(value as i64, ast::IntTy::I16)
pub fn i16(self, value: u16) -> F::Result {
self.build_int(value as u64, ast::IntTy::I16)
}

pub fn i32(self, value: i32) -> F::Result {
assert!(value >= 0);
self.build_int(value as i64, ast::IntTy::I32)
pub fn i32(self, value: u32) -> F::Result {
self.build_int(value as u64, ast::IntTy::I32)
}

pub fn i64(self, value: i64) -> F::Result {
assert!(value >= 0);
self.build_int(value, ast::IntTy::I64)
pub fn i64(self, value: u64) -> F::Result {
self.build_int(value as u64, ast::IntTy::I64)
}

pub fn uint(self, value: u64) -> F::Result {
Expand Down
3 changes: 3 additions & 0 deletions tests/test_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ fn test_lit() {
check(builder.expr().u64(5), builder.lit().u64(5));
check(builder.expr().usize(5), builder.lit().usize(5));

// Doesn't crash.
assert_eq!(builder.expr().i64(::std::i64::MIN),
builder.expr().neg().lit().i64(1 << 63));
check(builder.expr().str("string"), builder.lit().str("string"));
}

Expand Down

0 comments on commit 876600a

Please sign in to comment.