[llvm-branch-commits] [flang] [llvm] [flang][OpenMP] Parsing and semantics of locators as part of OmpObject (PR #203910)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jun 15 06:56:29 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-openmp

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

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.

---

Patch is 54.63 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/203910.diff


37 Files Affected:

- (modified) flang/include/flang/Parser/dump-parse-tree.h (+1-1) 
- (modified) flang/include/flang/Parser/parse-tree.h (+12-11) 
- (modified) flang/include/flang/Semantics/expression.h (+2-2) 
- (modified) flang/include/flang/Semantics/symbol.h (+2-2) 
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.cpp (+22) 
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+40-9) 
- (modified) flang/lib/Parser/openmp-parsers.cpp (+23-14) 
- (modified) flang/lib/Parser/openmp-utils.cpp (+8-4) 
- (modified) flang/lib/Parser/unparse.cpp (+1-1) 
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+1-1) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+23-5) 
- (modified) flang/lib/Semantics/check-omp-structure.h (+1) 
- (modified) flang/lib/Semantics/check-omp-variant.cpp (+1-1) 
- (modified) flang/lib/Semantics/openmp-utils.cpp (+41-7) 
- (modified) flang/lib/Semantics/resolve-directives.cpp (+3) 
- (modified) flang/lib/Semantics/resolve-names.cpp (+14-2) 
- (modified) flang/lib/Semantics/rewrite-parse-tree.cpp (+17) 
- (added) flang/test/Lower/OpenMP/Todo/locator-call-affinity.f90 (+13) 
- (added) flang/test/Lower/OpenMP/Todo/locator-call-from.f90 (+12) 
- (added) flang/test/Lower/OpenMP/Todo/locator-call-map.f90 (+13) 
- (added) flang/test/Lower/OpenMP/Todo/locator-call-to.f90 (+12) 
- (added) flang/test/Lower/OpenMP/Todo/locator-reserved.f90 (+11) 
- (modified) flang/test/Parser/OpenMP/allocate-align-tree.f90 (+2-2) 
- (modified) flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 (+4-4) 
- (modified) flang/test/Parser/OpenMP/allocate-tree.f90 (+3-3) 
- (modified) flang/test/Parser/OpenMP/declare-variant.f90 (+4-4) 
- (modified) flang/test/Parser/OpenMP/depobj-construct.f90 (+4-4) 
- (modified) flang/test/Parser/OpenMP/groupprivate.f90 (+3-3) 
- (modified) flang/test/Parser/OpenMP/metadirective-dirspec.f90 (+7-7) 
- (modified) flang/test/Parser/OpenMP/metadirective-flush.f90 (+2-2) 
- (modified) flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 (+1-1) 
- (modified) flang/test/Parser/OpenMP/threadprivate.f90 (+2-2) 
- (modified) flang/test/Semantics/OpenMP/affinity-invalid.f90 (-8) 
- (modified) flang/test/Semantics/OpenMP/depend-substring.f90 (-9) 
- (added) flang/test/Semantics/OpenMP/reserved-locator.f90 (+6) 
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.h (+2) 
- (modified) llvm/lib/Frontend/OpenMP/OMP.cpp (+6) 


``````````diff
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...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/203910


More information about the llvm-branch-commits mailing list