[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