www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Address of parameterless ref function

reply Timon Gehr <timon.gehr gmx.ch> writes:
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
next sibling parent Cliff Hudson <cliff.s.hudson gmail.com> writes:
--0016e6d99c7b683bc504a07ffdec
Content-Type: text/plain; charset=ISO-8859-1

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?

--0016e6d99c7b683bc504a07ffdec Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable It looks like in the absence of an assignment of the output of g() to some = value (say int b =3D g()) which the compiler would insert conversion code f= or, the ref is retaining some pointer semantics. =A0I&#39;m guessing that b= ecause writeln is variadic the compiler doesn&#39;t do anything with g&#39;= s output (like dereference it, convert it to an int, etc.), so you just kee= p getting the pointer of &#39;a&#39; back. =A0I don&#39;t know the internal= s, but I&#39;m guessing ref is syntactic sugar to make pointer operations a= ppear like normal value operations. =A0If you replaced (conceptually) ref i= nt g() with int* g(), and replace return ++a with ++a; return &amp;a, then = you&#39;d get the output you see.<div> <br></div><div>- Cliff<br><br><div class=3D"gmail_quote">On Sat, Apr 9, 201= 1 at 9:59 AM, Timon Gehr <span dir=3D"ltr">&lt;<a href=3D"mailto:timon.gehr= gmx.ch">timon.gehr gmx.ch</a>&gt;</span> wrote:<br><blockquote class=3D"gm= ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le= ft:1ex;"> Whats the output of the following code supposed to be?<br> <br> import std.stdio;<br> <br> int a=3D0;<br> ref int g(){<br> =A0 =A0writeln(&quot;called g&quot;);<br> =A0 =A0return ++a;<br> }<br> <br> void main(){<br> =A0 =A0int function() f=3D&amp;g;<br> =A0 =A0writeln(cast(int)&amp;a);<br> =A0 =A0writeln(f());<br> =A0 =A0writeln(f());<br> =A0 =A0writeln(f());<br> }<br> <br> The output using dmd 2.052<br> -144918776<br> called g<br> -144918776<br> called g<br> -144918776<br> called g<br> -144918776<br> <br> This is certainly wrong, as it includes an IMPLICIT cast from int* to int, = but<br> there are happening other strange things.<br> <br> How to distinguish taking the address of a call to a parameterless ref<br> function from taking the address of the function itself anyways?<br> <br> <br> <br> </blockquote></div><br></div> --0016e6d99c7b683bc504a07ffdec--
Apr 09 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
parent Timon Gehr <timon.gehr gmx.ch> writes:
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
prev sibling next sibling parent Cliff Hudson <cliff.s.hudson gmail.com> writes:
--0016e6dd8f44c53c7b04a080337c
Content-Type: text/plain; charset=ISO-8859-1

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.com
 wrote:

 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.

--0016e6dd8f44c53c7b04a080337c Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Which compiler are you using? =A0Have you tried a different one?<br><br><di= v class=3D"gmail_quote">On Sat, Apr 9, 2011 at 10:55 AM, Andrej Mitrovic <s= pan dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.mi= trovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex;">Interesting. The problem I think is that th= e delegate is declared as<br> returning int, not ref int. I don&#39;t even think we can specify ref as<br=

as returning an int*, you get this nice error:<br> <br> Error: cannot implicitly convert expression (&amp; g) of type int<br> function() ref to int* function()<br> <br> Still, you can&#39;t declare the delegate as &quot;int function() ref&quot;= or &quot;ref<br> int function()&quot;. I&#39;m not sure why, or why int* can be implicitly c= ast<br> to int in this case.<br> </blockquote></div><br> --0016e6dd8f44c53c7b04a080337c--
Apr 09 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm using DMD 2.052. Why, are you allowed to declare delegates with ref returns?
Apr 09 2011
prev sibling next sibling parent Cliff Hudson <cliff.s.hudson gmail.com> writes:
--20cf301fbeffae9bac04a0806e9f
Content-Type: text/plain; charset=ISO-8859-1

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.com
 wrote:

 I'm using DMD 2.052. Why, are you allowed to declare delegates with ref
 returns?

--20cf301fbeffae9bac04a0806e9f Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable No I was wondering if a different compiler would treat the assignment of &a= mp;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 err= or because the signature of f does not match the signature of g (which is w= hat I would expect.)<br> <br><div class=3D"gmail_quote">On Sat, Apr 9, 2011 at 11:12 AM, Andrej Mitr= ovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">an= drej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmai= l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left= :1ex;"> I&#39;m using DMD 2.052. Why, are you allowed to declare delegates with ref= returns?<br> </blockquote></div><br> --20cf301fbeffae9bac04a0806e9f--
Apr 09 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
It's the same with GDC as is with DMD, just checked.
Apr 09 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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