Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/OpenMPSupport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ implementation.
| | | | |
| | | | Flang parser: https://github.com/llvm/llvm-project/pull/153807 |
| | | | Flang sema: https://github.com/llvm/llvm-project/pull/154779 |
| | | | Clang parse/sema: https://github.com/llvm/llvm-project/pull/158134 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| variable-category on default clause | :good:`done` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ OpenMP Support
- Properly handle array section/assumed-size array privatization in C/C++.
- Added support for ``variable-category`` modifier in ``default clause``.
- Added support for ``defaultmap`` directive implicit-behavior ``storage``.
- Added parsing and semantic analysis support for ``groupprivate`` directive.

Improvements
^^^^^^^^^^^^
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/ASTMutationListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,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())
Expand Down
62 changes: 62 additions & 0 deletions clang/include/clang/AST/DeclOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>)
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1887,6 +1887,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));
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4585,6 +4585,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 = [];
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -11708,6 +11708,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<
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/SemaOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCategoryImpl:
case Import:
case OMPThreadPrivate:
case OMPGroupPrivate:
case OMPAllocate:
case OMPRequires:
case OMPCapturedExpr:
Expand Down
28 changes: 28 additions & 0 deletions clang/lib/AST/DeclOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/OpenMPClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,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:
Expand Down Expand Up @@ -222,6 +223,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:
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,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:
Expand Down Expand Up @@ -564,6 +565,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:
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) ==
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading