Skip to content

Commit fab2a56

Browse files
committed
Look through references for non-bool comparison operators
1 parent 2bb3063 commit fab2a56

5 files changed

Lines changed: 50 additions & 4 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4753,14 +4753,19 @@ std::string Converter::GetComparisonBool(const clang::FunctionDecl *op,
47534753
if (ret->isIntegerType()) {
47544754
return std::format("(({}) != 0)", call);
47554755
}
4756-
const auto *record = ret->getAsCXXRecordDecl();
4756+
bool returns_ref = ret->isReferenceType();
4757+
const auto *record = ret.getNonReferenceType()->getAsCXXRecordDecl();
47574758
assert(record && "unsupported comparison operator return type");
47584759
for (const auto *found : record->getVisibleConversionFunctions()) {
47594760
const auto *conversion = clang::dyn_cast<clang::CXXConversionDecl>(found);
47604761
if (conversion && conversion->getConversionType()->isBooleanType()) {
4761-
return std::format("{{ let __cmp = &{}; {}::{}({}) }}", call,
4762-
GetUFCSName(conversion), GetMethodName(conversion),
4763-
GetComparisonReceiver(conversion, record, "__cmp"));
4762+
auto receiver =
4763+
returns_ref
4764+
? GetComparisonReferenceReceiver(conversion, record, "__cmp")
4765+
: GetComparisonReceiver(conversion, record, "__cmp");
4766+
return std::format("{{ let __cmp = {}{}; {}::{}({}) }}",
4767+
returns_ref ? "" : "&", call, GetUFCSName(conversion),
4768+
GetMethodName(conversion), receiver);
47644769
}
47654770
}
47664771
assert(0 && "comparison operator result has no conversion to bool");
@@ -4773,6 +4778,13 @@ Converter::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
47734778
return std::format("{} as *const {}", value, GetRecordName(decl));
47744779
}
47754780

4781+
std::string
4782+
Converter::GetComparisonReferenceReceiver(const clang::CXXMethodDecl *method,
4783+
const clang::CXXRecordDecl *decl,
4784+
std::string_view ptr) {
4785+
return GetComparisonReceiver(method, decl, std::format("&*{}", ptr));
4786+
}
4787+
47764788
std::string Converter::GetComparisonReceiver(const clang::CXXMethodDecl *method,
47774789
const clang::CXXRecordDecl *,
47784790
std::string_view lhs) {

‎cpp2rust/converter/converter.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,11 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
694694
GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
695695
std::string_view value);
696696

697+
virtual std::string
698+
GetComparisonReferenceReceiver(const clang::CXXMethodDecl *method,
699+
const clang::CXXRecordDecl *decl,
700+
std::string_view ptr);
701+
697702
virtual std::string GetComparisonReceiver(const clang::CXXMethodDecl *method,
698703
const clang::CXXRecordDecl *decl,
699704
std::string_view lhs);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,12 @@ ConverterRefCount::GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
583583
return BoxValue(GetShallowCopy(decl, value)) + ".as_pointer()";
584584
}
585585

586+
std::string ConverterRefCount::GetComparisonReferenceReceiver(
587+
const clang::CXXMethodDecl *, const clang::CXXRecordDecl *,
588+
std::string_view ptr) {
589+
return std::format("&{}", ptr);
590+
}
591+
586592
std::string
587593
ConverterRefCount::GetComparisonReceiver(const clang::CXXMethodDecl *,
588594
const clang::CXXRecordDecl *decl,

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class ConverterRefCount final : public Converter {
4545
std::string GetComparisonReferenceArg(const clang::CXXRecordDecl *decl,
4646
std::string_view value) override;
4747

48+
std::string GetComparisonReferenceReceiver(const clang::CXXMethodDecl *method,
49+
const clang::CXXRecordDecl *decl,
50+
std::string_view ptr) override;
51+
4852
std::string GetComparisonReceiver(const clang::CXXMethodDecl *method,
4953
const clang::CXXRecordDecl *decl,
5054
std::string_view lhs) override;

‎tests/unit/operator_comparison_nonbool.cpp‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ struct Boolish {
4242
MyBool operator==(Boolish a, Boolish b) { return MyBool(a.v == b.v); }
4343
MyBool operator<(Boolish a, Boolish b) { return MyBool(a.v < b.v); }
4444

45+
struct RefBool {
46+
bool value;
47+
explicit RefBool(bool v) : value(v) {}
48+
RefBool(const RefBool &) = delete;
49+
operator bool() const { return value; }
50+
};
51+
52+
static RefBool ref_true{true};
53+
54+
struct RefInt {
55+
int v;
56+
RefBool &operator==(const RefInt &) const { return ref_true; }
57+
};
58+
4559
int main() {
4660
X a{1}, b{2}, c{1};
4761
assert((a == c) == 2);
@@ -76,5 +90,10 @@ int main() {
7690
Boolish bs[] = {{3}, {1}, {2}};
7791
std::sort(bs, bs + 3);
7892
assert(bs[0].v == 1 && bs[1].v == 2 && bs[2].v == 3);
93+
94+
RefInt ri1{1}, ri2{2};
95+
assert(ri1 == ri2);
96+
RefInt ris[] = {{1}, {2}};
97+
assert(std::find(ris, ris + 2, ri2) == ris);
7998
return 0;
8099
}

0 commit comments

Comments
 (0)