[clang] 2e499ee - [OPENMP50]Add initial support for 'affinity' clause.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Tue May 19 05:43:51 PDT 2020
Author: Alexey Bataev
Date: 2020-05-19T08:19:09-04:00
New Revision: 2e499eee5884456f3dd068662ee1785f24bd88cc
URL: https://github.com/llvm/llvm-project/commit/2e499eee5884456f3dd068662ee1785f24bd88cc
DIFF: https://github.com/llvm/llvm-project/commit/2e499eee5884456f3dd068662ee1785f24bd88cc.diff
LOG: [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
Added:
clang/test/OpenMP/task_affinity_messages.cpp
Modified:
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/Basic/OpenMPKinds.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/OpenMP/task_ast_print.cpp
clang/tools/libclang/CIndex.cpp
llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
Removed:
################################################################################
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 0b49209fb127..54e83f461980 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -7252,6 +7252,107 @@ class OMPUsesAllocatorsClause final
}
};
+/// 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>
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 015ec8d80e51..a264d1cf24b2 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -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
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 831ea1f6163c..15a3d411237e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10799,6 +10799,12 @@ class Sema final {
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 {
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index d4d398f43c9d..14c4c78e5f39 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -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) {
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 501c07b9b667..bd2eeb699e65 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -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
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 841d76ba27ed..8dddb66fa322 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -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");
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index ae3094430fdf..f91098d1d345 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -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'.");
}
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 19acfe1158fb..bd40e6b991a5 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -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 ||
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index e03b926bc581..b62fb26f8b49 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -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);
+}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index f8b84c292881..923792fde7fc 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -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
diff erent 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(),
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 3f4164690c78..16bcb18f4e68 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -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());
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index bd7cbfc2a50e..1e3adb588da2 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -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) {
diff --git a/clang/test/OpenMP/task_affinity_messages.cpp b/clang/test/OpenMP/task_affinity_messages.cpp
new file mode 100644
index 000000000000..34ec8d2e1e14
--- /dev/null
+++ b/clang/test/OpenMP/task_affinity_messages.cpp
@@ -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;
+}
diff --git a/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp
index cc569a6aab84..b58dd02b9891 100644
--- a/clang/test/OpenMP/task_ast_print.cpp
+++ b/clang/test/OpenMP/task_ast_print.cpp
@@ -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;
}
@@ -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() {}
@@ -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)
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 589d38fa615a..79a970c229dd 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -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) {
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index 8677b38a9afb..e16e7c6ad1f9 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -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)
More information about the cfe-commits
mailing list