@@ -200,6 +200,10 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
200200 return CheckAllowed (clause);
201201}
202202
203+ bool OmpStructureChecker::IsExtendedListItem (const Symbol &sym) {
204+ return evaluate::IsVariable (sym) || sym.IsSubprogram ();
205+ }
206+
203207bool OmpStructureChecker::IsCloselyNestedRegion (const OmpDirectiveSet &set) {
204208 // Definition of close nesting:
205209 //
@@ -454,6 +458,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
454458 }
455459}
456460
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+
457469void OmpStructureChecker::Enter (const parser::OpenMPLoopConstruct &x) {
458470 const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t )};
459471 const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t )};
@@ -1246,7 +1258,8 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
12461258 context_.Say (x.source ,
12471259 " If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause" _err_en_US);
12481260 }
1249- if (toClause) {
1261+ unsigned version{context_.langOptions ().OpenMPVersion };
1262+ if (toClause && version >= 52 ) {
12501263 context_.Warn (common::UsageWarning::OpenMPUsage, toClause->source ,
12511264 " The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead." _warn_en_US);
12521265 }
@@ -2318,6 +2331,31 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
23182331
23192332void OmpStructureChecker::Enter (const parser::OmpClause &x) {
23202333 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+ }
23212359}
23222360
23232361// Following clauses do not have a separate node in parse-tree.h.
@@ -2365,7 +2403,6 @@ CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
23652403CHECK_SIMPLE_CLAUSE (Simd, OMPC_simd)
23662404CHECK_SIMPLE_CLAUSE (Sizes, OMPC_sizes)
23672405CHECK_SIMPLE_CLAUSE (TaskReduction, OMPC_task_reduction)
2368- CHECK_SIMPLE_CLAUSE (To, OMPC_to)
23692406CHECK_SIMPLE_CLAUSE (Uniform, OMPC_uniform)
23702407CHECK_SIMPLE_CLAUSE (Unknown, OMPC_unknown)
23712408CHECK_SIMPLE_CLAUSE (Untied, OMPC_untied)
@@ -2391,7 +2428,6 @@ CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)
23912428CHECK_SIMPLE_CLAUSE (Doacross, OMPC_doacross)
23922429CHECK_SIMPLE_CLAUSE (OmpxAttribute, OMPC_ompx_attribute)
23932430CHECK_SIMPLE_CLAUSE (OmpxBare, OMPC_ompx_bare)
2394- CHECK_SIMPLE_CLAUSE (Enter, OMPC_enter)
23952431CHECK_SIMPLE_CLAUSE (Fail, OMPC_fail)
23962432CHECK_SIMPLE_CLAUSE (Weak, OMPC_weak)
23972433
@@ -3357,6 +3393,47 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
33573393 }
33583394}
33593395
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+
33603437llvm::StringRef OmpStructureChecker::getClauseName (llvm::omp::Clause clause) {
33613438 return llvm::omp::getOpenMPClauseName (clause);
33623439}
0 commit comments