https://github.com/akash-manna-sky created https://github.com/llvm/llvm-project/pull/227699
Fixes #217893 `copyprivate` needs its list items to be threadprivate or private in the enclosing context. For a data member we only checked that it wasn't `shared`, and then assumed an enclosing construct had already made a private copy of it. That doesn't hold in a `task` or `taskloop` region, where a member that is private outside is implicitly firstprivate but gets no copy, or under `default(none)`, where it has no attribute at all. With no copy to refer to we hit `assert(VD || isOpenMPCapturedDecl(D))`, and without assertions a null address could end up being passed to `__kmpc_copyprivate`. A data member with no private copy is now diagnosed with the existing "copyprivate variable must be threadprivate or private in the enclosing context" error. In a dependent context the copies aren't built until instantiation, so the clause keeps the list item as written there and is checked when instantiated, like the other data-sharing clauses. That also fixes the crash for a data member in `copyprivate` inside a member function template. >From cd34c759b7b7d527313f4759a63e57bc37f37971 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Wed, 30 Sep 2026 18:38:26 +0530 Subject: [PATCH] [Clang][OpenMP] Fix crash on `copyprivate` of a non-privatized data member `copyprivate` needs its list items to be threadprivate or private in the enclosing context. For a data member we only checked that it was not `shared` and then assumed an enclosing construct had already made a private copy of it. That does not hold in a `task` or `taskloop` region, where a member that is private outside is implicitly firstprivate but gets no copy, or under `default(none)`. With no copy to refer to we hit `assert(VD || isOpenMPCapturedDecl(D))`. Diagnose such a member with the existing "copyprivate variable must be threadprivate or private in the enclosing context" error. In a dependent context the copies are not built until instantiation, so keep the list item as written there and check it on instantiation, like the other data-sharing clauses do. Fixes #217893 --- clang/docs/ReleaseNotes.md | 2 + clang/lib/Sema/SemaOpenMP.cpp | 16 ++++++-- .../OpenMP/single_copyprivate_messages.cpp | 41 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 3c6acf353f93f..01d9cd14cf4f4 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -550,6 +550,8 @@ features cannot lower the translation-unit ABI level; - 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) +- Fixed a crash when an OpenMP `copyprivate` clause names a non-static data member that is not private in the + enclosing context, which is now diagnosed, or names a data member inside a member function template. (#GH217893) - Fixed an assertion failure when a variable implicitly mapped by an OpenMP `target` directive has a class type (such as `std::map`) whose mapper lookup instantiates a class template specialization. (#GH154704) - Fixed a bug where repeated #imports of modular headers in non-modular compilation were translated to #pragma clang module import. (#GH216924) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 41cfc1dcd3649..f1b440a625d7c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -23289,6 +23289,14 @@ OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, reportOriginalDsa(SemaRef, DSAStack, D, DVar); continue; } + // A data member is private only if an enclosing construct captured it. + if (isa<FieldDecl>(D) && !SemaRef.CurContext->isDependentContext() && + !isOpenMPCapturedDecl(D)) { + Diag(ELoc, diag::err_omp_required_access) + << getOpenMPClauseNameForDiag(OMPC_copyprivate) + << "threadprivate or private in the enclosing context"; + continue; + } } } @@ -23333,10 +23341,12 @@ OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // No need to mark vars as copyprivate, they are already threadprivate or // implicitly private. - assert(VD || isOpenMPCapturedDecl(D)); + assert(VD || SemaRef.CurContext->isDependentContext() || + isOpenMPCapturedDecl(D)); Vars.push_back( - VD ? RefExpr->IgnoreParens() - : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false)); + (VD || SemaRef.CurContext->isDependentContext()) + ? RefExpr->IgnoreParens() + : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false)); SrcExprs.push_back(PseudoSrcExpr); DstExprs.push_back(PseudoDstExpr); AssignmentOps.push_back(AssignmentOp.get()); diff --git a/clang/test/OpenMP/single_copyprivate_messages.cpp b/clang/test/OpenMP/single_copyprivate_messages.cpp index 1dc508b01bd74..734c48f863b6d 100644 --- a/clang/test/OpenMP/single_copyprivate_messages.cpp +++ b/clang/test/OpenMP/single_copyprivate_messages.cpp @@ -206,3 +206,44 @@ int parallel() { return 0; } + +namespace GH217893 { +struct S { + int a; + S() { +#pragma omp parallel firstprivate(a) +#pragma omp taskloop +#pragma omp single copyprivate(a) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}} expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + }; // expected-error {{expected statement}} + + void nested() { +#pragma omp parallel firstprivate(a) +#pragma omp taskloop + for (int i = 0; i < 2; ++i) { +#pragma omp single copyprivate(a) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}} expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}} + foo(); + } +#pragma omp parallel default(none) +#pragma omp single copyprivate(a) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}} + foo(); +#pragma omp parallel private(a) +#pragma omp single copyprivate(a) + foo(); + } + + template <class T> void dependent() { +#pragma omp parallel private(a) +#pragma omp single copyprivate(a) + foo(); +#pragma omp parallel private(a) +#pragma omp task +#pragma omp taskgroup +#pragma omp single copyprivate(a) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}} + foo(); + } +}; + +void instantiate(S &s) { + s.dependent<int>(); // expected-note {{in instantiation of function template specialization 'GH217893::S::dependent<int>' requested here}} +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
