Skip to content

Commit 8d8680b

Browse files
authored
Convert operand as lvalue in array-to-pointer decay (#404)
1 parent 5e214e7 commit 8d8680b

4 files changed

Lines changed: 80 additions & 25 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2457,7 +2457,10 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
24572457
}
24582458
bool dest_pointee_const =
24592459
expr->getType()->getPointeeType().isConstQualified();
2460-
Convert(sub_expr);
2460+
{
2461+
PushExprKind push(*this, ExprKind::LValue);
2462+
Convert(sub_expr);
2463+
}
24612464
if (IsStringLiteralExpr(sub_expr)) {
24622465
StrCat(".as_ptr()");
24632466
if (!dest_pointee_const) {

‎tests/unit/array_reference.cpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ void fill(int (&a)[3], int v) {
2626

2727
int sum_twice(const int (&a)[3]) { return sum(a) + sum(a); }
2828

29+
int sum_ptr(const int *p) { return p[0] + p[1] + p[2]; }
30+
31+
int sum_decayed(const int (&a)[3]) { return sum_ptr(a); }
32+
33+
void bump_ptr(int *p) { p[0] += 1; }
34+
35+
void bump_decayed(int (&a)[3]) { bump_ptr(a); }
36+
2937
void fill_and_sum(int (&a)[3], int v, int &out) {
3038
fill(a, v);
3139
out = sum_twice(a);
@@ -74,6 +82,10 @@ int main() {
7482
assert(pts[0].x == 11);
7583
assert(pts[1].y == 14);
7684
assert(sum_points(pts) == 30);
85+
assert(sum_decayed(arr) == sum(arr));
86+
bump_decayed(arr);
87+
assert(arr[0] == 3);
88+
7789
const char *names[2] = {"ab", "cde"};
7890
assert(total_len(names) == 5);
7991
return 0;

‎tests/unit/out/refcount/array_reference.rs‎

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,26 @@ pub fn sum_twice_4(a: Ptr<Box<[i32]>>) -> i32 {
5252
return (({ sum_2(((a).clone() as Ptr<Box<[i32]>>)) })
5353
+ ({ sum_2(((a).clone() as Ptr<Box<[i32]>>)) }));
5454
}
55-
pub fn fill_and_sum_5(a: Ptr<Box<[i32]>>, v: i32, out: Ptr<i32>) {
55+
pub fn sum_ptr_5(p: Ptr<i32>) -> i32 {
56+
let p: Value<Ptr<i32>> = Rc::new(RefCell::new(p));
57+
return ((((*p.borrow()).offset((0) as isize).read())
58+
+ ((*p.borrow()).offset((1) as isize).read()))
59+
+ ((*p.borrow()).offset((2) as isize).read()));
60+
}
61+
pub fn sum_decayed_6(a: Ptr<Box<[i32]>>) -> i32 {
62+
return ({ sum_ptr_5((a.to_strong().as_pointer() as Ptr<i32>)) });
63+
}
64+
pub fn bump_ptr_7(p: Ptr<i32>) {
65+
let p: Value<Ptr<i32>> = Rc::new(RefCell::new(p));
66+
{
67+
let _ptr = (*p.borrow()).offset((0) as isize);
68+
_ptr.write(_ptr.read() + 1)
69+
};
70+
}
71+
pub fn bump_decayed_8(a: Ptr<Box<[i32]>>) {
72+
({ bump_ptr_7((a.to_strong().as_pointer() as Ptr<i32>)) });
73+
}
74+
pub fn fill_and_sum_9(a: Ptr<Box<[i32]>>, v: i32, out: Ptr<i32>) {
5675
let v: Value<i32> = Rc::new(RefCell::new(v));
5776
({
5877
let _a: Ptr<Box<[i32]>> = ((a).clone() as Ptr<Box<[i32]>>);
@@ -62,7 +81,7 @@ pub fn fill_and_sum_5(a: Ptr<Box<[i32]>>, v: i32, out: Ptr<i32>) {
6281
let __rhs = ({ sum_twice_4(((a).clone() as Ptr<Box<[i32]>>)) });
6382
out.write(__rhs);
6483
}
65-
pub fn pick_6(s: Ptr<Box<[u8]>>) -> Ptr<Box<[u8]>> {
84+
pub fn pick_10(s: Ptr<Box<[u8]>>) -> Ptr<Box<[u8]>> {
6685
return ((s).clone() as Ptr<Box<[u8]>>);
6786
}
6887
#[derive(Default)]
@@ -95,7 +114,7 @@ impl ByteRepr for Point {
95114
}
96115
}
97116
}
98-
pub fn sum_points_7(p: Ptr<Box<[Point]>>) -> i32 {
117+
pub fn sum_points_11(p: Ptr<Box<[Point]>>) -> i32 {
99118
return {
100119
let _lhs = {
101120
let _lhs = {
@@ -127,7 +146,7 @@ pub fn sum_points_7(p: Ptr<Box<[Point]>>) -> i32 {
127146
.borrow())
128147
};
129148
}
130-
pub fn shift_points_8(p: Ptr<Box<[Point]>>, d: i32) {
149+
pub fn shift_points_12(p: Ptr<Box<[Point]>>, d: i32) {
131150
let d: Value<i32> = Rc::new(RefCell::new(d));
132151
(*(*(p.to_strong().as_pointer() as Ptr<Point>)
133152
.offset((0) as isize)
@@ -142,7 +161,7 @@ pub fn shift_points_8(p: Ptr<Box<[Point]>>, d: i32) {
142161
.y
143162
.borrow_mut()) += (*d.borrow());
144163
}
145-
pub fn total_len_9(names: Ptr<Box<[Ptr<u8>]>>) -> i32 {
164+
pub fn total_len_13(names: Ptr<Box<[Ptr<u8>]>>) -> i32 {
146165
return (({
147166
len5_1(
148167
((names.to_strong().as_pointer() as Ptr<Ptr<u8>>)
@@ -173,21 +192,21 @@ fn main_0() -> i32 {
173192
assert!((({ sum_2((arr.as_pointer() as Ptr<Box<[i32]>>),) }) == 21));
174193
assert!((({ sum_twice_4((arr.as_pointer() as Ptr<Box<[i32]>>),) }) == 42));
175194
let out: Value<i32> = Rc::new(RefCell::new(0));
176-
({ fill_and_sum_5((arr.as_pointer() as Ptr<Box<[i32]>>), 2, out.as_pointer()) });
195+
({ fill_and_sum_9((arr.as_pointer() as Ptr<Box<[i32]>>), 2, out.as_pointer()) });
177196
assert!(((*out.borrow()) == 12));
178197
assert!(((*arr.borrow())[(0) as usize] == 2));
179198
let lit: Ptr<Box<[u8]>> = Ptr::<Box<[u8]>>::from_string_literal_array(b"beta");
180199
assert!((({ len_0(((lit).clone() as Ptr<Box<[u8]>>),) }) == 4));
181200
assert!(
182-
((((({ pick_6(Ptr::<Box<[u8]>>::from_string_literal_array(b"beta"),) })
201+
((((({ pick_10(Ptr::<Box<[u8]>>::from_string_literal_array(b"beta"),) })
183202
.to_strong()
184203
.as_pointer() as Ptr::<u8>)
185204
.offset((0) as isize)
186205
.read()) as i32)
187206
== (('b' as u8) as i32))
188207
);
189208
assert!(
190-
(({ len_0((({ pick_6((buf.as_pointer() as Ptr<Box<[u8]>>),) }) as Ptr<Box<[u8]>>),) })
209+
(({ len_0((({ pick_10((buf.as_pointer() as Ptr<Box<[u8]>>),) }) as Ptr<Box<[u8]>>),) })
191210
== 4)
192211
);
193212
let pts: Value<Box<[Point]>> = Rc::new(RefCell::new(Box::new([
@@ -200,16 +219,22 @@ fn main_0() -> i32 {
200219
y: Rc::new(RefCell::new(4)),
201220
},
202221
])));
203-
assert!((({ sum_points_7((pts.as_pointer() as Ptr<Box<[Point]>>),) }) == 10));
204-
({ shift_points_8((pts.as_pointer() as Ptr<Box<[Point]>>), 10) });
222+
assert!((({ sum_points_11((pts.as_pointer() as Ptr<Box<[Point]>>),) }) == 10));
223+
({ shift_points_12((pts.as_pointer() as Ptr<Box<[Point]>>), 10) });
205224
assert!(((*(*pts.borrow())[(0) as usize].x.borrow()) == 11));
206225
assert!(((*(*pts.borrow())[(1) as usize].y.borrow()) == 14));
207-
assert!((({ sum_points_7((pts.as_pointer() as Ptr<Box<[Point]>>),) }) == 30));
226+
assert!((({ sum_points_11((pts.as_pointer() as Ptr<Box<[Point]>>),) }) == 30));
227+
assert!(
228+
(({ sum_decayed_6((arr.as_pointer() as Ptr<Box<[i32]>>),) })
229+
== ({ sum_2((arr.as_pointer() as Ptr<Box<[i32]>>),) }))
230+
);
231+
({ bump_decayed_8((arr.as_pointer() as Ptr<Box<[i32]>>)) });
232+
assert!(((*arr.borrow())[(0) as usize] == 3));
208233
let names: Value<Box<[Ptr<u8>]>> = Rc::new(RefCell::new(Box::new([
209234
Ptr::<u8>::from_string_literal(b"ab"),
210235
Ptr::<u8>::from_string_literal(b"cde"),
211236
])));
212-
assert!((({ total_len_9((names.as_pointer() as Ptr<Box<[Ptr::<u8>]>>),) }) == 5));
237+
assert!((({ total_len_13((names.as_pointer() as Ptr<Box<[Ptr::<u8>]>>),) }) == 5));
213238
return 0;
214239
}
215240
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/array_reference.rs‎

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,27 @@ pub unsafe fn fill_3(a: *mut [i32; 3], mut v: i32) {
3333
pub unsafe fn sum_twice_4(a: *const [i32; 3]) -> i32 {
3434
return ((unsafe { sum_2(a) }) + (unsafe { sum_2(a) }));
3535
}
36-
pub unsafe fn fill_and_sum_5(a: *mut [i32; 3], mut v: i32, out: *mut i32) {
36+
pub unsafe fn sum_ptr_5(mut p: *const i32) -> i32 {
37+
return (((*p.offset((0) as isize)) + (*p.offset((1) as isize))) + (*p.offset((2) as isize)));
38+
}
39+
pub unsafe fn sum_decayed_6(a: *const [i32; 3]) -> i32 {
40+
return (unsafe { sum_ptr_5((*a).as_ptr()) });
41+
}
42+
pub unsafe fn bump_ptr_7(mut p: *mut i32) {
43+
(*p.offset((0) as isize)) += 1;
44+
}
45+
pub unsafe fn bump_decayed_8(a: *mut [i32; 3]) {
46+
(unsafe { bump_ptr_7((*a).as_mut_ptr()) });
47+
}
48+
pub unsafe fn fill_and_sum_9(a: *mut [i32; 3], mut v: i32, out: *mut i32) {
3749
(unsafe {
3850
let _a: *mut [i32; 3] = a;
3951
let _v: i32 = v;
4052
fill_3(_a, _v)
4153
});
4254
(*out) = (unsafe { sum_twice_4(a) });
4355
}
44-
pub unsafe fn pick_6(s: *const [libc::c_char; 5]) -> *const [libc::c_char; 5] {
56+
pub unsafe fn pick_10(s: *const [libc::c_char; 5]) -> *const [libc::c_char; 5] {
4557
return s;
4658
}
4759
#[repr(C)]
@@ -50,15 +62,15 @@ pub struct Point {
5062
pub x: i32,
5163
pub y: i32,
5264
}
53-
pub unsafe fn sum_points_7(p: *const [Point; 2]) -> i32 {
65+
pub unsafe fn sum_points_11(p: *const [Point; 2]) -> i32 {
5466
return (((((*p)[(0) as usize].x) + ((*p)[(0) as usize].y)) + ((*p)[(1) as usize].x))
5567
+ ((*p)[(1) as usize].y));
5668
}
57-
pub unsafe fn shift_points_8(p: *mut [Point; 2], mut d: i32) {
69+
pub unsafe fn shift_points_12(p: *mut [Point; 2], mut d: i32) {
5870
(*p)[(0) as usize].x += d;
5971
(*p)[(1) as usize].y += d;
6072
}
61-
pub unsafe fn total_len_9(names: *mut [*const libc::c_char; 2]) -> i32 {
73+
pub unsafe fn total_len_13(names: *mut [*const libc::c_char; 2]) -> i32 {
6274
return ((unsafe { len5_1((*names)[(0) as usize]) })
6375
+ (unsafe { len5_1((*names)[(1) as usize]) }));
6476
}
@@ -78,24 +90,27 @@ unsafe fn main_0() -> i32 {
7890
assert!(((unsafe { sum_2(&arr,) }) == (21)));
7991
assert!(((unsafe { sum_twice_4(&arr,) }) == (42)));
8092
let mut out: i32 = 0;
81-
(unsafe { fill_and_sum_5(&mut arr, 2, &mut out) });
93+
(unsafe { fill_and_sum_9(&mut arr, 2, &mut out) });
8294
assert!(((out) == (12)));
8395
assert!(((arr[(0) as usize]) == (2)));
8496
let lit: *const [libc::c_char; 5] = &std::mem::transmute(*b"beta\0");
8597
assert!(((unsafe { len_0(lit,) }) == (4)));
8698
assert!(
87-
(((*(unsafe { pick_6(&std::mem::transmute(*b"beta\0"),) }))[(0) as usize] as i32)
99+
(((*(unsafe { pick_10(&std::mem::transmute(*b"beta\0"),) }))[(0) as usize] as i32)
88100
== (('b' as libc::c_char) as i32))
89101
);
90-
assert!(((unsafe { len_0((unsafe { pick_6(&buf,) }),) }) == (4)));
102+
assert!(((unsafe { len_0((unsafe { pick_10(&buf,) }),) }) == (4)));
91103
let mut pts: [Point; 2] = [Point { x: 1, y: 2 }, Point { x: 3, y: 4 }];
92-
assert!(((unsafe { sum_points_7(&pts,) }) == (10)));
93-
(unsafe { shift_points_8(&mut pts, 10) });
104+
assert!(((unsafe { sum_points_11(&pts,) }) == (10)));
105+
(unsafe { shift_points_12(&mut pts, 10) });
94106
assert!(((pts[(0) as usize].x) == (11)));
95107
assert!(((pts[(1) as usize].y) == (14)));
96-
assert!(((unsafe { sum_points_7(&pts,) }) == (30)));
108+
assert!(((unsafe { sum_points_11(&pts,) }) == (30)));
109+
assert!(((unsafe { sum_decayed_6(&arr,) }) == (unsafe { sum_2(&arr,) })));
110+
(unsafe { bump_decayed_8(&mut arr) });
111+
assert!(((arr[(0) as usize]) == (3)));
97112
let mut names: [*const libc::c_char; 2] = [c"ab".as_ptr(), c"cde".as_ptr()];
98-
assert!(((unsafe { total_len_9(&mut names,) }) == (5)));
113+
assert!(((unsafe { total_len_13(&mut names,) }) == (5)));
99114
return 0;
100115
}
101116
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)