forked from OSchip/llvm-project
[OPENMP50]Initial support for detach clause in task directive.
Added parsing/sema/serialization support for detach clause.
This commit is contained in:
parent
211ba00ce0
commit
0f0564bb9a
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) { }
|
||||
|
|
|
@ -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: \
|
||||
|
|
|
@ -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'.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 *) {}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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 *) {}
|
||||
|
|
Loading…
Reference in New Issue