[clang] Worked on the issue #147324 (PR #167228)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Nov 9 07:59:04 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (Sandeep2265)
<details>
<summary>Changes</summary>
edited in the file SemaTemplate.cpp and also added few testcases.
---
Full diff: https://github.com/llvm/llvm-project/pull/167228.diff
7 Files Affected:
- (modified) clang/lib/Sema/SemaTemplate.cpp (+35-19)
- (added) clang/test/SemaCXX/lambda-local-c++17.cpp (+11)
- (added) clang/test/SemaCXX/lambda-local-c++20.cpp (+11)
- (added) clang/test/SemaCXX/nested-local.cpp (+9)
- (added) clang/test/SemaCXX/static-local.cpp (+8)
- (added) clang/test/SemaCXX/template-member-local-c++17.cpp (+16)
- (added) clang/test/SemaCXX/template-member-local-c++20.cpp (+16)
``````````diff
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();
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/167228
More information about the cfe-commits
mailing list