Thread overview
[Issue 6705] Bad codegen when passing fields as template alias params
Nov 03, 2019
Basile-z
Nov 03, 2019
Basile-z
Mar 21, 2020
Basile-z
Aug 09, 2020
Walter Bright
Aug 29, 2020
Walter Bright
Sep 15, 2020
Walter Bright
Sep 15, 2020
Walter Bright
November 03, 2019
https://issues.dlang.org/show_bug.cgi?id=6705

Basile-z <b2.temp@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |b2.temp@gmx.com

--- Comment #2 from Basile-z <b2.temp@gmx.com> ---
this is a case where the global function (and non static) used as template
param becomes a (non-static) member.

But when the global func used as alias template parameter is explicitely declared static this just works for example:


static int func(alias F)(int i)
{
    return i;
}

class C
{
    int a;
}

void main()
{
    auto a = &func!(C.a);
    assert(a(5) == 5);
    auto i = func!(C.a)(5);
}

I once tried to infer "static" but this broke the test suite... so people have to put it by themselves even if it is weird to do so at the global scope.

--
November 03, 2019
https://issues.dlang.org/show_bug.cgi?id=6705

Basile-z <b2.temp@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Hardware|x86                         |All

--
March 21, 2020
https://issues.dlang.org/show_bug.cgi?id=6705

Basile-z <b2.temp@gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|b2.temp@gmx.com             |

--
August 09, 2020
https://issues.dlang.org/show_bug.cgi?id=6705

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #3 from Walter Bright <bugzilla@digitalmars.com> ---
The generated code is:

__Dmain comdat
                enter   4,0
                mov     EAX,offset __D4test__T4funcS_DQq1C1aiZQqMFNaNbNiNfiZi
                mov     -4[EBP],EAX
                mov     EAX,5             <=== EAX should be pushed on the
stack
                call    dword ptr -4[EBP]
                mov     ECX,5
                cmp     EAX,ECX
                je      L2A
                push    0Eh
                mov     EDX,offset FLAT:___a6_746573742e64
                push    EDX
                call    near ptr __d_assertp
L2A:            xor     EAX,EAX
                leave
                ret

__D4test__T4funcS_DQq1C1aiZQqMFNaNbNiNfiZi      comdat
                mov     EAX,4[ESP]
                ret     4

Not sure why it isn't pushed on the stack.

--
August 29, 2020
https://issues.dlang.org/show_bug.cgi?id=6705

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |backend

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=6705

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|backend, rejects-valid,     |accepts-invalid, safe
                   |wrong-code                  |

--- Comment #4 from Walter Bright <bugzilla@digitalmars.com> ---
Here's what's happening:

When C.a is passed as an alias argument to func(), then func becomes (for that
instantiation) a member of C. Being a member function, then it expects a 'this'
pointer. But when a(5) is called, there is no 'this' pointer, and the '5' is
interpreted as the 'this' pointer, and 'i' is garbage.

The same problem appears with this simpler example:

    class C
    {
        int a;
        int member(long);
    }

    void moon()
    {
        auto f = &C.member;  // creates `int function(long)`
        f();  // oops, no `this`
    }

It does need to be possible to take the address of a member function without the 'this', and if we make that an error, we may break existing legitimate code.

Note the following:

    int delegate(long) dg;
    pragma(msg, typeof(dg.funcptr));

prints:

    int function(long)

so changing the type of &C.member to `void*` isn't going to work, either.

meaning one can construct delegates by using &C.member for dg.funcptr and some void* for dg.ptr.

What I can do is make taking the address of a member without `this` not allowed in @safe code.

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=6705

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |INVALID

--- Comment #5 from Walter Bright <bugzilla@digitalmars.com> ---
Well, I'll be. Adding @safe causes the code to give an error on taking the address.

That resolves this issue.

--