Skip to content

Commit d3cec4b

Browse files
authored
Fix address of conditional operand (#403)
1 parent 104607b commit d3cec4b

5 files changed

Lines changed: 101 additions & 6 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,10 +2958,11 @@ bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) {
29582958
ConvertCondition(expr->getCond());
29592959
bool branch_is_addr =
29602960
expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType();
2961+
bool branch_is_mut = curr_init_type_.empty() || IsMut(curr_init_type_.back());
29612962
{
29622963
PushBrace then_brace(*this);
29632964
if (branch_is_addr) {
2964-
StrCat(token::kRef, keyword_mut_);
2965+
StrCat(token::kRef, branch_is_mut ? keyword_mut_ : "");
29652966
}
29662967
PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::nullopt
29672968
: autoref_mut_);
@@ -2973,7 +2974,7 @@ bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) {
29732974
{
29742975
PushBrace else_brace(*this);
29752976
if (branch_is_addr) {
2976-
StrCat(token::kRef, keyword_mut_);
2977+
StrCat(token::kRef, branch_is_mut ? keyword_mut_ : "");
29772978
}
29782979
PushExplicitAutoref no_autoref(*this, branch_is_addr ? std::nullopt
29792980
: autoref_mut_);
@@ -4190,6 +4191,18 @@ void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) {
41904191
StrCat(EmitMaterializedTempBinding(qual_type, expr));
41914192
return;
41924193
}
4194+
if (auto *cond = clang::dyn_cast<clang::ConditionalOperator>(
4195+
expr->IgnoreParenImpCasts());
4196+
cond && cond->isLValue()) {
4197+
{
4198+
PushExprKind push(*this, ExprKind::LValue);
4199+
PushInitType init_type(*this, qual_type);
4200+
Convert(cond);
4201+
}
4202+
StrCat(keyword::kAs);
4203+
Convert(qual_type);
4204+
return;
4205+
}
41934206
StrCat(token::kRef);
41944207
if (IsMut(qual_type)) {
41954208
StrCat(keyword_mut_);

‎tests/unit/09_references.cpp‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,26 @@ int main() {
1111
h_ref2 = 17;
1212

1313
assert(h_ref1 + h_ref2 == 34);
14+
15+
int a = 1;
16+
int b = 2;
17+
int &r = a < b ? a : b;
18+
r = 10;
19+
assert(a == 10);
20+
21+
const int &cr = a > b ? a : b;
22+
assert(cr == 10);
23+
24+
const int x = 1;
25+
const int y = 2;
26+
const int &cx = x < y ? x : y;
27+
assert(cx == 1);
28+
29+
const int *cp = a > b ? &a : &b;
30+
assert(*cp == 10);
31+
32+
int *mp = a < b ? &a : &b;
33+
*mp = 20;
34+
assert(b == 20);
1435
return 0;
1536
}

‎tests/unit/out/refcount/09_references.rs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,42 @@ fn main_0() -> i32 {
2323
_lhs + (h_ref2.read())
2424
} == 34)
2525
);
26+
let a: Value<i32> = Rc::new(RefCell::new(1));
27+
let b: Value<i32> = Rc::new(RefCell::new(2));
28+
let r: Ptr<i32> = if ((*a.borrow()) < (*b.borrow())) {
29+
a.as_pointer()
30+
} else {
31+
b.as_pointer()
32+
};
33+
r.write(10);
34+
assert!(((*a.borrow()) == 10));
35+
let cr: Ptr<i32> = if ((*a.borrow()) > (*b.borrow())) {
36+
a.as_pointer()
37+
} else {
38+
b.as_pointer()
39+
};
40+
assert!(((cr.read()) == 10));
41+
let x: Value<i32> = Rc::new(RefCell::new(1));
42+
let y: Value<i32> = Rc::new(RefCell::new(2));
43+
let cx: Ptr<i32> = if ((*x.borrow()) < (*y.borrow())) {
44+
x.as_pointer()
45+
} else {
46+
y.as_pointer()
47+
};
48+
assert!(((cx.read()) == 1));
49+
let cp: Value<Ptr<i32>> = Rc::new(RefCell::new(if ((*a.borrow()) > (*b.borrow())) {
50+
(a.as_pointer())
51+
} else {
52+
(b.as_pointer())
53+
}));
54+
assert!((((*cp.borrow()).read()) == 10));
55+
let mp: Value<Ptr<i32>> = Rc::new(RefCell::new(if ((*a.borrow()) < (*b.borrow())) {
56+
(a.as_pointer())
57+
} else {
58+
(b.as_pointer())
59+
}));
60+
(*mp.borrow()).write(20);
61+
assert!(((*b.borrow()) == 20));
2662
return 0;
2763
}
2864
pub fn __cpp2rust_init_globals() {}

‎tests/unit/out/unsafe/09_references.rs‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,31 @@ unsafe fn main_0() -> i32 {
2020
let h_ref2: *mut i32 = &mut (*h_ptr);
2121
(*h_ref2) = 17;
2222
assert!((((*h_ref1) + (*h_ref2)) == (34)));
23+
let mut a: i32 = 1;
24+
let mut b: i32 = 2;
25+
let r: *mut i32 = if ((a) < (b)) { &mut a } else { &mut b } as *mut i32;
26+
(*r) = 10;
27+
assert!(((a) == (10)));
28+
let cr: *const i32 = if ((a) > (b)) { &a } else { &b } as *const i32;
29+
assert!(((*cr) == (10)));
30+
let x: i32 = 1;
31+
let y: i32 = 2;
32+
let cx: *const i32 = if ((x) < (y)) { &x } else { &y } as *const i32;
33+
assert!(((*cx) == (1)));
34+
let mut cp: *const i32 = (if ((a) > (b)) {
35+
(&mut a as *mut i32)
36+
} else {
37+
(&mut b as *mut i32)
38+
})
39+
.cast_const();
40+
assert!(((*cp) == (10)));
41+
let mut mp: *mut i32 = if ((a) < (b)) {
42+
(&mut a as *mut i32)
43+
} else {
44+
(&mut b as *mut i32)
45+
};
46+
(*mp) = 20;
47+
assert!(((b) == (20)));
2348
return 0;
2449
}
2550
pub unsafe fn __cpp2rust_init_globals() {}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ unsafe fn main_0() -> i32 {
2020
libcc2rs::cerr_unsafe()
2121
};
2222
write!((*os1), "hello\n",);
23-
let os2: *mut std::fs::File = &mut if cond {
24-
std::fs::File::from_raw_fd(
23+
let os2: *mut std::fs::File = if cond {
24+
&mut std::fs::File::from_raw_fd(
2525
std::io::stdout()
2626
.as_fd()
2727
.try_clone_to_owned()
2828
.unwrap()
2929
.into_raw_fd(),
3030
)
3131
} else {
32-
std::fs::File::from_raw_fd(
32+
&mut std::fs::File::from_raw_fd(
3333
std::io::stderr()
3434
.as_fd()
3535
.try_clone_to_owned()
3636
.unwrap()
3737
.into_raw_fd(),
3838
)
39-
};
39+
} as *mut std::fs::File;
4040
write!((*os2), "hello\n",);
4141
return 0;
4242
}

0 commit comments

Comments
 (0)