@@ -200,6 +200,10 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
200
200
return CheckAllowed (clause);
201
201
}
202
202
203
+ bool OmpStructureChecker::IsExtendedListItem (const Symbol &sym) {
204
+ return evaluate::IsVariable (sym) || sym.IsSubprogram ();
205
+ }
206
+
203
207
bool OmpStructureChecker::IsCloselyNestedRegion (const OmpDirectiveSet &set) {
204
208
// Definition of close nesting:
205
209
//
@@ -454,6 +458,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
454
458
}
455
459
}
456
460
461
+ void OmpStructureChecker::Leave (const parser::OpenMPConstruct &) {
462
+ for (const auto &[sym, source] : deferredNonVariables_) {
463
+ context_.SayWithDecl (
464
+ *sym, source, " '%s' must be a variable" _err_en_US, sym->name ());
465
+ }
466
+ deferredNonVariables_.clear ();
467
+ }
468
+
457
469
void OmpStructureChecker::Enter (const parser::OpenMPLoopConstruct &x) {
458
470
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t )};
459
471
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t )};
@@ -1246,7 +1258,8 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
1246
1258
context_.Say (x.source ,
1247
1259
" If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause" _err_en_US);
1248
1260
}
1249
- if (toClause) {
1261
+ unsigned version{context_.langOptions ().OpenMPVersion };
1262
+ if (toClause && version >= 52 ) {
1250
1263
context_.Warn (common::UsageWarning::OpenMPUsage, toClause->source ,
1251
1264
" The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead." _warn_en_US);
1252
1265
}
@@ -2318,6 +2331,31 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
2318
2331
2319
2332
void OmpStructureChecker::Enter (const parser::OmpClause &x) {
2320
2333
SetContextClause (x);
2334
+
2335
+ llvm::omp::Clause clauseId = std::visit (
2336
+ [this ](auto &&s) { return GetClauseKindForParserClass (s); }, x.u );
2337
+
2338
+ // The visitors for these clauses do their own checks.
2339
+ switch (clauseId) {
2340
+ case llvm::omp::Clause::OMPC_copyprivate:
2341
+ case llvm::omp::Clause::OMPC_enter:
2342
+ case llvm::omp::Clause::OMPC_lastprivate:
2343
+ case llvm::omp::Clause::OMPC_reduction:
2344
+ case llvm::omp::Clause::OMPC_to:
2345
+ return ;
2346
+ default :
2347
+ break ;
2348
+ }
2349
+
2350
+ if (const parser::OmpObjectList * objList{GetOmpObjectList (x)}) {
2351
+ SymbolSourceMap symbols;
2352
+ GetSymbolsInObjectList (*objList, symbols);
2353
+ for (const auto &[sym, source] : symbols) {
2354
+ if (!evaluate::IsVariable (sym)) {
2355
+ deferredNonVariables_.insert ({sym, source});
2356
+ }
2357
+ }
2358
+ }
2321
2359
}
2322
2360
2323
2361
// Following clauses do not have a separate node in parse-tree.h.
@@ -2365,7 +2403,6 @@ CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
2365
2403
CHECK_SIMPLE_CLAUSE (Simd, OMPC_simd)
2366
2404
CHECK_SIMPLE_CLAUSE (Sizes, OMPC_sizes)
2367
2405
CHECK_SIMPLE_CLAUSE (TaskReduction, OMPC_task_reduction)
2368
- CHECK_SIMPLE_CLAUSE (To, OMPC_to)
2369
2406
CHECK_SIMPLE_CLAUSE (Uniform, OMPC_uniform)
2370
2407
CHECK_SIMPLE_CLAUSE (Unknown, OMPC_unknown)
2371
2408
CHECK_SIMPLE_CLAUSE (Untied, OMPC_untied)
@@ -2391,7 +2428,6 @@ CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)
2391
2428
CHECK_SIMPLE_CLAUSE (Doacross, OMPC_doacross)
2392
2429
CHECK_SIMPLE_CLAUSE (OmpxAttribute, OMPC_ompx_attribute)
2393
2430
CHECK_SIMPLE_CLAUSE (OmpxBare, OMPC_ompx_bare)
2394
- CHECK_SIMPLE_CLAUSE (Enter, OMPC_enter)
2395
2431
CHECK_SIMPLE_CLAUSE (Fail, OMPC_fail)
2396
2432
CHECK_SIMPLE_CLAUSE (Weak, OMPC_weak)
2397
2433
@@ -3357,6 +3393,47 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
3357
3393
}
3358
3394
}
3359
3395
3396
+ void OmpStructureChecker::Enter (const parser::OmpClause::Enter &x) {
3397
+ CheckAllowedClause (llvm::omp::Clause::OMPC_enter);
3398
+ const parser::OmpObjectList &objList{x.v };
3399
+ SymbolSourceMap symbols;
3400
+ GetSymbolsInObjectList (objList, symbols);
3401
+ for (const auto &[sym, source] : symbols) {
3402
+ if (!IsExtendedListItem (*sym)) {
3403
+ context_.SayWithDecl (*sym, source,
3404
+ " '%s' must be a variable or a procedure" _err_en_US, sym->name ());
3405
+ }
3406
+ }
3407
+ }
3408
+
3409
+ void OmpStructureChecker::Enter (const parser::OmpClause::To &x) {
3410
+ CheckAllowedClause (llvm::omp::Clause::OMPC_to);
3411
+ if (dirContext_.empty ()) {
3412
+ return ;
3413
+ }
3414
+ // The "to" clause is only allowed on "declare target" (pre-5.1), and
3415
+ // "target update". In the former case it can take an extended list item,
3416
+ // in the latter a variable (a locator).
3417
+
3418
+ // The "declare target" construct (and the "to" clause on it) are already
3419
+ // handled (in the declare-target checkers), so just look at "to" in "target
3420
+ // update".
3421
+ if (GetContext ().directive == llvm::omp::OMPD_declare_target) {
3422
+ return ;
3423
+ }
3424
+ assert (GetContext ().directive == llvm::omp::OMPD_target_update);
3425
+
3426
+ const parser::OmpObjectList &objList{x.v };
3427
+ SymbolSourceMap symbols;
3428
+ GetSymbolsInObjectList (objList, symbols);
3429
+ for (const auto &[sym, source] : symbols) {
3430
+ if (!evaluate::IsVariable (*sym)) {
3431
+ context_.SayWithDecl (
3432
+ *sym, source, " '%s' must be a variable" _err_en_US, sym->name ());
3433
+ }
3434
+ }
3435
+ }
3436
+
3360
3437
llvm::StringRef OmpStructureChecker::getClauseName (llvm::omp::Clause clause) {
3361
3438
return llvm::omp::getOpenMPClauseName (clause);
3362
3439
}
0 commit comments