[llvm-branch-commits] [flang] [flang][OpenMP] Switch clause verification to descriptor-based (PR #229527)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 6 12:49:39 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/229527
>From 84f57585dd07c54351d323ad5575f9e1f0ee3320 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 9 Sep 2026 14:33:55 -0500
Subject: [PATCH] [flang][OpenMP] Switch clause verification to
descriptor-based
Delete all the scattered pieces of clause verification that are now
replaced by the unified handling.
---
flang/lib/Parser/openmp-utils.cpp | 4 +
flang/lib/Semantics/check-omp-atomic.cpp | 31 --
flang/lib/Semantics/check-omp-loop.cpp | 12 +
flang/lib/Semantics/check-omp-structure.cpp | 330 +++---------------
flang/lib/Semantics/check-omp-structure.h | 32 +-
flang/lib/Semantics/check-omp-syntax.cpp | 299 ++++++++++++++++
flang/lib/Semantics/check-omp-variant.cpp | 2 -
flang/lib/Semantics/openmp-utils.cpp | 5 +-
.../test/Lower/OpenMP/target-kernel-types.f90 | 2 +-
flang/test/Semantics/OpenMP/atomic.f90 | 2 +-
flang/test/Semantics/OpenMP/atomic05.f90 | 10 +-
flang/test/Semantics/OpenMP/cancel.f90 | 8 +-
.../Semantics/OpenMP/clause-validity01.f90 | 15 +-
.../Semantics/OpenMP/clause-validity02.f90 | 14 +-
.../Semantics/OpenMP/combined-constructs.f90 | 4 +-
.../OpenMP/declarative-directive01.f90 | 4 +-
.../Semantics/OpenMP/declare-target01.f90 | 13 +
.../Semantics/OpenMP/declare-target02.f90 | 15 +
.../Semantics/OpenMP/declare-target06.f90 | 1 +
.../OpenMP/declare-variant-match.f90 | 2 +-
.../Semantics/OpenMP/depobj-construct-v50.f90 | 2 +-
flang/test/Semantics/OpenMP/detach02.f90 | 2 +-
.../Semantics/OpenMP/device-constructs.f90 | 2 +-
flang/test/Semantics/OpenMP/flush02.f90 | 16 +-
flang/test/Semantics/OpenMP/flush03.f90 | 1 +
flang/test/Semantics/OpenMP/if-clause-45.f90 | 9 +-
flang/test/Semantics/OpenMP/if-clause-50.f90 | 5 +-
.../Semantics/OpenMP/interop-construct.f90 | 2 +-
.../loop-transformation-construct01.f90 | 10 +-
flang/test/Semantics/OpenMP/ordered03.f90 | 2 +-
flang/test/Semantics/OpenMP/requires01.f90 | 1 +
flang/test/Semantics/OpenMP/requires04.f90 | 1 +
flang/test/Semantics/OpenMP/requires05.f90 | 1 +
flang/test/Semantics/OpenMP/scan1.f90 | 7 +-
flang/test/Semantics/OpenMP/single03.f90 | 6 +-
flang/test/Semantics/OpenMP/single04.f90 | 10 +-
.../test/Semantics/OpenMP/target-update01.f90 | 4 +-
flang/test/Semantics/OpenMP/task-45.f90 | 2 +-
flang/test/Semantics/OpenMP/tile01.f90 | 2 +-
.../test/Semantics/OpenMP/unroll-clauses.f90 | 2 +-
.../Semantics/OpenMP/workdistribute04.f90 | 2 +-
flang/test/Semantics/indirect02.f90 | 4 +-
42 files changed, 515 insertions(+), 383 deletions(-)
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index 1910d765e22d02..5387735f823fd4 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -150,6 +150,10 @@ const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
std::string GetUpperName(
llvm::omp::Clause id, llvm::omp::Version version, bool annotate) {
+ if (id == llvm::omp::Clause::OMPC_cancellation_construct_type) {
+ return "cancel-directive-name";
+ }
+
llvm::StringRef annot("");
if (annotate) {
switch (id) {
diff --git a/flang/lib/Semantics/check-omp-atomic.cpp b/flang/lib/Semantics/check-omp-atomic.cpp
index 7e8a3ffef8909c..22a1435fc0363c 100644
--- a/flang/lib/Semantics/check-omp-atomic.cpp
+++ b/flang/lib/Semantics/check-omp-atomic.cpp
@@ -1631,40 +1631,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPAtomicConstruct &x) {
llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_relaxed,
llvm::omp::Clause::OMPC_release, llvm::omp::Clause::OMPC_seq_cst};
- auto checkExclusive{[&](llvm::ArrayRef<llvm::omp::Clause> group,
- std::string_view name,
- const parser::OmpClauseList &clauses) {
- const parser::OmpClause *present{nullptr};
- for (const parser::OmpClause &clause : clauses.v) {
- llvm::omp::Clause id{clause.Id()};
- if (!llvm::is_contained(group, id)) {
- continue;
- }
- if (present == nullptr) {
- present = &clause;
- continue;
- } else if (id == present->Id()) {
- // Ignore repetitions of the same clause, those will be diagnosed
- // separately.
- continue;
- }
- parser::MessageFormattedText txt(
- "At most one clause from the '%s' group is allowed on ATOMIC construct"_err_en_US,
- name.data());
- parser::Message message(clause.source, txt);
- message.Attach(present->source,
- "Previous clause from this group provided here"_en_US);
- context_.Say(std::move(message));
- return;
- }
- }};
-
const parser::OmpDirectiveSpecification &dirSpec{x.BeginDir()};
llvm::omp::Clause kind{x.GetKind()};
- checkExclusive(atomic, "atomic", dirSpec.Clauses());
- checkExclusive(memoryOrder, "memory-order", dirSpec.Clauses());
-
checkIncompatibleMemoryOrderClause(context_, x, atomic, memoryOrder);
// OpenMP 5.2 [15.8.3] extended-atomic Clauses: acq_rel and release cannot
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 5165ca5f70d078..94ed87a6f05e57 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -842,6 +842,7 @@ void OmpStructureChecker::CheckDoacross(
void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+ auto leafs{llvm::omp::getLeafConstructsOrSelf(dirStack_.back()->DirId())};
parser::CharBlock source{GetContext().clauseSource};
std::string clauseName{
parser::omp::GetUpperName(llvm::omp::Clause::OMPC_ordered, version)};
@@ -872,6 +873,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
}
}
}
+
+ // ORDERED is not allowed on DISTRIBUTE, so if it is the only leaf,
+ // a diagnostic has already been emitted.
+ if (leafs.size() > 1 &&
+ llvm::is_contained(leafs, llvm::omp::OMPD_distribute)) {
+ context_.Say(GetContext().clauseSource,
+ "%s clause is not allowed on a compound directive with %s as a constituent"_err_en_US,
+ clauseName,
+ parser::omp::GetUpperName(
+ llvm::omp::Directive::OMPD_distribute, version));
+ }
}
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6193b297b62fb5..6f43d250954790 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -529,7 +529,6 @@ class OmpUnitedTaskDesignatorChecker {
bool OmpStructureChecker::IsAllowedClause(llvm::omp::Clause clauseId) {
// Do not do clause checks while processing METADIRECTIVE.
- // See comment in CheckAllowedClause.
if (GetDirectiveNest(ContextSelectorNest) > 0) {
return true;
}
@@ -537,81 +536,6 @@ bool OmpStructureChecker::IsAllowedClause(llvm::omp::Clause clauseId) {
context_.langOptions().getOpenMPVersion(), &context_);
}
-static llvm::omp::Version AllowedInFutureVersion(llvm::omp::Clause clauseId,
- llvm::omp::Directive dirId, llvm::omp::Version version,
- SemanticsContext *semaCtx) {
- for (llvm::omp::Version v : llvm::omp::getOpenMPVersions()) {
- if (v <= version) {
- continue;
- }
- if (llvm::omp::isAllowedClauseForDirective(dirId, clauseId, v)) {
- return v;
- }
- }
- return llvm::omp::Version();
-}
-
-bool OmpStructureChecker::CheckAllowedClause(llvm::omp::Clause clauseId,
- parser::CharBlock clauseSource, llvm::omp::Directive dirId) {
- // Do not do clause checks while processing METADIRECTIVE.
- // Context selectors can contain clauses that are not given as a part
- // of a construct, but as trait properties. Testing whether they are
- // valid or not is deferred to the checks of the context selectors.
- // As it stands now, these clauses would appear as if they were present
- // on METADIRECTIVE, leading to incorrect diagnostics.
- if (GetDirectiveNest(ContextSelectorNest) > 0) {
- return true;
- }
-
- llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
-
- // Don't consult the overrides here. Checking the overrides would suppress
- // repeated warnings for multiple occurrences of the same scenario (which
- // may be desirable), but it would also suppress repeated errors with
- // -Werror (which is undesirable).
- if (!llvm::omp::isAllowedClauseForDirective(dirId, clauseId, version)) {
- if (auto allowedInVersion{
- AllowedInFutureVersion(clauseId, dirId, version, &context_)}) {
- context_.Warn(common::UsageWarning::OpenMPFuture, clauseSource,
- "%s clause is not allowed on %s directive in %s, %s"_warn_en_US,
- GetUpperName(clauseId, version), GetUpperName(dirId, version),
- ThisVersion(version), TryVersion(allowedInVersion));
- SetAllowedClauseOverride(clauseId, dirId, allowedInVersion);
- } else {
- context_.Say(clauseSource,
- "%s clause is not allowed on %s directive"_err_en_US,
- GetUpperName(clauseId, version), GetUpperName(dirId, version));
- }
- return false;
- }
-
- return true;
-}
-
-// Mark clauseId as allowed on dirId. If dirId is a compound directive,
-// identify all leafs that allow the clause in version "since" or later,
-// and mark the clause as allowed on these leafs as well.
-// If dirId is not a compound directive, the "since" argument is ignored.
-void OmpStructureChecker::SetAllowedClauseOverride(llvm::omp::Clause clauseId,
- llvm::omp::Directive dirId, llvm::omp::Version since) {
- SemanticOverrides &overrides{context_.GetOmpSemanticOverrides()};
- overrides.allowedClauses[clauseId].set(dirId);
-
- auto leafs{llvm::omp::getLeafConstructsOrSelf(dirId)};
- if (leafs.size() > 1) {
- llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
- assert(since > version && "\"since\" should be a future version");
- for (llvm::omp::Directive leaf : leafs) {
- if (auto allowedInVersion{
- AllowedInFutureVersion(clauseId, leaf, version, &context_)}) {
- if (allowedInVersion <= since) {
- overrides.allowedClauses[clauseId].set(leaf);
- }
- }
- }
- }
-}
-
void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
if (GetCommonBlockFromObj(object) ||
std::holds_alternative<parser::OmpObject::Invalid>(object.u)) {
@@ -1136,144 +1060,25 @@ void OmpStructureChecker::CheckDirectiveInDoConcurrent(parser::CharBlock source,
}
}
-std::pair<const parser::OmpClause *, const parser::OmpClause *>
-OmpStructureChecker::FindMutuallyExclusiveClauses(llvm::omp::Clauses exclusive,
- const std::vector<const parser::OmpClause *> &clauses) {
- const parser::OmpClause *first{nullptr};
- for (const parser::OmpClause *clause : clauses) {
- llvm::omp::Clause clauseId{clause->Id()};
- if (!exclusive.test(clauseId)) {
- continue;
- }
- if (first) {
- llvm::omp::Clause firstId{first->Id()};
- if (clauseId < firstId) {
- return std::make_pair(clause, first);
- } else if (clauseId > firstId) {
- return std::make_pair(first, clause);
- }
- } else {
- first = clause;
- }
- }
- return std::make_pair(nullptr, nullptr);
-}
-
-void OmpStructureChecker::CheckClauses(parser::OmpDirectiveName dirName,
+void OmpStructureChecker::AddClauses(
llvm::iterator_range<ClauseIterator> beginClauses,
llvm::iterator_range<ClauseIterator> endClauses) {
- llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
- llvm::omp::Directive dirId{dirName.v};
- std::vector<const parser::OmpClause *> allClauses;
-
+ // Record the clauses in the directive context.
auto addClause{[&](const parser::OmpClause &clause) {
llvm::omp::Clause clauseId{clause.Id()};
AddClauseToCrtContext(clauseId);
SetContextClause(clause);
SetContextClauseInfo(clauseId);
- allClauses.push_back(&clause);
}};
for (const parser::OmpClause &clause : beginClauses) {
addClause(clause);
}
for (const parser::OmpClause &clause : endClauses) {
- llvm::omp::Clause clauseId{clause.Id()};
- if (llvm::omp::isEndClause(clauseId)) {
+ if (llvm::omp::isEndClause(clause.Id())) {
addClause(clause);
- } else {
- context_.Say(clause.source,
- "%s clause is not allowed on an end-directive"_err_en_US,
- GetUpperName(clauseId, version));
}
}
-
- llvm::omp::Clauses notAllowed;
-
- for (const parser::OmpClause *clause : allClauses) {
- llvm::omp::Clause clauseId{clause->Id()};
- switch (clauseId) {
- // Special cases.
- case llvm::omp::Clause::OMPC_cancellation_construct_type:
- case llvm::omp::Clause::OMPC_ompx_bare:
- continue;
- default:
- break;
- }
- if (!CheckAllowedClause(clauseId, clause->source, dirId)) {
- notAllowed.set(clauseId);
- }
- }
- auto newEnd{llvm::remove_if(allClauses, [&](const parser::OmpClause *clause) {
- return notAllowed.test(clause->Id());
- })};
- allClauses.erase(newEnd, allClauses.end());
-
- std::multimap<llvm::omp::Clause, parser::CharBlock> present;
- // Exclusive clauses aren't necessarily unique, but there is no way
- // to specify a clause in both sets right now, and all clauses currently
- // listed as exclusive also happen to be unique.
- llvm::omp::Clauses uniqueSet{//
- directiveClausesMap_[dirId].allowedOnce |
- directiveClausesMap_[dirId].allowedExclusive};
-
- for (const parser::OmpClause *clause : allClauses) {
- llvm::omp::Clause clauseId{clause->Id()};
- // Special case.
- if (clauseId == llvm::omp::Clause::OMPC_cancellation_construct_type) {
- continue;
- }
- auto range{llvm::make_range(present.equal_range(clauseId))};
- if (uniqueSet.test(clauseId)) {
- // Only report any repeated clause once.
- if (std::distance(range.begin(), range.end()) == 1) {
- std::string clauseName{GetUpperName(clauseId, version)};
- context_
- .Say(clause->source,
- "At most one %s clause can appear on %s directive"_err_en_US,
- clauseName, GetUpperName(dirId, version))
- .Attach(range.begin()->second,
- "%s clause was first specified here"_en_US, clauseName);
- }
- }
- present.insert(std::make_pair(clauseId, clause->source));
- }
-
- bool requiredPresent{false};
- // Prepare the requiredSet relevant to the current OpenMP version.
- llvm::omp::Clauses requiredSet;
- for (llvm::omp::Clause id : directiveClausesMap_[dirId].requiredOneOf) {
- // Do not report overridden clauses as required.
- if (llvm::omp::isAllowedClauseForDirective(dirId, id, version)) {
- requiredSet.set(id);
- }
- }
- for (llvm::omp::Clause id : requiredSet) {
- if (!requiredPresent && present.count(id) != 0) {
- requiredPresent = true;
- }
- }
-
- if (!requiredPresent && !requiredSet.empty()) {
- context_.Say(dirName.source,
- "At least one of %s %s must appear on %s directive"_err_en_US,
- ClauseSetToString(requiredSet),
- requiredSet.count() == 1 ? "clause" : "clauses",
- GetUpperName(dirName.v, version));
- }
-
- auto pair{FindMutuallyExclusiveClauses(
- directiveClausesMap_[dirId].allowedExclusive, allClauses)};
- if (pair.first && pair.second) {
- std::string firstName{GetUpperName(pair.first->Id(), version)};
- std::string secondName{GetUpperName(pair.second->Id(), version)};
- context_
- .Say(pair.second->source,
- "%s and %s clauses are mutually exclusive and may not appear on the same %s directive"_err_en_US,
- firstName, secondName, GetUpperName(dirId, version))
- .Attach(pair.first->source, "%s clause was specified here"_en_US,
- firstName);
- }
}
void OmpStructureChecker::CheckMultipleOccurrence(
@@ -1489,14 +1294,14 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
std::is_base_of_v<parser::OmpBlockConstruct, TypeS> ||
std::is_same_v<parser::OpenMPSectionsConstruct, TypeS>) {
if (auto &endSpec{s.EndDir()}) {
- CheckClauses(dirName,
- llvm::iterator_range(s.BeginDir().Clauses().v),
+ VerifyClauseSyntax(&s.BeginDir(), &*endSpec);
+ AddClauses(llvm::iterator_range(s.BeginDir().Clauses().v),
llvm::iterator_range(endSpec->Clauses().v));
return;
}
}
- CheckClauses(dirName,
- llvm::iterator_range(dirStack_.back()->Clauses().v),
+ VerifyClauseSyntax(dirStack_.back(), nullptr);
+ AddClauses(llvm::iterator_range(dirStack_.back()->Clauses().v),
llvm::iterator_range(std::list<parser::OmpClause>{}));
},
x.u);
@@ -1533,7 +1338,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeConstruct &x) {
PushContextAndClauseSets(dirName.source, dirName.v);
dirStack_.push_back(&GetOmpDirectiveSpecification(x));
- CheckClauses(dirName, llvm::iterator_range(dirStack_.back()->Clauses().v),
+ VerifyClauseSyntax(dirStack_.back(), nullptr);
+ AddClauses(llvm::iterator_range(dirStack_.back()->Clauses().v),
llvm::iterator_range(std::list<parser::OmpClause>{}));
CheckDirectiveInPureProcedure(dirName.source, dirName.v, *dirStack_.back());
@@ -1793,34 +1599,24 @@ void OmpStructureChecker::CheckSingleConstruct(
const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
SymbolSourceMap copyPrivateSyms;
- parser::CharBlock nowaitSource1, nowaitSource2;
- auto catchCopyPrivateNowaitClauses =
- [&](const parser::OmpDirectiveSpecification &spec,
- parser::CharBlock &nowaitSource) {
+ auto collectCopyprivateSymbols =
+ [&](const parser::OmpDirectiveSpecification &spec) {
for (auto &clause : spec.Clauses().v) {
llvm::omp::Clause clauseId{clause.Id()};
if (clauseId == llvm::omp::Clause::OMPC_copyprivate) {
GetSymbolsInObjectList(*GetOmpObjectList(clause), copyPrivateSyms);
- } else if (clauseId == llvm::omp::Clause::OMPC_nowait) {
- if (nowaitSource.empty()) {
- nowaitSource = clause.source;
- }
}
}
};
- catchCopyPrivateNowaitClauses(beginSpec, nowaitSource1);
+ collectCopyprivateSymbols(beginSpec);
if (auto &endSpec{x.EndDir()}) {
- catchCopyPrivateNowaitClauses(*endSpec, nowaitSource2);
+ collectCopyprivateSymbols(*endSpec);
}
- std::string nowaitName{//
- GetUpperName(llvm::omp::Clause::OMPC_nowait, version)};
std::string copyPrivateName{
GetUpperName(llvm::omp::Clause::OMPC_copyprivate, version)};
- std::string singleName{
- GetUpperName(llvm::omp::Directive::OMPD_single, version)};
std::pair<const Symbol *, parser::CharBlock> last{nullptr, {}};
bool reported{false};
@@ -1840,15 +1636,6 @@ void OmpStructureChecker::CheckSingleConstruct(
}
last = std::make_pair(symbol, source);
}
-
- if (version <= 52 && !copyPrivateSyms.empty() &&
- (!nowaitSource1.empty() || !nowaitSource2.empty())) {
- parser::CharBlock source{
- !nowaitSource1.empty() ? nowaitSource1 : nowaitSource2};
- context_.Say(source,
- "%s clause must not be used with %s clause on %s directive"_err_en_US,
- nowaitName, copyPrivateName, singleName);
- }
}
void OmpStructureChecker::CheckMasterNesting(
@@ -2339,8 +2126,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPDepobjConstruct &x) {
}
}
if (clauses.v.size() != 1) {
- context_.Say(
- x.source, "The DEPOBJ construct requires a single clause"_err_en_US);
return;
}
@@ -3060,10 +2845,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPAllocatorsConstruct &x) {
void OmpStructureChecker::CheckScan(
const parser::OpenMPSimpleStandaloneConstruct &x) {
- if (x.v.Clauses().v.size() != 1) {
- context_.Say(x.source,
- "Exactly one of EXCLUSIVE or INCLUSIVE clause is expected"_err_en_US);
- }
if (!CurrentDirectiveIsNested() ||
!llvm::omp::scanParentAllowedSet.test(GetContextParent().directive)) {
context_.Say(x.source,
@@ -3194,11 +2975,6 @@ void OmpStructureChecker::CheckTargetUpdate() {
const parser::OmpClause *toWrapper{FindClause(llvm::omp::Clause::OMPC_to)};
const parser::OmpClause *fromWrapper{
FindClause(llvm::omp::Clause::OMPC_from)};
- if (!toWrapper && !fromWrapper) {
- context_.Say(GetContext().directiveSource,
- "At least one motion-clause (TO/FROM) must be specified on "
- "TARGET UPDATE construct."_err_en_US);
- }
if (toWrapper && fromWrapper) {
SymbolSourceMap toSymbols, fromSymbols;
GetSymbolsInObjectList(*GetOmpObjectList(*fromWrapper), fromSymbols);
@@ -3466,7 +3242,13 @@ void OmpStructureChecker::Leave(
}
void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
auto &flushList{std::get<std::optional<parser::OmpArgumentList>>(x.v.t)};
+ std::string flushName{
+ GetUpperName(llvm::omp::Directive::OMPD_flush, version)};
+
+ auto &mdesc{llvm::omp::getDescriptor(llvm::omp::ClauseSet::MemoryOrder)};
+ llvm::omp::Clauses memOrder{mdesc.getClauses(version)};
auto isVariableListItemOrCommonBlock{[](const Symbol &sym) {
return IsVariableListItem(sym) ||
@@ -3482,20 +3264,31 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) {
}
}
- if (FindClause(llvm::omp::Clause::OMPC_acquire) ||
- FindClause(llvm::omp::Clause::OMPC_release) ||
- FindClause(llvm::omp::Clause::OMPC_acq_rel)) {
- context_.Say(flushList->source,
- "If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive"_err_en_US);
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ if (memOrder.test(clause.Id())) {
+ context_.Say(flushList->source,
+ "If a '%s' clause is specified, list items must not be specified on the %s directive"_err_en_US,
+ mdesc.getName(), flushName);
+ break;
+ }
+ }
+ }
+
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ llvm::omp::Clause clauseId{clause.Id()};
+ if (clauseId == llvm::omp::Clause::OMPC_relaxed) {
+ context_.Say(clause.source, "'%s' cannot be %s on %s directive"_err_en_US,
+ mdesc.getName(),
+ GetUpperName(llvm::omp::Clause::OMPC_relaxed, version), flushName);
}
}
- llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
if (version >= 52) {
auto &flags{std::get<parser::OmpDirectiveSpecification::Flags>(x.v.t)};
if (flags.test(parser::OmpDirectiveSpecification::Flag::DeprecatedSyntax)) {
context_.Say(x.source,
- "The syntax \"FLUSH clause (object, ...)\" has been deprecated, use \"FLUSH(object, ...) clause\" instead"_warn_en_US);
+ "The syntax \"FLUSH clause (object, ...)\" has been deprecated, use \"%s(object, ...) clause\" instead"_warn_en_US,
+ flushName);
}
}
}
@@ -3638,9 +3431,9 @@ void OmpStructureChecker::Enter(
if (dir != llvm::omp::Directive::OMPD_cancel &&
dir != llvm::omp::Directive::OMPD_cancellation_point) {
- // Do not call CheckAllowed/CheckAllowedClause, because in case of an error
- // it will print "CANCELLATION_CONSTRUCT_TYPE" as the clause name instead
- // of the contained construct name.
+ // Do not call CheckAllowed because in case of an error it will print
+ // "CANCELLATION_CONSTRUCT_TYPE" as the clause name instead of the
+ // contained construct name.
context_.Say(dirName.source, "%s cannot follow %s"_err_en_US,
parser::omp::GetUpperName(dirName.v, version),
parser::omp::GetUpperName(dir, version));
@@ -3689,9 +3482,6 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
parser::OmpClause::CancellationConstructType;
if (auto *cctype{std::get_if<CancellationConstructType>(&clause.u)}) {
if (cancelee) {
- context_.Say(cancelSource,
- "Multiple cancel-directive-name clauses are not allowed on %s construct"_err_en_US,
- cancelName);
return std::nullopt;
}
cancelee = std::get<parser::OmpDirectiveName>(cctype->v.t).v;
@@ -3699,12 +3489,8 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
}
if (!cancelee) {
- context_.Say(cancelSource,
- "Missing cancel-directive-name clause on the %s construct"_err_en_US,
- cancelName);
return std::nullopt;
}
-
return cancelee;
}
@@ -3914,11 +3700,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &x) {
if (GetContext().directive == llvm::omp::Directive::OMPD_task) {
if (auto *detachClause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
- if (version < 52) {
- // OpenMP 5.0: 2.10.1 Task construct restrictions
- CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_detach,
- {llvm::omp::Clause::OMPC_mergeable});
- } else if (version >= 52) {
+ if (version >= 52) {
// OpenMP 5.2: 12.5.2 Detach construct restrictions
if (FindClause(llvm::omp::Clause::OMPC_final)) {
context_.Say(GetContext().clauseSource,
@@ -5407,10 +5189,21 @@ void OmpStructureChecker::CheckLastprivateModifier(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
CheckCopyingPolymorphicAllocatable(
currSymbols, llvm::omp::Clause::OMPC_copyin);
+
+ // COPYIN is not allowed on TARGET, so if it is the only leaf,
+ // a diagnostic has already been emitted.
+ auto leafs{llvm::omp::getLeafConstructsOrSelf(dirStack_.back()->DirId())};
+ if (leafs.size() > 1 && llvm::is_contained(leafs, llvm::omp::OMPD_target)) {
+ context_.Say(GetContext().clauseSource,
+ "%s clause is not allowed on a compound directive with %s as a constituent"_err_en_US,
+ GetUpperName(llvm::omp::Clause::OMPC_copyin, version),
+ GetUpperName(llvm::omp::Directive::OMPD_target, version));
+ }
}
void OmpStructureChecker::CheckStructureComponent(
@@ -5961,9 +5754,9 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::OmpxBare &x) {
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
- // Don't call CheckAllowedClause, because it allows "ompx_bare" on
- // a non-combined "target" directive (for reasons of splitting combined
- // directives). In source code it's only allowed on "target teams".
+ // The OMPX_BARE clause is allowed in both TARGET and TEAMS for the
+ // purposes of construct decomposition. In source code it's only allowed
+ // on TARGET TEAMS.
if (GetContext().directive != llvm::omp::Directive::OMPD_target_teams) {
context_.Say(GetContext().clauseSource,
"%s clause is only allowed on combined TARGET TEAMS"_err_en_US,
@@ -6326,10 +6119,11 @@ void OmpStructureChecker::CheckWorkdistributeBlockStmts(
const parser::Block &block, parser::CharBlock source) {
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
llvm::omp::Version since(60);
- if (version < since)
+ if (version < since) {
context_.Say(source,
"WORKDISTRIBUTE construct is not allowed in %s, %s"_err_en_US,
ThisVersion(version), TryVersion(since));
+ }
OmpWorkdistributeBlockChecker ompWorkdistributeBlockChecker{context_, source};
@@ -6490,7 +6284,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::ThreadLimit &x) {
void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
bool isDependClauseOccurred{false};
bool hasInitClause{false};
- bool hasActionClause{false};
int targetCount{0}, targetSyncCount{0};
std::set<std::string> interopVarNames;
// An interop-var must be a scalar variable of integer type. Reject
@@ -6573,7 +6366,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
common::visitors{
[&](const parser::OmpClause::Init &initClause) {
hasInitClause = true;
- hasActionClause = true;
auto &modifiers{OmpGetModifiers(initClause.v)};
auto &&interopTypeModifier{
OmpGetRepeatableModifier<parser::OmpInteropType>(modifiers)};
@@ -6635,7 +6427,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
isDependClauseOccurred = true;
},
[&](const parser::OmpClause::Destroy &destroyClause) {
- hasActionClause = true;
if (!destroyClause.v) {
context_.Say(GetContext().directiveSource,
"The DESTROY clause on an INTEROP construct must specify an interop variable"_err_en_US);
@@ -6649,7 +6440,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
}
},
[&](const parser::OmpClause::Use &useClause) {
- hasActionClause = true;
const auto *interopVar{
parser::Unwrap<parser::OmpObject>(useClause.v)};
CheckTypeParamInquiry(
@@ -6663,12 +6453,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
},
clause.u);
}
- // At least one action-clause (init, use, or destroy) must appear on an
- // interop construct; a construct with only e.g. device or depend is invalid.
- if (!hasActionClause) {
- context_.Say(GetContext().directiveSource,
- "At least one action-clause (INIT, USE, or DESTROY) must appear on the INTEROP construct"_err_en_US);
- }
if (targetCount > 1 || targetSyncCount > 1) {
context_.Say(GetContext().directiveSource,
"Each interop-type may be specified at most once."_err_en_US);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 17f531a3508b7e..c283f511f63b13 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -68,7 +68,8 @@ template <typename ElemTy, typename SetsSetTy> struct AppliedElementInfo {
using AppliedModifierInfo =
AppliedElementInfo<llvm::omp::Modifier, llvm::omp::ModifierSets>;
-using AppliedModifier = AppliedModifierInfo::ElementTy;
+using AppliedClauseInfo =
+ AppliedElementInfo<llvm::omp::Clause, llvm::omp::ClauseSets>;
// Mapping from 'Symbol' to 'Source' to keep track of the variables
// used in multiple clauses
@@ -357,6 +358,21 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
const parser::OmpTraitSetSelector &, const parser::OmpTraitSelector &);
// check-omp-syntax.cpp
+ bool VerifyClauseVersion(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ bool VerifyClauseRequired(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ bool VerifyClauseUnique(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ bool VerifyClauseExclusive(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ bool VerifyClauseUltimate(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ bool VerifyClauseSyntax(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info);
+ void VerifyClauseSyntax(const parser::OmpDirectiveSpecification *beginSpec,
+ const parser::OmpDirectiveSpecification *endDir);
+
bool VerifyModifierVersion(parser::omp::WithSource<llvm::omp::Clause> clause,
const AppliedModifierInfo &info);
bool VerifyModifierRequired(parser::omp::WithSource<llvm::omp::Clause> clause,
@@ -372,14 +388,14 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
const AppliedModifierInfo &info);
void VerifyModifierSyntax(const parser::OmpClause &x);
+ void SetAllowedClauseOverride(llvm::omp::Clause clauseId,
+ llvm::omp::Directive dirId,
+ llvm::omp::Version since = llvm::omp::Version());
+
// check-omp-structure.cpp
using ClauseIterator =
decltype(std::declval<const parser::OmpClauseList>().v.begin());
bool IsAllowedClause(llvm::omp::Clause clauseId);
- bool CheckAllowedClause(llvm::omp::Clause clauseId,
- parser::CharBlock clauseSource, llvm::omp::Directive dirId);
- void SetAllowedClauseOverride(llvm::omp::Clause clauseId,
- llvm::omp::Directive dirId, llvm::omp::Version since);
void CheckArgumentObjectKind(const parser::OmpClause &x);
void CheckDirectiveSpelling(
parser::CharBlock spelling, llvm::omp::Directive id);
@@ -391,13 +407,9 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
llvm::omp::Directive id, const parser::OmpDirectiveSpecification &spec);
void CheckDirectiveInDoConcurrent(parser::CharBlock source,
llvm::omp::Directive id, const parser::OmpDirectiveSpecification &spec);
- void CheckClauses(parser::OmpDirectiveName dirName,
- llvm::iterator_range<ClauseIterator> beginClauses,
+ void AddClauses(llvm::iterator_range<ClauseIterator> beginClauses,
llvm::iterator_range<ClauseIterator> endClauses);
void AnalyzeObject(const parser::OmpObject &object);
- std::pair<const parser::OmpClause *, const parser::OmpClause *>
- FindMutuallyExclusiveClauses(llvm::omp::Clauses exclusive,
- const std::vector<const parser::OmpClause *> &clauses);
const parser::OpenMPConstruct *GetCurrentConstruct() const;
void CheckSourceLabel(const parser::Label &);
diff --git a/flang/lib/Semantics/check-omp-syntax.cpp b/flang/lib/Semantics/check-omp-syntax.cpp
index 37585d3a0e5389..784ad8c623b64a 100644
--- a/flang/lib/Semantics/check-omp-syntax.cpp
+++ b/flang/lib/Semantics/check-omp-syntax.cpp
@@ -63,6 +63,19 @@ static llvm::omp::Version NextVersion(llvm::omp::Version version) {
return llvm::omp::Version();
}
+static std::string EnumSetToString(
+ llvm::omp::Clauses set, llvm::omp::Version version) {
+ llvm::SmallVector<std::string> names;
+ for (llvm::omp::Clause c : set) {
+ names.emplace_back(GetUpperName(c, version));
+ }
+ if (names.size() == 1) {
+ return names.front();
+ }
+ return llvm::join(llvm::ArrayRef(names).drop_back(), ", ") + " or " +
+ names.back();
+}
+
static std::string EnumSetToString(
llvm::omp::Modifiers set, llvm::omp::Version version) {
llvm::SmallVector<std::string> names;
@@ -76,6 +89,19 @@ static std::string EnumSetToString(
names.back();
}
+static std::string OneOfClauses(
+ llvm::omp::ClauseSet set, llvm::omp::Version version) {
+ auto &sdesc{llvm::omp::getDescriptor(set)};
+ llvm::omp::Clauses members{sdesc.getClauses(version)};
+
+ if (size_t count{members.size()}; count == 1) {
+ return EnumSetToString(members, version) + " clause";
+ } else if (count > 1) {
+ return "One of " + EnumSetToString(members, version) + " clauses";
+ }
+ return "";
+}
+
static std::string OneOfModifiers(
llvm::omp::ModifierSet set, llvm::omp::Version version) {
auto &sdesc{llvm::omp::getDescriptor(set)};
@@ -323,6 +349,250 @@ static ResultTy VerifyUltimate(
return result;
}
+bool OmpStructureChecker::VerifyClauseVersion(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+ bool isCancel{dirName.v == llvm::omp::Directive::OMPD_cancel ||
+ dirName.v == llvm::omp::Directive::OMPD_cancellation_point};
+
+ auto result = VerifyVersions(info, dirName.v, version);
+
+ for (auto &[c, svr] : result) {
+ std::string cname{GetUpperName(c, version)};
+ std::string dname{GetUpperName(dirName.v, version)};
+ llvm::omp::Version since(svr.second.Min);
+ llvm::omp::Version until(svr.second.Max);
+
+ // Cancellation construct type clauses are directive names. They are
+ // only allowed on CANCEL and CANCELLATION_POINT directives. They may
+ // appear as byproducts of parsing an invalid directive name,
+ // e.g. SECTIONS PARALLEL, where SECTIONS will be the directive name,
+ // and PARALLEL will be a cancellation-construct-type clause.
+ // This may cause confusing error messages to be emitted, so deal with
+ // these cases separately.
+ if (!isCancel && c == llvm::omp::Clause::OMPC_cancellation_construct_type) {
+ context_.Say(svr.first, "%s cannot follow %s"_err_en_US,
+ parser::ToUpperCaseLetters(svr.first.ToString()), dname);
+ continue;
+ }
+
+ if (since == ~0u && until == 0u) {
+ context_.Say(svr.first,
+ "%s clause is not allowed on %s directive"_err_en_US, cname, dname);
+ } else if (since != ~0u && version < since) {
+ context_.Warn(common::UsageWarning::OpenMPFuture, svr.first,
+ "%s clause is not allowed on %s directive in %s, %s"_warn_en_US,
+ cname, dname, omp::ThisVersion(version), omp::TryVersion(since));
+ SetAllowedClauseOverride(c, dirName.v, since);
+ } else if (until != 0u && version > until) {
+ context_.Warn(common::UsageWarning::OpenMPDeprecated, svr.first,
+ "%s clause is no longer allowed on %s directive since %s"_warn_en_US,
+ cname, dname, omp::ThisVersion(NextVersion(until)));
+ SetAllowedClauseOverride(c, dirName.v);
+ }
+ }
+
+ return result.empty();
+}
+
+// In OpenMP 6.0+ the COMBINER clause is required on DECLARE_REDUCTION,
+// even though the old syntax (with the combiner expression inside the
+// directive argument) is still allowed.
+static bool missingCombiner(llvm::omp::Directive d, llvm::omp::Clause c) {
+ return d == llvm::omp::Directive::OMPD_declare_reduction &&
+ c == llvm::omp::Clause::OMPC_combiner;
+}
+
+bool OmpStructureChecker::VerifyClauseRequired(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+
+ auto result = VerifyRequired(info, dirName.v, version);
+
+ for (llvm::omp::Clause c : result.first) {
+ // Exceptions:
+ if (version >= 60 && missingCombiner(dirName.v, c)) {
+ continue;
+ }
+
+ context_.Say(dirName.source,
+ "%s clause is required on %s directive"_err_en_US,
+ GetUpperName(c, version), GetUpperName(dirName.v, version));
+ }
+
+ for (llvm::omp::ClauseSet s : result.second) {
+ // If the group is required, at least one clause from that group must
+ // be present.
+ // Note: The tricky part is that when a directive accepts a clause
+ // group, it may still have restrictions that exclude some members of
+ // that group. For example FLUSH accepts memory-order group, but not the
+ // RELAXED clause (note that the memory-order group is not "required").
+ // If such a restriction applied to a required group, we don't want to say
+ // Directive XYZ requires one of FOO, BAR or BAZ clauses
+ // and then
+ // BAZ clause is not allowed on XYZ directive
+ // This hasn't happened yet, but may happen in the future.
+ if (s != llvm::omp::ClauseSet::CancelDirectiveName) {
+ context_.Say(dirName.source, "%s is required on %s directive"_err_en_US,
+ OneOfClauses(s, version), GetUpperName(dirName.v, version));
+ } else {
+ // cancel-directive-name is somewhat special: the ClauseSet doesn't
+ // contain any actual clauses. Moreover, the clauses are cancellable
+ // directive names and have no separate definitions. They are encoded
+ // as directive ids inside OmpCancellationConstructTypeClause with the
+ // id OMPC_cancellation_construct_type.
+ context_.Say(dirName.source,
+ "One of '%s' clauses is required on %s directive"_err_en_US,
+ llvm::omp::getDescriptor(s).getName().str(),
+ GetUpperName(dirName.v, version));
+ }
+ }
+
+ return result.first.empty() && result.second.empty();
+}
+
+bool OmpStructureChecker::VerifyClauseUnique(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+
+ auto result = VerifyUnique(info, dirName.v, version);
+
+ for (auto [id, where] : result) {
+ context_
+ .Say(where.second,
+ "At most one %s clause can appear on %s directive"_err_en_US,
+ GetUpperName(id, version), GetUpperName(dirName.v, version))
+ .Attach(where.first, "previous occurrence of this clause"_en_US);
+ }
+ return result.empty();
+}
+
+bool OmpStructureChecker::VerifyClauseExclusive(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+
+ auto resultExcl = VerifyExclusive(info, dirName.v, version);
+
+ for (auto [id, wrong] : resultExcl) {
+ auto [otherId, source, otherSource] = wrong;
+ context_
+ .Say(source,
+ "%s clause cannot be specified together with a clause of a different type"_err_en_US,
+ GetUpperName(id, version))
+ .Attach(otherSource, "%s provided here"_en_US,
+ GetUpperName(otherId, version));
+ }
+
+ auto resultMut = VerifyMutuallyExclusive(info, dirName.v, version);
+
+ for (auto [id, wrong] : resultMut) {
+ auto [otherId, setId, source, otherSource] = wrong;
+ auto thisName{GetUpperName(id, version)};
+ std::string annot;
+ if (llvm::omp::isClauseGroup(setId)) {
+ auto &sdesc{llvm::omp::getDescriptor(setId)};
+ annot = " as members of '" + sdesc.getName().str() + "' clause group";
+ }
+ context_
+ .Say(otherSource,
+ "%s and %s clauses are mutually exclusive%s"_err_en_US,
+ GetUpperName(otherId, version), thisName, annot)
+ .Attach(source, "%s clause specified here"_en_US, thisName);
+ }
+
+ return resultExcl.empty() && resultMut.empty();
+}
+
+bool OmpStructureChecker::VerifyClauseUltimate(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+
+ auto result = VerifyUltimate(info, dirName.v, version, /*last=*/true);
+
+ for (auto [id, where] : result) {
+ context_.Say(where, "%s should be the last clause"_err_en_US,
+ GetUpperName(id, version));
+ }
+
+ return result.empty();
+}
+
+// Collect the information about clauses specified on the given directive.
+// If a clause is allowed on this directive in "version", store the list of
+// clause sets that the directive allows in "version" in AppliedClause.
+// If a clause is not allowed on this directive in "version", but is allowed
+// on it in another version v, store the list of clause sets that the directive
+// allows in v.
+// In either case, store the applied version in AppliedClause.
+// If the clause is not allowed in any version, the applied version will
+// be the default (i.e. 0) and no sets will be stored.
+AppliedClauseInfo GetAppliedClauses(
+ const parser::OmpDirectiveSpecification *beginSpec,
+ const parser::OmpDirectiveSpecification *endSpec,
+ llvm::omp::Version version) {
+ using AppliedClause = AppliedClauseInfo::ElementTy;
+ AppliedClauseInfo info;
+ llvm::omp::Directive dirId{beginSpec->DirId()};
+ auto &ddesc{llvm::omp::getDescriptor(dirId)};
+
+ auto addClauses = [&](const parser::OmpClauseList &clauses) {
+ for (auto &clause : clauses.v) {
+ auto &am{info.elements.emplace_back(AppliedClause{})};
+ am.id = WithSource{clause.Id(), clause.source};
+ am.version = GetClosestVersion(
+ descriptor::GetVersionRangeForElement(am.id.value, dirId), version);
+ if (am.version) {
+ for (auto s : ddesc.getClauseSets(am.version)) {
+ auto &sdesc{llvm::omp::getDescriptor(s)};
+ if (sdesc.getClauses(am.version).test(am.id.value)) {
+ am.sets.set(s);
+ }
+ }
+ }
+ }
+ };
+
+ addClauses(DEREF(beginSpec).Clauses());
+ if (endSpec) {
+ addClauses(endSpec->Clauses());
+ }
+
+ return info;
+}
+
+bool OmpStructureChecker::VerifyClauseSyntax(
+ parser::OmpDirectiveName dirName, const AppliedClauseInfo &info) {
+ bool valid[]{
+ VerifyClauseVersion(dirName, info),
+ VerifyClauseRequired(dirName, info),
+ VerifyClauseUnique(dirName, info),
+ VerifyClauseExclusive(dirName, info),
+ VerifyClauseUltimate(dirName, info),
+ };
+
+ return llvm::all_of(valid, [](bool x) { return x; });
+}
+
+void OmpStructureChecker::VerifyClauseSyntax(
+ const parser::OmpDirectiveSpecification *beginSpec,
+ const parser::OmpDirectiveSpecification *endSpec) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+
+ if (endSpec) {
+ for (const parser::OmpClause &clause : endSpec->Clauses().v) {
+ llvm::omp::Clause id{clause.Id()};
+ auto &desc{llvm::omp::getDescriptor(id)};
+ if (!desc.getProperties(version).test(llvm::omp::Property::EndClause)) {
+ context_.Say(clause.source,
+ "%s clause is not allowed on an end-directive"_err_en_US,
+ GetUpperName(id, version));
+ }
+ }
+ }
+ VerifyClauseSyntax(
+ beginSpec->DirName(), GetAppliedClauses(beginSpec, endSpec, version));
+}
+
bool OmpStructureChecker::VerifyModifierVersion(
WithSource<llvm::omp::Clause> clause, const AppliedModifierInfo &info) {
// Verify that the specified modifiers are allowed in this version.
@@ -580,4 +850,33 @@ void OmpStructureChecker::VerifyModifierSyntax(const parser::OmpClause &x) {
break;
}
}
+
+// Mark clauseId as allowed on dirId.
+// * If dirId is a compound directive and "since" is a valid version,
+// identify all leafs that allow the clause in version "since" or later,
+// and mark the clause as allowed on these leafs as well.
+// This is intended for allowing a "future case" in the current version.
+// * If dirId is a compound directive and "since" is not a valid version
+// (i.e. !since is true) then mark the clause as allowed on all leafs
+// that allow it in _some_ version. This is intended for allowing
+// "deprecated cases".
+// * If dirId is not a compound directive the "since" parameter is ignored.
+void OmpStructureChecker::SetAllowedClauseOverride(llvm::omp::Clause clauseId,
+ llvm::omp::Directive dirId, llvm::omp::Version since) {
+ omp::SemanticOverrides &overrides{context_.GetOmpSemanticOverrides()};
+ overrides.allowedClauses[clauseId].set(dirId);
+
+ auto leafs{llvm::omp::getLeafConstructsOrSelf(dirId)};
+ if (leafs.size() > 1) {
+ llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+ assert(
+ (!since || since > version) && "\"since\" should be a future version");
+ for (llvm::omp::Directive leaf : leafs) {
+ auto range{descriptor::GetVersionRangeForElement(clauseId, leaf)};
+ if (range.isValid() && (!since || since >= range.Min)) {
+ overrides.allowedClauses[clauseId].set(leaf);
+ }
+ }
+ }
+}
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 7add875c96d883..ab981f688893ad 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -1170,8 +1170,6 @@ void OmpStructureChecker::CheckOmpDeclareVariantDirective(
const parser::traits::OmpContextSelectorSpecification *matchSelector{
getMatchClauseContextSelector(spec)};
if (!matchSelector) {
- context_.Say(x.source,
- "DECLARE_VARIANT directive requires a MATCH clause"_err_en_US);
return;
}
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 16c265ce39690d..0f8f37739a2a84 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -43,6 +43,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
+#include "llvm/Frontend/OpenMP/OMPDescriptors.h"
#include <array>
#include <cinttypes>
@@ -76,7 +77,9 @@ bool IsClauseAllowedOnDirective(llvm::omp::Clause clauseId,
return true;
}
}
- return llvm::omp::isAllowedClauseForDirective(dirId, clauseId, version);
+
+ const auto &desc{llvm::omp::getDescriptor(dirId)};
+ return descriptor::GetAllowedElements(desc, version).test(clauseId);
}
bool IsClauseAllowedOnDirective(llvm::omp::Clause clauseId,
diff --git a/flang/test/Lower/OpenMP/target-kernel-types.f90 b/flang/test/Lower/OpenMP/target-kernel-types.f90
index 50d715ea61486a..2799540116b3fb 100644
--- a/flang/test/Lower/OpenMP/target-kernel-types.f90
+++ b/flang/test/Lower/OpenMP/target-kernel-types.f90
@@ -1,4 +1,4 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-assume-teams-oversubscription -fopenmp-assume-threads-oversubscription -o - %s | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -fopenmp-assume-teams-oversubscription -fopenmp-assume-threads-oversubscription -o - %s | FileCheck %s
! ------------------------------------------------------------------------------
! GENERIC KERNELS
diff --git a/flang/test/Semantics/OpenMP/atomic.f90 b/flang/test/Semantics/OpenMP/atomic.f90
index 773c866e8c731c..d54262e3b8e519 100644
--- a/flang/test/Semantics/OpenMP/atomic.f90
+++ b/flang/test/Semantics/OpenMP/atomic.f90
@@ -35,7 +35,7 @@
a = a + 1
!$omp end atomic
- !ERROR: At most one clause from the 'atomic' group is allowed on ATOMIC construct
+ !ERROR: READ and WRITE clauses are mutually exclusive as members of 'atomic' clause group
!$omp atomic read write
!ERROR: Atomic expression a+1._4 should be a variable
a = a + 1
diff --git a/flang/test/Semantics/OpenMP/atomic05.f90 b/flang/test/Semantics/OpenMP/atomic05.f90
index 1c67b9354cf2c7..a1d8b19bbad963 100644
--- a/flang/test/Semantics/OpenMP/atomic05.f90
+++ b/flang/test/Semantics/OpenMP/atomic05.f90
@@ -5,20 +5,20 @@
program OmpAtomic
integer :: g, x
- !ERROR: At most one clause from the 'memory-order' group is allowed on ATOMIC construct
+ !ERROR: RELAXED and SEQ_CST clauses are mutually exclusive as members of 'memory-order' clause group
!$omp atomic relaxed, seq_cst
x = x + 1
- !ERROR: At most one clause from the 'memory-order' group is allowed on ATOMIC construct
+ !ERROR: SEQ_CST and RELAXED clauses are mutually exclusive as members of 'memory-order' clause group
!$omp atomic read seq_cst, relaxed
x = g
- !ERROR: At most one clause from the 'memory-order' group is allowed on ATOMIC construct
+ !ERROR: RELAXED and RELEASE clauses are mutually exclusive as members of 'memory-order' clause group
!$omp atomic write relaxed, release
x = 2 * 4
- !ERROR: At most one clause from the 'memory-order' group is allowed on ATOMIC construct
+ !ERROR: RELEASE and SEQ_CST clauses are mutually exclusive as members of 'memory-order' clause group
!$omp atomic update release, seq_cst
!ERROR: This is not a valid ATOMIC UPDATE operation
x = 10
- !ERROR: At most one clause from the 'memory-order' group is allowed on ATOMIC construct
+ !ERROR: RELEASE and SEQ_CST clauses are mutually exclusive as members of 'memory-order' clause group
!$omp atomic capture release, seq_cst
x = g
g = x * 10
diff --git a/flang/test/Semantics/OpenMP/cancel.f90 b/flang/test/Semantics/OpenMP/cancel.f90
index 6147d581c4e69e..24c23fcbe42475 100644
--- a/flang/test/Semantics/OpenMP/cancel.f90
+++ b/flang/test/Semantics/OpenMP/cancel.f90
@@ -2,28 +2,28 @@
subroutine f00
!$omp parallel
-!ERROR: Missing cancel-directive-name clause on the CANCEL construct
+!ERROR: cancel-directive-name clause is required on CANCEL directive
!$omp cancel
!$omp end parallel
end
subroutine f01
!$omp parallel
-!ERROR: Multiple cancel-directive-name clauses are not allowed on CANCEL construct
+!ERROR: At most one cancel-directive-name clause can appear on CANCEL directive
!$omp cancel parallel parallel
!$omp end parallel
end
subroutine f02
!$omp parallel
-!ERROR: Missing cancel-directive-name clause on the CANCELLATION POINT construct
+!ERROR: cancel-directive-name clause is required on CANCELLATION POINT directive
!$omp cancellation point
!$omp end parallel
end
subroutine f03
!$omp parallel
-!ERROR: Multiple cancel-directive-name clauses are not allowed on CANCELLATION POINT construct
+!ERROR: At most one cancel-directive-name clause can appear on CANCELLATION POINT directive
!$omp cancellation point parallel parallel
!$omp end parallel
end
diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90
index 62c45818822c68..861d07ec4c59ed 100644
--- a/flang/test/Semantics/OpenMP/clause-validity01.f90
+++ b/flang/test/Semantics/OpenMP/clause-validity01.f90
@@ -84,7 +84,8 @@
end do
!$omp end target
- !ERROR: ALLOCATE clause is not allowed on TARGET DATA directive
+ !ERROR: ALLOCATE clause is not allowed on TARGET DATA directive in OpenMP v5.2, try -fopenmp-version=60 [-Wopenmp-future]
+ !ERROR: The ALLOCATE clause requires that 'b' must be listed in a private data-sharing attribute clause on the same directive
!$omp target data map(from: b) allocate(b)
do i = 1, N
z = 2
@@ -286,6 +287,7 @@
!$omp section
c = 1
d = 2
+ !ERROR: NUM_THREADS clause is not allowed on SECTIONS directive
!ERROR: NUM_THREADS clause is not allowed on an end-directive
!$omp end sections num_threads(4)
@@ -324,7 +326,6 @@
!$omp end sections
!$omp parallel sections
- !ERROR: NOWAIT clause is not allowed on PARALLEL SECTIONS directive
!$omp end parallel sections nowait
! 2.7.3 single-clause -> private-clause |
@@ -335,7 +336,7 @@
!$omp parallel
b = 1
!ERROR: LASTPRIVATE clause is not allowed on SINGLE directive
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: NOWAIT and COPYPRIVATE clauses are mutually exclusive
!$omp single private(a) lastprivate(c) nowait
a = 3.14
!ERROR: COPYPRIVATE variable 'a' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
@@ -470,7 +471,7 @@
a = 3.14
enddo
- !ERROR: GRAINSIZE and NUM_TASKS clauses are mutually exclusive and may not appear on the same TASKLOOP directive
+ !ERROR: NUM_TASKS and GRAINSIZE clauses are mutually exclusive
!$omp taskloop num_tasks(3) grainsize(2)
do i = 1,N
a = 3.14
@@ -523,12 +524,12 @@
!WARNING: The syntax "FLUSH clause (object, ...)" has been deprecated, use "FLUSH(object, ...) clause" instead
!$omp flush acquire
!WARNING: The syntax "FLUSH clause (object, ...)" has been deprecated, use "FLUSH(object, ...) clause" instead
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush release (c)
!WARNING: The syntax "FLUSH clause (object, ...)" has been deprecated, use "FLUSH(object, ...) clause" instead
!$omp flush seq_cst
!WARNING: The syntax "FLUSH clause (object, ...)" has been deprecated, use "FLUSH(object, ...) clause" instead
- !ERROR: RELAXED clause is not allowed on FLUSH directive
+ !ERROR: 'memory-order' cannot be RELAXED on FLUSH directive
!$omp flush relaxed
! 2.13.2 critical Construct
@@ -584,7 +585,7 @@
!ERROR: Misplaced OpenMP end-directive
!$omp end taskloop
- !ERROR: GRAINSIZE and NUM_TASKS clauses are mutually exclusive and may not appear on the same TASKLOOP SIMD directive
+ !ERROR: NUM_TASKS and GRAINSIZE clauses are mutually exclusive
!$omp taskloop simd num_tasks(3) grainsize(2)
do i = 1,N
a = 3.14
diff --git a/flang/test/Semantics/OpenMP/clause-validity02.f90 b/flang/test/Semantics/OpenMP/clause-validity02.f90
index 1906df9d0eb477..b9c84797cbf742 100644
--- a/flang/test/Semantics/OpenMP/clause-validity02.f90
+++ b/flang/test/Semantics/OpenMP/clause-validity02.f90
@@ -3,8 +3,20 @@
subroutine bad_in_45(h_ptr)
integer, pointer :: h_ptr
!ERROR: USE_DEVICE_ADDR clause is not allowed on TARGET DATA directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
- !ERROR: At least one of MAP, USE_DEVICE_PTR clauses must appear on TARGET DATA directive
+ !ERROR: MAP clause is required on TARGET DATA directive
!$omp target data use_device_addr(h_ptr)
!$omp end target data
end
+subroutine f02(N)
+ integer :: N
+ integer :: i, j
+ real :: a
+ !ERROR: ORDERED clause with an argument is not allowed on a compound directive with SIMD as a constituent
+ !$omp do simd ordered(2)
+ do i = 1, N
+ do j = 1, N
+ a = 3.14
+ enddo
+ enddo
+end
diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90
index c01998b1fa1b00..560ecb10332965 100644
--- a/flang/test/Semantics/OpenMP/combined-constructs.f90
+++ b/flang/test/Semantics/OpenMP/combined-constructs.f90
@@ -53,7 +53,7 @@ program main
enddo
!$omp end target parallel
- !ERROR: COPYIN clause is not allowed on TARGET PARALLEL directive
+ !ERROR: COPYIN clause is not allowed on a compound directive with TARGET as a constituent
!ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause
!$omp target parallel copyin(a)
do i = 1, N
@@ -100,7 +100,7 @@ program main
enddo
!$omp end target parallel do
- !ERROR: COPYIN clause is not allowed on TARGET PARALLEL DO directive
+ !ERROR: COPYIN clause is not allowed on a compound directive with TARGET as a constituent
!ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause
!$omp target parallel do copyin(a)
do i = 1, N
diff --git a/flang/test/Semantics/OpenMP/declarative-directive01.f90 b/flang/test/Semantics/OpenMP/declarative-directive01.f90
index 9e0612b5c8b53b..42b667e1f7afdf 100644
--- a/flang/test/Semantics/OpenMP/declarative-directive01.f90
+++ b/flang/test/Semantics/OpenMP/declarative-directive01.f90
@@ -38,7 +38,7 @@ end module m1
subroutine declare_simd_2
use m1
procedure (sub) sub1
- !ERROR: INBRANCH and NOTINBRANCH clauses are mutually exclusive and may not appear on the same DECLARE SIMD directive
+ !ERROR: INBRANCH and NOTINBRANCH clauses are mutually exclusive as members of 'branch' clause group
!$omp declare simd(sub1) inbranch notinbranch
procedure (sub), pointer::p
p=>sub1
@@ -60,6 +60,7 @@ subroutine foo
!WARNING: The entity with PARAMETER attribute is used in a DECLARE TARGET directive [-Wopenmp-usage]
!WARNING: The entity with PARAMETER attribute is used in a DECLARE TARGET directive [-Wopenmp-usage]
!$omp declare target (foo, N, M)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
@@ -69,6 +70,7 @@ subroutine foo
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target enter(Q, S) link(R)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!ERROR: MAP clause is not allowed on DECLARE TARGET directive
diff --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90
index b498cf649126da..b48cfb5b98de0e 100644
--- a/flang/test/Semantics/OpenMP/declare-target01.f90
+++ b/flang/test/Semantics/OpenMP/declare-target01.f90
@@ -48,16 +48,19 @@ module declare_target01
!ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
!$omp declare target (y%KIND)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var)
!$omp declare target enter (my_var)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var) device_type(host)
!$omp declare target enter (my_var) device_type(host)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: A structure component cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var%t_i)
@@ -65,6 +68,7 @@ module declare_target01
!ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target enter (my_var%t_i)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: A structure component cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var%t_arr)
@@ -72,6 +76,7 @@ module declare_target01
!ERROR: A structure component cannot appear on the DECLARE TARGET directive
!$omp declare target enter (my_var%t_arr)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var%kind_param)
@@ -79,6 +84,7 @@ module declare_target01
!ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (my_var%kind_param)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (my_var%len_param)
@@ -86,16 +92,19 @@ module declare_target01
!ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (my_var%len_param)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr)
!$omp declare target enter (arr)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr) device_type(nohost)
!$omp declare target enter (arr) device_type(nohost)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: An array element cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr(1))
@@ -103,6 +112,7 @@ module declare_target01
!ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target enter (arr(1))
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: An array element cannot appear on the DECLARE TARGET directive
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr(1:2))
@@ -110,6 +120,7 @@ module declare_target01
!ERROR: An array element cannot appear on the DECLARE TARGET directive
!$omp declare target enter (arr(1:2))
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (x%KIND)
@@ -117,6 +128,7 @@ module declare_target01
!ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (x%KIND)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (w%LEN)
@@ -124,6 +136,7 @@ module declare_target01
!ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
!$omp declare target enter (w%LEN)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!ERROR: Type parameter inquiry is not allowed as a list item on TO clause
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (y%KIND)
diff --git a/flang/test/Semantics/OpenMP/declare-target02.f90 b/flang/test/Semantics/OpenMP/declare-target02.f90
index db9e51a197b2c0..1157a8747cfc47 100644
--- a/flang/test/Semantics/OpenMP/declare-target02.f90
+++ b/flang/test/Semantics/OpenMP/declare-target02.f90
@@ -16,16 +16,19 @@ program declare_target02
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target (a1)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr1_to)
!$omp declare target enter (arr1_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (blk1_to)
!$omp declare target enter (blk1_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target to (a1_to)
@@ -44,6 +47,7 @@ program declare_target02
!ERROR: A variable in a DECLARE TARGET directive cannot appear in an EQUIVALENCE statement
!$omp declare target (eq_a)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot appear in an EQUIVALENCE statement
!$omp declare target to (eq_a)
@@ -57,6 +61,7 @@ program declare_target02
!ERROR: A variable in a DECLARE TARGET directive cannot appear in an EQUIVALENCE statement
!$omp declare target (eq_c)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot appear in an EQUIVALENCE statement
!$omp declare target to (eq_c)
@@ -87,6 +92,7 @@ subroutine func()
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target (a3)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target to (arr2_to)
@@ -94,11 +100,13 @@ subroutine func()
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target enter (arr2_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr3_to)
!$omp declare target enter (arr3_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target to (a2_to)
@@ -106,6 +114,7 @@ subroutine func()
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target enter (a2_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target to (a3_to)
@@ -137,15 +146,18 @@ module mod4
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target (a4)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (arr4_to)
!$omp declare target enter (arr4_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to (blk4_to)
!$omp declare target enter (blk4_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target to (a4_to)
@@ -174,6 +186,7 @@ subroutine func5()
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target (a5)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target to (arr5_to)
@@ -181,6 +194,7 @@ subroutine func5()
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target enter (arr5_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target to (blk5_to)
@@ -188,6 +202,7 @@ subroutine func5()
!ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly
!$omp declare target enter (blk5_to)
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block
!$omp declare target to (a5_to)
diff --git a/flang/test/Semantics/OpenMP/declare-target06.f90 b/flang/test/Semantics/OpenMP/declare-target06.f90
index 5dc4b8042ce1dd..5341aa73267de6 100644
--- a/flang/test/Semantics/OpenMP/declare-target06.f90
+++ b/flang/test/Semantics/OpenMP/declare-target06.f90
@@ -12,6 +12,7 @@ module test_0
!ERROR: No explicit type declared for 'no_implicit_materialization_2'
!$omp declare target link(no_implicit_materialization_2)
+!WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!ERROR: No explicit type declared for 'no_implicit_materialization_3'
!$omp declare target to(no_implicit_materialization_3)
diff --git a/flang/test/Semantics/OpenMP/declare-variant-match.f90 b/flang/test/Semantics/OpenMP/declare-variant-match.f90
index 73558dc171b692..5cd82aaa36044b 100644
--- a/flang/test/Semantics/OpenMP/declare-variant-match.f90
+++ b/flang/test/Semantics/OpenMP/declare-variant-match.f90
@@ -97,7 +97,7 @@ subroutine sub
end subroutine
subroutine f08
-!ERROR: DECLARE_VARIANT directive requires a MATCH clause
+!ERROR: MATCH clause is required on DECLARE VARIANT directive
!$omp declare variant (sub:vsub)
contains
subroutine vsub
diff --git a/flang/test/Semantics/OpenMP/depobj-construct-v50.f90 b/flang/test/Semantics/OpenMP/depobj-construct-v50.f90
index ce030a1082bde3..1fc0760ba50928 100644
--- a/flang/test/Semantics/OpenMP/depobj-construct-v50.f90
+++ b/flang/test/Semantics/OpenMP/depobj-construct-v50.f90
@@ -40,6 +40,6 @@ subroutine f05
subroutine f06
integer :: obj
-!ERROR: The DEPOBJ construct requires a single clause
+!ERROR: UPDATE (depend-objects) and DESTROY clauses are mutually exclusive
!$omp depobj(obj) update(in) destroy
end
diff --git a/flang/test/Semantics/OpenMP/detach02.f90 b/flang/test/Semantics/OpenMP/detach02.f90
index f0e53b92edf6d0..811e4a5de3dd61 100644
--- a/flang/test/Semantics/OpenMP/detach02.f90
+++ b/flang/test/Semantics/OpenMP/detach02.f90
@@ -14,7 +14,7 @@ program detach02
x = x + 1
!$omp end task
- !ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
+ !ERROR: DETACH and MERGEABLE clauses are mutually exclusive
!$omp task detach(event_01) mergeable
x = x + 1
!$omp end task
diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90
index b74304222c8351..7e950751fea030 100644
--- a/flang/test/Semantics/OpenMP/device-constructs.f90
+++ b/flang/test/Semantics/OpenMP/device-constructs.f90
@@ -144,7 +144,7 @@ program main
cptr = c_null_ptr
!$omp end target data
- !ERROR: At least one of MAP, USE_DEVICE_ADDR, USE_DEVICE_PTR clauses must appear on TARGET DATA directive
+ !ERROR: One of MAP, USE_DEVICE_ADDR or USE_DEVICE_PTR clauses is required on TARGET DATA directive
!$omp target data device(0)
do i = 1, N
a = 3.14d0
diff --git a/flang/test/Semantics/OpenMP/flush02.f90 b/flang/test/Semantics/OpenMP/flush02.f90
index db0cc12398b970..dbb33d4de03636 100644
--- a/flang/test/Semantics/OpenMP/flush02.f90
+++ b/flang/test/Semantics/OpenMP/flush02.f90
@@ -28,7 +28,7 @@
if (omp_get_thread_num() == 1) THEN
! Not allowed clauses.
!$omp flush seq_cst
- !ERROR: RELAXED clause is not allowed on FLUSH directive
+ !ERROR: 'memory-order' cannot be RELAXED on FLUSH directive
!$omp flush relaxed
! Not allowed more than once.
@@ -39,7 +39,7 @@
!ERROR: At most one ACQUIRE clause can appear on FLUSH directive
!$omp flush acquire acquire
- ! Mix of allowed and not allowed.
+ !ERROR: SEQ_CST and ACQUIRE clauses are mutually exclusive as members of 'memory-order' clause group
!$omp flush seq_cst acquire
END IF
@@ -57,21 +57,21 @@
array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/)
if (omp_get_thread_num() == 3) THEN
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush acq_rel (array)
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush acq_rel (array, a, i)
array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/)
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush release (array)
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush release (array, a)
array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/)
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush acquire (array)
- !ERROR: If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive
+ !ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!$omp flush acquire (array, a, structObj%rr)
END IF
!$omp end parallel
diff --git a/flang/test/Semantics/OpenMP/flush03.f90 b/flang/test/Semantics/OpenMP/flush03.f90
index 82c5bef5f5b8d6..d92555c341d502 100644
--- a/flang/test/Semantics/OpenMP/flush03.f90
+++ b/flang/test/Semantics/OpenMP/flush03.f90
@@ -2,6 +2,7 @@
subroutine f00(x)
integer :: x
+!ERROR: If a 'memory-order' clause is specified, list items must not be specified on the FLUSH directive
!ERROR: The syntax "FLUSH clause (object, ...)" has been deprecated, use "FLUSH(object, ...) clause" instead
!$omp flush seq_cst (x)
end
diff --git a/flang/test/Semantics/OpenMP/if-clause-45.f90 b/flang/test/Semantics/OpenMP/if-clause-45.f90
index 1ed2fcf8c0ae1a..5b34090d41d903 100644
--- a/flang/test/Semantics/OpenMP/if-clause-45.f90
+++ b/flang/test/Semantics/OpenMP/if-clause-45.f90
@@ -77,7 +77,6 @@ program main
end do
!$omp end distribute simd
- !ERROR: IF clause is not allowed on DISTRIBUTE SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: IF clause is not allowed on DISTRIBUTE SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
!$omp distribute simd if(.true.) if(simd: .false.)
@@ -109,7 +108,6 @@ program main
end do
!$omp end do simd
- !ERROR: IF clause is not allowed on DO SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: IF clause is not allowed on DO SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
!$omp do simd if(.true.) if(simd: .false.)
@@ -236,7 +234,6 @@ program main
end do
!$omp end simd
- !ERROR: IF clause is not allowed on SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: IF clause is not allowed on SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
!$omp simd if(.true.) if(simd: .false.)
@@ -569,7 +566,6 @@ program main
!$omp teams if(target: .true.)
!$omp end teams
- !ERROR: IF clause is not allowed on TEAMS directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: IF clause is not allowed on TEAMS directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
!$omp teams if(.true.) if(teams: .false.)
@@ -578,23 +574,27 @@ program main
! ----------------------------------------------------------------------------
! TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!$omp teams distribute if(.true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
!$omp teams distribute if(teams: .true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE directive
!$omp teams distribute if(target: .true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v4.5, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
!$omp teams distribute if(.true.) if(teams: .true.)
do i = 1, 10
@@ -652,7 +652,6 @@ program main
end do
!$omp end teams distribute simd
- !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: IF clause is not allowed on TEAMS DISTRIBUTE SIMD directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
!ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
diff --git a/flang/test/Semantics/OpenMP/if-clause-50.f90 b/flang/test/Semantics/OpenMP/if-clause-50.f90
index 651b62d6a43448..94cd8d3133519a 100644
--- a/flang/test/Semantics/OpenMP/if-clause-50.f90
+++ b/flang/test/Semantics/OpenMP/if-clause-50.f90
@@ -544,7 +544,6 @@ program main
!$omp teams if(target: .true.)
!$omp end teams
- !ERROR: IF clause is not allowed on TEAMS directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: IF clause is not allowed on TEAMS directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v5.0, try -fopenmp-version=52
!$omp teams if(.true.) if(teams: .false.)
@@ -553,23 +552,27 @@ program main
! ----------------------------------------------------------------------------
! TEAMS DISTRIBUTE
! ----------------------------------------------------------------------------
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!$omp teams distribute if(.true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v5.0, try -fopenmp-version=52
!$omp teams distribute if(teams: .true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE directive
!$omp teams distribute if(target: .true.)
do i = 1, 10
end do
!$omp end teams distribute
+ !ERROR: IF clause is not allowed on TEAMS DISTRIBUTE directive in OpenMP v5.0, try -fopenmp-version=52 [-Wopenmp-future]
!ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v5.0, try -fopenmp-version=52
!$omp teams distribute if(.true.) if(teams: .true.)
do i = 1, 10
diff --git a/flang/test/Semantics/OpenMP/interop-construct.f90 b/flang/test/Semantics/OpenMP/interop-construct.f90
index 69484d77b05e11..7f3cc5b3b03b95 100644
--- a/flang/test/Semantics/OpenMP/interop-construct.f90
+++ b/flang/test/Semantics/OpenMP/interop-construct.f90
@@ -154,7 +154,7 @@ END SUBROUTINE test_interop_17
! only a device (or other non-action) clause is invalid.
SUBROUTINE test_interop_18(dev)
INTEGER :: dev
- !ERROR: At least one action-clause (INIT, USE, or DESTROY) must appear on the INTEROP construct
+ !ERROR: One of DESTROY, INIT or USE clauses is required on INTEROP directive
!$OMP INTEROP DEVICE(dev)
PRINT *, 'pass'
END SUBROUTINE test_interop_18
diff --git a/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90 b/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90
index 10affbb4fd4746..5369f1cf7a7cc4 100644
--- a/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90
+++ b/flang/test/Semantics/OpenMP/loop-transformation-construct01.f90
@@ -19,7 +19,7 @@ subroutine loop_transformation_construct2
integer :: v(i)
!$omp do
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
do x = 1, i
v(x) = v(x) * 2
@@ -54,7 +54,7 @@ subroutine loop_transformation_construct4
v(x) = v(x) * 2
end do
!ERROR: This construct should contain a DO-loop or a loop-nest-generating construct
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
end subroutine
@@ -66,7 +66,7 @@ subroutine loop_transformation_construct5
!$omp do
!ERROR: This construct requires a canonical loop nest
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
!BECAUSE: Fully unrolled loop does not result in a loop nest
!$omp unroll full
@@ -83,7 +83,7 @@ subroutine loop_transformation_construct6
!$omp do
!ERROR: This construct requires a canonical loop nest
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
!BECAUSE: Fully unrolled loop does not result in a loop nest
!$omp unroll
@@ -99,7 +99,7 @@ subroutine loop_transformation_construct7
integer :: v(i)
!$omp do
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
!$omp unroll partial(2)
do x = 1, i
diff --git a/flang/test/Semantics/OpenMP/ordered03.f90 b/flang/test/Semantics/OpenMP/ordered03.f90
index ca5e3bf151b415..90e053ed58b6ef 100644
--- a/flang/test/Semantics/OpenMP/ordered03.f90
+++ b/flang/test/Semantics/OpenMP/ordered03.f90
@@ -52,7 +52,7 @@ subroutine sub1()
end do
!$omp end target parallel do
- !ERROR: ORDERED clause is not allowed on TARGET TEAMS DISTRIBUTE PARALLEL DO directive
+ !ERROR: ORDERED clause is not allowed on a compound directive with DISTRIBUTE as a constituent
!$omp target teams distribute parallel do ordered(1)
do i = 1, N
!ERROR: An ORDERED construct with the DEPEND clause must be closely nested in a worksharing-loop (or parallel worksharing-loop) construct with ORDERED clause with a parameter
diff --git a/flang/test/Semantics/OpenMP/requires01.f90 b/flang/test/Semantics/OpenMP/requires01.f90
index 9153f7ddf91b77..717ac9fff588bb 100644
--- a/flang/test/Semantics/OpenMP/requires01.f90
+++ b/flang/test/Semantics/OpenMP/requires01.f90
@@ -3,6 +3,7 @@
!WARNING: REVERSE_OFFLOAD clause is not supported and will be ignored
!$omp requires reverse_offload unified_shared_memory
+!ERROR: One of ATOMIC_DEFAULT_MEM_ORDER, DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, UNIFIED_ADDRESS or UNIFIED_SHARED_MEMORY clauses is required on REQUIRES directive
!ERROR: NOWAIT clause is not allowed on REQUIRES directive
!$omp requires nowait
end
diff --git a/flang/test/Semantics/OpenMP/requires04.f90 b/flang/test/Semantics/OpenMP/requires04.f90
index e392564c523d53..70767817a8fae4 100644
--- a/flang/test/Semantics/OpenMP/requires04.f90
+++ b/flang/test/Semantics/OpenMP/requires04.f90
@@ -7,6 +7,7 @@
subroutine f
integer, save :: x
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to(x) device_type(nohost)
!$omp declare target enter(x) device_type(nohost)
diff --git a/flang/test/Semantics/OpenMP/requires05.f90 b/flang/test/Semantics/OpenMP/requires05.f90
index 31f0b29edddda3..fb428410c73e2a 100644
--- a/flang/test/Semantics/OpenMP/requires05.f90
+++ b/flang/test/Semantics/OpenMP/requires05.f90
@@ -6,6 +6,7 @@
! clause and no device_type.
subroutine f
+ !WARNING: TO clause is no longer allowed on DECLARE TARGET directive since OpenMP v5.2 [-Wopenmp-deprecated]
!WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-deprecated]
!$omp declare target to(f)
!$omp declare target enter(f)
diff --git a/flang/test/Semantics/OpenMP/scan1.f90 b/flang/test/Semantics/OpenMP/scan1.f90
index e6b1ccf695fff9..8138bea60cf85f 100644
--- a/flang/test/Semantics/OpenMP/scan1.f90
+++ b/flang/test/Semantics/OpenMP/scan1.f90
@@ -9,25 +9,26 @@ subroutine test_scan()
!$omp parallel do simd
do k = 1, n
!ERROR: UNTIED clause is not allowed on SCAN directive
+ !ERROR: One of EXCLUSIVE or INCLUSIVE clauses is required on SCAN directive
!$omp scan untied
end do
!$omp parallel do simd
do k = 1, n
- !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected
+ !ERROR: One of EXCLUSIVE or INCLUSIVE clauses is required on SCAN directive
!$omp scan
end do
!$omp parallel do simd reduction(inscan,+: x, y)
do k = 1, n
- !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected
+ !ERROR: INCLUSIVE and EXCLUSIVE clauses are mutually exclusive
!$omp scan inclusive(x) exclusive(y)
end do
!ERROR: List item y must appear in EXCLUSIVE or INCLUSIVE clause of an enclosed SCAN directive
!$omp parallel do simd reduction(inscan,+: x, y)
do k = 1, n
- !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected
+ !ERROR: INCLUSIVE and EXCLUSIVE clauses are mutually exclusive
!ERROR: List item z must appear in REDUCTION clause with the INSCAN modifier of the parent directive
!$omp scan inclusive(x) exclusive(z)
end do
diff --git a/flang/test/Semantics/OpenMP/single03.f90 b/flang/test/Semantics/OpenMP/single03.f90
index d082be4a142e47..601e45f776426a 100644
--- a/flang/test/Semantics/OpenMP/single03.f90
+++ b/flang/test/Semantics/OpenMP/single03.f90
@@ -6,7 +6,7 @@ subroutine omp_single
i = 10; j = 11
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp single copyprivate(i) nowait
print *, "omp single", i
!$omp end single
@@ -18,16 +18,16 @@ subroutine omp_single
!$omp end parallel
!$omp parallel
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: NOWAIT and COPYPRIVATE clauses are mutually exclusive
!$omp single nowait
print *, "omp single", i
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
!$omp end single copyprivate(i)
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context
!$omp single copyprivate(i)
print *, "omp single", i
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
!$omp end single nowait
!ERROR: COPYPRIVATE variable 'j' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct
diff --git a/flang/test/Semantics/OpenMP/single04.f90 b/flang/test/Semantics/OpenMP/single04.f90
index 1eac263c95764b..328f80557af4d2 100644
--- a/flang/test/Semantics/OpenMP/single04.f90
+++ b/flang/test/Semantics/OpenMP/single04.f90
@@ -21,7 +21,7 @@ program single
! Invalid testcases
!$omp single
print *, x
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp end single copyprivate(x) nowait
!ERROR: 'x' appears more than once in a COPYPRIVATE clause
@@ -44,20 +44,20 @@ program single
!ERROR: At most one NOWAIT clause can appear on SINGLE directive
!$omp end single nowait nowait
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp single copyprivate(x) nowait
print *, x
!ERROR: 'x' appears more than once in a COPYPRIVATE clause
!ERROR: At most one NOWAIT clause can appear on SINGLE directive
!$omp end single copyprivate(x) nowait
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp single copyprivate(x)
print *, x
!ERROR: 'x' appears more than once in a COPYPRIVATE clause
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
!$omp end single copyprivate(x) nowait
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp single copyprivate(x, y) nowait
print *, x
!ERROR: 'x' appears more than once in a COPYPRIVATE clause
@@ -65,7 +65,7 @@ program single
!ERROR: At most one NOWAIT clause can appear on SINGLE directive
!$omp end single copyprivate(x, z) copyprivate(z) nowait
- !ERROR: NOWAIT clause must not be used with COPYPRIVATE clause on SINGLE directive
+ !ERROR: COPYPRIVATE and NOWAIT clauses are mutually exclusive
!$omp single copyprivate(x) nowait copyprivate(y) copyprivate(z)
print *, x
!ERROR: 'x' appears more than once in a COPYPRIVATE clause
diff --git a/flang/test/Semantics/OpenMP/target-update01.f90 b/flang/test/Semantics/OpenMP/target-update01.f90
index a7a12b96e85454..a69e628f357907 100644
--- a/flang/test/Semantics/OpenMP/target-update01.f90
+++ b/flang/test/Semantics/OpenMP/target-update01.f90
@@ -2,10 +2,10 @@
subroutine foo(x)
integer :: x
- !ERROR: At least one motion-clause (TO/FROM) must be specified on TARGET UPDATE construct.
+ !ERROR: One of FROM or TO clauses is required on TARGET UPDATE directive
!$omp target update
- !ERROR: At least one motion-clause (TO/FROM) must be specified on TARGET UPDATE construct.
+ !ERROR: One of FROM or TO clauses is required on TARGET UPDATE directive
!$omp target update nowait
!$omp target update to(x) nowait
diff --git a/flang/test/Semantics/OpenMP/task-45.f90 b/flang/test/Semantics/OpenMP/task-45.f90
index 64b7cf765f8d2d..7c6e7a6e8c3ff1 100644
--- a/flang/test/Semantics/OpenMP/task-45.f90
+++ b/flang/test/Semantics/OpenMP/task-45.f90
@@ -7,7 +7,7 @@
subroutine f
use omp_lib, only: omp_event_handle_kind
integer(kind=omp_event_handle_kind) :: e
- !ERROR: Clause MERGEABLE is not allowed if clause DETACH appears on the TASK directive
+ !ERROR: MERGEABLE and DETACH clauses are mutually exclusive
!WARNING: DETACH clause is not allowed on TASK directive in OpenMP v4.5, try -fopenmp-version=50 [-Wopenmp-future]
!$omp task mergeable detach(e)
!$omp end task
diff --git a/flang/test/Semantics/OpenMP/tile01.f90 b/flang/test/Semantics/OpenMP/tile01.f90
index 2e98586bef8fc8..dc1b5b9d48a4fe 100644
--- a/flang/test/Semantics/OpenMP/tile01.f90
+++ b/flang/test/Semantics/OpenMP/tile01.f90
@@ -6,7 +6,7 @@ subroutine missing_sizes
implicit none
integer i
- !ERROR: At least one of SIZES clause must appear on TILE directive
+ !ERROR: SIZES clause is required on TILE directive
!$omp tile
do i = 1, 42
print *, i
diff --git a/flang/test/Semantics/OpenMP/unroll-clauses.f90 b/flang/test/Semantics/OpenMP/unroll-clauses.f90
index 68dd47ce29b921..f524058c8fef29 100644
--- a/flang/test/Semantics/OpenMP/unroll-clauses.f90
+++ b/flang/test/Semantics/OpenMP/unroll-clauses.f90
@@ -8,7 +8,7 @@ subroutine unroll_clauses
integer :: i
integer :: v(n)
- !ERROR: FULL and PARTIAL clauses are mutually exclusive and may not appear on the same UNROLL directive
+ !ERROR: FULL and PARTIAL clauses are mutually exclusive
!$omp unroll full partial(2)
do i = 1, n
v(i) = i
diff --git a/flang/test/Semantics/OpenMP/workdistribute04.f90 b/flang/test/Semantics/OpenMP/workdistribute04.f90
index d407e8a073ae40..bb6d635f833c29 100644
--- a/flang/test/Semantics/OpenMP/workdistribute04.f90
+++ b/flang/test/Semantics/OpenMP/workdistribute04.f90
@@ -1,4 +1,4 @@
-! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -Werror -Wno-experimental-option
! OpenMP Version 6.0
! workdistribute Construct
! Unsuported OpenMP version
diff --git a/flang/test/Semantics/indirect02.f90 b/flang/test/Semantics/indirect02.f90
index 3fae39f1c22813..65135615d30c79 100644
--- a/flang/test/Semantics/indirect02.f90
+++ b/flang/test/Semantics/indirect02.f90
@@ -1,6 +1,6 @@
! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive
-! RUN: not %flang -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s --check-prefix="CHECK-50"
+! RUN: not %flang -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s --check-prefixes="CHECK-50","CHECK-52"
! RUN: not %flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s --check-prefix="CHECK-52"
module functions
@@ -14,7 +14,7 @@ function func() result(i)
contains
function func1() result(i)
- !CHECK-50: INDIRECT clause is not allowed on DECLARE TARGET directive in OpenMP v5.0, try -fopenmp-version=51
+ !CHECK-50: INDIRECT clause is not allowed on DECLARE TARGET directive in OpenMP v5.0, try -fopenmp-version=51 [-Wopenmp-future]
!CHECK-52: not yet implemented: Unhandled clause INDIRECT in DECLARE TARGET construct
!$omp declare target enter(func1) indirect(.true.)
character(1) :: i
More information about the llvm-branch-commits
mailing list