[OPENMP50]Initial support for detach clause in task directive.

Added parsing/sema/serialization support for detach clause.
This commit is contained in:
Alexey Bataev 2020-03-17 09:17:42 -04:00
parent 211ba00ce0
commit 0f0564bb9a
17 changed files with 296 additions and 18 deletions

View File

@ -6827,6 +6827,68 @@ public:
}
};
/// 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>

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -10364,6 +10364,10 @@ public:
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,

View File

@ -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,

View File

@ -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) { }

View File

@ -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: \

View File

@ -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'.");
}
}

View File

@ -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();

View File

@ -270,6 +270,8 @@ private:
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 @@ public:
/// 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,

View File

@ -1950,6 +1950,16 @@ public:
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 different 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) {

View File

@ -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 *) {}

View File

@ -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());

View File

@ -11,6 +11,7 @@
#define HEADER
typedef void *omp_depend_t;
typedef unsigned long omp_event_handle_t;
void foo() {}
@ -31,8 +32,9 @@ protected:
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 @@ 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){{$}}
// 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)

View File

@ -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@+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 @@ L2:
// expected-error@+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@+2 {{in instantiation of function template specialization 'foo<int>' requested here}}
// expected-note@+1 {{in instantiation of function template specialization 'foo<S>' requested here}}
return foo<int>() + foo<S>();

View File

@ -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 *) {}