digitalmars.D - Address of parameterless ref function
- Timon Gehr (26/26) Apr 09 2011 Whats the output of the following code supposed to be?
- Cliff Hudson (11/38) Apr 09 2011 It looks like in the absence of an assignment of the output of g() to so...
- Andrej Mitrovic (9/9) Apr 09 2011 Interesting. The problem I think is that the delegate is declared as
- Timon Gehr (12/12) Apr 10 2011 I think I get it now. The example is actually invalid code accepted by t...
- Andrej Mitrovic (5/5) Apr 10 2011 You can also use this:
- Cliff Hudson (2/12) Apr 09 2011
- Andrej Mitrovic (1/1) Apr 09 2011 I'm using DMD 2.052. Why, are you allowed to declare delegates with ref ...
- Cliff Hudson (6/9) Apr 09 2011 No I was wondering if a different compiler would treat the assignment of...
- Andrej Mitrovic (1/1) Apr 09 2011 It's the same with GDC as is with DMD, just checked.
Whats the output of the following code supposed to be? import std.stdio; int a=0; ref int g(){ writeln("called g"); return ++a; } void main(){ int function() f=&g; writeln(cast(int)&a); writeln(f()); writeln(f()); writeln(f()); } The output using dmd 2.052 -144918776 called g -144918776 called g -144918776 called g -144918776 This is certainly wrong, as it includes an IMPLICIT cast from int* to int, but there are happening other strange things. How to distinguish taking the address of a call to a parameterless ref function from taking the address of the function itself anyways?
Apr 09 2011
It looks like in the absence of an assignment of the output of g() to some value (say int b = g()) which the compiler would insert conversion code for, the ref is retaining some pointer semantics. I'm guessing that because writeln is variadic the compiler doesn't do anything with g's output (like dereference it, convert it to an int, etc.), so you just keep getting the pointer of 'a' back. I don't know the internals, but I'm guessing ref is syntactic sugar to make pointer operations appear like normal value operations. If you replaced (conceptually) ref int g() with int* g(), and replace return ++a with ++a; return &a, then you'd get the output you see. - Cliff On Sat, Apr 9, 2011 at 9:59 AM, Timon Gehr <timon.gehr gmx.ch> wrote:Whats the output of the following code supposed to be? import std.stdio; int a=0; ref int g(){ writeln("called g"); return ++a; } void main(){ int function() f=&g; writeln(cast(int)&a); writeln(f()); writeln(f()); writeln(f()); } The output using dmd 2.052 -144918776 called g -144918776 called g -144918776 called g -144918776 This is certainly wrong, as it includes an IMPLICIT cast from int* to int, but there are happening other strange things. How to distinguish taking the address of a call to a parameterless ref function from taking the address of the function itself anyways?
Apr 09 2011
Interesting. The problem I think is that the delegate is declared as returning int, not ref int. I don't even think we can specify ref as the return value of a delegate. But if you try to declare the delegate as returning an int*, you get this nice error: Error: cannot implicitly convert expression (& g) of type int function() ref to int* function() Still, you can't declare the delegate as "int function() ref" or "ref int function()". I'm not sure why, or why int* can be implicitly cast to int in this case.
Apr 09 2011
I think I get it now. The example is actually invalid code accepted by the dmd frontend. It allows a pointer of type "int function() ref" to be implicitly converted to "int function()". Internally the "int function() ref" returns a pointer to an integer. Both integers and pointers are returned the same way (EAX register AFAIK). Therefore, after the assignment f=&g, the function f=&g is treated as if it was a function that returns an int in the EAX register, while actually it returns a reference to an int in the EAX register. The EAX contents of the EAX register are just interpreted differently. That is how the implicit reinterpret-cast from "int ref" to "int" takes place. I am filing a bug report. BTW: You can actually declare a variable of type "int function() ref" by the means of the auto keyword, but not in any other way. I assume this is a bug too.
Apr 10 2011
You can also use this: typeof(&g) f; f = &g; But I'd say it's definitely a bug if we can't declare delegates with ref returns.
Apr 10 2011
Which compiler are you using? Have you tried a different one? On Sat, Apr 9, 2011 at 10:55 AM, Andrej Mitrovic <andrej.mitrovich gmail.comwrote:Interesting. The problem I think is that the delegate is declared as returning int, not ref int. I don't even think we can specify ref as the return value of a delegate. But if you try to declare the delegate as returning an int*, you get this nice error: Error: cannot implicitly convert expression (& g) of type int function() ref to int* function() Still, you can't declare the delegate as "int function() ref" or "ref int function()". I'm not sure why, or why int* can be implicitly cast to int in this case.
Apr 09 2011
I'm using DMD 2.052. Why, are you allowed to declare delegates with ref returns?
Apr 09 2011
No I was wondering if a different compiler would treat the assignment of &g to f as needing to generate a conversion from int* to int internally (which I think is what Timon was expecting?), or if it would generate an error because the signature of f does not match the signature of g (which is what I would expect.) On Sat, Apr 9, 2011 at 11:12 AM, Andrej Mitrovic <andrej.mitrovich gmail.comwrote:I'm using DMD 2.052. Why, are you allowed to declare delegates with ref returns?
Apr 09 2011
It's the same with GDC as is with DMD, just checked.
Apr 09 2011