[flang-commits] [flang] [flang][OpenMP] Utilities to get uppercase directive/clause names (PR #184853)

via flang-commits flang-commits at lists.llvm.org
Thu Mar 5 10:49:27 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

It is a convention to use uppercase names of directives and clauses in diagnostic messages, but getting such names is somewhat cumbersome:
```
parser::ToUpperCaseLetters(llvm::omp::getOpenMPDirectiveName(dirId));
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(clauseId));
```

Implement `GetUpperName` (overloaded for clauses and directives) to shorten it to
```
GetUpperName(dirId, version);
GetUpperName(clauseId, version);
```

This patch replaces existing instances of this pattern, adding the use of OpenMP version where it was previously missing.

---

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


6 Files Affected:

- (modified) flang/include/flang/Parser/openmp-utils.h (+3) 
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+5-3) 
- (modified) flang/lib/Parser/openmp-utils.cpp (+12) 
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+2-3) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+76-76) 
- (modified) flang/lib/Semantics/resolve-directives.cpp (+8-14) 


``````````diff
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 6cfaf8bb21712..b8fb6078d59a5 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -113,6 +113,9 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
   return detail::DirectiveNameScope::GetOmpDirectiveName(x);
 }
 
+std::string GetUpperName(llvm::omp::Clause id, unsigned version);
+std::string GetUpperName(llvm::omp::Directive id, unsigned version);
+
 const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x);
 const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x);
 
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 89af32121487b..3a9ed35e41cb9 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4326,10 +4326,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
         !std::holds_alternative<clause::TaskReduction>(clause.u) &&
         !std::holds_alternative<clause::Detach>(clause.u) &&
         !std::holds_alternative<clause::Device>(clause.u)) {
-      std::string name =
-          parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(clause.id));
-      if (!semaCtx.langOptions().OpenMPSimd)
+      const common::LangOptions &options = semaCtx.langOptions();
+      if (!options.OpenMPSimd) {
+        std::string name =
+            parser::omp::GetUpperName(clause.id, options.OpenMPVersion);
         TODO(clauseLocation, name + " clause is not implemented yet");
+      }
     }
   }
 
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index 9aa7014ccb057..c81f48f6323dd 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -16,6 +16,8 @@
 #include "flang/Common/template.h"
 #include "flang/Common/visit.h"
 #include "flang/Parser/tools.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 #include <tuple>
 #include <type_traits>
@@ -23,6 +25,16 @@
 
 namespace Fortran::parser::omp {
 
+std::string GetUpperName(llvm::omp::Clause id, unsigned version) {
+  llvm::StringRef name{llvm::omp::getOpenMPClauseName(id, version)};
+  return parser::ToUpperCaseLetters(name);
+}
+
+std::string GetUpperName(llvm::omp::Directive id, unsigned version) {
+  llvm::StringRef name{llvm::omp::getOpenMPDirectiveName(id, version)};
+  return parser::ToUpperCaseLetters(name);
+}
+
 const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x) {
   if (auto *y = std::get_if<SpecificationConstruct>(&x.u)) {
     if (auto *z{std::get_if<common::Indirection<OpenMPDeclarativeConstruct>>(
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index de7a155dd96ef..0cad16dc3deb1 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -784,7 +784,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
         if (dir != llvm::omp::Directive::OMPD_declare_simd) {
           context_.Say(modSource,
               "A modifier may not be specified in a LINEAR clause on the %s directive"_err_en_US,
-              parser::ToUpperCaseLetters(getDirectiveName(dir)));
+              parser::omp::GetUpperName(dir, version));
           valid = false;
         }
       } else {
@@ -793,8 +793,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
           if (dir != llvm::omp::Directive::OMPD_declare_simd) {
             context_.Say(modSource,
                 "A REF or UVAL '%s' may not be specified in a LINEAR clause on the %s directive"_err_en_US,
-                desc.name.str(),
-                parser::ToUpperCaseLetters(getDirectiveName(dir)));
+                desc.name.str(), parser::omp::GetUpperName(dir, version));
             valid = false;
           }
         }
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9bdd3d1dbc231..8275b0d4913dd 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -367,12 +367,10 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
     // Only report it if there is a later version that allows it.
     // If it's not allowed at all, it will be reported by CheckAllowed.
     if (allowedInVersion != 0) {
-      auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())};
-      auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())};
-
       context_.Say(dirCtx.clauseSource,
           "%s clause is not allowed on directive %s in %s, %s"_err_en_US,
-          clauseName, dirName, ThisVersion(version),
+          parser::omp::GetUpperName(clause, version),
+          parser::omp::GetUpperName(dir, version), ThisVersion(version),
           TryVersion(allowedInVersion));
     }
   }
@@ -925,10 +923,10 @@ void OmpStructureChecker::CheckTargetNest(const parser::OpenMPConstruct &c) {
       },
       c.u);
   if (!eligibleTarget) {
+    unsigned version{context_.langOptions().OpenMPVersion};
     context_.Warn(common::UsageWarning::OpenMPUsage, source,
         "If %s directive is nested inside TARGET region, the behaviour is unspecified"_port_en_US,
-        parser::ToUpperCaseLetters(
-            getDirectiveName(ineligibleTargetDir).str()));
+        parser::omp::GetUpperName(ineligibleTargetDir, version));
   }
 }
 
@@ -936,6 +934,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
   const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
   const std::optional<parser::OmpEndDirective> &endSpec{x.EndDir()};
   const parser::Block &block{std::get<parser::Block>(x.t)};
+  unsigned version{context_.langOptions().OpenMPVersion};
 
   PushContextAndClauseSets(beginSpec.DirName().source, beginSpec.DirId());
 
@@ -947,7 +946,7 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
     llvm::omp::Directive dirId{beginSpec.DirId()};
     auto &msg{context_.Say(beginSpec.source,
         "Expected OpenMP END %s directive"_err_en_US,
-        parser::ToUpperCaseLetters(getDirectiveName(dirId)))};
+        parser::omp::GetUpperName(dirId, version))};
     // ORDERED has two variants, so be explicit about which variant we think
     // this is.
     if (dirId == llvm::omp::Directive::OMPD_ordered) {
@@ -1707,7 +1706,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPRequiresConstruct &x) {
       if (!visitedAtomicSource_.empty()) {
         parser::MessageFormattedText txt(
             "REQUIRES directive with '%s' clause found lexically after atomic operation without a memory order clause"_err_en_US,
-            parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(id)));
+            parser::omp::GetUpperName(id, version));
         parser::Message message(clause.source, txt);
         message.Attach(visitedAtomicSource_, "Previous atomic construct"_en_US);
         context_.Say(std::move(message));
@@ -1732,9 +1731,8 @@ void OmpStructureChecker::Enter(const parser::OpenMPRequiresConstruct &x) {
       if (version < 60 && hasArgument) {
         context_.Say(clause.source,
             "An argument to %s is an %s feature, %s"_warn_en_US,
-            parser::ToUpperCaseLetters(
-                llvm::omp::getOpenMPClauseName(clause.Id())),
-            ThisVersion(60), TryVersion(60));
+            parser::omp::GetUpperName(clause.Id(), version), ThisVersion(60),
+            TryVersion(60));
       }
     }
   }
@@ -2977,6 +2975,7 @@ void OmpStructureChecker::Enter(
     const parser::OmpClause::CancellationConstructType &x) {
   llvm::omp::Directive dir{GetContext().directive};
   auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)};
+  unsigned version{context_.langOptions().OpenMPVersion};
 
   if (dir != llvm::omp::Directive::OMPD_cancel &&
       dir != llvm::omp::Directive::OMPD_cancellation_point) {
@@ -2984,8 +2983,8 @@ void OmpStructureChecker::Enter(
     // it will print "CANCELLATION_CONSTRUCT_TYPE" as the clause name instead
     // of the contained construct name.
     context_.Say(dirName.source, "%s cannot follow %s"_err_en_US,
-        parser::ToUpperCaseLetters(getDirectiveName(dirName.v)),
-        parser::ToUpperCaseLetters(getDirectiveName(dir)));
+        parser::omp::GetUpperName(dirName.v, version),
+        parser::omp::GetUpperName(dir, version));
   } else {
     switch (dirName.v) {
     case llvm::omp::Directive::OMPD_do:
@@ -2996,7 +2995,7 @@ void OmpStructureChecker::Enter(
     default:
       context_.Say(dirName.source,
           "%s is not a cancellable construct"_err_en_US,
-          parser::ToUpperCaseLetters(getDirectiveName(dirName.v)));
+          parser::omp::GetUpperName(dirName.v, version));
       break;
     }
   }
@@ -3029,8 +3028,9 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
   }
   // Given clauses from CANCEL or CANCELLATION_POINT, identify the construct
   // to which the cancellation applies.
+  unsigned version{context_.langOptions().OpenMPVersion};
   std::optional<llvm::omp::Directive> cancelee;
-  llvm::StringRef cancelName{getDirectiveName(cancelDir)};
+  std::string cancelName{parser::omp::GetUpperName(cancelDir, version)};
 
   for (const parser::OmpClause &clause : maybeClauses->v) {
     using CancellationConstructType =
@@ -3039,7 +3039,7 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
       if (cancelee) {
         context_.Say(cancelSource,
             "Multiple cancel-directive-name clauses are not allowed on the %s construct"_err_en_US,
-            parser::ToUpperCaseLetters(cancelName.str()));
+            cancelName);
         return std::nullopt;
       }
       cancelee = std::get<parser::OmpDirectiveName>(cctype->v.t).v;
@@ -3049,7 +3049,7 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
   if (!cancelee) {
     context_.Say(cancelSource,
         "Missing cancel-directive-name clause on the %s construct"_err_en_US,
-        parser::ToUpperCaseLetters(cancelName.str()));
+        cancelName);
     return std::nullopt;
   }
 
@@ -3058,7 +3058,8 @@ std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
 
 void OmpStructureChecker::CheckCancellationNest(
     const parser::CharBlock &source, llvm::omp::Directive type) {
-  llvm::StringRef typeName{getDirectiveName(type)};
+  unsigned version{context_.langOptions().OpenMPVersion};
+  std::string typeName{parser::omp::GetUpperName(type, version)};
 
   if (CurrentDirectiveIsNested()) {
     // If construct-type-clause is taskgroup, the cancellation construct must be
@@ -3099,8 +3100,7 @@ void OmpStructureChecker::CheckCancellationNest(
       if (!eligibleCancellation) {
         context_.Say(source,
             "With %s clause, %s construct must be closely nested inside TASK or TASKLOOP construct and %s region must be closely nested inside TASKGROUP region"_err_en_US,
-            parser::ToUpperCaseLetters(typeName.str()),
-            ContextDirectiveAsFortran(), ContextDirectiveAsFortran());
+            typeName, ContextDirectiveAsFortran(), ContextDirectiveAsFortran());
       }
       return;
     case llvm::omp::Directive::OMPD_sections:
@@ -3128,10 +3128,8 @@ void OmpStructureChecker::CheckCancellationNest(
     if (!eligibleCancellation) {
       context_.Say(source,
           "With %s clause, %s construct cannot be closely nested inside %s construct"_err_en_US,
-          parser::ToUpperCaseLetters(typeName.str()),
-          ContextDirectiveAsFortran(),
-          parser::ToUpperCaseLetters(
-              getDirectiveName(GetContextParent().directive).str()));
+          typeName, ContextDirectiveAsFortran(),
+          parser::omp::GetUpperName(GetContextParent().directive, version));
     }
   } else {
     // The cancellation directive cannot be orphaned.
@@ -3139,26 +3137,22 @@ void OmpStructureChecker::CheckCancellationNest(
     case llvm::omp::Directive::OMPD_taskgroup:
       context_.Say(source,
           "%s %s directive is not closely nested inside TASK or TASKLOOP"_err_en_US,
-          ContextDirectiveAsFortran(),
-          parser::ToUpperCaseLetters(typeName.str()));
+          ContextDirectiveAsFortran(), typeName);
       break;
     case llvm::omp::Directive::OMPD_sections:
       context_.Say(source,
           "%s %s directive is not closely nested inside SECTION or SECTIONS"_err_en_US,
-          ContextDirectiveAsFortran(),
-          parser::ToUpperCaseLetters(typeName.str()));
+          ContextDirectiveAsFortran(), typeName);
       break;
     case llvm::omp::Directive::OMPD_do:
       context_.Say(source,
           "%s %s directive is not closely nested inside the construct that matches the DO clause type"_err_en_US,
-          ContextDirectiveAsFortran(),
-          parser::ToUpperCaseLetters(typeName.str()));
+          ContextDirectiveAsFortran(), typeName);
       break;
     case llvm::omp::Directive::OMPD_parallel:
       context_.Say(source,
           "%s %s directive is not closely nested inside the construct that matches the PARALLEL clause type"_err_en_US,
-          ContextDirectiveAsFortran(),
-          parser::ToUpperCaseLetters(typeName.str()));
+          ContextDirectiveAsFortran(), typeName);
       break;
     default:
       // This is diagnosed later.
@@ -3209,6 +3203,8 @@ void OmpStructureChecker::Leave(const parser::OmpEndDirective &x) {
 // 3. Checks on clauses which are not in 'struct OmpClause' from parse-tree.h.
 
 void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+
   // 2.7.1 Loop Construct Restriction
   if (llvm::omp::allDoSet.test(GetContext().directive)) {
     if (auto *clause{FindClause(llvm::omp::Clause::OMPC_schedule)}) {
@@ -3299,7 +3295,6 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
 
   if (GetContext().directive == llvm::omp::Directive::OMPD_task) {
     if (auto *detachClause{FindClause(llvm::omp::Clause::OMPC_detach)}) {
-      unsigned version{context_.langOptions().OpenMPVersion};
       if (version == 50 || version == 51) {
         // OpenMP 5.0: 2.10.1 Task construct restrictions
         CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_detach,
@@ -3361,7 +3356,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
     if (sym.test(Symbol::Flag::OmpThreadprivate))
       context_.Say(name.source,
           "A THREADPRIVATE variable cannot be in %s clause"_err_en_US,
-          parser::ToUpperCaseLetters(getClauseName(clauseTy).str()));
+          parser::omp::GetUpperName(clauseTy, version));
   };
 
   // [5.1] 2.21.2 Threadprivate Directive Restriction
@@ -3578,6 +3573,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::TaskReduction &x) {
 bool OmpStructureChecker::CheckReductionOperator(
     const parser::OmpReductionIdentifier &ident, parser::CharBlock source,
     llvm::omp::Clause clauseId) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+
   auto visitOperator{[&](const parser::DefinedOperator &dOpr) {
     if (const auto *intrinsicOp{
             std::get_if<parser::DefinedOperator::IntrinsicOperator>(&dOpr.u)}) {
@@ -3610,7 +3607,7 @@ bool OmpStructureChecker::CheckReductionOperator(
       }
     }
     context_.Say(source, "Invalid reduction operator in %s clause."_err_en_US,
-        parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+        parser::omp::GetUpperName(clauseId, version));
     return false;
   }};
 
@@ -3628,7 +3625,7 @@ bool OmpStructureChecker::CheckReductionOperator(
     if (!valid) {
       context_.Say(source,
           "Invalid reduction identifier in %s clause."_err_en_US,
-          parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+          parser::omp::GetUpperName(clauseId, version));
     }
     return valid;
   }};
@@ -3665,7 +3662,7 @@ void OmpStructureChecker::CheckReductionObjects(
       auto source{GetObjectSource(object)};
       context_.Say(source ? *source : GetContext().clauseSource,
           "Common block names are not allowed in %s clause"_err_en_US,
-          parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+          parser::omp::GetUpperName(clauseId, version));
     }
   }
 
@@ -3684,7 +3681,7 @@ void OmpStructureChecker::CheckReductionObjects(
           auto source{GetObjectSource(object)};
           context_.Say(source ? *source : GetContext().clauseSource,
               "The base expression of an array element or section in %s clause must be an identifier"_err_en_US,
-              parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+              parser::omp::GetUpperName(clauseId, version));
         }
       }
     }
@@ -3695,7 +3692,7 @@ void OmpStructureChecker::CheckReductionObjects(
           auto source{GetObjectSource(object)};
           context_.Say(source ? *source : GetContext().clauseSource,
               "Type parameter inquiry is not permitted in %s clause"_err_en_US,
-              parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+              parser::omp::GetUpperName(clauseId, version));
         }
       }
     }
@@ -3862,6 +3859,8 @@ void OmpStructureChecker::CheckReductionObjectTypes(
 
 void OmpStructureChecker::CheckReductionModifier(
     const parser::OmpReductionModifier &modifier) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+
   using ReductionModifier = parser::OmpReductionModifier;
   if (modifier.v == ReductionModifier::Value::Default) {
     // The default one is always ok.
@@ -3878,7 +3877,7 @@ void OmpStructureChecker::CheckReductionModifier(
     // The reduction-modifier must be default.
     context_.Say(GetContext().clauseSource,
         "REDUCTION modifier on %s directive must be DEFAULT"_err_en_US,
-        parser::ToUpperCaseLetters(GetContext().directiveSource.ToString()));
+        parser::omp::GetUpperName(dirCtx.directive, version));
     return;
   }
   if (modifier.v == ReductionModifier::Value::Task) {
@@ -3931,6 +3930,7 @@ void OmpStructureChecker::CheckReductionArraySection(
 
 void OmpStructureChecker::CheckSharedBindingInOuterContext(
     const parser::OmpObjectList &redObjectList) {
+  unsigned version{context_.langOptions().OpenMPVersion};
   //  TODO: Verify the assumption here that the immediately enclosing region is
   //  the parallel region to which the worksharing construct having reduction
   //  binds to.
@@ -3953,12 +3953,10 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
                             " be shared in the parallel regions to which any"
                             " of the worksharing regions arising from the "
                             "worksharing construct bind."_err_en_US,
-                            parser::ToUpperCaseLetters(
-                                getClauseName(llvm::omp::Clause::OMPC_reduction)
-                                    .str()),
+                            parser::omp::GetUpperName(
+                                llvm::omp::Clause::OMPC_reduction, version),
                             symbol->name(),
-                            parser::ToUpperCaseLetters(
-                                getClauseName(type).str()));
+                            parser::omp::GetUpperName(type, version));
                       }
                     }
                   }
@@ -4095,13 +4093,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
 
 void OmpStructureChecker::CheckIsLoopIvPartOfClause(
     llvmOmpClause clause, const parser::OmpObjectList &ompObjectList) {
+  unsigned version{context_.langOptions().OpenMPVersion};
   for (const auto &ompObject : ompObjectList.v) {
     if (const parser::Name *name{parser::Unwrap<parser::Name>(ompObject)}) {
       if (name->symbol == GetContext().loopIV) {
         context_.Say(name->source,
             "DO iteration variable %s is not allowed in %s clause."_err_en_US,
-            name->ToString(),
-            parser::ToUpperCaseLetters(getClauseName(clause).str()));
+            name->ToString(), parser::omp::GetUpperName(clause, version));
       }
     }
   }
@@ -4216,10 +4214,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
     if (auto *dnm{OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(
             modifiers)}) {
       ...
[truncated]

``````````

</details>


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


More information about the flang-commits mailing list