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

Reply via email to