Skip to content

Commit 0365312

Browse files
committed
transpile: In name_reference, also check expression for side effects
1 parent afa06c4 commit 0365312

4 files changed

Lines changed: 41 additions & 50 deletions

File tree

c2rust-transpile/src/translator/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use proc_macro2::{Punct, Spacing::*, Span, TokenStream, TokenTree};
1818
use syn::spanned::Spanned as _;
1919
use syn::{
2020
AttrStyle, BareVariadic, BinOp, Block, Expr, ExprBinary, ExprBlock, ExprBreak, ExprCast,
21-
ExprField, ExprIndex, ExprParen, ExprReturn, ExprUnary, FnArg, ForeignItem, ForeignItemFn,
22-
ForeignItemMacro, ForeignItemStatic, ForeignItemType, Ident, Item, ItemConst, ItemEnum,
23-
ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct,
24-
ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Lit, MacroDelimiter, PathSegment,
25-
ReturnType, Stmt, Type, TypeTuple, UnOp, UseTree, Visibility,
21+
ExprParen, ExprReturn, ExprUnary, FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro,
22+
ForeignItemStatic, ForeignItemType, Ident, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
23+
ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait,
24+
ItemTraitAlias, ItemType, ItemUnion, ItemUse, Lit, MacroDelimiter, PathSegment, ReturnType,
25+
Stmt, Type, TypeTuple, UnOp, UseTree, Visibility,
2626
};
2727

2828
use crate::diagnostics::TranslationResult;

c2rust-transpile/src/translator/named_references.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,6 @@ fn is_lvalue(e: &Expr) -> bool {
1818
)
1919
}
2020

21-
/// Check if something is a side-effect free Rust lvalue.
22-
fn is_simple_lvalue(e: &Expr) -> bool {
23-
use Expr::*;
24-
match *unparen(e) {
25-
Path(..) => true,
26-
Unary(ExprUnary {
27-
op: syn::UnOp::Deref(_),
28-
ref expr,
29-
..
30-
})
31-
| Field(ExprField { base: ref expr, .. })
32-
| Index(ExprIndex { ref expr, .. }) => is_simple_lvalue(expr),
33-
_ => false,
34-
}
35-
}
36-
3721
pub struct NamedReference<R> {
3822
pub lvalue: Box<Expr>,
3923
pub rvalue: R,
@@ -106,18 +90,17 @@ impl<'c> Translation<'c> {
10690
.kind
10791
.get_qual_type()
10892
.ok_or_else(|| format_err!("bad reference type"))?;
93+
94+
let is_pure = self.ast_context.is_expr_pure(reference);
10995
let read = |write| self.read(reference_ty, write);
11096
let reference = self.convert_expr(ctx.used(), reference, Some(reference_ty))?;
11197
reference.and_then_try(|reference| {
112-
if !uses_read && is_lvalue(&reference) {
98+
if is_lvalue(&reference) && (is_pure || !uses_read) {
99+
let rvalue = uses_read.then(|| read(reference.clone())).transpose()?;
100+
113101
Ok(WithStmts::new_val(NamedReference {
114102
lvalue: reference,
115-
rvalue: None,
116-
}))
117-
} else if is_simple_lvalue(&reference) {
118-
Ok(WithStmts::new_val(NamedReference {
119-
lvalue: reference.clone(),
120-
rvalue: Some(read(reference)?),
103+
rvalue,
121104
}))
122105
} else {
123106
// This is the case where we explicitly need to factor out possible side-effects.

c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2021.clang15.snap

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,19 @@ pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() {
6262
arr[side_effect() as usize] -= 1;
6363
arr[side_effect() as usize] += 1;
6464
arr[side_effect() as usize] -= 1;
65-
arr[side_effect() as usize] += 1;
66-
let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize];
67-
arr[side_effect() as usize] -= 1;
68-
let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize];
69-
let c2rust_fresh0 = arr[side_effect() as usize];
70-
arr[side_effect() as usize] = arr[side_effect() as usize] + 1;
65+
let c2rust_lvalue = &raw mut arr[side_effect() as usize];
66+
*c2rust_lvalue += 1;
67+
let mut pre_inc: ::core::ffi::c_int = *c2rust_lvalue;
68+
let c2rust_lvalue_0 = &raw mut arr[side_effect() as usize];
69+
*c2rust_lvalue_0 -= 1;
70+
let mut pre_dec: ::core::ffi::c_int = *c2rust_lvalue_0;
71+
let c2rust_lvalue_1 = &raw mut arr[side_effect() as usize];
72+
let c2rust_fresh0 = *c2rust_lvalue_1;
73+
*c2rust_lvalue_1 = *c2rust_lvalue_1 + 1;
7174
let mut post_inc: ::core::ffi::c_int = c2rust_fresh0;
72-
let c2rust_fresh1 = arr[side_effect() as usize];
73-
arr[side_effect() as usize] = arr[side_effect() as usize] - 1;
75+
let c2rust_lvalue_2 = &raw mut arr[side_effect() as usize];
76+
let c2rust_fresh1 = *c2rust_lvalue_2;
77+
*c2rust_lvalue_2 = *c2rust_lvalue_2 - 1;
7478
let mut post_dec: ::core::ffi::c_int = c2rust_fresh1;
7579
}
7680
#[no_mangle]

c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.2024.clang15.snap

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,20 @@ pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() {
6262
arr[side_effect() as usize] -= 1;
6363
arr[side_effect() as usize] += 1;
6464
arr[side_effect() as usize] -= 1;
65-
arr[side_effect() as usize] += 1;
66-
let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize];
67-
arr[side_effect() as usize] -= 1;
68-
let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize];
69-
let c2rust_fresh0 = arr[side_effect() as usize];
70-
arr[side_effect() as usize] = arr[side_effect() as usize] + 1;
71-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh0;
72-
let c2rust_fresh1 = arr[side_effect() as usize];
73-
arr[side_effect() as usize] = arr[side_effect() as usize] - 1;
74-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh1;
65+
let c2rust_lvalue = &raw mut *lvalue_side_effect();
66+
*c2rust_lvalue += 1;
67+
let mut pre_inc: ::core::ffi::c_int = *c2rust_lvalue;
68+
let c2rust_lvalue_0 = &raw mut *lvalue_side_effect();
69+
*c2rust_lvalue_0 -= 1;
70+
let mut pre_dec: ::core::ffi::c_int = *c2rust_lvalue_0;
71+
let c2rust_lvalue_1 = &raw mut *lvalue_side_effect();
72+
let c2rust_fresh2 = *c2rust_lvalue_1;
73+
*c2rust_lvalue_1 = *c2rust_lvalue_1 + 1;
74+
let mut post_inc: ::core::ffi::c_int = c2rust_fresh2;
75+
let c2rust_lvalue_2 = &raw mut *lvalue_side_effect();
76+
let c2rust_fresh3 = *c2rust_lvalue_2;
77+
*c2rust_lvalue_2 = *c2rust_lvalue_2 - 1;
78+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh3;
7579
}
7680
#[unsafe(no_mangle)]
7781
pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() {
@@ -86,13 +90,13 @@ pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() {
8690
*c2rust_lvalue_0 -= 1;
8791
let mut pre_dec: ::core::ffi::c_int = *c2rust_lvalue_0;
8892
let c2rust_lvalue_1 = &raw mut *lvalue_side_effect();
89-
let c2rust_fresh2 = *c2rust_lvalue_1;
93+
let c2rust_lvalue_1 = *c2rust_lvalue_1;
9094
*c2rust_lvalue_1 = *c2rust_lvalue_1 + 1;
91-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh2;
95+
let mut post_inc: ::core::ffi::c_int = c2rust_lvalue_1;
9296
let c2rust_lvalue_2 = &raw mut *lvalue_side_effect();
93-
let c2rust_fresh3 = *c2rust_lvalue_2;
97+
let c2rust_fresh2 = *c2rust_lvalue_2;
9498
*c2rust_lvalue_2 = *c2rust_lvalue_2 - 1;
95-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh3;
99+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh2;
96100
}
97101
#[unsafe(no_mangle)]
98102
pub unsafe extern "C" fn unsigned_compound_desugaring() {

0 commit comments

Comments
 (0)