diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index a86e745bdd..e6f9e09f41 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -3341,10 +3341,12 @@ impl<'c> Translation<'c> { } BinaryConditional(ty, lhs, rhs) => { + let rhs = self.convert_expr(ctx, rhs, None)?; + if ctx.is_unused() { - let mut lhs = self.convert_condition(ctx, false, lhs)?; - let rhs = self.convert_expr(ctx, rhs, None)?; - lhs = lhs.merge_unsafe(rhs.is_unsafe()); + let lhs = self + .convert_condition(ctx, false, lhs)? + .merge_unsafe(rhs.is_unsafe()); Ok(lhs.and_then(|val| { WithStmts::new( @@ -3359,19 +3361,28 @@ impl<'c> Translation<'c> { ) })) } else { - self.name_reference_write_read(ctx, lhs)?.try_map( - |NamedReference { - rvalue: lhs_val, .. - }| { - let cond = self.match_bool(ctx, true, ty.ctype, lhs_val.clone())?; - let ite = mk().ifte_expr( - cond, - mk().block(vec![mk().expr_stmt(lhs_val)]), - Some(self.convert_expr(ctx, rhs, None)?.to_expr()), - ); - Ok(ite) - }, - ) + let lhs = self + .convert_expr(ctx.used(), lhs, None)? + .merge_unsafe(rhs.is_unsafe()); + let fresh_name = self.renamer.borrow_mut().fresh(); + + lhs.and_then_try(|lhs| { + let fresh_stmt = mk().local_stmt(Box::new(mk().local( + mk().ident_pat(&fresh_name), + None, + Some(lhs), + ))); + + let cond = + self.match_bool(ctx, true, ty.ctype, mk().ident_expr(&fresh_name))?; + let ite = mk().ifte_expr( + cond, + mk().block(vec![mk().expr_stmt(mk().ident_expr(&fresh_name))]), + Some(rhs.to_expr()), + ); + + Ok(WithStmts::new(vec![fresh_stmt], ite)) + }) } } diff --git a/c2rust-transpile/src/translator/named_references.rs b/c2rust-transpile/src/translator/named_references.rs index ede42c8fab..f33edcfb7f 100644 --- a/c2rust-transpile/src/translator/named_references.rs +++ b/c2rust-transpile/src/translator/named_references.rs @@ -122,13 +122,14 @@ impl<'c> Translation<'c> { } else { // This is the case where we explicitly need to factor out possible side-effects. - let ptr_name = self.renamer.borrow_mut().fresh(); + let ptr_name = self.renamer.borrow_mut().pick_name("c2rust_side_effects"); - // let ref mut p = lhs; + // let p = &raw mut lhs; + self.use_feature("raw_ref_op"); let compute_ref = mk().local_stmt(Box::new(mk().local( - mk().mutbl().ident_ref_pat(&ptr_name), + mk().ident_pat(&ptr_name), None, - Some(reference), + Some(mk().mutbl().raw_borrow_expr(reference)), ))); let write = diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index a03f240ffe..c45327d4f5 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -212,7 +212,7 @@ impl<'c> Translation<'c> { ))) } else { let lhs = self.convert_cast( - ctx, + ctx.used(), initial_lhs_type_id, compute_lhs_type_id, WithStmts::new_val(read.clone()), @@ -234,8 +234,15 @@ impl<'c> Translation<'c> { ) })?; - let val = - self.convert_cast(ctx, compute_res_type_id, lhs_type_id, val, None, None, None)?; + let val = self.convert_cast( + ctx.used(), + compute_res_type_id, + lhs_type_id, + val, + None, + None, + None, + )?; Ok(val.map(|val| mk().assign_expr(write.clone(), val))) } @@ -424,7 +431,7 @@ impl<'c> Translation<'c> { .expect("Cannot convert non-assignment operator"); let lhs = self.convert_cast( - ctx, + ctx.used(), initial_lhs_type_id, expr_or_comp_type_id, WithStmts::new_val(read.clone()), @@ -447,7 +454,7 @@ impl<'c> Translation<'c> { )?; let val = self.convert_cast( - ctx, + ctx.used(), result_type_id, expr_type_id, val, @@ -650,7 +657,7 @@ impl<'c> Translation<'c> { }; self.convert_assignment_operator_with_rhs( - ctx.used(), + ctx, op, ty, arg, @@ -789,7 +796,7 @@ impl<'c> Translation<'c> { .map(|a| mk().unary_expr(UnOp::Not(Default::default()), a))), CUnOp::Not => { - let val = self.convert_condition(ctx, false, arg)?; + let val = self.convert_condition(ctx.used(), false, arg)?; Ok(val.map(|x| mk().cast_expr(x, mk().abs_path_ty(vec!["core", "ffi", "c_int"])))) } CUnOp::Extension => { diff --git a/c2rust-transpile/tests/snapshots.rs b/c2rust-transpile/tests/snapshots.rs index 4f10e330ea..36a15da67d 100644 --- a/c2rust-transpile/tests/snapshots.rs +++ b/c2rust-transpile/tests/snapshots.rs @@ -354,6 +354,11 @@ fn test_compound_literals() { transpile("compound_literals.c").run(); } +#[test] +fn test_conditions() { + transpile("conditions.c").run(); +} + #[test] fn test_empty_init() { transpile("empty_init.c").run(); diff --git a/c2rust-transpile/tests/snapshots/if_else.c b/c2rust-transpile/tests/snapshots/conditions.c similarity index 72% rename from c2rust-transpile/tests/snapshots/if_else.c rename to c2rust-transpile/tests/snapshots/conditions.c index 0c14291440..9eb0da5ebc 100644 --- a/c2rust-transpile/tests/snapshots/if_else.c +++ b/c2rust-transpile/tests/snapshots/conditions.c @@ -83,3 +83,22 @@ int nested_early_returns(int x) { } return x; } + +void conditional_operator(const unsigned sz, int buf[const]) { + int x = 0, y = 1; + *(0 ? &y : &x) = 10; + + buf[2] = 1 ? 2 : 3; + buf[3] = 0 ? 2 : 3; +} + +static int id(int i) { return i;} +static int add(int *p, int i, int r) { *p += i; return r;} + +void binary_conditional_operator(const unsigned sz, int buf[const]) { + buf[0] = id(0) ?: id(1); + buf[1] = id(2) ?: id(3); + + (void) (add(buf+2, 2, 0) ?: add(buf+3, 3, 0)); + (void) (add(buf+4, 4, 1) ?: add(buf+5, 5, 0)); +} diff --git a/c2rust-transpile/tests/snapshots/exprs.c b/c2rust-transpile/tests/snapshots/exprs.c index 633e854f9f..7d7c283f3f 100644 --- a/c2rust-transpile/tests/snapshots/exprs.c +++ b/c2rust-transpile/tests/snapshots/exprs.c @@ -2,7 +2,13 @@ int puts(const char *str); static int side_effect(){ puts("the return of side effect"); - return 10; + return 0; +} + +static int* lvalue_side_effect(){ + puts("the return of side effect"); + static int VAL = 42; + return &VAL; } void unary_without_side_effect(){ @@ -20,18 +26,43 @@ void unary_without_side_effect(){ } void unary_with_side_effect(){ - char* arr[1] = {0}; + char *arr[1] = {0}; -side_effect(); +side_effect(); ~side_effect(); !side_effect(); &""[side_effect()]; - *arr[side_effect()]; +} + +void inc_decl_with_rvalue_side_effect() { + int arr[1] = {0}; + + // Increment/decrement, expression value not used ++arr[side_effect()]; --arr[side_effect()]; arr[side_effect()]++; arr[side_effect()]--; + + // Increment/decrement, expression value is used + int pre_inc = ++arr[side_effect()]; + int pre_dec = --arr[side_effect()]; + int post_inc = arr[side_effect()]++; + int post_dec = arr[side_effect()]--; +} + +void inc_decl_with_lvalue_side_effect() { + // Increment/decrement, expression value not used + ++*lvalue_side_effect(); + --*lvalue_side_effect(); + (*lvalue_side_effect())++; + (*lvalue_side_effect())--; + + // Increment/decrement, expression value is used + int pre_inc = ++*lvalue_side_effect(); + int pre_dec = --*lvalue_side_effect(); + int post_inc = (*lvalue_side_effect())++; + int post_dec = (*lvalue_side_effect())--; } void unsigned_compound_desugaring(void) { diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2021.clang15.snap new file mode 100644 index 0000000000..b1baf9b891 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2021.clang15.snap @@ -0,0 +1,169 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/conditions.2021.clang15.rs +--- +#![allow( + clippy::missing_safety_doc, + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![feature(raw_ref_op)] +#[no_mangle] +pub unsafe extern "C" fn simple_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + x += 1 as ::core::ffi::c_int; + } else { + x += 2 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn multiple_ifs(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + x += 1 as ::core::ffi::c_int; + } + if x != 0 { + x += 2 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn nested_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + if x < 10 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } else { + x += 2 as ::core::ffi::c_int; + } + } else { + x -= 1 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn nested_if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + if x < 10 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } + x += 2 as ::core::ffi::c_int; + } else { + x -= 1 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn early_returns(mut a: ::core::ffi::c_int) -> ::core::ffi::c_int { + if a == 2 as ::core::ffi::c_int { + return 2 as ::core::ffi::c_int; + } + if a == 3 as ::core::ffi::c_int { + a += 1 as ::core::ffi::c_int; + } + if a == 4 as ::core::ffi::c_int { + return 1 as ::core::ffi::c_int; + } + return 0 as ::core::ffi::c_int; +} +#[no_mangle] +pub unsafe extern "C" fn nested_early_returns(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + if x != 0 { + x += 1 as ::core::ffi::c_int; + return x; + } + x += 2 as ::core::ffi::c_int; + } else { + if x != 0 { + x += 3 as ::core::ffi::c_int; + return x; + } + x += 4 as ::core::ffi::c_int; + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn conditional_operator( + sz: ::core::ffi::c_uint, + buf: *mut ::core::ffi::c_int, +) { + let mut x: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + let mut y: ::core::ffi::c_int = 1 as ::core::ffi::c_int; + *if false { &raw mut y } else { &raw mut x } = 10 as ::core::ffi::c_int; + *(buf as *mut ::core::ffi::c_int).offset(2 as ::core::ffi::c_int as isize) = if true { + 2 as ::core::ffi::c_int + } else { + 3 as ::core::ffi::c_int + }; + *(buf as *mut ::core::ffi::c_int).offset(3 as ::core::ffi::c_int as isize) = if false { + 2 as ::core::ffi::c_int + } else { + 3 as ::core::ffi::c_int + }; +} +unsafe extern "C" fn id(mut i: ::core::ffi::c_int) -> ::core::ffi::c_int { + return i; +} +unsafe extern "C" fn add( + mut p: *mut ::core::ffi::c_int, + mut i: ::core::ffi::c_int, + mut r: ::core::ffi::c_int, +) -> ::core::ffi::c_int { + *p += i; + return r; +} +#[no_mangle] +pub unsafe extern "C" fn binary_conditional_operator( + sz: ::core::ffi::c_uint, + buf: *mut ::core::ffi::c_int, +) { + let c2rust_fresh0 = id(0 as ::core::ffi::c_int); + *(buf as *mut ::core::ffi::c_int).offset(0 as ::core::ffi::c_int as isize) = + if c2rust_fresh0 != 0 { + c2rust_fresh0 + } else { + id(1 as ::core::ffi::c_int) + }; + let c2rust_fresh1 = id(2 as ::core::ffi::c_int); + *(buf as *mut ::core::ffi::c_int).offset(1 as ::core::ffi::c_int as isize) = + if c2rust_fresh1 != 0 { + c2rust_fresh1 + } else { + id(3 as ::core::ffi::c_int) + }; + if add( + (buf as *mut ::core::ffi::c_int).offset(2 as ::core::ffi::c_int as isize), + 2 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ) == 0 + { + add( + (buf as *mut ::core::ffi::c_int).offset(3 as ::core::ffi::c_int as isize), + 3 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ); + } + if add( + (buf as *mut ::core::ffi::c_int).offset(4 as ::core::ffi::c_int as isize), + 4 as ::core::ffi::c_int, + 1 as ::core::ffi::c_int, + ) == 0 + { + add( + (buf as *mut ::core::ffi::c_int).offset(5 as ::core::ffi::c_int as isize), + 5 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ); + } +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2024.clang15.snap new file mode 100644 index 0000000000..16343532d5 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@conditions.c.2024.clang15.snap @@ -0,0 +1,169 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/conditions.2024.clang15.rs +--- +#![allow( + clippy::missing_safety_doc, + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unsafe_op_in_unsafe_fn, + unused_assignments, + unused_mut +)] +#[unsafe(no_mangle)] +pub unsafe extern "C" fn simple_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + x += 1 as ::core::ffi::c_int; + } else { + x += 2 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn multiple_ifs(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + x += 1 as ::core::ffi::c_int; + } + if x != 0 { + x += 2 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn nested_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + if x < 10 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } else { + x += 2 as ::core::ffi::c_int; + } + } else { + x -= 1 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn nested_if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x > 0 as ::core::ffi::c_int { + if x < 10 as ::core::ffi::c_int { + x += 1 as ::core::ffi::c_int; + } + x += 2 as ::core::ffi::c_int; + } else { + x -= 1 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn early_returns(mut a: ::core::ffi::c_int) -> ::core::ffi::c_int { + if a == 2 as ::core::ffi::c_int { + return 2 as ::core::ffi::c_int; + } + if a == 3 as ::core::ffi::c_int { + a += 1 as ::core::ffi::c_int; + } + if a == 4 as ::core::ffi::c_int { + return 1 as ::core::ffi::c_int; + } + return 0 as ::core::ffi::c_int; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn nested_early_returns(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { + if x != 0 { + if x != 0 { + x += 1 as ::core::ffi::c_int; + return x; + } + x += 2 as ::core::ffi::c_int; + } else { + if x != 0 { + x += 3 as ::core::ffi::c_int; + return x; + } + x += 4 as ::core::ffi::c_int; + } + return x; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn conditional_operator( + sz: ::core::ffi::c_uint, + buf: *mut ::core::ffi::c_int, +) { + let mut x: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + let mut y: ::core::ffi::c_int = 1 as ::core::ffi::c_int; + *if false { &raw mut y } else { &raw mut x } = 10 as ::core::ffi::c_int; + *(buf as *mut ::core::ffi::c_int).offset(2 as ::core::ffi::c_int as isize) = if true { + 2 as ::core::ffi::c_int + } else { + 3 as ::core::ffi::c_int + }; + *(buf as *mut ::core::ffi::c_int).offset(3 as ::core::ffi::c_int as isize) = if false { + 2 as ::core::ffi::c_int + } else { + 3 as ::core::ffi::c_int + }; +} +unsafe extern "C" fn id(mut i: ::core::ffi::c_int) -> ::core::ffi::c_int { + return i; +} +unsafe extern "C" fn add( + mut p: *mut ::core::ffi::c_int, + mut i: ::core::ffi::c_int, + mut r: ::core::ffi::c_int, +) -> ::core::ffi::c_int { + *p += i; + return r; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn binary_conditional_operator( + sz: ::core::ffi::c_uint, + buf: *mut ::core::ffi::c_int, +) { + let c2rust_fresh0 = id(0 as ::core::ffi::c_int); + *(buf as *mut ::core::ffi::c_int).offset(0 as ::core::ffi::c_int as isize) = + if c2rust_fresh0 != 0 { + c2rust_fresh0 + } else { + id(1 as ::core::ffi::c_int) + }; + let c2rust_fresh1 = id(2 as ::core::ffi::c_int); + *(buf as *mut ::core::ffi::c_int).offset(1 as ::core::ffi::c_int as isize) = + if c2rust_fresh1 != 0 { + c2rust_fresh1 + } else { + id(3 as ::core::ffi::c_int) + }; + if add( + (buf as *mut ::core::ffi::c_int).offset(2 as ::core::ffi::c_int as isize), + 2 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ) == 0 + { + add( + (buf as *mut ::core::ffi::c_int).offset(3 as ::core::ffi::c_int as isize), + 3 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ); + } + if add( + (buf as *mut ::core::ffi::c_int).offset(4 as ::core::ffi::c_int as isize), + 4 as ::core::ffi::c_int, + 1 as ::core::ffi::c_int, + ) == 0 + { + add( + (buf as *mut ::core::ffi::c_int).offset(5 as ::core::ffi::c_int as isize), + 5 as ::core::ffi::c_int, + 0 as ::core::ffi::c_int, + ); + } +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2021.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2021.clang15.snap index 56ee5f78bf..4a286ce356 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2021.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2021.clang15.snap @@ -24,7 +24,12 @@ pub const B: C2Rust_Unnamed = 1; pub const A: C2Rust_Unnamed = 0; unsafe extern "C" fn side_effect() -> ::core::ffi::c_int { puts(b"the return of side effect\0".as_ptr() as *const ::core::ffi::c_char); - return 10 as ::core::ffi::c_int; + return 0 as ::core::ffi::c_int; +} +unsafe extern "C" fn lvalue_side_effect() -> *mut ::core::ffi::c_int { + puts(b"the return of side effect\0".as_ptr() as *const ::core::ffi::c_char); + static mut VAL: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + return &raw mut VAL; } #[no_mangle] pub unsafe extern "C" fn unary_without_side_effect() { @@ -49,11 +54,45 @@ pub unsafe extern "C" fn unary_with_side_effect() { (side_effect() == 0) as ::core::ffi::c_int; (b"\0".as_ptr() as *const ::core::ffi::c_char).offset(side_effect() as isize) as *const ::core::ffi::c_char; - *arr[side_effect() as usize]; - arr[side_effect() as usize] = arr[side_effect() as usize].offset(1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1); +} +#[no_mangle] +pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() { + let mut arr: [::core::ffi::c_int; 1] = [0 as ::core::ffi::c_int]; + arr[side_effect() as usize] += 1; + arr[side_effect() as usize] -= 1; + arr[side_effect() as usize] += 1; + arr[side_effect() as usize] -= 1; + arr[side_effect() as usize] += 1; + let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize]; + arr[side_effect() as usize] -= 1; + let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize]; + let c2rust_fresh0 = arr[side_effect() as usize]; + arr[side_effect() as usize] = arr[side_effect() as usize] + 1; + let mut post_inc: ::core::ffi::c_int = c2rust_fresh0; + let c2rust_fresh1 = arr[side_effect() as usize]; + arr[side_effect() as usize] = arr[side_effect() as usize] - 1; + let mut post_dec: ::core::ffi::c_int = c2rust_fresh1; +} +#[no_mangle] +pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() { + *lvalue_side_effect() += 1; + *lvalue_side_effect() -= 1; + *lvalue_side_effect() += 1; + *lvalue_side_effect() -= 1; + let c2rust_side_effects = &raw mut *lvalue_side_effect(); + *c2rust_side_effects += 1; + let mut pre_inc: ::core::ffi::c_int = *c2rust_side_effects; + let c2rust_side_effects_0 = &raw mut *lvalue_side_effect(); + *c2rust_side_effects_0 -= 1; + let mut pre_dec: ::core::ffi::c_int = *c2rust_side_effects_0; + let c2rust_side_effects_1 = &raw mut *lvalue_side_effect(); + let c2rust_fresh2 = *c2rust_side_effects_1; + *c2rust_side_effects_1 = *c2rust_side_effects_1 + 1; + let mut post_inc: ::core::ffi::c_int = c2rust_fresh2; + let c2rust_side_effects_2 = &raw mut *lvalue_side_effect(); + let c2rust_fresh3 = *c2rust_side_effects_2; + *c2rust_side_effects_2 = *c2rust_side_effects_2 - 1; + let mut post_dec: ::core::ffi::c_int = c2rust_fresh3; } #[no_mangle] pub unsafe extern "C" fn unsigned_compound_desugaring() { diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap index 04e6019c9c..c6c2bcb67b 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap @@ -24,7 +24,12 @@ pub const B: C2Rust_Unnamed = 1; pub const A: C2Rust_Unnamed = 0; unsafe extern "C" fn side_effect() -> ::core::ffi::c_int { puts(b"the return of side effect\0".as_ptr() as *const ::core::ffi::c_char); - return 10 as ::core::ffi::c_int; + return 0 as ::core::ffi::c_int; +} +unsafe extern "C" fn lvalue_side_effect() -> *mut ::core::ffi::c_int { + puts(b"the return of side effect\0".as_ptr() as *const ::core::ffi::c_char); + static mut VAL: ::core::ffi::c_int = 42 as ::core::ffi::c_int; + return &raw mut VAL; } #[unsafe(no_mangle)] pub unsafe extern "C" fn unary_without_side_effect() { @@ -49,11 +54,45 @@ pub unsafe extern "C" fn unary_with_side_effect() { (side_effect() == 0) as ::core::ffi::c_int; (b"\0".as_ptr() as *const ::core::ffi::c_char).offset(side_effect() as isize) as *const ::core::ffi::c_char; - *arr[side_effect() as usize]; - arr[side_effect() as usize] = arr[side_effect() as usize].offset(1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(1); - arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1); +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() { + let mut arr: [::core::ffi::c_int; 1] = [0 as ::core::ffi::c_int]; + arr[side_effect() as usize] += 1; + arr[side_effect() as usize] -= 1; + arr[side_effect() as usize] += 1; + arr[side_effect() as usize] -= 1; + arr[side_effect() as usize] += 1; + let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize]; + arr[side_effect() as usize] -= 1; + let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize]; + let c2rust_fresh0 = arr[side_effect() as usize]; + arr[side_effect() as usize] = arr[side_effect() as usize] + 1; + let mut post_inc: ::core::ffi::c_int = c2rust_fresh0; + let c2rust_fresh1 = arr[side_effect() as usize]; + arr[side_effect() as usize] = arr[side_effect() as usize] - 1; + let mut post_dec: ::core::ffi::c_int = c2rust_fresh1; +} +#[unsafe(no_mangle)] +pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() { + *lvalue_side_effect() += 1; + *lvalue_side_effect() -= 1; + *lvalue_side_effect() += 1; + *lvalue_side_effect() -= 1; + let c2rust_side_effects = &raw mut *lvalue_side_effect(); + *c2rust_side_effects += 1; + let mut pre_inc: ::core::ffi::c_int = *c2rust_side_effects; + let c2rust_side_effects_0 = &raw mut *lvalue_side_effect(); + *c2rust_side_effects_0 -= 1; + let mut pre_dec: ::core::ffi::c_int = *c2rust_side_effects_0; + let c2rust_side_effects_1 = &raw mut *lvalue_side_effect(); + let c2rust_fresh2 = *c2rust_side_effects_1; + *c2rust_side_effects_1 = *c2rust_side_effects_1 + 1; + let mut post_inc: ::core::ffi::c_int = c2rust_fresh2; + let c2rust_side_effects_2 = &raw mut *lvalue_side_effect(); + let c2rust_fresh3 = *c2rust_side_effects_2; + *c2rust_side_effects_2 = *c2rust_side_effects_2 - 1; + let mut post_dec: ::core::ffi::c_int = c2rust_fresh3; } #[unsafe(no_mangle)] pub unsafe extern "C" fn unsigned_compound_desugaring() { diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@if_else.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@if_else.c.snap deleted file mode 100644 index 05f99290ee..0000000000 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@if_else.c.snap +++ /dev/null @@ -1,95 +0,0 @@ ---- -source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/if_else.rs -input_file: c2rust-transpile/tests/snapshots/if_else.c ---- -#![allow( - clippy::missing_safety_doc, - dead_code, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_assignments, - unused_mut -)] -#[no_mangle] -pub unsafe extern "C" fn simple_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x != 0 { - x += 1 as ::core::ffi::c_int; - } else { - x += 2 as ::core::ffi::c_int; - } - return x; -} -#[no_mangle] -pub unsafe extern "C" fn if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x > 0 as ::core::ffi::c_int { - x += 1 as ::core::ffi::c_int; - } - return x; -} -#[no_mangle] -pub unsafe extern "C" fn multiple_ifs(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x != 0 { - x += 1 as ::core::ffi::c_int; - } - if x != 0 { - x += 2 as ::core::ffi::c_int; - } - return x; -} -#[no_mangle] -pub unsafe extern "C" fn nested_if_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x > 0 as ::core::ffi::c_int { - if x < 10 as ::core::ffi::c_int { - x += 1 as ::core::ffi::c_int; - } else { - x += 2 as ::core::ffi::c_int; - } - } else { - x -= 1 as ::core::ffi::c_int; - } - return x; -} -#[no_mangle] -pub unsafe extern "C" fn nested_if_no_else(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x > 0 as ::core::ffi::c_int { - if x < 10 as ::core::ffi::c_int { - x += 1 as ::core::ffi::c_int; - } - x += 2 as ::core::ffi::c_int; - } else { - x -= 1 as ::core::ffi::c_int; - } - return x; -} -#[no_mangle] -pub unsafe extern "C" fn early_returns(mut a: ::core::ffi::c_int) -> ::core::ffi::c_int { - if a == 2 as ::core::ffi::c_int { - return 2 as ::core::ffi::c_int; - } - if a == 3 as ::core::ffi::c_int { - a += 1 as ::core::ffi::c_int; - } - if a == 4 as ::core::ffi::c_int { - return 1 as ::core::ffi::c_int; - } - return 0 as ::core::ffi::c_int; -} -#[no_mangle] -pub unsafe extern "C" fn nested_early_returns(mut x: ::core::ffi::c_int) -> ::core::ffi::c_int { - if x != 0 { - if x != 0 { - x += 1 as ::core::ffi::c_int; - return x; - } - x += 2 as ::core::ffi::c_int; - } else { - if x != 0 { - x += 3 as ::core::ffi::c_int; - return x; - } - x += 4 as ::core::ffi::c_int; - } - return x; -}