r209825 - Sema: Check dll attributes on static data members

Nico Rieck nico.rieck at gmail.com
Thu May 29 09:50:20 PDT 2014


Author: nrieck
Date: Thu May 29 11:50:20 2014
New Revision: 209825

URL: http://llvm.org/viewvc/llvm-project?rev=209825&view=rev
Log:
Sema: Check dll attributes on static data members

Redeclarations cannot add a dll attribute and static data members cannot
be defined.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/dllexport.cpp
    cfe/trunk/test/SemaCXX/dllimport.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=209825&r1=209824&r2=209825&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 29 11:50:20 2014
@@ -2102,6 +2102,8 @@ def err_attribute_dllimport_function_def
   "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<DiagGroup<"unsupported-visibility">>;
 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<

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=209825&r1=209824&r2=209825&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 29 11:50:20 2014
@@ -4907,10 +4907,15 @@ static void checkDLLAttributeRedeclarati
   // 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<FunctionDecl>(NewDecl) && cast<FunctionDecl>(NewDecl)->isInlined();
+  bool IsInline = false, IsStaticDataMember = false;
+  if (const auto *VD = dyn_cast<VarDecl>(NewDecl))
+    // Ignore static data because out-of-line definitions are diagnosed
+    // separately.
+    IsStaticDataMember = VD->isStaticDataMember();
+  else if (const auto *FD = dyn_cast<FunctionDecl>(NewDecl))
+    IsInline = FD->isInlined();
 
-  if (OldImportAttr && !HasNewAttr && !IsInline) {
+  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<DLLImportAttr>()) {
+    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<UsedAttr>()) {
     if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
       Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;

Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=209825&r1=209824&r2=209825&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Thu May 29 11:50:20 2014
@@ -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::staticInlineD
        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 Export
 __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 Member
 __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<typename T> __declspec(dllexport) static        void staticInclass() {}
   template<typename T> __declspec(dllexport) static        void staticInlineDef();
   template<typename T> __declspec(dllexport) static inline void staticInlineDecl();
+
+#if __has_feature(cxx_variable_templates)
+  template<typename T> __declspec(dllexport) static        int  StaticField;
+  template<typename T> __declspec(dllexport) static        int  StaticFieldDef;
+  template<typename T> __declspec(dllexport) static const  int  StaticConstField;
+  template<typename T> __declspec(dllexport) static const  int  StaticConstFieldDef;
+  template<typename T> __declspec(dllexport) static const  int  StaticConstFieldEqualInit = 1;
+  template<typename T> __declspec(dllexport) static const  int  StaticConstFieldBraceInit{1};
+  template<typename T> __declspec(dllexport) constexpr static int ConstexprField = 1;
+  template<typename T> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1;
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T>        void ExportMemberTmpl::normalDef() {}
@@ -535,6 +577,11 @@ template<typename T>        void ExportM
 template<typename T> inline void ExportMemberTmpl::staticInlineDef() {}
 template<typename T>        void ExportMemberTmpl::staticInlineDecl() {}
 
+#if __has_feature(cxx_variable_templates)
+template<typename T>        int  ExportMemberTmpl::StaticFieldDef;
+template<typename T> const  int  ExportMemberTmpl::StaticConstFieldDef = 1;
+template<typename T> constexpr int ExportMemberTmpl::ConstexprFieldDef;
+#endif // __has_feature(cxx_variable_templates)
 
 
 // Redeclarations cannot add dllexport.
@@ -545,6 +592,12 @@ struct MemTmplRedecl {
   template<typename T> static        void staticDef();         // expected-note{{previous declaration is here}}
   template<typename T> static        void staticInlineDef();   // expected-note{{previous declaration is here}}
   template<typename T> static inline void staticInlineDecl();  // expected-note{{previous declaration is here}}
+
+#if __has_feature(cxx_variable_templates)
+  template<typename T> static        int  StaticField;         // expected-note{{previous declaration is here}}
+  template<typename T> static const  int  StaticConstField;    // expected-note{{previous declaration is here}}
+  template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> __declspec(dllexport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}}
@@ -554,6 +607,12 @@ template<typename T> __declspec(dllexpor
 template<typename T> __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}}
 template<typename T> __declspec(dllexport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}}
 
+#if __has_feature(cxx_variable_templates)
+template<typename T> __declspec(dllexport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}}
+template<typename T> __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
 
 
 
+#if __has_feature(cxx_variable_templates)
+struct MemVarTmpl {
+  template<typename T>                       static const int StaticVar = 1;
+  template<typename T> __declspec(dllexport) static const int ExportedStaticVar = 1;
+};
+template<typename T> const int MemVarTmpl::StaticVar;
+template<typename T> const int MemVarTmpl::ExportedStaticVar;
+
+// Export implicit instantiation of an exported member variable template.
+int useMemVarTmpl() { return MemVarTmpl::ExportedStaticVar<ImplicitInst_Exported>; }
+
+// Export explicit instantiation declaration of an exported member variable
+// template.
+extern template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
+       template const int MemVarTmpl::ExportedStaticVar<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of an exported member variable
+// template.
+template const int MemVarTmpl::ExportedStaticVar<ExplicitInst_Exported>;
+
+// Export specialization of an exported member variable template.
+template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Exported>;
+template<> __declspec(dllexport) const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_Def_Exported> = 1;
+
+// Not exporting specialization of an exported member variable template without
+// explicit dllexport.
+template<> const int MemVarTmpl::ExportedStaticVar<ExplicitSpec_NotExported>;
+
+
+// Export explicit instantiation declaration of a non-exported member variable
+// template.
+extern template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
+       template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitDecl_Exported>;
+
+// Export explicit instantiation definition of a non-exported member variable
+// template.
+template __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitInst_Exported>;
+
+// Export specialization of a non-exported member variable template.
+template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Exported>;
+template<> __declspec(dllexport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Exported> = 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<typename T>        void ExportClassTmplMembers<T>::normalDef() {}
@@ -662,6 +778,10 @@ template<typename T>        void ExportC
 template<typename T>        void ExportClassTmplMembers<T>::protectedDef() {}
 template<typename T>        void ExportClassTmplMembers<T>::privateDef() {}
 
+template<typename T>        int  ExportClassTmplMembers<T>::StaticFieldDef;
+template<typename T> const  int  ExportClassTmplMembers<T>::StaticConstFieldDef = 1;
+template<typename T> constexpr int ExportClassTmplMembers<T>::ConstexprFieldDef;
+
 template struct ExportClassTmplMembers<ImplicitInst_Exported>;
 
 
@@ -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<typename T> __declspec(dllexport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}}
@@ -689,6 +813,10 @@ template<typename T> __declspec(dllexpor
 template<typename T> __declspec(dllexport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}}
 template<typename T> __declspec(dllexport)        void CTMR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}}
 
+template<typename T> __declspec(dllexport)        int  CTMR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) const  int  CTMR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}}
+
 
 
 //===----------------------------------------------------------------------===//
@@ -707,6 +835,17 @@ struct ExportClsTmplMemTmpl {
   template<typename U> __declspec(dllexport) static        void staticInclass() {}
   template<typename U> __declspec(dllexport) static        void staticInlineDef();
   template<typename U> __declspec(dllexport) static inline void staticInlineDecl();
+
+#if __has_feature(cxx_variable_templates)
+  template<typename U> __declspec(dllexport) static        int  StaticField;
+  template<typename U> __declspec(dllexport) static        int  StaticFieldDef;
+  template<typename U> __declspec(dllexport) static const  int  StaticConstField;
+  template<typename U> __declspec(dllexport) static const  int  StaticConstFieldDef;
+  template<typename U> __declspec(dllexport) static const  int  StaticConstFieldEqualInit = 1;
+  template<typename U> __declspec(dllexport) static const  int  StaticConstFieldBraceInit{1};
+  template<typename U> __declspec(dllexport) constexpr static int ConstexprField = 1;
+  template<typename U> __declspec(dllexport) constexpr static int ConstexprFieldDef = 1;
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> template<typename U>        void ExportClsTmplMemTmpl<T>::normalDef() {}
@@ -716,6 +855,12 @@ template<typename T> template<typename U
 template<typename T> template<typename U> inline void ExportClsTmplMemTmpl<T>::staticInlineDef() {}
 template<typename T> template<typename U>        void ExportClsTmplMemTmpl<T>::staticInlineDecl() {}
 
+#if __has_feature(cxx_variable_templates)
+template<typename T> template<typename U>        int  ExportClsTmplMemTmpl<T>::StaticFieldDef;
+template<typename T> template<typename U> const  int  ExportClsTmplMemTmpl<T>::StaticConstFieldDef = 1;
+template<typename T> template<typename U> constexpr int ExportClsTmplMemTmpl<T>::ConstexprFieldDef;
+#endif // __has_feature(cxx_variable_templates)
+
 
 // Redeclarations cannot add dllexport.
 template<typename T>
@@ -726,6 +871,12 @@ struct CTMTR /*ClassTmplMemberTmplRedecl
   template<typename U> static        void staticDef();         // expected-note{{previous declaration is here}}
   template<typename U> static        void staticInlineDef();   // expected-note{{previous declaration is here}}
   template<typename U> static inline void staticInlineDecl();  // expected-note{{previous declaration is here}}
+
+#if __has_feature(cxx_variable_templates)
+  template<typename U> static        int  StaticField;         // expected-note{{previous declaration is here}}
+  template<typename U> static const  int  StaticConstField;    // expected-note{{previous declaration is here}}
+  template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}}
@@ -734,3 +885,9 @@ template<typename T> template<typename U
 template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}}
 template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}}
 template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}}
+
+#if __has_feature(cxx_variable_templates)
+template<typename T> template<typename U> __declspec(dllexport)        int  CTMTR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) const  int  CTMTR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}}
+#endif // __has_feature(cxx_variable_templates)

Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=209825&r1=209824&r2=209825&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Thu May 29 11:50:20 2014
@@ -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::virtualInline
 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 Import
 __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 Member
 __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 at -1{{definition of dllimport static field not allowed}}
+                                                                       // expected-note at -2{{attribute is here}}
+__declspec(dllimport) const  int  MemberRedecl::StaticConstField = 1;  // expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 'dllimport' attribute}}
+                                                                       // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                       // expected-note at -2{{attribute is here}}
+__declspec(dllimport) constexpr int MemberRedecl::ConstexprField;      // expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllimport' attribute}}
+                                                                       // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                       // expected-note at -2{{attribute is here}}
+
 
 
 //===----------------------------------------------------------------------===//
@@ -525,6 +562,17 @@ struct ImportMemberTmpl {
   template<typename T> __declspec(dllimport) static        void staticInclass() {}
   template<typename T> __declspec(dllimport) static        void staticInlineDef();
   template<typename T> __declspec(dllimport) static inline void staticInlineDecl();
+
+#if __has_feature(cxx_variable_templates)
+  template<typename T> __declspec(dllimport) static        int  StaticField;
+  template<typename T> __declspec(dllimport) static        int  StaticFieldDef; // expected-note{{attribute is here}}
+  template<typename T> __declspec(dllimport) static const  int  StaticConstField;
+  template<typename T> __declspec(dllimport) static const  int  StaticConstFieldDef; // expected-note{{attribute is here}}
+  template<typename T> __declspec(dllimport) static const  int  StaticConstFieldEqualInit = 1;
+  template<typename T> __declspec(dllimport) static const  int  StaticConstFieldBraceInit{1};
+  template<typename T> __declspec(dllimport) constexpr static int ConstexprField = 1;
+  template<typename T> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T>        void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
@@ -534,6 +582,12 @@ template<typename T>        void ImportM
 template<typename T> inline void ImportMemberTmpl::staticInlineDef() {}
 template<typename T>        void ImportMemberTmpl::staticInlineDecl() {}
 
+#if __has_feature(cxx_variable_templates)
+template<typename T>        int  ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}}
+template<typename T> const  int  ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}}
+template<typename T> 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<typename T> static        void staticDef();         // expected-note{{previous declaration is here}}
   template<typename T> static        void staticInlineDef();   // expected-note{{previous declaration is here}}
   template<typename T> static inline void staticInlineDecl();  // expected-note{{previous declaration is here}}
+
+#if __has_feature(cxx_variable_templates)
+  template<typename T> static        int  StaticField;         // expected-note{{previous declaration is here}}
+  template<typename T> static const  int  StaticConstField;    // expected-note{{previous declaration is here}}
+  template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> __declspec(dllimport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}}
@@ -554,6 +614,18 @@ template<typename T> __declspec(dllimpor
 template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}}
 template<typename T> __declspec(dllimport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}}
 
+#if __has_feature(cxx_variable_templates)
+template<typename T> __declspec(dllimport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}}
+                                                                                            // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                                            // expected-note at -2{{attribute is here}}
+template<typename T> __declspec(dllimport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}}
+                                                                                            // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                                            // expected-note at -2{{attribute is here}}
+template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField;     // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}}
+                                                                                            // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                                            // expected-note at -2{{attribute is here}}
+#endif // __has_feature(cxx_variable_templates)
+
 
 
 struct MemFunTmpl {
@@ -628,6 +700,52 @@ template<> __declspec(dllimport) inline
 
 
 
+#if __has_feature(cxx_variable_templates)
+struct MemVarTmpl {
+  template<typename T>                       static const int StaticVar = 1;
+  template<typename T> __declspec(dllimport) static const int ImportedStaticVar = 1;
+};
+
+// Import implicit instantiation of an imported member variable template.
+int useMemVarTmpl() { return MemVarTmpl::ImportedStaticVar<ImplicitInst_Imported>; }
+
+// Import explicit instantiation declaration of an imported member variable
+// template.
+extern template const int MemVarTmpl::ImportedStaticVar<ExplicitDecl_Imported>;
+
+// 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<ExplicitSpec_Imported>;
+template<> __declspec(dllimport) const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_Def_Imported> = 1;
+                                                                                // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                                // expected-note at -2{{attribute is here}}
+
+// Not importing specialization of a member variable template without explicit
+// dllimport.
+template<> const int MemVarTmpl::ImportedStaticVar<ExplicitSpec_NotImported>;
+
+
+// Import explicit instantiation declaration of a non-imported member variable
+// template.
+extern template __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitDecl_Imported>;
+
+// 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<ExplicitSpec_Imported>;
+template<> __declspec(dllimport) const int MemVarTmpl::StaticVar<ExplicitSpec_Def_Imported> = 1;
+                                                                                // expected-error at -1{{definition of dllimport static field not allowed}}
+                                                                                // expected-note at -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<typename T>        void ImportC
 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}}
+
 
 // Redeclarations cannot add dllimport.
 template<typename T>
@@ -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<typename T> __declspec(dllimport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}}
@@ -697,6 +834,16 @@ template<typename T> __declspec(dllimpor
 template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}}
 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 at -1{{definition of dllimport static field not allowed}}
+                                                                                       // expected-note at -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 at -1{{definition of dllimport static field not allowed}}
+                                                                                       // expected-note at -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 at -1{{definition of dllimport static field not allowed}}
+                                                                                       // expected-note at -2{{attribute is here}}
+
 
 
 //===----------------------------------------------------------------------===//
@@ -715,6 +862,17 @@ struct ImportClsTmplMemTmpl {
   template<typename U> __declspec(dllimport) static        void staticInclass() {}
   template<typename U> __declspec(dllimport) static        void staticInlineDef();
   template<typename U> __declspec(dllimport) static inline void staticInlineDecl();
+
+#if __has_feature(cxx_variable_templates)
+  template<typename U> __declspec(dllimport) static        int  StaticField;
+  template<typename U> __declspec(dllimport) static        int  StaticFieldDef; // expected-note{{attribute is here}}
+  template<typename U> __declspec(dllimport) static const  int  StaticConstField;
+  template<typename U> __declspec(dllimport) static const  int  StaticConstFieldDef; // expected-note{{attribute is here}}
+  template<typename U> __declspec(dllimport) static const  int  StaticConstFieldEqualInit = 1;
+  template<typename U> __declspec(dllimport) static const  int  StaticConstFieldBraceInit{1};
+  template<typename U> __declspec(dllimport) constexpr static int ConstexprField = 1;
+  template<typename U> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
@@ -724,6 +882,12 @@ template<typename T> template<typename U
 template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::staticInlineDef() {}
 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}}
+#endif // __has_feature(cxx_variable_templates)
+
 
 // Redeclarations cannot add dllimport.
 template<typename T>
@@ -734,6 +898,12 @@ struct CTMTR /*ClassTmplMemberTmplRedecl
   template<typename U> static        void staticDef();         // expected-note{{previous declaration is here}}
   template<typename U> static        void staticInlineDef();   // expected-note{{previous declaration is here}}
   template<typename U> static inline void staticInlineDecl();  // expected-note{{previous declaration is here}}
+
+#if __has_feature(cxx_variable_templates)
+  template<typename U> static        int  StaticField;         // expected-note{{previous declaration is here}}
+  template<typename U> static const  int  StaticConstField;    // expected-note{{previous declaration is here}}
+  template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
+#endif // __has_feature(cxx_variable_templates)
 };
 
 template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}}
@@ -744,3 +914,15 @@ template<typename T> template<typename U
                                                                                                              // expected-error at -1{{dllimport cannot be applied to non-inline function definition}}
 template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}}
 template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}}
+
+#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 at -1{{definition of dllimport static field not allowed}}
+                                                                                                             // expected-note at -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 at -1{{definition of dllimport static field not allowed}}
+                                                                                                             // expected-note at -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 at -1{{definition of dllimport static field not allowed}}
+                                                                                                             // expected-note at -2{{attribute is here}}
+#endif // __has_feature(cxx_variable_templates)





More information about the cfe-commits mailing list