[flang-commits] [flang] e68e8d3 - [flang][OpenMP] Parsing and semantics of locators as part of OmpObject (#203910)
via flang-commits
flang-commits at lists.llvm.org
Wed Jun 24 06:51:42 PDT 2026
Author: Krzysztof Parzyszek
Date: 2026-06-24T08:51:36-05:00
New Revision: e68e8d35c91b4fd3ba0ae3ef12d79b41d92580b2
URL: https://github.com/llvm/llvm-project/commit/e68e8d35c91b4fd3ba0ae3ef12d79b41d92580b2
DIFF: https://github.com/llvm/llvm-project/commit/e68e8d35c91b4fd3ba0ae3ef12d79b41d92580b2.diff
LOG: [flang][OpenMP] Parsing and semantics of locators as part of OmpObject (#203910)
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.
Added:
flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90
flang/test/Lower/OpenMP/Todo/locator-call-from.f90
flang/test/Lower/OpenMP/Todo/locator-call-map.f90
flang/test/Lower/OpenMP/Todo/locator-call-to.f90
flang/test/Lower/OpenMP/Todo/locator-reserved.f90
flang/test/Semantics/OpenMP/reserved-locator.f90
Modified:
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/include/flang/Semantics/expression.h
flang/include/flang/Semantics/symbol.h
flang/lib/Lower/OpenMP/ClauseProcessor.cpp
flang/lib/Lower/OpenMP/Clauses.cpp
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Parser/openmp-utils.cpp
flang/lib/Parser/unparse.cpp
flang/lib/Semantics/check-omp-loop.cpp
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/lib/Semantics/check-omp-variant.cpp
flang/lib/Semantics/openmp-utils.cpp
flang/lib/Semantics/resolve-directives.cpp
flang/lib/Semantics/resolve-names.cpp
flang/lib/Semantics/rewrite-parse-tree.cpp
flang/test/Parser/OpenMP/allocate-align-tree.f90
flang/test/Parser/OpenMP/allocate-tree-spec-part.f90
flang/test/Parser/OpenMP/allocate-tree.f90
flang/test/Parser/OpenMP/declare-variant.f90
flang/test/Parser/OpenMP/depobj-construct.f90
flang/test/Parser/OpenMP/groupprivate.f90
flang/test/Parser/OpenMP/metadirective-dirspec.f90
flang/test/Parser/OpenMP/metadirective-flush.f90
flang/test/Parser/OpenMP/openmp6-directive-spellings.f90
flang/test/Parser/OpenMP/threadprivate.f90
flang/test/Semantics/OpenMP/affinity-invalid.f90
flang/test/Semantics/OpenMP/depend-substring.f90
llvm/include/llvm/Frontend/OpenMP/OMP.h
llvm/lib/Frontend/OpenMP/OMP.cpp
Removed:
################################################################################
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 598cb31e851f8..75468d683af48 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 23c26ba733e86..e0511b5b4803d 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -925,8 +925,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 4f19dfb98024d..f1ccb64e3dfb3 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..34dc6ed56b435 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,
@@ -139,13 +173,10 @@ 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::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..8a18bcc9e4485 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)))
+
+// Parse x(...)(...) as a substring instead of a function reference.
+TYPE_PARSER( //
+ 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 3e1f2e6cdf5d0..c77c1c53f4813 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -665,7 +665,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 816b8fd2f149d..81600fa1ddbb9 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};
@@ -1671,7 +1687,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);
}
@@ -1685,10 +1702,10 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
void OmpStructureChecker::Enter(const parser::OmpGroupprivateDirective &x) {
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);
@@ -3557,7 +3574,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 8d9b25fb2a11d..4499e2a213384 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -131,6 +131,7 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void Enter(const parser::OpenMPCriticalConstruct &);
void Enter(const parser::OpenMPAtomicConstruct &);
+ void Enter(const parser::OmpLocator &x);
void Enter(const parser::OmpClauseList &);
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 c681cd601b856..8b782030c37e3 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -688,7 +688,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 1aa27a5fe6074..0556920877f45 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 2e1a1cbe01aef..f3865cfb877dc 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3176,6 +3176,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 c6800e15be9dc..a6f3fe12eb9b7 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..bdccde8af3b94 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 (CheckMisparsedArrayElement(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"))
More information about the flang-commits
mailing list