diff options
author | Hans Wennborg <hans@hanshq.net> | 2014-06-04 00:18:41 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2014-06-04 00:18:41 +0000 |
commit | e9af3164237f16a35e6f57c06f09b20cb7b4b622 (patch) | |
tree | 4eb060352c9e8fea1fb072d2fda4b450ce15b3ac | |
parent | 547f536bcf6a29ffd63b5f921c5c15732e17dd19 (diff) | |
download | bcm5719-llvm-e9af3164237f16a35e6f57c06f09b20cb7b4b622.tar.gz bcm5719-llvm-e9af3164237f16a35e6f57c06f09b20cb7b4b622.zip |
Downgrade "definition of dllimport static field" error to warning for class templates (PR19902)
This allows us to compile the following kind of code, which occurs in MSVC
headers:
template <typename> struct S {
__declspec(dllimport) static int x;
};
template <typename T> int S<T>::x;
The definition works similarly to a dllimport inline function definition and
gets available_externally linkage.
Differential Revision: http://reviews.llvm.org/D3998
llvm-svn: 210141
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 13 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport.cpp | 9 | ||||
-rw-r--r-- | clang/test/SemaCXX/dllimport.cpp | 31 |
4 files changed, 42 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 28273caa6ce..2ea49df7cb1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2109,6 +2109,9 @@ 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 warn_attribute_dllimport_static_field_definition : Warning< + "definition of dllimport static field">, + InGroup<DiagGroup<"dllimport-static-field-def">>; 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< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 075b399a673..9bd51b9f19c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9061,10 +9061,19 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { if (const DLLImportAttr *IA = VD->getAttr<DLLImportAttr>()) { if (VD->isStaticDataMember() && VD->isOutOfLine() && VD->isThisDeclarationADefinition()) { + // We allow definitions of dllimport class template static data members + // with a warning. + bool IsClassTemplateMember = + cast<CXXRecordDecl>(VD->getFirstDecl()->getDeclContext()) + ->getDescribedClassTemplate(); + Diag(VD->getLocation(), - diag::err_attribute_dllimport_static_field_definition); + IsClassTemplateMember + ? diag::warn_attribute_dllimport_static_field_definition + : diag::err_attribute_dllimport_static_field_definition); Diag(IA->getLocation(), diag::note_attribute); - VD->setInvalidDecl(); + if (!IsClassTemplateMember) + VD->setInvalidDecl(); } } diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp index ed36d8d0440..70661a94269 100644 --- a/clang/test/CodeGenCXX/dllimport.cpp +++ b/clang/test/CodeGenCXX/dllimport.cpp @@ -571,6 +571,15 @@ namespace Vtordisp { template class C<char>; } +namespace ClassTemplateStaticDef { + template <typename T> struct __declspec(dllimport) S { + static int x; + }; + template <typename T> int S<T>::x; + // CHECK-DAG: @"\01?x@?$S@H@ClassTemplateStaticDef@@2HA" = available_externally dllimport global i32 0 + int f() { return S<int>::x; } +} + //===----------------------------------------------------------------------===// // Negative checks //===----------------------------------------------------------------------===// diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp index 3f4a4871c52..7ca89f0dd08 100644 --- a/clang/test/SemaCXX/dllimport.cpp +++ b/clang/test/SemaCXX/dllimport.cpp @@ -816,9 +816,9 @@ template<typename T> void ImportClassTmplMembers<T>::staticDef() {} // ex template<typename T> inline void ImportClassTmplMembers<T>::staticInlineDef() {} template<typename T> void ImportClassTmplMembers<T>::staticInlineDecl() {} -template<typename T> int ImportClassTmplMembers<T>::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} -template<typename T> const int ImportClassTmplMembers<T>::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} -template<typename T> constexpr int ImportClassTmplMembers<T>::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template<typename T> int ImportClassTmplMembers<T>::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template<typename T> const int ImportClassTmplMembers<T>::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template<typename T> constexpr int ImportClassTmplMembers<T>::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} // Redeclarations cannot add dllimport. @@ -853,13 +853,13 @@ template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef( template<typename T> __declspec(dllimport) void CTMR<T>::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} template<typename T> __declspec(dllimport) int CTMR<T>::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<typename T> __declspec(dllimport) const int CTMR<T>::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<typename T> __declspec(dllimport) constexpr int CTMR<T>::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<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::s template<typename T> template<typename U> void ImportClsTmplMemTmpl<T>::staticInlineDecl() {} #if __has_feature(cxx_variable_templates) -template<typename T> template<typename U> int ImportClsTmplMemTmpl<T>::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} -template<typename T> template<typename U> const int ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} -template<typename T> template<typename U> constexpr int ImportClsTmplMemTmpl<T>::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +template<typename T> template<typename U> int ImportClsTmplMemTmpl<T>::StaticFieldDef; // expected-warning{{definition of dllimport static field}} +template<typename T> template<typename U> const int ImportClsTmplMemTmpl<T>::StaticConstFieldDef = 1; // expected-warning{{definition of dllimport static field}} +template<typename T> template<typename U> constexpr int ImportClsTmplMemTmpl<T>::ConstexprFieldDef; // expected-warning{{definition of dllimport static field}} #endif // __has_feature(cxx_variable_templates) @@ -935,13 +935,13 @@ template<typename T> template<typename U> __declspec(dllimport) void CTMT #if __has_feature(cxx_variable_templates) template<typename T> template<typename U> __declspec(dllimport) int CTMTR<T>::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<typename T> template<typename U> __declspec(dllimport) const int CTMTR<T>::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<typename T> template<typename U> __declspec(dllimport) constexpr int CTMTR<T>::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 @@ class __declspec(dllexport) ExportClassWithDllMember { void __declspec(dllimport) foo(); void __declspec(dllexport) bar(); }; + +namespace ImportedExplicitSpecialization { +template <typename T> struct S { static int x; }; +template <typename T> int S<T>::x = sizeof(T); +template <> struct __declspec(dllimport) S<int> { static int x; }; // expected-note{{attribute is here}} +int S<int>::x = -1; // expected-error{{definition of dllimport static field not allowed}} +} |