[llvm-branch-commits] [flang] [flang][OpenMP] Remove OmpVerifyModifiers (PR #218508)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 25 06:09:51 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/218508
>From 531cebb28ce8b15c4cb9af09d215816dc440e329 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 21 Aug 2026 11:08:31 -0500
Subject: [PATCH] [flang][OpenMP] Remove OmpVerifyModifiers
Verification of clause modifiers is now done in a single place.
The OmpVerifyModifiers function was left in place, but was reduced
to always return "true".
Remove the definition and all calls to it.
The large amount of apparent changes is mostly due to unindenting
and reformatting previously indented code.
---
.../flang/Semantics/openmp-modifiers.h | 6 -
flang/lib/Semantics/check-omp-loop.cpp | 95 ++--
flang/lib/Semantics/check-omp-structure.cpp | 442 +++++++-----------
flang/lib/Semantics/check-omp-structure.h | 2 -
flang/lib/Semantics/check-omp-variant.cpp | 2 -
5 files changed, 221 insertions(+), 326 deletions(-)
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index a045a92b951e4..2045749f2e59f 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -192,12 +192,6 @@ Fortran::parser::CharBlock OmpGetModifierSource(
}
llvm_unreachable("`specific` must be a member of `modifiers`");
}
-
-template <typename ClauseTy>
-bool OmpVerifyModifiers(const ClauseTy &clause, llvm::omp::Clause id,
- parser::CharBlock clauseSource, SemanticsContext &semaCtx) {
- return true;
-}
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 7c73ba8f17802..f587cfa6ba4d4 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -762,7 +762,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
unsigned version{context_.langOptions().OpenMPVersion};
llvm::omp::Directive dir{GetContext().directive};
- parser::CharBlock clauseSource{GetContext().clauseSource};
const parser::OmpLinearModifier *linearMod{nullptr};
SymbolSourceMap symbols;
@@ -780,61 +779,59 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
}};
- if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_linear, clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- linearMod = OmpGetUniqueModifier<parser::OmpLinearModifier>(modifiers);
- if (linearMod) {
- auto &desc{llvm::omp::getDescriptor(llvm::omp::Modifier::LinearModifier)};
- parser::CharBlock modSource{OmpGetModifierSource(modifiers, linearMod)};
- bool valid{true};
-
- if (version < 52) {
- // Modifiers on LINEAR are only allowed on DECLARE SIMD
+ auto &modifiers{OmpGetModifiers(x.v)};
+ linearMod = OmpGetUniqueModifier<parser::OmpLinearModifier>(modifiers);
+ if (linearMod) {
+ auto &desc{llvm::omp::getDescriptor(llvm::omp::Modifier::LinearModifier)};
+ parser::CharBlock modSource{OmpGetModifierSource(modifiers, linearMod)};
+ bool valid{true};
+
+ if (version < 52) {
+ // Modifiers on LINEAR are only allowed on DECLARE SIMD
+ if (dir != llvm::omp::Directive::OMPD_declare_simd) {
+ context_.Say(modSource,
+ "A modifier may not be specified in a LINEAR clause on the %s directive"_err_en_US,
+ parser::omp::GetUpperName(dir, version));
+ valid = false;
+ }
+ } else {
+ if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
+ linearMod->v == parser::OmpLinearModifier::Value::Uval) {
if (dir != llvm::omp::Directive::OMPD_declare_simd) {
context_.Say(modSource,
- "A modifier may not be specified in a LINEAR clause on the %s directive"_err_en_US,
- parser::omp::GetUpperName(dir, version));
+ "A REF or UVAL '%s' may not be specified in a LINEAR clause on the %s directive"_err_en_US,
+ desc.getName().str(), parser::omp::GetUpperName(dir, version));
valid = false;
}
- } else {
- if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
- linearMod->v == parser::OmpLinearModifier::Value::Uval) {
- if (dir != llvm::omp::Directive::OMPD_declare_simd) {
- context_.Say(modSource,
- "A REF or UVAL '%s' may not be specified in a LINEAR clause on the %s directive"_err_en_US,
- desc.getName().str(), parser::omp::GetUpperName(dir, version));
- valid = false;
- }
- }
- if (!std::get</*PostModified=*/bool>(x.v.t)) {
- context_.Say(modSource,
- "The 'modifier(<list>)' syntax is deprecated in %s, use '<list> : modifier' instead"_warn_en_US,
- ThisVersion(version));
- }
}
+ if (!std::get</*PostModified=*/bool>(x.v.t)) {
+ context_.Say(modSource,
+ "The 'modifier(<list>)' syntax is deprecated in %s, use '<list> : modifier' instead"_warn_en_US,
+ ThisVersion(version));
+ }
+ }
- if (valid) {
- for (auto &[symbol, source] : symbols) {
- if (linearMod->v != parser::OmpLinearModifier::Value::Ref) {
- CheckIntegerNoRef(symbol, source);
- } else {
- if (!IsAllocatable(*symbol) && !IsAssumedShape(*symbol) &&
- !IsPolymorphic(*symbol)) {
- context_.Say(source,
- "The list item `%s` specified with the REF '%s' must be polymorphic variable, assumed-shape array, or a variable with the `ALLOCATABLE` attribute"_err_en_US,
- symbol->name(), desc.getName().str());
- }
+ if (valid) {
+ for (auto &[symbol, source] : symbols) {
+ if (linearMod->v != parser::OmpLinearModifier::Value::Ref) {
+ CheckIntegerNoRef(symbol, source);
+ } else {
+ if (!IsAllocatable(*symbol) && !IsAssumedShape(*symbol) &&
+ !IsPolymorphic(*symbol)) {
+ context_.Say(source,
+ "The list item `%s` specified with the REF '%s' must be polymorphic variable, assumed-shape array, or a variable with the `ALLOCATABLE` attribute"_err_en_US,
+ symbol->name(), desc.getName().str());
}
- if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
- linearMod->v == parser::OmpLinearModifier::Value::Uval) {
- if (!IsDummy(*symbol) || IsValue(*symbol)) {
- context_.Say(source,
- "If the `%s` is REF or UVAL, the list item '%s' must be a dummy argument without the VALUE attribute"_err_en_US,
- desc.getName().str(), symbol->name());
- }
+ }
+ if (linearMod->v == parser::OmpLinearModifier::Value::Ref ||
+ linearMod->v == parser::OmpLinearModifier::Value::Uval) {
+ if (!IsDummy(*symbol) || IsValue(*symbol)) {
+ context_.Say(source,
+ "If the `%s` is REF or UVAL, the list item '%s' must be a dummy argument without the VALUE attribute"_err_en_US,
+ desc.getName().str(), symbol->name());
}
- } // for (symbol, source)
- }
+ }
+ } // for (symbol, source)
}
}
@@ -959,8 +956,6 @@ void OmpStructureChecker::Enter(const parser::OmpLoopModifier &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Apply &x) {
EnterDirectiveNest(ApplyNest);
- OmpVerifyModifiers(
- x.v, llvm::omp::Clause::OMPC_apply, GetContext().clauseSource, context_);
}
void OmpStructureChecker::Leave(const parser::OmpClause::Apply &x) {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index acf73c74f3e91..2240c2e48c0a5 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1528,12 +1528,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Hint &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpClause::DynGroupprivate &x) {
- parser::CharBlock source{GetContext().clauseSource};
-
- OmpVerifyModifiers(x.v, llvm::omp::OMPC_dyn_groupprivate, source, context_);
-}
-
template <typename Checker> struct DirectiveSpellingVisitor {
using Directive = llvm::omp::Directive;
@@ -2414,11 +2408,6 @@ void OmpStructureChecker::CheckInitOnDepobj(
CheckTypeParamInquiry(initClause.source, std::get<parser::OmpObject>(init.t),
llvm::omp::Clause::OMPC_init);
- if (!OmpVerifyModifiers(
- init, llvm::omp::Clause::OMPC_init, initClause.source, context_)) {
- return;
- }
-
auto &modifiers{OmpGetModifiers(init)};
if (auto *depInfo{
OmpGetUniqueModifier<parser::OmpDepinfoModifier>(modifiers)}) {
@@ -2789,18 +2778,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
- if (OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_allocate, GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- if (auto *align{
- OmpGetUniqueModifier<parser::OmpAlignModifier>(modifiers)}) {
- if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) {
- context_.Say(OmpGetModifierSource(modifiers, align),
- "The alignment value should be a constant positive integer"_err_en_US);
- } else if (!llvm::isPowerOf2_64(*v)) {
- context_.Say(OmpGetModifierSource(modifiers, align),
- "The alignment value should be a power of 2"_err_en_US);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (auto *align{OmpGetUniqueModifier<parser::OmpAlignModifier>(modifiers)}) {
+ if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) {
+ context_.Say(OmpGetModifierSource(modifiers, align),
+ "The alignment value should be a constant positive integer"_err_en_US);
+ } else if (!llvm::isPowerOf2_64(*v)) {
+ context_.Say(OmpGetModifierSource(modifiers, align),
+ "The alignment value should be a power of 2"_err_en_US);
}
}
@@ -4147,6 +4132,12 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
// Those are extensions/synthetic clauses and they don't have descriptors.
break;
case llvm::omp::Clause::OMPC_uses_allocators: {
+ // The traits of the deprecated syntax are stored as a traits-array
+ // modifier, but they are not the 5.2 modifier, so they must not be
+ // version-checked. A modifier that postdates the OpenMP version in effect
+ // is only warned about, so the specification is accepted as an extension
+ // and must still be checked, otherwise a malformed one would reach lowering
+ // unvalidated.
auto &uac{parser::UnwrapRef<parser::OmpUsesAllocatorsClause>(x)};
for (auto &&as : uac.v) {
bool legacy{std::get<bool>(as.t)};
@@ -4194,21 +4185,19 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
auto &objects{*GetOmpObjectList(x)};
- if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_reduction,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- const auto *ident{
- OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
- assert(ident && "reduction-identifier is a required modifier");
- if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
- llvm::omp::OMPC_reduction)) {
- CheckReductionObjectTypes(objects, *ident);
- }
- using ReductionModifier = parser::OmpReductionModifier;
- if (auto *modifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
- CheckReductionModifier(*modifier);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
}
+ using ReductionModifier = parser::OmpReductionModifier;
+ if (auto *modifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
+ CheckReductionModifier(*modifier);
+ }
+
CheckReductionObjects(objects, llvm::omp::Clause::OMPC_reduction);
// If this is a worksharing construct then ensure the reduction variable
@@ -4233,34 +4222,30 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::InReduction &x) {
auto &objects{*GetOmpObjectList(x)};
- if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_in_reduction,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- const auto *ident{
- OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
- assert(ident && "reduction-identifier is a required modifier");
- if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
- llvm::omp::OMPC_in_reduction)) {
- CheckReductionObjectTypes(objects, *ident);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_in_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
}
+
CheckReductionObjects(objects, llvm::omp::Clause::OMPC_in_reduction);
}
void OmpStructureChecker::Enter(const parser::OmpClause::TaskReduction &x) {
auto &objects{*GetOmpObjectList(x)};
- if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_task_reduction,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- const auto *ident{
- OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
- assert(ident && "reduction-identifier is a required modifier");
- if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
- llvm::omp::OMPC_task_reduction)) {
- CheckReductionObjectTypes(objects, *ident);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_task_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
}
+
CheckReductionObjects(objects, llvm::omp::Clause::OMPC_task_reduction);
}
@@ -4820,21 +4805,19 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Align &x) {
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
- if (OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_aligned, GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- if (auto *align{OmpGetUniqueModifier<parser::OmpAlignment>(modifiers)}) {
- const auto &v{GetIntValue(align->v)};
- if (!v || *v <= 0) {
- context_.Say(OmpGetModifierSource(modifiers, align),
- "The alignment value should be a constant positive integer"_err_en_US);
- } else if (((*v) & (*v - 1)) != 0) {
- context_.Warn(common::UsageWarning::OpenMPUsage,
- OmpGetModifierSource(modifiers, align),
- "Alignment is not a power of 2, Aligned clause will be ignored"_warn_en_US);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (auto *align{OmpGetUniqueModifier<parser::OmpAlignment>(modifiers)}) {
+ const auto &v{GetIntValue(align->v)};
+ if (!v || *v <= 0) {
+ context_.Say(OmpGetModifierSource(modifiers, align),
+ "The alignment value should be a constant positive integer"_err_en_US);
+ } else if (((*v) & (*v - 1)) != 0) {
+ context_.Warn(common::UsageWarning::OpenMPUsage,
+ OmpGetModifierSource(modifiers, align),
+ "Alignment is not a power of 2, Aligned clause will be ignored"_warn_en_US);
}
}
+
// 2.8.1 TODO: list-item attribute check
}
@@ -4851,11 +4834,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
ThisVersion(version), TryVersion(50));
}
}
- if (!OmpVerifyModifiers(x.v, llvm::omp::OMPC_defaultmap,
- GetContext().clauseSource, context_)) {
- // If modifier verification fails, return early.
- return;
- }
+
auto &modifiers{OmpGetModifiers(x.v)};
auto *maybeCategory{
OmpGetUniqueModifier<parser::OmpVariableCategory>(modifiers)};
@@ -4911,11 +4890,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
// diagnostics.
llvm::omp::Directive appliesTo{llvm::omp::Directive::OMPD_unknown};
- if (!OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_if, GetContext().clauseSource, context_)) {
- return;
- }
-
auto &modifiers{OmpGetModifiers(x.v)};
if (auto *dnm{
OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(modifiers)}) {
@@ -5061,11 +5035,6 @@ void OmpStructureChecker::CheckAllowedMapTypes(parser::OmpMapType::Value type,
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
- if (!OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_map, GetContext().clauseSource, context_)) {
- return;
- }
-
auto &modifiers{OmpGetModifiers(x.v)};
unsigned version{context_.langOptions().OpenMPVersion};
if (auto commas{std::get<bool>(x.v.t)}; !commas && version >= 52) {
@@ -5241,10 +5210,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
const parser::OmpScheduleClause &scheduleClause = x.v;
- if (!OmpVerifyModifiers(scheduleClause, llvm::omp::OMPC_schedule,
- GetContext().clauseSource, context_)) {
- return;
- }
// 2.7 Loop Construct Restriction
if (llvm::omp::allDoSet.test(GetContext().directive)) {
@@ -5302,20 +5267,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
}
llvm::omp::Directive dir{GetContext().directive};
- if (OmpVerifyModifiers(deviceClause, llvm::omp::OMPC_device,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(deviceClause)};
+ auto &modifiers{OmpGetModifiers(deviceClause)};
- if (auto *deviceMod{
- OmpGetUniqueModifier<parser::OmpDeviceModifier>(modifiers)}) {
- using Value = parser::OmpDeviceModifier::Value;
- if (dir != llvm::omp::OMPD_target && deviceMod->v == Value::Ancestor) {
- auto name{llvm::omp::getDescriptor(llvm::omp::Modifier::DeviceModifier)
- .getName()};
- context_.Say(OmpGetModifierSource(modifiers, deviceMod),
- "The ANCESTOR %s must not appear on the DEVICE clause on any directive other than the TARGET construct. Found on %s construct."_err_en_US,
- name.str(), parser::omp::GetUpperName(dir, version));
- }
+ if (auto *deviceMod{
+ OmpGetUniqueModifier<parser::OmpDeviceModifier>(modifiers)}) {
+ using Value = parser::OmpDeviceModifier::Value;
+ if (dir != llvm::omp::OMPD_target && deviceMod->v == Value::Ancestor) {
+ auto name{llvm::omp::getDescriptor(llvm::omp::Modifier::DeviceModifier)
+ .getName()};
+ context_.Say(OmpGetModifierSource(modifiers, deviceMod),
+ "The ANCESTOR %s must not appear on the DEVICE clause on any directive other than the TARGET construct. Found on %s construct."_err_en_US,
+ name.str(), parser::omp::GetUpperName(dir, version));
}
}
}
@@ -5394,14 +5356,11 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
}
}
}
- if (OmpVerifyModifiers(*taskDep, llvm::omp::OMPC_depend,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(*taskDep)};
- if (OmpGetUniqueModifier<parser::OmpIterator>(modifiers)) {
- if (dir == llvm::omp::OMPD_depobj) {
- context_.Say(GetContext().clauseSource,
- "An iterator-modifier may specify multiple locators, a DEPEND clause on a DEPOBJ construct must only specify one locator"_warn_en_US);
- }
+ auto &modifiers{OmpGetModifiers(*taskDep)};
+ if (OmpGetUniqueModifier<parser::OmpIterator>(modifiers)) {
+ if (dir == llvm::omp::OMPD_depobj) {
+ context_.Say(GetContext().clauseSource,
+ "An iterator-modifier may specify multiple locators, a DEPEND clause on a DEPOBJ construct must only specify one locator"_warn_en_US);
}
}
}
@@ -5413,12 +5372,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Doacross &x) {
void OmpStructureChecker::CheckDoacross(
const parser::OmpDoacross &doa, llvm::omp::Clause clauseId) {
- parser::CharBlock clauseSource{GetContext().clauseSource};
-
- if (!OmpVerifyModifiers(doa, clauseId, clauseSource, context_)) {
- return;
- }
-
auto &iterVec{std::get<std::optional<parser::OmpIterationVector>>(doa.t)};
auto &modifiers{OmpGetModifiers(doa)};
@@ -5551,61 +5504,58 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
CheckPrivateSymbolsInOuterCxt(
currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);
- if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_lastprivate,
- GetContext().clauseSource, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- using LastprivateModifier = parser::OmpLastprivateModifier;
- if (auto *modifier{OmpGetUniqueModifier<LastprivateModifier>(modifiers)}) {
- CheckLastprivateModifier(*modifier);
- if (modifier->v == LastprivateModifier::Value::Conditional) {
- // A conditional lastprivate list item must be a scalar variable of
- // intrinsic Numeric or Logical category. Arrays are excluded by the
- // rank check; character, derived, and polymorphic entities by the
- // category check.
- auto checkConditionalItem{[&](const Symbol &symbol,
- const parser::CharBlock &source) {
- // Resolve host/use-association so the type and attribute checks see
- // the entity's real properties, not the local association symbol.
- const Symbol &ultimate{symbol.GetUltimate()};
- const DeclTypeSpec *type{ultimate.GetType()};
- bool isScalarIntrinsicNonChar{ultimate.Rank() == 0 && type &&
- (type->category() == DeclTypeSpec::Category::Numeric ||
- type->category() == DeclTypeSpec::Category::Logical)};
- if (!isScalarIntrinsicNonChar) {
- context_.Say(source,
- "A list item that appears in a LASTPRIVATE clause with the "
- "CONDITIONAL modifier must be a scalar variable with intrinsic "
- "type, as defined by the Fortran language, excluding character "
- "type, but '%s' is not"_err_en_US,
- symbol.name());
- } else if (IsAllocatableOrPointer(ultimate)) {
- // Standard-legal, but lowering does not yet preserve descriptors.
- // TODO: support POINTER/ALLOCATABLE conditional lastprivate.
- context_.Say(source,
- "A POINTER or ALLOCATABLE list item is not yet supported by "
- "Flang in a LASTPRIVATE clause with the CONDITIONAL modifier, "
- "'%s'"_err_en_US,
- symbol.name());
- }
- }};
- // Check whole variables (Designator -> DataRef -> Name) and
- // common blocks (a bare Name, rejected above as having no type).
- // Array elements, sections, components, and substrings are other
- // designator forms, left to the general OpenMP object diagnostics.
- for (const parser::OmpObject &object : objectList.v) {
- const parser::Name *name{std::get_if<parser::Name>(&object.u)};
- if (!name) {
- if (const auto *designator{
- std::get_if<parser::Designator>(&object.u)}) {
- if (const auto *dataRef{
- std::get_if<parser::DataRef>(&designator->u)}) {
- name = std::get_if<parser::Name>(&dataRef->u);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ using LastprivateModifier = parser::OmpLastprivateModifier;
+ if (auto *modifier{OmpGetUniqueModifier<LastprivateModifier>(modifiers)}) {
+ CheckLastprivateModifier(*modifier);
+ if (modifier->v == LastprivateModifier::Value::Conditional) {
+ // A conditional lastprivate list item must be a scalar variable of
+ // intrinsic Numeric or Logical category. Arrays are excluded by the
+ // rank check; character, derived, and polymorphic entities by the
+ // category check.
+ auto checkConditionalItem{[&](const Symbol &symbol,
+ const parser::CharBlock &source) {
+ // Resolve host/use-association so the type and attribute checks see
+ // the entity's real properties, not the local association symbol.
+ const Symbol &ultimate{symbol.GetUltimate()};
+ const DeclTypeSpec *type{ultimate.GetType()};
+ bool isScalarIntrinsicNonChar{ultimate.Rank() == 0 && type &&
+ (type->category() == DeclTypeSpec::Category::Numeric ||
+ type->category() == DeclTypeSpec::Category::Logical)};
+ if (!isScalarIntrinsicNonChar) {
+ context_.Say(source,
+ "A list item that appears in a LASTPRIVATE clause with the "
+ "CONDITIONAL modifier must be a scalar variable with intrinsic "
+ "type, as defined by the Fortran language, excluding character "
+ "type, but '%s' is not"_err_en_US,
+ symbol.name());
+ } else if (IsAllocatableOrPointer(ultimate)) {
+ // Standard-legal, but lowering does not yet preserve descriptors.
+ // TODO: support POINTER/ALLOCATABLE conditional lastprivate.
+ context_.Say(source,
+ "A POINTER or ALLOCATABLE list item is not yet supported by "
+ "Flang in a LASTPRIVATE clause with the CONDITIONAL modifier, "
+ "'%s'"_err_en_US,
+ symbol.name());
+ }
+ }};
+ // Check whole variables (Designator -> DataRef -> Name) and
+ // common blocks (a bare Name, rejected above as having no type).
+ // Array elements, sections, components, and substrings are other
+ // designator forms, left to the general OpenMP object diagnostics.
+ for (const parser::OmpObject &object : objectList.v) {
+ const parser::Name *name{std::get_if<parser::Name>(&object.u)};
+ if (!name) {
+ if (const auto *designator{
+ std::get_if<parser::Designator>(&object.u)}) {
+ if (const auto *dataRef{
+ std::get_if<parser::DataRef>(&designator->u)}) {
+ name = std::get_if<parser::Name>(&dataRef->u);
}
}
- if (name && name->symbol) {
- checkConditionalItem(*name->symbol, name->source);
- }
+ }
+ if (name && name->symbol) {
+ checkConditionalItem(*name->symbol, name->source);
}
}
}
@@ -5870,16 +5820,6 @@ void OmpStructureChecker::CheckUsesAllocatorsSpec(
unsigned version{context_.langOptions().OpenMPVersion};
bool isLegacySyntax{std::get<bool>(spec.t)};
- // The traits of the deprecated syntax are stored as a traits-array modifier,
- // but they are not the 5.2 modifier, so they must not be version-checked.
- // A modifier that postdates the OpenMP version in effect is only warned
- // about, so the specification is accepted as an extension and must still be
- // checked, otherwise a malformed one would reach lowering unvalidated.
- if (!isLegacySyntax) {
- OmpVerifyModifiers(spec, llvm::omp::OMPC_uses_allocators,
- GetContext().clauseSource, context_);
- }
-
auto &modifiers{OmpGetModifiers(spec)};
const auto *memSpace{OmpGetUniqueModifier<parser::OmpMemSpace>(modifiers)};
const auto *traits{OmpGetUniqueModifier<parser::OmpTraitsArray>(modifiers)};
@@ -6151,17 +6091,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) {
- OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_);
-}
-
void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
- if (!OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_from, GetContext().clauseSource, context_)) {
- return;
- }
-
auto &modifiers{OmpGetModifiers(x.v)};
unsigned version{context_.langOptions().OpenMPVersion};
@@ -6180,11 +6110,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
- if (!OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_to, GetContext().clauseSource, context_)) {
- return;
- }
-
auto &modifiers{OmpGetModifiers(x.v)};
unsigned version{context_.langOptions().OpenMPVersion};
@@ -6689,15 +6614,12 @@ void OmpStructureChecker::CheckDimsModifier(parser::CharBlock source,
void OmpStructureChecker::Enter(const parser::OmpClause::NumTeams &x) {
constexpr auto clauseId{llvm::omp::Clause::OMPC_num_teams};
- parser::CharBlock source{GetContext().clauseSource};
auto &values{std::get<std::list<parser::ScalarIntExpr>>(x.v.t)};
- if (OmpVerifyModifiers(x.v, clauseId, source, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
- CheckDimsModifier(
- OmpGetModifierSource(modifiers, dims), values.size(), *dims);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
+ CheckDimsModifier(
+ OmpGetModifierSource(modifiers, dims), values.size(), *dims);
}
for (auto &val : values) {
@@ -6707,15 +6629,12 @@ void OmpStructureChecker::Enter(const parser::OmpClause::NumTeams &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::NumThreads &x) {
constexpr auto clauseId{llvm::omp::Clause::OMPC_num_threads};
- parser::CharBlock source{GetContext().clauseSource};
auto &values{std::get<std::list<parser::ScalarIntExpr>>(x.v.t)};
- if (OmpVerifyModifiers(x.v, clauseId, source, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
- CheckDimsModifier(
- OmpGetModifierSource(modifiers, dims), values.size(), *dims);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
+ CheckDimsModifier(
+ OmpGetModifierSource(modifiers, dims), values.size(), *dims);
}
for (auto &val : values) {
@@ -6725,15 +6644,12 @@ void OmpStructureChecker::Enter(const parser::OmpClause::NumThreads &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::ThreadLimit &x) {
constexpr auto clauseId{llvm::omp::Clause::OMPC_thread_limit};
- parser::CharBlock source{GetContext().clauseSource};
auto &values{std::get<std::list<parser::ScalarIntExpr>>(x.v.t)};
- if (OmpVerifyModifiers(x.v, clauseId, source, context_)) {
- auto &modifiers{OmpGetModifiers(x.v)};
- if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
- CheckDimsModifier(
- OmpGetModifierSource(modifiers, dims), values.size(), *dims);
- }
+ auto &modifiers{OmpGetModifiers(x.v)};
+ if (auto *dims{OmpGetUniqueModifier<parser::OmpDimsModifier>(modifiers)}) {
+ CheckDimsModifier(
+ OmpGetModifierSource(modifiers, dims), values.size(), *dims);
}
for (auto &val : values) {
@@ -6828,62 +6744,56 @@ void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
[&](const parser::OmpClause::Init &initClause) {
hasInitClause = true;
hasActionClause = true;
- if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init,
- GetContext().directiveSource, context_)) {
-
- auto &modifiers{OmpGetModifiers(initClause.v)};
- auto &&interopTypeModifier{
- OmpGetRepeatableModifier<parser::OmpInteropType>(
- modifiers)};
- for (const auto &it : interopTypeModifier) {
- if (it->v == parser::OmpInteropType::Value::Targetsync) {
- ++targetSyncCount;
- } else {
- ++targetCount;
- }
- }
- if (auto *depInfo{
- OmpGetUniqueModifier<parser::OmpDepinfoModifier>(
- modifiers)}) {
- auto &desc{llvm::omp::getDescriptor(
- llvm::omp::Modifier::DepinfoModifier)};
- context_.Say(OmpGetModifierSource(modifiers, depInfo),
- "The '%s' is not allowed on INTEROP construct"_err_en_US,
- desc.getName().str());
+
+ auto &modifiers{OmpGetModifiers(initClause.v)};
+ auto &&interopTypeModifier{
+ OmpGetRepeatableModifier<parser::OmpInteropType>(modifiers)};
+ for (const auto &it : interopTypeModifier) {
+ if (it->v == parser::OmpInteropType::Value::Targetsync) {
+ ++targetSyncCount;
+ } else {
+ ++targetCount;
}
- // A prefer_type foreign-runtime-identifier must be a
- // constant expression of integer OpenMP type or a base
- // language string literal. This is enforced for the flat form
- // (prefer_type(fr-id, ...)); the OpenMP 6.0
- // brace form (prefer_type({fr(...), attr(...)}, ...)) is not
- // yet supported in lowering and is diagnosed there, so its
- // operands are not validated here.
- if (auto *preferType{
- OmpGetUniqueModifier<parser::OmpPreferType>(
- modifiers)}) {
- for (const auto &prefSpec : preferType->v) {
- const auto *fri{
- std::get_if<parser::OmpPreferenceSpecification::
- ForeignRuntimeIdentifier>(&prefSpec.u)};
- if (!fri) {
- continue;
- }
- if (const auto *expr{GetExpr(context_, fri->value())}) {
- std::optional<evaluate::DynamicType> type{
- expr->GetType()};
- bool isIntOrChar{type &&
- (type->category() ==
- evaluate::TypeCategory::Integer ||
- type->category() ==
- evaluate::TypeCategory::Character)};
- if (!evaluate::IsConstantExpr(*expr) || !isIntOrChar) {
- context_.Say(fri->value().source,
- "The foreign-runtime-identifier in a `prefer_type` modifier must be a constant expression of integer OpenMP type or a base language string literal"_err_en_US);
- }
+ }
+ if (auto *depInfo{
+ OmpGetUniqueModifier<parser::OmpDepinfoModifier>(
+ modifiers)}) {
+ auto &desc{llvm::omp::getDescriptor(
+ llvm::omp::Modifier::DepinfoModifier)};
+ context_.Say(OmpGetModifierSource(modifiers, depInfo),
+ "The '%s' is not allowed on INTEROP construct"_err_en_US,
+ desc.getName().str());
+ }
+ // A prefer_type foreign-runtime-identifier must be a
+ // constant expression of integer OpenMP type or a base
+ // language string literal. This is enforced for the flat form
+ // (prefer_type(fr-id, ...)); the OpenMP 6.0
+ // brace form (prefer_type({fr(...), attr(...)}, ...)) is not
+ // yet supported in lowering and is diagnosed there, so its
+ // operands are not validated here.
+ if (auto *preferType{
+ OmpGetUniqueModifier<parser::OmpPreferType>(modifiers)}) {
+ for (const auto &prefSpec : preferType->v) {
+ const auto *fri{
+ std::get_if<parser::OmpPreferenceSpecification::
+ ForeignRuntimeIdentifier>(&prefSpec.u)};
+ if (!fri) {
+ continue;
+ }
+ if (const auto *expr{GetExpr(context_, fri->value())}) {
+ std::optional<evaluate::DynamicType> type{expr->GetType()};
+ bool isIntOrChar{type &&
+ (type->category() == evaluate::TypeCategory::Integer ||
+ type->category() ==
+ evaluate::TypeCategory::Character)};
+ if (!evaluate::IsConstantExpr(*expr) || !isIntOrChar) {
+ context_.Say(fri->value().source,
+ "The foreign-runtime-identifier in a `prefer_type` modifier must be a constant expression of integer OpenMP type or a base language string literal"_err_en_US);
}
}
}
}
+
const auto *interopVar{parser::Unwrap<parser::OmpObject>(
std::get<parser::OmpObject>(initClause.v.t))};
CheckTypeParamInquiry(
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 966c32e212dcb..394c1508cd4ab 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -204,8 +204,6 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void Enter(const parser::OmpClause::Device &x);
void Enter(const parser::OmpClause::Doacross &x);
void Enter(const parser::OmpClause::DynamicAllocators &x);
- void Enter(const parser::OmpClause::DynGroupprivate &x);
- void Enter(const parser::OmpClause::Enter &x);
void Enter(const parser::OmpClause::Firstprivate &x);
void Enter(const parser::OmpClause::From &x);
void Enter(const parser::OmpClause::HasDeviceAddr &x);
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 0f8daf84d25ec..0a88b698f0e99 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -187,8 +187,6 @@ void OmpStructureChecker::CheckDefaultNoneInAssociatedLoop(
}
void OmpStructureChecker::Enter(const parser::OmpClause::When &x) {
- OmpVerifyModifiers(
- x.v, llvm::omp::OMPC_when, GetContext().clauseSource, context_);
// Record this WHEN clause's context selector so the variant directive it
// controls can be paired with it for static-applicability matching. A
// well-formed WHEN clause has exactly one modifier, its context selector;
More information about the llvm-branch-commits
mailing list