So the latest bug I ran into at work involved a missing vtable in Clang. No, I’m
not able to produce a reduced case, so evasion is the only route.
In the meantime, let’s document how to look at vtables.
So, the layout of vtables in memory is simple: the first 8 bytes of every class
with virtual methods is a pointer to a table of function pointers. There’s
exactly one vtable for every class, and if the information for generating this
is missing, you get the familiar linker error.
An object of the EliminateConditionals class will be 1 byte long (any two 0
byte objects will be equal to each other, hence 1 byte). An object of the class
Predicate will be 8 bytes long (the vtable entry), and the vtable will contain
one 8 byte pointer each to shouldEliminate() and ~Predicate(). The reason
they ask you to make destructors virtual is simple: if you’re using a derived
object cast as a base object, and then destructing it doesn’t call the
destructors on the members unique to the derived class.
That’s an image lookup, and it works as long as everything is loaded; nothing
needs to run.