Skip to content

Commit 30e51ad

Browse files
committed
Fix hoisted initialization outside goto_block
1 parent 6b0264a commit 30e51ad

4 files changed

Lines changed: 103 additions & 1 deletion

File tree

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ void ConverterRefCount::EmitHoistedInArmAssignment(clang::VarDecl *decl) {
726726
PushConversionKind push(*this, ConversionKind::Unboxed);
727727
StrCat(token::kStar, GetNamedDeclAsString(decl), ".borrow_mut()",
728728
token::kAssign);
729-
Convert(decl->getInit());
729+
StrCat(ConvertFreshRValue(decl->getInit(), decl->getType()));
730730
StrCat(token::kSemiColon);
731731
}
732732

tests/unit/goto_cleanup.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,32 @@ static int from_switch(int n) {
4141
return ret;
4242
}
4343

44+
struct wrapper {
45+
int *item;
46+
};
47+
48+
static int via_pointer(struct wrapper *w, int fail) {
49+
int ret = 0;
50+
int *item = w->item;
51+
if (fail) {
52+
ret = -1;
53+
goto out;
54+
}
55+
ret = *item;
56+
out:
57+
return ret;
58+
}
59+
4460
int main(void) {
4561
assert(early(-1) == -1);
4662
assert(early(5) == 100);
4763
assert(from_loop(2) == 999);
4864
assert(from_loop(10) == 7);
4965
assert(from_switch(1) == 10);
5066
assert(from_switch(2) == 999);
67+
int value = 42;
68+
struct wrapper w = {&value};
69+
assert(via_pointer(&w, 0) == 42);
70+
assert(via_pointer(&w, 1) == -1);
5171
return 0;
5272
}

tests/unit/out/refcount/goto_cleanup.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,52 @@ pub fn from_switch_2(n: i32) -> i32 {
7777
});
7878
panic!("ub: non-void function does not return a value")
7979
}
80+
#[derive(Default)]
81+
pub struct wrapper {
82+
pub item: Value<Ptr<i32>>,
83+
}
84+
impl Clone for wrapper {
85+
fn clone(&self) -> Self {
86+
Self {
87+
item: Rc::new(RefCell::new((*self.item.borrow()).clone())),
88+
}
89+
}
90+
}
91+
impl ByteRepr for wrapper {
92+
fn byte_size() -> usize {
93+
8
94+
}
95+
fn to_bytes(&self, buf: &mut [u8]) {
96+
(*self.item.borrow()).to_bytes(&mut buf[0..8]);
97+
}
98+
fn from_bytes(buf: &[u8]) -> Self {
99+
Self {
100+
item: Rc::new(RefCell::new(<Ptr<i32>>::from_bytes(&buf[0..8]))),
101+
}
102+
}
103+
}
104+
pub fn via_pointer_3(w: Ptr<wrapper>, fail: i32) -> i32 {
105+
let w: Value<Ptr<wrapper>> = Rc::new(RefCell::new(w));
106+
let fail: Value<i32> = Rc::new(RefCell::new(fail));
107+
let ret: Value<i32> = <Value<i32>>::default();
108+
let item: Value<Ptr<i32>> = Rc::new(RefCell::new(Ptr::<i32>::null()));
109+
goto_block!({
110+
'__entry: {
111+
*ret.borrow_mut() = 0;
112+
*item.borrow_mut() = (*(*(*w.borrow()).upgrade().deref()).item.borrow()).clone();
113+
if ((*fail.borrow()) != 0) {
114+
(*ret.borrow_mut()) = -1_i32;
115+
goto!('out);
116+
}
117+
let __rhs = ((*item.borrow()).read());
118+
(*ret.borrow_mut()) = __rhs;
119+
}
120+
'out: {
121+
return (*ret.borrow());
122+
}
123+
});
124+
panic!("ub: non-void function does not return a value")
125+
}
80126
pub fn main() {
81127
std::process::exit(main_0());
82128
}
@@ -87,5 +133,11 @@ fn main_0() -> i32 {
87133
assert!((((({ from_loop_1(10,) }) == 7) as i32) != 0));
88134
assert!((((({ from_switch_2(1,) }) == 10) as i32) != 0));
89135
assert!((((({ from_switch_2(2,) }) == 999) as i32) != 0));
136+
let value: Value<i32> = Rc::new(RefCell::new(42));
137+
let w: Value<wrapper> = Rc::new(RefCell::new(wrapper {
138+
item: Rc::new(RefCell::new((value.as_pointer()))),
139+
}));
140+
assert!((((({ via_pointer_3((w.as_pointer()), 0,) }) == 42) as i32) != 0));
141+
assert!((((({ via_pointer_3((w.as_pointer()), 1,) }) == -1_i32) as i32) != 0));
90142
return 0;
91143
}

tests/unit/out/unsafe/goto_cleanup.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,30 @@ pub unsafe fn from_switch_2(mut n: i32) -> i32 {
7373
});
7474
panic!("ub: non-void function does not return a value")
7575
}
76+
#[repr(C)]
77+
#[derive(Copy, Clone, Default)]
78+
pub struct wrapper {
79+
pub item: *mut i32,
80+
}
81+
pub unsafe fn via_pointer_3(mut w: *mut wrapper, mut fail: i32) -> i32 {
82+
let mut ret: i32 = 0_i32;
83+
let mut item: *mut i32 = std::ptr::null_mut();
84+
goto_block!({
85+
'__entry: {
86+
ret = 0;
87+
item = (*w).item;
88+
if (fail != 0) {
89+
ret = -1_i32;
90+
goto!('out);
91+
}
92+
ret = (*item);
93+
}
94+
'out: {
95+
return ret;
96+
}
97+
});
98+
panic!("ub: non-void function does not return a value")
99+
}
76100
pub fn main() {
77101
unsafe {
78102
std::process::exit(main_0() as i32);
@@ -85,5 +109,11 @@ unsafe fn main_0() -> i32 {
85109
assert!(((((unsafe { from_loop_1(10,) }) == (7)) as i32) != 0));
86110
assert!(((((unsafe { from_switch_2(1,) }) == (10)) as i32) != 0));
87111
assert!(((((unsafe { from_switch_2(2,) }) == (999)) as i32) != 0));
112+
let mut value: i32 = 42;
113+
let mut w: wrapper = wrapper {
114+
item: (&mut value as *mut i32),
115+
};
116+
assert!(((((unsafe { via_pointer_3((&mut w as *mut wrapper), 0,) }) == (42)) as i32) != 0));
117+
assert!(((((unsafe { via_pointer_3((&mut w as *mut wrapper), 1,) }) == (-1_i32)) as i32) != 0));
88118
return 0;
89119
}

0 commit comments

Comments
 (0)