Skip to content

Commit 6ed5af8

Browse files
committed
Lower CmpExp between classes to __cmp call
1 parent 1c66d43 commit 6ed5af8

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/dmd/expressionsem.d

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11333,7 +11333,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1133311333
return setError();
1133411334
}
1133511335

11336-
EXP cmpop;
11336+
11337+
EXP cmpop = exp.op;
1133711338
if (auto e = exp.op_overload(sc, &cmpop))
1133811339
{
1133911340
if (!e.type.isscalar() && e.type.equals(exp.e1.type))
@@ -11343,13 +11344,46 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1134311344
}
1134411345
if (e.op == EXP.call)
1134511346
{
11347+
11348+
if (t1.ty == Tclass && t2.ty == Tclass)
11349+
{
11350+
// Lower to object.__cmp(e1, e2)
11351+
Expression cl = new IdentifierExp(exp.loc, Id.empty);
11352+
cl = new DotIdExp(exp.loc, cl, Id.object);
11353+
cl = new DotIdExp(exp.loc, cl, Id.__cmp);
11354+
cl = cl.expressionSemantic(sc);
11355+
11356+
auto arguments = new Expressions();
11357+
// Check if op_overload found a better match by calling e2.opCmp(e1)
11358+
// If the operands were swapped, then the result must be reversed
11359+
// e1.opCmp(e2) == -e2.opCmp(e1)
11360+
// cmpop takes care of this
11361+
if (exp.op == cmpop)
11362+
{
11363+
arguments.push(exp.e1);
11364+
arguments.push(exp.e2);
11365+
}
11366+
else
11367+
{
11368+
// Use better match found by op_overload
11369+
arguments.push(exp.e2);
11370+
arguments.push(exp.e1);
11371+
}
11372+
11373+
cl = new CallExp(exp.loc, cl, arguments);
11374+
cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
11375+
result = cl.expressionSemantic(sc);
11376+
return;
11377+
}
11378+
1134611379
e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
1134711380
e = e.expressionSemantic(sc);
1134811381
}
1134911382
result = e;
1135011383
return;
1135111384
}
1135211385

11386+
1135311387
if (Expression ex = typeCombine(exp, sc))
1135411388
{
1135511389
result = ex;

src/dmd/opover.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,11 +853,11 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
853853
{
854854
// Rewrite (e1 op e2) as e2.opfunc(e1)
855855
result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
856+
// When reversing operands of comparison operators,
857+
// need to reverse the sense of the op
858+
if (pop)
859+
*pop = reverseRelation(e.op);
856860
}
857-
// When reversing operands of comparison operators,
858-
// need to reverse the sense of the op
859-
if (pop)
860-
*pop = reverseRelation(e.op);
861861
return;
862862
}
863863
}

test/runnable/class_opCmp.d

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class A
2+
{
3+
int x;
4+
this(int a) { x = a; }
5+
6+
alias opCmp = Object.opCmp;
7+
alias opCmp = my_cmp;
8+
9+
final int my_cmp(A a)
10+
{
11+
return x - a.x;
12+
}
13+
}
14+
15+
void main()
16+
{
17+
auto a1 = new A(1);
18+
auto a2 = new A(2);
19+
A a_null = null;
20+
assert(a1 > a_null);
21+
assert(a_null < a1);
22+
assert(!(a1 < a1));
23+
assert(a1 < a2);
24+
assert(a2 > a1);
25+
}

0 commit comments

Comments
 (0)