llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (Ritanya-B-Bharadwaj) <details> <summary>Changes</summary> --- Patch is 35.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158134.diff 20 Files Affected: - (modified) clang/docs/OpenMPSupport.rst (+1-1) - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/include/clang/AST/ASTMutationListener.h (+6) - (modified) clang/include/clang/AST/ASTNodeTraverser.h (+5) - (modified) clang/include/clang/AST/DeclOpenMP.h (+62) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+6) - (modified) clang/include/clang/Basic/Attr.td (+6) - (modified) clang/include/clang/Basic/DeclNodes.td (+1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) - (modified) clang/include/clang/Sema/SemaOpenMP.h (+6) - (modified) clang/lib/AST/DeclBase.cpp (+1) - (modified) clang/lib/AST/DeclOpenMP.cpp (+28) - (modified) clang/lib/AST/OpenMPClause.cpp (+2) - (modified) clang/lib/Basic/OpenMPKinds.cpp (+2) - (modified) clang/lib/Parse/ParseOpenMP.cpp (+32) - (modified) clang/lib/Sema/SemaOpenMP.cpp (+115-15) - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+18) - (added) clang/test/OpenMP/groupprivate_ast_print.cpp (+57) - (added) clang/test/OpenMP/groupprivate_messages.cpp (+111) - (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+7) ``````````diff diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index 76b6a72fec721..d457f5a9aa077 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -476,7 +476,7 @@ implementation. +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ | Local clause on declare target | :part:`In Progress` | :none:`unclaimed` | | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ -| groupprivate directive | :part:`In Progress` | :none:`unclaimed` | | +| groupprivate directive | :part:`partial` | :none:`unclaimed` | | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ | variable-category on default clause | :part:`In Progress` | :none:`unclaimed` | | +-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 031a196bbc83f..66154269abfc1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -342,6 +342,7 @@ OpenMP Support modifier in the ``adjust_args`` clause. - Allow array length to be omitted in array section subscript expression. - Fixed non-contiguous strided update in the ``omp target update`` directive with the ``from`` clause. +- Added parsing and semantic analysis support for ``groupprivate`` directive. Improvements ^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h index 2c4ec2ce67f36..2c6989f254467 100644 --- a/clang/include/clang/AST/ASTMutationListener.h +++ b/clang/include/clang/AST/ASTMutationListener.h @@ -121,6 +121,12 @@ class ASTMutationListener { /// \param D the declaration marked OpenMP threadprivate. virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {} + /// A declaration is marked as OpenMP groupprivate which was not + /// previously marked as groupprivate. + /// + /// \param D the declaration marked OpenMP groupprivate. + virtual void DeclarationMarkedOpenMPGroupPrivate(const Decl *D) {} + /// A declaration is marked as OpenMP declaretarget which was not /// previously marked as declaretarget. /// diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index d9dc8290b0e49..f0b16bf667c8d 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -625,6 +625,11 @@ class ASTNodeTraverser Visit(E); } + void VisitOMPGroupPrivateDecl(const OMPGroupPrivateDecl *D) { + for (const auto *E : D->varlist()) + Visit(E); + } + void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { Visit(D->getCombiner()); if (const auto *Initializer = D->getInitializer()) diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h index f3e18ad0339af..06414cef6baf3 100644 --- a/clang/include/clang/AST/DeclOpenMP.h +++ b/clang/include/clang/AST/DeclOpenMP.h @@ -158,6 +158,68 @@ class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> { static bool classofKind(Kind K) { return K == OMPThreadPrivate; } }; +/// This represents '#pragma omp groupprivate ...' directive. +/// For example, in the following, both 'a' and 'A::b' are groupprivate: +/// +/// \code +/// int a; +/// #pragma omp groupprivate(a) +/// struct A { +/// static int b; +/// #pragma omp groupprivate(b) +/// }; +/// \endcode +/// +class OMPGroupPrivateDecl final : public OMPDeclarativeDirective<Decl> { + friend class OMPDeclarativeDirective<Decl>; + + LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION(); + + OMPGroupPrivateDecl(DeclContext *DC = nullptr, + SourceLocation L = SourceLocation()) + : OMPDeclarativeDirective<Decl>(OMPGroupPrivate, DC, L) {} + + ArrayRef<const Expr *> getVars() const { + auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); + return {Storage, Data->getNumChildren()}; + } + + MutableArrayRef<Expr *> getVars() { + auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); + return {Storage, Data->getNumChildren()}; + } + + void setVars(ArrayRef<Expr *> VL); + +public: + static OMPGroupPrivateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, ArrayRef<Expr *> VL); + static OMPGroupPrivateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID, + unsigned N); + + typedef MutableArrayRef<Expr *>::iterator varlist_iterator; + typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; + typedef llvm::iterator_range<varlist_iterator> varlist_range; + typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; + + unsigned varlist_size() const { return Data->getNumChildren(); } + bool varlist_empty() const { return Data->getChildren().empty(); } + + varlist_range varlist() { + return varlist_range(varlist_begin(), varlist_end()); + } + varlist_const_range varlist() const { + return varlist_const_range(varlist_begin(), varlist_end()); + } + varlist_iterator varlist_begin() { return getVars().begin(); } + varlist_iterator varlist_end() { return getVars().end(); } + varlist_const_iterator varlist_begin() const { return getVars().begin(); } + varlist_const_iterator varlist_end() const { return getVars().end(); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPGroupPrivate; } +}; + enum class OMPDeclareReductionInitKind { Call, // Initialized by function call. Direct, // omp_priv(<expr>) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 248b89200eace..9e2a4503fcbe7 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1883,6 +1883,12 @@ DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { } }) +DEF_TRAVERSE_DECL(OMPGroupPrivateDecl, { + for (auto *I : D->varlist()) { + TRY_TO(TraverseStmt(I)); + } +}) + DEF_TRAVERSE_DECL(OMPRequiresDecl, { for (auto *C : D->clauselists()) { TRY_TO(TraverseOMPClause(C)); diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index a9fa4a8f07454..f37bfae3c0d7c 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4551,6 +4551,12 @@ def OMPThreadPrivateDecl : InheritableAttr { let Documentation = [InternalOnly]; } +def OMPGroupPrivateDecl : InheritableAttr { + let Spellings = []; + let SemaHandler = 0; + let Documentation = [InternalOnly]; +} + def OMPCaptureNoInit : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 8d6731b50f509..04311055bb600 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -106,6 +106,7 @@ def OutlinedFunction : DeclNode<Decl>, DeclContext; def Captured : DeclNode<Decl>, DeclContext; def Import : DeclNode<Decl>; def OMPThreadPrivate : DeclNode<Decl>; +def OMPGroupPrivate : DeclNode<Decl>; def OMPAllocate : DeclNode<Decl>; def OMPRequires : DeclNode<Decl>; def Empty : DeclNode<Decl>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a7f3d37823075..45f5820d94ead 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11667,6 +11667,10 @@ def err_omp_threadprivate_incomplete_type : Error< "threadprivate variable with incomplete type %0">; def err_omp_no_dsa_for_variable : Error< "variable %0 must have explicitly specified data sharing attributes">; +def err_omp_groupprivate_incomplete_type : Error< + "groupprivate variable with incomplete type %0">; +def err_omp_groupprivate_with_initializer : Error< + "variable %0 with initializer cannot appear in groupprivate directive">; def err_omp_defaultmap_no_attr_for_variable : Error< "variable %0 must have explicitly specified data sharing attributes, data mapping attributes, or in an is_device_ptr clause">; def note_omp_default_dsa_none : Note< diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 91c3d4bd5210e..0f23186097491 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -227,6 +227,12 @@ class SemaOpenMP : public SemaBase { /// Builds a new OpenMPThreadPrivateDecl and checks its correctness. OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList); + /// Called on well-formed '#pragma omp groupprivate'. + DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, + ArrayRef<Expr *> VarList); + /// Builds a new OpenMPGroupPrivateDecl and checks its correctness. + OMPGroupPrivateDecl *CheckOMPGroupPrivateDecl(SourceLocation Loc, + ArrayRef<Expr *> VarList); /// Called on well-formed '#pragma omp allocate'. DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList, diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 680a4d74171a9..b244f0a6e6a95 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -986,6 +986,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPGroupPrivate: case OMPAllocate: case OMPRequires: case OMPCapturedExpr: diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index 32c82f614d6f2..ef08a1c30042f 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -48,6 +48,34 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { llvm::copy(VL, getVars().begin()); } +//===----------------------------------------------------------------------===// +// OMPGroupPrivateDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPGroupPrivateDecl::anchor() {} + +OMPGroupPrivateDecl *OMPGroupPrivateDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + ArrayRef<Expr *> VL) { + auto *D = OMPDeclarativeDirective::createDirective<OMPGroupPrivateDecl>( + C, DC, {}, VL.size(), L); + D->setVars(VL); + return D; +} + +OMPGroupPrivateDecl *OMPGroupPrivateDecl::CreateDeserialized(ASTContext &C, + GlobalDeclID ID, + unsigned N) { + return OMPDeclarativeDirective::createEmptyDirective<OMPGroupPrivateDecl>( + C, ID, 0, N); +} + +void OMPGroupPrivateDecl::setVars(ArrayRef<Expr *> VL) { + assert(VL.size() == Data->getNumChildren() && + "Number of variables is not the same as the preallocated buffer"); + llvm::copy(VL, getVars().begin()); +} + //===----------------------------------------------------------------------===// // OMPAllocateDecl Implementation. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 588b0dcc6d7b8..16c27b8a73393 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -122,6 +122,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_groupprivate: case OMPC_flush: case OMPC_depobj: case OMPC_read: @@ -221,6 +222,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: + case OMPC_groupprivate: case OMPC_flush: case OMPC_depobj: case OMPC_read: diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 220b31b0f19bc..0803a2276bfa0 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -196,6 +196,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str, } case OMPC_unknown: case OMPC_threadprivate: + case OMPC_groupprivate: case OMPC_if: case OMPC_final: case OMPC_safelen: @@ -540,6 +541,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, llvm_unreachable("Invalid OpenMP 'num_threads' clause modifier"); case OMPC_unknown: case OMPC_threadprivate: + case OMPC_groupprivate: case OMPC_if: case OMPC_final: case OMPC_safelen: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 5db2f2e2ccf86..d26761f648b3b 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2009,6 +2009,19 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } break; } + case OMPD_groupprivate: { + ConsumeToken(); + DeclDirectiveListParserHelper Helper(this, DKind); + if (!ParseOpenMPSimpleVarList(DKind, Helper, + /*AllowScopeSpecifier=*/true)) { + skipUntilPragmaOpenMPEnd(DKind); + // Skip the last annot_pragma_openmp_end. + ConsumeAnnotationToken(); + return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective( + Loc, Helper.getIdentifiers()); + } + break; + } case OMPD_allocate: { ConsumeToken(); DeclDirectiveListParserHelper Helper(this, DKind); @@ -2731,6 +2744,24 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( SkipUntil(tok::annot_pragma_openmp_end); break; } + case OMPD_groupprivate: { + if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == + ParsedStmtContext()) { + Diag(Tok, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind, OMPVersion) << 0; + } + ConsumeToken(); + DeclDirectiveListParserHelper Helper(this, DKind); + if (!ParseOpenMPSimpleVarList(DKind, Helper, + /*AllowScopeSpecifier=*/false)) { + skipUntilPragmaOpenMPEnd(DKind); + DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective( + Loc, Helper.getIdentifiers()); + Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); + } + SkipUntil(tok::annot_pragma_openmp_end); + break; + } case OMPD_allocate: { // FIXME: Should this be permitted in C++? if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == @@ -3285,6 +3316,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, skipUntilPragmaOpenMPEnd(DKind); break; case OMPC_threadprivate: + case OMPC_groupprivate: case OMPC_uniform: case OMPC_match: if (!WrongDirective) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7d800c446b595..a08984e372aff 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -234,6 +234,7 @@ class DSAStackTy { /// Stack of used declaration and their data-sharing attributes. DeclSAMapTy Threadprivates; + DeclSAMapTy Groupprivates; const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr; SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack; /// true, if check for DSA must be from parent directive, false, if @@ -1497,6 +1498,12 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, Data.RefExpr.setPointer(E); Data.PrivateCopy = nullptr; Data.Modifier = Modifier; + } else if (A == OMPC_groupprivate) { + DSAInfo &Data = Groupprivates[D]; + Data.Attributes = A; + Data.RefExpr.setPointer(E); + Data.PrivateCopy = nullptr; + Data.Modifier = Modifier; } else { DSAInfo &Data = getTopOfStack().SharingMap[D]; assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || @@ -3105,7 +3112,8 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, // OpenMP [2.9.2, Syntax, C/C++] // Variables must be file-scope, namespace-scope, or static block-scope. - if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) { + if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) && + !VD->hasGlobalStorage()) { Diag(Id.getLoc(), diag::err_omp_global_var_arg) << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal(); bool IsDecl = @@ -3119,8 +3127,8 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, VarDecl *CanonicalVD = VD->getCanonicalDecl(); NamedDecl *ND = CanonicalVD; // OpenMP [2.9.2, Restrictions, C/C++, p.2] - // A threadprivate directive for file-scope variables must appear outside - // any definition or declaration. + // A threadprivate or groupprivate directive for file-scope variables must + // appear outside any definition or declaration. if (CanonicalVD->getDeclContext()->isTranslationUnit() && !SemaRef.getCurLexicalContext()->isTranslationUnit()) { Diag(Id.getLoc(), diag::err_omp_var_scope) @@ -3133,9 +3141,9 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, return ExprError(); } // OpenMP [2.9.2, Restrictions, C/C++, p.3] - // A threadprivate directive for static class member variables must appear - // in the class definition, in the same scope in which the member - // variables are declared. + // A threadprivate or groupprivate directive for static class member + // variables must appear in the class definition, in the same scope in which + // the member variables are declared. if (CanonicalVD->isStaticDataMember() && !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) { Diag(Id.getLoc(), diag::err_omp_var_scope) @@ -3148,9 +3156,9 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, return ExprError(); } // OpenMP [2.9.2, Restrictions, C/C++, p.4] - // A threadprivate directive for namespace-scope variables must appear - // outside any definition or declaration other than the namespace - // definition itself. + // A threadprivate or groupprivate directive for namespace-scope variables + // must appear outside any definition or declaration other than the + // namespace definition itself. if (CanonicalVD->getDeclContext()->isNamespace() && (!SemaRef.getCurLexicalContext()->isFileContext() || !SemaRef.getCurLexicalContext()->Encloses( @@ -3165,8 +3173,9 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, return ExprError(); } // OpenMP [2.9.2, Restrictions, C/C++, p.6] - // A threadprivate directive for static block-scope variables must appear - // in the scope of the variable and not in a nested scope. + // A threadprivate or groupprivate directive for static block-scope + // variables must appear in the scope of the variable and not in a nested + // scope. if (CanonicalVD->isLocalVarDecl() && CurScope && !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) { D... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/158134 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits