From 9ada80aeb56ef4ab6e2639d55284c85b0f32b25f Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 19 Sep 2026 21:22:23 +0100 Subject: [PATCH] Implement Ord for Ptr --- cpp2rust/converter/converter.cpp | 3 +- libcc2rs/src/rc.rs | 14 +- tests/unit/operator_comparison_defaulted.cpp | 10 ++ .../refcount/operator_comparison_defaulted.rs | 153 ++++++++++++++---- tests/unit/out/refcount/operator_traits.rs | 6 +- .../unsafe/operator_comparison_defaulted.rs | 72 ++++++++- tests/unit/out/unsafe/operator_traits.rs | 2 +- 7 files changed, 217 insertions(+), 43 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index cf33029e6..ac9d57c27 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2575,7 +2575,8 @@ bool Converter::VisitCXXRewrittenBinaryOperator( bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) { if (expr->getOpcode() == clang::BO_Cmp) { - StrCat(std::format("({}).cmp(&({}))", ConvertRValue(expr->getLHS()), + StrCat(std::format("std::cmp::Ord::cmp(&({}), &({}))", + ConvertRValue(expr->getLHS()), ConvertRValue(expr->getRHS()))); computed_expr_type_ = ComputedExprType::FreshValue; return false; diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index ff374c713..da8fb4370 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -167,15 +167,21 @@ impl PartialEq for Ptr { impl Eq for Ptr {} -impl PartialOrd for Ptr { - fn partial_cmp(&self, other: &Self) -> Option { +impl Ord for Ptr { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self.kind.partial_cmp(&other.kind) { - Some(std::cmp::Ordering::Equal) => self.byte_offset().partial_cmp(&other.byte_offset()), - ord => ord, + Some(std::cmp::Ordering::Equal) | None => self.byte_offset().cmp(&other.byte_offset()), + Some(ord) => ord, } } } +impl PartialOrd for Ptr { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl Ptr { #[inline] pub fn null() -> Self { diff --git a/tests/unit/operator_comparison_defaulted.cpp b/tests/unit/operator_comparison_defaulted.cpp index afc124f8e..bd8809d4e 100644 --- a/tests/unit/operator_comparison_defaulted.cpp +++ b/tests/unit/operator_comparison_defaulted.cpp @@ -48,6 +48,11 @@ struct Secondary { bool operator>=(const Secondary &) const = default; }; +struct PtrMember { + int *p; + auto operator<=>(const PtrMember &) const = default; +}; + int main() { Eq e1{1, 2}, e2{1, 2}, e3{1, 3}; assert(e1 == e2); @@ -72,5 +77,10 @@ int main() { assert(s1 < s2); assert(s2 >= s1); assert(!(s2 < s1)); + int arr[2] = {0, 0}; + PtrMember p1{arr}, p2{arr + 1}, p3{arr}; + assert(p1 < p2); + assert(p1 == p3); + assert((p2 <=> p1) == std::strong_ordering::greater); return 0; } diff --git a/tests/unit/out/refcount/operator_comparison_defaulted.rs b/tests/unit/out/refcount/operator_comparison_defaulted.rs index eb09a71b9..9fb43e66d 100644 --- a/tests/unit/out/refcount/operator_comparison_defaulted.rs +++ b/tests/unit/out/refcount/operator_comparison_defaulted.rs @@ -407,6 +407,58 @@ impl ByteRepr for Secondary { } } } +#[derive(Default)] +pub struct PtrMember { + pub p: Value>, +} +impl std::cmp::Ord for PtrMember { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + { + PtrMemberImpl::operator_cmp( + &Rc::new(RefCell::new(PtrMember { p: self.p.clone() })).as_pointer(), + Rc::new(RefCell::new(PtrMember { p: other.p.clone() })).as_pointer(), + ) + } + } +} +impl std::cmp::PartialOrd for PtrMember { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for PtrMember { + fn eq(&self, other: &Self) -> bool { + { + PtrMemberImpl::operator_cmp( + &Rc::new(RefCell::new(PtrMember { p: self.p.clone() })).as_pointer(), + Rc::new(RefCell::new(PtrMember { p: other.p.clone() })).as_pointer(), + ) == std::cmp::Ordering::Equal + } + } +} +impl std::cmp::Eq for PtrMember {} +impl Clone for PtrMember { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + p: Rc::new(RefCell::new((*self.p.borrow()).clone())), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for PtrMember { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.p.borrow()).to_bytes(&mut buf[0..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + p: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + } + } +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -525,6 +577,27 @@ fn main_0() -> i32 { assert!(({ SecondaryImpl::operator_lt(&s1.as_pointer(), s2.as_pointer(),) })); assert!(({ SecondaryImpl::operator_ge(&s2.as_pointer(), s1.as_pointer(),) })); assert!(!({ SecondaryImpl::operator_lt(&s2.as_pointer(), s1.as_pointer(),) })); + let arr: Value> = Rc::new(RefCell::new(Box::new([0, 0]))); + let p1: Value = Rc::new(RefCell::new(PtrMember { + p: Rc::new(RefCell::new((arr.as_pointer() as Ptr))), + })); + let p2: Value = Rc::new(RefCell::new(PtrMember { + p: Rc::new(RefCell::new( + (arr.as_pointer() as Ptr).offset((1) as isize), + )), + })); + let p3: Value = Rc::new(RefCell::new(PtrMember { + p: Rc::new(RefCell::new((arr.as_pointer() as Ptr))), + })); + assert!( + ({ PtrMemberImpl::operator_cmp(&p1.as_pointer(), p2.as_pointer(),) }) + == std::cmp::Ordering::Less + ); + assert!(({ PtrMemberImpl::operator_eq(&p1.as_pointer(), p3.as_pointer(),) })); + assert!( + ({ PtrMemberImpl::operator_cmp(&p2.as_pointer(), p1.as_pointer(),) }) + == std::cmp::Ordering::Greater + ); return 0; } pub trait BothImpl { @@ -540,10 +613,10 @@ impl BothImpl for Ptr { } fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).a.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).a.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).a.borrow()), + &(*(*_a0.upgrade().deref()).a.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } @@ -558,19 +631,19 @@ pub trait CmpImpl { impl CmpImpl for Ptr { fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).a.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).a.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).a.borrow()), + &(*(*_a0.upgrade().deref()).a.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } } { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).b.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).b.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).b.borrow()), + &(*(*_a0.upgrade().deref()).b.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } @@ -608,10 +681,10 @@ pub trait InnerImpl { impl InnerImpl for Ptr { fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).x.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).x.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).x.borrow()), + &(*(*_a0.upgrade().deref()).x.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } @@ -631,10 +704,10 @@ pub trait OrdOnlyImpl { impl OrdOnlyImpl for Ptr { fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).a.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).a.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).a.borrow()), + &(*(*_a0.upgrade().deref()).a.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } @@ -660,10 +733,10 @@ impl OuterImpl for Ptr { } } { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).y.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).y.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).y.borrow()), + &(*(*_a0.upgrade().deref()).y.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } @@ -680,6 +753,30 @@ impl OuterImpl for Ptr { }); } } +pub trait PtrMemberImpl { + fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering; + fn operator_eq(&self, _a0: Ptr) -> bool; +} +impl PtrMemberImpl for Ptr { + fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { + { + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).p.borrow()), + &(*(*_a0.upgrade().deref()).p.borrow()), + ))); + if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { + return (*cmp.borrow_mut()).clone(); + } + } + return std::cmp::Ordering::Equal; + } + fn operator_eq(&self, _a0: Ptr) -> bool { + return { + let _lhs = (*(*(*self).upgrade().deref()).p.borrow()).clone(); + _lhs == (*(*_a0.upgrade().deref()).p.borrow()).clone() + }; + } +} pub trait SecondaryImpl { fn operator_eq(&self, _a0: Ptr) -> bool; fn operator_ne(&self, _a0: Ptr) -> bool; @@ -702,10 +799,10 @@ impl SecondaryImpl for Ptr { } fn operator_cmp(&self, _a0: Ptr) -> std::cmp::Ordering { { - let cmp: Value = Rc::new(RefCell::new( - (*(*(*self).upgrade().deref()).a.borrow()) - .cmp(&(*(*_a0.upgrade().deref()).a.borrow())), - )); + let cmp: Value = Rc::new(RefCell::new(std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).a.borrow()), + &(*(*_a0.upgrade().deref()).a.borrow()), + ))); if !((*cmp.borrow()) == std::cmp::Ordering::Equal) { return (*cmp.borrow_mut()).clone(); } diff --git a/tests/unit/out/refcount/operator_traits.rs b/tests/unit/out/refcount/operator_traits.rs index 30c6b92c8..1bc3bd670 100644 --- a/tests/unit/out/refcount/operator_traits.rs +++ b/tests/unit/out/refcount/operator_traits.rs @@ -487,8 +487,10 @@ pub trait CmpImpl { } impl CmpImpl for Ptr { fn operator_cmp(&self, o: Ptr) -> std::cmp::Ordering { - return (*(*(*self).upgrade().deref()).v.borrow()) - .cmp(&(*(*o.upgrade().deref()).v.borrow())); + return std::cmp::Ord::cmp( + &(*(*(*self).upgrade().deref()).v.borrow()), + &(*(*o.upgrade().deref()).v.borrow()), + ); } fn operator_eq(&self, o: Ptr) -> bool { return { diff --git a/tests/unit/out/unsafe/operator_comparison_defaulted.rs b/tests/unit/out/unsafe/operator_comparison_defaulted.rs index c25fc6f11..6643bfaf8 100644 --- a/tests/unit/out/unsafe/operator_comparison_defaulted.rs +++ b/tests/unit/out/unsafe/operator_comparison_defaulted.rs @@ -33,13 +33,15 @@ pub struct Cmp { impl Cmp { pub unsafe fn operator_cmp(&self, _a0: *const Cmp) -> std::cmp::Ordering { { - let mut cmp: std::cmp::Ordering = ((*(self as *const Cmp)).a).cmp(&((*_a0).a)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Cmp)).a), &((*_a0).a)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } } { - let mut cmp: std::cmp::Ordering = ((*(self as *const Cmp)).b).cmp(&((*_a0).b)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Cmp)).b), &((*_a0).b)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -78,7 +80,8 @@ impl Both { } pub unsafe fn operator_cmp(&self, _a0: *const Both) -> std::cmp::Ordering { { - let mut cmp: std::cmp::Ordering = ((*(self as *const Both)).a).cmp(&((*_a0).a)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Both)).a), &((*_a0).a)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -110,7 +113,8 @@ pub struct OrdOnly { impl OrdOnly { pub unsafe fn operator_cmp(&self, _a0: *const OrdOnly) -> std::cmp::Ordering { { - let mut cmp: std::cmp::Ordering = ((*(self as *const OrdOnly)).a).cmp(&((*_a0).a)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const OrdOnly)).a), &((*_a0).a)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -142,7 +146,8 @@ pub struct Inner { impl Inner { pub unsafe fn operator_cmp(&self, _a0: *const Inner) -> std::cmp::Ordering { { - let mut cmp: std::cmp::Ordering = ((*(self as *const Inner)).x).cmp(&((*_a0).x)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Inner)).x), &((*_a0).x)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -187,7 +192,8 @@ impl Outer { } } { - let mut cmp: std::cmp::Ordering = ((*(self as *const Outer)).y).cmp(&((*_a0).y)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Outer)).y), &((*_a0).y)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -234,7 +240,8 @@ impl Secondary { } pub unsafe fn operator_cmp(&self, _a0: *const Secondary) -> std::cmp::Ordering { { - let mut cmp: std::cmp::Ordering = ((*(self as *const Secondary)).a).cmp(&((*_a0).a)); + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const Secondary)).a), &((*_a0).a)); if !(cmp == std::cmp::Ordering::Equal) { return cmp; } @@ -270,6 +277,44 @@ impl std::cmp::PartialEq for Secondary { } } impl std::cmp::Eq for Secondary {} +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct PtrMember { + pub p: *mut i32, +} +impl PtrMember { + pub unsafe fn operator_cmp(&self, _a0: *const PtrMember) -> std::cmp::Ordering { + { + let mut cmp: std::cmp::Ordering = + std::cmp::Ord::cmp(&((*(self as *const PtrMember)).p), &((*_a0).p)); + if !(cmp == std::cmp::Ordering::Equal) { + return cmp; + } + } + return std::cmp::Ordering::Equal; + } + pub unsafe fn operator_eq(&self, _a0: *const PtrMember) -> bool { + return (((*(self as *const PtrMember)).p) == ((*_a0).p)); + } +} +impl std::cmp::Ord for PtrMember { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + unsafe { PtrMember::operator_cmp(self, other as *const PtrMember) } + } +} +impl std::cmp::PartialOrd for PtrMember { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for PtrMember { + fn eq(&self, other: &Self) -> bool { + unsafe { + PtrMember::operator_cmp(self, other as *const PtrMember) == std::cmp::Ordering::Equal + } + } +} +impl std::cmp::Eq for PtrMember {} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -329,6 +374,19 @@ unsafe fn main_0() -> i32 { assert!((unsafe { Secondary::operator_lt(&s1, &s2,) })); assert!((unsafe { Secondary::operator_ge(&s2, &s1,) })); assert!(!(unsafe { Secondary::operator_lt(&s2, &s1,) })); + let mut arr: [i32; 2] = [0, 0]; + let mut p1: PtrMember = PtrMember { + p: arr.as_mut_ptr(), + }; + let mut p2: PtrMember = PtrMember { + p: arr.as_mut_ptr().offset((1) as isize), + }; + let mut p3: PtrMember = PtrMember { + p: arr.as_mut_ptr(), + }; + assert!((unsafe { PtrMember::operator_cmp(&p1, &p2,) }) == std::cmp::Ordering::Less); + assert!((unsafe { PtrMember::operator_eq(&p1, &p3,) })); + assert!((unsafe { PtrMember::operator_cmp(&p2, &p1,) }) == std::cmp::Ordering::Greater); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/operator_traits.rs b/tests/unit/out/unsafe/operator_traits.rs index 95ab11b2c..8c33a8350 100644 --- a/tests/unit/out/unsafe/operator_traits.rs +++ b/tests/unit/out/unsafe/operator_traits.rs @@ -66,7 +66,7 @@ pub struct Cmp { } impl Cmp { pub unsafe fn operator_cmp(&self, o: *const Cmp) -> std::cmp::Ordering { - return (self.v).cmp(&((*o).v)); + return std::cmp::Ord::cmp(&(self.v), &((*o).v)); } pub unsafe fn operator_eq(&self, o: *const Cmp) -> bool { return ((self.v) == ((*o).v));