[clang] [clang] require template arg list after template kw (PR #80801)

2024-05-31 Thread Erick Velez via cfe-commits

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)

2024-05-31 Thread Erick Velez via cfe-commits

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)

2024-05-31 Thread Erich Keane via cfe-commits

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)

2024-05-31 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-31 Thread Aaron Ballman via cfe-commits

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)

2024-05-31 Thread Aaron Ballman via cfe-commits

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)

2024-05-30 Thread Erick Velez via cfe-commits

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)

2024-05-30 Thread via cfe-commits


@@ -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)

2024-05-30 Thread via cfe-commits


@@ -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)

2024-05-30 Thread via cfe-commits


@@ -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)

2024-05-30 Thread Erick Velez via cfe-commits


@@ -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)

2024-05-30 Thread Erick Velez via cfe-commits

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)

2024-05-30 Thread Erick Velez via cfe-commits

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)

2024-05-30 Thread Erick Velez via cfe-commits

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)

2024-05-28 Thread Shafik Yaghmour via cfe-commits


@@ -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)

2024-05-28 Thread Aaron Ballman via cfe-commits


@@ -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)

2024-05-28 Thread Aaron Ballman via cfe-commits

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)

2024-05-28 Thread Aaron Ballman via cfe-commits

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)

2024-05-23 Thread Erick Velez via cfe-commits

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)

2024-03-26 Thread Erick Velez via cfe-commits

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)

2024-02-08 Thread Erick Velez via cfe-commits

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)

2024-02-07 Thread Erick Velez via cfe-commits

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)

2024-02-07 Thread Erick Velez via cfe-commits

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)

2024-02-07 Thread Erick Velez via cfe-commits

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)

2024-02-06 Thread Davis Herring via cfe-commits


@@ -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)

2024-02-06 Thread Erick Velez via cfe-commits


@@ -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)

2024-02-06 Thread Vlad Serebrennikov via cfe-commits

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)

2024-02-06 Thread Vlad Serebrennikov via cfe-commits


@@ -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)

2024-02-06 Thread Erick Velez via cfe-commits

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)

2024-02-06 Thread Davis Herring via cfe-commits


@@ -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)

2024-02-06 Thread Davis Herring via cfe-commits


@@ -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)

2024-02-06 Thread Erick Velez via cfe-commits


@@ -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)

2024-02-06 Thread via cfe-commits


@@ -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)

2024-02-05 Thread via cfe-commits

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)

2024-02-05 Thread Erick Velez via cfe-commits

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