AST: Fix bad interaction between vtable layout, access control and -enable-testing
Swift allows a method override to be more visible than the base method.
In practice, this means that since it might be possible for client
code to see the override but not the base method, we have to take
extra care when emitting the override.
Specifically, the override always receives a new vtable entry, and
a vtable thunk is emitted in place of the base method's vtable entry
which re-dispatches via the override's vtable entry.
This allows client code to further override the method without any
knowledge of the base method's vtable entry, which may be inaccessible
to the client.
In order for the above to work, three places in the code perform
co-ordinated checks:
- needsNewVTableEntry() determines whether the override is more
visible than the base, in which case it receives a new vtable
entry
- SILGenModule::emitVTableMethod() performs the same check in order
to emit the re-dispatching vtable thunk in place of the base
method's entry
- in the client, SILVTableVisitor then skips the base method's
vtable entry entirely when emitting the derived class, since no
thunk is to be emitted.
The problem was that the first two used effective access (where
internal declarations become public with -enable-testing), while
the last check used formal access. As a result, it was possible
for the method override vtable entry to never be emitted in the
client.
Consistently using either effective access or formal access would
fix the problem. I fixed the first two to rely on formal access;
the reason is that using effective access makes vtable layout
depend on whether the library was built with -enable-testing or
not, which is undesirable since we do not want -enable-testing to
impact the ABI, even for non-resilient frameworks.
Fixes rdar://problem/74108928.