Bug 8545 – defined opCast disables cast(void*)this in classes

Status
RESOLVED
Resolution
INVALID
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-08-12T20:33:46Z
Last change time
2023-01-02T08:31:28Z
Assigned to
No Owner
Creator
Andrej Mitrovic

Comments

Comment #0 by andrej.mitrovich — 2012-08-12T20:33:46Z
class Foo { T opCast(T : int)() { return 1; } void* test() { return cast(void*)this; } } void main() { } This is problematic, cast(void*)this is the trick used to get the address of 'this' object. &this is the address of the reference and can't be used for the same purpose. So defining opCast for any type ends up disabling 'cast(void*)this'. I honestly think we should have a druntime function or some kind of compiler intrinsic to get the equivalent of 'cast(void*)this'. That cast itself looks too hacky to begin with.
Comment #1 by andrej.mitrovich — 2012-08-12T20:35:06Z
Oh and the error message, not that it matters: Error: template instance opCast!(void*) opCast!(void*) does not match template declaration opCast(T : int)
Comment #2 by bugzilla — 2012-08-12T21:50:50Z
I don't think this is major, because you can use a union: { static union U { Object o; void* p; } U u; u.o = this; return u.p; } In fact, because a union can be used for reinterpret casting, I don't think any new syntax or semantics are needed.
Comment #3 by andrej.mitrovich — 2012-08-13T07:57:58Z
(In reply to comment #2) > I don't think this is major, because you can use a union: > > { > static union U { Object o; void* p; } > U u; > u.o = this; > return u.p; > } > > In fact, because a union can be used for reinterpret casting, I don't think any > new syntax or semantics are needed. I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an inner d_object pointer which it uses to invoke D virtual methods). You're asking me to introduce overhead for every time a new class object is instantiated.
Comment #4 by art.08.09 — 2012-08-14T03:21:53Z
(In reply to comment #3) > (In reply to comment #2) > > I don't think this is major, because you can use a union: > > > > { > > static union U { Object o; void* p; } > > U u; > > u.o = this; > > return u.p; > > } > > > > In fact, because a union can be used for reinterpret casting, I don't think any > > new syntax or semantics are needed. > > I'm speaking in terms of wrapping C++ libraries (A C++ wrapper class has an > inner d_object pointer which it uses to invoke D virtual methods). You're > asking me to introduce overhead for every time a new class object is > instantiated. The compiler /should/ handle it w/o any additional runtime overhead. You could also use void* test() { return *cast(void**)&this; } Which approach will be more efficient probably depends on compiler implementation; ideally both versions should be free.
Comment #5 by andrej.mitrovich — 2012-08-14T08:18:35Z
> You could also use > > void* test() { return *cast(void**)&this; } > Thanks! It does seem to create the exact same assembly even with no optimizations.
Comment #6 by alphaglosined — 2023-01-01T18:18:13Z
I'm reopening this bug report for two reasons: 1. Hipreme ran into this when creating a class manually which had opCast defined. 2. With the current work replacing _d_newclass with a template, new will no longer work with a class that isn't ultra-specific with its opCast. In practice this will be a breaking change, so it's time to fix this bug to prevent code breakage.
Comment #7 by alphaglosined — 2023-01-02T08:31:28Z
Closing again, because I did make a mistake. The new class hook won't need this, and destroy already works. So even if this doesn't make sense why it wasn't fixed, I'll put it back to original state.