https://github.com/emily-dror updated https://github.com/llvm/llvm-project/pull/149781
>From 90ae570afa7b323be99fd36fd833902f5de9918e Mon Sep 17 00:00:00 2001 From: Emily Dror <emilydro...@gmail.com> Date: Mon, 21 Jul 2025 12:00:08 +0300 Subject: [PATCH 1/2] [clang][Diagnostic] Clarify error message for auto Show line and file for auto template error in -std=c++20 or -std=c++23 --- clang/lib/Sema/SemaTemplate.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b76619fc50268..4505d5f7f2226 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8238,12 +8238,24 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) { // C++ [temp.mem]p2: // A local class shall not have member templates. - if (RD->isLocalClass()) - return Diag(TemplateParams->getTemplateLoc(), - diag::err_template_inside_local_class) - << TemplateParams->getSourceRange(); - else - return false; + if (RD->isLocalClass()) { + SourceLocation DiagLoc = TemplateParams->getTemplateLoc(); + if (DiagLoc.isInvalid()) { + for (const NamedDecl *Param : *TemplateParams) { + if (Param && Param->getLocation().isValid()) { + DiagLoc = Param->getLocation(); + break; + } + } + } + if (DiagLoc.isInvalid()) { + // Still no good location? Fall back to the class declaration itself + DiagLoc = RD->getLocation(); + } + return Diag(DiagLoc, diag::err_template_inside_local_class) + << TemplateParams->getSourceRange(); + } + return false; } } >From 76dc7f2aaaa05208eb7a11ee4b5e783ff59ec41b Mon Sep 17 00:00:00 2001 From: Emily Dror <emilydro...@gmail.com> Date: Mon, 21 Jul 2025 12:00:08 +0300 Subject: [PATCH 2/2] [clang][Diagnostic] Clarify error message for auto Show line and file for auto template error in -std=c++20 or -std=c++23 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaTemplate.cpp | 33 +++++++++++---------- clang/test/SemaCXX/template-local-class.cpp | 9 ++++++ 3 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 clang/test/SemaCXX/template-local-class.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 46a77673919d3..fb6f85ab51aa5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -717,6 +717,8 @@ Improvements to Clang's diagnostics Added a new warning in this group for the case where the attribute is missing/implicit on an override of a virtual method. +- Improved diagnostic location for templates declared inside local classes. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b39a23f3039e1..cf893156f39d9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8231,6 +8231,19 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // C++ [temp.class.spec]p6: [P2096] // A partial specialization may be declared in any scope in which the // corresponding primary template may be defined. + auto FindTemplateParamsLoc = [](TemplateParameterList *TemplateParams, + SourceLocation Fallback) { + SourceLocation DiagLoc = TemplateParams->getTemplateLoc(); + if (DiagLoc.isValid()) + return DiagLoc; + + for (const NamedDecl *Param : *TemplateParams) + if (Param && Param->getLocation().isValid()) + return Param->getLocation(); + + return Fallback; + }; + if (Ctx) { if (Ctx->isFileContext()) return false; @@ -8238,29 +8251,17 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // C++ [temp.mem]p2: // A local class shall not have member templates. if (RD->isLocalClass()) { - SourceLocation DiagLoc = TemplateParams->getTemplateLoc(); - if (DiagLoc.isInvalid()) { - for (const NamedDecl *Param : *TemplateParams) { - if (Param && Param->getLocation().isValid()) { - DiagLoc = Param->getLocation(); - break; - } - } - } - if (DiagLoc.isInvalid()) { - // Still no good location? Fall back to the class declaration itself - DiagLoc = RD->getLocation(); - } - return Diag(DiagLoc, diag::err_template_inside_local_class) + return Diag(FindTemplateParamsLoc(TemplateParams, RD->getLocation()), + diag::err_template_inside_local_class) << TemplateParams->getSourceRange(); } return false; } } - return Diag(TemplateParams->getTemplateLoc(), + return Diag(FindTemplateParamsLoc(TemplateParams, SourceLocation()), diag::err_template_outside_namespace_or_class_scope) - << TemplateParams->getSourceRange(); + << TemplateParams->getSourceRange(); } /// Determine what kind of template specialization the given declaration diff --git a/clang/test/SemaCXX/template-local-class.cpp b/clang/test/SemaCXX/template-local-class.cpp new file mode 100644 index 0000000000000..10f819f4d0ea0 --- /dev/null +++ b/clang/test/SemaCXX/template-local-class.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void foo() { + struct Local { + template <typename T> // expected-error {{member templates are not allowed inside local classes}} + void bar(); + }; +} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits