MS ABI: Don't always instantiate all members of dllexported class templates (PR20163)
Normally we mark all members of exported classes referenced to get them emitted.
However, MSVC doesn't do this for class templates that are implicitly specialized or
just have an explicit instantiation declaration. For such specializations, the members
are emitted when referenced.
The exception is the case when the dllexport attribute is propagated from a base class
to a base class template that doesn't have an explicit attribute: in this case all
methods of the base class template do get instantiated.
llvm-svn: 216145
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 49a5068..ffec442 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4432,6 +4432,9 @@
// FIXME: MSVC's docs say all bases must be exportable, but this doesn't
// seem to be true in practice?
+ TemplateSpecializationKind TSK =
+ Class->getTemplateSpecializationKind();
+
for (Decl *Member : Class->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(Member);
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
@@ -4471,7 +4474,14 @@
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
if (ClassExported) {
if (MD->isUserProvided()) {
- // Instantiate non-default methods.
+ // Instantiate non-default methods..
+
+ // .. except for certain kinds of template specializations.
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ continue;
+ if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
+ continue;
+
S.MarkFunctionReferenced(Class->getLocation(), MD);
} else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
MD->isCopyAssignmentOperator() ||