Skip to content

Commit 054611a

Browse files
authored
Fix array pointer dereference and temporary array materialisation (#487)
1 parent 5931047 commit 054611a

4 files changed

Lines changed: 89 additions & 5 deletions

File tree

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,19 @@ ConverterRefCount::MaterializeTemp(const std::string &binding_name,
500500
clang::QualType param_type,
501501
clang::Expr *expr) {
502502
auto pointee = param_type.getNonReferenceType();
503-
auto value = ConvertFreshRValue(expr, pointee);
504-
auto type_str = ToStringBase(pointee);
505503
const auto *decl = in_const_initializer_ ? keyword::kStatic : keyword::kLet;
506-
507-
auto binding = std::format("{} {} : Value<{}> = Rc::new(RefCell::new({}));",
508-
decl, binding_name, type_str, value);
504+
std::string binding;
505+
if (pointee->isConstantArrayType()) {
506+
PushConversionKind push(*this, ConversionKind::FullRefCount);
507+
binding =
508+
std::format("{} {} : {} = {};", decl, binding_name, ToString(pointee),
509+
BoxValue(ConvertVarInitValue(pointee, expr)));
510+
} else {
511+
auto value = ConvertFreshRValue(expr, pointee);
512+
auto type_str = ToStringBase(pointee);
513+
binding = std::format("{} {} : Value<{}> = Rc::new(RefCell::new({}));",
514+
decl, binding_name, type_str, value);
515+
}
509516
auto ref =
510517
in_const_initializer_ ? ".with(Value::as_pointer)" : ".as_pointer()";
511518
return {binding, binding_name + ref};
@@ -3041,6 +3048,9 @@ void ConverterRefCount::ConvertPointerSubscript(
30413048
ConvertPointerElem(base, idx);
30423049
} else {
30433050
ConvertPointerOffset(base, idx);
3051+
if (expr->getType()->isArrayType()) {
3052+
StrCat(GetPointerDerefSuffix(expr->getType()), ".as_pointer()");
3053+
}
30443054
}
30453055
if (deref) {
30463056
StrCat(GetPointerDerefSuffix(expr->getType()));
@@ -3122,6 +3132,11 @@ void ConverterRefCount::ConvertDeref(clang::Expr *expr) {
31223132
str = std::move(buf).str();
31233133
}
31243134

3135+
if (isAddrOf() && pointee_type->isArrayType()) {
3136+
str = std::format("({}){}.as_pointer()", std::move(str),
3137+
GetPointerDerefSuffix(pointee_type));
3138+
}
3139+
31253140
if (isObject() && WantsElementPtr() &&
31263141
(IsBoxedType(ctx_, pointee_type) || pointee_type->isArrayType())) {
31273142
StrCat(std::format("Ptr::<{}>::decay(&({}))", ToString(pointee_type),

‎tests/unit/array_reference.cpp‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ int main() {
6565
assert(len(buf) == 4);
6666
int arr[3] = {1, 2, 3};
6767
assert(sum(arr) == 6);
68+
assert(sum({1, 2, 3}) == 6);
6869
fill(arr, 7);
6970
assert(sum(arr) == 21);
7071
assert(sum_twice(arr) == 42);
@@ -88,5 +89,17 @@ int main() {
8889

8990
const char *names[2] = {"ab", "cde"};
9091
assert(total_len(names) == 5);
92+
93+
int rows[2][3] = {{1, 2, 3}, {4, 5, 6}};
94+
int (*p)[3] = rows;
95+
++p;
96+
assert(*p == &rows[1][0]);
97+
int (&r)[3] = *p;
98+
assert(r[0] == 4);
99+
assert(sum(r) == 15);
100+
assert(sum(*p) == 15);
101+
int (*q)[3] = rows;
102+
assert(sum(q[1]) == 15);
103+
assert(q[1] == &rows[1][0]);
91104
return 0;
92105
}

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ fn main_0() -> i32 {
9999
assert!((({ len_0(buf.as_pointer(),) }) == 4));
100100
let arr: Value<Box<[i32]>> = Rc::new(RefCell::new(Box::new([1, 2, 3])));
101101
assert!((({ sum_2(arr.as_pointer(),) }) == 6));
102+
assert!(
103+
(({
104+
let _a: Value<Box<[i32]>> = Rc::new(RefCell::new(Box::new([1, 2, 3])));
105+
sum_2(_a.as_pointer())
106+
}) == 6)
107+
);
102108
({ fill_3(arr.as_pointer(), 7) });
103109
assert!((({ sum_2(arr.as_pointer(),) }) == 21));
104110
assert!((({ sum_twice_4(arr.as_pointer(),) }) == 42));
@@ -130,6 +136,36 @@ fn main_0() -> i32 {
130136
Ptr::<i8>::from_string_literal(b"cde"),
131137
])));
132138
assert!((({ total_len_13(names.as_pointer(),) }) == 5));
139+
let rows: Value<Box<[Value<Box<[i32]>>]>> = Rc::new(RefCell::new(Box::new([
140+
Rc::new(RefCell::new(Box::new([1, 2, 3]))),
141+
Rc::new(RefCell::new(Box::new([4, 5, 6]))),
142+
])));
143+
let mut p: Ptr<Value<Box<[i32]>>> = (rows.as_pointer() as Ptr<Value<Box<[i32]>>>);
144+
p.prefix_inc();
145+
assert!(
146+
({ ((p).read().as_pointer() as Ptr::<i32>).clone() } == {
147+
((((rows.as_pointer() as Ptr<Value<Box<[i32]>>>)
148+
.offset(1)
149+
.read()
150+
.as_pointer()) as Ptr<i32>)
151+
.offset(0))
152+
})
153+
);
154+
let r: Ptr<i32> = ((p).read().as_pointer()).clone();
155+
assert!(((elem!((r), 0).read()) == 4));
156+
assert!((({ sum_2((r).clone(),) }) == 15));
157+
assert!((({ sum_2(((p).read().as_pointer()).clone(),) }) == 15));
158+
let mut q: Ptr<Value<Box<[i32]>>> = (rows.as_pointer() as Ptr<Value<Box<[i32]>>>);
159+
assert!((({ sum_2(q.offset((1) as isize).read().as_pointer(),) }) == 15));
160+
assert!(
161+
({ (q.offset((1) as isize).read().as_pointer() as Ptr::<i32>) } == {
162+
((((rows.as_pointer() as Ptr<Value<Box<[i32]>>>)
163+
.offset(1)
164+
.read()
165+
.as_pointer()) as Ptr<i32>)
166+
.offset(0))
167+
})
168+
);
133169
return 0;
134170
}
135171
pub fn __cpp2rust_init_globals() {}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ unsafe fn main_0() -> i32 {
8686
assert!(((unsafe { len_0(&buf,) }) == (4)));
8787
let mut arr: [i32; 3] = [1, 2, 3];
8888
assert!(((unsafe { sum_2(&arr,) }) == (6)));
89+
assert!(
90+
((unsafe {
91+
let mut _a: [i32; 3] = [1, 2, 3];
92+
sum_2(&mut _a)
93+
}) == (6))
94+
);
8995
(unsafe { fill_3(&mut arr, 7) });
9096
assert!(((unsafe { sum_2(&arr,) }) == (21)));
9197
assert!(((unsafe { sum_twice_4(&arr,) }) == (42)));
@@ -111,6 +117,20 @@ unsafe fn main_0() -> i32 {
111117
assert!(((arr[(0) as usize]) == (3)));
112118
let mut names: [*const libc::c_char; 2] = [c"ab".as_ptr(), c"cde".as_ptr()];
113119
assert!(((unsafe { total_len_13(&mut names,) }) == (5)));
120+
let mut rows: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]];
121+
let mut p: *mut [i32; 3] = rows.as_mut_ptr();
122+
p.prefix_inc();
123+
assert!((((*p).as_mut_ptr()) == (&mut rows[(1) as usize][(0) as usize] as *mut i32)));
124+
let r: *mut [i32; 3] = &mut (*p);
125+
assert!((((*r)[(0) as usize]) == (4)));
126+
assert!(((unsafe { sum_2(r,) }) == (15)));
127+
assert!(((unsafe { sum_2(&(*p),) }) == (15)));
128+
let mut q: *mut [i32; 3] = rows.as_mut_ptr();
129+
assert!(((unsafe { sum_2(&(*q.offset((1) as isize)),) }) == (15)));
130+
assert!(
131+
(((*q.offset((1) as isize)).as_mut_ptr())
132+
== (&mut rows[(1) as usize][(0) as usize] as *mut i32))
133+
);
114134
return 0;
115135
}
116136
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)