Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -11445,8 +11445,6 @@ } else if (Constructor->getInheritedConstructor()) { DefineInheritingConstructor(Loc, Constructor); } - - MarkVTableUsed(Loc, Constructor->getParent()); } else if (CXXDestructorDecl *Destructor = dyn_cast(Func)) { Destructor = cast(Destructor->getFirstDecl()); Index: test/SemaTemplate/virtual-member-functions.cpp =================================================================== --- test/SemaTemplate/virtual-member-functions.cpp +++ test/SemaTemplate/virtual-member-functions.cpp @@ -44,7 +44,7 @@ template struct HasOutOfLineKey { - HasOutOfLineKey() { } + HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey::f' requested here}} virtual T *f(float *fp); }; @@ -53,7 +53,7 @@ return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} } -HasOutOfLineKey out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey::f' requested here}} +HasOutOfLineKey out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey::HasOutOfLineKey' requested here}} namespace std { class type_info; @@ -102,3 +102,53 @@ Y* f(X* x) { return dynamic_cast(x); } // expected-note {{in instantiation of member function 'DynamicCast::X::foo' requested here}} Y* f2(X* x) { return dynamic_cast(x); } } + +namespace avoid_using_vtable { +// We shouldn't emit the vtable for this code, in any ABI. If we emit the +// vtable, we emit an implicit virtual dtor, which calls ~RefPtr, which requires +// a complete type for DeclaredOnly. +// +// Previously we would reference the vtable in the MS C++ ABI, even though we +// don't need to emit either the ctor or the dtor. In the Itanium C++ ABI, the +// 'trace' method is the key function, so even though we use the vtable, we +// don't emit it. + +template +struct RefPtr { + T *m_ptr; + ~RefPtr() { m_ptr->deref(); } +}; +struct DeclaredOnly; +struct Base { + virtual ~Base(); +}; + +struct AvoidVTable : Base { + RefPtr m_insertionStyle; + virtual void trace(); + AvoidVTable(); +}; +// Don't call the dtor, because that will emit an implicit dtor, and require a +// complete type for DeclaredOnly. +void foo() { new AvoidVTable; } +} + +namespace vtable_uses_incomplete { +// Opposite of the previous test that avoids a vtable, this one tests that we +// use the vtable when the ctor is defined inline. +template +struct RefPtr { + T *m_ptr; + ~RefPtr() { m_ptr->deref(); } // expected-error {{member access into incomplete type 'vtable_uses_incomplete::DeclaredOnly'}} +}; +struct DeclaredOnly; // expected-note {{forward declaration of 'vtable_uses_incomplete::DeclaredOnly'}} +struct Base { + virtual ~Base(); +}; + +struct UsesVTable : Base { + RefPtr m_insertionStyle; + virtual void trace(); + UsesVTable() {} // expected-note {{in instantiation of member function 'vtable_uses_incomplete::RefPtr::~RefPtr' requested here}} +}; +}