@@ -2739,6 +2739,59 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
27392739 llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
27402740 }
27412741
2742+ if (GetContext ().directive == llvm::omp::Directive::OMPD_task) {
2743+ if (auto *d_clause{FindClause (llvm::omp::Clause::OMPC_detach)}) {
2744+ // OpenMP 5.0: Task construct restrictions
2745+ CheckNotAllowedIfClause (
2746+ llvm::omp::Clause::OMPC_detach, {llvm::omp::Clause::OMPC_mergeable});
2747+
2748+ // OpenMP 5.2: Task construct restrictions
2749+ if (FindClause (llvm::omp::Clause::OMPC_final)) {
2750+ context_.Say (GetContext ().clauseSource ,
2751+ " If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task" _err_en_US);
2752+ }
2753+
2754+ const auto &detachClause{
2755+ std::get<parser::OmpClause::Detach>(d_clause->u )};
2756+ if (const auto *name{parser::Unwrap<parser::Name>(detachClause.v .v )}) {
2757+ if (name->symbol ) {
2758+ std::string eventHandleSymName{name->ToString ()};
2759+ auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
2760+ &objs,
2761+ std::string clause) {
2762+ for (const auto &obj : objs.v ) {
2763+ if (const parser::Name *objName{
2764+ parser::Unwrap<parser::Name>(obj)}) {
2765+ if (objName->ToString () == eventHandleSymName) {
2766+ context_.Say (GetContext ().clauseSource ,
2767+ " A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct" _err_en_US,
2768+ eventHandleSymName, clause);
2769+ }
2770+ }
2771+ }
2772+ };
2773+ if (auto *dataEnvClause{
2774+ FindClause (llvm::omp::Clause::OMPC_private)}) {
2775+ const auto &pClause{
2776+ std::get<parser::OmpClause::Private>(dataEnvClause->u )};
2777+ checkVarAppearsInDataEnvClause (pClause.v , " PRIVATE" );
2778+ } else if (auto *dataEnvClause{
2779+ FindClause (llvm::omp::Clause::OMPC_firstprivate)}) {
2780+ const auto &fpClause{
2781+ std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u )};
2782+ checkVarAppearsInDataEnvClause (fpClause.v , " FIRSTPRIVATE" );
2783+ } else if (auto *dataEnvClause{
2784+ FindClause (llvm::omp::Clause::OMPC_in_reduction)}) {
2785+ const auto &irClause{
2786+ std::get<parser::OmpClause::InReduction>(dataEnvClause->u )};
2787+ checkVarAppearsInDataEnvClause (
2788+ std::get<parser::OmpObjectList>(irClause.v .t ), " IN_REDUCTION" );
2789+ }
2790+ }
2791+ }
2792+ }
2793+ }
2794+
27422795 auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
27432796 llvmOmpClause clauseTy) {
27442797 if (sym.test (Symbol::Flag::OmpThreadprivate))
@@ -2823,7 +2876,6 @@ CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
28232876CHECK_SIMPLE_CLAUSE (Contains, OMPC_contains)
28242877CHECK_SIMPLE_CLAUSE (Default, OMPC_default)
28252878CHECK_SIMPLE_CLAUSE (Depobj, OMPC_depobj)
2826- CHECK_SIMPLE_CLAUSE (Detach, OMPC_detach)
28272879CHECK_SIMPLE_CLAUSE (DeviceType, OMPC_device_type)
28282880CHECK_SIMPLE_CLAUSE (DistSchedule, OMPC_dist_schedule)
28292881CHECK_SIMPLE_CLAUSE (Exclusive, OMPC_exclusive)
@@ -3352,40 +3404,45 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
33523404 const parser::CharBlock &source, const parser::OmpObjectList &objList,
33533405 llvm::StringRef clause) {
33543406 for (const auto &ompObject : objList.v ) {
3355- common::visit (
3356- common::visitors{
3357- [&](const parser::Designator &designator) {
3358- if (const auto *dataRef{
3359- std::get_if<parser::DataRef>(&designator.u )}) {
3360- if (IsDataRefTypeParamInquiry (dataRef)) {
3407+ CheckIsVarPartOfAnotherVar (source, ompObject, clause);
3408+ }
3409+ }
3410+
3411+ void OmpStructureChecker::CheckIsVarPartOfAnotherVar (
3412+ const parser::CharBlock &source, const parser::OmpObject &ompObject,
3413+ llvm::StringRef clause) {
3414+ common::visit (
3415+ common::visitors{
3416+ [&](const parser::Designator &designator) {
3417+ if (const auto *dataRef{
3418+ std::get_if<parser::DataRef>(&designator.u )}) {
3419+ if (IsDataRefTypeParamInquiry (dataRef)) {
3420+ context_.Say (source,
3421+ " A type parameter inquiry cannot appear on the %s "
3422+ " directive" _err_en_US,
3423+ ContextDirectiveAsFortran ());
3424+ } else if (parser::Unwrap<parser::StructureComponent>(
3425+ ompObject) ||
3426+ parser::Unwrap<parser::ArrayElement>(ompObject)) {
3427+ if (llvm::omp::nonPartialVarSet.test (GetContext ().directive )) {
33613428 context_.Say (source,
3362- " A type parameter inquiry cannot appear on the %s "
3429+ " A variable that is part of another variable (as an "
3430+ " array or structure element) cannot appear on the %s "
33633431 " directive" _err_en_US,
33643432 ContextDirectiveAsFortran ());
3365- } else if (parser::Unwrap<parser::StructureComponent>(
3366- ompObject) ||
3367- parser::Unwrap<parser::ArrayElement>(ompObject)) {
3368- if (llvm::omp::nonPartialVarSet.test (
3369- GetContext ().directive )) {
3370- context_.Say (source,
3371- " A variable that is part of another variable (as an "
3372- " array or structure element) cannot appear on the %s "
3373- " directive" _err_en_US,
3374- ContextDirectiveAsFortran ());
3375- } else {
3376- context_.Say (source,
3377- " A variable that is part of another variable (as an "
3378- " array or structure element) cannot appear in a "
3379- " %s clause" _err_en_US,
3380- clause.data ());
3381- }
3433+ } else {
3434+ context_.Say (source,
3435+ " A variable that is part of another variable (as an "
3436+ " array or structure element) cannot appear in a "
3437+ " %s clause" _err_en_US,
3438+ clause.data ());
33823439 }
33833440 }
3384- },
3385- [&]( const parser::Name &name) { },
3386- },
3387- ompObject. u );
3388- }
3441+ }
3442+ },
3443+ [&]( const parser::Name &name) { },
3444+ },
3445+ ompObject. u );
33893446}
33903447
33913448void OmpStructureChecker::Enter (const parser::OmpClause::Firstprivate &x) {
@@ -3711,6 +3768,30 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
37113768 x.v .u );
37123769}
37133770
3771+ void OmpStructureChecker::Enter (const parser::OmpClause::Detach &x) {
3772+ // OpenMP 5.0: Task construct restrictions
3773+ CheckAllowedClause (llvm::omp::Clause::OMPC_detach);
3774+
3775+ // OpenMP 5.2: Detach clause restrictions
3776+ CheckIsVarPartOfAnotherVar (GetContext ().clauseSource , x.v .v , " DETACH" );
3777+ if (const auto *name{parser::Unwrap<parser::Name>(x.v .v )}) {
3778+ if (name->symbol ) {
3779+ if (IsPointer (*name->symbol )) {
3780+ context_.Say (GetContext ().clauseSource ,
3781+ " The event-handle: `%s` must not have the POINTER attribute" _err_en_US,
3782+ name->ToString ());
3783+ }
3784+ }
3785+ auto type{name->symbol ->GetType ()};
3786+ if (!name->symbol ->GetType ()->IsNumeric (TypeCategory::Integer) ||
3787+ evaluate::ToInt64 (type->numericTypeSpec ().kind ()) != 8 ) {
3788+ context_.Say (GetContext ().clauseSource ,
3789+ " The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)" _err_en_US,
3790+ name->ToString ());
3791+ }
3792+ }
3793+ }
3794+
37143795void OmpStructureChecker::CheckAllowedMapTypes (
37153796 const parser::OmpMapType::Value &type,
37163797 const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
0 commit comments