diff --git a/c2rust-transpile/src/translator/enums.rs b/c2rust-transpile/src/translator/enums.rs index 88a9045b13..02b37e8059 100644 --- a/c2rust-transpile/src/translator/enums.rs +++ b/c2rust-transpile/src/translator/enums.rs @@ -182,7 +182,7 @@ impl<'c> Translation<'c> { variants.contains(&enum_constant_id) } - fn enum_integral_type(&self, enum_id: CEnumId) -> CQualTypeId { + pub(crate) fn enum_integral_type(&self, enum_id: CEnumId) -> CQualTypeId { match self.ast_context[enum_id].kind { CDeclKind::Enum { integral_type: Some(integral_type), diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index 12ebc9f56f..6b1e57cb5c 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -624,12 +624,21 @@ impl<'c> Translation<'c> { _ => mk().lit_expr(mk().int_unsuffixed_lit(1)), }; - let one_type_id = - if let CTypeKind::Pointer(..) = self.ast_context.resolve_type(arg_type.ctype).kind { - CQualTypeId::new(self.ast_context.type_for_kind(&CTypeKind::Int)) - } else { - arg_type - }; + let mut one_type_id = arg_type; + let mut compute_lhs_type_id = arg_type; + let mut compute_res_type_id = ty; + + match self.ast_context.resolve_type(arg_type.ctype).kind { + CTypeKind::Pointer(..) => { + one_type_id = CQualTypeId::new(self.ast_context.type_for_kind(&CTypeKind::Int)); + } + CTypeKind::Enum(enum_id) => { + one_type_id = self.enum_integral_type(enum_id); + compute_lhs_type_id = one_type_id; + compute_res_type_id = one_type_id; + } + _ => {} + }; self.convert_assignment_operator_with_rhs( ctx, @@ -638,8 +647,8 @@ impl<'c> Translation<'c> { arg, one_type_id, WithStmts::new_val(one), - Some(arg_type), - Some(ty), + Some(compute_lhs_type_id), + Some(compute_res_type_id), ) } @@ -697,9 +706,9 @@ impl<'c> Translation<'c> { let mut is_unsafe = false; // Track unsafety if we call `pointer::offset`. // *p + 1 - let val = if let &CTypeKind::Pointer(pointee) = - &self.ast_context.resolve_type(ty.ctype).kind - { + let mut type_kind = &self.ast_context.resolve_type(ty.ctype).kind; + + let val = if let &CTypeKind::Pointer(pointee) = type_kind { if let Some(n) = self.compute_size_of_expr(pointee.ctype) { one = n } @@ -711,15 +720,17 @@ impl<'c> Translation<'c> { }; is_unsafe = true; mk().method_call_expr(read, "offset", vec![n]) - } else if self - .ast_context - .resolve_type(ty.ctype) - .kind - .is_unsigned_integral_type() - { - mk().method_call_expr(read, op.wrapping_method(), vec![one]) } else { - mk().binary_expr(BinOp::from(op), read, one) + if let &CTypeKind::Enum(enum_id) = type_kind { + let integral_type = self.enum_integral_type(enum_id); + type_kind = &self.ast_context.resolve_type(integral_type.ctype).kind; + } + + if type_kind.is_unsigned_integral_type() { + mk().method_call_expr(read, op.wrapping_method(), vec![one]) + } else { + mk().binary_expr(BinOp::from(op), read, one) + } }; // *p = *p + rhs diff --git a/c2rust-transpile/tests/snapshots/enums.c b/c2rust-transpile/tests/snapshots/enums.c index ba83188062..7a8fd546c3 100644 --- a/c2rust-transpile/tests/snapshots/enums.c +++ b/c2rust-transpile/tests/snapshots/enums.c @@ -26,6 +26,12 @@ void test_enums(void) { foo -= 2; bar -= 2; + // Increment + ++foo; + ++bar; + bar = foo++; + foo = bar++; + Foo e = Foo1; // Compare to same type diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2021.clang15.snap index 20d12c7e2b..1801a51ebe 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2021.clang15.snap @@ -38,6 +38,14 @@ pub unsafe extern "C" fn test_enums() { bar = Bar3; foo = (foo as ::core::ffi::c_uint).wrapping_sub(2 as ::core::ffi::c_uint) as Foo; bar = (bar as ::core::ffi::c_int - 2 as ::core::ffi::c_int) as Bar; + foo = (foo as ::core::ffi::c_uint).wrapping_add(1) as Foo; + bar = (bar as ::core::ffi::c_int + 1) as Bar; + let c2rust_fresh0 = foo; + foo = foo.wrapping_add(1); + bar = c2rust_fresh0 as Bar; + let c2rust_fresh1 = bar; + bar = bar + 1; + foo = c2rust_fresh1 as Foo; let mut e: Foo = Foo1; let mut enum_enum: ::core::ffi::c_int = (e as ::core::ffi::c_uint == foo as ::core::ffi::c_uint) as ::core::ffi::c_int; diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2024.clang15.snap index 9bcb1274b9..8aa6150078 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@enums.c.2024.clang15.snap @@ -39,6 +39,14 @@ pub unsafe extern "C" fn test_enums() { bar = Bar3; foo = (foo as ::core::ffi::c_uint).wrapping_sub(2 as ::core::ffi::c_uint) as Foo; bar = (bar as ::core::ffi::c_int - 2 as ::core::ffi::c_int) as Bar; + foo = (foo as ::core::ffi::c_uint).wrapping_add(1) as Foo; + bar = (bar as ::core::ffi::c_int + 1) as Bar; + let c2rust_fresh0 = foo; + foo = foo.wrapping_add(1); + bar = c2rust_fresh0 as Bar; + let c2rust_fresh1 = bar; + bar = bar + 1; + foo = c2rust_fresh1 as Foo; let mut e: Foo = Foo1; let mut enum_enum: ::core::ffi::c_int = (e as ::core::ffi::c_uint == foo as ::core::ffi::c_uint) as ::core::ffi::c_int;