Author: rnk Date: Wed Sep 11 11:09:10 2019 New Revision: 371642 URL: http://llvm.org/viewvc/llvm-project?rev=371642&view=rev Log: [MS] Consder constexpr globals to be inline, as in C++17
Summary: Microsoft seems to do this regardless of the language mode, so we must also do it in order to be ABI compatible. Fixes PR36125 Reviewers: thakis Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47956 Added: cfe/trunk/test/CodeGenCXX/ms-constexpr-static-data-member.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp cfe/trunk/test/CXX/drs/dr7xx.cpp cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp cfe/trunk/test/SemaCXX/dllexport.cpp cfe/trunk/test/SemaCXX/dllimport.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Sep 11 11:09:10 2019 @@ -6846,7 +6846,9 @@ NamedDecl *Sema::ActOnVariableDeclarator // C++1z [dcl.spec.constexpr]p1: // A static data member declared with the constexpr specifier is // implicitly an inline variable. - if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17) + if (NewVD->isStaticDataMember() && + (getLangOpts().CPlusPlus17 || + Context.getTargetInfo().getCXXABI().isMicrosoft())) NewVD->setImplicitlyInline(); break; @@ -12003,7 +12005,8 @@ void Sema::ActOnUninitializedDecl(Decl * if (Var->isStaticDataMember()) { // C++1z removes the relevant rule; the in-class declaration is always // a definition there. - if (!getLangOpts().CPlusPlus17) { + if (!getLangOpts().CPlusPlus17 && + !Context.getTargetInfo().getCXXABI().isMicrosoft()) { Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init) << Var->getDeclName(); Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original) +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Wed Sep 11 11:09:10 2019 @@ -1,6 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -std=c++14 %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -std=c++1z %s + +// MSVC always adopted the C++17 rule that implies that constexpr variables are +// implicitly inline, so do the test again. +// RUN: %clang_cc1 -triple x86_64-windows-msvc -DMS_ABI -fsyntax-only -verify -std=c++11 %s struct notlit { // expected-note {{not literal because}} notlit() {} @@ -29,7 +33,7 @@ void f2(constexpr int i) {} // expected- struct s2 { constexpr int mi1; // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}} static constexpr int mi2; -#if __cplusplus <= 201402L +#if __cplusplus <= 201402L && !defined(MS_ABI) // expected-error@-2 {{requires an initializer}} #else // expected-error@-4 {{default initialization of an object of const}} Modified: cfe/trunk/test/CXX/drs/dr7xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr7xx.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr7xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr7xx.cpp Wed Sep 11 11:09:10 2019 @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors namespace dr705 { // dr705: yes namespace N { Added: cfe/trunk/test/CodeGenCXX/ms-constexpr-static-data-member.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-constexpr-static-data-member.cpp?rev=371642&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/ms-constexpr-static-data-member.cpp (added) +++ cfe/trunk/test/CodeGenCXX/ms-constexpr-static-data-member.cpp Wed Sep 11 11:09:10 2019 @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -emit-llvm -triple=x86_64-windows-msvc %s -o - | FileCheck %s + +struct Foo { int x, y; }; + +struct S { + // PR36125 + static constexpr char sdm_char_array[] = "asdf"; + + // PR43280 + static constexpr const char *sdm_char_ptr = "asdf"; + + static constexpr Foo sdm_udt{1, 2}; +}; + +void useptr(const void *p); +void usethem() { + useptr(&S::sdm_char_array); + useptr(&S::sdm_char_ptr); + useptr(&S::sdm_udt); +} + +// CHECK-DAG: @"?sdm_char_array@S@@2QBDB" = linkonce_odr dso_local constant [5 x i8] c"asdf\00", comdat, align 1 + +// CHECK-DAG: @"?sdm_char_ptr@S@@2QEBDEB" = linkonce_odr dso_local constant i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"??_C@_04JIHMPGLA@asdf?$AA@", i32 0, i32 0), comdat, align 8 + +// CHECK-DAG: @"?sdm_udt@S@@2UFoo@@B" = linkonce_odr dso_local constant %struct.Foo { i32 1, i32 2 }, comdat, align 4 Modified: cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp (original) +++ cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members-exported.cpp Wed Sep 11 11:09:10 2019 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-extensions %s -o - | FileCheck %s enum Enum { zero, one, two }; Modified: cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp (original) +++ cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp Wed Sep 11 11:09:10 2019 @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple=x86_64-windows-msvc %s -o - | FileCheck %s struct S { static const int NoInit_Ref; Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Wed Sep 11 11:09:10 2019 @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX11 -// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s -// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCPP1Y +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 -verify -fsyntax-only %s -Wno-c++11-extensions -Wno-c++1y-extensions -DPRECXX11 +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1y -verify -fsyntax-only %s -DCPP1Y #define CONST const Modified: cfe/trunk/test/SemaCXX/dllexport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/dllexport.cpp (original) +++ cfe/trunk/test/SemaCXX/dllexport.cpp Wed Sep 11 11:09:10 2019 @@ -742,7 +742,7 @@ struct MemberRedecl { 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}} + constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} }; __declspec(dllexport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllexport' attribute}} @@ -757,7 +757,12 @@ __declspec(dllexport) void Member __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}} +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllexport' attribute}} +#endif +__declspec(dllexport) constexpr int MemberRedecl::ConstexprField; #ifdef MS struct __declspec(dllexport) ClassWithMultipleDefaultCtors { @@ -841,7 +846,7 @@ struct MemTmplRedecl { #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}} + template<typename T> constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} #endif // __has_feature(cxx_variable_templates) }; @@ -855,7 +860,13 @@ template<typename T> __declspec(dllexpor #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}} + +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template<typename T> __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; #endif // __has_feature(cxx_variable_templates) @@ -1045,7 +1056,7 @@ struct CTMR /*ClassTmplMemberRedecl*/ { 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}} + constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(definition|declaration)}} is here}} }; template<typename T> __declspec(dllexport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} @@ -1060,7 +1071,12 @@ template<typename T> __declspec(dllexpor 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}} +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField; @@ -1120,7 +1136,7 @@ struct CTMTR /*ClassTmplMemberTmplRedecl #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}} + template<typename U> constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} #endif // __has_feature(cxx_variable_templates) }; @@ -1134,7 +1150,12 @@ template<typename T> template<typename U #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}} +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField; #endif // __has_feature(cxx_variable_templates) // FIXME: Precedence rules seem to be different for classes. Modified: cfe/trunk/test/SemaCXX/dllimport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=371642&r1=371641&r2=371642&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/dllimport.cpp (original) +++ cfe/trunk/test/SemaCXX/dllimport.cpp Wed Sep 11 11:09:10 2019 @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c++1y -Wunsupported-dll-base-class-template -DMS %s // RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c++1y -Wunsupported-dll-base-class-template -DGNU %s // RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template -DGNU %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c++17 -Wunsupported-dll-base-class-template -DGNU %s // Helper structs to make templates more expressive. struct ImplicitInst_Imported {}; @@ -586,7 +587,10 @@ public: __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}} +#if __cplusplus < 201703L && !defined(MS) + // expected-note@+2{{attribute is here}} +#endif + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; }; #ifdef MS @@ -631,7 +635,10 @@ inline void ImportMembers::staticInlineD 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}} +#if __cplusplus < 201703L && !defined(MS) +// expected-error@+2{{definition of dllimport static field not allowed}} +#endif +constexpr int ImportMembers::ConstexprFieldDef; // Import on member definitions. @@ -667,7 +674,11 @@ __declspec(dllimport) void Import __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}} +#if __cplusplus < 201703L && !defined(MS) +// expected-error@+3{{definition of dllimport static field not allowed}} +// expected-note@+2{{attribute is here}} +#endif +__declspec(dllimport) constexpr int ImportMemberDefs::ConstexprField; // Import special member functions. @@ -800,7 +811,7 @@ struct MemberRedecl { 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}} + constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} }; __declspec(dllimport) void MemberRedecl::normalDef() {} // expected-error{{redeclaration of 'MemberRedecl::normalDef' cannot add 'dllimport' attribute}} @@ -831,9 +842,15 @@ __declspec(dllimport) int Member __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}} + +#if __cplusplus < 201703L && !defined(MS) +// expected-error@+6{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 'dllimport' attribute}} +// expected-error@+5{{definition of dllimport static field not allowed}} +// expected-note@+4{{attribute is here}} +#else +// expected-warning@+2{{attribute declaration must precede definition}} +#endif +__declspec(dllimport) constexpr int MemberRedecl::ConstexprField; @@ -875,7 +892,7 @@ struct ImportMemberTmpl { 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}} + template<typename T> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; #endif // __has_feature(cxx_variable_templates) }; @@ -900,7 +917,9 @@ template<typename T> inline void ImportM #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}} +#ifdef MS +template<typename T> constexpr int ImportMemberTmpl::ConstexprFieldDef; +#endif #endif // __has_feature(cxx_variable_templates) @@ -921,7 +940,9 @@ struct MemTmplRedecl { #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}} +#ifdef MS + template<typename T> constexpr static int ConstexprField = 1; // expected-note{{previous definition is here}} +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -949,9 +970,10 @@ template<typename T> __declspec(dllimpor template<typename T> __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<typename T> __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}} +#ifdef MS +// expected-warning@+1{{attribute declaration must precede definition}} +template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; +#endif #endif // __has_feature(cxx_variable_templates) @@ -1159,7 +1181,10 @@ public: __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}} +#if __cplusplus < 201703L && !defined(MS) + // expected-note@+2{{attribute is here}} +#endif + __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; }; // NB: MSVC is inconsistent here and disallows *InlineDef on class templates, @@ -1203,7 +1228,10 @@ template<typename T> void ImportC 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}} +#if __cplusplus < 201703L && !defined(MS) +// expected-warning@+2{{definition of dllimport static field}} +#endif +template<typename T> constexpr int ImportClassTmplMembers<T>::ConstexprFieldDef; // Redeclarations cannot add dllimport. @@ -1227,7 +1255,7 @@ struct CTMR /*ClassTmplMemberRedecl*/ { 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}} + constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} }; template<typename T> __declspec(dllimport) void CTMR<T>::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} @@ -1256,9 +1284,15 @@ template<typename T> __declspec(dllimpor template<typename T> __declspec(dllimport) const int CTMR<T>::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}} // 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-warning@-1{{definition of dllimport static field}} - // expected-note@-2{{attribute is here}} + +#if __cplusplus < 201703L && !defined(MS) +// expected-error@+6{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}} +// expected-warning@+5{{definition of dllimport static field}} +// expected-note@+4{{attribute is here}} +#else +// expected-warning@+2{{attribute declaration must precede definition}} +#endif +template<typename T> __declspec(dllimport) constexpr int CTMR<T>::ConstexprField; @@ -1306,7 +1340,9 @@ struct ImportClsTmplMemTmpl { 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}} +#ifdef MS + template<typename U> __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -1331,7 +1367,9 @@ template<typename T> template<typename U #if __has_feature(cxx_variable_templates) 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}} +#ifdef MS +template<typename T> template<typename U> constexpr int ImportClsTmplMemTmpl<T>::ConstexprFieldDef; +#endif #endif // __has_feature(cxx_variable_templates) @@ -1353,7 +1391,9 @@ struct CTMTR /*ClassTmplMemberTmplRedecl #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}} +#ifdef MS + template<typename U> constexpr static int ConstexprField = 1; // expected-note{{previous definition is here}} +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -1379,9 +1419,10 @@ template<typename T> template<typename U 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-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-warning@-1{{definition of dllimport static field}} - // expected-note@-2{{attribute is here}} +#ifdef MS +// expected-warning@+1{{attribute declaration must precede definition}} +template<typename T> template<typename U> __declspec(dllimport) constexpr int CTMTR<T>::ConstexprField; +#endif #endif // __has_feature(cxx_variable_templates) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits