Skip to content

Commit a895429

Browse files
committed
transpile: In name_reference, also check expression for side effects
1 parent 5a1bd5f commit a895429

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.clang15.snap

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

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

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

0 commit comments

Comments
 (0)