diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index 48e47cef2508..c27c84e281be 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -11333,6 +11333,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } + EXP cmpop; if (auto e = exp.op_overload(sc, &cmpop)) { @@ -11343,6 +11344,40 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (e.op == EXP.call) { + + if (t1.ty == Tclass && t2.ty == Tclass) + { + // Lower to object.__cmp(e1, e2) + Expression cl = new IdentifierExp(exp.loc, Id.empty); + cl = new DotIdExp(exp.loc, cl, Id.object); + cl = new DotIdExp(exp.loc, cl, Id.__cmp); + cl = cl.expressionSemantic(sc); + + CallExp cexp = cast(CallExp) e; + + auto arguments = new Expressions(); + // Check if op_overload found a better match by calling e2.opCmp(e1) + if (exp.e2 == (*cexp.arguments)[0]) + { + arguments.push(exp.e1); + arguments.push(exp.e2); + } + else + { + // Use better match found by op_overload + arguments.push(exp.e2); + arguments.push(exp.e1); + } + + cl = new CallExp(exp.loc, cl, arguments); + // If the operands were swapped, then the result must be reversed + // e1.opCmp(e2) == -e2.opCmp(e1) + // cmpop takes care of this + cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0)); + result = cl.expressionSemantic(sc); + return; + } + e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0); e = e.expressionSemantic(sc); } @@ -11350,6 +11385,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (Expression ex = typeCombine(exp, sc)) { result = ex;