50 changes: 50 additions & 0 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
35 changes: 35 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,19 @@ class TreeTransform {
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.
Expand Down Expand Up @@ -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(),
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
75 changes: 75 additions & 0 deletions clang/test/OpenMP/task_affinity_messages.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
14 changes: 7 additions & 7 deletions clang/test/OpenMP/task_ast_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class S7 : public T {
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;
}
Expand All @@ -47,9 +47,9 @@ class S7 : public T {
};

// 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() {}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down