diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 2968ced03a..d8827a3611 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -2173,6 +2173,8 @@ impl CastKind { (CTypeKind::Function(..), CTypeKind::Pointer(..)) => CastKind::FunctionToPointerDecay, + (CTypeKind::Bool, CTypeKind::Pointer(..)) => CastKind::IntegralToPointer, + (_, CTypeKind::Pointer(..)) if source_ty_kind.is_enum_or_integral_type() => { CastKind::IntegralToPointer } @@ -2191,6 +2193,10 @@ impl CastKind { CastKind::BooleanToSignedIntegral } + (CTypeKind::Bool, _) if target_ty_kind.is_enum_or_integral_type() => { + CastKind::IntegralCast + } + (_, _) if source_ty_kind.is_enum_or_integral_type() && target_ty_kind.is_enum_or_integral_type() => @@ -2198,6 +2204,10 @@ impl CastKind { CastKind::IntegralCast } + (CTypeKind::Bool, _) if target_ty_kind.is_floating_type() => { + CastKind::IntegralToFloating + } + (_, _) if source_ty_kind.is_enum_or_integral_type() && target_ty_kind.is_floating_type() => @@ -3224,7 +3234,7 @@ impl CTypeKind { use CTypeKind::*; matches!( self, - Bool | UChar + UChar | UInt | UShort | ULong @@ -3272,7 +3282,11 @@ impl CTypeKind { } pub fn is_scalar(&self) -> bool { - self.is_integral_type() || self.is_floating_type() || self.is_enum() || self.is_pointer() + self.is_bool() + || self.is_integral_type() + || self.is_floating_type() + || self.is_enum() + || self.is_pointer() } pub fn as_underlying_decl(&self) -> Option { @@ -3297,7 +3311,7 @@ impl CTypeKind { /// Choose the smaller, simpler of the two types if they are cast-compatible. pub fn smaller_compatible_type(ty1: CTypeKind, ty2: CTypeKind) -> Option { - let int = Self::is_integral_type; + let int = |ty: &Self| ty.is_integral_type() || ty.is_bool(); let float = Self::is_floating_type; use CTypeKind::*; diff --git a/c2rust-transpile/src/translator/literals.rs b/c2rust-transpile/src/translator/literals.rs index e8c76c12a5..e9fd340caa 100644 --- a/c2rust-transpile/src/translator/literals.rs +++ b/c2rust-transpile/src/translator/literals.rs @@ -49,7 +49,7 @@ impl<'c> Translation<'c> { let ty_kind = &self.ast_context.resolve_type(ty.ctype).kind; match *lit { CLiteral::Integer(value, _) | CLiteral::Character(value) - if ty_kind.is_integral_type() && !ty_kind.is_bool() => + if ty_kind.is_integral_type() => { ty_kind.guaranteed_integer_in_range(value) && (!is_negated || ty_kind.is_signed_integral_type()) diff --git a/c2rust-transpile/src/translator/pointers.rs b/c2rust-transpile/src/translator/pointers.rs index 65172c32ed..e2e88a601e 100644 --- a/c2rust-transpile/src/translator/pointers.rs +++ b/c2rust-transpile/src/translator/pointers.rs @@ -513,6 +513,7 @@ impl<'c> Translation<'c> { } } + /// Makes a cast from an integer, enum or boolean type to a pointer. pub fn convert_integral_to_pointer_cast( &self, ctx: ExprContext, diff --git a/c2rust-transpile/tests/snapshots/bool.c b/c2rust-transpile/tests/snapshots/bool.c index 9b7cc23af2..0a14e24852 100644 --- a/c2rust-transpile/tests/snapshots/bool.c +++ b/c2rust-transpile/tests/snapshots/bool.c @@ -29,4 +29,10 @@ void test_bool() { // Tests https://github.com/immunant/c2rust/issues/340 int0 |= int1; + + // Casts to/from other numeric types + // Regression test for https://github.com/immunant/c2rust/pull/2005#discussion_r4068559462 + int1 += 1U; + int1 *= 2.0; + double d = int1; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap index 46a5cc84cb..289bb9014f 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2021.clang15.snap @@ -52,4 +52,7 @@ pub unsafe extern "C" fn test_bool() { } else { }; int0 = int0 as ::core::ffi::c_int | int1 as ::core::ffi::c_int != 0; + int1 = (int1 as ::core::ffi::c_uint).wrapping_add(1 as ::core::ffi::c_uint) != 0; + int1 = int1 as u8 as ::core::ffi::c_double * 2.0f64 != 0.; + let mut d: ::core::ffi::c_double = int1 as u8 as ::core::ffi::c_double; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap index f770cddba2..dfd0e473f2 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@bool.c.2024.clang15.snap @@ -53,4 +53,7 @@ pub unsafe extern "C" fn test_bool() { } else { }; int0 = int0 as ::core::ffi::c_int | int1 as ::core::ffi::c_int != 0; + int1 = (int1 as ::core::ffi::c_uint).wrapping_add(1 as ::core::ffi::c_uint) != 0; + int1 = int1 as u8 as ::core::ffi::c_double * 2.0f64 != 0.; + let mut d: ::core::ffi::c_double = int1 as u8 as ::core::ffi::c_double; }