[Issue 18541] comparison `==` of two typeid() should always be rewritten as a "is"

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Mar 6 22:06:27 UTC 2018


https://issues.dlang.org/show_bug.cgi?id=18541

--- Comment #9 from Ketmar Dark <ketmar at ketmar.no-ip.org> ---
compiler transforms `==` for objects to virtual call, and dmd cannot
devirtualize calls (yet? ;-). so yeah, no inlining.

it is quite possible to rewrite the call into `e1 is e1 || .object.opEquals(e1,
e2)`, tho.


--- a/src/ddmd/opover.d
+++ b/src/ddmd/opover.d
@@ -30,6 +30,7 @@ import ddmd.globals;
 import ddmd.id;
 import ddmd.identifier;
 import ddmd.mtype;
+import ddmd.sideeffect;
 import ddmd.statement;
 import ddmd.tokens;
 import ddmd.visitor;
@@ -1162,7 +1163,7 @@ extern (C++) Expression op_overload(Expression e, Scope*
sc)
                 if (!(cd1.cpp || cd2.cpp))
                 {
                     /* Rewrite as:
-                     *      .object.opEquals(e1, e2)
+                     *      e1 is e2 || .object.opEquals(e1, e2)
                      */
                     Expression e1x = e.e1;
                     Expression e2x = e.e2;
@@ -1176,12 +1177,38 @@ extern (C++) Expression op_overload(Expression e,
Scope* sc)
                     if (cd2.isInterfaceDeclaration())
                         e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to :
to.constOf());

+                    /* create temporaries, to avoid invalid rewriting of this:
+                     *    if (arr[i++] is obj || .object.opEquals(arr[i++],
obj)
+                     * rewrite to:
+                     *    tmp1 = e1x, tmp2 = e2x, then use temps
+                     */
+                    // load e1x to temporary
+                    auto tmp1 = copyToTemp(STCnodtor, "__opEqualsTmp1", e1x);
+                    auto e1xtmp = new CommaExp(e.loc, new
DeclarationExp(e.loc, tmp1), new VarExp(e.loc, tmp1));
+
+                    // load e2x to temporary
+                    auto tmp2 = copyToTemp(STCnodtor, "__opEqualsTmp2", e2x);
+                    auto e2xtmp = new CommaExp(e.loc, new
DeclarationExp(e.loc, tmp2), new VarExp(e.loc, tmp2));
+
+                    // e1 is e2
+                    auto expis = new IdentityExp(TOKidentity, e.loc, e1xtmp,
e2xtmp);
+
+                    // and use fresh varexps with temps (previous ones can be
changed by semanticing)
+                    e1x = new VarExp(e.loc, tmp1);
+                    e2x = new VarExp(e.loc, tmp2);
+
+                    // .object.opEquals(e1, e2)
                     result = new IdentifierExp(e.loc, Id.empty);
                     result = new DotIdExp(e.loc, result, Id.object);
                     result = new DotIdExp(e.loc, result, Id.eq);
                     result = new CallExp(e.loc, result, e1x, e2x);
+
+                    // expis || result
+                    result = new LogicalExp(e.loc, TOKoror, expis, result);
+
                     if (e.op == TOKnotequal)
                         result = new NotExp(e.loc, result);
+
                     result = result.semantic(sc);
                     return;
                 }

--


More information about the Digitalmars-d-bugs mailing list