D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3500 - super behaves differently with -inline
Summary: super behaves differently with -inline
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: Other All
: P2 critical
Assignee: No Owner
URL:
Keywords: patch, wrong-code
Depends on:
Blocks: 3761
  Show dependency treegraph
 
Reported: 2009-11-12 10:20 UTC by nfxjfg
Modified: 2014-02-15 13:12 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description nfxjfg 2009-11-12 10:20:47 UTC
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 nfxjfg 2009-11-12 10:29:58 UTC
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 Don 2010-01-04 02:48:03 UTC
This may be related to bug 2127.
Comment 3 Don 2010-02-03 00:19:21 UTC
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();
}
--------------------------------
Comment 4 Walter Bright 2010-02-06 00:03:16 UTC
changeset 373
Comment 5 Walter Bright 2010-03-08 22:21:10 UTC
Fixed dmd 1.057 and 2.041