When marking virtual functions as used for a class' vtable, mark all functions
which will appear in the vtable as used, not just those ones which were
declared within the class itself. Fixes an issue reported as comment#3 in
PR12763 -- we sometimes assert in codegen if we try to emit a reference to a
function declaration which we've not marked as referenced. This also matches
gcc's observed behavior.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159895 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fc631d0..3270809 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -10795,14 +10795,23 @@
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;
+ // 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 (MD->isVirtual() && !MD->isPure())
- MarkFunctionReferenced(Loc, MD);
+ // 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.