diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4790,6 +4790,7 @@ def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; def err_template_member : Error<"member %0 declared as a template">; +def err_member_with_template_arguments : Error<"member %0 cannot have template arguments">; def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; def err_template_tag_noparams : Error< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3395,6 +3395,15 @@ return nullptr; } + if (isInstField && + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) { + Diag(D.getIdentifierLoc(), diag::err_member_with_template_arguments) + << II + << SourceRange(D.getName().TemplateId->LAngleLoc, + D.getName().TemplateId->RAngleLoc) + << D.getName().TemplateId->LAngleLoc; + } + if (SS.isSet() && !SS.isInvalid()) { // The user provided a superfluous scope specifier inside a class // definition: diff --git a/clang/test/SemaCXX/class.cpp b/clang/test/SemaCXX/class.cpp --- a/clang/test/SemaCXX/class.cpp +++ b/clang/test/SemaCXX/class.cpp @@ -208,6 +208,22 @@ } } -struct PR9989 { - static int const PR9989_Member = sizeof PR9989_Member; +struct PR9989 { + static int const PR9989_Member = sizeof PR9989_Member; }; + + +namespace GH54151 { + +struct S { + int i<0>; // expected-error {{member 'i' cannot have template arguments}} + int j; // expected-error {{member 'j' cannot have template arguments}} +}; + +template +struct U { + int i; // expected-error {{member 'i' cannot have template arguments}} + int j; // expected-error {{member 'j' cannot have template arguments}} +}; + +} // namespace GH54151