Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2109,6 +2109,9 @@ "definition of dllimport data">; def err_attribute_dllimport_static_field_definition : Error< "definition of dllimport static field not allowed">; +def warn_attribute_dllimport_static_field_definition : Warning< + "definition of dllimport static field">, + InGroup>; def err_attribute_dll_member_of_dll_class : Error< "attribute %q0 cannot be applied to member of %q1 class">; def err_attribute_weakref_not_static : Error< Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -9061,10 +9061,17 @@ if (const DLLImportAttr *IA = VD->getAttr()) { if (VD->isStaticDataMember() && VD->isOutOfLine() && VD->isThisDeclarationADefinition()) { + // We allow definitions of dllimport class template static data members + // with a warning. + bool JustWarn = cast(VD->getFirstDecl()->getDeclContext()) + ->getDescribedClassTemplate(); + Diag(VD->getLocation(), - diag::err_attribute_dllimport_static_field_definition); + JustWarn ? diag::warn_attribute_dllimport_static_field_definition + : diag::err_attribute_dllimport_static_field_definition); Diag(IA->getLocation(), diag::note_attribute); - VD->setInvalidDecl(); + if (!JustWarn) + VD->setInvalidDecl(); } } Index: test/CodeGenCXX/dllimport.cpp =================================================================== --- test/CodeGenCXX/dllimport.cpp +++ test/CodeGenCXX/dllimport.cpp @@ -571,6 +571,15 @@ template class C; } +namespace ClassTemplateStaticDef { + template struct __declspec(dllimport) S { + static int x; + }; + template int S::x; + // CHECK-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = available_externally dllimport global i32 0 + int f() { return S::x; } +} + //===----------------------------------------------------------------------===// // Negative checks //===----------------------------------------------------------------------===// Index: test/SemaCXX/dllimport.cpp =================================================================== --- test/SemaCXX/dllimport.cpp +++ test/SemaCXX/dllimport.cpp @@ -816,9 +816,9 @@ 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}} +template int ImportClassTmplMembers::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template const int ImportClassTmplMembers::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template constexpr int ImportClassTmplMembers::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} // Redeclarations cannot add dllimport. @@ -853,13 +853,13 @@ 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-warning@-1{{definition of dllimport static field}} // 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-warning@-1{{definition of dllimport static field}} // 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-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} @@ -901,9 +901,9 @@ 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}} +template template int ImportClsTmplMemTmpl::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template template const int ImportClsTmplMemTmpl::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template template constexpr int ImportClsTmplMemTmpl::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} #endif // __has_feature(cxx_variable_templates) @@ -935,13 +935,13 @@ #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-warning@-1{{definition of dllimport static field}} // 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-warning@-1{{definition of dllimport static field}} // 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-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} #endif // __has_feature(cxx_variable_templates) @@ -976,3 +976,10 @@ void __declspec(dllimport) foo(); void __declspec(dllexport) bar(); }; + +namespace ImportedExplicitSpecialization { +template struct S { static int x; }; +template int S::x = sizeof(T); +template <> struct __declspec(dllimport) S { static int x; }; // expected-note{{attribute is here}} +int S::x = -1; // expected-error{{definition of dllimport static field not allowed}} +}