Bug 20110 – Module constructor implicitly converts a delegate pointer into a function pointer

Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Mac OS X
Creation time
2019-08-06T06:16:30Z
Last change time
2019-08-07T10:22:55Z
Assigned to
No Owner
Creator
Andrej Mitrovic

Comments

Comment #0 by andrej.mitrovich — 2019-08-06T06:16:30Z
----- import std.stdio; alias void function(int, int) Callback; void passCallback ( Callback cb ) { cb(10, 20); } class C { static this() { passCallback(&test); // doesn't fail???? } void test (int foo, int bar) { writefln("foo: %s, bar: %s", foo, bar); } } void main () { auto c = new C; static assert(!is(typeof(passCallback(&c.test)))); // correct } import std.stdio; alias void function(int, int) Callback; void passCallback ( Callback cb ) { cb(10, 20); } class C { static this() { passCallback(&test); // doesn't fail???? } void test (int foo, int bar) { writefln("foo: %s, bar: %s", foo, bar); // corrupt parameter } } void main () { auto c = new C; static assert(!is(typeof(passCallback(&c.test)))); // correct } ----- I don't know if this is an edge-case in the implementation, but it's really dangerous. In my case, I tried to pass a pointer to an extern(C) function to a C library, and got corruption. It's because I forgot to mark my function as `static`, so I was actually passing a function which has the hidden 'this' object as the first parameter..
Comment #1 by andrej.mitrovich — 2019-08-06T06:17:07Z
Ah I botched up the code sample, great. This is the one: ----- import std.stdio; alias void function(int, int) Callback; void passCallback ( Callback cb ) { cb(10, 20); } class C { static this() { passCallback(&test); // doesn't fail???? } void test (int foo, int bar) { writefln("foo: %s, bar: %s", foo, bar); } } void main () { auto c = new C; static assert(!is(typeof(passCallback(&c.test)))); // correct } -----
Comment #2 by simen.kjaras — 2019-08-06T06:57:27Z
There's a difference between &c.test as you use in the assert, and &C.test, which is what you use in the static this(). The former requires an instance to serve as the context for the delegate, while the latter does not. That said, is this behavior useful? Should typeof(&C.test) really be void function(int, int)? As demonstrated above, it's just plain wrong. The correct type for typeof(&C.test) is probably void function(int, int, C), as demonstrated below: alias int function(int, int, C) Callback; void passCallback ( Callback cb ) { auto c = new C; c.i = 30; assert(cb(10, 20, c) == 102030); } class C { int i; int test (int foo, int bar) { return foo*10000 + bar*100 + i; } } unittest { passCallback(cast(Callback)&C.test); }
Comment #3 by simen.kjaras — 2019-08-07T10:22:55Z
*** This issue has been marked as a duplicate of issue 17080 ***