summaryrefslogtreecommitdiff
path: root/flang/lib/Semantics/check-omp-structure.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Semantics/check-omp-structure.cpp')
-rw-r--r--flang/lib/Semantics/check-omp-structure.cpp107
1 files changed, 94 insertions, 13 deletions
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 5ef504aa7232..bdb8a7249f1a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -200,6 +200,14 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
return CheckAllowed(clause);
}
+bool OmpStructureChecker::IsVariableListItem(const Symbol &sym) {
+ return evaluate::IsVariable(sym) || sym.attrs().test(Attr::POINTER);
+}
+
+bool OmpStructureChecker::IsExtendedListItem(const Symbol &sym) {
+ return IsVariableListItem(sym) || sym.IsSubprogram();
+}
+
bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
// Definition of close nesting:
//
@@ -454,6 +462,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
}
}
+void OmpStructureChecker::Leave(const parser::OpenMPConstruct &) {
+ for (const auto &[sym, source] : deferredNonVariables_) {
+ context_.SayWithDecl(
+ *sym, source, "'%s' must be a variable"_err_en_US, sym->name());
+ }
+ deferredNonVariables_.clear();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
@@ -1246,7 +1262,8 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
context_.Say(x.source,
"If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
}
- if (toClause) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (toClause && version >= 52) {
context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
"The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
}
@@ -2318,6 +2335,31 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
void OmpStructureChecker::Enter(const parser::OmpClause &x) {
SetContextClause(x);
+
+ llvm::omp::Clause clauseId = std::visit(
+ [this](auto &&s) { return GetClauseKindForParserClass(s); }, x.u);
+
+ // The visitors for these clauses do their own checks.
+ switch (clauseId) {
+ case llvm::omp::Clause::OMPC_copyprivate:
+ case llvm::omp::Clause::OMPC_enter:
+ case llvm::omp::Clause::OMPC_lastprivate:
+ case llvm::omp::Clause::OMPC_reduction:
+ case llvm::omp::Clause::OMPC_to:
+ return;
+ default:
+ break;
+ }
+
+ if (const parser::OmpObjectList * objList{GetOmpObjectList(x)}) {
+ SymbolSourceMap symbols;
+ GetSymbolsInObjectList(*objList, symbols);
+ for (const auto &[sym, source] : symbols) {
+ if (!IsVariableListItem(*sym)) {
+ deferredNonVariables_.insert({sym, source});
+ }
+ }
+ }
}
// Following clauses do not have a separate node in parse-tree.h.
@@ -2364,8 +2406,8 @@ CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed)
CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd)
CHECK_SIMPLE_CLAUSE(Sizes, OMPC_sizes)
+CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation)
CHECK_SIMPLE_CLAUSE(TaskReduction, OMPC_task_reduction)
-CHECK_SIMPLE_CLAUSE(To, OMPC_to)
CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied)
@@ -2391,7 +2433,6 @@ CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)
CHECK_SIMPLE_CLAUSE(Doacross, OMPC_doacross)
CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute)
CHECK_SIMPLE_CLAUSE(OmpxBare, OMPC_ompx_bare)
-CHECK_SIMPLE_CLAUSE(Enter, OMPC_enter)
CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail)
CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak)
@@ -2988,15 +3029,15 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
void OmpStructureChecker::CheckAllowedMapTypes(
- const parser::OmpMapType::Type &type,
- const std::list<parser::OmpMapType::Type> &allowedMapTypeList) {
+ const parser::OmpMapClause::Type &type,
+ const std::list<parser::OmpMapClause::Type> &allowedMapTypeList) {
if (!llvm::is_contained(allowedMapTypeList, type)) {
std::string commaSeparatedMapTypes;
llvm::interleave(
allowedMapTypeList.begin(), allowedMapTypeList.end(),
- [&](const parser::OmpMapType::Type &mapType) {
+ [&](const parser::OmpMapClause::Type &mapType) {
commaSeparatedMapTypes.append(parser::ToUpperCaseLetters(
- parser::OmpMapType::EnumToString(mapType)));
+ parser::OmpMapClause::EnumToString(mapType)));
},
[&] { commaSeparatedMapTypes.append(", "); });
context_.Say(GetContext().clauseSource,
@@ -3008,10 +3049,9 @@ void OmpStructureChecker::CheckAllowedMapTypes(
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
CheckAllowedClause(llvm::omp::Clause::OMPC_map);
+ using Type = parser::OmpMapClause::Type;
- if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.v.t)}) {
- using Type = parser::OmpMapType::Type;
- const Type &type{std::get<Type>(maptype->t)};
+ if (const auto &mapType{std::get<std::optional<Type>>(x.v.t)}) {
switch (GetContext().directive) {
case llvm::omp::Directive::OMPD_target:
case llvm::omp::Directive::OMPD_target_teams:
@@ -3021,13 +3061,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
case llvm::omp::Directive::OMPD_target_data:
CheckAllowedMapTypes(
- type, {Type::To, Type::From, Type::Tofrom, Type::Alloc});
+ *mapType, {Type::To, Type::From, Type::Tofrom, Type::Alloc});
break;
case llvm::omp::Directive::OMPD_target_enter_data:
- CheckAllowedMapTypes(type, {Type::To, Type::Alloc});
+ CheckAllowedMapTypes(*mapType, {Type::To, Type::Alloc});
break;
case llvm::omp::Directive::OMPD_target_exit_data:
- CheckAllowedMapTypes(type, {Type::From, Type::Release, Type::Delete});
+ CheckAllowedMapTypes(*mapType, {Type::From, Type::Release, Type::Delete});
break;
default:
break;
@@ -3357,6 +3397,47 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
}
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_enter);
+ const parser::OmpObjectList &objList{x.v};
+ SymbolSourceMap symbols;
+ GetSymbolsInObjectList(objList, symbols);
+ for (const auto &[sym, source] : symbols) {
+ if (!IsExtendedListItem(*sym)) {
+ context_.SayWithDecl(*sym, source,
+ "'%s' must be a variable or a procedure"_err_en_US, sym->name());
+ }
+ }
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_to);
+ if (dirContext_.empty()) {
+ return;
+ }
+ // The "to" clause is only allowed on "declare target" (pre-5.1), and
+ // "target update". In the former case it can take an extended list item,
+ // in the latter a variable (a locator).
+
+ // The "declare target" construct (and the "to" clause on it) are already
+ // handled (in the declare-target checkers), so just look at "to" in "target
+ // update".
+ if (GetContext().directive == llvm::omp::OMPD_declare_target) {
+ return;
+ }
+ assert(GetContext().directive == llvm::omp::OMPD_target_update);
+
+ const parser::OmpObjectList &objList{x.v};
+ SymbolSourceMap symbols;
+ GetSymbolsInObjectList(objList, symbols);
+ for (const auto &[sym, source] : symbols) {
+ if (!IsVariableListItem(*sym)) {
+ context_.SayWithDecl(
+ *sym, source, "'%s' must be a variable"_err_en_US, sym->name());
+ }
+ }
+}
+
llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) {
return llvm::omp::getOpenMPClauseName(clause);
}