https://github.com/TPPPP72 updated https://github.com/llvm/llvm-project/pull/216692
>From 2b554eceedccc8c593f99253bbfa074f8238887a Mon Sep 17 00:00:00 2001 From: Shengxin Pei <[email protected]> Date: Mon, 17 Aug 2026 21:10:35 +0800 Subject: [PATCH 1/2] [clang] Fixed a crash when declaring a member template within a local class inside an OpenMP region --- clang/docs/ReleaseNotes.md | 1 + clang/lib/Sema/SemaTemplate.cpp | 16 ++++++++++++---- clang/test/SemaOpenMP/gh216052.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaOpenMP/gh216052.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 0e40754efd30e..1fa6c5745b850 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -416,6 +416,7 @@ features cannot lower the translation-unit ABI level; - Fixed an ICE that occurred when a structured binding pack is expanded outside the lambda where it was declared. (#GH214160) - Fixed a bug where a stray closing curley brace in an OpenMP/OpenACC pragma could cause pragma parsing issues when inside of a member function. (#GH214195) - Fixed a bug where preprocessor directives following comments were not correctly recognized when using -C. (#GH48361) +- Fixed a crash when declaring a member template within a local class inside an OpenMP region. (#GH216052) #### Bug Fixes to Compiler Builtins diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index dff681454ae5a..8411d7474bb3f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8504,12 +8504,20 @@ 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()) + + // Trace the outer context chain, bypassing nested records and OpenMP + // captured regions, to determine if the class in defined inside a + // function or method. + const DeclContext *DC = RD->getDeclContext(); + while (DC && (DC->isRecord() || isa<CapturedDecl>(DC))) + DC = DC->getParent(); + + if (DC && DC->isFunctionOrMethod()) return Diag(TemplateParams->getTemplateLoc(), diag::err_template_inside_local_class) - << TemplateParams->getSourceRange(); - else - return false; + << TemplateParams->getSourceRange(); + + return false; } } diff --git a/clang/test/SemaOpenMP/gh216052.cpp b/clang/test/SemaOpenMP/gh216052.cpp new file mode 100644 index 0000000000000..483b302c3a028 --- /dev/null +++ b/clang/test/SemaOpenMP/gh216052.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fopenmp -fsyntax-only -verify %s + +void f1() { +#pragma omp parallel + class O { + // expected-error@+1 {{templates cannot be declared inside of a local class}} + template <class T> class I { + void bar(bool b = true); + }; + I<int> bar; // expected-error {{no template named 'I'}} + }; +} + +void f2() { +#pragma omp parallel + class O { + class P { + // expected-error@+1 {{templates cannot be declared inside of a local class}} + template <class T> class I { + void bar(bool b = true); + }; + I<int> bar; // expected-error {{no template named 'I'}} + }; + }; +} >From 6f36ef6061008c922efc26d9bebbf6f5c2967dcc Mon Sep 17 00:00:00 2001 From: Shengxin Pei <[email protected]> Date: Tue, 18 Aug 2026 10:41:44 +0800 Subject: [PATCH 2/2] use isa_and_nonnull --- clang/lib/Sema/SemaTemplate.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8411d7474bb3f..c1d8c3500a9a9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" @@ -8508,11 +8509,11 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // Trace the outer context chain, bypassing nested records and OpenMP // captured regions, to determine if the class in defined inside a // function or method. - const DeclContext *DC = RD->getDeclContext(); - while (DC && (DC->isRecord() || isa<CapturedDecl>(DC))) - DC = DC->getParent(); + const DeclContext *OutCtx = RD->getDeclContext(); + while (isa_and_nonnull<CapturedDecl, CXXRecordDecl>(OutCtx)) + OutCtx = OutCtx->getParent(); - if (DC && DC->isFunctionOrMethod()) + if (OutCtx && OutCtx->isFunctionOrMethod()) return Diag(TemplateParams->getTemplateLoc(), diag::err_template_inside_local_class) << TemplateParams->getSourceRange(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
