In practice neither GCC nor Clang seem to be willing to believe that the vtable is immutable. See https://goo.gl/y0cx1r, for example, which shows only the first of two calls being devirtualized. The call to fprintf within B::work is sufficient to cause to both compilers to reload the vtable pointer, preventing devirtualization of the second call.
Interestingly enough, when a use of placement new is visible to the compiler it can prevent the conservative behavior mentioned above. In https://goo.gl/Y8rwYG the vtable store that placement new conceptually generates allows Clang to devirtualize the second virtual call. GCC doesn't appear to catch this case.