From 078d2f89cd6adf8ed6e464c2432f9a55b2cb1534 Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Thu, 29 May 2014 16:50:20 +0000 Subject: [PATCH] Sema: Check dll attributes on static data members Redeclarations cannot add a dll attribute and static data members cannot be defined. llvm-svn: 209825 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 + clang/lib/Sema/SemaDecl.cpp | 24 ++- clang/test/SemaCXX/dllexport.cpp | 157 +++++++++++++++++++ clang/test/SemaCXX/dllimport.cpp | 182 +++++++++++++++++++++++ 4 files changed, 362 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7a9eb4f..ac43a0c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2102,6 +2102,8 @@ def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; def err_attribute_dllimport_data_definition : Error< "definition of dllimport data">; +def err_attribute_dllimport_static_field_definition : Error< + "definition of dllimport static field not allowed">; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< @@ -2443,6 +2445,7 @@ def warn_attribute_protected_visibility : InGroup>; def err_mismatched_visibility: Error<"visibility does not match previous declaration">; def note_previous_attribute : Note<"previous attribute is here">; +def note_attribute : Note<"attribute is here">; def err_mismatched_ms_inheritance : Error< "inheritance model does not match %select{definition|previous declaration}0">; def warn_ignored_ms_inheritance : Warning< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9614d0d..075b399 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4907,10 +4907,15 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // A redeclaration is not allowed to drop a dllimport attribute, the only // exception being inline function definitions. // NB: MSVC converts such a declaration to dllexport. - bool IsInline = - isa(NewDecl) && cast(NewDecl)->isInlined(); - - if (OldImportAttr && !HasNewAttr && !IsInline) { + bool IsInline = false, IsStaticDataMember = false; + if (const auto *VD = dyn_cast(NewDecl)) + // Ignore static data because out-of-line definitions are diagnosed + // separately. + IsStaticDataMember = VD->isStaticDataMember(); + else if (const auto *FD = dyn_cast(NewDecl)) + IsInline = FD->isInlined(); + + if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember) { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_attribute_prev_attribute_ignored) << NewDecl << OldImportAttr; @@ -9052,6 +9057,17 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { checkAttributesAfterMerging(*this, *VD); + // Imported static data members cannot be defined out-of-line. + if (const DLLImportAttr *IA = VD->getAttr()) { + if (VD->isStaticDataMember() && VD->isOutOfLine() && + VD->isThisDeclarationADefinition()) { + Diag(VD->getLocation(), + diag::err_attribute_dllimport_static_field_definition); + Diag(IA->getLocation(), diag::note_attribute); + VD->setInvalidDecl(); + } + } + if (UsedAttr *Attr = VD->getAttr()) { if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) { Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr; diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp index c361c49..510d34bb 100644 --- a/clang/test/SemaCXX/dllexport.cpp +++ b/clang/test/SemaCXX/dllexport.cpp @@ -379,6 +379,17 @@ protected: __declspec(dllexport) void protectedDef(); private: __declspec(dllexport) void privateDef(); +public: + + __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to variables and functions}} + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static int StaticFieldDef; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldDef; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; + __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; }; void ExportMembers::Nested::normalDef() {} @@ -394,6 +405,10 @@ inline void ExportMembers::staticInlineDef() {} void ExportMembers::protectedDef() {} void ExportMembers::privateDef() {} + int ExportMembers::StaticFieldDef; +const int ExportMembers::StaticConstFieldDef = 1; +constexpr int ExportMembers::ConstexprFieldDef; + // Export on member definitions. struct ExportMemberDefs { @@ -406,6 +421,10 @@ struct ExportMemberDefs { __declspec(dllexport) static void staticDef(); __declspec(dllexport) static void staticInlineDef(); __declspec(dllexport) static inline void staticInlineDecl(); + + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) constexpr static int ConstexprField = 1; }; __declspec(dllexport) void ExportMemberDefs::normalDef() {} @@ -418,6 +437,10 @@ __declspec(dllexport) void ExportMemberDefs::staticDef() {} __declspec(dllexport) inline void ExportMemberDefs::staticInlineDef() {} __declspec(dllexport) void ExportMemberDefs::staticInlineDecl() {} +__declspec(dllexport) int ExportMemberDefs::StaticField; +__declspec(dllexport) const int ExportMemberDefs::StaticConstField = 1; +__declspec(dllexport) constexpr int ExportMemberDefs::ConstexprField; + // Export special member functions. struct ExportSpecials { @@ -497,6 +520,10 @@ struct MemberRedecl { static void staticDef(); // expected-note{{previous declaration is here}} static void staticInlineDef(); // expected-note{{previous declaration is here}} static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; __declspec(dllexport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllexport' attribute}} @@ -509,6 +536,10 @@ __declspec(dllexport) void MemberRedecl::staticDef() {} // expect __declspec(dllexport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllexport' attribute}} __declspec(dllexport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} +__declspec(dllexport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllexport' attribute}} +__declspec(dllexport) const int MemberRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllexport' attribute}} +__declspec(dllexport) constexpr int MemberRedecl::ConstexprField; // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllexport' attribute}} + //===----------------------------------------------------------------------===// @@ -526,6 +557,17 @@ struct ExportMemberTmpl { template __declspec(dllexport) static void staticInclass() {} template __declspec(dllexport) static void staticInlineDef(); template __declspec(dllexport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template __declspec(dllexport) static int StaticField; + template __declspec(dllexport) static int StaticFieldDef; + template __declspec(dllexport) static const int StaticConstField; + template __declspec(dllexport) static const int StaticConstFieldDef; + template __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + template __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + template __declspec(dllexport) constexpr static int ConstexprField = 1; + template __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +#endif // __has_feature(cxx_variable_templates) }; template void ExportMemberTmpl::normalDef() {} @@ -535,6 +577,11 @@ template void ExportMemberTmpl::staticDef() {} template inline void ExportMemberTmpl::staticInlineDef() {} template void ExportMemberTmpl::staticInlineDecl() {} +#if __has_feature(cxx_variable_templates) +template int ExportMemberTmpl::StaticFieldDef; +template const int ExportMemberTmpl::StaticConstFieldDef = 1; +template constexpr int ExportMemberTmpl::ConstexprFieldDef; +#endif // __has_feature(cxx_variable_templates) // Redeclarations cannot add dllexport. @@ -545,6 +592,12 @@ struct MemTmplRedecl { template static void staticDef(); // expected-note{{previous declaration is here}} template static void staticInlineDef(); // expected-note{{previous declaration is here}} template static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template static int StaticField; // expected-note{{previous declaration is here}} + template static const int StaticConstField; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) }; template __declspec(dllexport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}} @@ -554,6 +607,12 @@ template __declspec(dllexport) void MemTmplRedecl::staticDef( template __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}} template __declspec(dllexport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} +#if __has_feature(cxx_variable_templates) +template __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} +#endif // __has_feature(cxx_variable_templates) + struct MemFunTmpl { @@ -621,6 +680,52 @@ template<> __declspec(dllexport) inline void MemFunTmpl::staticDef static const int StaticVar = 1; + template __declspec(dllexport) static const int ExportedStaticVar = 1; +}; +template const int MemVarTmpl::StaticVar; +template const int MemVarTmpl::ExportedStaticVar; + +// Export implicit instantiation of an exported member variable template. +int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar; } + +// Export explicit instantiation declaration of an exported member variable +// template. +extern template const int MemVarTmpl::ExportedStaticVar; + template const int MemVarTmpl::ExportedStaticVar; + +// Export explicit instantiation definition of an exported member variable +// template. +template const int MemVarTmpl::ExportedStaticVar; + +// Export specialization of an exported member variable template. +template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar; +template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar = 1; + +// Not exporting specialization of an exported member variable template without +// explicit dllexport. +template<> const int MemVarTmpl::ExportedStaticVar; + + +// Export explicit instantiation declaration of a non-exported member variable +// template. +extern template __declspec(dllexport) const int MemVarTmpl::StaticVar; + template __declspec(dllexport) const int MemVarTmpl::StaticVar; + +// Export explicit instantiation definition of a non-exported member variable +// template. +template __declspec(dllexport) const int MemVarTmpl::StaticVar; + +// Export specialization of a non-exported member variable template. +template<> __declspec(dllexport) const int MemVarTmpl::StaticVar; +template<> __declspec(dllexport) const int MemVarTmpl::StaticVar = 1; + +#endif // __has_feature(cxx_variable_templates) + + + //===----------------------------------------------------------------------===// // Class template members //===----------------------------------------------------------------------===// @@ -648,6 +753,17 @@ protected: __declspec(dllexport) void protectedDef(); private: __declspec(dllexport) void privateDef(); +public: + + __declspec(dllexport) int Field; // expected-warning{{'dllexport' attribute only applies to variables and functions}} + __declspec(dllexport) static int StaticField; + __declspec(dllexport) static int StaticFieldDef; + __declspec(dllexport) static const int StaticConstField; + __declspec(dllexport) static const int StaticConstFieldDef; + __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllexport) constexpr static int ConstexprField = 1; + __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; }; template void ExportClassTmplMembers::normalDef() {} @@ -662,6 +778,10 @@ template void ExportClassTmplMembers::staticInlineDecl() { template void ExportClassTmplMembers::protectedDef() {} template void ExportClassTmplMembers::privateDef() {} +template int ExportClassTmplMembers::StaticFieldDef; +template const int ExportClassTmplMembers::StaticConstFieldDef = 1; +template constexpr int ExportClassTmplMembers::ConstexprFieldDef; + template struct ExportClassTmplMembers; @@ -677,6 +797,10 @@ struct CTMR /*ClassTmplMemberRedecl*/ { static void staticDef(); // expected-note{{previous declaration is here}} static void staticInlineDef(); // expected-note{{previous declaration is here}} static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; template __declspec(dllexport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} @@ -689,6 +813,10 @@ template __declspec(dllexport) void CTMR::staticDef() {} template __declspec(dllexport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}} template __declspec(dllexport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} + //===----------------------------------------------------------------------===// @@ -707,6 +835,17 @@ struct ExportClsTmplMemTmpl { template __declspec(dllexport) static void staticInclass() {} template __declspec(dllexport) static void staticInlineDef(); template __declspec(dllexport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template __declspec(dllexport) static int StaticField; + template __declspec(dllexport) static int StaticFieldDef; + template __declspec(dllexport) static const int StaticConstField; + template __declspec(dllexport) static const int StaticConstFieldDef; + template __declspec(dllexport) static const int StaticConstFieldEqualInit = 1; + template __declspec(dllexport) static const int StaticConstFieldBraceInit{1}; + template __declspec(dllexport) constexpr static int ConstexprField = 1; + template __declspec(dllexport) constexpr static int ConstexprFieldDef = 1; +#endif // __has_feature(cxx_variable_templates) }; template template void ExportClsTmplMemTmpl::normalDef() {} @@ -716,6 +855,12 @@ template template void ExportClsTmplMemTmpl::s template template inline void ExportClsTmplMemTmpl::staticInlineDef() {} template template void ExportClsTmplMemTmpl::staticInlineDecl() {} +#if __has_feature(cxx_variable_templates) +template template int ExportClsTmplMemTmpl::StaticFieldDef; +template template const int ExportClsTmplMemTmpl::StaticConstFieldDef = 1; +template template constexpr int ExportClsTmplMemTmpl::ConstexprFieldDef; +#endif // __has_feature(cxx_variable_templates) + // Redeclarations cannot add dllexport. template @@ -726,6 +871,12 @@ struct CTMTR /*ClassTmplMemberTmplRedecl*/ { template static void staticDef(); // expected-note{{previous declaration is here}} template static void staticInlineDef(); // expected-note{{previous declaration is here}} template static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template static int StaticField; // expected-note{{previous declaration is here}} + template static const int StaticConstField; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) }; template template __declspec(dllexport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}} @@ -734,3 +885,9 @@ template template __declspec(dllexport) void CTMT template template __declspec(dllexport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}} template template __declspec(dllexport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}} template template __declspec(dllexport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}} + +#if __has_feature(cxx_variable_templates) +template template __declspec(dllexport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +#endif // __has_feature(cxx_variable_templates) diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp index 41f8e3c..dea8333 100644 --- a/clang/test/SemaCXX/dllimport.cpp +++ b/clang/test/SemaCXX/dllimport.cpp @@ -387,6 +387,17 @@ protected: __declspec(dllimport) void protectedDecl(); private: __declspec(dllimport) void privateDecl(); +public: + + __declspec(dllimport) int Field; // expected-warning{{'dllimport' attribute only applies to variables and functions}} + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} }; void ImportMembers::Nested::normalDef() {} // expected-warning{{'ImportMembers::Nested::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} @@ -400,6 +411,10 @@ inline void ImportMembers::virtualInlineDef() {} inline void ImportMembers::staticInlineDef() {} void ImportMembers::staticInlineDecl() {} + int ImportMembers::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +const int ImportMembers::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +constexpr int ImportMembers::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} + // Import on member definitions. struct ImportMemberDefs { @@ -412,6 +427,10 @@ struct ImportMemberDefs { __declspec(dllimport) static void staticDef(); __declspec(dllimport) static void staticInlineDef(); __declspec(dllimport) static inline void staticInlineDecl(); + + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) constexpr static int ConstexprField = 1; }; __declspec(dllimport) void ImportMemberDefs::normalDef() {} // expected-error{{dllimport cannot be applied to non-inline function definition}} @@ -424,6 +443,10 @@ __declspec(dllimport) void ImportMemberDefs::staticDef() {} // expected-e __declspec(dllimport) inline void ImportMemberDefs::staticInlineDef() {} __declspec(dllimport) void ImportMemberDefs::staticInlineDecl() {} +__declspec(dllimport) int ImportMemberDefs::StaticField; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} +__declspec(dllimport) const int ImportMemberDefs::StaticConstField = 1; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} +__declspec(dllimport) constexpr int ImportMemberDefs::ConstexprField; // expected-error{{definition of dllimport static field not allowed}} expected-note{{attribute is here}} + // Import special member functions. struct ImportSpecials { @@ -493,6 +516,10 @@ struct MemberRedecl { static void staticDef(); // expected-note{{previous declaration is here}} static void staticInlineDef(); // expected-note{{previous declaration is here}} static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; __declspec(dllimport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllimport' attribute}} @@ -508,6 +535,16 @@ __declspec(dllimport) void MemberRedecl::staticDef() {} // expect __declspec(dllimport) inline void MemberRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDef' cannot add 'dllimport' attribute}} __declspec(dllimport) void MemberRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemberRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} +__declspec(dllimport) int MemberRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +__declspec(dllimport) const int MemberRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +__declspec(dllimport) constexpr int MemberRedecl::ConstexprField; // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + //===----------------------------------------------------------------------===// @@ -525,6 +562,17 @@ struct ImportMemberTmpl { template __declspec(dllimport) static void staticInclass() {} template __declspec(dllimport) static void staticInlineDef(); template __declspec(dllimport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template __declspec(dllimport) static int StaticField; + template __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + template __declspec(dllimport) static const int StaticConstField; + template __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + template __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + template __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + template __declspec(dllimport) constexpr static int ConstexprField = 1; + template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) }; template void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} @@ -534,6 +582,12 @@ template void ImportMemberTmpl::staticDef() {} // expected-wa template inline void ImportMemberTmpl::staticInlineDef() {} template void ImportMemberTmpl::staticInlineDecl() {} +#if __has_feature(cxx_variable_templates) +template int ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template const int ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +template constexpr int ImportMemberTmpl::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +#endif // __has_feature(cxx_variable_templates) + // Redeclarations cannot add dllimport. struct MemTmplRedecl { @@ -543,6 +597,12 @@ struct MemTmplRedecl { template static void staticDef(); // expected-note{{previous declaration is here}} template static void staticInlineDef(); // expected-note{{previous declaration is here}} template static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template static int StaticField; // expected-note{{previous declaration is here}} + template static const int StaticConstField; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) }; template __declspec(dllimport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}} @@ -554,6 +614,18 @@ template __declspec(dllimport) void MemTmplRedecl::staticDef( template __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}} template __declspec(dllimport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} +#if __has_feature(cxx_variable_templates) +template __declspec(dllimport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template __declspec(dllimport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) + struct MemFunTmpl { @@ -628,6 +700,52 @@ template<> __declspec(dllimport) inline void MemFunTmpl::staticDef static const int StaticVar = 1; + template __declspec(dllimport) static const int ImportedStaticVar = 1; +}; + +// Import implicit instantiation of an imported member variable template. +int useMemVarTmpl() { return MemVarTmpl::ImportedStaticVar; } + +// Import explicit instantiation declaration of an imported member variable +// template. +extern template const int MemVarTmpl::ImportedStaticVar; + +// An explicit instantiation definition of an imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of an imported member variable template. +template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar; +template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar = 1; + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + +// Not importing specialization of a member variable template without explicit +// dllimport. +template<> const int MemVarTmpl::ImportedStaticVar; + + +// Import explicit instantiation declaration of a non-imported member variable +// template. +extern template __declspec(dllimport) const int MemVarTmpl::StaticVar; + +// An explicit instantiation definition of a non-imported member variable template +// cannot be imported because the template must be defined which is illegal. The +// in-class initializer does not count. + +// Import specialization of a non-imported member variable template. +template<> __declspec(dllimport) const int MemVarTmpl::StaticVar; +template<> __declspec(dllimport) const int MemVarTmpl::StaticVar = 1; + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + +#endif // __has_feature(cxx_variable_templates) + + + //===----------------------------------------------------------------------===// // Class template members //===----------------------------------------------------------------------===// @@ -655,6 +773,17 @@ protected: __declspec(dllimport) void protectedDecl(); private: __declspec(dllimport) void privateDecl(); +public: + + __declspec(dllimport) int Field; // expected-warning{{'dllimport' attribute only applies to variables and functions}} + __declspec(dllimport) static int StaticField; + __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstField; + __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + __declspec(dllimport) constexpr static int ConstexprField = 1; + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} }; // NB: MSVC is inconsistent here and disallows *InlineDef on class templates, @@ -669,6 +798,10 @@ template void ImportClassTmplMembers::staticDef() {} // ex template inline void ImportClassTmplMembers::staticInlineDef() {} template void ImportClassTmplMembers::staticInlineDecl() {} +template int ImportClassTmplMembers::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template const int ImportClassTmplMembers::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +template constexpr int ImportClassTmplMembers::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} + // Redeclarations cannot add dllimport. template @@ -682,6 +815,10 @@ struct CTMR /*ClassTmplMemberRedecl*/ { static void staticDef(); // expected-note{{previous declaration is here}} static void staticInlineDef(); // expected-note{{previous declaration is here}} static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + + static int StaticField; // expected-note{{previous declaration is here}} + static const int StaticConstField; // expected-note{{previous declaration is here}} + constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; template __declspec(dllimport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} @@ -697,6 +834,16 @@ template __declspec(dllimport) void CTMR::staticDef() {} template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} template __declspec(dllimport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template __declspec(dllimport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template __declspec(dllimport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} + //===----------------------------------------------------------------------===// @@ -715,6 +862,17 @@ struct ImportClsTmplMemTmpl { template __declspec(dllimport) static void staticInclass() {} template __declspec(dllimport) static void staticInlineDef(); template __declspec(dllimport) static inline void staticInlineDecl(); + +#if __has_feature(cxx_variable_templates) + template __declspec(dllimport) static int StaticField; + template __declspec(dllimport) static int StaticFieldDef; // expected-note{{attribute is here}} + template __declspec(dllimport) static const int StaticConstField; + template __declspec(dllimport) static const int StaticConstFieldDef; // expected-note{{attribute is here}} + template __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; + template __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; + template __declspec(dllimport) constexpr static int ConstexprField = 1; + template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) }; template template void ImportClsTmplMemTmpl::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} @@ -724,6 +882,12 @@ template template void ImportClsTmplMemTmpl::s template template inline void ImportClsTmplMemTmpl::staticInlineDef() {} template template void ImportClsTmplMemTmpl::staticInlineDecl() {} +#if __has_feature(cxx_variable_templates) +template template int ImportClsTmplMemTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template template const int ImportClsTmplMemTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} +template template constexpr int ImportClsTmplMemTmpl::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +#endif // __has_feature(cxx_variable_templates) + // Redeclarations cannot add dllimport. template @@ -734,6 +898,12 @@ struct CTMTR /*ClassTmplMemberTmplRedecl*/ { template static void staticDef(); // expected-note{{previous declaration is here}} template static void staticInlineDef(); // expected-note{{previous declaration is here}} template static inline void staticInlineDecl(); // expected-note{{previous declaration is here}} + +#if __has_feature(cxx_variable_templates) + template static int StaticField; // expected-note{{previous declaration is here}} + template static const int StaticConstField; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#endif // __has_feature(cxx_variable_templates) }; template template __declspec(dllimport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}} @@ -744,3 +914,15 @@ template template __declspec(dllimport) void CTMT // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} template template __declspec(dllimport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}} + +#if __has_feature(cxx_variable_templates) +template template __declspec(dllimport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template template __declspec(dllimport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +template template __declspec(dllimport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllimport' attribute}} + // expected-error@-1{{definition of dllimport static field not allowed}} + // expected-note@-2{{attribute is here}} +#endif // __has_feature(cxx_variable_templates) -- 2.7.4