Improve key-function computation for templates. In particular:
- All classes can have a key function; templates don't change that.
non-template classes when computing the key function.
- We always mark all of the virtual member functions of class
template instantiations.
- The vtable for an instantiation of a class template has weak
linkage.
We could probably use available_externally linkage for vtables of
classes instantiated by explicit instantiation declarations (extern
templates), but GCC doesn't do this and I'm not 100% that the ABI
permits it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92753 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 204d776..ecf95d7 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5702,19 +5702,31 @@
ClassesWithUnmarkedVirtualMembers.insert(std::make_pair(RD, Loc));
return;
}
-
- const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
- if (!KeyFunction) {
- // This record does not have a key function, so we assume that the vtable
- // will be emitted when it's used by the constructor.
- if (!isa<CXXConstructorDecl>(MD))
+ switch (RD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization: {
+ const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
+
+ if (!KeyFunction) {
+ // This record does not have a key function, so we assume that the vtable
+ // will be emitted when it's used by the constructor.
+ if (!isa<CXXConstructorDecl>(MD))
+ return;
+ } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) {
+ // We don't have the right key function.
return;
- } else if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) {
- // We don't have the right key function.
- return;
+ }
+ break;
}
-
+
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ // Always mark the virtual members of an instantiated template.
+ break;
+ }
+
// Mark the members as referenced.
MarkVirtualMembersReferenced(Loc, RD);
ClassesWithUnmarkedVirtualMembers.erase(RD);