[clang] [clang][Diagnostic] Clarify error message for auto (PR #149781)
Emily Dror via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 2 10:24:59 PDT 2025
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 <emilydror01 at 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 <emilydror01 at 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();
+ };
+}
+
More information about the cfe-commits
mailing list