diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | test/CodeGenCXX/virt-template-vtable.cpp | 10 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-exception-spec-cxx11.cpp | 14 |
3 files changed, 41 insertions, 8 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index fc631d0d87..32708090c9 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -10795,14 +10795,23 @@ bool Sema::DefineUsedVTables() { void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD) { - for (CXXRecordDecl::method_iterator i = RD->method_begin(), - e = RD->method_end(); i != e; ++i) { - CXXMethodDecl *MD = *i; - - // C++ [basic.def.odr]p2: - // [...] A virtual member function is used if it is not pure. [...] - if (MD->isVirtual() && !MD->isPure()) - MarkFunctionReferenced(Loc, MD); + // Mark all functions which will appear in RD's vtable as used. + CXXFinalOverriderMap FinalOverriders; + RD->getFinalOverriders(FinalOverriders); + for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), + E = FinalOverriders.end(); + I != E; ++I) { + for (OverridingMethods::const_iterator OI = I->second.begin(), + OE = I->second.end(); + OI != OE; ++OI) { + assert(OI->second.size() > 0 && "no final overrider"); + CXXMethodDecl *Overrider = OI->second.front().Method; + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (!Overrider->isPure()) + MarkFunctionReferenced(Loc, Overrider); + } } // Only classes that have virtual bases need a VTT. diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp index 25736fd603..a6067d62c6 100644 --- a/test/CodeGenCXX/virt-template-vtable.cpp +++ b/test/CodeGenCXX/virt-template-vtable.cpp @@ -20,3 +20,13 @@ template class A<short>; // CHECK: @_ZTV1AIlE = weak_odr unnamed_addr constant // CHECK: @_ZTV1AIsE = weak_odr unnamed_addr constant // CHECK: @_ZTV1AIiE = linkonce_odr unnamed_addr constant + +template<class T> struct C { + virtual void c() {} +}; +struct D : C<int> { + virtual void d(); +}; +void D::d() {} + +// CHECK: define {{.*}}@_ZN1CIiE1cEv( diff --git a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp index 8a6f9efa68..c560c6ba2a 100644 --- a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp +++ b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp @@ -131,3 +131,17 @@ template<typename T> struct Derived : Base { Derived<Exc1> d1; // ok Derived<Exc2> d2; // expected-note {{in instantiation of}} + +// If the vtable for a derived class is used, the exception specification of +// any member function which ends up in that vtable is needed, even if it was +// declared in a base class. +namespace PR12763 { + template<bool *B> struct T { + virtual void f() noexcept (*B); // expected-error {{constant expression}} expected-note {{read of non-const}} + }; + bool b; // expected-note {{here}} + struct X : public T<&b> { + virtual void g(); + }; + void X::g() {} // expected-note {{in instantiation of}} +} |