r226208 - Warn about dllexported explicit class template instantiation declarations (PR22035)
Hans Wennborg
hans at hanshq.net
Thu Jan 15 13:18:30 PST 2015
Author: hans
Date: Thu Jan 15 15:18:30 2015
New Revision: 226208
URL: http://llvm.org/viewvc/llvm-project?rev=226208&view=rev
Log:
Warn about dllexported explicit class template instantiation declarations (PR22035)
Clang would previously become confused and crash here.
It does not make a lot of sense to export these, so warning seems appropriate.
MSVC will export some member functions for this kind of specializations, whereas
MinGW ignores the dllexport-edness. The latter behaviour seems better.
Differential Revision: http://reviews.llvm.org/D6984
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CodeGenCXX/dllexport.cpp
cfe/trunk/test/SemaCXX/dllexport.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=226208&r1=226207&r2=226208&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jan 15 15:18:30 2015
@@ -2201,6 +2201,9 @@ def err_attribute_dllimport_static_field
def warn_attribute_dllimport_static_field_definition : Warning<
"definition of dllimport static field">,
InGroup<DiagGroup<"dllimport-static-field-def">>;
+def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
+ "explicit instantiation declaration should not be 'dllexport'">,
+ InGroup<DiagGroup<"dllexport-explicit-instantation-decl">>;
def warn_invalid_initializer_from_system_header : Warning<
"invalid constructor form class in system header, should not be explicit">,
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=226208&r1=226207&r2=226208&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jan 15 15:18:30 2015
@@ -4709,15 +4709,20 @@ static void checkDLLAttribute(Sema &S, C
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
const bool ClassImported = !ClassExported;
+ TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
+
+ // Don't dllexport explicit class template instantiation declarations.
+ if (ClassExported && TSK == TSK_ExplicitInstantiationDeclaration) {
+ Class->dropAttr<DLLExportAttr>();
+ return;
+ }
+
// Force declaration of implicit members so they can inherit the attribute.
S.ForceDeclarationOfImplicitMembers(Class);
// 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);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=226208&r1=226207&r2=226208&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 15 15:18:30 2015
@@ -7165,9 +7165,27 @@ Sema::ActOnExplicitInstantiation(Scope *
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
- TemplateSpecializationKind TSK
- = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
- : TSK_ExplicitInstantiationDeclaration;
+ TemplateSpecializationKind TSK = ExternLoc.isInvalid()
+ ? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ // Check for dllexport class template instantiation declarations.
+ for (AttributeList *A = Attr; A; A = A->getNext()) {
+ if (A->getKind() == AttributeList::AT_DLLExport) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLoc(), diag::note_attribute);
+ break;
+ }
+ }
+
+ if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) {
+ Diag(ExternLoc,
+ diag::warn_attribute_dllexport_explicit_instantiation_decl);
+ Diag(A->getLocation(), diag::note_attribute);
+ }
+ }
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=226208&r1=226207&r2=226208&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Thu Jan 15 15:18:30 2015
@@ -631,6 +631,17 @@ template <typename T> struct ExplicitIns
};
template struct __declspec(dllexport) ExplicitInstConstexprMembers<void>;
+template <typename T> struct ExplicitInstantiationDeclTemplate { void f() {} };
+extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclTemplate at H@@QAEXXZ"
+
+template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate { void f() {} };
+extern template struct ExplicitInstantiationDeclExportedTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate at H@@QAEXXZ"
+
+
//===----------------------------------------------------------------------===//
// Classes with template base classes
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=226208&r1=226207&r2=226208&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Thu Jan 15 15:18:30 2015
@@ -353,10 +353,10 @@ ImplicitlyInstantiatedExportedTemplate<I
// Don't instantiate class members of templates with explicit instantiation declarations, even if they are exported.
struct IncompleteType2;
-template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl {
+template <typename T> struct __declspec(dllexport) ExportedTemplateWithExplicitInstantiationDecl { // expected-note{{attribute is here}}
int f() { return sizeof(T); } // no-error
};
-extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>;
+extern template struct ExportedTemplateWithExplicitInstantiationDecl<IncompleteType2>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}}
// Instantiate class members for explicitly instantiated exported templates.
struct IncompleteType3; // expected-note{{forward declaration of 'IncompleteType3'}}
@@ -386,7 +386,12 @@ template <typename T> struct __declspec(
};
struct __declspec(dllexport) ExportedBaseClass2 : public ExportedBaseClassTemplateOfExportedClass<IncompleteType5> {};
+// Warn about explicit instantiation declarations of dllexport classes.
+template <typename T> struct ExplicitInstantiationDeclTemplate {};
+extern template struct __declspec(dllexport) ExplicitInstantiationDeclTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}} expected-note{{attribute is here}}
+template <typename T> struct __declspec(dllexport) ExplicitInstantiationDeclExportedTemplate {}; // expected-note{{attribute is here}}
+extern template struct ExplicitInstantiationDeclExportedTemplate<int>; // expected-warning{{explicit instantiation declaration should not be 'dllexport'}}
//===----------------------------------------------------------------------===//
// Classes with template base classes
More information about the cfe-commits
mailing list