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@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@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 _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
