[clang] [clang][Parser] "Better" error messages for invalid template template (PR #95726)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 16 17:29:19 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (Veeloxfire)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/95726.diff
3 Files Affected:
- (modified) clang/lib/Parse/ParseTemplate.cpp (+17)
- (modified) clang/test/CXX/drs/cwg1xx.cpp (+2)
- (modified) clang/test/Parser/cxx-template-decl.cpp (+1-1)
``````````diff
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 at -1 +{{}}
+ // expected-note at -2 {{did you mean to use 'typename'?}}
template <template X<class T> > void f(A<X>) { }
// expected-error at -1 +{{}}
+ // expected-note at -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 at -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}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/95726
More information about the cfe-commits
mailing list