<div dir="ltr">Hi,<div><br></div><div>clang currently calls MarkVTableUsed() for classes that get their virtual methods called or that participate in a dynamic_cast. This is unnecessary, since CodeGen only emits vtables when it generates constructor, destructor, and vtt code.</div><div><br></div><div>Remember that sema's MarkVTableUsed() doesn't actually cause emission of a vtable, it only marks all methods that are in the vtable as referenced – to make sure that when codegen decides to write a vtable, everything in there is actually defined. Since virtual calls and dynamic casts do not cause codegen to write a vtable, it's not necessary to define methods in the vtable for them. After this patch, sema only calls MarkVTableUsed() for the definitions of constructors and destructors – the only two things that make codegen write a vtable* (look for `getAddrOfVTable` in lib/CodeGen).</div>







<div><br></div><div>They still get defined if they're referenced by a direct call – this only affects virtual methods that are not called and were only referenced by MarkVTableUsed(), for example if a different virtual method was called). For the same reason, this doesn't have an effect on what llvm can or can't optimize (see also PR20337 comment 10). It does lead to the emission of fewer unneeded methods, which will speed up builds.</div><div><br></div><div>While this shouldn't change the behavior of codegen (other than being faster), it does make clang more permissive: virtual methods (in particular destructors) end up being instantiated less often. In particular, classes that have members that are smart pointers to incomplete types will now get their implicit virtual destructor instantiated less frequently. For example, this used to not compile but does now compile:</div><div><br></div><div><div>    template <typename T> struct OwnPtr {</div><div>      ~OwnPtr() { static_assert((sizeof(T) > 0), "TypeMustBeComplete"); }</div><div>    };</div><div>    class ScriptLoader;<br></div><div>    struct Base { virtual ~Base(); };<br></div><div>    struct Sub : public Base {</div><div>      virtual void someFun() const {}</div><div>      OwnPtr<ScriptLoader> m_loader;</div><div>    };</div><div>    void f(Sub *s) { s->someFun(); }<br></div></div><div><br></div><div>The more permissive behavior matches both gcc (where this is not often observable, since in practice most things with virtual methods have a key function) and cl (which is my motivation for this change) – this fixes PR20337.</div><div><br></div><div>This is similar to r213109 in spirit. r225761 was a prerequisite for this change.</div><div><br>Various tests relied on "a->f()" marking a's vtable as used (in the sema sense), switch these to just construct a on the stack. This forces instantiation of the implicit constructor, which will mark the vtable as used.</div><div><br></div><div>* The exception is -fapple-kext mode: In this mode, qualified calls to virtual functions (`a->Base::f()`) still go through the vtable, and since the vtable pointer off this doesn't point to Base's vtable, this needs to reference Base's vtable directly. To keep this working, keep referencing the vtable for virtual calls in apple kext mode. There's 0 test coverage for this :-/</div><div><br></div><div>Nico</div></div>