D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 5974 - Incorrect nested function address in expression (&f).ptr
Summary: Incorrect nested function address in expression (&f).ptr
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: Other Windows
: P2 normal
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2011-05-09 23:46 UTC by Denis Shelomovskii
Modified: 2017-06-26 11:57 UTC (History)
3 users (show)

See Also:


Attachments
Problem curious test case (323 bytes, text/x-dsrc)
2011-05-09 23:46 UTC, Denis Shelomovskii
Details

Note You need to log in before you can comment on or make changes to this issue.
Description Denis Shelomovskii 2011-05-09 23:46:44 UTC
Created attachment 966 [details]
Problem curious test case

Simple program:

void main()
{
    void f() { }

    void* t;

    t = (&f).ptr;
    //t = (&f).funcptr; //Uncommented: Error: &f is not an lvalue
}

First, look at lines 00402019 and 0040201E in disassembled main (dmd 1.067):

void main()
00402010  enter       4,0  

    void* t;
00402014  xor         eax,eax 
00402016  mov         dword ptr [t],eax 

    t = (&f).ptr;
00402019  mov         ecx,offset main@main@f (402028h) 
0040201E  mov         dword ptr [t],eax 
00402021  xor         eax,eax 
    //t = (&f).funcptr; //Uncommented: Error: &f is not an lvalue
}
00402023  leave            
00402024  ret              
00402025  int         3    
00402026  int         3    
00402027  int         3    
{
    void f() { }
00402028  enter       4,0  
0040202C  mov         dword ptr [ebp-4],eax 
0040202F  leave            
00402030  ret              


Second, why "&f is not an lvalue" error occurs for "(&f).funcptr"? Maybe, I
don't understand something?

Third, look at curiousTest.d attachment - it fails only if both asserts are
uncommented.
Comment 1 Don 2011-12-20 23:28:04 UTC
More direct test case:

void main()
{	
    void f() { }

    void* t1 = (&f).ptr;
    void* t2 = (&f).ptr;
    assert(t1 == t2);
}
The fac that (&f).funcptr fails to compile is a separate though closely related bug.
Comment 2 yebblies 2012-01-18 19:10:45 UTC
(In reply to comment #0)
> Second, why "&f is not an lvalue" error occurs for "(&f).funcptr"? Maybe, I
> don't understand something?

iirc this fails because dmd rewrites dg.funcptr as *(cast(void**)(&dg)+1), which naturally doesn't work on an rvalue.  The way to fix this is to rewrite it as cast(void*)(cast(uint<64/128>)dg >> <32/64>), the same way array length is accessed.
Comment 3 Vladimir Panteleev 2017-06-26 11:57:36 UTC
I believe this was fixed in https://github.com/dlang/dmd/pull/3181 - at least, the program in comment 2 stops failing after that change. Please reopen otherwise.