[flang-commits] [flang] [llvm] [flang][OpenMP] Add parsing and semantic checks for USES_ALLOCATORS (PR #213955)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 4 07:31:48 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Sairudra More (Saieiei)
<details>
<summary>Changes</summary>
Closes #<!-- -->213958
Adds Flang frontend support for the OpenMP `uses_allocators` clause, including parsing, unparsing, and semantic checks for allocator traits and version-dependent syntax. Lowering remains unimplemented.
Assisted-by: GitHub Copilot
---
Patch is 72.23 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213955.diff
22 Files Affected:
- (modified) flang/docs/OpenMPSupport.md (+2-2)
- (modified) flang/include/flang/Parser/dump-parse-tree.h (+5)
- (modified) flang/include/flang/Parser/parse-tree.h (+39)
- (modified) flang/include/flang/Semantics/openmp-modifiers.h (+2)
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+24-2)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+64)
- (modified) flang/lib/Parser/unparse.cpp (+31)
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+8-2)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+326)
- (modified) flang/lib/Semantics/check-omp-structure.h (+6)
- (modified) flang/lib/Semantics/openmp-modifiers.cpp (+33)
- (added) flang/test/Lower/OpenMP/Todo/target-uses-allocators.f90 (+42)
- (added) flang/test/Parser/OpenMP/uses-allocators-bad-syntax.f90 (+35)
- (added) flang/test/Parser/OpenMP/uses-allocators.f90 (+118)
- (added) flang/test/Semantics/OpenMP/uses-allocators-handle-kind.f90 (+32)
- (added) flang/test/Semantics/OpenMP/uses-allocators-no-omp-lib.f90 (+16)
- (added) flang/test/Semantics/OpenMP/uses-allocators-user-module.f90 (+29)
- (added) flang/test/Semantics/OpenMP/uses-allocators-version50.f90 (+56)
- (added) flang/test/Semantics/OpenMP/uses-allocators-version51.f90 (+45)
- (added) flang/test/Semantics/OpenMP/uses-allocators-version60.f90 (+99)
- (added) flang/test/Semantics/OpenMP/uses-allocators.f90 (+314)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+1)
``````````diff
diff --git a/flang/docs/OpenMPSupport.md b/flang/docs/OpenMPSupport.md
index fd6731fd28a2b..755e6cac7169e 100644
--- a/flang/docs/OpenMPSupport.md
+++ b/flang/docs/OpenMPSupport.md
@@ -124,7 +124,7 @@ Parser/Semantics, MLIR, Lowering, or the OpenMPIRBuilder.
| allocate directive and allocate clause | <span class="part">partial</span> | | Semantics coverage exists in `flang/test/Semantics/OpenMP/allocate-directive.f90` and `flang/test/Semantics/OpenMP/allocate-clause01.f90`; lowering support expanded, with remaining TODO coverage (`flang/test/Lower/OpenMP/Todo/allocate-clause-align.f90`, `flang/test/Lower/OpenMP/Todo/allocate-clause-allocator.f90`). | [llvm/llvm-project#121356](https://github.com/llvm/llvm-project/pull/121356), [llvm/llvm-project#165719](https://github.com/llvm/llvm-project/pull/165719), [llvm/llvm-project#165865](https://github.com/llvm/llvm-project/pull/165865), [llvm/llvm-project#187167](https://github.com/llvm/llvm-project/pull/187167) |
| metadirective | <span class="part">partial</span> | | Semantics coverage exists in `flang/test/Semantics/OpenMP/metadirective-construct.f90`; lowering support exists for several construct-selector paths (`flang/test/Lower/OpenMP/metadirective-construct.f90`, `flang/test/Lower/OpenMP/metadirective-nothing.f90`), but some selector/variant paths remain TODO-tracked in lowering. | [llvm/llvm-project#159945](https://github.com/llvm/llvm-project/pull/159945), [llvm/llvm-project#193664](https://github.com/llvm/llvm-project/pull/193664), [llvm/llvm-project#194402](https://github.com/llvm/llvm-project/pull/194402), [llvm/llvm-project#194424](https://github.com/llvm/llvm-project/pull/194424) |
| support full defaultmap functionality | <span class="part">partial</span> | | Core coverage exists (`flang/test/Lower/OpenMP/defaultmap.f90`, `flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90`), but lowering has known partial paths (for example defaultmap-firstprivate TODO tests). | [llvm/llvm-project#135226](https://github.com/llvm/llvm-project/pull/135226), [llvm/llvm-project#166715](https://github.com/llvm/llvm-project/pull/166715), [llvm/llvm-project#167806](https://github.com/llvm/llvm-project/pull/167806), [llvm/llvm-project#177389](https://github.com/llvm/llvm-project/pull/177389), [llvm/llvm-project#190764](https://github.com/llvm/llvm-project/pull/190764) |
-| clause: uses_allocators | <span class="part">partial</span> | | Parsed/checked in semantics allocator tests, but lowering has explicit TODO handling (`cp.processTODO<...UsesAllocators>` in `flang/lib/Lower/OpenMP/OpenMP.cpp`). | |
+| clause: uses_allocators | <span class="part">partial</span> | | Parsing and semantic checking are supported for the OpenMP 5.2 syntax and for the pre-5.2 comma-separated list syntax, the latter accepted in 5.0/5.1, accepted with a deprecation warning in 5.2, and removed and rejected in 6.0 and later (`flang/test/Parser/OpenMP/uses-allocators.f90`, `flang/test/Semantics/OpenMP/uses-allocators.f90`, `flang/test/Semantics/OpenMP/uses-allocators-version60.f90`); lowering is unimplemented and reports a `not yet implemented` diagnostic (`flang/test/Lower/OpenMP/Todo/target-uses-allocators.f90`). The OpenMP 6.0 form with more than one clause-argument-specification is diagnosed as not yet supported. | |
| clause: in_reduction | <span class="part">partial</span> | | Semantics and lowering coverage exists for several task/taskgroup/taskloop forms (`flang/test/Semantics/OpenMP/in-reduction.f90`, `flang/test/Lower/OpenMP/task-inreduction.f90`, `flang/test/Lower/OpenMP/taskloop-inreduction.f90`, `flang/test/Lower/OpenMP/taskgroup-task_reduction02.f90`); some target-related forms remain TODO (for example `flang/test/Lower/OpenMP/Todo/target-inreduction.f90`). | [llvm/llvm-project#139704](https://github.com/llvm/llvm-project/pull/139704), [llvm/llvm-project#205124](https://github.com/llvm/llvm-project/pull/205124) |
| user-defined mappers | <span class="good">done</span> | | Supported with semantics/lowering/transform coverage. | [llvm/llvm-project#140560](https://github.com/llvm/llvm-project/pull/140560), [llvm/llvm-project#163860](https://github.com/llvm/llvm-project/pull/163860), [llvm/llvm-project#167903](https://github.com/llvm/llvm-project/pull/167903), [llvm/llvm-project#179936](https://github.com/llvm/llvm-project/pull/179936), [llvm/llvm-project#189136](https://github.com/llvm/llvm-project/pull/189136) |
| map array-section with implicit mapper | <span class="part">partial</span> | | Mapper and map coverage exists (`flang/test/Lower/OpenMP/map-mapper.f90`, `flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90`), with remaining iterator/modifier gaps in lowering (`flang/lib/Lower/OpenMP/ClauseProcessor.cpp` TODOs). | [llvm/llvm-project#175133](https://github.com/llvm/llvm-project/pull/175133), [llvm/llvm-project#177389](https://github.com/llvm/llvm-project/pull/177389) |
@@ -214,7 +214,7 @@ Parser/Semantics, MLIR, Lowering, or the OpenMPIRBuilder.
| minus operator deprecation handling | <span class="part">partial</span> | | Partially handled in semantic diagnostics. | |
| linear clause syntax deprecation | <span class="none">unclaimed</span> | | Add semantic deprecation diagnostics with fix-it guidance and tests for accepted/deprecated spellings. | |
| map clause modifiers without commas (deprecation) | <span class="none">unclaimed</span> | | Add parser/semantics deprecation diagnostics for comma-less map modifiers and tests that verify warning text and accepted replacements. | |
-| uses_allocators list syntax (deprecation) | <span class="none">unclaimed</span> | | Add diagnostics for deprecated uses_allocators list syntax and ensure lowering still handles canonical replacements. | |
+| uses_allocators list syntax (deprecation) | <span class="part">partial</span> | | The comma-separated list syntax is accepted in OpenMP 5.0 and 5.1, accepted with a deprecation/portability warning in 5.2, and removed and rejected in 6.0 and later, where [6.0:B.2] removes all features deprecated in 5.0, 5.1 and 5.2 (`flang/test/Semantics/OpenMP/uses-allocators.f90`, `flang/test/Semantics/OpenMP/uses-allocators-version60.f90`); lowering of the clause is still unimplemented. | |
| default clause on metadirectives (deprecation) | <span class="none">unclaimed</span> | | Add dedicated metadirective deprecation diagnostics and tests for legacy/default-clause usage. | |
| destroy clause syntax on depobj (deprecation) | <span class="part">partial</span> | | Deprecation diagnostics are implemented (for example warning coverage in `flang/test/Semantics/OpenMP/depobj-construct-v52.f90`). | |
| source and sink task-dependence modifiers (deprecation) | <span class="part">partial</span> | | Deprecation diagnostics are implemented (for example warning coverage in `flang/test/Semantics/OpenMP/depobj-construct-v52.f90`). | |
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 729bcbc9b7cab..1c66724aa9eb3 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -689,6 +689,7 @@ class ParseTreeDumper {
NODE(parser, OmpMapTypeModifier)
NODE_ENUM(OmpMapTypeModifier, Value)
NODE(parser, OmpMatchClause)
+ NODE(parser, OmpMemspaceModifier)
NODE(parser, OmpMessageClause)
NODE(parser, OmpMetadirectiveDirective)
NODE(parser, OmpNoOpenMPClause)
@@ -759,6 +760,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpThreadsetClause, ThreadsetPolicy)
NODE(parser, OmpToClause)
NODE(OmpToClause, Modifier)
+ NODE(parser, OmpTraitsArrayModifier)
NODE(parser, OmpTraitProperty)
NODE(parser, OmpTraitPropertyExtension)
NODE(OmpTraitPropertyExtension, Complex)
@@ -778,6 +780,9 @@ class ParseTreeDumper {
NODE(parser, OmpUnifiedSharedMemoryClause)
NODE(parser, OmpUpdateDependObjectsClause)
NODE(parser, OmpUseClause)
+ NODE(parser, OmpUsesAllocatorsClause)
+ NODE(OmpUsesAllocatorsClause, AllocatorSpec)
+ NODE(OmpUsesAllocatorsClause::AllocatorSpec, Modifier)
NODE(parser, OmpUtilityDirective)
NODE(parser, OmpVariableCategory)
NODE_ENUM(OmpVariableCategory, Value)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 497d985c1c8c5..ea4f9187911d8 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4217,6 +4217,14 @@ struct OmpMapTypeModifier {
WRAPPER_CLASS_BOILERPLATE(OmpMapTypeModifier, Value);
};
+// Ref: [5.2:181-182]
+//
+// mem-space-modifier ->
+// MEMSPACE(memspace-handle) // since 5.2
+struct OmpMemspaceModifier {
+ WRAPPER_CLASS_BOILERPLATE(OmpMemspaceModifier, ScalarIntExpr);
+};
+
// Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254]
//
// modifier ->
@@ -4353,6 +4361,14 @@ struct OmpTaskDependenceType {
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
};
+// Ref: [5.2:181-182]
+//
+// traits-array-modifier ->
+// TRAITS(traits-array) // since 5.2
+struct OmpTraitsArrayModifier {
+ WRAPPER_CLASS_BOILERPLATE(OmpTraitsArrayModifier, common::Indirection<Expr>);
+};
+
// Ref: [4.5:229-230], [5.0:324-325], [5.1:357-358], [5.2:161-162]
//
// variable-category ->
@@ -5138,6 +5154,29 @@ struct OmpUseClause {
WRAPPER_CLASS_BOILERPLATE(OmpUseClause, OmpObject);
};
+// Ref: [5.0:170-175], [5.1:197-203], [5.2:181-182]
+//
+// uses-allocators-clause ->
+// USES_ALLOCATORS(allocator[(traits-array)]
+// [, allocator[(traits-array)]]...) | // since 5.0, dep. 5.2
+// USES_ALLOCATORS([modifier...:] allocator) // since 5.2
+// modifier ->
+// mem-space-modifier |
+// traits-array-modifier // since 5.2
+struct OmpUsesAllocatorsClause {
+ struct AllocatorSpec {
+ TUPLE_CLASS_BOILERPLATE(AllocatorSpec);
+ MODIFIER_BOILERPLATE(OmpMemspaceModifier, OmpTraitsArrayModifier);
+ CharBlock source;
+ // The traits of the deprecated "allocator(traits-array)" form are stored
+ // as a traits-array modifier. The flag records which of the two surface
+ // syntaxes was written, which both the unparser and the deprecation
+ // diagnostic need.
+ std::tuple<MODIFIERS(), ScalarIntExpr, /*IsLegacySyntax=*/bool> t;
+ };
+ WRAPPER_CLASS_BOILERPLATE(OmpUsesAllocatorsClause, std::list<AllocatorSpec>);
+};
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index d6f225f329f41..c8788e2e89547 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -95,6 +95,7 @@ DECLARE_DESCRIPTOR(parser::OmpLowerBound);
DECLARE_DESCRIPTOR(parser::OmpMapper);
DECLARE_DESCRIPTOR(parser::OmpMapType);
DECLARE_DESCRIPTOR(parser::OmpMapTypeModifier);
+DECLARE_DESCRIPTOR(parser::OmpMemspaceModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderModifier);
DECLARE_DESCRIPTOR(parser::OmpOrderingModifier);
DECLARE_DESCRIPTOR(parser::OmpPreferType);
@@ -107,6 +108,7 @@ DECLARE_DESCRIPTOR(parser::OmpSelfModifier);
DECLARE_DESCRIPTOR(parser::OmpStepComplexModifier);
DECLARE_DESCRIPTOR(parser::OmpStepSimpleModifier);
DECLARE_DESCRIPTOR(parser::OmpTaskDependenceType);
+DECLARE_DESCRIPTOR(parser::OmpTraitsArrayModifier);
DECLARE_DESCRIPTOR(parser::OmpVariableCategory);
DECLARE_DESCRIPTOR(parser::OmpxHoldModifier);
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 941e875259a20..6bcfa67a5b814 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1785,8 +1785,30 @@ UseDevicePtr make(const parser::OmpClause::UseDevicePtr &inp,
UsesAllocators make(const parser::OmpClause::UsesAllocators &inp,
semantics::SemanticsContext &semaCtx) {
- // inp -> empty
- llvm_unreachable("Empty: uses_allocators");
+ // inp.v -> parser::OmpUsesAllocatorsClause
+ using AllocatorSpec = parser::OmpUsesAllocatorsClause::AllocatorSpec;
+
+ auto makeSpec = [&](const AllocatorSpec &spec) {
+ auto &mods = semantics::OmpGetModifiers(spec);
+ auto *memSpace =
+ semantics::OmpGetUniqueModifier<parser::OmpMemspaceModifier>(mods);
+ auto *traits =
+ semantics::OmpGetUniqueModifier<parser::OmpTraitsArrayModifier>(mods);
+
+ std::optional<UsesAllocators::TraitsArray> traitsArray;
+ if (traits) {
+ // Semantics has verified that the traits array is a named constant.
+ const parser::Name *name{parser::Unwrap<parser::Name>(traits->v.value())};
+ traitsArray = makeObject(DEREF(name), semaCtx);
+ }
+ return UsesAllocators::AllocatorSpec{
+ {/*MemSpace=*/maybeApplyToV(makeExprFn(semaCtx), memSpace),
+ /*TraitsArray=*/std::move(traitsArray),
+ /*Allocator=*/
+ makeExpr(std::get<parser::ScalarIntExpr>(spec.t), semaCtx)}};
+ };
+
+ return UsesAllocators{/*Allocators=*/makeList(inp.v.v, makeSpec)};
}
// Weak: empty
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 7b467c73d8fc1..f9ca489646527 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -987,6 +987,9 @@ struct OmpMapTypeModifierParser {
TYPE_PARSER(OmpMapTypeModifierParser{})
+TYPE_PARSER(construct<OmpMemspaceModifier>( //
+ "MEMSPACE" >> parenthesized(scalarIntExpr)))
+
TYPE_PARSER(construct<OmpOrderModifier>(
"REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
"UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained)))
@@ -1042,6 +1045,9 @@ TYPE_PARSER(construct<OmpTaskDependenceType>(
"MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
"OUT" >> pure(OmpTaskDependenceType::Value::Out)))
+TYPE_PARSER(construct<OmpTraitsArrayModifier>( //
+ "TRAITS" >> parenthesized(indirect(expr))))
+
TYPE_PARSER(construct<OmpVariableCategory>(
"AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) ||
"ALL"_id >> pure(OmpVariableCategory::Value::All) ||
@@ -1162,6 +1168,12 @@ TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
construct<OmpToClause::Modifier>(Parser<OmpIterator>{})))))
+TYPE_PARSER(sourced(construct<OmpUsesAllocatorsClause::AllocatorSpec::Modifier>(
+ sourced(construct<OmpUsesAllocatorsClause::AllocatorSpec::Modifier>(
+ Parser<OmpMemspaceModifier>{}) ||
+ construct<OmpUsesAllocatorsClause::AllocatorSpec::Modifier>(
+ Parser<OmpTraitsArrayModifier>{})))))
+
TYPE_PARSER(sourced(construct<OmpWhenClause::Modifier>( //
Parser<OmpContextSelector>{})))
@@ -1521,6 +1533,55 @@ TYPE_PARSER(construct<OmpSeverityClause>(
TYPE_PARSER(construct<OmpMessageClause>(expr))
TYPE_PARSER(construct<OmpHoldsClause>(indirect(expr)))
+
+// The deprecated "allocator[(traits-array)]" form is normalized into the 5.2
+// representation so that both surface syntaxes share one parse tree shape.
+static OmpUsesAllocatorsClause::AllocatorSpec makeLegacyAllocatorSpec(
+ Name &&name, common::Indirection<Expr> &&traits) {
+ using AllocatorSpec = OmpUsesAllocatorsClause::AllocatorSpec;
+ CharBlock traitsSource{traits.value().source};
+ AllocatorSpec::Modifier mod{OmpTraitsArrayModifier{std::move(traits)}};
+ mod.source = traitsSource;
+ std::list<AllocatorSpec::Modifier> mods;
+ mods.emplace_back(std::move(mod));
+
+ CharBlock allocatorSource{name.source};
+ Expr allocator{Designator{DataRef{std::move(name)}}};
+ allocator.source = allocatorSource;
+ return AllocatorSpec{std::move(mods),
+ ScalarIntExpr{IntExpr{common::Indirection<Expr>{std::move(allocator)}}},
+ /*IsLegacySyntax=*/true};
+}
+
+static OmpUsesAllocatorsClause::AllocatorSpec makeCanonicalAllocatorSpec(
+ std::list<OmpUsesAllocatorsClause::AllocatorSpec::Modifier> &&mods,
+ ScalarIntExpr &&allocator) {
+ return OmpUsesAllocatorsClause::AllocatorSpec{
+ std::move(mods), std::move(allocator), /*IsLegacySyntax=*/false};
+}
+
+// Parse "modifier...: allocator" first: a modifier list is followed by a
+// colon, which neither of the other two forms can contain.
+TYPE_PARSER(sourced( //
+ applyFunction<OmpUsesAllocatorsClause::AllocatorSpec>(
+ makeCanonicalAllocatorSpec,
+ nonemptyList(
+ Parser<OmpUsesAllocatorsClause::AllocatorSpec::Modifier>{}) /
+ ":",
+ scalarIntExpr) ||
+ // Parse the deprecated "allocator(traits-array)" before a bare allocator,
+ // because it is also syntactically an array element reference.
+ applyFunction<OmpUsesAllocatorsClause::AllocatorSpec>(
+ makeLegacyAllocatorSpec, Parser<Name>{},
+ parenthesized(indirect(expr))) ||
+ construct<OmpUsesAllocatorsClause::AllocatorSpec>(
+ pure<std::optional<
+ std::list<OmpUsesAllocatorsClause::AllocatorSpec::Modifier>>>(),
+ scalarIntExpr, pure(false))))
+
+TYPE_PARSER(construct<OmpUsesAllocatorsClause>(
+ nonemptyList(Parser<OmpUsesAllocatorsClause::AllocatorSpec>{})))
+
TYPE_PARSER(construct<OmpAbsentClause>(many(maybe(","_tok) >>
construct<llvm::omp::Directive>(unwrap(OmpDirectiveNameParser{})))))
TYPE_PARSER(construct<OmpContainsClause>(many(maybe(","_tok) >>
@@ -1744,6 +1805,9 @@ TYPE_PARSER( //
"USE_DEVICE_ADDR" >>
construct<OmpClause>(construct<OmpClause::UseDeviceAddr>(
parenthesized(Parser<OmpObjectList>{}))) ||
+ "USES_ALLOCATORS" >>
+ construct<OmpClause>(construct<OmpClause::UsesAllocators>(
+ parenthesized(Parser<OmpUsesAllocatorsClause>{}))) ||
"UNIFIED_ADDRESS" >>
construct<OmpClause>(construct<OmpClause::UnifiedAddress>(
maybe(parenthesized(scalarLogicalConstantExpr)))) ||
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 23d04f2e3ea42..8286030952158 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2636,6 +2636,37 @@ class UnparseVisitor {
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
+ void Unparse(const OmpMemspaceModifier &x) {
+ Word("MEMSPACE(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const OmpTraitsArrayModifier &x) {
+ Word("TRAITS(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const OmpUsesAllocatorsClause &x) { Walk(x.v, ", "); }
+ void Unparse(const OmpUsesAllocatorsClause::AllocatorSpec &x) {
+ using Modifier = OmpUsesAllocatorsClause::AllocatorSpec::Modifier;
+ const auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
+ if (std::get<bool>(x.t)) {
+ // Unparse using the deprecated pre-5.2 syntax.
+ Walk(std::get<ScalarIntExpr>(x.t));
+ if (modifiers) {
+ for (const Modifier &m : *modifiers) {
+ if (auto *traits{std::get_if<OmpTraitsArrayModifier>(&m.u)}) {
+ Put("(");
+ Walk(traits->v);
+ Put(")");
+ }
+ }
+ }
+ } else {
+ Walk(modifiers, ": ");
+ Walk(std::get<ScalarIntExpr>(x.t));
+ }
+ }
void Unparse(const OmpTraitPropertyExtension::Complex &x) {
using PropList = std::list<common::Indirection<OmpTraitPropertyExtension>>;
Walk(std::get<OmpTraitPropertyName>(x.t));
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 65d097b5a31f7..e0c221a2ffa32 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -472,8 +472,14 @@ void OmpStructureChecker::CheckIterationVariables(
for (const parser::OmpClause &clause : spec.Clauses().v) {
llvm::omp::Clause clauseId{clause.Id()};
if (llvm::omp::isDataSharingAttributeClause(clauseId, version)) {
- for (const parser::OmpObject &object :
- parser::omp::GetOmpObjectList(clause)->v) {
+ // Not every data-sharing attribute clause takes an object list, e.g.
+ // USES_ALLOCATORS takes allocator specifications instead.
+ const parser::OmpObjectList *objects{
+ parser::omp::GetOmpObjectList(clause)};
+ if (!objects) {
+ continue;
+ }
+ for (const parser::OmpObject &object : objects->v) {
if (const Symbol *symbol{GetObjectSymbol(object, /*ultimate=*/true)}) {
auto maybeSource{parser::omp::GetObjectSource(object)};
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/213955
More information about the flang-commits
mailing list