-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[clang] [OpenMP] New OpenMP 6.0 - Parsing and Sema support for groupprivate #158134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] [OpenMP] New OpenMP 6.0 - Parsing and Sema support for groupprivate #158134
Conversation
@llvm/pr-subscribers-clang-modules @llvm/pr-subscribers-clang Author: None (Ritanya-B-Bharadwaj) ChangesPatch is 35.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/158134.diff 20 Files Affected:
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]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
2fa20d5
to
7e66fd6
Compare
1ee8016
to
e108ff6
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/186/builds/12498 Here is the relevant piece of the build log for the reference
|
No description provided.