@@ -1203,6 +1203,64 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
1203
1203
deviceConstructFound_ = true ;
1204
1204
}
1205
1205
1206
+ if (GetContext ().directive == llvm::omp::Directive::OMPD_single) {
1207
+ std::set<Symbol *> singleCopyprivateSyms;
1208
+ std::set<Symbol *> endSingleCopyprivateSyms;
1209
+ bool foundNowait{false };
1210
+ parser::CharBlock NowaitSource;
1211
+
1212
+ auto catchCopyPrivateNowaitClauses = [&](const auto &dir, bool endDir) {
1213
+ for (auto &clause : std::get<parser::OmpClauseList>(dir.t ).v ) {
1214
+ if (clause.Id () == llvm::omp::Clause::OMPC_copyprivate) {
1215
+ for (const auto &ompObject : GetOmpObjectList (clause)->v ) {
1216
+ const auto *name{parser::Unwrap<parser::Name>(ompObject)};
1217
+ if (Symbol * symbol{name->symbol }) {
1218
+ if (singleCopyprivateSyms.count (symbol)) {
1219
+ if (endDir) {
1220
+ context_.Warn (common::UsageWarning::OpenMPUsage, name->source ,
1221
+ " The COPYPRIVATE clause with '%s' is already used on the SINGLE directive" _warn_en_US,
1222
+ name->ToString ());
1223
+ } else {
1224
+ context_.Say (name->source ,
1225
+ " '%s' appears in more than one COPYPRIVATE clause on the SINGLE directive" _err_en_US,
1226
+ name->ToString ());
1227
+ }
1228
+ } else if (endSingleCopyprivateSyms.count (symbol)) {
1229
+ context_.Say (name->source ,
1230
+ " '%s' appears in more than one COPYPRIVATE clause on the END SINGLE directive" _err_en_US,
1231
+ name->ToString ());
1232
+ } else {
1233
+ if (endDir) {
1234
+ endSingleCopyprivateSyms.insert (symbol);
1235
+ } else {
1236
+ singleCopyprivateSyms.insert (symbol);
1237
+ }
1238
+ }
1239
+ }
1240
+ }
1241
+ } else if (clause.Id () == llvm::omp::Clause::OMPC_nowait) {
1242
+ if (foundNowait) {
1243
+ context_.Say (clause.source ,
1244
+ " At most one NOWAIT clause can appear on the SINGLE directive" _err_en_US);
1245
+ } else {
1246
+ foundNowait = !endDir;
1247
+ }
1248
+ if (!NowaitSource.ToString ().size ()) {
1249
+ NowaitSource = clause.source ;
1250
+ }
1251
+ }
1252
+ }
1253
+ };
1254
+ catchCopyPrivateNowaitClauses (beginBlockDir, false );
1255
+ catchCopyPrivateNowaitClauses (endBlockDir, true );
1256
+ unsigned version{context_.langOptions ().OpenMPVersion };
1257
+ if (version <= 52 && NowaitSource.ToString ().size () &&
1258
+ (singleCopyprivateSyms.size () || endSingleCopyprivateSyms.size ())) {
1259
+ context_.Say (NowaitSource,
1260
+ " NOWAIT clause must not be used with COPYPRIVATE clause on the SINGLE directive" _err_en_US);
1261
+ }
1262
+ }
1263
+
1206
1264
switch (beginDir.v ) {
1207
1265
case llvm::omp::Directive::OMPD_target:
1208
1266
if (CheckTargetBlockOnlyTeams (block)) {
@@ -2903,12 +2961,6 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
2903
2961
// clause
2904
2962
CheckMultListItems ();
2905
2963
2906
- // 2.7.3 Single Construct Restriction
2907
- if (GetContext ().directive == llvm::omp::Directive::OMPD_end_single) {
2908
- CheckNotAllowedIfClause (
2909
- llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait});
2910
- }
2911
-
2912
2964
auto testThreadprivateVarErr = [&](Symbol sym, parser::Name name,
2913
2965
llvmOmpClause clauseTy) {
2914
2966
if (sym.test (Symbol::Flag::OmpThreadprivate))
@@ -3549,15 +3601,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
3549
3601
3550
3602
void OmpStructureChecker::Enter (const parser::OmpClause::Nowait &x) {
3551
3603
CheckAllowedClause (llvm::omp::Clause::OMPC_nowait);
3552
- if (llvm::omp::noWaitClauseNotAllowedSet.test (GetContext ().directive )) {
3553
- context_.Say (GetContext ().clauseSource ,
3554
- " %s clause is not allowed on the OMP %s directive,"
3555
- " use it on OMP END %s directive " _err_en_US,
3556
- parser::ToUpperCaseLetters (
3557
- getClauseName (llvm::omp::Clause::OMPC_nowait).str ()),
3558
- parser::ToUpperCaseLetters (GetContext ().directiveSource .ToString ()),
3559
- parser::ToUpperCaseLetters (GetContext ().directiveSource .ToString ()));
3560
- }
3561
3604
}
3562
3605
3563
3606
bool OmpStructureChecker::IsDataRefTypeParamInquiry (
@@ -4288,15 +4331,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
4288
4331
CheckIntentInPointer (symbols, llvm::omp::Clause::OMPC_copyprivate);
4289
4332
CheckCopyingPolymorphicAllocatable (
4290
4333
symbols, llvm::omp::Clause::OMPC_copyprivate);
4291
- if (GetContext ().directive == llvm::omp::Directive::OMPD_single) {
4292
- context_.Say (GetContext ().clauseSource ,
4293
- " %s clause is not allowed on the OMP %s directive,"
4294
- " use it on OMP END %s directive " _err_en_US,
4295
- parser::ToUpperCaseLetters (
4296
- getClauseName (llvm::omp::Clause::OMPC_copyprivate).str ()),
4297
- parser::ToUpperCaseLetters (GetContext ().directiveSource .ToString ()),
4298
- parser::ToUpperCaseLetters (GetContext ().directiveSource .ToString ()));
4299
- }
4300
4334
}
4301
4335
4302
4336
void OmpStructureChecker::Enter (const parser::OmpClause::Lastprivate &x) {
0 commit comments