[OPENMP 5.0]Initial support for 'allocator' clause.

Added parsing/sema analysis/serialization/deserialization for the
'allocator' clause of the 'allocate' directive.

llvm-svn: 355952
This commit is contained in:
Alexey Bataev 2019-03-12 18:52:33 +00:00
parent 85c2955f45
commit 9cc10fc926
26 changed files with 512 additions and 47 deletions

View File

@ -396,6 +396,8 @@ public:
void VisitOMPAllocateDecl(const OMPAllocateDecl *D) {
for (const auto *E : D->varlists())
Visit(E);
for (const auto *C : D->clauselists())
Visit(C);
}
template <typename SpecializationDecl>

View File

@ -421,12 +421,21 @@ public:
///
class OMPAllocateDecl final
: public Decl,
private llvm::TrailingObjects<OMPAllocateDecl, Expr *> {
private llvm::TrailingObjects<OMPAllocateDecl, Expr *, OMPClause *> {
friend class ASTDeclReader;
friend TrailingObjects;
/// Number of variable within the allocate directive.
unsigned NumVars = 0;
/// Number of clauses associated with the allocate directive.
unsigned NumClauses = 0;
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return NumVars;
}
size_t numTrailingObjects(OverloadToken<OMPClause *>) const {
return NumClauses;
}
virtual void anchor();
@ -443,19 +452,41 @@ class OMPAllocateDecl final
void setVars(ArrayRef<Expr *> VL);
/// Returns an array of immutable clauses associated with this directive.
ArrayRef<OMPClause *> getClauses() const {
return llvm::makeArrayRef(getTrailingObjects<OMPClause *>(), NumClauses);
}
/// Returns an array of clauses associated with this directive.
MutableArrayRef<OMPClause *> getClauses() {
return MutableArrayRef<OMPClause *>(getTrailingObjects<OMPClause *>(),
NumClauses);
}
/// Sets an array of clauses to this requires declaration
void setClauses(ArrayRef<OMPClause *> CL);
public:
static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<Expr *> VL);
SourceLocation L, ArrayRef<Expr *> VL,
ArrayRef<OMPClause *> CL);
static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned N);
unsigned NVars, unsigned NClauses);
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;
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
using clauselist_range = llvm::iterator_range<clauselist_iterator>;
using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
unsigned clauselist_size() const { return NumClauses; }
bool clauselist_empty() const { return NumClauses == 0; }
varlist_range varlists() {
return varlist_range(varlist_begin(), varlist_end());
@ -468,6 +499,21 @@ public:
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
clauselist_range clauselists() {
return clauselist_range(clauselist_begin(), clauselist_end());
}
clauselist_const_range clauselists() const {
return clauselist_const_range(clauselist_begin(), clauselist_end());
}
clauselist_iterator clauselist_begin() { return getClauses().begin(); }
clauselist_iterator clauselist_end() { return getClauses().end(); }
clauselist_const_iterator clauselist_begin() const {
return getClauses().begin();
}
clauselist_const_iterator clauselist_end() const {
return getClauses().end();
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPAllocate; }
};

View File

@ -243,6 +243,58 @@ public:
}
};
/// This represents 'allocator' clause in the '#pragma omp ...'
/// directive.
///
/// \code
/// #pragma omp allocate(a) allocator(omp_default_mem_alloc)
/// \endcode
/// In this example directive '#pragma omp allocate' has simple 'allocator'
/// clause with the allocator 'omp_default_mem_alloc'.
class OMPAllocatorClause : public OMPClause {
friend class OMPClauseReader;
/// Location of '('.
SourceLocation LParenLoc;
/// Expression with the allocator.
Stmt *Allocator = nullptr;
/// Set allocator.
void setAllocator(Expr *A) { Allocator = A; }
public:
/// Build 'allocator' clause with the given allocator.
///
/// \param A Allocator.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
OMPAllocatorClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_allocator, StartLoc, EndLoc), LParenLoc(LParenLoc),
Allocator(A) {}
/// Build an empty clause.
OMPAllocatorClause()
: OMPClause(OMPC_allocator, SourceLocation(), SourceLocation()) {}
/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// Returns allocator.
Expr *getAllocator() const { return cast_or_null<Expr>(Allocator); }
child_range children() { return child_range(&Allocator, &Allocator + 1); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_allocator;
}
};
/// This represents 'if' clause in the '#pragma omp ...' directive.
///
/// \code

View File

@ -1614,9 +1614,10 @@ DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, {
DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); })
DEF_TRAVERSE_DECL(OMPAllocateDecl, {
for (auto *I : D->varlists()) {
for (auto *I : D->varlists())
TRY_TO(TraverseStmt(I));
}
for (auto *C : D->clauselists())
TRY_TO(TraverseOMPClause(C));
})
// A helper method for TemplateDecl's children.
@ -2826,6 +2827,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseWithPostUpdate(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAllocatorClause(
OMPAllocatorClause *C) {
TRY_TO(TraverseStmt(C->getAllocator()));
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
TRY_TO(VisitOMPClauseWithPreInit(C));

View File

@ -3156,6 +3156,7 @@ def OMPAllocateDecl : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Args = [ExprArgument<"Allocator">];
let Documentation = [Undocumented];
}

View File

@ -9135,6 +9135,8 @@ def note_omp_invalid_subscript_on_this_ptr_map : Note <
"expected 'this' subscript expression on map clause to be 'this[0]'">;
def err_omp_invalid_map_this_expr : Error <
"invalid 'this' expression on 'map' clause">;
def err_implied_omp_allocator_handle_t_not_found : Error<
"omp_allocator_handle_t type not found; include <omp.h>">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {

View File

@ -188,6 +188,9 @@
#ifndef OPENMP_DECLARE_MAPPER_CLAUSE
#define OPENMP_DECLARE_MAPPER_CLAUSE(Name)
#endif
#ifndef OPENMP_ALLOCATE_CLAUSE
# define OPENMP_ALLOCATE_CLAUSE(Name)
#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@ -247,6 +250,7 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd
OPENMP_DIRECTIVE(allocate)
// OpenMP clauses.
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
OPENMP_CLAUSE(if, OMPIfClause)
OPENMP_CLAUSE(final, OMPFinalClause)
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
@ -489,6 +493,9 @@ OPENMP_REQUIRES_CLAUSE(reverse_offload)
OPENMP_REQUIRES_CLAUSE(dynamic_allocators)
OPENMP_REQUIRES_CLAUSE(atomic_default_mem_order)
// Clauses allowed for OpenMP directive 'allocate'.
OPENMP_ALLOCATE_CLAUSE(allocator)
// Modifiers for 'atomic_default_mem_order' clause.
OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(seq_cst)
OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(acq_rel)
@ -910,6 +917,7 @@ OPENMP_TASKGROUP_CLAUSE(task_reduction)
// Clauses allowed for OpenMP directive 'declare mapper'.
OPENMP_DECLARE_MAPPER_CLAUSE(map)
#undef OPENMP_ALLOCATE_CLAUSE
#undef OPENMP_DECLARE_MAPPER_CLAUSE
#undef OPENMP_TASKGROUP_CLAUSE
#undef OPENMP_TASKLOOP_SIMD_CLAUSE

View File

@ -8781,6 +8781,8 @@ public:
//
private:
void *VarDataSharingAttributesStack;
/// omp_allocator_handle_t type.
QualType OMPAllocatorHandleT;
/// Number of nested '#pragma omp declare target' directives.
unsigned DeclareTargetNestingLevel = 0;
/// Initialization of data-sharing attributes stack.
@ -8892,6 +8894,7 @@ public:
/// Called on well-formed '#pragma omp allocate'.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
ArrayRef<Expr *> VarList,
ArrayRef<OMPClause *> Clauses,
DeclContext *Owner = nullptr);
/// Called on well-formed '#pragma omp requires'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
@ -9247,6 +9250,11 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'allocator' clause.
OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'if' clause.
OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
Expr *Condition, SourceLocation StartLoc,

View File

@ -59,20 +59,26 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
void OMPAllocateDecl::anchor() { }
OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ArrayRef<Expr *> VL) {
OMPAllocateDecl *D = new (C, DC, additionalSizeToAlloc<Expr *>(VL.size()))
SourceLocation L, ArrayRef<Expr *> VL,
ArrayRef<OMPClause *> CL) {
OMPAllocateDecl *D = new (
C, DC, additionalSizeToAlloc<Expr *, OMPClause *>(VL.size(), CL.size()))
OMPAllocateDecl(OMPAllocate, DC, L);
D->NumVars = VL.size();
D->setVars(VL);
D->NumClauses = CL.size();
D->setClauses(CL);
return D;
}
OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned N) {
OMPAllocateDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N))
OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation());
D->NumVars = N;
unsigned NVars,
unsigned NClauses) {
OMPAllocateDecl *D =
new (C, ID, additionalSizeToAlloc<Expr *, OMPClause *>(NVars, NClauses))
OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation());
D->NumVars = NVars;
D->NumClauses = NClauses;
return D;
}
@ -82,6 +88,13 @@ void OMPAllocateDecl::setVars(ArrayRef<Expr *> VL) {
std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
}
void OMPAllocateDecl::setClauses(ArrayRef<OMPClause *> CL) {
assert(CL.size() == NumClauses &&
"Number of variables is not the same as the preallocated buffer");
std::uninitialized_copy(CL.begin(), CL.end(),
getTrailingObjects<OMPClause *>());
}
//===----------------------------------------------------------------------===//
// OMPRequiresDecl Implementation.
//===----------------------------------------------------------------------===//

View File

@ -1560,6 +1560,12 @@ void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
}
Out << ")";
}
if (!D->clauselist_empty()) {
Out << " ";
OMPClausePrinter Printer(Out, Policy);
for (OMPClause *C : D->clauselists())
Printer.Visit(C);
}
}
void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {

View File

@ -73,6 +73,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_final:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
@ -145,6 +146,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
@ -1086,6 +1088,12 @@ void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
OS << ")";
}
void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) {
OS << "allocator(";
Node->getAllocator()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
OS << "collapse(";
Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);

View File

@ -457,6 +457,11 @@ void OMPClauseProfiler::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
Profiler->VisitStmt(C->getSimdlen());
}
void OMPClauseProfiler::VisitOMPAllocatorClause(const OMPAllocatorClause *C) {
if (C->getAllocator())
Profiler->VisitStmt(C->getAllocator());
}
void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) {
if (C->getNumForLoops())
Profiler->VisitStmt(C->getNumForLoops());

View File

@ -155,6 +155,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
@ -337,6 +338,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
case OMPC_firstprivate:
@ -805,6 +807,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
#define OPENMP_DECLARE_MAPPER_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
default:
break;
}
break;
case OMPD_allocate:
switch (CKind) {
#define OPENMP_ALLOCATE_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
default:
break;
@ -814,7 +826,6 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_end_declare_target:
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_section:
case OMPD_master:
case OMPD_taskyield:

View File

@ -3948,6 +3948,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_in_reduction:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_default:
case OMPC_seq_cst:

View File

@ -842,7 +842,7 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
/// annot_pragma_openmp_end
///
/// allocate-directive:
/// annot_pragma_openmp 'allocate' simple-variable-list
/// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
/// annot_pragma_openmp_end
///
/// declare-reduction-directive:
@ -897,16 +897,44 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/true)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
SmallVector<OMPClause *, 1> Clauses;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind =
Tok.isAnnotation() ? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
!FirstClauses[CKind].getInt());
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[CKind].setInt(true);
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Actions.EndOpenMPClause();
break;
}
// Skip ',' if any.
if (Tok.is(tok::comma))
ConsumeToken();
Actions.EndOpenMPClause();
}
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
}
// Skip the last annot_pragma_openmp_end.
ConsumeAnnotationToken();
return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers());
return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
Clauses);
}
break;
}
@ -925,9 +953,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.StartOpenMPClause(CKind);
OMPClause *Clause =
ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt());
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch);
OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
!FirstClauses[CKind].getInt());
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[CKind].setInt(true);
if (Clause != nullptr)
Clauses.push_back(Clause);
@ -1214,15 +1243,42 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/false)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
SmallVector<OMPClause *, 1> Clauses;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind =
Tok.isAnnotation() ? OMPC_unknown
: getOpenMPClauseKind(PP.getSpelling(Tok));
Actions.StartOpenMPClause(CKind);
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
!FirstClauses[CKind].getInt());
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
StopBeforeMatch);
FirstClauses[CKind].setInt(true);
if (Clause != nullptr)
Clauses.push_back(Clause);
if (Tok.is(tok::annot_pragma_openmp_end)) {
Actions.EndOpenMPClause();
break;
}
// Skip ',' if any.
if (Tok.is(tok::comma))
ConsumeToken();
Actions.EndOpenMPClause();
}
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
}
DeclGroupPtrTy Res =
Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers());
DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
Loc, Helper.getIdentifiers(), Clauses);
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
}
SkipUntil(tok::annot_pragma_openmp_end);
@ -1506,7 +1562,7 @@ bool Parser::ParseOpenMPSimpleVarList(
/// thread_limit-clause | priority-clause | grainsize-clause |
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
/// from-clause | is_device_ptr-clause | task_reduction-clause |
/// in_reduction-clause
/// in_reduction-clause | allocator-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@ -1535,6 +1591,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_allocator:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@ -1555,6 +1612,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// At most one grainsize clause can appear on the directive.
// OpenMP [2.9.2, taskloop Construct, Restrictions]
// At most one num_tasks clause can appear on the directive.
// OpenMP [2.11.3, allocate Directive, Restrictions]
// At most one allocator clause can appear on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@ -1722,6 +1781,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// hint-clause:
/// 'hint' '(' expression ')'
///
/// allocator-clause:
/// 'allocator' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
bool ParseOnly) {
SourceLocation Loc = ConsumeToken();

View File

@ -2194,9 +2194,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
return D;
}
Sema::DeclGroupPtrTy
Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
DeclContext *Owner) {
Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective(
SourceLocation Loc, ArrayRef<Expr *> VarList,
ArrayRef<OMPClause *> Clauses, DeclContext *Owner) {
assert(Clauses.size() <= 1 && "Expected at most one clause.");
Expr *Allocator = nullptr;
if (!Clauses.empty())
Allocator = cast<OMPAllocatorClause>(Clauses.back())->getAllocator();
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
auto *DE = cast<DeclRefExpr>(RefExpr);
@ -2213,17 +2217,18 @@ Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
continue;
Vars.push_back(RefExpr);
VD->addAttr(
OMPAllocateDeclAttr::CreateImplicit(Context, DE->getSourceRange()));
Attr *A = OMPAllocateDeclAttr::CreateImplicit(Context, Allocator,
DE->getSourceRange());
VD->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPAllocate(VD,
VD->getAttr<OMPAllocateDeclAttr>());
ML->DeclarationMarkedOpenMPAllocate(VD, A);
}
if (Vars.empty())
return nullptr;
if (!Owner)
Owner = getCurLexicalContext();
OMPAllocateDecl *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars);
OMPAllocateDecl *D =
OMPAllocateDecl::Create(Context, Owner, Loc, Vars, Clauses);
D->setAccess(AS_public);
Owner->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
@ -8436,6 +8441,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_simdlen:
Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_allocator:
Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_collapse:
Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
@ -9009,6 +9017,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_final:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
@ -9259,6 +9268,43 @@ OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc,
OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
}
/// Tries to find omp_allocator_handle_t type.
static bool FindOMPAllocatorHandleT(Sema &S, SourceLocation Loc,
QualType &OMPAllocatorHandleT) {
if (!OMPAllocatorHandleT.isNull())
return true;
DeclarationName OMPAllocatorHandleTName =
&S.getASTContext().Idents.get("omp_allocator_handle_t");
auto *TD = dyn_cast_or_null<TypeDecl>(S.LookupSingleName(
S.TUScope, OMPAllocatorHandleTName, Loc, Sema::LookupAnyName));
if (!TD) {
S.Diag(Loc, diag::err_implied_omp_allocator_handle_t_not_found);
return false;
}
OMPAllocatorHandleT = S.getASTContext().getTypeDeclType(TD);
return true;
}
OMPClause *Sema::ActOnOpenMPAllocatorClause(Expr *A, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
// OpenMP [2.11.3, allocate Directive, Description]
// allocator is an expression of omp_allocator_handle_t type.
if (!FindOMPAllocatorHandleT(*this, A->getExprLoc(), OMPAllocatorHandleT))
return nullptr;
ExprResult Allocator = DefaultLvalueConversion(A);
if (Allocator.isInvalid())
return nullptr;
Allocator = PerformImplicitConversion(Allocator.get(), OMPAllocatorHandleT,
Sema::AA_Initializing,
/*AllowExplicit=*/true);
if (Allocator.isInvalid())
return nullptr;
return new (Context)
OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *NumForLoops,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@ -9326,6 +9372,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@ -9503,6 +9550,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:
@ -9724,6 +9772,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_schedule:
case OMPC_private:
@ -9928,6 +9977,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_default:
case OMPC_proc_bind:

View File

@ -2883,9 +2883,20 @@ Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
assert(isa<DeclRefExpr>(Var) && "allocate arg is not a DeclRefExpr");
Vars.push_back(Var);
}
SmallVector<OMPClause *, 4> Clauses;
// Copy map clauses from the original mapper.
for (OMPClause *C : D->clauselists()) {
auto *AC = cast<OMPAllocatorClause>(C);
ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs);
if (!NewE.isUsable())
continue;
OMPClause *IC = SemaRef.ActOnOpenMPAllocatorClause(
NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc());
Clauses.push_back(IC);
}
Sema::DeclGroupPtrTy Res =
SemaRef.ActOnOpenMPAllocateDirective(D->getLocation(), Vars, Owner);
Sema::DeclGroupPtrTy Res = SemaRef.ActOnOpenMPAllocateDirective(
D->getLocation(), Vars, Clauses, Owner);
if (Res.get().isNull())
return nullptr;
return Res.get().getSingleDecl();

View File

@ -1554,6 +1554,16 @@ public:
return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
}
/// Build a new OpenMP 'allocator' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPAllocatorClause(Expr *A, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPAllocatorClause(A, StartLoc, LParenLoc, EndLoc);
}
/// Build a new OpenMP 'collapse' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@ -8343,6 +8353,16 @@ TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPAllocatorClause(OMPAllocatorClause *C) {
ExprResult E = getDerived().TransformExpr(C->getAllocator());
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPAllocatorClause(
E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSimdlenClause(OMPSimdlenClause *C) {

View File

@ -11704,6 +11704,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_simdlen:
C = new (Context) OMPSimdlenClause();
break;
case OMPC_allocator:
C = new (Context) OMPAllocatorClause();
break;
case OMPC_collapse:
C = new (Context) OMPCollapseClause();
break;
@ -11929,6 +11932,11 @@ void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
C->setLParenLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPAllocatorClause(OMPAllocatorClause *C) {
C->setAllocator(Record.readExpr());
C->setLParenLoc(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
C->setNumForLoops(Record.readSubExpr());
C->setLParenLoc(Record.readSourceLocation());

View File

@ -2637,12 +2637,19 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
VisitDecl(D);
unsigned NumVars = D->varlist_size();
unsigned NumClauses = D->clauselist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i) {
Vars.push_back(Record.readExpr());
}
D->setVars(Vars);
SmallVector<OMPClause *, 8> Clauses;
Clauses.reserve(NumClauses);
OMPClauseReader ClauseReader(Record);
for (unsigned I = 0; I != NumClauses; ++I)
Clauses.push_back(ClauseReader.readClause());
D->setClauses(Clauses);
}
void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) {
@ -3878,9 +3885,12 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_OMP_THREADPRIVATE:
D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_OMP_ALLOCATE:
D = OMPAllocateDecl::CreateDeserialized(Context, ID, Record.readInt());
case DECL_OMP_ALLOCATE: {
unsigned NumVars = Record.readInt();
unsigned NumClauses = Record.readInt();
D = OMPAllocateDecl::CreateDeserialized(Context, ID, NumVars, NumClauses);
break;
}
case DECL_OMP_REQUIRES:
D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
@ -4481,8 +4491,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,
break;
case UPD_DECL_MARKED_OPENMP_ALLOCATE:
D->addAttr(OMPAllocateDeclAttr::CreateImplicit(Reader.getContext(),
ReadSourceRange()));
D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
Reader.getContext(), Record.readExpr(), ReadSourceRange()));
break;
case UPD_DECL_EXPORTED: {

View File

@ -5291,6 +5291,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
break;
case UPD_DECL_MARKED_OPENMP_ALLOCATE:
Record.AddStmt(D->getAttr<OMPAllocateDeclAttr>()->getAllocator());
Record.AddSourceRange(D->getAttr<OMPAllocateDeclAttr>()->getRange());
break;
@ -6534,6 +6535,11 @@ void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
Record.AddSourceLocation(C->getLParenLoc());
}
void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) {
Record.AddStmt(C->getAllocator());
Record.AddSourceLocation(C->getLParenLoc());
}
void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
Record.AddStmt(C->getNumForLoops());
Record.AddSourceLocation(C->getLParenLoc());

View File

@ -1747,9 +1747,13 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
Record.push_back(D->varlist_size());
Record.push_back(D->clauselist_size());
VisitDecl(D);
for (auto *I : D->varlists())
Record.AddStmt(I);
OMPClauseWriter ClauseWriter(Record);
for (OMPClause *C : D->clauselists())
ClauseWriter.writeClause(C);
Code = serialization::DECL_OMP_ALLOCATE;
}

View File

@ -0,0 +1,89 @@
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
typedef void **omp_allocator_handle_t;
extern const omp_allocator_handle_t omp_default_mem_alloc;
extern const omp_allocator_handle_t omp_large_cap_mem_alloc;
extern const omp_allocator_handle_t omp_const_mem_alloc;
extern const omp_allocator_handle_t omp_high_bw_mem_alloc;
extern const omp_allocator_handle_t omp_low_lat_mem_alloc;
extern const omp_allocator_handle_t omp_cgroup_mem_alloc;
extern const omp_allocator_handle_t omp_pteam_mem_alloc;
extern const omp_allocator_handle_t omp_thread_mem_alloc;
struct St{
int a;
};
struct St1{
int a;
static int b;
// CHECK: static int b;
#pragma omp allocate(b) allocator(omp_default_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(St1::b) allocator(omp_default_mem_alloc){{$}}
} d;
int a, b;
// CHECK: int a;
// CHECK: int b;
#pragma omp allocate(a) allocator(omp_large_cap_mem_alloc)
#pragma omp allocate(a) allocator(omp_const_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_large_cap_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_const_mem_alloc)
#pragma omp allocate(d, b) allocator(omp_high_bw_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(d,b) allocator(omp_high_bw_mem_alloc)
template <class T>
struct ST {
static T m;
#pragma omp allocate(m) allocator(omp_low_lat_mem_alloc)
};
template <class T> T foo() {
T v;
#pragma omp allocate(v) allocator(omp_cgroup_mem_alloc)
v = ST<T>::m;
return v;
}
//CHECK: template <class T> T foo() {
//CHECK-NEXT: T v;
//CHECK-NEXT: #pragma omp allocate(v) allocator(omp_cgroup_mem_alloc)
//CHECK: template<> int foo<int>() {
//CHECK-NEXT: int v;
//CHECK-NEXT: #pragma omp allocate(v) allocator(omp_cgroup_mem_alloc)
namespace ns{
int a;
}
// CHECK: namespace ns {
// CHECK-NEXT: int a;
// CHECK-NEXT: }
#pragma omp allocate(ns::a) allocator(omp_pteam_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(ns::a) allocator(omp_pteam_mem_alloc)
int main () {
static int a;
// CHECK: static int a;
#pragma omp allocate(a) allocator(omp_thread_mem_alloc)
// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_thread_mem_alloc)
a=2;
return (foo<int>());
}
extern template int ST<int>::m;
#endif

View File

@ -0,0 +1,27 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s
struct St{
int a;
};
int sss;
#pragma omp allocate(sss) allocate // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(sss) allocator // expected-error {{expected '(' after 'allocator'}}
#pragma omp allocate(sss) allocator(0, // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
#pragma omp allocate(sss) allocator(0,sss // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
#pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
#pragma omp allocate(sss) allocator(sss) // expected-error {{omp_allocator_handle_t type not found; include <omp.h>}}
typedef void *omp_allocator_handle_t;
struct St1{
int a;
static int b;
#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'omp_allocator_handle_t' (aka 'void *') with an expression of incompatible type 'int'}}
} d;
#pragma omp allocate(d) allocator(nullptr)
extern void *allocator;
#pragma omp allocate(d) allocator(allocator)

View File

@ -12,14 +12,17 @@
#if !defined(PASS1)
#define PASS1
typedef void **omp_allocator_handle_t;
extern const omp_allocator_handle_t omp_default_mem_alloc;
int a;
// CHECK: int a;
#elif !defined(PASS2)
#define PASS2
#pragma omp allocate(a)
// CHECK: #pragma omp allocate(a)
#pragma omp allocate(a) allocator(omp_default_mem_alloc)
// CHECK: #pragma omp allocate(a) allocator(omp_default_mem_alloc)
#else

View File

@ -2168,6 +2168,10 @@ void OMPClauseEnqueue::VisitOMPSimdlenClause(const OMPSimdlenClause *C) {
Visitor->AddStmt(C->getSimdlen());
}
void OMPClauseEnqueue::VisitOMPAllocatorClause(const OMPAllocatorClause *C) {
Visitor->AddStmt(C->getAllocator());
}
void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) {
Visitor->AddStmt(C->getNumForLoops());
}