This week I've worked on _d_class_cast
.
The only issue I encountered was related to the shared
attribute. Since the attributes of the argument passed to the hook are removed (to avoid template instance cluttering), code from core.atomic
, similar to this, failed to compile:
void atomicStore_impl(T)(T* dest, T value)
{}
void atomicStore(T, V)(ref shared T val, auto ref shared V newval)
{
atomicStore_impl(cast(T*)val, cast(V)newval);
}
class A {}
shared A a;
shared A b;
void main()
{
atomicStore(a, b);
}
The problem with this code is that, although the expression newval
passed to the hook was stripped of attributes, the underlying VarExp
was not. Therefore, a simple fix was to also strip the attributes from the VarExp
:
if (auto v = cex.e1.isVarExp())
{
v.var.type = v.var.type.unqualify(MODFlags.shared_);
}
Now some other compilation failures came up, so I defaulted to skipping shared access checks for _d_cast
altogether in functionParameters()
:
if (!p.isReference())
{
if (fd && fd.ident != Id._d_cast)
{
err |= arg.checkSharedAccess(sc);
}
}
This is a cleaner solution, and is actually safe because no direct accesses to the casted object are performed in the hook.
The only thing left to do is to implement a suggested improvement that is based on the observation that _d_class_cast
does not use the template argument To
at all, so a wrapper over it, such as private void* _d_class_cast(To)(Object o){ return _d_class_cast_impl(o, typeid(To)); }
, could be used such that no duplicated code is generated for each template instantiation. The straightforward implementation does seem to cause some weird issues in phobos, but I am still investigation. As soon as I figure it out, the PR is good to go.