New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate correct code for delegate .ptr property. #2200
Conversation
Note, could instead create a temporary like .funcptr, but doesn't seem worth it...
|
Yep, this is an issue for LDC as well. In the past, we simply directly generated a |
I'm not a huge fan of this, I think the correct solution would be to have a new ast class, similar in concept to |
It's not doing glue work in the front end. Its telling the back end the we want to take the base address of the delegate. Type munging a { .ptr, .func } to a void* is not trivially understood at all. Or any non-scalar to pointer for that matter... |
You are generating
Yeah, the current hack is much worse. |
Well, delegates aren't CTFE -able, no? Much for the same reason why virtual methods aren't CTFE -able. |
Actually delegates are CTFEable, and so are virtual functions! |
Well I should really give you a wizard hat then! :o) |
@donc - I've had a look at the bug report, and that's for .funcptr, this change is for the object reference. |
This causes a regression on the following code:
I also don't see the point of having both an rvalue and an lvalue case. If the rvalue code works, why have the lvalue code at all? |
Of course it makes sense now that I've had some sleep. |
That would generate |
Would and should pass. |
Try it before and after applying this patch, you will see. |
Aye, I am also aware that CTFE now sees dg.ptr as returning the address of a local stack variable. :o) |
I'm not sure what the state of this is. Is there a reason for the separate lvalue/rvalue path, and is the "you will see" mean it works correctly? |
There is a separate lvalue/rvalue path because cast's can't be used as lvalues, eg: |
There needs to be a comment to this effect in the source code. Also, what about @yebblies last comment? |
You need to fix the ctfe regression i posted earlier, and/or add the test case: |
That test case doesn't make sense to me. Don't you mean: |
You need to be able to access the |
Because, to me |
Yeah, makes sense. How about: I don't care about the value of |
OK, I'm picking this up and giving it a rethink this week. Any ideas you want to throw at the drawing board in terms of representing this in the front-end implementation? Thanks |
|
I have a patch that implements this, but it changes the behavior of https://github.com/yebblies/dmd/tree/dgfuncptr This is a program that compiles without errors with my changes, current behavior is shown in comments where it differs. void main()
{
int n;
auto p = { ++n; };
enum q = delegate {};
static assert(is(typeof(p.ptr) == void*));
static assert(is(typeof(p.funcptr) == void*)); // (currently, void())
// Can read dg.ptr at run time
auto x = p.ptr;
// Can read dg.funcptr at run time
auto y = p.funcptr;
// Cannot read dg.ptr at compile time (currently, can)
static assert(!__traits(compiles, { enum a = q.ptr; }));
// Cannot read dg.funcptr at compile time (currently, can)
static assert(!__traits(compiles, { enum a = q.funcptr; }));
// cannot assign dg.ptr (currently, can)
static assert(!__traits(compiles, p.ptr = null));
// cannot assign dg.funcptr (currently, can)
static assert(!__traits(compiles, p.funcptr = null));
} I'm not so sure about prohibiting them at compile time, I guess that you could use them to determine if two delegates reference the same function/data. This patch has a side effect of fixing bug 2438 Thoughts? |
Where you say "currently can" at compile time - does it actually work ? I'd honestly be surprised if it did... As for the other two, I would probably stress assignment to .ptr and .funcptr - unless of course you want to make them lvalue properties... |
And if the examples where you currently can at compile time, I would expect CTFE to translate them to (p.ptr) |
Well, you can do And yeah, I think |
edit: s/lvalues/rvalues |
Whoops, my bad... (must have been looking into a mirror to work out which was my left hand). |
The typeof funcptr should be the function type, void* is just way off. |
The function pointer type would be so even further, as there is no way to |
Exactly. It makes very little sense for it to be callable. |
The code change is devoid of comments. Given all the comments here, surely there should be some explanation in the comments, and a test case to validate the changes. |
@WalterBright - I'm not sure what people are even asking to change here anymore. For me, it helps if the frontend does an explicit cast from delegate -> pointer rather than the type stuffing that is currently going on. For Daniel, he wants CTFE support, but I'm not sure that actually covers the scope of this pull. |
I want this not to cause a regression - the |
OK - there are no current tests for this though so it not immediately evident what the regression is, and whether or not the regression is actually a bug fix. :-) I honestly doubt that |
btw @yebblies - where did you get to with your |
The regression is the code that currently compiles, but doesn't after applying this patch. #2200 (comment) I might have another look at |
The current patch I have does this:
The rvalueness matches what Should it be readable at compile time? |
It looks like accessing it from ctfe doesn't currently really work anyway, although IIRC this patch makes it ICE. So if both properties being an rvalue is acceptable, maybe this will do it? #3181 |
I don't think so. Maybe more like turn something that questionably works into an 'error: can not evaluate delegate' |
Ok. Still, I think something along the lines of #3181 would be better. |
ping on this |
Rather than forcing the type, which confuses gcc back-end type system. Generate correct code in the front-end. Not sure if ldc suffers from this too? @klickverbot will be able to confirm. :o)