Modern C++ compilers reliably devirtualize calls to final methods but diverge significantly on corner cases involving dataflow, internal linkage, and type provenance.
Key Takeaways
final class or method is the most portable devirtualization trigger; GCC, Clang, and MSVC all handle it, but ICC 21.1.9 misses inherited final methods.
Dataflow-based devirtualization degrades fast: Clang fails on conditional casts, MSVC and ICC fail even on simple Base *p = &d patterns.
Classes in anonymous namespaces grant internal linkage, blocking external derivation; compilers can devirtualize calls through such types within the same TU.
GCC uniquely detects devirtualization via incomplete external types whose members have internal linkage; no other tested compiler does this.
LTO whole-program analysis is explicitly out of scope; all results reflect single-TU compiler analysis only.
Hacker News Comment Review
One commenter frames devirtualization as fundamentally a whole-program problem, arguing separate compilation and the Itanium ABI leave single-TU compilers structurally limited without final or stack-provenance tricks.
Discussion is sparse with no substantive rebuttal or additional benchmark data surfaced.