@@ -2739,6 +2739,59 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
2739
2739
llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
2740
2740
}
2741
2741
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
+
2742
2795
auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
2743
2796
llvmOmpClause clauseTy) {
2744
2797
if (sym.test (Symbol::Flag::OmpThreadprivate))
@@ -2823,7 +2876,6 @@ CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
2823
2876
CHECK_SIMPLE_CLAUSE (Contains, OMPC_contains)
2824
2877
CHECK_SIMPLE_CLAUSE (Default, OMPC_default)
2825
2878
CHECK_SIMPLE_CLAUSE (Depobj, OMPC_depobj)
2826
- CHECK_SIMPLE_CLAUSE (Detach, OMPC_detach)
2827
2879
CHECK_SIMPLE_CLAUSE (DeviceType, OMPC_device_type)
2828
2880
CHECK_SIMPLE_CLAUSE (DistSchedule, OMPC_dist_schedule)
2829
2881
CHECK_SIMPLE_CLAUSE (Exclusive, OMPC_exclusive)
@@ -3352,40 +3404,45 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
3352
3404
const parser::CharBlock &source, const parser::OmpObjectList &objList,
3353
3405
llvm::StringRef clause) {
3354
3406
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 )) {
3361
3428
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 "
3363
3431
" directive" _err_en_US,
3364
3432
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 ());
3382
3439
}
3383
3440
}
3384
- },
3385
- [&]( const parser::Name &name) { },
3386
- },
3387
- ompObject. u );
3388
- }
3441
+ }
3442
+ },
3443
+ [&]( const parser::Name &name) { },
3444
+ },
3445
+ ompObject. u );
3389
3446
}
3390
3447
3391
3448
void OmpStructureChecker::Enter (const parser::OmpClause::Firstprivate &x) {
@@ -3711,6 +3768,30 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
3711
3768
x.v .u );
3712
3769
}
3713
3770
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
+
3714
3795
void OmpStructureChecker::CheckAllowedMapTypes (
3715
3796
const parser::OmpMapType::Value &type,
3716
3797
const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
0 commit comments