June 16

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.