@@ -1605,7 +1605,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &c) {
1605
1605
const auto &dir{std::get<parser::Verbatim>(c.t )};
1606
1606
const auto &objectList{std::get<parser::OmpObjectList>(c.t )};
1607
1607
CheckSymbolNames (dir.source , objectList);
1608
- CheckIsVarPartOfAnotherVar (dir.source , objectList);
1608
+ CheckVarIsNotPartOfAnotherVar (dir.source , objectList);
1609
1609
CheckThreadprivateOrDeclareTargetVar (objectList);
1610
1610
dirContext_.pop_back ();
1611
1611
}
@@ -1746,7 +1746,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) {
1746
1746
for (const auto &clause : clauseList.v ) {
1747
1747
CheckAlignValue (clause);
1748
1748
}
1749
- CheckIsVarPartOfAnotherVar (dir.source , objectList);
1749
+ CheckVarIsNotPartOfAnotherVar (dir.source , objectList);
1750
1750
}
1751
1751
1752
1752
void OmpStructureChecker::Leave (const parser::OpenMPDeclarativeAllocate &x) {
@@ -1912,7 +1912,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
1912
1912
if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u )}) {
1913
1913
deviceConstructFound_ = true ;
1914
1914
CheckSymbolNames (dir.source , *objectList);
1915
- CheckIsVarPartOfAnotherVar (dir.source , *objectList);
1915
+ CheckVarIsNotPartOfAnotherVar (dir.source , *objectList);
1916
1916
CheckThreadprivateOrDeclareTargetVar (*objectList);
1917
1917
} else if (const auto *clauseList{
1918
1918
parser::Unwrap<parser::OmpClauseList>(spec.u )}) {
@@ -1925,18 +1925,18 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
1925
1925
toClauseFound = true ;
1926
1926
auto &objList{std::get<parser::OmpObjectList>(toClause.v .t )};
1927
1927
CheckSymbolNames (dir.source , objList);
1928
- CheckIsVarPartOfAnotherVar (dir.source , objList);
1928
+ CheckVarIsNotPartOfAnotherVar (dir.source , objList);
1929
1929
CheckThreadprivateOrDeclareTargetVar (objList);
1930
1930
},
1931
1931
[&](const parser::OmpClause::Link &linkClause) {
1932
1932
CheckSymbolNames (dir.source , linkClause.v );
1933
- CheckIsVarPartOfAnotherVar (dir.source , linkClause.v );
1933
+ CheckVarIsNotPartOfAnotherVar (dir.source , linkClause.v );
1934
1934
CheckThreadprivateOrDeclareTargetVar (linkClause.v );
1935
1935
},
1936
1936
[&](const parser::OmpClause::Enter &enterClause) {
1937
1937
enterClauseFound = true ;
1938
1938
CheckSymbolNames (dir.source , enterClause.v );
1939
- CheckIsVarPartOfAnotherVar (dir.source , enterClause.v );
1939
+ CheckVarIsNotPartOfAnotherVar (dir.source , enterClause.v );
1940
1940
CheckThreadprivateOrDeclareTargetVar (enterClause.v );
1941
1941
},
1942
1942
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
@@ -2019,7 +2019,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) {
2019
2019
CheckAlignValue (clause);
2020
2020
}
2021
2021
if (objectList) {
2022
- CheckIsVarPartOfAnotherVar (dir.source , *objectList);
2022
+ CheckVarIsNotPartOfAnotherVar (dir.source , *objectList);
2023
2023
}
2024
2024
}
2025
2025
@@ -2039,7 +2039,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) {
2039
2039
for (const auto &clause : clauseList.v ) {
2040
2040
if (const auto *allocClause{
2041
2041
parser::Unwrap<parser::OmpClause::Allocate>(clause)}) {
2042
- CheckIsVarPartOfAnotherVar (
2042
+ CheckVarIsNotPartOfAnotherVar (
2043
2043
dir.source , std::get<parser::OmpObjectList>(allocClause->v .t ));
2044
2044
}
2045
2045
}
@@ -3156,6 +3156,65 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
3156
3156
// clause
3157
3157
CheckMultListItems ();
3158
3158
3159
+ if (GetContext ().directive == llvm::omp::Directive::OMPD_task) {
3160
+ if (auto *detachClause{FindClause (llvm::omp::Clause::OMPC_detach)}) {
3161
+ unsigned version{context_.langOptions ().OpenMPVersion };
3162
+ if (version == 50 || version == 51 ) {
3163
+ // OpenMP 5.0: 2.10.1 Task construct restrictions
3164
+ CheckNotAllowedIfClause (llvm::omp::Clause::OMPC_detach,
3165
+ {llvm::omp::Clause::OMPC_mergeable});
3166
+ } else if (version >= 52 ) {
3167
+ // OpenMP 5.2: 12.5.2 Detach construct restrictions
3168
+ if (FindClause (llvm::omp::Clause::OMPC_final)) {
3169
+ context_.Say (GetContext ().clauseSource ,
3170
+ " If a DETACH clause appears on a directive, then the encountering task must not be a FINAL task" _err_en_US);
3171
+ }
3172
+
3173
+ const auto &detach{
3174
+ std::get<parser::OmpClause::Detach>(detachClause->u )};
3175
+ if (const auto *name{parser::Unwrap<parser::Name>(detach.v .v )}) {
3176
+ Symbol *eventHandleSym{name->symbol };
3177
+ auto checkVarAppearsInDataEnvClause = [&](const parser::OmpObjectList
3178
+ &objs,
3179
+ std::string clause) {
3180
+ for (const auto &obj : objs.v ) {
3181
+ if (const parser::Name *
3182
+ objName{parser::Unwrap<parser::Name>(obj)}) {
3183
+ if (&objName->symbol ->GetUltimate () == eventHandleSym) {
3184
+ context_.Say (GetContext ().clauseSource ,
3185
+ " A variable: `%s` that appears in a DETACH clause cannot appear on %s clause on the same construct" _err_en_US,
3186
+ objName->source , clause);
3187
+ }
3188
+ }
3189
+ }
3190
+ };
3191
+ if (auto *dataEnvClause{
3192
+ FindClause (llvm::omp::Clause::OMPC_private)}) {
3193
+ const auto &pClause{
3194
+ std::get<parser::OmpClause::Private>(dataEnvClause->u )};
3195
+ checkVarAppearsInDataEnvClause (pClause.v , " PRIVATE" );
3196
+ } else if (auto *dataEnvClause{
3197
+ FindClause (llvm::omp::Clause::OMPC_shared)}) {
3198
+ const auto &sClause {
3199
+ std::get<parser::OmpClause::Shared>(dataEnvClause->u )};
3200
+ checkVarAppearsInDataEnvClause (sClause .v , " SHARED" );
3201
+ } else if (auto *dataEnvClause{
3202
+ FindClause (llvm::omp::Clause::OMPC_firstprivate)}) {
3203
+ const auto &fpClause{
3204
+ std::get<parser::OmpClause::Firstprivate>(dataEnvClause->u )};
3205
+ checkVarAppearsInDataEnvClause (fpClause.v , " FIRSTPRIVATE" );
3206
+ } else if (auto *dataEnvClause{
3207
+ FindClause (llvm::omp::Clause::OMPC_in_reduction)}) {
3208
+ const auto &irClause{
3209
+ std::get<parser::OmpClause::InReduction>(dataEnvClause->u )};
3210
+ checkVarAppearsInDataEnvClause (
3211
+ std::get<parser::OmpObjectList>(irClause.v .t ), " IN_REDUCTION" );
3212
+ }
3213
+ }
3214
+ }
3215
+ }
3216
+ }
3217
+
3159
3218
auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
3160
3219
llvmOmpClause clauseTy) {
3161
3220
if (sym.test (Symbol::Flag::OmpThreadprivate))
@@ -3238,7 +3297,6 @@ CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture)
3238
3297
CHECK_SIMPLE_CLAUSE (Contains, OMPC_contains)
3239
3298
CHECK_SIMPLE_CLAUSE (Default, OMPC_default)
3240
3299
CHECK_SIMPLE_CLAUSE (Depobj, OMPC_depobj)
3241
- CHECK_SIMPLE_CLAUSE (Detach, OMPC_detach)
3242
3300
CHECK_SIMPLE_CLAUSE (DeviceType, OMPC_device_type)
3243
3301
CHECK_SIMPLE_CLAUSE (DistSchedule, OMPC_dist_schedule)
3244
3302
CHECK_SIMPLE_CLAUSE (Exclusive, OMPC_exclusive)
@@ -3745,14 +3803,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
3745
3803
3746
3804
void OmpStructureChecker::Enter (const parser::OmpClause::Shared &x) {
3747
3805
CheckAllowedClause (llvm::omp::Clause::OMPC_shared);
3748
- CheckIsVarPartOfAnotherVar (GetContext ().clauseSource , x.v , " SHARED" );
3806
+ CheckVarIsNotPartOfAnotherVar (GetContext ().clauseSource , x.v , " SHARED" );
3749
3807
CheckCrayPointee (x.v , " SHARED" );
3750
3808
}
3751
3809
void OmpStructureChecker::Enter (const parser::OmpClause::Private &x) {
3752
3810
SymbolSourceMap symbols;
3753
3811
GetSymbolsInObjectList (x.v , symbols);
3754
3812
CheckAllowedClause (llvm::omp::Clause::OMPC_private);
3755
- CheckIsVarPartOfAnotherVar (GetContext ().clauseSource , x.v , " PRIVATE" );
3813
+ CheckVarIsNotPartOfAnotherVar (GetContext ().clauseSource , x.v , " PRIVATE" );
3756
3814
CheckIntentInPointer (symbols, llvm::omp::Clause::OMPC_private);
3757
3815
CheckCrayPointee (x.v , " PRIVATE" );
3758
3816
}
@@ -3781,50 +3839,50 @@ bool OmpStructureChecker::IsDataRefTypeParamInquiry(
3781
3839
return dataRefIsTypeParamInquiry;
3782
3840
}
3783
3841
3784
- void OmpStructureChecker::CheckIsVarPartOfAnotherVar (
3842
+ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar (
3785
3843
const parser::CharBlock &source, const parser::OmpObjectList &objList,
3786
3844
llvm::StringRef clause) {
3787
3845
for (const auto &ompObject : objList.v ) {
3788
- common::visit (
3789
- common::visitors{
3790
- [&](const parser::Designator &designator) {
3791
- if (const auto *dataRef{
3792
- std::get_if<parser::DataRef>(&designator.u )}) {
3793
- if (IsDataRefTypeParamInquiry (dataRef)) {
3846
+ CheckVarIsNotPartOfAnotherVar (source, ompObject, clause);
3847
+ }
3848
+ }
3849
+
3850
+ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar (
3851
+ const parser::CharBlock &source, const parser::OmpObject &ompObject,
3852
+ llvm::StringRef clause) {
3853
+ common::visit (
3854
+ common::visitors{
3855
+ [&](const parser::Designator &designator) {
3856
+ if (const auto *dataRef{
3857
+ std::get_if<parser::DataRef>(&designator.u )}) {
3858
+ if (IsDataRefTypeParamInquiry (dataRef)) {
3859
+ context_.Say (source,
3860
+ " A type parameter inquiry cannot appear on the %s directive" _err_en_US,
3861
+ ContextDirectiveAsFortran ());
3862
+ } else if (parser::Unwrap<parser::StructureComponent>(
3863
+ ompObject) ||
3864
+ parser::Unwrap<parser::ArrayElement>(ompObject)) {
3865
+ if (llvm::omp::nonPartialVarSet.test (GetContext ().directive )) {
3794
3866
context_.Say (source,
3795
- " A type parameter inquiry cannot appear on the %s "
3796
- " directive" _err_en_US,
3867
+ " A variable that is part of another variable (as an array or structure element) cannot appear on the %s directive" _err_en_US,
3797
3868
ContextDirectiveAsFortran ());
3798
- } else if (parser::Unwrap<parser::StructureComponent>(
3799
- ompObject) ||
3800
- parser::Unwrap<parser::ArrayElement>(ompObject)) {
3801
- if (llvm::omp::nonPartialVarSet.test (
3802
- GetContext ().directive )) {
3803
- context_.Say (source,
3804
- " A variable that is part of another variable (as an "
3805
- " array or structure element) cannot appear on the %s "
3806
- " directive" _err_en_US,
3807
- ContextDirectiveAsFortran ());
3808
- } else {
3809
- context_.Say (source,
3810
- " A variable that is part of another variable (as an "
3811
- " array or structure element) cannot appear in a "
3812
- " %s clause" _err_en_US,
3813
- clause.data ());
3814
- }
3869
+ } else {
3870
+ context_.Say (source,
3871
+ " A variable that is part of another variable (as an array or structure element) cannot appear in a %s clause" _err_en_US,
3872
+ clause.data ());
3815
3873
}
3816
3874
}
3817
- },
3818
- [&]( const parser::Name &name) { },
3819
- },
3820
- ompObject. u );
3821
- }
3875
+ }
3876
+ },
3877
+ [&]( const parser::Name &name) { },
3878
+ },
3879
+ ompObject. u );
3822
3880
}
3823
3881
3824
3882
void OmpStructureChecker::Enter (const parser::OmpClause::Firstprivate &x) {
3825
3883
CheckAllowedClause (llvm::omp::Clause::OMPC_firstprivate);
3826
3884
3827
- CheckIsVarPartOfAnotherVar (GetContext ().clauseSource , x.v , " FIRSTPRIVATE" );
3885
+ CheckVarIsNotPartOfAnotherVar (GetContext ().clauseSource , x.v , " FIRSTPRIVATE" );
3828
3886
CheckCrayPointee (x.v , " FIRSTPRIVATE" );
3829
3887
CheckIsLoopIvPartOfClause (llvmOmpClause::OMPC_firstprivate, x.v );
3830
3888
@@ -4147,6 +4205,33 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
4147
4205
}
4148
4206
}
4149
4207
4208
+ void OmpStructureChecker::Enter (const parser::OmpClause::Detach &x) {
4209
+ unsigned version{context_.langOptions ().OpenMPVersion };
4210
+ if (version >= 52 ) {
4211
+ SetContextClauseInfo (llvm::omp::Clause::OMPC_detach);
4212
+ } else {
4213
+ // OpenMP 5.0: 2.10.1 Task construct restrictions
4214
+ CheckAllowedClause (llvm::omp::Clause::OMPC_detach);
4215
+ }
4216
+ // OpenMP 5.2: 12.5.2 Detach clause restrictions
4217
+ if (version >= 52 ) {
4218
+ CheckVarIsNotPartOfAnotherVar (GetContext ().clauseSource , x.v .v , " DETACH" );
4219
+ }
4220
+
4221
+ if (const auto *name{parser::Unwrap<parser::Name>(x.v .v )}) {
4222
+ if (version >= 52 && IsPointer (*name->symbol )) {
4223
+ context_.Say (GetContext ().clauseSource ,
4224
+ " The event-handle: `%s` must not have the POINTER attribute" _err_en_US,
4225
+ name->ToString ());
4226
+ }
4227
+ if (!name->symbol ->GetType ()->IsNumeric (TypeCategory::Integer)) {
4228
+ context_.Say (GetContext ().clauseSource ,
4229
+ " The event-handle: `%s` must be of type integer(kind=omp_event_handle_kind)" _err_en_US,
4230
+ name->ToString ());
4231
+ }
4232
+ }
4233
+ }
4234
+
4150
4235
void OmpStructureChecker::CheckAllowedMapTypes (
4151
4236
const parser::OmpMapType::Value &type,
4152
4237
const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
@@ -4495,7 +4580,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
4495
4580
CheckAllowedClause (llvm::omp::Clause::OMPC_lastprivate);
4496
4581
4497
4582
const auto &objectList{std::get<parser::OmpObjectList>(x.v .t )};
4498
- CheckIsVarPartOfAnotherVar (
4583
+ CheckVarIsNotPartOfAnotherVar (
4499
4584
GetContext ().clauseSource , objectList, " LASTPRIVATE" );
4500
4585
CheckCrayPointee (objectList, " LASTPRIVATE" );
4501
4586
0 commit comments