[llvm-branch-commits] [flang] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE (PR #118128)

Krzysztof Parzyszek via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Nov 29 11:41:06 PST 2024


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/118128

The usual changes, added more references to OpenMP specs.

>From cfcf8d1e7ffdcec92dc0dfffccb3c620a2df804f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 27 Nov 2024 08:34:33 -0600
Subject: [PATCH] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE

The usual changes, added more references to OpenMP specs.
---
 flang/examples/FeatureList/FeatureList.cpp    |   3 +-
 .../FlangOmpReport/FlangOmpReportVisitor.cpp  |   5 +-
 .../FlangOmpReport/FlangOmpReportVisitor.h    |   2 +-
 flang/include/flang/Parser/dump-parse-tree.h  |   7 +-
 flang/include/flang/Parser/parse-tree.h       |  50 ++++++--
 .../flang/Semantics/openmp-modifiers.h        |   2 +
 flang/lib/Lower/OpenMP/Clauses.cpp            |  36 ++----
 flang/lib/Parser/CMakeLists.txt               |   1 +
 flang/lib/Parser/openmp-parsers.cpp           |  73 ++++++++---
 flang/lib/Parser/unparse.cpp                  |  15 ++-
 flang/lib/Semantics/check-omp-structure.cpp   | 121 +++++++++++-------
 flang/lib/Semantics/openmp-modifiers.cpp      |  34 +++++
 .../test/Parser/OpenMP/if-clause-unparse.f90  |  20 +--
 flang/test/Parser/OpenMP/if-clause.f90        |  22 ++--
 .../test/Parser/OpenMP/lastprivate-clause.f90 |   4 +-
 .../Semantics/OpenMP/clause-validity01.f90    |   4 +-
 flang/test/Semantics/OpenMP/if-clause.f90     |  64 ++++-----
 17 files changed, 297 insertions(+), 166 deletions(-)

diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index c5cb8c8fdf40bb..41a6255207976d 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -492,7 +492,8 @@ struct NodeVisitor {
   READ_FEATURE(OmpPrescriptiveness)
   READ_FEATURE(OmpPrescriptiveness::Value)
   READ_FEATURE(OmpIfClause)
-  READ_FEATURE(OmpIfClause::DirectiveNameModifier)
+  READ_FEATURE(OmpIfClause::Modifier)
+  READ_FEATURE(OmpDirectiveNameModifier)
   READ_FEATURE(OmpLinearClause)
   READ_FEATURE(OmpLinearClause::WithModifier)
   READ_FEATURE(OmpLinearClause::WithoutModifier)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index afabd564ad5bdc..2dc480f0c901b1 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -8,6 +8,7 @@
 
 #include "FlangOmpReportVisitor.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 namespace Fortran {
 namespace parser {
@@ -238,9 +239,9 @@ void OpenMPCounterVisitor::Post(const OmpScheduleClause::Kind &c) {
   clauseDetails +=
       "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
 }
-void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
+void OpenMPCounterVisitor::Post(const OmpDirectiveNameModifier &c) {
   clauseDetails +=
-      "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
+      "name_modifier=" + llvm::omp::getOpenMPDirectiveName(c.v).str() + ";";
 }
 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
   clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index ed202e8ed2a4c7..59bdac8594cb7c 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -77,7 +77,7 @@ struct OpenMPCounterVisitor {
   void Post(const OmpTaskDependenceType::Value &c);
   void Post(const OmpMapType::Value &c);
   void Post(const OmpScheduleClause::Kind &c);
-  void Post(const OmpIfClause::DirectiveNameModifier &c);
+  void Post(const OmpDirectiveNameModifier &c);
   void Post(const OmpCancelType::Type &c);
   void Post(const OmpClause &c);
   void PostClauseCommon(const ClauseInfo &ci);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 1ec38de29b85d6..b0b8d8d7ccc556 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -548,10 +548,13 @@ class ParseTreeDumper {
   NODE(OmpFromClause, Modifier)
   NODE(parser, OmpExpectation)
   NODE_ENUM(OmpExpectation, Value)
+  NODE(parser, OmpDirectiveNameModifier)
   NODE(parser, OmpIfClause)
-  NODE_ENUM(OmpIfClause, DirectiveNameModifier)
-  NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
+  NODE(OmpIfClause, Modifier)
   NODE(parser, OmpLastprivateClause)
+  NODE(OmpLastprivateClause, Modifier)
+  NODE(parser, OmpLastprivateModifier)
+  NODE_ENUM(OmpLastprivateModifier, Value)
   NODE(parser, OmpLinearClause)
   NODE(OmpLinearClause, WithModifier)
   NODE(OmpLinearClause, WithoutModifier)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index c00560b1f1726a..06c32831d2c60c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3543,6 +3543,23 @@ struct OmpDeviceModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpDeviceModifier, Value);
 };
 
+// Ref: [5.2:72-73,230-323], in 4.5-5.1 it's scattered over individual
+// directives that allow the IF clause.
+//
+// directive-name-modifier ->
+//    PARALLEL | TARGET | TARGET DATA |
+//    TARGET ENTER DATA | TARGET EXIT DATA |
+//    TARGET UPDATE | TASK | TASKLOOP |             // since 4.5
+//    CANCEL[*] | SIMD |                            // since 5.0
+//    TEAMS                                         // since 5.2
+//
+// [*] The IF clause is allowed on CANCEL in OpenMP 4.5, but only without
+// the directive-name-modifier. For the sake of uniformity CANCEL can be
+// considered a valid value in 4.5 as well.
+struct OmpDirectiveNameModifier {
+  WRAPPER_CLASS_BOILERPLATE(OmpDirectiveNameModifier, llvm::omp::Directive);
+};
+
 // Ref: [5.1:205-209], [5.2:166-168]
 //
 // motion-modifier ->
@@ -3566,6 +3583,15 @@ struct OmpIterator {
   WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
 };
 
+// Ref: [5.0:288-290], [5.1:321-322], [5.2:115-117]
+//
+// lastprivate-modifier ->
+//    CONDITIONAL                                   // since 5.0
+struct OmpLastprivateModifier {
+  ENUM_CLASS(Value, Conditional)
+  WRAPPER_CLASS_BOILERPLATE(OmpLastprivateModifier, Value);
+};
+
 // Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
 //
 // linear-modifier ->
@@ -3898,12 +3924,16 @@ struct OmpGrainsizeClause {
   std::tuple<MODIFIERS(), ScalarIntExpr> t;
 };
 
-// 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
+// Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives
+// that allow the IF clause.
+//
+// if-clause ->
+//    IF([directive-name-modifier:]
+//        scalar-logical-expression)                // since 4.5
 struct OmpIfClause {
   TUPLE_CLASS_BOILERPLATE(OmpIfClause);
-  ENUM_CLASS(DirectiveNameModifier, Parallel, Simd, Target, TargetData,
-      TargetEnterData, TargetExitData, TargetUpdate, Task, Taskloop, Teams)
-  std::tuple<std::optional<DirectiveNameModifier>, ScalarLogicalExpr> t;
+  MODIFIER_BOILERPLATE(OmpDirectiveNameModifier);
+  std::tuple<MODIFIERS(), ScalarLogicalExpr> t;
 };
 
 // OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier:
@@ -3913,13 +3943,15 @@ struct OmpInReductionClause {
   std::tuple<OmpReductionIdentifier, OmpObjectList> t;
 };
 
-// OMP 5.0 2.19.4.5 lastprivate-clause ->
-//                    LASTPRIVATE ([lastprivate-modifier :] list)
-//                  lastprivate-modifier -> CONDITIONAL
+// Ref: [4.5:199-201], [5.0:288-290], [5.1:321-322], [5.2:115-117]
+//
+// lastprivate-clause ->
+//    LASTPRIVATE(list) |                           // since 4.5
+//    LASTPRIVATE([lastprivate-modifier:] list)     // since 5.0
 struct OmpLastprivateClause {
   TUPLE_CLASS_BOILERPLATE(OmpLastprivateClause);
-  ENUM_CLASS(LastprivateModifier, Conditional);
-  std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
+  MODIFIER_BOILERPLATE(OmpLastprivateModifier);
+  std::tuple<MODIFIERS(), OmpObjectList> t;
 };
 
 // 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index dbc554198df21f..4025ce112d9cab 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -74,8 +74,10 @@ DECLARE_DESCRIPTOR(parser::OmpAllocatorSimpleModifier);
 DECLARE_DESCRIPTOR(parser::OmpChunkModifier);
 DECLARE_DESCRIPTOR(parser::OmpDependenceType);
 DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
+DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
 DECLARE_DESCRIPTOR(parser::OmpExpectation);
 DECLARE_DESCRIPTOR(parser::OmpIterator);
+DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
 DECLARE_DESCRIPTOR(parser::OmpLinearModifier);
 DECLARE_DESCRIPTOR(parser::OmpMapper);
 DECLARE_DESCRIPTOR(parser::OmpMapType);
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index ff2667983d4367..10c31963ec493a 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -825,27 +825,13 @@ Holds make(const parser::OmpClause::Holds &inp,
 If make(const parser::OmpClause::If &inp,
         semantics::SemanticsContext &semaCtx) {
   // inp.v -> parser::OmpIfClause
-  using wrapped = parser::OmpIfClause;
-
-  CLAUSET_ENUM_CONVERT( //
-      convert, wrapped::DirectiveNameModifier, llvm::omp::Directive,
-      // clang-format off
-      MS(Parallel,         OMPD_parallel)
-      MS(Simd,             OMPD_simd)
-      MS(Target,           OMPD_target)
-      MS(TargetData,       OMPD_target_data)
-      MS(TargetEnterData,  OMPD_target_enter_data)
-      MS(TargetExitData,   OMPD_target_exit_data)
-      MS(TargetUpdate,     OMPD_target_update)
-      MS(Task,             OMPD_task)
-      MS(Taskloop,         OMPD_taskloop)
-      MS(Teams,            OMPD_teams)
-      // clang-format on
-  );
-  auto &t0 = std::get<std::optional<wrapped::DirectiveNameModifier>>(inp.v.t);
+  auto &mods = semantics::OmpGetModifiers(inp.v);
+  auto *m0 =
+      semantics::OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(mods);
   auto &t1 = std::get<parser::ScalarLogicalExpr>(inp.v.t);
-  return If{{/*DirectiveNameModifier=*/maybeApply(convert, t0),
-             /*IfExpression=*/makeExpr(t1, semaCtx)}};
+  return If{
+      {/*DirectiveNameModifier=*/maybeApplyToV([](auto &&s) { return s; }, m0),
+       /*IfExpression=*/makeExpr(t1, semaCtx)}};
 }
 
 // Inbranch: empty
@@ -889,20 +875,20 @@ IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp,
 Lastprivate make(const parser::OmpClause::Lastprivate &inp,
                  semantics::SemanticsContext &semaCtx) {
   // inp.v -> parser::OmpLastprivateClause
-  using wrapped = parser::OmpLastprivateClause;
-
   CLAUSET_ENUM_CONVERT( //
-      convert, parser::OmpLastprivateClause::LastprivateModifier,
+      convert, parser::OmpLastprivateModifier::Value,
       Lastprivate::LastprivateModifier,
       // clang-format off
       MS(Conditional, Conditional)
       // clang-format on
   );
 
-  auto &t0 = std::get<std::optional<wrapped::LastprivateModifier>>(inp.v.t);
+  auto &mods = semantics::OmpGetModifiers(inp.v);
+  auto *m0 =
+      semantics::OmpGetUniqueModifier<parser::OmpLastprivateModifier>(mods);
   auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
 
-  return Lastprivate{{/*LastprivateModifier=*/maybeApply(convert, t0),
+  return Lastprivate{{/*LastprivateModifier=*/maybeApplyToV(convert, m0),
                       /*List=*/makeObjects(t1, semaCtx)}};
 }
 
diff --git a/flang/lib/Parser/CMakeLists.txt b/flang/lib/Parser/CMakeLists.txt
index 600a2f67df4431..d364671d7a3229 100644
--- a/flang/lib/Parser/CMakeLists.txt
+++ b/flang/lib/Parser/CMakeLists.txt
@@ -30,6 +30,7 @@ add_flang_library(FortranParser
   LINK_COMPONENTS
   Support
   FrontendOpenACC
+  FrontendOpenMP
 
   DEPENDS
   omp_gen
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 1d3dd518601995..920f97f7ca0f21 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -16,6 +16,10 @@
 #include "token-parsers.h"
 #include "type-parser-implementation.h"
 #include "flang/Parser/parse-tree.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 // OpenMP Directives and Clauses
 namespace Fortran::parser {
@@ -23,6 +27,47 @@ namespace Fortran::parser {
 constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
 constexpr auto endOmpLine = space >> endOfLine;
 
+/// Parse OpenMP directive name (this includes compound directives).
+struct OmpDirectiveNameParser {
+  using resultType = llvm::omp::Directive;
+  using Token = TokenStringMatch<false, false>;
+
+  std::optional<resultType> Parse(ParseState &state) const {
+    for (const NameWithId &nid : directives()) {
+      if (attempt(Token(nid.first.data())).Parse(state)) {
+        return nid.second;
+      }
+    }
+    return std::nullopt;
+  }
+
+private:
+  using NameWithId = std::pair<std::string, llvm::omp::Directive>;
+
+  llvm::iterator_range<const NameWithId *> directives() const;
+  void initTokens(NameWithId *) const;
+};
+
+llvm::iterator_range<const OmpDirectiveNameParser::NameWithId *>
+OmpDirectiveNameParser::directives() const {
+  static NameWithId table[llvm::omp::Directive_enumSize];
+  [[maybe_unused]] static bool init = (initTokens(table), true);
+  return llvm::make_range(std::cbegin(table), std::cend(table));
+}
+
+void OmpDirectiveNameParser::initTokens(NameWithId *table) const {
+  for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) {
+    auto id{static_cast<llvm::omp::Directive>(i)};
+    llvm::StringRef name{llvm::omp::getOpenMPDirectiveName(id)};
+    table[i] = std::make_pair(name.str(), id);
+  }
+  // Sort the table with respect to the directive name length in a descending
+  // order. This is to make sure that longer names are tried first, before
+  // any potential prefix (e.g. "target update" before "target").
+  std::sort(table, table + llvm::omp::Directive_enumSize,
+      [](auto &a, auto &b) { return a.first.size() > b.first.size(); });
+}
+
 template <typename Clause, typename Separator> struct ModifierList {
   constexpr ModifierList(Separator sep) : sep_(sep) {}
   constexpr ModifierList(const ModifierList &) = default;
@@ -136,6 +181,9 @@ TYPE_PARSER(construct<OmpIterator>( //
     "ITERATOR" >>
     parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
 
+TYPE_PARSER(construct<OmpLastprivateModifier>(
+    "CONDITIONAL" >> pure(OmpLastprivateModifier::Value::Conditional)))
+
 // 2.15.3.7 LINEAR (linear-list: linear-step)
 //          linear-list -> list | modifier(list)
 //          linear-modifier -> REF | VAL | UVAL
@@ -232,6 +280,11 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
 TYPE_PARSER(sourced(
     construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
 
+TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
+
+TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
+    Parser<OmpLastprivateModifier>{})))
+
 TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
     sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
         construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -345,22 +398,7 @@ TYPE_PARSER(construct<OmpDeviceTypeClause>(
 
 // 2.12 IF (directive-name-modifier: scalar-logical-expr)
 TYPE_PARSER(construct<OmpIfClause>(
-    maybe(
-        ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
-            "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) ||
-            "TARGET ENTER DATA" >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
-            "TARGET EXIT DATA" >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
-            "TARGET DATA" >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
-            "TARGET UPDATE" >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
-            "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
-            "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
-            "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
-            "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) /
-        ":"),
+    maybe(nonemptyList(Parser<OmpIfClause::Modifier>{}) / ":"),
     scalarLogicalExpr))
 
 TYPE_PARSER(construct<OmpReductionClause>(
@@ -460,8 +498,7 @@ TYPE_PARSER(
 
 // OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
 TYPE_PARSER(construct<OmpLastprivateClause>(
-    maybe("CONDITIONAL" >>
-        pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
+    maybe(nonemptyList(Parser<OmpLastprivateClause::Modifier>{}) / ":"),
     Parser<OmpObjectList>{}))
 
 // OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD )
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index cd025333a077d3..43c7ef540cb7af 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2074,6 +2074,9 @@ class UnparseVisitor {
                   },
         x.u);
   }
+  void Unparse(const OmpDirectiveNameModifier &x) {
+    Word(llvm::omp::getOpenMPDirectiveName(x.v));
+  }
   void Unparse(const OmpIteratorSpecifier &x) {
     Walk(std::get<TypeDeclarationStmt>(x.t));
     Put(" = ");
@@ -2090,9 +2093,8 @@ class UnparseVisitor {
     Put(")");
   }
   void Unparse(const OmpLastprivateClause &x) {
-    Walk(
-        std::get<std::optional<OmpLastprivateClause::LastprivateModifier>>(x.t),
-        ":");
+    using Modifier = OmpLastprivateClause::Modifier;
+    Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
     Walk(std::get<OmpObjectList>(x.t));
   }
   void Unparse(const OmpMapClause &x) {
@@ -2127,7 +2129,8 @@ class UnparseVisitor {
     Walk(std::get<OmpObjectList>(x.t));
   }
   void Unparse(const OmpIfClause &x) {
-    Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t), ":");
+    using Modifier = OmpIfClause::Modifier;
+    Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
     Walk(std::get<ScalarLogicalExpr>(x.t));
   }
   void Unparse(const OmpLinearClause::WithoutModifier &x) {
@@ -2826,8 +2829,7 @@ class UnparseVisitor {
   WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default
   WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP defaultmap
   WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category
-  WALK_NESTED_ENUM(
-      OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier
+  WALK_NESTED_ENUM(OmpLastprivateModifier, Value) // OMP lastprivate-modifier
   WALK_NESTED_ENUM(OmpChunkModifier, Value) // OMP chunk-modifier
   WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier
   WALK_NESTED_ENUM(OmpOrderingModifier, Value) // OMP ordering-modifier
@@ -2838,7 +2840,6 @@ class UnparseVisitor {
       OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type
   WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
   WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation
-  WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
   WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
   WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
   WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 9e589067c8868d..a88aba5a54a023 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3428,36 +3428,81 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
 
 void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_if);
-  using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
-  // TODO Check that, when multiple 'if' clauses are applied to a combined
-  // construct, at most one of them applies to each directive.
-  static std::unordered_map<dirNameModifier, OmpDirectiveSet>
-      dirNameModifierMap{{dirNameModifier::Parallel, llvm::omp::allParallelSet},
-          {dirNameModifier::Simd, llvm::omp::allSimdSet},
-          {dirNameModifier::Target, llvm::omp::allTargetSet},
-          {dirNameModifier::TargetData,
-              {llvm::omp::Directive::OMPD_target_data}},
-          {dirNameModifier::TargetEnterData,
-              {llvm::omp::Directive::OMPD_target_enter_data}},
-          {dirNameModifier::TargetExitData,
-              {llvm::omp::Directive::OMPD_target_exit_data}},
-          {dirNameModifier::TargetUpdate,
-              {llvm::omp::Directive::OMPD_target_update}},
-          {dirNameModifier::Task, {llvm::omp::Directive::OMPD_task}},
-          {dirNameModifier::Taskloop, llvm::omp::allTaskloopSet},
-          {dirNameModifier::Teams, llvm::omp::allTeamsSet}};
-  if (const auto &directiveName{
-          std::get<std::optional<dirNameModifier>>(x.v.t)}) {
-    auto search{dirNameModifierMap.find(*directiveName)};
-    if (search == dirNameModifierMap.end() ||
-        !search->second.test(GetContext().directive)) {
-      context_
-          .Say(GetContext().clauseSource,
-              "Unmatched directive name modifier %s on the IF clause"_err_en_US,
-              parser::ToUpperCaseLetters(
-                  parser::OmpIfClause::EnumToString(*directiveName)))
-          .Attach(
-              GetContext().directiveSource, "Cannot apply to directive"_en_US);
+  unsigned version{context_.langOptions().OpenMPVersion};
+  llvm::omp::Directive dir{GetContext().directive};
+
+  auto isConstituent{[](llvm::omp::Directive dir, llvm::omp::Directive part) {
+    using namespace llvm::omp;
+    llvm::ArrayRef<Directive> dirLeafs{getLeafConstructsOrSelf(dir)};
+    llvm::ArrayRef<Directive> partLeafs{getLeafConstructsOrSelf(part)};
+    // Maybe it's sufficient to check if every leaf of `part` is also a leaf
+    // of `dir`, but to be safe check if `partLeafs` is a sub-sequence of
+    // `dirLeafs`.
+    size_t dirSize{dirLeafs.size()}, partSize{partLeafs.size()};
+    // Find the first leaf from `part` in `dir`.
+    if (auto first = llvm::find(dirLeafs, partLeafs.front());
+        first != dirLeafs.end()) {
+      // A leaf can only appear once in a compound directive, so if `part`
+      // is a subsequence of `dir`, it must start here.
+      long firstPos{std::distance(dirLeafs.begin(), first)};
+      llvm::ArrayRef<Directive> subSeq{
+          first, std::min<size_t>(dirSize - firstPos, partSize)};
+      return subSeq == partLeafs;
+    }
+    return false;
+  }};
+
+  if (OmpVerifyModifiers(
+          x.v, llvm::omp::OMPC_if, GetContext().clauseSource, context_)) {
+    auto &modifiers{OmpGetModifiers(x.v)};
+    if (auto *dnm{OmpGetUniqueModifier<parser::OmpDirectiveNameModifier>(
+            modifiers)}) {
+      llvm::omp::Directive sub{dnm->v};
+      std::string subName{parser::ToUpperCaseLetters(
+          llvm::omp::getOpenMPDirectiveName(sub).str())};
+      std::string dirName{parser::ToUpperCaseLetters(
+          llvm::omp::getOpenMPDirectiveName(dir).str())};
+
+      parser::CharBlock modifierSource{OmpGetModifierSource(modifiers, dnm)};
+      auto desc{OmpGetDescriptor<parser::OmpDirectiveNameModifier>()};
+      std::string modName{desc.name.str()};
+
+      if (!isConstituent(dir, sub)) {
+        context_
+            .Say(modifierSource,
+                "%s is not a constituent of the %s directive"_err_en_US,
+                subName, dirName)
+            .Attach(GetContext().directiveSource,
+                "Cannot apply to directive"_en_US);
+      } else {
+        static llvm::omp::Directive valid45[]{
+            llvm::omp::OMPD_cancel, //
+            llvm::omp::OMPD_parallel, //
+            /* OMP 5.0+ also allows OMPD_simd */
+            llvm::omp::OMPD_target, //
+            llvm::omp::OMPD_target_data, //
+            llvm::omp::OMPD_target_enter_data, //
+            llvm::omp::OMPD_target_exit_data, //
+            llvm::omp::OMPD_target_update, //
+            llvm::omp::OMPD_task, //
+            llvm::omp::OMPD_taskloop, //
+            /* OMP 5.2+ also allows OMPD_teams */
+        };
+        if (version < 50 && sub == llvm::omp::OMPD_simd) {
+          context_.Say(modifierSource,
+              "%s is not allowed as '%s' in %s, %s"_warn_en_US, subName,
+              modName, ThisVersion(version), TryVersion(50));
+        } else if (version < 52 && sub == llvm::omp::OMPD_teams) {
+          context_.Say(modifierSource,
+              "%s is not allowed as '%s' in %s, %s"_warn_en_US, subName,
+              modName, ThisVersion(version), TryVersion(52));
+        } else if (!llvm::is_contained(valid45, sub) &&
+            sub != llvm::omp::OMPD_simd && sub != llvm::omp::OMPD_teams) {
+          context_.Say(modifierSource,
+              "%s is not allowed as '%s' in %s"_err_en_US, subName, modName,
+              ThisVersion(version));
+        }
+      }
     }
   }
 }
@@ -3857,20 +3902,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
   CheckPrivateSymbolsInOuterCxt(
       currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);
 
-  using LastprivateModifier = parser::OmpLastprivateClause::LastprivateModifier;
-  const auto &maybeMod{std::get<std::optional<LastprivateModifier>>(x.v.t)};
-  if (maybeMod) {
-    unsigned version{context_.langOptions().OpenMPVersion};
-    unsigned allowedInVersion = 50;
-    if (version < allowedInVersion) {
-      std::string thisVersion{
-          std::to_string(version / 10) + "." + std::to_string(version % 10)};
-      context_.Say(GetContext().clauseSource,
-          "LASTPRIVATE clause with CONDITIONAL modifier is not "
-          "allowed in %s, %s"_err_en_US,
-          ThisVersion(version), TryVersion(allowedInVersion));
-    }
-  }
+  OmpVerifyModifiers(
+      x.v, llvm::omp::OMPC_lastprivate, GetContext().clauseSource, context_);
 }
 
 void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index e384b0270e6eae..f8f81e6c6ffa15 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -190,6 +190,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeviceModifier>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &
+OmpGetDescriptor<parser::OmpDirectiveNameModifier>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"directive-name-modifier",
+      /*props=*/
+      {
+          {45, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {45, {Clause::OMPC_if}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
   static const OmpModifierDescriptor desc{
@@ -225,6 +242,23 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &
+OmpGetDescriptor<parser::OmpLastprivateModifier>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"lastprivate-modifier",
+      /*props=*/
+      {
+          {50, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {50, {Clause::OMPC_lastprivate}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
   static const OmpModifierDescriptor desc{
diff --git a/flang/test/Parser/OpenMP/if-clause-unparse.f90 b/flang/test/Parser/OpenMP/if-clause-unparse.f90
index 20f7b36e743e1a..ce058caa54a938 100644
--- a/flang/test/Parser/OpenMP/if-clause-unparse.f90
+++ b/flang/test/Parser/OpenMP/if-clause-unparse.f90
@@ -10,50 +10,50 @@ program if_unparse
   !$omp target update if(cond)
 
   ! CHECK: !$OMP TARGET UPDATE
-  ! CHECK-SAME: IF(TARGETUPDATE:cond)
+  ! CHECK-SAME: IF(TARGET UPDATE: cond)
   !$omp target update if(target update: cond)
   
   ! CHECK: !$OMP TARGET UPDATE
-  ! CHECK-SAME: IF(TARGETUPDATE:cond)
+  ! CHECK-SAME: IF(TARGET UPDATE: cond)
   !$omp target update if(targetupdate: cond)
 
   ! CHECK: !$OMP TARGET ENTER DATA
-  ! CHECK-SAME: IF(TARGETENTERDATA:cond)
+  ! CHECK-SAME: IF(TARGET ENTER DATA: cond)
   !$omp target enter data map(to: i) if(target enter data: cond)
 
   ! CHECK: !$OMP TARGET EXIT DATA
-  ! CHECK-SAME: IF(TARGETEXITDATA:cond)
+  ! CHECK-SAME: IF(TARGET EXIT DATA: cond)
   !$omp target exit data map(from: i) if(target exit data: cond)
 
   ! CHECK: !$OMP TARGET DATA
-  ! CHECK-SAME: IF(TARGETDATA:cond)
+  ! CHECK-SAME: IF(TARGET DATA: cond)
   !$omp target data map(tofrom: i) if(target data: cond)
   !$omp end target data
 
   ! CHECK: !$OMP TARGET
-  ! CHECK-SAME: IF(TARGET:cond)
+  ! CHECK-SAME: IF(TARGET: cond)
   !$omp target if(target: cond)
   !$omp end target
 
   ! CHECK: !$OMP TEAMS
-  ! CHECK-SAME: IF(TEAMS:cond)
+  ! CHECK-SAME: IF(TEAMS: cond)
   !$omp teams if(teams: cond)
   !$omp end teams
 
   ! CHECK: !$OMP PARALLEL DO SIMD
-  ! CHECK-SAME: IF(PARALLEL:i<10) IF(SIMD:.FALSE.)
+  ! CHECK-SAME: IF(PARALLEL: i<10) IF(SIMD: .FALSE.)
   !$omp parallel do simd if(parallel: i < 10) if(simd: .false.)
   do i = 1, 10
   end do
   !$omp end parallel do simd
 
   ! CHECK: !$OMP TASK
-  ! CHECK-SAME: IF(TASK:cond)
+  ! CHECK-SAME: IF(TASK: cond)
   !$omp task if(task: cond)
   !$omp end task
 
   ! CHECK: !$OMP TASKLOOP
-  ! CHECK-SAME: IF(TASKLOOP:cond)
+  ! CHECK-SAME: IF(TASKLOOP: cond)
   !$omp taskloop if(taskloop: cond)
   do i = 1, 10
   end do
diff --git a/flang/test/Parser/OpenMP/if-clause.f90 b/flang/test/Parser/OpenMP/if-clause.f90
index 6d69e16e7cc731..b3e3913f8bd1cf 100644
--- a/flang/test/Parser/OpenMP/if-clause.f90
+++ b/flang/test/Parser/OpenMP/if-clause.f90
@@ -1,4 +1,4 @@
-! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck %s
 
 program openmp_parse_if
   logical :: cond
@@ -11,34 +11,34 @@ program openmp_parse_if
 
   ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update
   ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = TargetUpdate
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target update
   !$omp target update if(target update: cond) to(i)
 
   ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target enter data
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = TargetEnterData
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target enter data
   !$omp target enter data map(to: i) if(target enter data: cond)
 
   ! CHECK: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target exit data
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = TargetExitData
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target exit data
   !$omp target exit data map(from: i) if(target exit data: cond)
 
   ! CHECK: OmpBlockDirective -> llvm::omp::Directive = target data
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = TargetData
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target data
   !$omp target data map(tofrom: i) if(target data: cond)
   !$omp end target data
 
   ! CHECK: OmpLoopDirective -> llvm::omp::Directive = target teams distribute parallel do simd
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Target
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = target
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Teams
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = teams
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Parallel
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = parallel
   ! CHECK: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Simd
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = simd
   !$omp target teams distribute parallel do simd if(target: cond) &
   !$omp&    if(teams: cond) if(parallel: cond) if(simd: cond)
   do i = 1, 10
@@ -47,13 +47,13 @@ program openmp_parse_if
 
   ! CHECK: OmpBlockDirective -> llvm::omp::Directive = task
   ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Task
+  ! CHECK-NEXT: OmpDirectiveNameModifier -> llvm::omp::Directive = task
   !$omp task if(task: cond)
   !$omp end task
 
   ! CHECK: OmpLoopDirective -> llvm::omp::Directive = taskloop
   ! CHECK-NEXT: OmpClause -> If -> OmpIfClause
-  ! CHECK-NEXT: DirectiveNameModifier = Taskloop
+  ! CHECK-NEXT: DirectiveNameModifier -> llvm::omp::Directive = taskloop
   !$omp taskloop if(taskloop: cond)
   do i = 1, 10
   end do
diff --git a/flang/test/Parser/OpenMP/lastprivate-clause.f90 b/flang/test/Parser/OpenMP/lastprivate-clause.f90
index 382f02c75e7f14..ac25174f3cc427 100644
--- a/flang/test/Parser/OpenMP/lastprivate-clause.f90
+++ b/flang/test/Parser/OpenMP/lastprivate-clause.f90
@@ -39,7 +39,7 @@ subroutine foo2()
 !UNPARSE: SUBROUTINE foo2
 !UNPARSE:  INTEGER x, i
 !UNPARSE:   x=1_4
-!UNPARSE: !$OMP PARALLEL DO  LASTPRIVATE(CONDITIONAL:x)
+!UNPARSE: !$OMP PARALLEL DO  LASTPRIVATE(CONDITIONAL: x)
 !UNPARSE:  DO i=1_4,100_4
 !UNPARSE:    x=x+1_4
 !UNPARSE:  END DO
@@ -49,6 +49,6 @@ subroutine foo2()
 !PARSE-TREE:   Name = 'foo2'
 !PARSE-TREE: OmpLoopDirective -> llvm::omp::Directive = parallel do
 !PARSE-TREE: OmpClauseList -> OmpClause -> Lastprivate -> OmpLastprivateClause
-!PARSE-TREE:   LastprivateModifier = Conditional
+!PARSE-TREE:   Modifier -> OmpLastprivateModifier -> Value = Conditional
 !PARSE-TREE:   OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
 !PARSE-TREE: EndSubroutineStmt
diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90
index bc9d2d37060fc2..66e11e4b540f0f 100644
--- a/flang/test/Semantics/OpenMP/clause-validity01.f90
+++ b/flang/test/Semantics/OpenMP/clause-validity01.f90
@@ -241,7 +241,7 @@
   enddo
   !$omp end parallel do simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL DO directive
   !$omp parallel do if(target:a>1.)
   do i = 1, N
   enddo
@@ -532,7 +532,7 @@
   a = 1.
   !$omp end task
 
-  !ERROR: Unmatched directive name modifier TASKLOOP on the IF clause
+  !ERROR: TASKLOOP is not a constituent of the TASK directive
   !$omp task private(a) if(taskloop:a.eq.1)
   a = 1.
   !$omp end task
diff --git a/flang/test/Semantics/OpenMP/if-clause.f90 b/flang/test/Semantics/OpenMP/if-clause.f90
index 7aeb617e535630..23be4a751c8926 100644
--- a/flang/test/Semantics/OpenMP/if-clause.f90
+++ b/flang/test/Semantics/OpenMP/if-clause.f90
@@ -18,7 +18,7 @@ program main
   end do
   !$omp end distribute parallel do
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the DISTRIBUTE PARALLEL DO directive
   !$omp distribute parallel do if(target: .true.)
   do i = 1, 10
   end do
@@ -45,7 +45,7 @@ program main
   end do
   !$omp end distribute parallel do simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the DISTRIBUTE PARALLEL DO SIMD directive
   !$omp distribute parallel do simd if(target: .true.)
   do i = 1, 10
   end do
@@ -66,7 +66,7 @@ program main
   end do
   !$omp end distribute simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the DISTRIBUTE SIMD directive
   !$omp distribute simd if(target: .true.)
   do i = 1, 10
   end do
@@ -92,7 +92,7 @@ program main
   end do
   !$omp end do simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the DO SIMD directive
   !$omp do simd if(target: .true.)
   do i = 1, 10
   end do
@@ -113,7 +113,7 @@ program main
   !$omp parallel if(parallel: .true.)
   !$omp end parallel
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL directive
   !$omp parallel if(target: .true.)
   !$omp end parallel
 
@@ -134,7 +134,7 @@ program main
   end do
   !$omp end parallel do
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL DO directive
   !$omp parallel do if(target: .true.)
   do i = 1, 10
   end do
@@ -159,7 +159,7 @@ program main
   end do
   !$omp end parallel do simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL DO SIMD directive
   !$omp parallel do simd if(target: .true.)
   do i = 1, 10
   end do
@@ -174,7 +174,7 @@ program main
   !$omp parallel sections if(parallel: .true.)
   !$omp end parallel sections
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL SECTIONS directive
   !$omp parallel sections if(target: .true.)
   !$omp end parallel sections
 
@@ -191,7 +191,7 @@ program main
   !$omp parallel workshare if(parallel: .true.)
   !$omp end parallel workshare
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the PARALLEL WORKSHARE directive
   !$omp parallel workshare if(target: .true.)
   !$omp end parallel workshare
 
@@ -212,7 +212,7 @@ program main
   end do
   !$omp end simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the SIMD directive
   !$omp simd if(target: .true.)
   do i = 1, 10
   end do
@@ -233,7 +233,7 @@ program main
   !$omp target if(target: .true.)
   !$omp end target
 
-  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !ERROR: PARALLEL is not a constituent of the TARGET directive
   !$omp target if(parallel: .true.)
   !$omp end target
 
@@ -250,7 +250,7 @@ program main
   !$omp target data map(tofrom: i) if(target data: .true.)
   !$omp end target data
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TARGET DATA directive
   !$omp target data map(tofrom: i) if(target: .true.)
   !$omp end target data
 
@@ -265,7 +265,7 @@ program main
 
   !$omp target enter data map(to: i) if(target enter data: .true.)
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TARGET ENTER DATA directive
   !$omp target enter data map(to: i) if(target: .true.)
 
   !ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
@@ -278,7 +278,7 @@ program main
 
   !$omp target exit data map(from: i) if(target exit data: .true.)
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TARGET EXIT DATA directive
   !$omp target exit data map(from: i) if(target: .true.)
   
   !ERROR: At most one IF clause can appear on the TARGET EXIT DATA directive
@@ -293,7 +293,7 @@ program main
   !$omp target parallel if(target: .true.) if(parallel: .false.)
   !$omp end target parallel
 
-  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !ERROR: SIMD is not a constituent of the TARGET PARALLEL directive
   !$omp target parallel if(simd: .true.)
   !$omp end target parallel
 
@@ -310,7 +310,7 @@ program main
   end do
   !$omp end target parallel do
 
-  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !ERROR: SIMD is not a constituent of the TARGET PARALLEL DO directive
   !$omp target parallel do if(simd: .true.)
   do i = 1, 10
   end do
@@ -330,7 +330,7 @@ program main
   end do
   !$omp end target parallel do simd
 
-  !ERROR: Unmatched directive name modifier TEAMS on the IF clause
+  !ERROR: TEAMS is not a constituent of the TARGET PARALLEL DO SIMD directive
   !$omp target parallel do simd if(teams: .true.)
   do i = 1, 10
   end do
@@ -349,7 +349,7 @@ program main
   end do
   !$omp end target simd
 
-  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !ERROR: PARALLEL is not a constituent of the TARGET SIMD directive
   !$omp target simd if(parallel: .true.)
   do i = 1, 10
   end do
@@ -364,7 +364,7 @@ program main
   !$omp target teams if(target: .true.) if(teams: .false.)
   !$omp end target teams
 
-  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !ERROR: PARALLEL is not a constituent of the TARGET TEAMS directive
   !$omp target teams if(parallel: .true.)
   !$omp end target teams
 
@@ -381,7 +381,7 @@ program main
   end do
   !$omp end target teams distribute
 
-  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !ERROR: PARALLEL is not a constituent of the TARGET TEAMS DISTRIBUTE directive
   !$omp target teams distribute if(parallel: .true.)
   do i = 1, 10
   end do
@@ -401,7 +401,7 @@ program main
   end do
   !$omp end target teams distribute parallel do
 
-  !ERROR: Unmatched directive name modifier SIMD on the IF clause
+  !ERROR: SIMD is not a constituent of the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
   !$omp target teams distribute parallel do if(simd: .true.)
   do i = 1, 10
   end do
@@ -422,7 +422,7 @@ program main
   end do
   !$omp end target teams distribute parallel do simd
 
-  !ERROR: Unmatched directive name modifier TASK on the IF clause
+  !ERROR: TASK is not a constituent of the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
   !$omp target teams distribute parallel do simd if(task: .true.)
   do i = 1, 10
   end do
@@ -442,7 +442,7 @@ program main
   end do
   !$omp end target teams distribute simd
 
-  !ERROR: Unmatched directive name modifier PARALLEL on the IF clause
+  !ERROR: PARALLEL is not a constituent of the TARGET TEAMS DISTRIBUTE SIMD directive
   !$omp target teams distribute simd if(parallel: .true.)
   do i = 1, 10
   end do
@@ -455,7 +455,7 @@ program main
   
   !$omp target update to(i) if(target update: .true.)
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TARGET UPDATE directive
   !$omp target update to(i) if(target: .true.)
 
   !ERROR: At most one IF clause can appear on the TARGET UPDATE directive
@@ -470,7 +470,7 @@ program main
   !$omp task if(task: .true.)
   !$omp end task
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TASK directive
   !$omp task if(target: .true.)
   !$omp end task
 
@@ -491,7 +491,7 @@ program main
   end do
   !$omp end taskloop
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TASKLOOP directive
   !$omp taskloop if(target: .true.)
   do i = 1, 10
   end do
@@ -516,7 +516,7 @@ program main
   end do
   !$omp end taskloop simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TASKLOOP SIMD directive
   !$omp taskloop simd if(target: .true.)
   do i = 1, 10
   end do
@@ -531,7 +531,7 @@ program main
   !$omp teams if(teams: .true.)
   !$omp end teams
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TEAMS directive
   !$omp teams if(target: .true.)
   !$omp end teams
 
@@ -552,7 +552,7 @@ program main
   end do
   !$omp end teams distribute
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE directive
   !$omp teams distribute if(target: .true.)
   do i = 1, 10
   end do
@@ -577,7 +577,7 @@ program main
   end do
   !$omp end teams distribute parallel do
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE PARALLEL DO directive
   !$omp teams distribute parallel do if(target: .true.)
   do i = 1, 10
   end do
@@ -597,7 +597,7 @@ program main
   end do
   !$omp end teams distribute parallel do simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE PARALLEL DO SIMD directive
   !$omp teams distribute parallel do simd if(target: .true.)
   do i = 1, 10
   end do
@@ -616,7 +616,7 @@ program main
   end do
   !$omp end teams distribute simd
 
-  !ERROR: Unmatched directive name modifier TARGET on the IF clause
+  !ERROR: TARGET is not a constituent of the TEAMS DISTRIBUTE SIMD directive
   !$omp teams distribute simd if(target: .true.)
   do i = 1, 10
   end do



More information about the llvm-branch-commits mailing list