Skip to content

Commit f39150f

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

4 files changed

Lines changed: 65 additions & 74 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.snap

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,37 +63,41 @@ pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() {
6363
arr[side_effect() as usize] -= 1;
6464
arr[side_effect() as usize] += 1;
6565
arr[side_effect() as usize] -= 1;
66-
arr[side_effect() as usize] += 1;
67-
let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize];
68-
arr[side_effect() as usize] -= 1;
69-
let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize];
70-
let c2rust_fresh0 = arr[side_effect() as usize];
71-
arr[side_effect() as usize] = arr[side_effect() as usize] + 1;
72-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh0;
73-
let c2rust_fresh1 = arr[side_effect() as usize];
74-
arr[side_effect() as usize] = arr[side_effect() as usize] - 1;
75-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh1;
66+
let c2rust_fresh0 = &raw mut arr[side_effect() as usize];
67+
*c2rust_fresh0 += 1;
68+
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh0;
69+
let c2rust_fresh1 = &raw mut arr[side_effect() as usize];
70+
*c2rust_fresh1 -= 1;
71+
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh1;
72+
let c2rust_fresh2 = &raw mut arr[side_effect() as usize];
73+
let c2rust_fresh3 = *c2rust_fresh2;
74+
*c2rust_fresh2 = *c2rust_fresh2 + 1;
75+
let mut post_inc: ::core::ffi::c_int = c2rust_fresh3;
76+
let c2rust_fresh4 = &raw mut arr[side_effect() as usize];
77+
let c2rust_fresh5 = *c2rust_fresh4;
78+
*c2rust_fresh4 = *c2rust_fresh4 - 1;
79+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh5;
7680
}
7781
#[no_mangle]
7882
pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() {
7983
*lvalue_side_effect() += 1;
8084
*lvalue_side_effect() -= 1;
8185
*lvalue_side_effect() += 1;
8286
*lvalue_side_effect() -= 1;
83-
let c2rust_fresh2 = &raw mut *lvalue_side_effect();
84-
*c2rust_fresh2 += 1;
85-
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh2;
86-
let c2rust_fresh3 = &raw mut *lvalue_side_effect();
87-
*c2rust_fresh3 -= 1;
88-
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh3;
89-
let c2rust_fresh4 = &raw mut *lvalue_side_effect();
90-
let c2rust_fresh5 = *c2rust_fresh4;
91-
*c2rust_fresh4 = *c2rust_fresh4 + 1;
92-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh5;
9387
let c2rust_fresh6 = &raw mut *lvalue_side_effect();
94-
let c2rust_fresh7 = *c2rust_fresh6;
95-
*c2rust_fresh6 = *c2rust_fresh6 - 1;
96-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh7;
88+
*c2rust_fresh6 += 1;
89+
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh6;
90+
let c2rust_fresh7 = &raw mut *lvalue_side_effect();
91+
*c2rust_fresh7 -= 1;
92+
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh7;
93+
let c2rust_fresh8 = &raw mut *lvalue_side_effect();
94+
let c2rust_fresh9 = *c2rust_fresh8;
95+
*c2rust_fresh8 = *c2rust_fresh8 + 1;
96+
let mut post_inc: ::core::ffi::c_int = c2rust_fresh9;
97+
let c2rust_fresh10 = &raw mut *lvalue_side_effect();
98+
let c2rust_fresh11 = *c2rust_fresh10;
99+
*c2rust_fresh10 = *c2rust_fresh10 - 1;
100+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh11;
97101
}
98102
#[no_mangle]
99103
pub unsafe extern "C" fn unsigned_compound_desugaring() {

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

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,37 +63,41 @@ pub unsafe extern "C" fn inc_decl_with_rvalue_side_effect() {
6363
arr[side_effect() as usize] -= 1;
6464
arr[side_effect() as usize] += 1;
6565
arr[side_effect() as usize] -= 1;
66-
arr[side_effect() as usize] += 1;
67-
let mut pre_inc: ::core::ffi::c_int = arr[side_effect() as usize];
68-
arr[side_effect() as usize] -= 1;
69-
let mut pre_dec: ::core::ffi::c_int = arr[side_effect() as usize];
70-
let c2rust_fresh0 = arr[side_effect() as usize];
71-
arr[side_effect() as usize] = arr[side_effect() as usize] + 1;
72-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh0;
73-
let c2rust_fresh1 = arr[side_effect() as usize];
74-
arr[side_effect() as usize] = arr[side_effect() as usize] - 1;
75-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh1;
66+
let c2rust_fresh0 = &raw mut arr[side_effect() as usize];
67+
*c2rust_fresh0 += 1;
68+
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh0;
69+
let c2rust_fresh1 = &raw mut arr[side_effect() as usize];
70+
*c2rust_fresh1 -= 1;
71+
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh1;
72+
let c2rust_fresh2 = &raw mut arr[side_effect() as usize];
73+
let c2rust_fresh3 = *c2rust_fresh2;
74+
*c2rust_fresh2 = *c2rust_fresh2 + 1;
75+
let mut post_inc: ::core::ffi::c_int = c2rust_fresh3;
76+
let c2rust_fresh4 = &raw mut arr[side_effect() as usize];
77+
let c2rust_fresh5 = *c2rust_fresh4;
78+
*c2rust_fresh4 = *c2rust_fresh4 - 1;
79+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh5;
7680
}
7781
#[unsafe(no_mangle)]
7882
pub unsafe extern "C" fn inc_decl_with_lvalue_side_effect() {
7983
*lvalue_side_effect() += 1;
8084
*lvalue_side_effect() -= 1;
8185
*lvalue_side_effect() += 1;
8286
*lvalue_side_effect() -= 1;
83-
let c2rust_fresh2 = &raw mut *lvalue_side_effect();
84-
*c2rust_fresh2 += 1;
85-
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh2;
86-
let c2rust_fresh3 = &raw mut *lvalue_side_effect();
87-
*c2rust_fresh3 -= 1;
88-
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh3;
89-
let c2rust_fresh4 = &raw mut *lvalue_side_effect();
90-
let c2rust_fresh5 = *c2rust_fresh4;
91-
*c2rust_fresh4 = *c2rust_fresh4 + 1;
92-
let mut post_inc: ::core::ffi::c_int = c2rust_fresh5;
9387
let c2rust_fresh6 = &raw mut *lvalue_side_effect();
94-
let c2rust_fresh7 = *c2rust_fresh6;
95-
*c2rust_fresh6 = *c2rust_fresh6 - 1;
96-
let mut post_dec: ::core::ffi::c_int = c2rust_fresh7;
88+
*c2rust_fresh6 += 1;
89+
let mut pre_inc: ::core::ffi::c_int = *c2rust_fresh6;
90+
let c2rust_fresh7 = &raw mut *lvalue_side_effect();
91+
*c2rust_fresh7 -= 1;
92+
let mut pre_dec: ::core::ffi::c_int = *c2rust_fresh7;
93+
let c2rust_fresh8 = &raw mut *lvalue_side_effect();
94+
let c2rust_fresh9 = *c2rust_fresh8;
95+
*c2rust_fresh8 = *c2rust_fresh8 + 1;
96+
let mut post_inc: ::core::ffi::c_int = c2rust_fresh9;
97+
let c2rust_fresh10 = &raw mut *lvalue_side_effect();
98+
let c2rust_fresh11 = *c2rust_fresh10;
99+
*c2rust_fresh10 = *c2rust_fresh10 - 1;
100+
let mut post_dec: ::core::ffi::c_int = c2rust_fresh11;
97101
}
98102
#[unsafe(no_mangle)]
99103
pub unsafe extern "C" fn unsigned_compound_desugaring() {

0 commit comments

Comments
 (0)