The following program behaves differently whether you pass -inline to dmd or not.
The correct output is "A::x()", but with -inline, it outputs "B::x()".
Conclusion: the dmd inliner must be buggy.
I confirmed this with:
- dmd 1.051/Tango
- dmd 2.035/Phobos
Command line, failing binary: dmd bug.d -inline
Correct binary: dmd bug.d
Test using Tango:
import tango.util.log.Trace;
class A {
void x() {
Trace.formatln("A::x()");
}
}
class B : A {
override void x() {
Trace.formatln("B::x()");
}
private void do_x() {
super.x();
}
}
void main() {
B b = new B();
b.do_x();
}
Comment #1 by nfxjfg — 2009-11-12T10:29:58Z
D2 testcase.
import std.stdio;
class A {
void x() {
writefln("A::x()");
}
}
class B : A {
override void x() {
writefln("B::x()");
}
private void do_x() {
super.x();
}
}
void main() {
B b = new B();
b.do_x();
}
Comment #2 by clugdbug — 2010-01-04T02:48:03Z
This may be related to bug 2127.
Comment #3 by clugdbug — 2010-02-03T00:19:21Z
The thing that isn't working correctly is this line from the 'Expressions' page in the spec: "If a member function is called with an explicit reference to super, a non-virtual call is made." This bug applies to D1 as well (DMD1.00 fails).
Cause: direct calls are normally implemented in e2ir.c. If CallExp::toElem() finds TOKsuper, it makes it a non-virtual call. But the direct call is a little bit of a hack (there's a "//BUG: fix" comment in FuncExp::toElem()).
inline.c, SuperExp::doInline() changes it from 'super' to a variable, so e2ir can't find it.
This patch disables inlining for direct 'super' calls. Allowing them to be inlined would be a quite difficult, I think.
Index: inline.c
===================================================================
--- inline.c (revision 362)
+++ inline.c (working copy)
@@ -275,6 +275,10 @@
int CallExp::inlineCost(InlineCostState *ics)
{
+ // Bugzilla 3500: super.func() calls must be devirtualized, and the inliner
+ // can't handle that at present.
+ if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper)
+ return COST_MAX;
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
}
-------------------------------------------------
Test case without any imports:
--------------------------------
class A {
void x() { }
}
class B : A {
override void x() {
assert(0);
}
final void do_x() {
super.x();
}
}
void main() {
B b = new B();
b.do_x();
}
--------------------------------