Skip to content

Commit d0194c3

Browse files
authored
Translate operators that receive by value arguments (#408)
1 parent 67cf0c7 commit d0194c3

7 files changed

Lines changed: 253 additions & 28 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4506,18 +4506,34 @@ std::string Converter::GetComparisonCall(const clang::FunctionDecl *op,
45064506
const clang::CXXRecordDecl *decl,
45074507
std::string_view lhs,
45084508
std::string_view rhs) {
4509-
auto record = GetRecordName(decl);
4510-
auto arg = std::format("{} as *const {}", rhs, record);
4509+
auto arg = [&](unsigned i, std::string_view value) {
4510+
if (op->getParamDecl(i)->getType()->isReferenceType()) {
4511+
return GetComparisonReferenceArg(decl, value);
4512+
}
4513+
return std::format("{}.clone()", value);
4514+
};
45114515
if (const auto *method = clang::dyn_cast<clang::CXXMethodDecl>(op)) {
4512-
auto recv = !MethodNeedsMutableReceiver(method)
4513-
? std::string(lhs)
4514-
: std::format("&mut *(&raw const *{}).cast_mut()", lhs);
45154516
return std::format("{}::{}({}, {})", GetUFCSName(method),
4516-
GetMethodName(method), recv, arg);
4517+
GetMethodName(method),
4518+
GetComparisonReceiver(method, decl, lhs), arg(0, rhs));
4519+
}
4520+
return std::format("{}({}, {})", GetNamedDeclAsString(op->getCanonicalDecl()),
4521+
arg(0, lhs), arg(1, rhs));
4522+
}
4523+
4524+
std::string
4525+
Converter::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
4526+
std::string_view value) {
4527+
return std::format("{} as *const {}", value, GetRecordName(decl));
4528+
}
4529+
4530+
std::string Converter::GetComparisonReceiver(const clang::CXXMethodDecl *method,
4531+
const clang::CXXRecordDecl *,
4532+
std::string_view lhs) {
4533+
if (!MethodNeedsMutableReceiver(method)) {
4534+
return std::string(lhs);
45174535
}
4518-
return std::format("{}({} as *const {}, {})",
4519-
GetNamedDeclAsString(op->getCanonicalDecl()), lhs, record,
4520-
arg);
4536+
return std::format("&mut *(&raw const *{}).cast_mut()", lhs);
45214537
}
45224538

45234539
void Converter::ConvertOrdAndPartialOrdTraits(const clang::CXXRecordDecl *decl,

‎cpp2rust/converter/converter.h‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -614,10 +614,17 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
614614
std::string_view eq_body,
615615
std::string_view record_name);
616616

617-
virtual std::string GetComparisonCall(const clang::FunctionDecl *op,
618-
const clang::CXXRecordDecl *decl,
619-
std::string_view lhs,
620-
std::string_view rhs);
617+
std::string GetComparisonCall(const clang::FunctionDecl *op,
618+
const clang::CXXRecordDecl *decl,
619+
std::string_view lhs, std::string_view rhs);
620+
621+
virtual std::string
622+
GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
623+
std::string_view value);
624+
625+
virtual std::string GetComparisonReceiver(const clang::CXXMethodDecl *method,
626+
const clang::CXXRecordDecl *decl,
627+
std::string_view lhs);
621628

622629
virtual void AddCloneTrait(const clang::RecordDecl *decl);
623630

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -443,18 +443,19 @@ bool ConverterRefCount::VisitOffsetOfExpr(clang::OffsetOfExpr *expr) {
443443
return false;
444444
}
445445

446-
std::string ConverterRefCount::GetComparisonCall(
447-
const clang::FunctionDecl *op, const clang::CXXRecordDecl *decl,
448-
std::string_view lhs, std::string_view rhs) {
446+
std::string
447+
ConverterRefCount::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
448+
std::string_view value) {
449+
PushConversionKind push(*this, ConversionKind::FullRefCount);
450+
return BoxValue(GetShallowCopy(decl, value)) + ".as_pointer()";
451+
}
452+
453+
std::string
454+
ConverterRefCount::GetComparisonReceiver(const clang::CXXMethodDecl *,
455+
const clang::CXXRecordDecl *decl,
456+
std::string_view lhs) {
449457
PushConversionKind push(*this, ConversionKind::FullRefCount);
450-
auto lhs_ptr = BoxValue(GetShallowCopy(decl, lhs)) + ".as_pointer()";
451-
auto rhs_ptr = BoxValue(GetShallowCopy(decl, rhs)) + ".as_pointer()";
452-
if (const auto *method = clang::dyn_cast<clang::CXXMethodDecl>(op)) {
453-
return std::format("{}::{}(&{}, {})", GetUFCSName(method),
454-
GetMethodName(method), lhs_ptr, rhs_ptr);
455-
}
456-
return std::format("{}({}, {})", GetNamedDeclAsString(op->getCanonicalDecl()),
457-
lhs_ptr, rhs_ptr);
458+
return std::format("&{}.as_pointer()", BoxValue(GetShallowCopy(decl, lhs)));
458459
}
459460

460461
std::string ConverterRefCount::GetShallowCopy(const clang::RecordDecl *decl,

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ class ConverterRefCount final : public Converter {
3636

3737
const char *CharRustType() const override { return "u8"; }
3838

39-
std::string GetComparisonCall(const clang::FunctionDecl *op,
40-
const clang::CXXRecordDecl *decl,
41-
std::string_view lhs,
42-
std::string_view rhs) override;
39+
std::string GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
40+
std::string_view value) override;
41+
42+
std::string GetComparisonReceiver(const clang::CXXMethodDecl *method,
43+
const clang::CXXRecordDecl *decl,
44+
std::string_view lhs) override;
4345

4446
std::string GetShallowCopy(const clang::RecordDecl *decl,
4547
std::string_view src);

‎tests/unit/operator_comparison_free.cpp‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,23 @@ bool operator>=(const S &a, const S &b) { return a.v >= b.v; }
1313
bool operator<(const S &a, int b) { return a.v < b; }
1414
bool operator<(int a, const S &b) { return a < b.v; }
1515

16+
struct V {
17+
int v;
18+
};
19+
20+
bool operator==(V a, V b) { return a.v == b.v; }
21+
bool operator!=(V a, V b) { return a.v != b.v; }
22+
bool operator<(V a, V b) { return a.v < b.v; }
23+
bool operator>(V a, V b) { return a.v > b.v; }
24+
1625
int main() {
26+
V x{1}, y{2}, z{1};
27+
assert(x == z);
28+
assert(x != y);
29+
assert(x < y);
30+
assert(y > x);
31+
assert(!(y < x));
32+
1733
S a{1}, b{2}, c{1};
1834
assert(a == c);
1935
assert(a != b);

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

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,120 @@ pub fn operator_lt_7(a: i32, b: Ptr<S>) -> bool {
117117
_lhs < (*(*b.upgrade().deref()).v.borrow())
118118
};
119119
}
120+
#[derive(Default)]
121+
pub struct V {
122+
pub v: Value<i32>,
123+
}
124+
impl std::cmp::Ord for V {
125+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
126+
{
127+
if operator_lt_8(self.clone(), other.clone()) {
128+
std::cmp::Ordering::Less
129+
} else if operator_lt_8(other.clone(), self.clone()) {
130+
std::cmp::Ordering::Greater
131+
} else {
132+
std::cmp::Ordering::Equal
133+
}
134+
}
135+
}
136+
}
137+
impl std::cmp::PartialOrd for V {
138+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
139+
Some(self.cmp(other))
140+
}
141+
}
142+
impl std::cmp::PartialEq for V {
143+
fn eq(&self, other: &Self) -> bool {
144+
{ operator_eq_9(self.clone(), other.clone()) }
145+
}
146+
}
147+
impl std::cmp::Eq for V {}
148+
impl Clone for V {
149+
fn clone(&self) -> Self {
150+
let __this: Value<V> = Rc::new(RefCell::new(Self {
151+
v: Rc::new(RefCell::new((*self.v.borrow()))),
152+
}));
153+
let this: Ptr<V> = __this.as_pointer();
154+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
155+
}
156+
}
157+
impl ByteRepr for V {
158+
fn byte_size() -> usize {
159+
4
160+
}
161+
fn to_bytes(&self, buf: &mut [u8]) {
162+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
163+
}
164+
fn from_bytes(buf: &[u8]) -> Self {
165+
Self {
166+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
167+
}
168+
}
169+
}
170+
pub fn operator_eq_9(a: V, b: V) -> bool {
171+
let a: Value<V> = Rc::new(RefCell::new(a));
172+
let b: Value<V> = Rc::new(RefCell::new(b));
173+
return ((*(*a.borrow()).v.borrow()) == (*(*b.borrow()).v.borrow()));
174+
}
175+
pub fn operator_ne_10(a: V, b: V) -> bool {
176+
let a: Value<V> = Rc::new(RefCell::new(a));
177+
let b: Value<V> = Rc::new(RefCell::new(b));
178+
return ((*(*a.borrow()).v.borrow()) != (*(*b.borrow()).v.borrow()));
179+
}
180+
pub fn operator_lt_8(a: V, b: V) -> bool {
181+
let a: Value<V> = Rc::new(RefCell::new(a));
182+
let b: Value<V> = Rc::new(RefCell::new(b));
183+
return ((*(*a.borrow()).v.borrow()) < (*(*b.borrow()).v.borrow()));
184+
}
185+
pub fn operator_gt_11(a: V, b: V) -> bool {
186+
let a: Value<V> = Rc::new(RefCell::new(a));
187+
let b: Value<V> = Rc::new(RefCell::new(b));
188+
return ((*(*a.borrow()).v.borrow()) > (*(*b.borrow()).v.borrow()));
189+
}
120190
pub fn main() {
121191
__cpp2rust_init_globals();
122192
std::process::exit(main_0());
123193
}
124194
fn main_0() -> i32 {
195+
let x: Value<V> = Rc::new(RefCell::new(V {
196+
v: Rc::new(RefCell::new(1)),
197+
}));
198+
let y: Value<V> = Rc::new(RefCell::new(V {
199+
v: Rc::new(RefCell::new(2)),
200+
}));
201+
let z: Value<V> = Rc::new(RefCell::new(V {
202+
v: Rc::new(RefCell::new(1)),
203+
}));
204+
assert!(
205+
({
206+
let _a: V = (*x.borrow()).clone();
207+
operator_eq_9(_a, (*z.borrow()).clone())
208+
})
209+
);
210+
assert!(
211+
({
212+
let _a: V = (*x.borrow()).clone();
213+
operator_ne_10(_a, (*y.borrow()).clone())
214+
})
215+
);
216+
assert!(
217+
({
218+
let _a: V = (*x.borrow()).clone();
219+
operator_lt_8(_a, (*y.borrow()).clone())
220+
})
221+
);
222+
assert!(
223+
({
224+
let _a: V = (*y.borrow()).clone();
225+
operator_gt_11(_a, (*x.borrow()).clone())
226+
})
227+
);
228+
assert!(
229+
!({
230+
let _a: V = (*y.borrow()).clone();
231+
operator_lt_8(_a, (*x.borrow()).clone())
232+
})
233+
);
125234
let a: Value<S> = Rc::new(RefCell::new(S {
126235
v: Rc::new(RefCell::new(1)),
127236
}));

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,87 @@ pub unsafe fn operator_lt_6(a: *const S, mut b: i32) -> bool {
5959
pub unsafe fn operator_lt_7(mut a: i32, b: *const S) -> bool {
6060
return ((a) < ((*b).v));
6161
}
62+
#[repr(C)]
63+
#[derive(Copy, Clone, Default)]
64+
pub struct V {
65+
pub v: i32,
66+
}
67+
impl std::cmp::Ord for V {
68+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
69+
unsafe {
70+
if operator_lt_8(self.clone(), other.clone()) {
71+
std::cmp::Ordering::Less
72+
} else if operator_lt_8(other.clone(), self.clone()) {
73+
std::cmp::Ordering::Greater
74+
} else {
75+
std::cmp::Ordering::Equal
76+
}
77+
}
78+
}
79+
}
80+
impl std::cmp::PartialOrd for V {
81+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
82+
Some(self.cmp(other))
83+
}
84+
}
85+
impl std::cmp::PartialEq for V {
86+
fn eq(&self, other: &Self) -> bool {
87+
unsafe { operator_eq_9(self.clone(), other.clone()) }
88+
}
89+
}
90+
impl std::cmp::Eq for V {}
91+
pub unsafe fn operator_eq_9(mut a: V, mut b: V) -> bool {
92+
return ((a.v) == (b.v));
93+
}
94+
pub unsafe fn operator_ne_10(mut a: V, mut b: V) -> bool {
95+
return ((a.v) != (b.v));
96+
}
97+
pub unsafe fn operator_lt_8(mut a: V, mut b: V) -> bool {
98+
return ((a.v) < (b.v));
99+
}
100+
pub unsafe fn operator_gt_11(mut a: V, mut b: V) -> bool {
101+
return ((a.v) > (b.v));
102+
}
62103
pub fn main() {
63104
unsafe {
64105
__cpp2rust_init_globals();
65106
std::process::exit(main_0() as i32);
66107
}
67108
}
68109
unsafe fn main_0() -> i32 {
110+
let mut x: V = V { v: 1 };
111+
let mut y: V = V { v: 2 };
112+
let mut z: V = V { v: 1 };
113+
assert!(
114+
(unsafe {
115+
let _a: V = x;
116+
operator_eq_9(_a, z)
117+
})
118+
);
119+
assert!(
120+
(unsafe {
121+
let _a: V = x;
122+
operator_ne_10(_a, y)
123+
})
124+
);
125+
assert!(
126+
(unsafe {
127+
let _a: V = x;
128+
operator_lt_8(_a, y)
129+
})
130+
);
131+
assert!(
132+
(unsafe {
133+
let _a: V = y;
134+
operator_gt_11(_a, x)
135+
})
136+
);
137+
assert!(
138+
!(unsafe {
139+
let _a: V = y;
140+
operator_lt_8(_a, x)
141+
})
142+
);
69143
let mut a: S = S { v: 1 };
70144
let mut b: S = S { v: 2 };
71145
let mut c: S = S { v: 1 };

0 commit comments

Comments
 (0)