Bug creation and email sending has been disabled, file new bugs at gcc.gnu.org/bugzilla
Bug 248 - Regression: Call result not properly saved when calling a vtbl function
Summary: Regression: Call result not properly saved when calling a vtbl function
Status: RESOLVED FIXED
Alias: None
Product: GDC
Classification: Unclassified
Component: gdc (show other bugs)
Version: development
Hardware: All All
: --- major
Assignee: Iain Buclaw
URL:
Depends on:
Blocks:
 
Reported: 2016-12-10 10:46 CET by Johannes Pfau
Modified: 2023-01-07 21:03 CET (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Pfau 2016-12-10 10:46:22 CET
Reduced from a DDMD build regression:

We've got a function getMemtype which has side effects and returns a class object Bar which has a virtual function isintegral. The function is called in this way: getMemtype().isintegral(). In this call the return value of getMemtype, the reference to a Bar object, is needed twice: Once to get the vtbl entry for isintegral and once to pass the object reference as the this pointer for isintegral. I guess the result of the getMemtype call is not saved properly. We can certainly see that the getMemType function executes twice.

@Iain I'll assign this to you as you are more familiar with this code.

---------------------------------------------------
import std.stdio;

class Bar
{
    bool isintegral()
    {
        return false;
    }
}

class Symbol
{
    Bar getMemtype()
    {
        writeln("foo");
        return new Bar();
    }
}

class Enum
{
    Symbol sym;
    bool isintegral()
    {
        return sym.getMemtype().isintegral();
    }
}

void main()
{
    Enum e = new Enum();
    e.sym = new Symbol();
    e.isintegral();
}
---------------------------------------------------
Comment 1 Johannes Pfau 2016-12-10 10:47:22 CET
Blocks new binary releases for travis-CI.
Comment 2 Iain Buclaw 2016-12-10 21:02:22 CET
(In reply to Johannes Pfau from comment #0)
> Reduced from a DDMD build regression:
> 
> We've got a function getMemtype which has side effects and returns a class
> object Bar which has a virtual function isintegral. The function is called
> in this way: getMemtype().isintegral(). In this call the return value of
> getMemtype, the reference to a Bar object, is needed twice: Once to get the
> vtbl entry for isintegral and once to pass the object reference as the this
> pointer for isintegral. I guess the result of the getMemtype call is not
> saved properly. We can certainly see that the getMemType function executes
> twice.
> 
> @Iain I'll assign this to you as you are more familiar with this code.
> 
> ---------------------------------------------------
> import std.stdio;
> 
> class Bar
> {
>     bool isintegral()
>     {
>         return false;
>     }
> }
> 
> class Symbol
> {
>     Bar getMemtype()
>     {
>         writeln("foo");
>         return new Bar();
>     }
> }
> 
> class Enum
> {
>     Symbol sym;
>     bool isintegral()
>     {
>         return sym.getMemtype().isintegral();
>     }
> }
> 
> void main()
> {
>     Enum e = new Enum();
>     e.sym = new Symbol();
>     e.isintegral();
> }
> ---------------------------------------------------

It looks like the expression is saved, but the saved expression is not re-used when passed as a parameter.

Analogous to:

SAVE_EXPR<this.sym.getMemtype(this.sym)>.isintegral(this.sym.getMemtype(this.sym));
Comment 3 Iain Buclaw 2016-12-10 21:13:55 CET
(In reply to Iain Buclaw from comment #2)
> 
> It looks like the expression is saved, but the saved expression is not
> re-used when passed as a parameter.
> 
> Analogous to:
> 
> SAVE_EXPR<this.sym.getMemtype(this.sym)>.isintegral(this.sym.getMemtype(this.
> sym));

See build_vindex_ref.  Where `object` is saved, but in the caller, the unsaved `object` is then passed to `build_method_call`.

So this saving of `object` should happen in the caller before calling build_vindex_ref.
Comment 4 Iain Buclaw 2016-12-10 21:36:11 CET
https://github.com/D-Programming-GDC/GDC/pull/264