Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6592,7 +6592,9 @@ // 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(); } } @@ -11080,7 +11082,8 @@ 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(); Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp =================================================================== --- clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -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 @@ 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}} Index: clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp =================================================================== --- clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -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 Index: clang/test/SemaCXX/dllexport.cpp =================================================================== --- clang/test/SemaCXX/dllexport.cpp +++ clang/test/SemaCXX/dllexport.cpp @@ -719,7 +719,7 @@ 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}} @@ -734,7 +734,12 @@ __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 { @@ -818,7 +823,7 @@ #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} - template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} #endif // __has_feature(cxx_variable_templates) }; @@ -832,7 +837,13 @@ #if __has_feature(cxx_variable_templates) template __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} template __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} + +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; #endif // __has_feature(cxx_variable_templates) @@ -1022,7 +1033,7 @@ 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 __declspec(dllexport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} @@ -1037,7 +1048,12 @@ template __declspec(dllexport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} template __declspec(dllexport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template __declspec(dllexport) constexpr int CTMR::ConstexprField; @@ -1097,7 +1113,7 @@ #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} - template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} + template constexpr static int ConstexprField = 1; // expected-note-re{{previous {{(declaration|definition)}} is here}} #endif // __has_feature(cxx_variable_templates) }; @@ -1111,7 +1127,12 @@ #if __has_feature(cxx_variable_templates) template template __declspec(dllexport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} template template __declspec(dllexport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +#ifdef MS +// expected-warning@+4{{attribute declaration must precede definition}} +#else +// expected-error@+2{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +#endif +template template __declspec(dllexport) constexpr int CTMTR::ConstexprField; #endif // __has_feature(cxx_variable_templates) // FIXME: Precedence rules seem to be different for classes. Index: clang/test/SemaCXX/dllimport.cpp =================================================================== --- clang/test/SemaCXX/dllimport.cpp +++ clang/test/SemaCXX/dllimport.cpp @@ -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 {}; @@ -582,7 +583,10 @@ __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 @@ -627,7 +631,10 @@ 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. @@ -663,7 +670,11 @@ __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. @@ -796,7 +807,7 @@ 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}} @@ -827,9 +838,15 @@ __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; @@ -871,7 +888,7 @@ template __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; template __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; template __declspec(dllimport) constexpr static int ConstexprField = 1; - template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} + template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; #endif // __has_feature(cxx_variable_templates) }; @@ -896,7 +913,9 @@ #if __has_feature(cxx_variable_templates) template int ImportMemberTmpl::StaticFieldDef; // expected-error{{definition of dllimport static field not allowed}} template const int ImportMemberTmpl::StaticConstFieldDef = 1; // expected-error{{definition of dllimport static field not allowed}} -template constexpr int ImportMemberTmpl::ConstexprFieldDef; // expected-error{{definition of dllimport static field not allowed}} +#ifdef MS +template constexpr int ImportMemberTmpl::ConstexprFieldDef; +#endif #endif // __has_feature(cxx_variable_templates) @@ -917,7 +936,9 @@ #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} - template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#ifdef MS + template constexpr static int ConstexprField = 1; // expected-note{{previous definition is here}} +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -945,9 +966,10 @@ template __declspec(dllimport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}} // expected-error@-1{{definition of dllimport static field not allowed}} // expected-note@-2{{attribute is here}} -template __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}} - // expected-error@-1{{definition of dllimport static field not allowed}} - // expected-note@-2{{attribute is here}} +#ifdef MS +// expected-warning@+1{{attribute declaration must precede definition}} +template __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; +#endif #endif // __has_feature(cxx_variable_templates) @@ -1155,7 +1177,10 @@ __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, @@ -1199,7 +1224,10 @@ 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}} +#if __cplusplus < 201703L && !defined(MS) +// expected-warning@+2{{definition of dllimport static field}} +#endif +template constexpr int ImportClassTmplMembers::ConstexprFieldDef; // Redeclarations cannot add dllimport. @@ -1223,7 +1251,7 @@ 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 __declspec(dllimport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} @@ -1252,9 +1280,15 @@ template __declspec(dllimport) const int CTMR::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 __declspec(dllimport) constexpr int CTMR::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 __declspec(dllimport) constexpr int CTMR::ConstexprField; @@ -1302,7 +1336,9 @@ template __declspec(dllimport) static const int StaticConstFieldEqualInit = 1; template __declspec(dllimport) static const int StaticConstFieldBraceInit{1}; template __declspec(dllimport) constexpr static int ConstexprField = 1; - template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; // expected-note{{attribute is here}} +#ifdef MS + template __declspec(dllimport) constexpr static int ConstexprFieldDef = 1; +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -1327,7 +1363,9 @@ #if __has_feature(cxx_variable_templates) 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}} +#ifdef MS +template template constexpr int ImportClsTmplMemTmpl::ConstexprFieldDef; +#endif #endif // __has_feature(cxx_variable_templates) @@ -1349,7 +1387,9 @@ #if __has_feature(cxx_variable_templates) template static int StaticField; // expected-note{{previous declaration is here}} template static const int StaticConstField; // expected-note{{previous declaration is here}} - template constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} +#ifdef MS + template constexpr static int ConstexprField = 1; // expected-note{{previous definition is here}} +#endif #endif // __has_feature(cxx_variable_templates) }; @@ -1375,9 +1415,10 @@ template template __declspec(dllimport) const int CTMTR::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 template __declspec(dllimport) constexpr int CTMTR::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 template __declspec(dllimport) constexpr int CTMTR::ConstexprField; +#endif #endif // __has_feature(cxx_variable_templates)