https://github.com/Sandeep2265 created 
https://github.com/llvm/llvm-project/pull/167228

edited in the file SemaTemplate.cpp and also added few testcases.

>From 78ac1692ec6e6acbbe4a5a4549f1a0ac8a6c1b0d Mon Sep 17 00:00:00 2001
From: Sandeep Krapa <[email protected]>
Date: Sun, 9 Nov 2025 21:13:31 +0530
Subject: [PATCH] Worked on the issue #147324 and solved it edited in the file
 SemaTemplate.cpp and also added few testcase.

---
 clang/lib/Sema/SemaTemplate.cpp               | 54 ++++++++++++-------
 clang/test/SemaCXX/lambda-local-c++17.cpp     | 11 ++++
 clang/test/SemaCXX/lambda-local-c++20.cpp     | 11 ++++
 clang/test/SemaCXX/nested-local.cpp           |  9 ++++
 clang/test/SemaCXX/static-local.cpp           |  8 +++
 .../SemaCXX/template-member-local-c++17.cpp   | 16 ++++++
 .../SemaCXX/template-member-local-c++20.cpp   | 16 ++++++
 7 files changed, 106 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/SemaCXX/lambda-local-c++17.cpp
 create mode 100644 clang/test/SemaCXX/lambda-local-c++20.cpp
 create mode 100644 clang/test/SemaCXX/nested-local.cpp
 create mode 100644 clang/test/SemaCXX/static-local.cpp
 create mode 100644 clang/test/SemaCXX/template-member-local-c++17.cpp
 create mode 100644 clang/test/SemaCXX/template-member-local-c++20.cpp

diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4a9e1bc93b918..ba91b25fc1843 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -8421,7 +8421,7 @@ bool Sema::TemplateParameterListsAreEqual(
   return true;
 }
 
-bool
+bool 
 Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
   if (!S)
     return false;
@@ -8445,33 +8445,49 @@ Sema::CheckTemplateDeclScope(Scope *S, 
TemplateParameterList *TemplateParams) {
   }
   Ctx = Ctx ? Ctx->getRedeclContext() : nullptr;
 
-  // C++ [temp]p2:
-  //   A template-declaration can appear only as a namespace scope or
-  //   class scope declaration.
-  // C++ [temp.expl.spec]p3:
-  //   An explicit specialization may be declared in any scope in which the
-  //   corresponding primary template may be defined.
-  // C++ [temp.class.spec]p6: [P2096]
-  //   A partial specialization may be declared in any scope in which the
-  //   corresponding primary template may be defined.
+  // Compute a SourceLocation to use for diagnostics. Prefer the explicit
+  // template location, but fall back to nearby Decl locations when needed.
+  SourceLocation Loc = TemplateParams->getTemplateLoc();
+  if (Loc.isInvalid())
+    Loc = TemplateParams->getSourceRange().getBegin();
+
+  if (Loc.isInvalid() && Ctx) {
+    if (const Decl *D = dyn_cast<Decl>(Ctx))
+      Loc = D->getBeginLoc();
+  }
+
+  // Try to extract class context if present.
+  CXXRecordDecl *RD = Ctx ? dyn_cast<CXXRecordDecl>(Ctx) : nullptr;
+  if (Loc.isInvalid() && RD)
+    Loc = RD->getLocation();
+
   if (Ctx) {
     if (Ctx->isFileContext())
       return false;
-    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) {
+
+    if (RD) {
       // 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
+      if (RD->isLocalClass()) {
+        // when the template location is not valid we are trying to use 
fallback SourceLocation such that diagnostic prints a usable file:line:col 
location
+        if (Loc.isInvalid())
+          Loc = TemplateParams->getSourceRange().getBegin();
+
+        return Diag(Loc, diag::err_template_inside_local_class)
+                 << TemplateParams->getSourceRange();
+      } 
+      else {
         return false;
+      }
     }
   }
 
-  return Diag(TemplateParams->getTemplateLoc(),
-              diag::err_template_outside_namespace_or_class_scope)
-    << TemplateParams->getSourceRange();
+  // when teplate declared outside the namspace or class scope it Fallbacks 
and it give valid SourceLocation with file:line info.
+  if (Loc.isInvalid())
+    Loc = TemplateParams->getSourceRange().getBegin();
+
+  return Diag(Loc, diag::err_template_outside_namespace_or_class_scope)
+           << TemplateParams->getSourceRange();
 }
 
 /// Determine what kind of template specialization the given declaration
diff --git a/clang/test/SemaCXX/lambda-local-c++17.cpp 
b/clang/test/SemaCXX/lambda-local-c++17.cpp
new file mode 100644
index 0000000000000..0d23849fa5cab
--- /dev/null
+++ b/clang/test/SemaCXX/lambda-local-c++17.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int main() {
+  auto L = []() {
+    struct LocalInLambda {
+      void qux(auto x) {} // expected-error {{'auto' not allowed in function 
prototype}}
+    };
+    (void)sizeof(LocalInLambda);
+  };
+  L();
+}
\ No newline at end of file
diff --git a/clang/test/SemaCXX/lambda-local-c++20.cpp 
b/clang/test/SemaCXX/lambda-local-c++20.cpp
new file mode 100644
index 0000000000000..1fc82d928a6b3
--- /dev/null
+++ b/clang/test/SemaCXX/lambda-local-c++20.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+int main() {
+  auto L = []() {
+    struct LocalInLambda { // expected-error {{templates cannot be declared 
inside of a local class}}
+      void qux(auto x) {}
+    };
+    (void)sizeof(LocalInLambda);
+  };
+  L();
+}
diff --git a/clang/test/SemaCXX/nested-local.cpp 
b/clang/test/SemaCXX/nested-local.cpp
new file mode 100644
index 0000000000000..e776979b4582b
--- /dev/null
+++ b/clang/test/SemaCXX/nested-local.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+
+void fn() {
+  struct Outer {
+    struct Inner {
+      void foo(auto x) {} // expected-error {{'auto' not allowed in function 
prototype}}
+    };
+  };
+}
diff --git a/clang/test/SemaCXX/static-local.cpp 
b/clang/test/SemaCXX/static-local.cpp
new file mode 100644
index 0000000000000..7c8d378e0e247
--- /dev/null
+++ b/clang/test/SemaCXX/static-local.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+int main() {
+  static struct StaticLocal { // expected-error {{templates cannot be declared 
inside of a local class}}
+    void bar(auto x) {}
+  } s;
+  (void)s;
+}
diff --git a/clang/test/SemaCXX/template-member-local-c++17.cpp 
b/clang/test/SemaCXX/template-member-local-c++17.cpp
new file mode 100644
index 0000000000000..237d400118888
--- /dev/null
+++ b/clang/test/SemaCXX/template-member-local-c++17.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<typename T>
+struct Outer {
+  void member() {
+    struct Local {
+      void baz(auto x) {} // expected-error {{'auto' not allowed in function 
prototype}}
+    };
+    (void)sizeof(Local);
+  }
+};
+
+int main() {
+  Outer<int> o;
+  o.member();
+}
diff --git a/clang/test/SemaCXX/template-member-local-c++20.cpp 
b/clang/test/SemaCXX/template-member-local-c++20.cpp
new file mode 100644
index 0000000000000..86ade46eebbf4
--- /dev/null
+++ b/clang/test/SemaCXX/template-member-local-c++20.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+
+template<typename T>
+struct Outer {
+  void member() {
+    struct Local { // expected-error {{templates cannot be declared inside of 
a local class}}
+      void baz(auto x) {}
+    };
+    (void)sizeof(Local);
+  }
+};
+
+int main() {
+  Outer<int> o;
+  o.member();
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to