[clang] 0f0564b - [OPENMP50]Initial support for detach clause in task directive.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 17 06:47:36 PDT 2020
Author: Alexey Bataev
Date: 2020-03-17T09:19:03-04:00
New Revision: 0f0564bb9a3ca4527eb2333eba34643e05c315ca
URL: https://github.com/llvm/llvm-project/commit/0f0564bb9a3ca4527eb2333eba34643e05c315ca
DIFF: https://github.com/llvm/llvm-project/commit/0f0564bb9a3ca4527eb2333eba34643e05c315ca.diff
LOG: [OPENMP50]Initial support for detach clause in task directive.
Added parsing/sema/serialization support for detach clause.
Added:
Modified:
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/OpenMPKinds.def
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/test/OpenMP/task_messages.cpp
clang/tools/libclang/CIndex.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 086c6a232de7..79f43fc8ab88 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -6827,6 +6827,68 @@ class OMPDestroyClause final : public OMPClause {
}
};
+/// This represents 'detach' clause in the '#pragma omp task' directive.
+///
+/// \code
+/// #pragma omp task detach(evt)
+/// \endcode
+/// In this example directive '#pragma omp detach' has simple 'detach' clause
+/// with the variable 'evt'.
+class OMPDetachClause final : public OMPClause {
+ friend class OMPClauseReader;
+
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+ /// Expression of the 'detach' clause.
+ Stmt *Evt = nullptr;
+
+ /// Set condition.
+ void setEventHandler(Expr *E) { Evt = E; }
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+public:
+ /// Build 'detach' clause with event-handler \a Evt.
+ ///
+ /// \param Evt Event handler expression.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ OMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_detach, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Evt(Evt) {}
+
+ /// Build an empty clause.
+ OMPDetachClause()
+ : OMPClause(OMPC_detach, SourceLocation(), SourceLocation()) {}
+
+ /// Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// Returns event-handler expression.
+ Expr *getEventHandler() const { return cast_or_null<Expr>(Evt); }
+
+ child_range children() { return child_range(&Evt, &Evt + 1); }
+
+ const_child_range children() const {
+ return const_child_range(&Evt, &Evt + 1);
+ }
+
+ 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() == OMPC_detach;
+ }
+};
+
/// 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 ce66eeef7a82..27a0bc774184 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3488,6 +3488,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPOrderClause(OMPOrderClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDetachClause(OMPDetachClause *C) {
+ TRY_TO(TraverseStmt(C->getEventHandler()));
+ 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/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 77df05fbaf05..a11365130734 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9976,9 +9976,9 @@ def err_omp_wrong_ordered_loop_count : Error<
"the parameter of the 'ordered' clause must be greater than or equal to the parameter of the 'collapse' clause">;
def note_collapse_loop_count : Note<
"parameter of the 'collapse' clause">;
-def err_omp_grainsize_num_tasks_mutually_exclusive : Error<
+def err_omp_clauses_mutually_exclusive : Error<
"'%0' and '%1' clause are mutually exclusive and may not appear on the same directive">;
-def note_omp_previous_grainsize_num_tasks : Note<
+def note_omp_previous_clause : Note<
"'%0' clause is specified here">;
def err_omp_hint_clause_no_name : Error<
"the name of the construct must be specified in presence of 'hint' clause">;
@@ -10150,6 +10150,8 @@ def note_omp_flush_order_clause_here : Note<
def err_omp_non_lvalue_in_map_or_motion_clauses: Error<
"expected addressable lvalue in '%0' clause"
>;
+def err_omp_event_var_expected : Error<
+ "expected variable of the 'omp_event_handle_t' type%select{|, not %1}0">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 70f962427e36..e6a4aa1d1f58 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -277,6 +277,7 @@ OPENMP_CLAUSE(nontemporal, OMPNontemporalClause)
OPENMP_CLAUSE(order, OMPOrderClause)
OPENMP_CLAUSE(depobj, OMPDepobjClause)
OPENMP_CLAUSE(destroy, OMPDestroyClause)
+OPENMP_CLAUSE(detach, OMPDetachClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@@ -471,6 +472,7 @@ OPENMP_TASK_CLAUSE(depend)
OPENMP_TASK_CLAUSE(priority)
OPENMP_TASK_CLAUSE(in_reduction)
OPENMP_TASK_CLAUSE(allocate)
+OPENMP_TASK_CLAUSE(detach)
// Clauses allowed for OpenMP directive 'atomic'.
OPENMP_ATOMIC_CLAUSE(read)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 121ceb7e5d36..f29e4f3c227c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10364,6 +10364,10 @@ class Sema final {
OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'detach' clause.
+ OMPClause *ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index e68a5d6820a9..b01aae433763 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -145,6 +145,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
break;
}
@@ -231,6 +232,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
break;
}
@@ -1294,6 +1296,12 @@ void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPDetachClause(OMPDetachClause *Node) {
+ OS << "detach(";
+ Node->getEventHandler()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
OS << "default("
<< getOpenMPSimpleClauseTypeName(OMPC_default,
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 9f1198370235..8d43491ea8f4 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -472,6 +472,11 @@ void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) {
Profiler->VisitStmt(C->getNumForLoops());
}
+void OMPClauseProfiler::VisitOMPDetachClause(const OMPDetachClause *C) {
+ if (Expr *Evt = C->getEventHandler())
+ Profiler->VisitStmt(Evt);
+}
+
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 5ecc24647e7c..a6e2b9dbf1a1 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -207,6 +207,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_match:
case OMPC_nontemporal:
case OMPC_destroy:
+ case OMPC_detach:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -432,6 +433,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_match:
case OMPC_nontemporal:
case OMPC_destroy:
+ case OMPC_detach:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -554,6 +556,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
}
break;
case OMPD_task:
+ if (OpenMPVersion < 50 && CKind == OMPC_detach)
+ return false;
switch (CKind) {
#define OPENMP_TASK_CLAUSE(Name) \
case OMPC_##Name: \
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index e3dd49021644..74fabb1ba04e 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4615,6 +4615,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 1da884f657a0..86c5996683bd 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2340,7 +2340,7 @@ bool Parser::ParseOpenMPSimpleVarList(
/// from-clause | is_device_ptr-clause | task_reduction-clause |
/// in_reduction-clause | allocator-clause | allocate-clause |
/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
-/// depobj-clause | destroy-clause
+/// depobj-clause | destroy-clause | detach-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -2372,6 +2372,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_hint:
case OMPC_allocator:
case OMPC_depobj:
+ case OMPC_detach:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -2394,6 +2395,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// 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.
+ // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
+ // At most one detach clause can appear on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@@ -2552,7 +2555,8 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// Parsing of OpenMP clauses with single expressions like 'final',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
-/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
+/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
+/// 'detach'.
///
/// final-clause:
/// 'final' '(' expression ')'
@@ -2584,6 +2588,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// allocator-clause:
/// 'allocator' '(' expression ')'
///
+/// detach-clause:
+/// 'detach' '(' event-handler-expression ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
bool ParseOnly) {
SourceLocation Loc = ConsumeToken();
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 898f658fcf9c..825dac9f14c8 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -270,6 +270,8 @@ class DSAStackTy {
QualType OMPAllocatorHandleT;
/// omp_depend_t type.
QualType OMPDependT;
+ /// omp_event_handle_t type.
+ QualType OMPEventHandleT;
/// Expression for the predefined allocators.
Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
nullptr};
@@ -298,6 +300,11 @@ class DSAStackTy {
/// Gets omp_depend_t type.
QualType getOMPDependT() const { return OMPDependT; }
+ /// Sets omp_event_handle_t type.
+ void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
+ /// Gets omp_event_handle_t type.
+ QualType getOMPEventHandleT() const { return OMPEventHandleT; }
+
bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
OpenMPClauseKind getClauseParsingMode() const {
assert(isClauseParsingMode() && "Must be in clause parsing mode.");
@@ -5090,6 +5097,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
break;
continue;
case OMPC_schedule:
+ case OMPC_detach:
break;
case OMPC_grainsize:
case OMPC_num_tasks:
@@ -8619,12 +8627,41 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Context, StartLoc, EndLoc, Clauses, AStmt, DSAStack->isCancelRegion());
}
+/// detach and mergeable clauses are mutially exclusive, check for it.
+static bool checkDetachMergeableClauses(Sema &S,
+ ArrayRef<OMPClause *> Clauses) {
+ const OMPClause *PrevClause = nullptr;
+ bool ErrorFound = false;
+ for (const OMPClause *C : Clauses) {
+ if (C->getClauseKind() == OMPC_detach ||
+ C->getClauseKind() == OMPC_mergeable) {
+ if (!PrevClause) {
+ PrevClause = C;
+ } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
+ S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
+ << getOpenMPClauseName(C->getClauseKind())
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
+ << getOpenMPClauseName(PrevClause->getClauseKind());
+ ErrorFound = true;
+ }
+ }
+ }
+ return ErrorFound;
+}
+
StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
if (!AStmt)
return StmtError();
+ // OpenMP 5.0, 2.10.1 task Construct
+ // If a detach clause appears on the directive, then a mergeable clause cannot
+ // appear on the same directive.
+ if (checkDetachMergeableClauses(*this, Clauses))
+ return StmtError();
+
auto *CS = cast<CapturedStmt>(AStmt);
// 1.2.2 OpenMP Language Terminology
// Structured block - An executable statement with a single entry at the
@@ -9884,12 +9921,10 @@ static bool checkGrainsizeNumTasksClauses(Sema &S,
if (!PrevClause)
PrevClause = C;
else if (PrevClause->getClauseKind() != C->getClauseKind()) {
- S.Diag(C->getBeginLoc(),
- diag::err_omp_grainsize_num_tasks_mutually_exclusive)
+ S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
<< getOpenMPClauseName(C->getClauseKind())
<< getOpenMPClauseName(PrevClause->getClauseKind());
- S.Diag(PrevClause->getBeginLoc(),
- diag::note_omp_previous_grainsize_num_tasks)
+ S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
<< getOpenMPClauseName(PrevClause->getClauseKind());
ErrorFound = true;
}
@@ -11027,6 +11062,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_depobj:
Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_detach:
+ Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
@@ -11806,6 +11844,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
llvm_unreachable("Unexpected OpenMP clause.");
}
return CaptureRegion;
@@ -12242,6 +12281,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_match:
case OMPC_nontemporal:
case OMPC_destroy:
+ case OMPC_detach:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12459,6 +12499,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12688,6 +12729,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_match:
case OMPC_nontemporal:
case OMPC_order:
+ case OMPC_detach:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12943,6 +12985,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_match:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_detach:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -17266,6 +17309,56 @@ OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
}
+/// Tries to find omp_event_handle_t type.
+static bool findOMPEventHandleT(Sema &S, SourceLocation Loc,
+ DSAStackTy *Stack) {
+ QualType OMPEventHandleT = Stack->getOMPEventHandleT();
+ if (!OMPEventHandleT.isNull())
+ return true;
+ IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
+ ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
+ if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
+ S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
+ return false;
+ }
+ Stack->setOMPEventHandleT(PT.get());
+ return true;
+}
+
+OMPClause *Sema::ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
+ !Evt->isInstantiationDependent() &&
+ !Evt->containsUnexpandedParameterPack()) {
+ if (!findOMPEventHandleT(*this, Evt->getExprLoc(), DSAStack))
+ return nullptr;
+ // OpenMP 5.0, 2.10.1 task Construct.
+ // event-handle is a variable of the omp_event_handle_t type.
+ auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
+ if (!Ref) {
+ Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
+ << 0 << Evt->getSourceRange();
+ return nullptr;
+ }
+ auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
+ if (!VD) {
+ Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
+ << 0 << Evt->getSourceRange();
+ return nullptr;
+ }
+ if (!Context.hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
+ VD->getType()) ||
+ VD->getType().isConstant(Context)) {
+ Diag(Evt->getExprLoc(), diag::err_omp_event_var_expected)
+ << 1 << VD->getType() << Evt->getSourceRange();
+ return nullptr;
+ }
+ }
+
+ return new (Context) OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPDistScheduleClause(
OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 97600dcc7a84..c7e90ad982ef 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1950,6 +1950,16 @@ class TreeTransform {
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
}
+ /// Build a new OpenMP 'detach' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide
diff erent behavior.
+ OMPClause *RebuildOMPDetachClause(Expr *Evt, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
+ }
+
/// Build a new OpenMP 'dist_schedule' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -8779,6 +8789,19 @@ TreeTransform<Derived>::TransformOMPOrderedClause(OMPOrderedClause *C) {
C->getLParenLoc(), E.get());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDetachClause(OMPDetachClause *C) {
+ ExprResult E;
+ if (Expr *Evt = C->getEventHandler()) {
+ E = getDerived().TransformExpr(Evt);
+ if (E.isInvalid())
+ return nullptr;
+ }
+ return getDerived().RebuildOMPDetachClause(E.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
+}
+
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPNowaitClause(OMPNowaitClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 096a741e7bb9..9f6bfebeabcb 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11830,6 +11830,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_destroy:
C = new (Context) OMPDestroyClause();
break;
+ case OMPC_detach:
+ C = new (Context) OMPDetachClause();
+ break;
}
assert(C && "Unknown OMPClause type");
@@ -11928,6 +11931,11 @@ void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPDetachClause(OMPDetachClause *C) {
+ C->setEventHandler(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1278841a15a2..b549fe9df016 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6096,6 +6096,11 @@ void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPDetachClause(OMPDetachClause *C) {
+ Record.AddStmt(C->getEventHandler());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Record.push_back(unsigned(C->getDefaultKind()));
Record.AddSourceLocation(C->getLParenLoc());
diff --git a/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp
index f8a669523a5a..73323c6c2ae5 100644
--- a/clang/test/OpenMP/task_ast_print.cpp
+++ b/clang/test/OpenMP/task_ast_print.cpp
@@ -11,6 +11,7 @@
#define HEADER
typedef void *omp_depend_t;
+typedef unsigned long omp_event_handle_t;
void foo() {}
@@ -31,8 +32,9 @@ class S7 : public T {
public:
S7(typename T::type v) : a(v) {
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)
+#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b) allocate(b) depend(depobj:x) detach(evt)
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
@@ -45,7 +47,7 @@ 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){{$}}
+// 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){{$}}
// CHECK: #pragma omp task private(this->a) private(this->a)
// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
@@ -96,7 +98,8 @@ T tmain(T argc, T *argv) {
S<T> s;
T arr[argc];
omp_depend_t x;
-#pragma omp task untied depend(in : argc, argv[b:argc], arr[:]) if (task : argc > 0) depend(depobj: x)
+ omp_event_handle_t evt;
+#pragma omp task untied depend(in : argc, argv[b:argc], arr[:]) 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)
foo();
@@ -112,7 +115,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: T arr[argc];
// CHECK-NEXT: omp_depend_t x;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x)
+// CHECK-NEXT: omp_event_handle_t evt;
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) 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: foo()
@@ -125,7 +129,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<int> s;
// CHECK-NEXT: int arr[argc];
// CHECK-NEXT: omp_depend_t x;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x)
+// CHECK-NEXT: omp_event_handle_t evt;
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) 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: foo()
@@ -138,7 +143,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<long> s;
// CHECK-NEXT: long arr[argc];
// CHECK-NEXT: omp_depend_t x;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x)
+// CHECK-NEXT: omp_event_handle_t evt;
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) 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: foo()
@@ -154,6 +160,7 @@ int main(int argc, char **argv) {
static int a;
int arr[10], arr1[argc];
omp_depend_t y;
+ omp_event_handle_t evt;
#pragma omp threadprivate(a)
Enum ee;
// CHECK: Enum ee;
@@ -162,9 +169,9 @@ int main(int argc, char **argv) {
a = 2;
// CHECK-NEXT: a = 2;
#pragma omp taskgroup task_reduction(min: arr1)
-#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1)
+#pragma omp task default(none), private(argc, b) firstprivate(argv, evt) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1), detach(evt)
// CHECK-NEXT: #pragma omp taskgroup task_reduction(min: arr1)
- // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1)
+ // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv,evt) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1) detach(evt)
foo();
// CHECK-NEXT: foo();
#pragma omp taskgroup task_reduction(min: arr1)
diff --git a/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp
index 062125f5f6ea..cec3bc0c1980 100644
--- a/clang/test/OpenMP/task_messages.cpp
+++ b/clang/test/OpenMP/task_messages.cpp
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
void xxx(int argc) {
int x; // expected-note {{initialize the variable 'x' to silence this warning}}
@@ -9,8 +11,12 @@ void xxx(int argc) {
}
void foo() {
+#pragma omp task detach(0) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'omp_event_handle_t' type not found; include <omp.h>}}
+ ;
}
+typedef unsigned long omp_event_handle_t;
+
#pragma omp task // expected-error {{unexpected OpenMP directive '#pragma omp task'}}
class S {
@@ -125,6 +131,22 @@ int foo() {
// expected-error at +1 {{directive '#pragma omp task' cannot contain more than one 'mergeable' clause}}
#pragma omp task mergeable mergeable
++r;
+ volatile omp_event_handle_t evt;
+ const omp_event_handle_t cevt = 0;
+ omp_event_handle_t sevt;
+ omp_event_handle_t &revt = sevt;
+#pragma omp task detach // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected '(' after 'detach'}}
+#pragma omp task detach( // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task detach() // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected expression}}
+#pragma omp task detach(a) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'int'}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'S'}}
+ ;
+#pragma omp task detach(evt) detach(evt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}}
+#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'const omp_event_handle_t' (aka 'const unsigned long')}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'omp_event_handle_t &' (aka 'unsigned long &')}}
+#pragma omp task detach(evt) mergeable // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'mergeable' and 'detach' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'detach' clause is specified here}}
+ ;
+#pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and 'mergeable' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'mergeable' clause is specified here}}
+#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type}}
+ ;
return a + b;
}
@@ -290,6 +312,21 @@ int main(int argc, char **argv) {
// expected-error at +1 {{directive '#pragma omp task' cannot contain more than one 'mergeable' clause}}
#pragma omp task mergeable mergeable
++r;
+ volatile omp_event_handle_t evt;
+ omp_event_handle_t sevt;
+ const omp_event_handle_t cevt = evt;
+ omp_event_handle_t &revt = sevt;
+#pragma omp task detach // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected '(' after 'detach'}}
+#pragma omp task detach( // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task detach() // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{expected expression}}
+#pragma omp task detach(a) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'int'}}
+#pragma omp task detach(evt) detach(evt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}}
+#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'const omp_event_handle_t' (aka 'const unsigned long')}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'omp_event_handle_t &' (aka 'unsigned long &')}}
+#pragma omp task detach(evt) mergeable // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'mergeable' and 'detach' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'detach' clause is specified here}}
+ ;
+#pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and 'mergeable' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'mergeable' clause is specified here}}
+#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type}}
+ ;
// expected-note at +2 {{in instantiation of function template specialization 'foo<int>' requested here}}
// expected-note at +1 {{in instantiation of function template specialization 'foo<S>' requested here}}
return foo<int>() + foo<S>();
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 62dc0e2b8f92..df5530c73c6d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2220,6 +2220,10 @@ void OMPClauseEnqueue::VisitOMPOrderedClause(const OMPOrderedClause *C) {
Visitor->AddStmt(C->getNumForLoops());
}
+void OMPClauseEnqueue::VisitOMPDetachClause(const OMPDetachClause *C) {
+ Visitor->AddStmt(C->getEventHandler());
+}
+
void OMPClauseEnqueue::VisitOMPNowaitClause(const OMPNowaitClause *) {}
void OMPClauseEnqueue::VisitOMPUntiedClause(const OMPUntiedClause *) {}
More information about the cfe-commits
mailing list