diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 69aea6c21ad393..5207cd5b41a325 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -580,6 +580,8 @@ Improvements to Clang's diagnostics - Clang no longer emits a "declared here" note for a builtin function that has no declaration in source. Fixes #GH93369. +- Clang now suggests a fix-it to correct ``template`` in a template-template parameter with a missing ``<`` to ``typename`` + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index a5130f56600e54..33030a0095c044 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -787,6 +787,20 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { assert(Tok.is(tok::kw_template) && "Expected 'template' keyword"); + if (Token Next = NextToken(); Next.isNot(tok::less)) { + // `template` may have been a typo for `typename`, given that the + // latter is more common. + + Diag(Next.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 TemplateParams; diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp index e7dddd1ea9278f..6810a1952504e3 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