https://github.com/Veeloxfire created 
https://github.com/llvm/llvm-project/pull/95726

For the somewhat easy mistake of `template<template A> ...` clang outputs a 
partially cryptic error

This patch changes this to assume the programmer intended `typename` in cases 
where `template` is illegal, and emit diagnostics (and forward parsing) 
accordingly

This mirrors the behaviour of `typedef` handling, so I feel its a reasonable 
qol change

Apologies if I missed any broken tests. Currently my local setup is messed up 
and fails on 100-200 tests eroniously, so I did my best to search through the 
errors and find the ones that needed updating

>From 44620330cd5238de549d3d77ddc447cd3bc51e60 Mon Sep 17 00:00:00 2001
From: Veeloxfire <58116051+veeloxf...@users.noreply.github.com>
Date: Mon, 17 Jun 2024 01:20:32 +0100
Subject: [PATCH] [clang][Parser] "Better" error messages for invalid template
 template

For the somewhat easy mistake of `template<template A> ...` clang outputs a 
partially cryptic error
Change this to assume the programmer intended `typename` in cases where 
`template` is illegal, and emit diagnostics (and forward parsing) accordingly
This mirrors the behaviour of `typedef` handling
---
 clang/lib/Parse/ParseTemplate.cpp       | 17 +++++++++++++++++
 clang/test/CXX/drs/cwg1xx.cpp           |  2 ++
 clang/test/Parser/cxx-template-decl.cpp |  2 +-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Parse/ParseTemplate.cpp 
b/clang/lib/Parse/ParseTemplate.cpp
index a5130f56600e5..e5308d9edac5f 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -787,6 +787,23 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned 
Depth,
                                                   unsigned Position) {
   assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
 
+  if (Token ahead = GetLookAheadToken(1);
+      ahead.isOneOf(tok::identifier, tok::ellipsis,
+                    tok::equal, tok::comma,
+                    tok::greater, tok::greatergreater, 
tok::greatergreatergreater)) {
+    // Maybe they intended `typename` instead of `template` (given thats more 
common)
+    // Error early, to add a fixit hint
+
+    Diag(ahead.getLocation(), diag::err_expected_less_after) << "template";
+    
+    Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
+      << 
FixItHint::CreateReplacement(CharSourceRange::getTokenRange(Tok.getLocation()),
+                                      "typename");
+
+    Tok.setKind(tok::kw_typename);
+    return ParseTypeParameter(Depth, Position);
+  }
+
   // Handle the template <...> part.
   SourceLocation TemplateLoc = ConsumeToken();
   SmallVector<NamedDecl*,8> TemplateParams;
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index e7dddd1ea9278..72b3ff40152d5 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -1145,8 +1145,10 @@ namespace cwg181 { // cwg181: yes
   namespace X {
     template <template X<class T> > struct A { };
     // expected-error@-1 +{{}}
+    //  expected-note@-2 {{did you mean to use 'typename'?}}
     template <template X<class T> > void f(A<X>) { }
     // expected-error@-1 +{{}}
+    //  expected-note@-2 {{did you mean to use 'typename'?}}
   }
 
   namespace Y {
diff --git a/clang/test/Parser/cxx-template-decl.cpp 
b/clang/test/Parser/cxx-template-decl.cpp
index 734438069b9ae..69b9ab012b478 100644
--- a/clang/test/Parser/cxx-template-decl.cpp
+++ b/clang/test/Parser/cxx-template-decl.cpp
@@ -22,7 +22,7 @@ template<template<int+>> struct x3; // expected-error 
{{expected ',' or '>' in t
                                          cpp14-error {{template template 
parameter requires 'class' after the parameter list}} \
                                          cpp17-error {{template template 
parameter requires 'class' or 'typename' after the parameter list}}
 template <template X> struct Err1; // expected-error {{expected '<' after 
'template'}} \
-// expected-error{{extraneous}}
+// expected-note{{did you mean to use 'typename'?}}
 template <template <typename> > struct Err2;       // cpp14-error {{template 
template parameter requires 'class' after the parameter list}}
 // cpp17-error@-1{{template template parameter requires 'class' or 'typename' 
after the parameter list}}
 template <template <typename> Foo> struct Err3;    // cpp14-error {{template 
template parameter requires 'class' after the parameter list}}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to