[flang-commits] [flang] [llvm] [flang][OpenMP] Parsing and semantics of locators as part of OmpObject (PR #203910)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Thu Jun 18 08:10:32 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/203910
>From 97a77ea6477f418d8f296a4cf353dd27cf2f7c93 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Sat, 13 Jun 2026 08:41:02 -0500
Subject: [PATCH 1/7] [flang] Extract misparsed function reference check into
function
Function calls and array element acceses have the same syntax, and some
array element accesses may be misparsed as calls. The ExprChecker will
identify and correct such cases in expressions, but they may also occur
outside of expressions (e.g. OpenMP directives and clauses).
To avoid code duplication extract the check into a new function
`IsMisparsedFunctionReference`.
---
flang/include/flang/Semantics/expression.h | 3 +
flang/lib/Semantics/expression.cpp | 70 ++++++++++++----------
2 files changed, 41 insertions(+), 32 deletions(-)
diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index f93b9a892715a..49063d570ce13 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -470,6 +470,9 @@ evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
void NoteUsedSymbols(
SemanticsContext &, const SomeExpr &, bool isDefinition = false);
+bool IsMisparsedArrayElement(
+ SemanticsContext &, const parser::FunctionReference &);
+
// Semantic analysis of all expressions in a parse tree, which becomes
// decorated with typed representations for top-level expressions.
class ExprChecker {
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index b457d1a87990d..aba4996bbce84 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -4354,38 +4354,12 @@ static void FixMisparsedFunctionReference(
if (auto *func{
std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
parser::FunctionReference &funcRef{func->value()};
- // Ensure that there are no argument keywords
- for (const auto &arg :
- std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
- if (std::get<std::optional<parser::Keyword>>(arg.t)) {
- return;
- }
- }
- auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
- if (Symbol *
- origSymbol{common::visit(
- common::visitors{
- [&](parser::Name &name) { return name.symbol; },
- [&](parser::ProcComponentRef &pcr) {
- return parser::UnwrapRef<parser::StructureComponent>(pcr)
- .Component()
- .symbol;
- },
- },
- proc.u)}) {
- Symbol &symbol{origSymbol->GetUltimate()};
- if (symbol.has<semantics::ObjectEntityDetails>() ||
- symbol.has<semantics::AssocEntityDetails>()) {
- // Note that expression in AssocEntityDetails cannot be a procedure
- // pointer as per C1105 so this cannot be a function reference.
- if constexpr (common::HasMember<common::Indirection<parser::Designator>,
- uType>) {
- if (CheckFuncRefToArrayElement(context, funcRef)) {
- u = common::Indirection{funcRef.ConvertToArrayElementRef()};
- }
- } else {
- DIE("can't fix misparsed function as array reference");
- }
+ if (semantics::IsMisparsedArrayElement(context, funcRef)) {
+ if constexpr (common::HasMember<common::Indirection<parser::Designator>,
+ uType>) {
+ u = common::Indirection{funcRef.ConvertToArrayElementRef()};
+ } else {
+ DIE("can't fix misparsed function as array reference");
}
}
}
@@ -5622,6 +5596,38 @@ void NoteUsedSymbols(
evaluate::CollectUsedSymbolValues(context, expr, isDefinition));
}
+bool IsMisparsedArrayElement(SemanticsContext &context,
+ const parser::FunctionReference &funcRef) {
+ // Ensure that there are no argument keywords
+ for (const auto &arg :
+ std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
+ if (std::get<std::optional<parser::Keyword>>(arg.t)) {
+ return false;
+ }
+ }
+ auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
+ if (const Symbol *
+ origSymbol{common::visit(
+ common::visitors{
+ [&](const parser::Name &name) { return name.symbol; },
+ [&](const parser::ProcComponentRef &pcr) {
+ return parser::UnwrapRef<parser::StructureComponent>(pcr)
+ .Component()
+ .symbol;
+ },
+ },
+ proc.u)}) {
+ const Symbol &symbol{origSymbol->GetUltimate()};
+ if (symbol.has<semantics::ObjectEntityDetails>() ||
+ symbol.has<semantics::AssocEntityDetails>()) {
+ // Note that expression in AssocEntityDetails cannot be a procedure
+ // pointer as per C1105 so this cannot be a function reference.
+ return evaluate::CheckFuncRefToArrayElement(context, funcRef);
+ }
+ }
+ return false;
+}
+
ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
bool ExprChecker::Pre(const parser::DataStmtObject &obj) {
>From 989c2a4633911b68ed25c2adf9618837e498be09 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 15 Jun 2026 08:21:57 -0500
Subject: [PATCH 2/7] format
---
flang/lib/Semantics/expression.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index aba4996bbce84..e776f4e6adc91 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -5596,8 +5596,8 @@ void NoteUsedSymbols(
evaluate::CollectUsedSymbolValues(context, expr, isDefinition));
}
-bool IsMisparsedArrayElement(SemanticsContext &context,
- const parser::FunctionReference &funcRef) {
+bool IsMisparsedArrayElement(
+ SemanticsContext &context, const parser::FunctionReference &funcRef) {
// Ensure that there are no argument keywords
for (const auto &arg :
std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
@@ -5606,8 +5606,7 @@ bool IsMisparsedArrayElement(SemanticsContext &context,
}
}
auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
- if (const Symbol *
- origSymbol{common::visit(
+ if (const Symbol *origSymbol{common::visit(
common::visitors{
[&](const parser::Name &name) { return name.symbol; },
[&](const parser::ProcComponentRef &pcr) {
>From ae8510040697cb7f1644d955c2bee50699932f78 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 9 Jun 2026 15:51:48 -0500
Subject: [PATCH 3/7] [flang][OpenMP] Parsing and semantics of locators as part
of OmpObject
Allow function call references and reserved locator names as parts of
OmpObject. Function calls and array element accesses have the same syntax,
and the OmpObject parser will parse them as function calls. This is then
corrected (if needed) immediately after the name resolution is complete.
There are no clause-specific semantic checks of proper locators. Existing
code will check if a proper locator is specified on a clause that allows
it.
Lowering of proper locators to MLIR is not implemented, and a TODO
message is emitted.
---
flang/include/flang/Parser/dump-parse-tree.h | 2 +-
flang/include/flang/Parser/parse-tree.h | 23 ++++-----
flang/include/flang/Semantics/expression.h | 4 +-
flang/include/flang/Semantics/symbol.h | 4 +-
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 22 +++++++++
flang/lib/Lower/OpenMP/Clauses.cpp | 49 +++++++++++++++----
flang/lib/Parser/openmp-parsers.cpp | 37 ++++++++------
flang/lib/Parser/openmp-utils.cpp | 12 +++--
flang/lib/Parser/unparse.cpp | 2 +-
flang/lib/Semantics/check-omp-loop.cpp | 2 +-
flang/lib/Semantics/check-omp-structure.cpp | 28 +++++++++--
flang/lib/Semantics/check-omp-structure.h | 1 +
flang/lib/Semantics/check-omp-variant.cpp | 2 +-
flang/lib/Semantics/openmp-utils.cpp | 48 +++++++++++++++---
flang/lib/Semantics/resolve-directives.cpp | 3 ++
flang/lib/Semantics/resolve-names.cpp | 16 +++++-
flang/lib/Semantics/rewrite-parse-tree.cpp | 17 +++++++
.../OpenMP/Todo/locator-call-affinity.f90 | 13 +++++
.../Lower/OpenMP/Todo/locator-call-from.f90 | 12 +++++
.../Lower/OpenMP/Todo/locator-call-map.f90 | 13 +++++
.../Lower/OpenMP/Todo/locator-call-to.f90 | 12 +++++
.../Lower/OpenMP/Todo/locator-reserved.f90 | 11 +++++
.../Parser/OpenMP/allocate-align-tree.f90 | 4 +-
.../Parser/OpenMP/allocate-tree-spec-part.f90 | 8 +--
flang/test/Parser/OpenMP/allocate-tree.f90 | 6 +--
flang/test/Parser/OpenMP/declare-variant.f90 | 8 +--
flang/test/Parser/OpenMP/depobj-construct.f90 | 8 +--
flang/test/Parser/OpenMP/groupprivate.f90 | 6 +--
.../Parser/OpenMP/metadirective-dirspec.f90 | 14 +++---
.../Parser/OpenMP/metadirective-flush.f90 | 4 +-
.../OpenMP/openmp6-directive-spellings.f90 | 2 +-
flang/test/Parser/OpenMP/threadprivate.f90 | 4 +-
.../Semantics/OpenMP/affinity-invalid.f90 | 8 ---
.../Semantics/OpenMP/depend-substring.f90 | 9 ----
.../Semantics/OpenMP/reserved-locator.f90 | 6 +++
llvm/include/llvm/Frontend/OpenMP/OMP.h | 2 +
llvm/lib/Frontend/OpenMP/OMP.cpp | 6 +++
37 files changed, 319 insertions(+), 109 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90
create mode 100644 flang/test/Lower/OpenMP/Todo/locator-call-from.f90
create mode 100644 flang/test/Lower/OpenMP/Todo/locator-call-map.f90
create mode 100644 flang/test/Lower/OpenMP/Todo/locator-call-to.f90
create mode 100644 flang/test/Lower/OpenMP/Todo/locator-reserved.f90
create mode 100644 flang/test/Semantics/OpenMP/reserved-locator.f90
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 1205101c21fcf..ceba23d7d4706 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -667,7 +667,6 @@ class ParseTreeDumper {
NODE(parser, OmpLinearModifier)
NODE_ENUM(OmpLinearModifier, Value)
NODE(parser, OmpLocator)
- NODE(parser, OmpLocatorList)
NODE(parser, OmpLooprangeClause)
NODE(parser, OmpLowerBound)
NODE(parser, OmpMapClause)
@@ -722,6 +721,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpRefModifier, Value)
NODE(parser, OmpReplayableClause)
NODE(parser, OmpRequiresDirective)
+ NODE(parser, OmpReservedIdentifier)
NODE(parser, OmpReverseOffloadClause)
NODE(parser, OmpScheduleClause)
NODE(OmpScheduleClause, Modifier)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ee6288539395c..ea4ce1882eb1b 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3599,6 +3599,16 @@ struct OmpTypeNameList {
WRAPPER_CLASS_BOILERPLATE(OmpTypeNameList, std::list<OmpTypeName>);
};
+struct OmpReservedIdentifier {
+ WRAPPER_CLASS_BOILERPLATE(OmpReservedIdentifier, Name);
+};
+
+// "Proper" locator, i.e. a function reference or a reserved locator.
+struct OmpLocator {
+ UNION_CLASS_BOILERPLATE(OmpLocator);
+ std::variant<FunctionReference, OmpReservedIdentifier> u;
+};
+
// 2.1 Directives or clauses may accept a list or extended-list.
// A list item is a variable, array section or common block name (enclosed
// in slashes). An extended list item is a list item or a procedure Name.
@@ -3612,7 +3622,7 @@ struct OmpObject {
CharBlock source;
};
UNION_CLASS_BOILERPLATE(OmpObject);
- std::variant<Designator, /*common block*/ Name, Invalid> u;
+ std::variant<Designator, OmpLocator, Name, Invalid> u;
};
struct OmpObjectList {
@@ -3688,15 +3698,6 @@ struct OmpInitializerExpression : public OmpStylizedExpression {
};
inline namespace arguments {
-struct OmpLocator {
- UNION_CLASS_BOILERPLATE(OmpLocator);
- std::variant<OmpObject, FunctionReference> u;
-};
-
-struct OmpLocatorList {
- WRAPPER_CLASS_BOILERPLATE(OmpLocatorList, std::list<OmpLocator>);
-};
-
// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
//
// Argument to DECLARE VARIANT with the base-name present. (When only
@@ -3737,7 +3738,7 @@ struct OmpReductionSpecifier {
struct OmpArgument {
CharBlock source;
UNION_CLASS_BOILERPLATE(OmpArgument);
- std::variant<OmpLocator, // {variable, extended, locator}-list-item
+ std::variant<OmpObject,
OmpBaseVariantNames, // base-name:variant-name
OmpMapperSpecifier, OmpReductionSpecifier>
u;
diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index 49063d570ce13..44ef81d93bad5 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -252,6 +252,8 @@ class ExpressionAnalyzer {
MaybeExpr Analyze(const parser::InitialDataTarget &);
MaybeExpr Analyze(const parser::NullInit &);
MaybeExpr Analyze(const parser::StmtFunctionStmt &);
+ MaybeExpr Analyze(const parser::FunctionReference &,
+ std::optional<parser::StructureConstructor> * = nullptr);
void Analyze(const parser::CallStmt &);
const Assignment *Analyze(const parser::AssignmentStmt &);
@@ -293,8 +295,6 @@ class ExpressionAnalyzer {
MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &);
MaybeExpr Analyze(const parser::SubstringInquiry &);
MaybeExpr Analyze(const parser::ArrayConstructor &);
- MaybeExpr Analyze(const parser::FunctionReference &,
- std::optional<parser::StructureConstructor> * = nullptr);
MaybeExpr Analyze(const parser::Expr::Parentheses &);
MaybeExpr Analyze(const parser::Expr::UnaryPlus &);
MaybeExpr Analyze(const parser::Expr::Negate &);
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 40c49c594a707..745e4fe442987 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -906,8 +906,8 @@ class Symbol {
// OpenMP special variables
OmpInVar, OmpOrigVar, OmpOutVar, OmpPrivVar,
// OpenMP miscellaneous flags
- OmpCommonBlock, OmpReduction, OmpInReduction, OmpAligned, OmpNontemporal,
- OmpAllocate, OmpDeclarativeAllocateDirective,
+ OmpReserved, OmpCommonBlock, OmpReduction, OmpInReduction, OmpAligned,
+ OmpNontemporal, OmpAllocate, OmpDeclarativeAllocateDirective,
OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget,
OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock,
OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit,
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index eb416d103fbe0..2dc3806a52df2 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -29,6 +29,24 @@ namespace Fortran {
namespace lower {
namespace omp {
+static void TodoLocators(mlir::Location loc, const omp::ObjectList &objects) {
+ for (const omp::Object &object : objects) {
+ if (auto &ref = object.ref()) {
+ auto op = GetTopLevelOperation(*ref).first;
+ if (op == evaluate::operation::Operator::Call)
+ TODO(loc, "Function call locators are not supported yet");
+ }
+ semantics::Symbol *symbol = object.sym();
+ if (symbol->test(semantics::Symbol::Flag::OmpReserved)) {
+ std::string name =
+ parser::ToLowerCaseLetters(object.sym()->name().ToString());
+ if (llvm::is_contained(llvm::omp::getReservedLocatorNames(), name)) {
+ TODO(loc, "Reserved locators are not supported yet");
+ }
+ }
+ }
+}
+
using ReductionModifier =
Fortran::lower::omp::clause::Reduction::ReductionModifier;
@@ -971,6 +989,8 @@ bool ClauseProcessor::processAffinity(
std::get<std::optional<omp::clause::Iterator>>(clause.t);
collectIteratorIVs(clause, converter, stmtCtx, iteratorRanges, ivSyms);
+ TodoLocators(clauseLocation, objects);
+
for (const omp::Object &object : objects) {
llvm::SmallVector<mlir::Value> bounds;
std::stringstream asFortran;
@@ -1972,6 +1992,7 @@ bool ClauseProcessor::processMap(
if (iterator)
TODO(currentLocation,
"Support for iterator modifiers is not implemented yet");
+ TodoLocators(currentLocation, objects);
processMapObjects(stmtCtx, clauseLocation,
std::get<omp::ObjectList>(clause.t), mapTypeBits,
@@ -2007,6 +2028,7 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
if (iterator)
TODO(clauseLocation, "Iterator modifier is not supported yet");
+ TodoLocators(clauseLocation, objects);
processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
parentMemberIndices, result.mapVars, mapObjects,
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 03852dc9e7d74..9ab9e9349254b 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -57,6 +57,12 @@ struct SymbolAndDesignatorExtractor {
evaluate::AsGenericExpr(AsRvalueRef(e)));
}
+ template <typename T>
+ static SymbolWithDesignator visit(const evaluate::FunctionRef<T> &e) {
+ return std::make_tuple(symbol_addr(*e.proc().GetSymbol()),
+ evaluate::AsGenericExpr(AsRvalueRef(e)));
+ }
+
static SymbolWithDesignator visit(const evaluate::ProcedureDesignator &e) {
return std::make_tuple(symbol_addr(*e.GetSymbol()), std::nullopt);
}
@@ -78,12 +84,16 @@ struct SymbolAndDesignatorExtractor {
if (maybeRef) {
if (&maybeRef->GetLastSymbol() == symbol)
return; // Symbol with a designator for it -> OK
- llvm_unreachable("Expecting designator for given symbol");
+ llvm_unreachable("Symbol mismatch");
+ } else if (auto *ref = evaluate::UnwrapProcedureRef(*maybeDsg)) {
+ if (ref->proc().GetSymbol() == symbol)
+ return;
+ llvm_unreachable("Symbol mismatch");
} else {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
maybeDsg->dump();
#endif
- llvm_unreachable("Expecting DataRef designator");
+ llvm_unreachable("Unexpected expression");
}
}
};
@@ -110,6 +120,14 @@ Object makeObject(const parser::Designator &dsg,
return Object{std::get<0>(sd), std::move(std::get<1>(sd))};
}
+Object makeObject(const parser::FunctionReference &ref,
+ semantics::SemanticsContext &semaCtx) {
+ evaluate::ExpressionAnalyzer ea{semaCtx};
+ SymbolWithDesignator sd = getSymbolAndDesignator(ea.Analyze(ref));
+ SymbolAndDesignatorExtractor::verify(sd);
+ return Object{std::get<0>(sd), std::move(std::get<1>(sd))};
+}
+
Object makeObject(const parser::StructureComponent &comp,
semantics::SemanticsContext &semaCtx) {
evaluate::ExpressionAnalyzer ea{semaCtx};
@@ -127,8 +145,24 @@ Object makeObject(const parser::OmpObject &object,
assert(name->symbol && "Expecting Symbol");
return Object{name->symbol, std::nullopt};
}
- // OmpObject is std::variant<Designator, /*common block*/ Name>;
- return makeObject(std::get<parser::Designator>(object.u), semaCtx);
+ assert(!std::holds_alternative<parser::OmpObject::Invalid>(object.u) &&
+ "Invalid object should have been caught in semantics");
+ // OmpObject is std::variant<Designator, OmpLocator, Name, Invalid>;
+ if (auto *desg = std::get_if<parser::Designator>(&object.u))
+ return makeObject(*desg, semaCtx);
+ if (auto *locator = std::get_if<parser::OmpLocator>(&object.u)) {
+ return common::visit( //
+ common::visitors{
+ [&](const parser::OmpReservedIdentifier &x) {
+ return makeObject(x.v, semaCtx);
+ },
+ [&](const parser::FunctionReference &x) {
+ return makeObject(x, semaCtx);
+ },
+ },
+ locator->u);
+ }
+ llvm_unreachable("Unexpected OmpObject");
}
Object makeObject(const parser::EntityDecl &decl,
@@ -141,11 +175,8 @@ ObjectList makeObjects(const parser::OmpArgumentList &objects,
return makeList(objects.v, [&](const parser::OmpArgument &arg) {
return common::visit(
common::visitors{
- [&](const parser::OmpLocator &locator) -> Object {
- if (auto *object = std::get_if<parser::OmpObject>(&locator.u)) {
- return makeObject(*object, semaCtx);
- }
- llvm_unreachable("Expecting object");
+ [&](const parser::OmpObject &object) -> Object {
+ return makeObject(object, semaCtx);
},
[](auto &&s) -> Object { //
llvm_unreachable("Expecting object");
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 7016c688a572d..a44228f2484f3 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -281,6 +281,27 @@ TYPE_PARSER(construct<common::OmpMemoryOrderType>(
"RELEASE" >> pure(common::OmpMemoryOrderType::Release) ||
"SEQ_CST" >> pure(common::OmpMemoryOrderType::Seq_Cst)))
+static bool IsReservedName(const Name &name) {
+ llvm::StringRef s(name.source.begin(), name.source.size());
+ return s.starts_with_insensitive("OMP_") ||
+ s.starts_with_insensitive("OMPX_");
+}
+
+TYPE_PARSER( //
+ construct<OmpReservedIdentifier>(predicated(name, IsReservedName)))
+
+TYPE_PARSER( //
+ // Parse x(...)(...) as a substring instead of a function reference.
+ construct<OmpLocator>(functionReference / !lookAhead("("_tok)) ||
+ construct<OmpLocator>(Parser<OmpReservedIdentifier>{}))
+
+TYPE_PARSER( //
+ construct<OmpObject>(Parser<OmpLocator>{}) ||
+ construct<OmpObject>(designator) ||
+ "/" >> construct<OmpObject>(name) / "/" ||
+ construct<OmpObject>(sourced(construct<OmpObject::Invalid>(
+ "//"_tok >> pure(OmpObject::Invalid::Kind::BlankCommonBlock)))))
+
// --- Modifier helpers -----------------------------------------------
template <typename Clause, typename Separator> struct ModifierList {
@@ -588,10 +609,6 @@ TYPE_PARSER( //
// At the moment these are only directive arguments. This is needed for
// parsing directive-specification.
-TYPE_PARSER( //
- construct<OmpLocator>(Parser<OmpObject>{}) ||
- construct<OmpLocator>(Parser<FunctionReference>{}))
-
TYPE_PARSER(construct<OmpBaseVariantNames>(
Parser<OmpObject>{} / ":", Parser<OmpObject>{}))
@@ -610,7 +627,7 @@ struct OmpArgumentParser {
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}),
// By default, prefer OmpReductionSpecifier over OmpBaseVariantNames.
construct<OmpArgument>(Parser<OmpReductionSpecifier>{}),
- construct<OmpArgument>(Parser<OmpLocator>{})))};
+ construct<OmpArgument>(Parser<OmpObject>{})))};
return parser.Parse(state);
}
};
@@ -625,13 +642,11 @@ struct OmpArgumentParser<llvm::omp::Directive::OMPD_declare_variant> {
// In DECLARE_VARIANT parse OmpBaseVariantNames instead of
// OmpReductionSpecifier.
construct<OmpArgument>(Parser<OmpBaseVariantNames>{}),
- construct<OmpArgument>(Parser<OmpLocator>{})))};
+ construct<OmpArgument>(Parser<OmpObject>{})))};
return parser.Parse(state);
}
};
-TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))
-
template <llvm::omp::Directive Id = llvm::omp::Directive::OMPD_unknown>
struct OmpArgumentListParser {
using resultType = OmpArgumentList;
@@ -1405,12 +1420,6 @@ TYPE_PARSER(construct<OmpNumThreadsClause>(
maybe(nonemptyList(Parser<OmpNumThreadsClause::Modifier>{}) / ":"),
nonemptyList(scalarIntExpr)))
-TYPE_PARSER( //
- construct<OmpObject>(designator) ||
- "/" >> construct<OmpObject>(name) / "/" ||
- construct<OmpObject>(sourced(construct<OmpObject::Invalid>(
- "//"_tok >> pure(OmpObject::Invalid::Kind::BlankCommonBlock)))))
-
// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
TYPE_PARSER(construct<OmpLastprivateClause>(
maybe(nonemptyList(Parser<OmpLastprivateClause::Modifier>{}) / ":"),
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index ec312bcf3ebfd..ca563f2df892d 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -54,16 +54,20 @@ std::optional<parser::CharBlock> GetObjectSource(
return name->source;
} else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
return GetLastName(*desg).source;
+ } else if (auto *locator{std::get_if<parser::OmpLocator>(&object.u)}) {
+ return common::visit( //
+ common::visitors{
+ [](const parser::OmpReservedIdentifier &x) { return x.v.source; },
+ [](const parser::FunctionReference &x) { return x.source; },
+ },
+ locator->u);
}
return std::nullopt;
}
const parser::OmpObject *GetArgumentObject(
const parser::OmpArgument &argument) {
- if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
- return std::get_if<parser::OmpObject>(&locator->u);
- }
- return nullptr;
+ return std::get_if<parser::OmpObject>(&argument.u);
}
namespace detail {
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 42f042e470e81..7d0038767a9c4 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2515,7 +2515,7 @@ class UnparseVisitor {
void Unparse(const OmpObject &x) {
common::visit( //
common::visitors{
- [&](const Designator &y) { Walk(y); },
+ [&](const auto &y) { Walk(y); },
[&](const Name &y) {
Put("/");
Walk(y);
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 689e3a0da89ca..bfb98b2295c16 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -666,7 +666,7 @@ void OmpStructureChecker::CheckScanModifier(
[&](const parser::Name &name) {
checkReductionSymbolInScan(name);
},
- [&](const parser::OmpObject::Invalid &invalid) {},
+ [&](const auto &) {},
},
ompObj.u);
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 7c531ae0046ae..05eed5860b4b7 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -414,12 +414,18 @@ void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
}
}
}
+
evaluate::ExpressionAnalyzer ea{context_};
auto restore{ea.AllowWholeAssumedSizeArray(true)};
common::visit( //
common::visitors{
[&](auto &&s) { ea.Analyze(s); },
- [&](const parser::OmpObject::Invalid &invalid) {},
+ [&](const parser::OmpLocator &x) {
+ if (auto *ref{std::get_if<parser::FunctionReference>(&x.u)}) {
+ ea.Analyze(*ref);
+ }
+ },
+ [&](const parser::OmpObject::Invalid &) {},
},
object.u);
}
@@ -616,6 +622,16 @@ bool OmpStructureChecker::HasRequires(llvm::omp::Clause req) {
DEREF(unit.symbol()).details());
}
+void OmpStructureChecker::Enter(const parser::OmpLocator &x) {
+ if (auto *reserved{parser::Unwrap<parser::OmpReservedIdentifier>(x.u)}) {
+ std::string name{parser::ToLowerCaseLetters(reserved->v.source.ToString())};
+ if (!llvm::is_contained(llvm::omp::getReservedLocatorNames(), name)) {
+ context_.Say(reserved->v.source, "'%s' is not a valid locator"_err_en_US,
+ parser::ToUpperCaseLetters(name));
+ }
+ }
+}
+
void OmpStructureChecker::CheckArgumentObjectKind(const parser::OmpClause &x) {
unsigned version{context_.langOptions().OpenMPVersion};
llvm::omp::Directive dirId{GetContext().directive};
@@ -1676,7 +1692,8 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
common::visit( //
common::visitors{
[&](auto &&s) { CheckThreadprivateOrDeclareTargetVar(s); },
- [&](const parser::OmpObject::Invalid &invalid) {},
+ [&](const parser::OmpLocator &) {},
+ [&](const parser::OmpObject::Invalid &) {},
},
object.u);
}
@@ -1693,10 +1710,10 @@ void OmpStructureChecker::Enter(const parser::OmpGroupprivateDirective &x) {
x.v.DirName().source, llvm::omp::Directive::OMPD_groupprivate);
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
- auto *locator{std::get_if<parser::OmpLocator>(&arg.u)};
+ auto *object{std::get_if<parser::OmpObject>(&arg.u)};
const Symbol *sym{GetArgumentSymbol(arg, /*ultimate=*/true)};
- if (!locator || !sym ||
+ if (!object || !sym ||
(!IsVariableListItem(*sym) && !IsCommonBlock(*sym))) {
context_.Say(arg.source,
"GROUPPRIVATE argument should be a variable or a named common block"_err_en_US);
@@ -3666,7 +3683,8 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &x) {
}
}
},
- [&](const parser::OmpObject::Invalid &invalid) {},
+ [&](const parser::OmpLocator &) {},
+ [&](const parser::OmpObject::Invalid &) {},
},
ompObject.u);
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 42ab0c2ef5ef1..f45fe7a46f3ed 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -167,6 +167,7 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void Enter(const parser::OpenMPAtomicConstruct &);
void Leave(const parser::OpenMPAtomicConstruct &);
+ void Enter(const parser::OmpLocator &x);
void Leave(const parser::OmpClauseList &);
void Enter(const parser::OmpClause &);
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 8ab160496b64a..88de08d3cf908 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -701,7 +701,7 @@ void OmpStructureChecker::CheckOmpDeclareVariantDirective(
CheckProcedureSymbol(base, arg.source);
CheckProcedureSymbol(variant, arg.source);
},
- [&](const parser::OmpLocator &y) {
+ [&](const parser::OmpObject &y) {
variant = GetArgumentSymbol(arg);
CheckProcedureSymbol(variant, arg.source);
const Scope &containingScope{context_.FindScope(x.source)};
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index b02ef81176a63..d5035cbd2ddcd 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -121,6 +121,21 @@ std::string TryVersion(unsigned version) {
return "try -fopenmp-version=" + std::to_string(version);
}
+static const Symbol *GetFunctionReferenceSymbol(
+ const parser::FunctionReference &ref) {
+ auto &proc{std::get<parser::ProcedureDesignator>(ref.v.t)};
+ return common::visit(
+ common::visitors{
+ [](const parser::Name &x) { return x.symbol; },
+ [](const parser::ProcComponentRef &x) {
+ return parser::UnwrapRef<parser::StructureComponent>(x.v)
+ .Component()
+ .symbol;
+ },
+ },
+ proc.u);
+}
+
const Symbol *GetObjectSymbol(const parser::OmpObject &object, bool ultimate) {
// Some symbols may be missing if the resolution failed, e.g. when an
// undeclared name is used with implicit none.
@@ -137,16 +152,28 @@ const Symbol *GetObjectSymbol(const parser::OmpObject &object, bool ultimate) {
} else {
return last.symbol;
}
+ } else if (auto *locator{std::get_if<parser::OmpLocator>(&object.u)}) {
+ const Symbol *sym = common::visit( //
+ common::visitors{
+ [](const parser::OmpReservedIdentifier &x) { return x.v.symbol; },
+ [](const parser::FunctionReference &x) {
+ return GetFunctionReferenceSymbol(x);
+ },
+ },
+ locator->u);
+ if (sym && ultimate) {
+ return &sym->GetUltimate();
+ } else {
+ return sym;
+ }
}
return nullptr;
}
const Symbol *GetArgumentSymbol(
const parser::OmpArgument &argument, bool ultimate) {
- if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
- if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
- return GetObjectSymbol(*object, ultimate);
- }
+ if (auto *object{GetArgumentObject(argument)}) {
+ return GetObjectSymbol(*object, ultimate);
}
return nullptr;
}
@@ -233,17 +260,21 @@ bool IsExtendedListItem(
if (IsVariableListItem(object, semaCtx)) {
return true;
}
- if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
- return IsProcedure(*sym);
+ if (!std::holds_alternative<parser::OmpLocator>(object.u)) {
+ if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+ return IsProcedure(*sym);
+ }
}
return false;
}
bool IsLocatorListItem(
const parser::OmpObject &object, SemanticsContext *semaCtx) {
- if (IsVariableListItem(object, semaCtx)) {
+ if (IsVariableListItem(object, semaCtx) ||
+ std::holds_alternative<parser::OmpLocator>(object.u)) {
return true;
}
+ // A statement function call may look like an array element access.
if (auto *desg{parser::Unwrap<parser::Designator>(object)}) {
evaluate::ExpressionAnalyzer ea(*semaCtx);
auto restorer{ea.GetContextualMessages().DiscardMessages()};
@@ -447,6 +478,9 @@ std::optional<bool> IsContiguous(
}
return std::optional<bool>{};
},
+ [&](const parser::OmpLocator &) {
+ return std::optional<bool>{};
+ },
[&](const parser::OmpObject::Invalid &) {
return std::optional<bool>{};
}},
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 5d72698b0250d..aca1a72035360 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3134,6 +3134,9 @@ void OmpAttributeVisitor::ResolveOmpObject(
[&](const parser::Name &name) { // common block
ResolveOmpCommonBlock(name, ompFlag);
},
+ [&](const parser::OmpLocator &ref) {
+ // Do nothing here.
+ },
[&](const parser::OmpObject::Invalid &invalid) {
switch (invalid.v) {
SWITCH_COVERS_ALL_CASES
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2acdaa916f557..e5853cf313b77 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1738,6 +1738,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));
}
+ bool Pre(const parser::OmpReservedIdentifier &);
void Post(const parser::OmpTypeName &);
bool Pre(const parser::OmpStylizedDeclaration &);
void Post(const parser::OmpStylizedDeclaration &);
@@ -1938,6 +1939,17 @@ void OmpVisitor::PushScopeWithSource(
currScope().AddSourceRange(source);
}
+bool OmpVisitor::Pre(const parser::OmpReservedIdentifier &x) {
+ // Create a unique symbol in the global scope.
+ if (auto *symbol{context().globalScope().FindSymbol(x.v.source)}) {
+ x.v.symbol = symbol;
+ } else {
+ MakePlaceholder(x.v, MiscDetails::Kind::None);
+ }
+ x.v.symbol->set(Symbol::Flag::OmpReserved);
+ return false;
+}
+
void OmpVisitor::Post(const parser::OmpTypeName &x) {
x.declTypeSpec = GetDeclTypeSpec();
}
@@ -2205,7 +2217,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
Walk(std::get<0>(names.t));
Walk(std::get<1>(names.t));
},
- [&](const parser::OmpLocator &locator) {
+ [&](const parser::OmpObject &object) {
// Manually resolve names in CRITICAL directives. This is because
// these names do not denote Fortran objects, and the CRITICAL
// directive causes them to be "auto-declared", i.e. inserted into
@@ -2215,7 +2227,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
if (x.DirId() == llvm::omp::Directive::OMPD_critical) {
ResolveCriticalName(arg);
} else {
- Walk(locator);
+ Walk(object);
}
},
},
diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp
index 4e1c9bae9c153..f3513d8a51128 100644
--- a/flang/lib/Semantics/rewrite-parse-tree.cpp
+++ b/flang/lib/Semantics/rewrite-parse-tree.cpp
@@ -82,6 +82,7 @@ class RewriteMutator {
bool Pre(parser::EndSubroutineStmt &) { return false; }
bool Pre(parser::EndTypeStmt &) { return false; }
+ bool Pre(parser::OmpObject &);
bool Pre(parser::OmpBlockConstruct &);
bool Pre(parser::OpenMPLoopConstruct &);
void Post(parser::OmpBlockConstruct &);
@@ -371,6 +372,22 @@ bool RewriteMutator::Pre(parser::Block &block) {
void RewriteMutator::Post(parser::Block &block) { this->Pre(block); }
+bool RewriteMutator::Pre(parser::OmpObject &object) {
+ // When parsing A(i) there is no way to tell whether it's a function call
+ // or an array element access. In OmpObject it will be preferentially
+ // parsed as FunctionReference, but once the name "A" is resolved, and it
+ // turns out to be an array, the function call in the OmpObject will need
+ // to be converted to an array element.
+ // This has to happen early, before the ExprChecker runs, or otherwise it
+ // will emit undesirable diagnostics.
+ if (auto *ref{parser::Unwrap<parser::FunctionReference>(object)}) {
+ if (IsMisparsedArrayElement(context_, *ref)) {
+ object.u = ref->ConvertToArrayElementRef();
+ }
+ }
+ return true;
+}
+
bool RewriteMutator::Pre(parser::OmpBlockConstruct &block) {
if (context_.langOptions().OpenMPSimd) {
auto &innerBlock = std::get<parser::Block>(block.t);
diff --git a/flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90 b/flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90
new file mode 100644
index 0000000000000..2f17e6c22c932
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90
@@ -0,0 +1,13 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: Function call locators are not supported yet
+
+subroutine f
+ interface
+ function p
+ integer, pointer :: p
+ end
+ end interface
+ !$omp task affinity(p())
+ !$omp end task
+end
diff --git a/flang/test/Lower/OpenMP/Todo/locator-call-from.f90 b/flang/test/Lower/OpenMP/Todo/locator-call-from.f90
new file mode 100644
index 0000000000000..66e6a5eb1a147
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/locator-call-from.f90
@@ -0,0 +1,12 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: Function call locators are not supported yet
+
+subroutine f
+ interface
+ function p
+ integer, pointer :: p
+ end
+ end interface
+ !$omp target update from(p())
+end
diff --git a/flang/test/Lower/OpenMP/Todo/locator-call-map.f90 b/flang/test/Lower/OpenMP/Todo/locator-call-map.f90
new file mode 100644
index 0000000000000..a0c17c7584e80
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/locator-call-map.f90
@@ -0,0 +1,13 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: Function call locators are not supported yet
+
+subroutine f
+ interface
+ function p
+ integer, pointer :: p
+ end
+ end interface
+ !$omp target map(p())
+ !$omp end target
+end
diff --git a/flang/test/Lower/OpenMP/Todo/locator-call-to.f90 b/flang/test/Lower/OpenMP/Todo/locator-call-to.f90
new file mode 100644
index 0000000000000..e5747bdda82b1
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/locator-call-to.f90
@@ -0,0 +1,12 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: Function call locators are not supported yet
+
+subroutine f
+ interface
+ function p
+ integer, pointer :: p
+ end
+ end interface
+ !$omp target update to(p())
+end
diff --git a/flang/test/Lower/OpenMP/Todo/locator-reserved.f90 b/flang/test/Lower/OpenMP/Todo/locator-reserved.f90
new file mode 100644
index 0000000000000..e742ce843501b
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/locator-reserved.f90
@@ -0,0 +1,11 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: Reserved locators are not supported yet
+
+subroutine f
+ ! This is a wrong use of OMP_ALL_MEMORY, but at the moment the clauses that
+ ! legally allow this locator aren't accepting it yet in flang.
+ !$omp target map(omp_all_memory)
+ !$omp end target
+end
+
diff --git a/flang/test/Parser/OpenMP/allocate-align-tree.f90 b/flang/test/Parser/OpenMP/allocate-align-tree.f90
index e440d23904693..35f7d00b88a29 100644
--- a/flang/test/Parser/OpenMP/allocate-align-tree.f90
+++ b/flang/test/Parser/OpenMP/allocate-align-tree.f90
@@ -25,7 +25,7 @@ end program allocate_align_tree
!CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | OmpBeginDirective
!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'j'
+!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'j'
!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '16_4'
!CHECK-NEXT: | | | LiteralConstant -> IntLiteralConstant = '16'
!CHECK-NEXT: | | Flags = {}
@@ -33,7 +33,7 @@ end program allocate_align_tree
!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | OmpBeginDirective
!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
+!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Constant -> Expr = '32_4'
!CHECK-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '32'
!CHECK-NEXT: | | | | OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8'
diff --git a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90
index 92ddbbdce05c5..6624273659200 100644
--- a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90
+++ b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90
@@ -20,7 +20,7 @@ end program allocate_tree
!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | OmpBeginDirective
!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f'
+!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'f'
!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8'
!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc'
!CHECK-NEXT: | | | | Flags = {}
@@ -34,7 +34,7 @@ end program allocate_tree
!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | OmpBeginDirective
!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'w'
+!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'w'
!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '3_8'
!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_const_mem_alloc'
!CHECK-NEXT: | | | | Flags = {}
@@ -42,7 +42,7 @@ end program allocate_tree
!CHECK-NEXT: | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | | | OmpBeginDirective
!CHECK-NEXT: | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
+!CHECK-NEXT: | | | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
!CHECK-NEXT: | | | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8'
!CHECK-NEXT: | | | | | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc'
!CHECK-NEXT: | | | | | | Flags = {}
@@ -50,7 +50,7 @@ end program allocate_tree
!CHECK-NEXT: | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | | | | | OmpBeginDirective
!CHECK-NEXT: | | | | | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'zarray'
+!CHECK-NEXT: | | | | | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'zarray'
!CHECK-NEXT: | | | | | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8'
!CHECK-NEXT: | | | | | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc'
!CHECK-NEXT: | | | | | | | | Flags = {}
diff --git a/flang/test/Parser/OpenMP/allocate-tree.f90 b/flang/test/Parser/OpenMP/allocate-tree.f90
index 17ffb76aeed96..d2d309a646f01 100644
--- a/flang/test/Parser/OpenMP/allocate-tree.f90
+++ b/flang/test/Parser/OpenMP/allocate-tree.f90
@@ -21,7 +21,7 @@ end program allocate_tree
!CHECK: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpAllocateDirective
!CHECK-NEXT: | OmpBeginDirective
!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'w'
+!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'w'
!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '3_8'
!CHECK-NEXT: | | | Designator -> DataRef -> Name = 'omp_const_mem_alloc'
!CHECK-NEXT: | | Flags = {}
@@ -30,7 +30,7 @@ end program allocate_tree
!CHECK: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | OmpBeginDirective
!CHECK-NEXT: | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
+!CHECK-NEXT: | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'xarray'
!CHECK-NEXT: | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8'
!CHECK-NEXT: | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc'
!CHECK-NEXT: | | Flags = {}
@@ -38,7 +38,7 @@ end program allocate_tree
!CHECK-NEXT: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpAllocateDirective
!CHECK-NEXT: | | | OmpBeginDirective
!CHECK-NEXT: | | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'zarray'
+!CHECK-NEXT: | | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'zarray'
!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Allocator -> Scalar -> Integer -> Expr = '1_8'
!CHECK-NEXT: | | | | | Designator -> DataRef -> Name = 'omp_default_mem_alloc'
!CHECK-NEXT: | | | | Flags = {}
diff --git a/flang/test/Parser/OpenMP/declare-variant.f90 b/flang/test/Parser/OpenMP/declare-variant.f90
index 07f65beaaf12a..cc967cf6642ee 100644
--- a/flang/test/Parser/OpenMP/declare-variant.f90
+++ b/flang/test/Parser/OpenMP/declare-variant.f90
@@ -38,7 +38,7 @@ subroutine sub (v1)
!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector
!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct
!PARSE-TREE: | | OmpTraitSelector
@@ -68,7 +68,7 @@ subroutine sub (v1)
!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector
!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct
!PARSE-TREE: | | OmpTraitSelector
@@ -96,7 +96,7 @@ subroutine sub (v1, v2)
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'vsub'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector
!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct
!PARSE-TREE: | | OmpTraitSelector
@@ -136,7 +136,7 @@ subroutine f2 (x, y)
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f1'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'f1'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector
!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct
!PARSE-TREE: | | OmpTraitSelector
diff --git a/flang/test/Parser/OpenMP/depobj-construct.f90 b/flang/test/Parser/OpenMP/depobj-construct.f90
index 2d4831fe62bbb..9a49976cfd4b0 100644
--- a/flang/test/Parser/OpenMP/depobj-construct.f90
+++ b/flang/test/Parser/OpenMP/depobj-construct.f90
@@ -13,7 +13,7 @@ subroutine f00
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> TaskDep
!PARSE-TREE: | | Modifier -> OmpTaskDependenceType -> OmpDependenceKind = In
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
@@ -30,7 +30,7 @@ subroutine f01
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> OmpDependenceKind = Out
subroutine f02
@@ -45,7 +45,7 @@ subroutine f02
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'x'
subroutine f03
@@ -60,7 +60,7 @@ subroutine f03
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Destroy ->
subroutine f04
diff --git a/flang/test/Parser/OpenMP/groupprivate.f90 b/flang/test/Parser/OpenMP/groupprivate.f90
index 120af619d3b9b..82e16ba08d90f 100644
--- a/flang/test/Parser/OpenMP/groupprivate.f90
+++ b/flang/test/Parser/OpenMP/groupprivate.f90
@@ -19,12 +19,12 @@ module m
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpGroupprivateDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = groupprivate
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
-!PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'y'
!PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> OmpDeviceType = Nohost
!PARSE-TREE: | Flags = {}
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpGroupprivateDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = groupprivate
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'z'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'z'
!PARSE-TREE: | OmpClauseList ->
!PARSE-TREE: | Flags = {}
diff --git a/flang/test/Parser/OpenMP/metadirective-dirspec.f90 b/flang/test/Parser/OpenMP/metadirective-dirspec.f90
index a24027161ef09..d63db6c93cf40 100644
--- a/flang/test/Parser/OpenMP/metadirective-dirspec.f90
+++ b/flang/test/Parser/OpenMP/metadirective-dirspec.f90
@@ -26,7 +26,7 @@ subroutine f00(x)
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = allocate
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f01(x)
@@ -52,7 +52,7 @@ subroutine f01(x)
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = critical
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f02
@@ -187,7 +187,7 @@ subroutine f04
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare simd
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f04'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'f04'
!PARSE-TREE: | | | OmpClauseList ->
!PARSE-TREE: ImplicitPart ->
@@ -212,7 +212,7 @@ subroutine f05
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare target
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f05'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'f05'
!PARSE-TREE: | | | OmpClauseList ->
!PARSE-TREE: ImplicitPart ->
@@ -239,8 +239,8 @@ subroutine f06(x, y)
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
-!PARSE-TREE: | | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | | | OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'y'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f07
@@ -266,5 +266,5 @@ subroutine f07
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = threadprivate
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 't'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 't'
!PARSE-TREE: | | | OmpClauseList ->
diff --git a/flang/test/Parser/OpenMP/metadirective-flush.f90 b/flang/test/Parser/OpenMP/metadirective-flush.f90
index e4e521ed07073..6b74bfdf50bdb 100644
--- a/flang/test/Parser/OpenMP/metadirective-flush.f90
+++ b/flang/test/Parser/OpenMP/metadirective-flush.f90
@@ -23,7 +23,7 @@ subroutine f00()
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst
!PARSE-TREE: | | | Flags = {DeprecatedSyntax}
@@ -49,6 +49,6 @@ subroutine f01()
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
-!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst
!PARSE-TREE: | | | Flags = {}
diff --git a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90
index dbe51d854da04..5a14d99795752 100644
--- a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90
+++ b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90
@@ -155,7 +155,7 @@ subroutine g05
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'g05'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'g05'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector
!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = User
!PARSE-TREE: | | OmpTraitSelector
diff --git a/flang/test/Parser/OpenMP/threadprivate.f90 b/flang/test/Parser/OpenMP/threadprivate.f90
index e03bf6f7f94b9..5295acf6fa0a7 100644
--- a/flang/test/Parser/OpenMP/threadprivate.f90
+++ b/flang/test/Parser/OpenMP/threadprivate.f90
@@ -19,7 +19,7 @@ module m
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpThreadprivateDirective -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = threadprivate
-!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Name = 'blk'
-!PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'b'
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpObject -> Name = 'blk'
+!PARSE-TREE: | OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'b'
!PARSE-TREE: | OmpClauseList ->
!PARSE-TREE: | Flags = {}
diff --git a/flang/test/Semantics/OpenMP/affinity-invalid.f90 b/flang/test/Semantics/OpenMP/affinity-invalid.f90
index 32e726bada937..34bf9bb3c0798 100644
--- a/flang/test/Semantics/OpenMP/affinity-invalid.f90
+++ b/flang/test/Semantics/OpenMP/affinity-invalid.f90
@@ -81,14 +81,6 @@ subroutine affinity_iterator_section_bad_stride(n)
!$omp end task
end subroutine
-subroutine affinity_substring_like_single_index()
- character(len=7) :: s
- !PORTABILITY: The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2.
- !ERROR: Substrings must be in the form parent-string(lb:ub)
- !$omp task affinity(s(2))
- !$omp end task
-end subroutine
-
subroutine affinity_substring_like_step()
character(len=7) :: s
!PORTABILITY: The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2.
diff --git a/flang/test/Semantics/OpenMP/depend-substring.f90 b/flang/test/Semantics/OpenMP/depend-substring.f90
index 23d6bb4c0b7b3..558172fa218d2 100644
--- a/flang/test/Semantics/OpenMP/depend-substring.f90
+++ b/flang/test/Semantics/OpenMP/depend-substring.f90
@@ -25,15 +25,6 @@ subroutine substring_2(c)
!$omp end task
end
-! Error
-subroutine substring_3(c)
- character(:), pointer :: c
- !PORTABILITY: The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2.
- !ERROR: Substrings must be in the form parent-string(lb:ub)
- !$omp task depend(out:c(2))
- !$omp end task
-end
-
! This is okay: interpreted as indexing into the array not as a substring
subroutine substring_3b(c)
character(:), pointer :: c(:)
diff --git a/flang/test/Semantics/OpenMP/reserved-locator.f90 b/flang/test/Semantics/OpenMP/reserved-locator.f90
new file mode 100644
index 0000000000000..3fc45ffa0f54c
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/reserved-locator.f90
@@ -0,0 +1,6 @@
+!RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -fopenmp-version=60
+
+subroutine f
+!ERROR: 'OMP_SOME_MEMORY' is not a valid locator
+ !$omp target update from(omp_some_memory)
+end
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h
index 8ba5171caab25..1faec3812412c 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h
@@ -103,6 +103,8 @@ LLVM_ABI ArrayRef<unsigned> getOpenMPVersions();
/// of a variable in given OpenMP version?
LLVM_ABI bool isPrivatizingConstruct(Directive D, unsigned Version);
+LLVM_ABI ArrayRef<StringRef> getReservedLocatorNames();
+
/// Create a nicer version of a function name for humans to look at.
LLVM_ABI std::string prettifyFunctionName(StringRef FunctionName);
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index 871b6211fc2a5..86e144624211c 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -228,6 +228,12 @@ bool isPrivatizingConstruct(Directive D, unsigned Version) {
return llvm::is_contained(Privatizing, D);
}
+ArrayRef<StringRef> getReservedLocatorNames() {
+ // All names must be lowercase.
+ static StringRef names[]{"omp_all_memory"};
+ return names;
+}
+
std::string prettifyFunctionName(StringRef FunctionName) {
// Internalized functions have the right name, but simply a suffix.
if (FunctionName.ends_with(".internalized"))
>From a8bc4bb82b9754d133e2e61b43367156b4473228 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 15 Jun 2026 09:01:19 -0500
Subject: [PATCH 4/7] format
---
flang/lib/Lower/OpenMP/Clauses.cpp | 2 +-
flang/lib/Parser/openmp-parsers.cpp | 2 +-
flang/lib/Semantics/openmp-utils.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 9ab9e9349254b..34dc6ed56b435 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -173,7 +173,7 @@ Object makeObject(const parser::EntityDecl &decl,
ObjectList makeObjects(const parser::OmpArgumentList &objects,
semantics::SemanticsContext &semaCtx) {
return makeList(objects.v, [&](const parser::OmpArgument &arg) {
- return common::visit(
+ return common::visit( //
common::visitors{
[&](const parser::OmpObject &object) -> Object {
return makeObject(object, semaCtx);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index a44228f2484f3..8a18bcc9e4485 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -290,8 +290,8 @@ static bool IsReservedName(const Name &name) {
TYPE_PARSER( //
construct<OmpReservedIdentifier>(predicated(name, IsReservedName)))
+// Parse x(...)(...) as a substring instead of a function reference.
TYPE_PARSER( //
- // Parse x(...)(...) as a substring instead of a function reference.
construct<OmpLocator>(functionReference / !lookAhead("("_tok)) ||
construct<OmpLocator>(Parser<OmpReservedIdentifier>{}))
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index d5035cbd2ddcd..b0e543a561e42 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -478,7 +478,7 @@ std::optional<bool> IsContiguous(
}
return std::optional<bool>{};
},
- [&](const parser::OmpLocator &) {
+ [&](const parser::OmpLocator &) { //
return std::optional<bool>{};
},
[&](const parser::OmpObject::Invalid &) {
>From 1df09249063820e86e245b4d1a005a57587675dd Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 15 Jun 2026 11:07:30 -0500
Subject: [PATCH 5/7] Restart build
>From d48ea50b6473c1e9a3b480d6665e37f5e425c2c0 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 15 Jun 2026 14:39:11 -0500
Subject: [PATCH 6/7] Rename function
---
flang/include/flang/Semantics/expression.h | 2 +-
flang/lib/Semantics/expression.cpp | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h
index 49063d570ce13..598cb31e851f8 100644
--- a/flang/include/flang/Semantics/expression.h
+++ b/flang/include/flang/Semantics/expression.h
@@ -470,7 +470,7 @@ evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
void NoteUsedSymbols(
SemanticsContext &, const SomeExpr &, bool isDefinition = false);
-bool IsMisparsedArrayElement(
+bool CheckMisparsedArrayElement(
SemanticsContext &, const parser::FunctionReference &);
// Semantic analysis of all expressions in a parse tree, which becomes
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index e776f4e6adc91..709292e62f97c 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -4354,7 +4354,7 @@ static void FixMisparsedFunctionReference(
if (auto *func{
std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
parser::FunctionReference &funcRef{func->value()};
- if (semantics::IsMisparsedArrayElement(context, funcRef)) {
+ if (semantics::CheckMisparsedArrayElement(context, funcRef)) {
if constexpr (common::HasMember<common::Indirection<parser::Designator>,
uType>) {
u = common::Indirection{funcRef.ConvertToArrayElementRef()};
@@ -5596,7 +5596,7 @@ void NoteUsedSymbols(
evaluate::CollectUsedSymbolValues(context, expr, isDefinition));
}
-bool IsMisparsedArrayElement(
+bool CheckMisparsedArrayElement(
SemanticsContext &context, const parser::FunctionReference &funcRef) {
// Ensure that there are no argument keywords
for (const auto &arg :
>From 87dae33de6911f2701c640352d2ea31290deeaaa Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 15 Jun 2026 14:41:11 -0500
Subject: [PATCH 7/7] Update function name
---
flang/lib/Semantics/rewrite-parse-tree.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/rewrite-parse-tree.cpp b/flang/lib/Semantics/rewrite-parse-tree.cpp
index f3513d8a51128..bdccde8af3b94 100644
--- a/flang/lib/Semantics/rewrite-parse-tree.cpp
+++ b/flang/lib/Semantics/rewrite-parse-tree.cpp
@@ -381,7 +381,7 @@ bool RewriteMutator::Pre(parser::OmpObject &object) {
// This has to happen early, before the ExprChecker runs, or otherwise it
// will emit undesirable diagnostics.
if (auto *ref{parser::Unwrap<parser::FunctionReference>(object)}) {
- if (IsMisparsedArrayElement(context_, *ref)) {
+ if (CheckMisparsedArrayElement(context_, *ref)) {
object.u = ref->ConvertToArrayElementRef();
}
}
More information about the flang-commits
mailing list