[OPENMP50]Add initial support for 'affinity' clause.

Summary:
Added parsing/sema/serialization support for affinity clause in task
directives.

Reviewers: jdoerfert

Subscribers: yaxunl, guansong, arphaman, llvm-commits, cfe-commits, caomhin

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D80148
This commit is contained in:
Alexey Bataev 2020-05-18 13:37:53 -04:00
parent c1ae72d03f
commit 2e499eee58
16 changed files with 379 additions and 15 deletions

View File

@ -7252,6 +7252,107 @@ public:
}
};
/// This represents clause 'affinity' in the '#pragma omp task'-based
/// directives.
///
/// \code
/// #pragma omp task affinity(iterator(i = 0:n) : ([3][n])a, b[:n], c[i])
/// \endcode
/// In this example directive '#pragma omp task' has clause 'affinity' with the
/// affinity modifer 'iterator(i = 0:n)' and locator items '([3][n])a', 'b[:n]'
/// and 'c[i]'.
class OMPAffinityClause final
: public OMPVarListClause<OMPAffinityClause>,
private llvm::TrailingObjects<OMPAffinityClause, Expr *> {
friend class OMPClauseReader;
friend OMPVarListClause;
friend TrailingObjects;
/// Location of ':' symbol.
SourceLocation ColonLoc;
/// Build clause.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param N Number of locators asssociated with the clause.
OMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity, StartLoc,
LParenLoc, EndLoc, N) {}
/// Build an empty clause.
/// \param N Number of locators asssociated with the clause.
///
explicit OMPAffinityClause(unsigned N)
: OMPVarListClause<OMPAffinityClause>(llvm::omp::OMPC_affinity,
SourceLocation(), SourceLocation(),
SourceLocation(), N) {}
/// Sets the affinity modifier for the clause, if any.
void setModifier(Expr *E) {
getTrailingObjects<Expr *>()[varlist_size()] = E;
}
/// Sets the location of ':' symbol.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
/// Creates clause with a modifier a list of locator items.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param Locators List of locator items.
static OMPAffinityClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier,
ArrayRef<Expr *> Locators);
/// Creates an empty clause with the place for \p N locator items.
///
/// \param C AST context.
/// \param N The number of locator items.
static OMPAffinityClause *CreateEmpty(const ASTContext &C, unsigned N);
/// Gets affinity modifier.
Expr *getModifier() { return getTrailingObjects<Expr *>()[varlist_size()]; }
Expr *getModifier() const {
return getTrailingObjects<Expr *>()[varlist_size()];
}
/// Gets the location of ':' symbol.
SourceLocation getColonLoc() const { return ColonLoc; }
// Iterators
child_range children() {
int Offset = getModifier() ? 1 : 0;
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end() + Offset));
}
const_child_range children() const {
auto Children = const_cast<OMPAffinityClause *>(this)->children();
return const_child_range(Children.begin(), Children.end());
}
child_range used_children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range used_children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
static bool classof(const OMPClause *T) {
return T->getClauseKind() == llvm::omp::OMPC_affinity;
}
};
/// This class implements a simple visitor for OMPClause
/// subclasses.
template<class ImplClass, template <typename> class Ptr, typename RetTy>

View File

@ -3560,6 +3560,15 @@ bool RecursiveASTVisitor<Derived>::VisitOMPUsesAllocatorsClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAffinityClause(
OMPAffinityClause *C) {
TRY_TO(TraverseStmt(C->getModifier()));
for (Expr *E : C->varlists())
TRY_TO(TraverseStmt(E));
return true;
}
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm

View File

@ -10799,6 +10799,12 @@ public:
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<UsesAllocatorsData> Data);
/// Called on well-formed 'affinity' clause.
OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier,
ArrayRef<Expr *> Locators);
/// The kind of conversion being performed.
enum CheckedConversionKind {

View File

@ -151,6 +151,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
break;
}
@ -241,6 +242,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
break;
}
@ -1368,6 +1370,25 @@ OMPUsesAllocatorsClause::CreateEmpty(const ASTContext &C, unsigned N) {
return new (Mem) OMPUsesAllocatorsClause(N);
}
OMPAffinityClause *
OMPAffinityClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier,
ArrayRef<Expr *> Locators) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Locators.size() + 1));
auto *Clause = new (Mem)
OMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, Locators.size());
Clause->setModifier(Modifier);
Clause->setVarRefs(Locators);
return Clause;
}
OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + 1));
return new (Mem) OMPAffinityClause(N);
}
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
@ -1969,6 +1990,21 @@ void OMPClausePrinter::VisitOMPUsesAllocatorsClause(
OS << ")";
}
void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) {
if (Node->varlist_empty())
return;
OS << "affinity";
char StartSym = '(';
if (Expr *Modifier = Node->getModifier()) {
OS << "(";
Modifier->printPretty(OS, nullptr, Policy);
OS << " :";
StartSym = ' ';
}
VisitOMPClauseList(Node, StartSym);
OS << ")";
}
void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
VariantMatchInfo &VMI) const {
for (const OMPTraitSet &Set : Sets) {

View File

@ -809,6 +809,12 @@ void OMPClauseProfiler::VisitOMPUsesAllocatorsClause(
Profiler->VisitStmt(D.AllocatorTraits);
}
}
void OMPClauseProfiler::VisitOMPAffinityClause(const OMPAffinityClause *C) {
if (const Expr *Modifier = C->getModifier())
Profiler->VisitStmt(Modifier);
for (const Expr *E : C->varlists())
Profiler->VisitStmt(E);
}
void OMPClauseProfiler::VisitOMPOrderClause(const OMPOrderClause *C) {}
} // namespace

View File

@ -175,6 +175,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@ -422,6 +423,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");

View File

@ -4734,6 +4734,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}

View File

@ -2668,6 +2668,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_nontemporal:
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_affinity:
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
case OMPC_uses_allocators:
@ -3275,7 +3276,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
getOpenMPClauseName(Kind).data()))
return true;
bool DependWithIterator = false;
bool HasIterator = false;
bool NeedRParenForLinear = false;
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
@ -3321,7 +3322,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// iterators-definition ]
// where iterator-specifier is [ iterator-type ] identifier =
// range-specification
DependWithIterator = true;
HasIterator = true;
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
Data.DepModOrTailExpr = IteratorRes.get();
@ -3440,12 +3441,24 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ConsumeToken();
}
}
} else if (Kind == OMPC_allocate) {
} else if (Kind == OMPC_allocate ||
(Kind == OMPC_affinity && Tok.is(tok::identifier) &&
PP.getSpelling(Tok) == "iterator")) {
// Handle optional allocator expression followed by colon delimiter.
ColonProtectionRAIIObject ColonRAII(*this);
TentativeParsingAction TPA(*this);
ExprResult Tail =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
// OpenMP 5.0, 2.10.1, task Construct.
// where aff-modifier is one of the following:
// iterator(iterators-definition)
ExprResult Tail;
if (Kind == OMPC_allocate) {
Tail = ParseAssignmentExpression();
} else {
HasIterator = true;
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
Tail = ParseOpenMPIteratorsExpr();
}
Tail = Actions.CorrectDelayedTyposInExpr(Tail);
Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
/*DiscardedValue=*/false);
if (Tail.isUsable()) {
@ -3454,8 +3467,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ColonLoc = ConsumeToken();
TPA.Commit();
} else {
// colon not found, no allocator specified, parse only list of
// variables.
// Colon not found, parse only list of variables.
TPA.Revert();
}
} else {
@ -3524,7 +3536,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (!T.consumeClose())
Data.RLoc = T.getCloseLocation();
// Exit from scope when the iterator is used in depend clause.
if (DependWithIterator)
if (HasIterator)
ExitScope();
return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
(MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||

View File

@ -18,6 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
@ -5414,6 +5415,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
continue;
case OMPC_allocator:
case OMPC_flush:
@ -11547,6 +11549,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@ -12301,6 +12304,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Unexpected OpenMP clause.");
}
return CaptureRegion;
@ -12740,6 +12744,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@ -12966,6 +12971,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@ -13199,6 +13205,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@ -13415,6 +13422,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_exclusive:
Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_affinity:
Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
DepModOrTailExpr, VarList);
break;
case OMPC_if:
case OMPC_depobj:
case OMPC_final:
@ -18785,3 +18796,42 @@ OMPClause *Sema::ActOnOpenMPUsesAllocatorClause(
return OMPUsesAllocatorsClause::Create(Context, StartLoc, LParenLoc, EndLoc,
NewData);
}
OMPClause *Sema::ActOnOpenMPAffinityClause(
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : Locators) {
assert(RefExpr && "NULL expr in OpenMP shared clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
continue;
}
SourceLocation ELoc = RefExpr->getExprLoc();
Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
if (!SimpleExpr->isLValue()) {
Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
<< 1 << 0 << RefExpr->getSourceRange();
continue;
}
ExprResult Res;
{
Sema::TentativeAnalysisScope Trap(*this);
Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
}
if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
!isa<OMPArrayShapingExpr>(SimpleExpr)) {
Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
<< 1 << 0 << RefExpr->getSourceRange();
continue;
}
Vars.push_back(SimpleExpr);
}
return OMPAffinityClause::Create(Context, StartLoc, LParenLoc, ColonLoc,
EndLoc, Modifier, Vars);
}

View File

@ -2107,6 +2107,19 @@ public:
Data);
}
/// Build a new OpenMP 'affinity' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPAffinityClause(SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc,
SourceLocation EndLoc, Expr *Modifier,
ArrayRef<Expr *> Locators) {
return getSema().ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc,
EndLoc, Modifier, Locators);
}
/// Build a new OpenMP 'order' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@ -9813,6 +9826,28 @@ OMPClause *TreeTransform<Derived>::TransformOMPUsesAllocatorsClause(
Data, C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPAffinityClause(OMPAffinityClause *C) {
SmallVector<Expr *, 4> Locators;
Locators.reserve(C->varlist_size());
ExprResult ModifierRes;
if (Expr *Modifier = C->getModifier()) {
ModifierRes = getDerived().TransformExpr(Modifier);
if (ModifierRes.isInvalid())
return nullptr;
}
for (Expr *E : C->varlists()) {
ExprResult Locator = getDerived().TransformExpr(E);
if (Locator.isInvalid())
continue;
Locators.push_back(Locator.get());
}
return getDerived().RebuildOMPAffinityClause(
C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), C->getEndLoc(),
ModifierRes.get(), Locators);
}
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPOrderClause(OMPOrderClause *C) {
return getDerived().RebuildOMPOrderClause(C->getKind(), C->getKindKwLoc(),

View File

@ -11951,6 +11951,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_uses_allocators:
C = OMPUsesAllocatorsClause::CreateEmpty(Context, Record.readInt());
break;
case llvm::omp::OMPC_affinity:
C = OMPAffinityClause::CreateEmpty(Context, Record.readInt());
break;
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
case llvm::omp::Enum: \
break;
@ -12794,6 +12797,18 @@ void OMPClauseReader::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {
C->setAllocatorsData(Data);
}
void OMPClauseReader::VisitOMPAffinityClause(OMPAffinityClause *C) {
C->setLParenLoc(Record.readSourceLocation());
C->setModifier(Record.readSubExpr());
C->setColonLoc(Record.readSourceLocation());
unsigned NumOfLocators = C->varlist_size();
SmallVector<Expr *, 4> Locators;
Locators.reserve(NumOfLocators);
for (unsigned I = 0; I != NumOfLocators; ++I)
Locators.push_back(Record.readSubExpr());
C->setVarRefs(Locators);
}
void OMPClauseReader::VisitOMPOrderClause(OMPOrderClause *C) {
C->setKind(Record.readEnum<OpenMPOrderClauseKind>());
C->setLParenLoc(Record.readSourceLocation());

View File

@ -6704,6 +6704,15 @@ void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {
}
}
void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) {
Record.push_back(C->varlist_size());
Record.AddSourceLocation(C->getLParenLoc());
Record.AddStmt(C->getModifier());
Record.AddSourceLocation(C->getColonLoc());
for (Expr *E : C->varlists())
Record.AddStmt(E);
}
void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {
writeUInt32(TI->Sets.size());
for (const auto &Set : TI->Sets) {

View File

@ -0,0 +1,75 @@
// RUN: %clang_cc1 -verify -fopenmp-version=50 -fopenmp -ferror-limit 100 -o - -std=c++11 %s
// RUN: %clang_cc1 -verify -fopenmp-version=50 -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s
void foo() {
}
bool foobool(int argc) {
return argc;
}
struct S1; // expected-note {{declared here}}
class vector {
public:
int operator[](int index) { return 0; }
};
int main(int argc, char **argv, char *env[]) {
vector vec;
typedef float V __attribute__((vector_size(16)));
V a;
auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
#pragma omp task affinity(arr[0])
#pragma omp task affinity // expected-error {{expected '(' after 'affinity'}}
#pragma omp task affinity ( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
#pragma omp task affinity () // expected-error {{expected expression}}
#pragma omp task affinity (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task affinity (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
#pragma omp task affinity (foobool(argc)), affinity (in, argc) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} expected-error {{use of undeclared identifier 'in'}}
#pragma omp task affinity (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp task affinity(argv[1][1] = '2')
#pragma omp task affinity (vec[1]) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}}
#pragma omp task affinity (in: argv[0]) // expected-error {{use of undeclared identifier 'in'}}
#pragma omp task affinity (main)
#pragma omp task affinity(a[0]) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}}
#pragma omp task affinity (vec[1:2]) // expected-error {{ value is not an array or pointer}}
#pragma omp task affinity (argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp task affinity (argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp task affinity (argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task affinity (argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp task affinity (argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task affinity (argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp task affinity (argv[-1:0])
#pragma omp task affinity (argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp task affinity (argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
#pragma omp task affinity(a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp task affinity(argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp task affinity(argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp task affinity(env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
#pragma omp task affinity(argv[ : argc][1 : argc - 1])
#pragma omp task affinity(arr[0])
#pragma omp task affinity(([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task affinity(([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task affinity(([]) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}}
#pragma omp task affinity(([])a // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
#pragma omp task affinity(([])a) // expected-error {{expected expression}}
#pragma omp task affinity(([a])a) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
#pragma omp task affinity(([a])argc) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
#pragma omp task affinity(([-1][0])argv) // expected-error {{array shaping dimension is evaluated to a non-positive value -1}} expected-error {{array shaping dimension is evaluated to a non-positive value 0}}
#pragma omp task affinity(iterator // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '(' after 'iterator'}} expected-error {{expected expression}}
#pragma omp task affinity(iterator():argc)
#pragma omp task affinity(iterator(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown type name 'argc'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
#pragma omp task affinity(iterator(unsigned argc: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '=' in iterator specifier}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
#pragma omp task affinity(iterator(unsigned argc = // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
#pragma omp task affinity(iterator(vector argc = 0:2):argc) // expected-error {{expected integral or pointer type as the iterator-type, not 'vector'}} expected-error {{expected expression}}
#pragma omp task affinity(iterator(vector *argc = nullptr:nullptr+2:0):argc) // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} expected-error {{iterator step expression 0 evaluates to 0}} expected-error {{expected expression}}
#pragma omp task affinity(iterator(vector *argc = 0:vector():argc):argc) // expected-error {{converting 'vector' to incompatible type 'vector *'}} expected-error {{expected expression}}
foo();
#pragma omp task affinity(iterator(i = 0:10, i = 0:10) : argv[i]) // expected-error {{redefinition of 'i'}} expected-note {{previous definition is here}}
i = 0; // expected-error {{use of undeclared identifier 'i'}}
return 0;
}

View File

@ -34,7 +34,7 @@ public:
omp_depend_t x;
omp_event_handle_t evt;
#pragma omp taskgroup allocate(b) task_reduction(+:b)
#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b) allocate(b) depend(depobj:x) detach(evt) depend(iterator(i=0:10:1, T *k = &a:&b), in: c[i], d[(int)(k-&a)])
#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b) allocate(b) depend(depobj:x) detach(evt) depend(iterator(i=0:10:1, T *k = &a:&b), in: c[i], d[(int)(k-&a)]) affinity(iterator(i=0:10:1, T *k = &a:&b): c[i], d[(int)(k-&a)])
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
@ -47,9 +47,9 @@ public:
};
// CHECK: #pragma omp taskgroup allocate(this->b) task_reduction(+: this->b)
// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10:1, T * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)]){{$}}
// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10:1, T * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)]) affinity(iterator(int i = 0:10:1, T * k = &this->a:&this->b) : this->c[i],this->d[(int)(k - &this->a)]){{$}}
// CHECK: #pragma omp task private(this->a) private(this->a)
// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10:1, S1 * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)])
// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10:1, S1 * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)]) affinity(iterator(int i = 0:10:1, S1 * k = &this->a:&this->b) : this->c[i],this->d[(int)(k - &this->a)])
class S8 : public S7<S1> {
S8() {}
@ -101,7 +101,7 @@ T tmain(T argc, T *argv) {
omp_event_handle_t evt;
#pragma omp task untied depend(in : argc, argv[b:argc], arr[:], ([argc][sizeof(T)])argv) if (task : argc > 0) depend(depobj: x) detach(evt)
a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0) priority(argc)
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0) priority(argc) affinity(argc, argv[b:argc], arr[:], ([argc][sizeof(T)])argv)
foo();
#pragma omp taskgroup task_reduction(-: argc)
#pragma omp task if (C) mergeable priority(C) in_reduction(-: argc)
@ -118,7 +118,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: omp_event_handle_t evt;
// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(T)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0) priority(argc)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0) priority(argc) affinity(argc,argv[b:argc],arr[:],([argc][sizeof(T)])argv)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
// CHECK-NEXT: #pragma omp task if(C) mergeable priority(C) in_reduction(-: argc)
@ -132,7 +132,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: omp_event_handle_t evt;
// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(int)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<int>::TS > 0) priority(argc)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<int>::TS > 0) priority(argc) affinity(argc,argv[b:argc],arr[:],([argc][sizeof(int)])argv)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
// CHECK-NEXT: #pragma omp task if(5) mergeable priority(5) in_reduction(-: argc)
@ -146,7 +146,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: omp_event_handle_t evt;
// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(long)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<long>::TS > 0) priority(argc)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<long>::TS > 0) priority(argc) affinity(argc,argv[b:argc],arr[:],([argc][sizeof(long)])argv)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
// CHECK-NEXT: #pragma omp task if(1) mergeable priority(1) in_reduction(-: argc)

View File

@ -2508,6 +2508,11 @@ void OMPClauseEnqueue::VisitOMPUsesAllocatorsClause(
Visitor->AddStmt(D.AllocatorTraits);
}
}
void OMPClauseEnqueue::VisitOMPAffinityClause(const OMPAffinityClause *C) {
Visitor->AddStmt(C->getModifier());
for (const Expr *E : C->varlists())
Visitor->AddStmt(E);
}
} // namespace
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {

View File

@ -197,6 +197,7 @@ __OMP_CLAUSE(detach, OMPDetachClause)
__OMP_CLAUSE(inclusive, OMPInclusiveClause)
__OMP_CLAUSE(exclusive, OMPExclusiveClause)
__OMP_CLAUSE(uses_allocators, OMPUsesAllocatorsClause)
__OMP_CLAUSE(affinity, OMPAffinityClause)
__OMP_CLAUSE_NO_CLASS(uniform)
__OMP_CLAUSE_NO_CLASS(device_type)
@ -865,6 +866,7 @@ __OMP_DIRECTIVE_CLAUSE(task, 1, ~0, priority)
__OMP_DIRECTIVE_CLAUSE(task, 1, ~0, in_reduction)
__OMP_DIRECTIVE_CLAUSE(task, 1, ~0, allocate)
__OMP_DIRECTIVE_CLAUSE(task, 50, ~0, detach)
__OMP_DIRECTIVE_CLAUSE(task, 50, ~0, affinity)
__OMP_DIRECTIVE_CLAUSE(atomic, 1, ~0, read)
__OMP_DIRECTIVE_CLAUSE(atomic, 1, ~0, write)