Skip to content

Commit a25706b

Browse files
authored
Fix rvalue usage of vector<bool>::reference (#576)
`vector<bool>::reference` is not a real reference type, it's a proxy. Handle that using ExprMapsValueToPointer which checks values, the vector bool reference, translated as pointers. Also use __a0 = a0 in the vector rules because I++ runs 2 times otherwise.
1 parent f349223 commit a25706b

8 files changed

Lines changed: 60 additions & 44 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1840,11 +1840,16 @@ bool Converter::ConvertSpecialCall(clang::CallExpr *expr) {
18401840
return false;
18411841
}
18421842

1843+
bool Converter::ExprMapsValueToPointer(const clang::CallExpr *expr) const {
1844+
return Mapper::Contains(ctx_, expr) && !expr->getType()->isPointerType() &&
1845+
RuleRegistry::MapsToPointer(ctx_, expr->getType());
1846+
}
1847+
18431848
void Converter::EmitCallResult(clang::CallExpr *expr, std::string str,
18441849
const TempMaterializationCtx *temps) {
18451850
bool deref = (GetReturnTypeOfFunction(expr)->isReferenceType() ||
18461851
(temps && IsReferenceType(expr))) &&
1847-
!isAddrOf() && !isVoid();
1852+
!isAddrOf() && !isVoid() && !ExprMapsValueToPointer(expr);
18481853
// The dereference is in the block of the temporaries, so they are still
18491854
// alive, as is the read of a field of the result.
18501855
if (deref && !(temps && Mapper::IsRefExpr(ctx_, expr))) {

‎cpp2rust/converter/converter.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
899899

900900
virtual bool IsReferenceType(const clang::Expr *expr) const;
901901

902+
bool ExprMapsValueToPointer(const clang::CallExpr *expr) const;
903+
902904
virtual bool RecordDerivesDefault(const clang::RecordDecl *decl);
903905

904906
virtual bool TypeDerivesDefault(clang::QualType qual_type);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ void ConverterRefCount::EmitCallResult(clang::CallExpr *expr, std::string str,
12371237
};
12381238
auto ty = GetReturnTypeOfFunction(expr);
12391239
if (auto *ref = ty->getAs<clang::ReferenceType>();
1240-
ref && !isAddrOf() && !isVoid()) {
1240+
ref && !isAddrOf() && !isVoid() && !ExprMapsValueToPointer(expr)) {
12411241
if (isLValue()) {
12421242
pending_deref_.set(wrap(std::move(str)), /*fresh=*/true);
12431243
return;

‎rules/vector/tgt_refcount.rs‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,19 @@ fn f118<T1>(a0: Ptr<bool>, a1: usize) -> Ptr<bool> {
160160
}
161161

162162
fn f119(a0: Ptr<bool>, a1: bool) -> Ptr<bool> {
163-
a0.write(a1);
164-
a0
163+
let __a0 = a0;
164+
__a0.write(a1);
165+
__a0
165166
}
166167

167168
fn f120(a0: Ptr<bool>, a1: bool) -> Ptr<bool> {
168-
a0.write(a1);
169-
a0
169+
let __a0 = a0;
170+
__a0.write(a1);
171+
__a0
170172
}
171173

172174
fn f121(a0: Ptr<bool>, a1: Ptr<bool>) -> Ptr<bool> {
173-
a0.write(a1.read());
174-
a0
175+
let __a0 = a0;
176+
__a0.write(a1.read());
177+
__a0
175178
}

‎rules/vector/tgt_unsafe.rs‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,16 +267,19 @@ unsafe fn f118<T1>(a0: &mut Vec<bool>, a1: usize) -> *mut bool {
267267
}
268268

269269
unsafe fn f119(a0: *mut bool, a1: bool) -> *mut bool {
270-
*a0 = a1;
271-
a0
270+
let __a0 = a0;
271+
*__a0 = a1;
272+
__a0
272273
}
273274

274275
unsafe fn f120(a0: *mut bool, a1: bool) -> *mut bool {
275-
*a0 = a1;
276-
a0
276+
let __a0 = a0;
277+
*__a0 = a1;
278+
__a0
277279
}
278280

279281
unsafe fn f121(a0: *mut bool, a1: *mut bool) -> *mut bool {
280-
*a0 = *a1;
281-
a0
282+
let __a0 = a0;
283+
*__a0 = *a1;
284+
__a0
282285
}

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,33 @@ fn main_0() -> i32 {
1515
let mut r1: Ptr<bool> = v1.decay().offset(0_usize as isize);
1616
assert!((v1.decay().offset(0_usize as isize).read()) && (r1.read()));
1717
{
18-
r1.write(false);
19-
(r1).clone()
18+
let __a0 = (r1).clone();
19+
__a0.write(false);
20+
__a0
2021
};
2122
assert!(!(v1.decay().offset(0_usize as isize).read()));
2223
let it: Value<RandomAccessIterator<bool>> = Rc::new(RefCell::new(v1.decay().begin()));
2324
let mut r2: Ptr<bool> = (*it.borrow()).iter_deref();
2425
{
25-
r2.write(true);
26-
(r2).clone()
26+
let __a0 = (r2).clone();
27+
__a0.write(true);
28+
__a0
2729
};
2830
assert!(v1.decay().offset(0_usize as isize).read());
2931
{
30-
v1.decay().offset(0_usize as isize).write(false);
31-
v1.decay().offset(0_usize as isize)
32+
let __a0 = v1.decay().offset(0_usize as isize);
33+
__a0.write(false);
34+
__a0
3235
};
3336
assert!(!(v1.decay().offset(0_usize as isize).read()));
3437
{
3538
let v: Value<Vec<bool>> = Rc::new(RefCell::new(Vec::from([false, false, false])));
3639
let mut i: i32 = 0;
37-
let mut b: bool = (*{
38-
v.decay()
39-
.offset((i.postfix_inc() as usize) as isize)
40-
.write(true);
41-
v.decay().offset((i.postfix_inc() as usize) as isize)
40+
let mut b: bool = {
41+
let __a0 = v.decay().offset((i.postfix_inc() as usize) as isize);
42+
__a0.write(true);
43+
__a0
4244
}
43-
.upgrade()
44-
.deref())
4545
.read();
4646
assert!(b);
4747
}

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,33 @@ unsafe fn main_0() -> i32 {
1717
let mut r1: *mut bool = (&mut (v1)[0_usize as usize] as *mut bool);
1818
assert!((*(&mut (v1)[0_usize as usize] as *mut bool)) && (*r1));
1919
{
20-
*r1 = false;
21-
r1
20+
let __a0 = r1;
21+
*__a0 = false;
22+
__a0
2223
};
2324
assert!(!(*(&mut (v1)[0_usize as usize] as *mut bool)));
2425
let mut it: UnsafeRandomAccessIterator<bool> = v1.begin();
2526
let mut r2: *mut bool = it.iter_deref();
2627
{
27-
*r2 = true;
28-
r2
28+
let __a0 = r2;
29+
*__a0 = true;
30+
__a0
2931
};
3032
assert!(*(&mut (v1)[0_usize as usize] as *mut bool));
3133
{
32-
*(&mut (v1)[0_usize as usize] as *mut bool) = false;
33-
(&mut (v1)[0_usize as usize] as *mut bool)
34+
let __a0 = (&mut (v1)[0_usize as usize] as *mut bool);
35+
*__a0 = false;
36+
__a0
3437
};
3538
assert!(!(*(&mut (v1)[0_usize as usize] as *mut bool)));
3639
{
3740
let mut v: Vec<bool> = Vec::from([false, false, false]);
3841
let mut i: i32 = 0;
39-
let mut b: bool = *(*{
40-
*(&mut (v)[(i.postfix_inc() as usize) as usize] as *mut bool) = true;
41-
(&mut (v)[(i.postfix_inc() as usize) as usize] as *mut bool)
42-
});
42+
let mut b: bool = *{
43+
let __a0 = (&mut (v)[(i.postfix_inc() as usize) as usize] as *mut bool);
44+
*__a0 = true;
45+
__a0
46+
};
4347
assert!(b);
4448
}
4549
return 0;

‎tests/unit/vector_bool_reference.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// XFAIL: refcount, unsafe
21
#include <cassert>
32
#include <vector>
43

@@ -14,11 +13,11 @@ int main() {
1413
assert(v1[0]);
1514
v1[0] = false;
1615
assert(!v1[0]);
17-
{
18-
std::vector<bool> v = {false, false, false };
19-
int i = 0;
20-
bool b = v[i++] = true;
21-
assert(b);
22-
}
16+
{
17+
std::vector<bool> v = {false, false, false};
18+
int i = 0;
19+
bool b = v[i++] = true;
20+
assert(b);
21+
}
2322
return 0;
2423
}

0 commit comments

Comments
 (0)