[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 closed https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From 2c8c5129a9df16c87d9a89ce3864b857c438978e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/8] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/cwg0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8328be5890dd..92e69ace3c635 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -887,6 +887,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index e149b1a0fb5ef..719bbc499a19b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 6c600bbc7c3f6..bff529d1339a7 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1418,7 +1418,7 @@ namespace cwg96 { // cwg96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index f42c812a860d0..2196bfb6eaac3 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T:
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/erichkeane approved this pull request. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || AaronBallman wrote: I think it's reasonable to handle in a follow-up, thanks! https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/AaronBallman approved this pull request. I think the changes are reasonable, but I'd like to wait a bit before landing to give @erichkeane a chance to review as templates code owner. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From 2c8c5129a9df16c87d9a89ce3864b857c438978e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/7] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/cwg0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8328be5890dd..92e69ace3c635 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -887,6 +887,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index e149b1a0fb5ef..719bbc499a19b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 6c600bbc7c3f6..bff529d1339a7 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1418,7 +1418,7 @@ namespace cwg96 { // cwg96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index f42c812a860d0..2196bfb6eaac3 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T:
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1404,7 +1404,11 @@ namespace cwg95 { // cwg95: 3.3 // expected-note@#cwg95-C-f {{implicitly declared private here}} } +<<< HEAD:clang/test/CXX/drs/cwg0xx.cpp namespace cwg96 { // cwg96: no +=== +namespace dr96 { // dr96: sup P1787 +>>> c639768eef90 (change error to pedenatic warn, regen DR html):clang/test/CXX/drs/dr0xx.cpp cor3ntin wrote: There are conflicts markers left here https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName=*/true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 cor3ntin wrote: ```suggestion // C++2c [tem.names]p6 ``` https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -251,6 +251,9 @@ Resolutions to C++ Defect Reports - P0522 implementation is enabled by default in all language versions, and provisional wording for CWG2398 is implemented. +- Require a template argument list after a template keyword. cor3ntin wrote: ```suggestion - Clang now requires a template argument list after a template keyword. ``` https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || evelez7 wrote: Yeah this case isn't covered here. The error fires before reaching this method. I can try to diagnose it for this patch if needed, or I can do a followup patch. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From 2c8c5129a9df16c87d9a89ce3864b857c438978e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/6] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/cwg0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8328be5890dd..92e69ace3c635 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -887,6 +887,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index e149b1a0fb5ef..719bbc499a19b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 6c600bbc7c3f6..bff529d1339a7 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1418,7 +1418,7 @@ namespace cwg96 { // cwg96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index f42c812a860d0..2196bfb6eaac3 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T:
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From 2c8c5129a9df16c87d9a89ce3864b857c438978e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/5] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/cwg0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8328be5890dd..92e69ace3c635 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -887,6 +887,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index e149b1a0fb5ef..719bbc499a19b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 6c600bbc7c3f6..bff529d1339a7 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1418,7 +1418,7 @@ namespace cwg96 { // cwg96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index f42c812a860d0..2196bfb6eaac3 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T:
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From 2c8c5129a9df16c87d9a89ce3864b857c438978e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/4] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/cwg0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8328be5890dd..92e69ace3c635 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -887,6 +887,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index e149b1a0fb5ef..719bbc499a19b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -3026,13 +3027,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 6c600bbc7c3f6..bff529d1339a7 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1418,7 +1418,7 @@ namespace cwg96 { // cwg96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index f42c812a860d0..2196bfb6eaac3 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'A::template n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T:
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); shafik wrote: ```suggestion /*AllowInjectedClassName=*/true); ``` nitpick https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || AaronBallman wrote: What about type templates: https://godbolt.org/z/1coGTT38P (hmm we may have a wider issue there, from looking at Clang's current behavior, so a FIXME would be reasonable too). https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/AaronBallman commented: Thank you for this! The changes should also come with a release note in clang/docs/ReleaseNotes.rst so users know about the change. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
evelez7 wrote: ping @Endilll https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
evelez7 wrote: ping https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/4] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/dr0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a30ab27566ec3e..159600f3e26dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fd262ff31e661a..b3a1a6f6cf80d0 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd65..127d45be5bda97 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index af121a8b75d512..37dbe0b212eb6a 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T::template n; } // expe
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/3] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/dr0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a30ab27566ec3e..159600f3e26dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fd262ff31e661a..b3a1a6f6cf80d0 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd65..127d45be5bda97 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index af121a8b75d512..37dbe0b212eb6a 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T::template n; } // expe
[clang] [clang] require template arg list after template kw (PR #80801)
evelez7 wrote: I was wondering why the Windows CI was failing but seems to be bugged according to Discourse. Newest commit changes the error to a pedantic warning that defaults to an error. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801 >From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH 1/2] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/dr0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a30ab27566ec3e..159600f3e26dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fd262ff31e661a..b3a1a6f6cf80d0 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd65..127d45be5bda97 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index af121a8b75d512..37dbe0b212eb6a 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}} template - int &f() { return T::template n; } // expe
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not opensdh wrote: Yes, P1787R6 deprecated that use case; you're supposed to just not use `template` there. This is consistent with the _recommendation_ in N1528, but of course we now reject the premise that `template` is _needed_ for a template template argument. The reasoning, if it helps, is that compilers already have to deal with ambiguity there: ```cpp template void f();// #1 template void f(int=0); // #2 template class> void f(void*=nullptr); // #3 template void g() { // in C++20, [temp.res]/6 and [temp.arg.template]/1 contradict each other here: f(); // could be #1 or #3 } template struct X { // OK per [temp.local]/1 void h() {f(T());} // could be #2 or #3 void i() {T::template R();} // could be anything } ``` Accordingly, [CWG1478](https://cplusplus.github.io/CWG/issues/1478.html)'s question was answered in the negative, and `template` (is to be) restricted to the case where it influences the interpretation of a `<`. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; evelez7 wrote: > This should be a pedantic warning (maybe defaulting to an error) Otherwise we > might break existing (non conforming) code I've done this by adding this as a warning to the Pedantic diagnostic group, but I've had to increment the number in `test/Misc/warning-flags.c:91`, and there's a rather stern warning about not adding to `-Wpedantic`. Would this be ok? https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/Endilll edited https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not Endilll wrote: @opensdh Thank you for the clarification. I guess I read [N1528](https://wg21.link/n1528) Would it be a correct statement to make that you deprecated the following case described in that paper? > Consequently, the recommendation of this paper is: If the template keyword is > followed by a name that does not have a template-argument-list, the name must > refer to a class template and be used in a context in which a class template > is valid, otherwise the program is ill-formed. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 edited https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not opensdh wrote: I'm not sure what direction of "superseded" you mean here, but (except for the separable alias-template bit) the comment is simply correct (since CWG96; before that any template would do). All that P1787R6 did here was correct the strange use of "name" to refer to (among other things) a *template-id* and deprecate the `T::template NestedTypeTemplate` case. https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? opensdh wrote: The alias template case was aligned with the class-template case as part of [CWG1710](https://cplusplus.github.io/CWG/issues/1710.html). https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? evelez7 wrote: The use of 'template' before an alias template is [deprecated](https://eel.is/c++draft/depr.template.template), along with before a class template. I wasn't sure how to interpret this for clang, they aren't errors yet? https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
@@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; cor3ntin wrote: This should be a pedantic warning (maybe defaulting to an error) Otherwise we might break existing (non conforming) code https://github.com/search?q=%2Fs%5C.template+%5Ba-zA_Z_%5D%2B%5B%28%5D%2F+language%3AC%2B%2B&type=code https://github.com/llvm/llvm-project/pull/80801 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] require template arg list after template kw (PR #80801)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Erick Velez (evelez7) Changes Require a template argument list after an identifier prefixed by the template keyword. Introduced by [CWG 96](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#96). Current wording of [temp.names] introduced in [P1787R6](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html). Fixes #53095 --- Full diff: https://github.com/llvm/llvm-project/pull/80801.diff 8 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+3) - (modified) clang/lib/Parse/ParseExprCXX.cpp (+17-6) - (modified) clang/test/CXX/drs/dr0xx.cpp (+1-1) - (modified) clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (+3-3) - (modified) clang/test/SemaCXX/template-specialization.cpp (+1-1) - (modified) clang/test/SemaTemplate/dependent-names.cpp (+3-3) - (modified) clang/test/SemaTemplate/template-id-expr.cpp (+18-18) - (modified) clang/test/SemaTemplate/template-id-printing.cpp (-13) ``diff diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a30ab27566ec3e..159600f3e26dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fd262ff31e661a..b3a1a6f6cf80d0 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd65..127d45be5bda97 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index af121a8b75d512..37dbe0b212eb6a 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} + int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a na
[clang] [clang] require template arg list after template kw (PR #80801)
https://github.com/evelez7 created https://github.com/llvm/llvm-project/pull/80801 Require a template argument list after an identifier prefixed by the template keyword. Introduced by [CWG 96](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#96). Current wording of [temp.names] introduced in [P1787R6](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html). Fixes #53095 >From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001 From: Erick Velez Date: Mon, 5 Feb 2024 21:26:07 -0800 Subject: [PATCH] [clang] require template arg list after template kw Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes #53095 --- .../clang/Basic/DiagnosticParseKinds.td | 3 ++ clang/lib/Parse/ParseExprCXX.cpp | 23 clang/test/CXX/drs/dr0xx.cpp | 2 +- .../cxx1y-variable-templates_in_class.cpp | 6 ++-- .../test/SemaCXX/template-specialization.cpp | 2 +- clang/test/SemaTemplate/dependent-names.cpp | 6 ++-- clang/test/SemaTemplate/template-id-expr.cpp | 36 +-- .../SemaTemplate/template-id-printing.cpp | 13 --- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index a30ab27566ec3e..159600f3e26dc0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error< "requires expression in requirement body; did " "you intend to place it in a nested requirement? (add another 'requires' " "before the expression)">; +def err_missing_template_arg_list_after_template_kw : Error< + "a template argument list is expected after a name prefixed by the template " + "keyword">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index fd262ff31e661a..b3a1a6f6cf80d0 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, SS, ObjectType, ObjectHadErrors, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, EnteringContext, Result, TemplateSpecified); -else if (TemplateSpecified && - Actions.ActOnTemplateName( - getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, - EnteringContext, Template, - /*AllowInjectedClassName*/ true) == TNK_Non_template) - return true; +if (TemplateSpecified) { + TemplateNameKind TNK = + Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result, +ObjectType, EnteringContext, Template, +/*AllowInjectedClassName*/ true); + if (TNK == TNK_Non_template) +return true; + + // C++ [template.names]p6 + // A name prefixed by the keyword template shall be followed by a template + // argument list or refer to a class template or an alias template. + if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name || + TNK == TNK_Var_template) && + !Tok.is(tok::less)) +Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw); +} return false; } diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp index 5959f0a0c8dd65..127d45be5bda97 100644 --- a/clang/test/CXX/drs/dr0xx.cpp +++ b/clang/test/CXX/drs/dr0xx.cpp @@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no // FIXME: This is ill-formed, because 'f' is not a template-id and does not // name a class template. // FIXME: What about alias templates? -int k2 = a.template f(1); +int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} A::template S s; B b; } diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index af121a8b75d512..37dbe0b212eb6a 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -384,16 +384,16 @@ namespace dependent_static_var_template { struct A { template static int n; // expected-note 2{{here}} }; - int &r = A::template n; // expected-error {{use of va