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 <[email protected]> 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
