diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 779cfdc0b..424d6a1c3 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -4643,6 +4643,32 @@ std::string Converter::GetComparisonCall(const clang::FunctionDecl *op, arg(0, lhs), arg(1, rhs)); } +std::string Converter::GetComparisonBool(const clang::FunctionDecl *op, + const clang::CXXRecordDecl *decl, + std::string_view lhs, + std::string_view rhs) { + auto call = GetComparisonCall(op, decl, lhs, rhs); + auto ret = op->getReturnType(); + if (ret->isBooleanType()) { + return call; + } + if (ret->isIntegerType()) { + return std::format("(({}) != 0)", call); + } + const auto *record = ret->getAsCXXRecordDecl(); + assert(record && "unsupported comparison operator return type"); + for (const auto *found : record->getVisibleConversionFunctions()) { + const auto *conversion = clang::dyn_cast(found); + if (conversion && conversion->getConversionType()->isBooleanType()) { + return std::format("{{ let __cmp = &{}; {}::{}({}) }}", call, + GetUFCSName(conversion), GetMethodName(conversion), + GetComparisonReceiver(conversion, record, "__cmp")); + } + } + assert(0 && "comparison operator result has no conversion to bool"); + return call; +} + std::string Converter::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl, std::string_view value) { @@ -4670,19 +4696,19 @@ void Converter::ConvertOrdAndPartialOrdTraits(const clang::CXXRecordDecl *decl, cmp_body = std::format("if {} {{ std::cmp::Ordering::Less }} else if {} {{ " "std::cmp::Ordering::Greater }} else {{ " "std::cmp::Ordering::Equal }}", - GetComparisonCall(lt, decl, "self", "other"), - GetComparisonCall(lt, decl, "other", "self")); + GetComparisonBool(lt, decl, "self", "other"), + GetComparisonBool(lt, decl, "other", "self")); } if (eq) { - eq_body = GetComparisonCall(eq, decl, "self", "other"); + eq_body = GetComparisonBool(eq, decl, "self", "other"); } else if (cmp) { eq_body = std::format("{} == std::cmp::Ordering::Equal", GetComparisonCall(cmp, decl, "self", "other")); } else { eq_body = std::format("!({}) && !({})", - GetComparisonCall(lt, decl, "self", "other"), - GetComparisonCall(lt, decl, "other", "self")); + GetComparisonBool(lt, decl, "self", "other"), + GetComparisonBool(lt, decl, "other", "self")); } ConvertOrdAndPartialOrdTraitsBase(cmp_body, eq_body, GetRecordName(decl)); @@ -4697,6 +4723,10 @@ void Converter::AddOrdTrait(const clang::CXXRecordDecl *decl) { fn->getDescribedFunctionTemplate() || !IsSameTypeComparison(fn, decl)) { return; } + if (fn->getOverloadedOperator() == clang::OO_Spaceship && + !ctx_.CompCategories.lookupInfoForType(fn->getReturnType())) { + return; + } switch (fn->getOverloadedOperator()) { case clang::OO_EqualEqual: eq = fn; diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 683ce155e..ff7200358 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -676,6 +676,10 @@ class Converter : public clang::RecursiveASTVisitor { const clang::CXXRecordDecl *decl, std::string_view lhs, std::string_view rhs); + std::string GetComparisonBool(const clang::FunctionDecl *op, + const clang::CXXRecordDecl *decl, + std::string_view lhs, std::string_view rhs); + virtual std::string GetComparisonReferenceArg(const clang::CXXRecordDecl *decl, std::string_view value); diff --git a/tests/unit/operator_comparison_nonbool.cpp b/tests/unit/operator_comparison_nonbool.cpp new file mode 100644 index 000000000..4b2861c05 --- /dev/null +++ b/tests/unit/operator_comparison_nonbool.cpp @@ -0,0 +1,80 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++20 +#include +#include + +struct X { + int v; +}; + +int operator==(X a, X b) { return a.v == b.v ? 2 : 0; } +int operator!=(X a, X b) { return a.v != b.v ? 3 : 0; } +int operator<(X a, X b) { return a.v < b.v ? 4 : 0; } +int operator>(X a, X b) { return a.v > b.v ? 5 : 0; } +int operator<=(X a, X b) { return a.v <= b.v ? 6 : 0; } +int operator>=(X a, X b) { return a.v >= b.v ? 7 : 0; } + +struct Result { + int r; +}; + +struct Custom { + int v; + Result operator<=>(const Custom &o) const { return Result{v - o.v}; } +}; + +struct Mixed { + int v; + Result operator<=>(const Mixed &o) const { return Result{v - o.v}; } + int operator<(const Mixed &o) const { return v < o.v ? 8 : 0; } + int operator==(const Mixed &o) const { return v == o.v ? 9 : 0; } +}; + +struct MyBool { + bool value; + explicit MyBool(bool v) : value(v) {} + operator bool() const { return value; } +}; + +struct Boolish { + int v; +}; + +MyBool operator==(Boolish a, Boolish b) { return MyBool(a.v == b.v); } +MyBool operator<(Boolish a, Boolish b) { return MyBool(a.v < b.v); } + +int main() { + X a{1}, b{2}, c{1}; + assert((a == c) == 2); + assert((a == b) == 0); + assert((a != b) == 3); + assert((a < b) == 4); + assert((b > a) == 5); + assert((a <= c) == 6); + assert((a >= c) == 7); + + X xs[] = {{3}, {1}, {2}}; + std::sort(xs, xs + 3); + assert(xs[0].v == 1 && xs[1].v == 2 && xs[2].v == 3); + + Custom p{5}, q{2}; + Result r = p <=> q; + assert(r.r == 3); + + Mixed m{4}, n{4}; + assert((m == n) == 9); + assert((m <=> n).r == 0); + Mixed ms[] = {{6}, {4}, {5}}; + std::sort(ms, ms + 3); + assert(ms[0].v == 4 && ms[1].v == 5 && ms[2].v == 6); + assert((ms[0] < ms[1]) == 8); + + Boolish b1{1}, b2{2}; + assert(b1 == Boolish{1}); + assert(!(b2 < b1)); + MyBool lt = b1 < b2; + assert(lt.value); + Boolish bs[] = {{3}, {1}, {2}}; + std::sort(bs, bs + 3); + assert(bs[0].v == 1 && bs[1].v == 2 && bs[2].v == 3); + return 0; +} diff --git a/tests/unit/out/refcount/operator_comparison_nonbool.rs b/tests/unit/out/refcount/operator_comparison_nonbool.rs new file mode 100644 index 000000000..bd227ef7b --- /dev/null +++ b/tests/unit/out/refcount/operator_comparison_nonbool.rs @@ -0,0 +1,366 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct X { + #[offset(0)] + pub v: i32, +} +impl std::cmp::Ord for X { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + { + if ((operator_lt_0(self.clone(), other.clone())) != 0) { + std::cmp::Ordering::Less + } else if ((operator_lt_0(other.clone(), self.clone())) != 0) { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for X { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for X { + fn eq(&self, other: &Self) -> bool { + { ((operator_eq_1(self.clone(), other.clone())) != 0) } + } +} +impl std::cmp::Eq for X {} +pub fn operator_eq_1(mut a: X, mut b: X) -> i32 { + return if (a.v == b.v) { 2 } else { 0 }; +} +pub fn operator_ne_2(mut a: X, mut b: X) -> i32 { + return if (a.v != b.v) { 3 } else { 0 }; +} +pub fn operator_lt_0(mut a: X, mut b: X) -> i32 { + return if (a.v < b.v) { 4 } else { 0 }; +} +pub fn operator_gt_3(mut a: X, mut b: X) -> i32 { + return if (a.v > b.v) { 5 } else { 0 }; +} +pub fn operator_le_4(mut a: X, mut b: X) -> i32 { + return if (a.v <= b.v) { 6 } else { 0 }; +} +pub fn operator_ge_5(mut a: X, mut b: X) -> i32 { + return if (a.v >= b.v) { 7 } else { 0 }; +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Result { + #[offset(0)] + pub r: i32, +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Custom { + #[offset(0)] + pub v: i32, +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Mixed { + #[offset(0)] + pub v: i32, +} +impl std::cmp::Ord for Mixed { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + { + if ((MixedImpl::operator_lt( + &Rc::new(RefCell::new(Mixed { v: self.v.clone() })).as_pointer(), + Rc::new(RefCell::new(Mixed { v: other.v.clone() })).as_pointer(), + )) != 0) + { + std::cmp::Ordering::Less + } else if ((MixedImpl::operator_lt( + &Rc::new(RefCell::new(Mixed { v: other.v.clone() })).as_pointer(), + Rc::new(RefCell::new(Mixed { v: self.v.clone() })).as_pointer(), + )) != 0) + { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for Mixed { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for Mixed { + fn eq(&self, other: &Self) -> bool { + { + ((MixedImpl::operator_eq( + &Rc::new(RefCell::new(Mixed { v: self.v.clone() })).as_pointer(), + Rc::new(RefCell::new(Mixed { v: other.v.clone() })).as_pointer(), + )) != 0) + } + } +} +impl std::cmp::Eq for Mixed {} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(1)] +pub struct MyBool { + #[offset(0)] + pub value: bool, +} +impl MyBool { + pub fn new(mut v: bool) -> Self { + Self { value: v } + } +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct Boolish { + #[offset(0)] + pub v: i32, +} +impl std::cmp::Ord for Boolish { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + { + if { + let __cmp = &operator_lt_6(self.clone(), other.clone()); + MyBoolImpl::to_bool( + &Rc::new(RefCell::new(MyBool { + value: __cmp.value.clone(), + })) + .as_pointer(), + ) + } { + std::cmp::Ordering::Less + } else if { + let __cmp = &operator_lt_6(other.clone(), self.clone()); + MyBoolImpl::to_bool( + &Rc::new(RefCell::new(MyBool { + value: __cmp.value.clone(), + })) + .as_pointer(), + ) + } { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for Boolish { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for Boolish { + fn eq(&self, other: &Self) -> bool { + { + { + let __cmp = &operator_eq_7(self.clone(), other.clone()); + MyBoolImpl::to_bool( + &Rc::new(RefCell::new(MyBool { + value: __cmp.value.clone(), + })) + .as_pointer(), + ) + } + } + } +} +impl std::cmp::Eq for Boolish {} +pub fn operator_eq_7(mut a: Boolish, mut b: Boolish) -> MyBool { + return MyBool::new({ (a.v == b.v) }); +} +pub fn operator_lt_6(mut a: Boolish, mut b: Boolish) -> MyBool { + return MyBool::new({ (a.v < b.v) }); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let mut a: X = X { v: 1 }; + let mut b: X = X { v: 2 }; + let mut c: X = X { v: 1 }; + assert!( + (({ + let _a: X = (a).clone(); + operator_eq_1(_a, (c).clone()) + }) == 2) + ); + assert!( + (({ + let _a: X = (a).clone(); + operator_eq_1(_a, (b).clone()) + }) == 0) + ); + assert!( + (({ + let _a: X = (a).clone(); + operator_ne_2(_a, (b).clone()) + }) == 3) + ); + assert!( + (({ + let _a: X = (a).clone(); + operator_lt_0(_a, (b).clone()) + }) == 4) + ); + assert!( + (({ + let _a: X = (b).clone(); + operator_gt_3(_a, (a).clone()) + }) == 5) + ); + assert!( + (({ + let _a: X = (a).clone(); + operator_le_4(_a, (c).clone()) + }) == 6) + ); + assert!( + (({ + let _a: X = (a).clone(); + operator_ge_5(_a, (c).clone()) + }) == 7) + ); + let xs: Value> = Rc::new(RefCell::new(Box::new([X { v: 3 }, X { v: 1 }, X { v: 2 }]))); + (xs.as_pointer() as Ptr).sort( + (xs.as_pointer() as Ptr) + .offset((3) as isize) + .get_offset(), + ); + assert!( + (({ (*xs.borrow())[(0) as usize].v } == 1) && ({ (*xs.borrow())[(1) as usize].v } == 2)) + && ({ (*xs.borrow())[(2) as usize].v } == 3) + ); + let p: Value = Rc::new(RefCell::new(Custom { v: 5 })); + let q: Value = Rc::new(RefCell::new(Custom { v: 2 })); + let mut r: Result = ({ CustomImpl::operator_cmp(&p.as_pointer(), q.as_pointer()) }); + assert!((r.r == 3)); + let m: Value = Rc::new(RefCell::new(Mixed { v: 4 })); + let n: Value = Rc::new(RefCell::new(Mixed { v: 4 })); + assert!((({ MixedImpl::operator_eq(&m.as_pointer(), n.as_pointer(),) }) == 9)); + assert!(({ ({ MixedImpl::operator_cmp(&m.as_pointer(), n.as_pointer(),) }).r } == 0)); + let ms: Value> = Rc::new(RefCell::new(Box::new([ + Mixed { v: 6 }, + Mixed { v: 4 }, + Mixed { v: 5 }, + ]))); + (ms.as_pointer() as Ptr).sort( + (ms.as_pointer() as Ptr) + .offset((3) as isize) + .get_offset(), + ); + assert!( + (({ (*ms.borrow())[(0) as usize].v } == 4) && ({ (*ms.borrow())[(1) as usize].v } == 5)) + && ({ (*ms.borrow())[(2) as usize].v } == 6) + ); + assert!( + (({ + let _o: Ptr = (ms.as_pointer() as Ptr).offset(1); + MixedImpl::operator_lt(&(ms.as_pointer() as Ptr).offset(0), _o) + }) == 8) + ); + let mut b1: Boolish = Boolish { v: 1 }; + let mut b2: Boolish = Boolish { v: 2 }; + assert!( + ({ + MyBoolImpl::to_bool( + &Rc::new(RefCell::new( + ({ + let _a: Boolish = (b1).clone(); + operator_eq_7(_a, Boolish { v: 1 }) + }), + )) + .as_pointer(), + ) + }) + ); + assert!( + !({ + MyBoolImpl::to_bool( + &Rc::new(RefCell::new( + ({ + let _a: Boolish = (b2).clone(); + operator_lt_6(_a, (b1).clone()) + }), + )) + .as_pointer(), + ) + }) + ); + let mut lt: MyBool = ({ + let _a: Boolish = (b1).clone(); + operator_lt_6(_a, (b2).clone()) + }); + assert!(lt.value); + let bs: Value> = Rc::new(RefCell::new(Box::new([ + Boolish { v: 3 }, + Boolish { v: 1 }, + Boolish { v: 2 }, + ]))); + (bs.as_pointer() as Ptr).sort( + (bs.as_pointer() as Ptr) + .offset((3) as isize) + .get_offset(), + ); + assert!( + (({ (*bs.borrow())[(0) as usize].v } == 1) && ({ (*bs.borrow())[(1) as usize].v } == 2)) + && ({ (*bs.borrow())[(2) as usize].v } == 3) + ); + return 0; +} +pub trait CustomImpl { + fn operator_cmp(&self, o: Ptr) -> Result; +} +impl CustomImpl for Ptr { + fn operator_cmp(&self, o: Ptr) -> Result { + return Result { + r: ({ (*self).with(|__s| __s.v) } - { o.with(|__s| __s.v) }), + }; + } +} +pub trait MixedImpl { + fn operator_cmp(&self, o: Ptr) -> Result; + fn operator_lt(&self, o: Ptr) -> i32; + fn operator_eq(&self, o: Ptr) -> i32; +} +impl MixedImpl for Ptr { + fn operator_cmp(&self, o: Ptr) -> Result { + return Result { + r: ({ (*self).with(|__s| __s.v) } - { o.with(|__s| __s.v) }), + }; + } + fn operator_lt(&self, o: Ptr) -> i32 { + return if ({ (*self).with(|__s| __s.v) } < { o.with(|__s| __s.v) }) { + 8 + } else { + 0 + }; + } + fn operator_eq(&self, o: Ptr) -> i32 { + return if ({ (*self).with(|__s| __s.v) } == { o.with(|__s| __s.v) }) { + 9 + } else { + 0 + }; + } +} +pub trait MyBoolImpl { + fn to_bool(&self) -> bool; +} +impl MyBoolImpl for Ptr { + fn to_bool(&self) -> bool { + return (*self).with(|__s| __s.value); + } +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/operator_comparison_nonbool.rs b/tests/unit/out/unsafe/operator_comparison_nonbool.rs new file mode 100644 index 000000000..d4b9150e8 --- /dev/null +++ b/tests/unit/out/unsafe/operator_comparison_nonbool.rs @@ -0,0 +1,306 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct X { + pub v: i32, +} +impl std::cmp::Ord for X { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + unsafe { + if ((operator_lt_0(self.clone(), other.clone())) != 0) { + std::cmp::Ordering::Less + } else if ((operator_lt_0(other.clone(), self.clone())) != 0) { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for X { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for X { + fn eq(&self, other: &Self) -> bool { + unsafe { ((operator_eq_1(self.clone(), other.clone())) != 0) } + } +} +impl std::cmp::Eq for X {} +pub unsafe fn operator_eq_1(mut a: X, mut b: X) -> i32 { + return if ((a.v) == (b.v)) { 2 } else { 0 }; +} +pub unsafe fn operator_ne_2(mut a: X, mut b: X) -> i32 { + return if ((a.v) != (b.v)) { 3 } else { 0 }; +} +pub unsafe fn operator_lt_0(mut a: X, mut b: X) -> i32 { + return if ((a.v) < (b.v)) { 4 } else { 0 }; +} +pub unsafe fn operator_gt_3(mut a: X, mut b: X) -> i32 { + return if ((a.v) > (b.v)) { 5 } else { 0 }; +} +pub unsafe fn operator_le_4(mut a: X, mut b: X) -> i32 { + return if ((a.v) <= (b.v)) { 6 } else { 0 }; +} +pub unsafe fn operator_ge_5(mut a: X, mut b: X) -> i32 { + return if ((a.v) >= (b.v)) { 7 } else { 0 }; +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Result { + pub r: i32, +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Custom { + pub v: i32, +} +impl Custom { + pub unsafe fn operator_cmp(&self, o: *const Custom) -> Result { + return Result { + r: ((self.v) - ((*o).v)), + }; + } +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Mixed { + pub v: i32, +} +impl Mixed { + pub unsafe fn operator_cmp(&self, o: *const Mixed) -> Result { + return Result { + r: ((self.v) - ((*o).v)), + }; + } + pub unsafe fn operator_lt(&self, o: *const Mixed) -> i32 { + return if ((self.v) < ((*o).v)) { 8 } else { 0 }; + } + pub unsafe fn operator_eq(&self, o: *const Mixed) -> i32 { + return if ((self.v) == ((*o).v)) { 9 } else { 0 }; + } +} +impl std::cmp::Ord for Mixed { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + unsafe { + if ((Mixed::operator_lt(self, other as *const Mixed)) != 0) { + std::cmp::Ordering::Less + } else if ((Mixed::operator_lt(other, self as *const Mixed)) != 0) { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for Mixed { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for Mixed { + fn eq(&self, other: &Self) -> bool { + unsafe { ((Mixed::operator_eq(self, other as *const Mixed)) != 0) } + } +} +impl std::cmp::Eq for Mixed {} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct MyBool { + pub value: bool, +} +impl MyBool { + pub unsafe fn new(mut v: bool) -> Self { + let mut this = Self { value: v }; + this + } + pub unsafe fn to_bool(&self) -> bool { + return self.value; + } +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Boolish { + pub v: i32, +} +impl std::cmp::Ord for Boolish { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + unsafe { + if { + let __cmp = &operator_lt_6(self.clone(), other.clone()); + MyBool::to_bool(__cmp) + } { + std::cmp::Ordering::Less + } else if { + let __cmp = &operator_lt_6(other.clone(), self.clone()); + MyBool::to_bool(__cmp) + } { + std::cmp::Ordering::Greater + } else { + std::cmp::Ordering::Equal + } + } + } +} +impl std::cmp::PartialOrd for Boolish { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl std::cmp::PartialEq for Boolish { + fn eq(&self, other: &Self) -> bool { + unsafe { + { + let __cmp = &operator_eq_7(self.clone(), other.clone()); + MyBool::to_bool(__cmp) + } + } + } +} +impl std::cmp::Eq for Boolish {} +pub unsafe fn operator_eq_7(mut a: Boolish, mut b: Boolish) -> MyBool { + return MyBool::new({ ((a.v) == (b.v)) }); +} +pub unsafe fn operator_lt_6(mut a: Boolish, mut b: Boolish) -> MyBool { + return MyBool::new({ ((a.v) < (b.v)) }); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut a: X = X { v: 1 }; + let mut b: X = X { v: 2 }; + let mut c: X = X { v: 1 }; + assert!( + ((unsafe { + let _a: X = a; + operator_eq_1(_a, c) + }) == (2)) + ); + assert!( + ((unsafe { + let _a: X = a; + operator_eq_1(_a, b) + }) == (0)) + ); + assert!( + ((unsafe { + let _a: X = a; + operator_ne_2(_a, b) + }) == (3)) + ); + assert!( + ((unsafe { + let _a: X = a; + operator_lt_0(_a, b) + }) == (4)) + ); + assert!( + ((unsafe { + let _a: X = b; + operator_gt_3(_a, a) + }) == (5)) + ); + assert!( + ((unsafe { + let _a: X = a; + operator_le_4(_a, c) + }) == (6)) + ); + assert!( + ((unsafe { + let _a: X = a; + operator_ge_5(_a, c) + }) == (7)) + ); + let mut xs: [X; 3] = [X { v: 3 }, X { v: 1 }, X { v: 2 }]; + { + let len = xs + .as_mut_ptr() + .offset((3) as isize) + .offset_from(xs.as_mut_ptr()) as usize; + ::std::slice::from_raw_parts_mut(xs.as_mut_ptr(), len).sort() + }; + assert!( + (((xs[(0) as usize].v) == (1)) && ((xs[(1) as usize].v) == (2))) + && ((xs[(2) as usize].v) == (3)) + ); + let mut p: Custom = Custom { v: 5 }; + let mut q: Custom = Custom { v: 2 }; + let mut r: Result = (unsafe { Custom::operator_cmp(&p, &q) }); + assert!(((r.r) == (3))); + let mut m: Mixed = Mixed { v: 4 }; + let mut n: Mixed = Mixed { v: 4 }; + assert!(((unsafe { Mixed::operator_eq(&m, &n,) }) == (9))); + assert!((((unsafe { Mixed::operator_cmp(&m, &n,) }).r) == (0))); + let mut ms: [Mixed; 3] = [Mixed { v: 6 }, Mixed { v: 4 }, Mixed { v: 5 }]; + { + let len = ms + .as_mut_ptr() + .offset((3) as isize) + .offset_from(ms.as_mut_ptr()) as usize; + ::std::slice::from_raw_parts_mut(ms.as_mut_ptr(), len).sort() + }; + assert!( + (((ms[(0) as usize].v) == (4)) && ((ms[(1) as usize].v) == (5))) + && ((ms[(2) as usize].v) == (6)) + ); + assert!( + ((unsafe { + let _o: *const Mixed = &ms[(1) as usize]; + Mixed::operator_lt(&ms[(0) as usize], _o) + }) == (8)) + ); + let mut b1: Boolish = Boolish { v: 1 }; + let mut b2: Boolish = Boolish { v: 2 }; + assert!( + (unsafe { + MyBool::to_bool( + &(unsafe { + let _a: Boolish = b1; + operator_eq_7(_a, Boolish { v: 1 }) + }), + ) + }) + ); + assert!( + !(unsafe { + MyBool::to_bool( + &(unsafe { + let _a: Boolish = b2; + operator_lt_6(_a, b1) + }), + ) + }) + ); + let mut lt: MyBool = (unsafe { + let _a: Boolish = b1; + operator_lt_6(_a, b2) + }); + assert!(lt.value); + let mut bs: [Boolish; 3] = [Boolish { v: 3 }, Boolish { v: 1 }, Boolish { v: 2 }]; + { + let len = bs + .as_mut_ptr() + .offset((3) as isize) + .offset_from(bs.as_mut_ptr()) as usize; + ::std::slice::from_raw_parts_mut(bs.as_mut_ptr(), len).sort() + }; + assert!( + (((bs[(0) as usize].v) == (1)) && ((bs[(1) as usize].v) == (2))) + && ((bs[(2) as usize].v) == (3)) + ); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {}