[flang-commits] [flang] [llvm] [flang][OpenMP] Check that IF clause applies to at most one leaf (PR #205164)

Krzysztof Parzyszek via flang-commits flang-commits at lists.llvm.org
Tue Jun 23 10:47:16 PDT 2026


https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/205164

>From f9257362fa40daa5d76e8956702866fb5e6b1fa2 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 22 Jun 2026 12:29:58 -0500
Subject: [PATCH 1/2] [flang][OpenMP] Check that IF clause applies to at most
 one leaf

This also allows placing the IF clause in the "allowedClauses" set for
all directives, instead of having it in "allowedOnceClauses" for some
directives and in "allowedClauses" for others.

The emitted diagnostic will show which constituent has multiple IF
clauses applying to it:
```
if.f90:4:35: error: At most one IF clause can apply to each directive constituent
    !$omp & if(target teams: x > 0) if(teams distribute: y > 0)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
if.f90:4:11: Previous IF clause applying to the TEAMS constituent
    !$omp & if(target teams: x > 0) if(teams distribute: y > 0)
            ^^^^^^^^^^^^^^^^^^^^^^^
```
---
 flang/lib/Semantics/check-omp-structure.cpp   | 44 ++++++++++--
 flang/lib/Semantics/check-omp-structure.h     |  5 ++
 .../Semantics/OpenMP/device-constructs.f90    |  4 +-
 flang/test/Semantics/OpenMP/if-clause-45.f90  | 29 ++++----
 flang/test/Semantics/OpenMP/if-clause-50.f90  | 32 ++++-----
 flang/test/Semantics/OpenMP/if-clause.f90     | 34 ++++-----
 llvm/include/llvm/Frontend/OpenMP/OMP.td      | 71 ++++++++++---------
 7 files changed, 127 insertions(+), 92 deletions(-)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index d87b2f1983de6..7fffcd26237f6 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3359,6 +3359,10 @@ void OmpStructureChecker::Leave(const parser::OmpEndDirective &x) {
   }
 }
 
+void OmpStructureChecker::Enter(const parser::OmpClauseList &) {
+  ifLeafs.clear();
+}
+
 // Clauses
 // Mainly categorized as
 // 1. Checks on 'OmpClauseList' from 'parse-tree.h'.
@@ -4317,6 +4321,13 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
     return false;
   }};
 
+  // The directive-name to which the clause applies. [Note: The directive-
+  // name-modifier is not necessarily a valid directive name, but that's how
+  // it's currently modeled.]
+  // This will be set only after other checks pass to avoid emitting irrelevant
+  // diagnostics.
+  llvm::omp::Directive appliesTo{llvm::omp::Directive::OMPD_unknown};
+
   if (!OmpVerifyModifiers(
           x.v, llvm::omp::OMPC_if, GetContext().clauseSource, context_)) {
     return;
@@ -4334,12 +4345,9 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
     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);
+      context_.Say(modifierSource,
+          "%s is not a constituent of the %s directive"_err_en_US, subName,
+          dirName);
     } else {
       static llvm::omp::Directive valid45[]{
           llvm::omp::OMPD_cancel, //
@@ -4362,11 +4370,33 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
         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) &&
+      } else if (version < 60 && !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));
+      } else {
+        appliesTo = sub;
+      }
+    }
+  } else {
+    appliesTo = GetContext().directive;
+  }
+
+  if (appliesTo != llvm::omp::Directive::OMPD_unknown) {
+    parser::CharBlock source{GetContext().clauseSource};
+    for (auto leaf : llvm::omp::getLeafConstructsOrSelf(appliesTo)) {
+      auto pair{ifLeafs.try_emplace(leaf, source)};
+      if (!pair.second) {
+        std::string ifName{GetUpperName(llvm::omp::Clause::OMPC_if, version)};
+        context_
+            .Say(source,
+                "At most one %s clause can apply to each directive constituent"_err_en_US,
+                ifName)
+            .Attach(pair.first->second,
+                "Previous %s clause applying to the %s constituent"_en_US,
+                ifName, GetUpperName(leaf, version));
+        break;
       }
     }
   }
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 1283feb32ef5f..840c740b2eb2b 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::OmpClauseList &);
   void Leave(const parser::OmpClauseList &);
   void Enter(const parser::OmpClause &);
 
@@ -388,6 +389,10 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   int allocateDirectiveLevel_{0};
   parser::CharBlock visitedAtomicSource_;
 
+  // Mapping of directive-name-modifier constituents to the sources of the
+  // IF clauses that referenced them. If there was no modifier, the entire
+  // directive is assumed to be listed.
+  std::map<llvm::omp::Directive, parser::CharBlock> ifLeafs;
   // Stack of nested DO loops and OpenMP constructs.
   // This is used to verify DO loop nest for DOACROSS, and branches into
   // and out of OpenMP constructs.
diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90
index db04e7db155ad..d74d720b2d35d 100644
--- a/flang/test/Semantics/OpenMP/device-constructs.f90
+++ b/flang/test/Semantics/OpenMP/device-constructs.f90
@@ -169,7 +169,7 @@ program main
   !ERROR: The device expression of the DEVICE clause must be a non-negative integer expression, 'omp_initial_device' (-1), or 'omp_invalid_device' (-2)
   !$omp target exit data map(delete:A) device(-3)
 
-  !ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target enter data map(to:a) if(.true.) if(.false.)
 
   !ERROR: Only the ALLOC, TO, TOFROM map types are permitted for MAP clauses on the TARGET ENTER DATA directive
@@ -185,7 +185,7 @@ program main
 
   !$omp target update if(.true.) device(1) to(a) from(b) depend(inout:c) nowait
 
-  !ERROR: At most one IF clause can appear on the TARGET UPDATE directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target update to(a) if(.true.) if(.false.)
 
   !ERROR: At most one DEVICE clause can appear on the TARGET UPDATE directive
diff --git a/flang/test/Semantics/OpenMP/if-clause-45.f90 b/flang/test/Semantics/OpenMP/if-clause-45.f90
index b013a33094727..4f444907b1617 100644
--- a/flang/test/Semantics/OpenMP/if-clause-45.f90
+++ b/flang/test/Semantics/OpenMP/if-clause-45.f90
@@ -24,7 +24,7 @@ program main
   end do
   !$omp end distribute parallel do
 
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp distribute parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -79,7 +79,6 @@ program main
 
   !ERROR: IF clause is not allowed on directive DISTRIBUTE SIMD in OpenMP v4.5, try -fopenmp-version=50
   !ERROR: IF clause is not allowed on directive DISTRIBUTE SIMD in OpenMP v4.5, try -fopenmp-version=50
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE SIMD directive
   !ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
   !$omp distribute simd if(.true.) if(simd: .false.)
   do i = 1, 10
@@ -112,7 +111,6 @@ program main
 
   !ERROR: IF clause is not allowed on directive DO SIMD in OpenMP v4.5, try -fopenmp-version=50
   !ERROR: IF clause is not allowed on directive DO SIMD in OpenMP v4.5, try -fopenmp-version=50
-  !ERROR: At most one IF clause can appear on the DO SIMD directive
   !ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
   !$omp do simd if(.true.) if(simd: .false.)
   do i = 1, 10
@@ -132,7 +130,7 @@ program main
   !$omp parallel if(target: .true.)
   !$omp end parallel
 
-  !ERROR: At most one IF clause can appear on the PARALLEL directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel if(.true.) if(parallel: .false.)
   !$omp end parallel
 
@@ -155,7 +153,7 @@ program main
   end do
   !$omp end parallel do
 
-  !ERROR: At most one IF clause can appear on the PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -194,7 +192,7 @@ program main
   !$omp parallel sections if(target: .true.)
   !$omp end parallel sections
 
-  !ERROR: At most one IF clause can appear on the PARALLEL SECTIONS directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel sections if(.true.) if(parallel: .false.)
   !$omp end parallel sections
 
@@ -211,7 +209,7 @@ program main
   !$omp parallel workshare if(target: .true.)
   !$omp end parallel workshare
 
-  !ERROR: At most one IF clause can appear on the PARALLEL WORKSHARE directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel workshare if(.true.) if(parallel: .false.)
   !$omp end parallel workshare
 
@@ -240,7 +238,6 @@ program main
 
   !ERROR: IF clause is not allowed on directive SIMD in OpenMP v4.5, try -fopenmp-version=50
   !ERROR: IF clause is not allowed on directive SIMD in OpenMP v4.5, try -fopenmp-version=50
-  !ERROR: At most one IF clause can appear on the SIMD directive
   !ERROR: SIMD is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=50
   !$omp simd if(.true.) if(simd: .false.)
   do i = 1, 10
@@ -260,7 +257,7 @@ program main
   !$omp target if(parallel: .true.)
   !$omp end target
 
-  !ERROR: At most one IF clause can appear on the TARGET directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target if(.true.) if(target: .false.)
   !$omp end target
 
@@ -277,7 +274,7 @@ program main
   !$omp target data map(tofrom: i) if(target: .true.)
   !$omp end target data
 
-  !ERROR: At most one IF clause can appear on the TARGET DATA directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target data map(tofrom: i) if(.true.) if(target data: .false.)
   !$omp end target data
 
@@ -291,7 +288,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target enter data map(to: i) if(.true.) if(target enter data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -304,7 +301,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target exit data map(from: i) if(.true.) if(target exit data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -490,7 +487,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target update to(i) if(.true.) if(target update: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -506,7 +503,7 @@ program main
   !$omp task if(target: .true.)
   !$omp end task
 
-  !ERROR: At most one IF clause can appear on the TASK directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp task if(.true.) if(task: .false.)
   !$omp end task
 
@@ -529,7 +526,7 @@ program main
   end do
   !$omp end taskloop
 
-  !ERROR: At most one IF clause can appear on the TASKLOOP directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp taskloop if(.true.) if(taskloop: .false.)
   do i = 1, 10
   end do
@@ -574,7 +571,6 @@ program main
 
   !ERROR: IF clause is not allowed on directive TEAMS in OpenMP v4.5, try -fopenmp-version=52
   !ERROR: IF clause is not allowed on directive TEAMS in OpenMP v4.5, try -fopenmp-version=52
-  !ERROR: At most one IF clause can appear on the TEAMS directive
   !ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
   !$omp teams if(.true.) if(teams: .false.)
   !$omp end teams
@@ -599,7 +595,6 @@ program main
   end do
   !$omp end teams distribute
 
-  !ERROR: At most one IF clause can appear on the TEAMS DISTRIBUTE directive
   !ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v4.5, try -fopenmp-version=52
   !$omp teams distribute if(.true.) if(teams: .true.)
   do i = 1, 10
diff --git a/flang/test/Semantics/OpenMP/if-clause-50.f90 b/flang/test/Semantics/OpenMP/if-clause-50.f90
index 3c385cdad9e65..23d7738949404 100644
--- a/flang/test/Semantics/OpenMP/if-clause-50.f90
+++ b/flang/test/Semantics/OpenMP/if-clause-50.f90
@@ -24,7 +24,7 @@ program main
   end do
   !$omp end distribute parallel do
 
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp distribute parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -72,7 +72,7 @@ program main
   end do
   !$omp end distribute simd
 
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp distribute simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -98,7 +98,7 @@ program main
   end do
   !$omp end do simd
 
-  !ERROR: At most one IF clause can appear on the DO SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp do simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -117,7 +117,7 @@ program main
   !$omp parallel if(target: .true.)
   !$omp end parallel
 
-  !ERROR: At most one IF clause can appear on the PARALLEL directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel if(.true.) if(parallel: .false.)
   !$omp end parallel
 
@@ -140,7 +140,7 @@ program main
   end do
   !$omp end parallel do
 
-  !ERROR: At most one IF clause can appear on the PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -178,7 +178,7 @@ program main
   !$omp parallel sections if(target: .true.)
   !$omp end parallel sections
 
-  !ERROR: At most one IF clause can appear on the PARALLEL SECTIONS directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel sections if(.true.) if(parallel: .false.)
   !$omp end parallel sections
 
@@ -195,7 +195,7 @@ program main
   !$omp parallel workshare if(target: .true.)
   !$omp end parallel workshare
 
-  !ERROR: At most one IF clause can appear on the PARALLEL WORKSHARE directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel workshare if(.true.) if(parallel: .false.)
   !$omp end parallel workshare
 
@@ -218,7 +218,7 @@ program main
   end do
   !$omp end simd
 
-  !ERROR: At most one IF clause can appear on the SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -237,7 +237,7 @@ program main
   !$omp target if(parallel: .true.)
   !$omp end target
 
-  !ERROR: At most one IF clause can appear on the TARGET directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target if(.true.) if(target: .false.)
   !$omp end target
 
@@ -254,7 +254,7 @@ program main
   !$omp target data map(tofrom: i) if(target: .true.)
   !$omp end target data
 
-  !ERROR: At most one IF clause can appear on the TARGET DATA directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target data map(tofrom: i) if(.true.) if(target data: .false.)
   !$omp end target data
 
@@ -268,7 +268,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target enter data map(to: i) if(.true.) if(target enter data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -281,7 +281,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target exit data map(from: i) if(.true.) if(target exit data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -463,7 +463,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target update to(i) if(.true.) if(target update: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -479,7 +479,7 @@ program main
   !$omp task if(target: .true.)
   !$omp end task
 
-  !ERROR: At most one IF clause can appear on the TASK directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp task if(.true.) if(task: .false.)
   !$omp end task
 
@@ -502,7 +502,7 @@ program main
   end do
   !$omp end taskloop
 
-  !ERROR: At most one IF clause can appear on the TASKLOOP directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp taskloop if(.true.) if(taskloop: .false.)
   do i = 1, 10
   end do
@@ -546,7 +546,6 @@ program main
 
   !ERROR: IF clause is not allowed on directive TEAMS in OpenMP v5.0, try -fopenmp-version=52
   !ERROR: IF clause is not allowed on directive TEAMS in OpenMP v5.0, try -fopenmp-version=52
-  !ERROR: At most one IF clause can appear on the TEAMS directive
   !ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v5.0, try -fopenmp-version=52
   !$omp teams if(.true.) if(teams: .false.)
   !$omp end teams
@@ -571,7 +570,6 @@ program main
   end do
   !$omp end teams distribute
 
-  !ERROR: At most one IF clause can appear on the TEAMS DISTRIBUTE directive
   !ERROR: TEAMS is not allowed as 'directive-name-modifier' in OpenMP v5.0, try -fopenmp-version=52
   !$omp teams distribute if(.true.) if(teams: .true.)
   do i = 1, 10
diff --git a/flang/test/Semantics/OpenMP/if-clause.f90 b/flang/test/Semantics/OpenMP/if-clause.f90
index 5e19c78a1ce76..ce11020e50f59 100644
--- a/flang/test/Semantics/OpenMP/if-clause.f90
+++ b/flang/test/Semantics/OpenMP/if-clause.f90
@@ -24,7 +24,7 @@ program main
   end do
   !$omp end distribute parallel do
 
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp distribute parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -72,7 +72,7 @@ program main
   end do
   !$omp end distribute simd
 
-  !ERROR: At most one IF clause can appear on the DISTRIBUTE SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp distribute simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -98,7 +98,7 @@ program main
   end do
   !$omp end do simd
 
-  !ERROR: At most one IF clause can appear on the DO SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp do simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -117,7 +117,7 @@ program main
   !$omp parallel if(target: .true.)
   !$omp end parallel
 
-  !ERROR: At most one IF clause can appear on the PARALLEL directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel if(.true.) if(parallel: .false.)
   !$omp end parallel
 
@@ -140,7 +140,7 @@ program main
   end do
   !$omp end parallel do
 
-  !ERROR: At most one IF clause can appear on the PARALLEL DO directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel do if(.true.) if(parallel: .false.)
   do i = 1, 10
   end do
@@ -178,7 +178,7 @@ program main
   !$omp parallel sections if(target: .true.)
   !$omp end parallel sections
 
-  !ERROR: At most one IF clause can appear on the PARALLEL SECTIONS directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel sections if(.true.) if(parallel: .false.)
   !$omp end parallel sections
 
@@ -195,7 +195,7 @@ program main
   !$omp parallel workshare if(target: .true.)
   !$omp end parallel workshare
 
-  !ERROR: At most one IF clause can appear on the PARALLEL WORKSHARE directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp parallel workshare if(.true.) if(parallel: .false.)
   !$omp end parallel workshare
 
@@ -218,7 +218,7 @@ program main
   end do
   !$omp end simd
 
-  !ERROR: At most one IF clause can appear on the SIMD directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp simd if(.true.) if(simd: .false.)
   do i = 1, 10
   end do
@@ -237,7 +237,7 @@ program main
   !$omp target if(parallel: .true.)
   !$omp end target
 
-  !ERROR: At most one IF clause can appear on the TARGET directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target if(.true.) if(target: .false.)
   !$omp end target
 
@@ -254,7 +254,7 @@ program main
   !$omp target data map(tofrom: i) if(target: .true.)
   !$omp end target data
 
-  !ERROR: At most one IF clause can appear on the TARGET DATA directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target data map(tofrom: i) if(.true.) if(target data: .false.)
   !$omp end target data
 
@@ -268,7 +268,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target enter data map(to: i) if(.true.) if(target enter data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -281,7 +281,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target exit data map(from: i) if(.true.) if(target exit data: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -458,7 +458,7 @@ program main
   !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
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp target update to(i) if(.true.) if(target update: .false.)
 
   ! ----------------------------------------------------------------------------
@@ -474,7 +474,7 @@ program main
   !$omp task if(target: .true.)
   !$omp end task
 
-  !ERROR: At most one IF clause can appear on the TASK directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp task if(.true.) if(task: .false.)
   !$omp end task
 
@@ -497,7 +497,7 @@ program main
   end do
   !$omp end taskloop
 
-  !ERROR: At most one IF clause can appear on the TASKLOOP directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp taskloop if(.true.) if(taskloop: .false.)
   do i = 1, 10
   end do
@@ -535,7 +535,7 @@ program main
   !$omp teams if(target: .true.)
   !$omp end teams
 
-  !ERROR: At most one IF clause can appear on the TEAMS directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp teams if(.true.) if(teams: .false.)
   !$omp end teams
 
@@ -558,7 +558,7 @@ program main
   end do
   !$omp end teams distribute
 
-  !ERROR: At most one IF clause can appear on the TEAMS DISTRIBUTE directive
+  !ERROR: At most one IF clause can apply to each directive constituent
   !$omp teams distribute if(.true.) if(teams: .true.)
   do i = 1, 10
   end do
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 65118c96bc2e8..679a944fc4358 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -761,9 +761,11 @@ def OMP_EndDeclareVariant : Directive<[Spelling<"end declare variant", 1, 52>,
   let languages = OMP_BeginDeclareVariant.languages;
 }
 def OMP_Cancel : Directive<[Spelling<"cancel">]> {
+  let allowedClauses = [
+    VersionedClause<OMPC_If>,
+  ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_CancellationConstructType>,
-    VersionedClause<OMPC_If>,
   ];
   let association = AS_None;
   let category = CA_Executable;
@@ -1074,6 +1076,7 @@ def OMP_Parallel : Directive<[Spelling<"parallel">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
@@ -1081,7 +1084,6 @@ def OMP_Parallel : Directive<[Spelling<"parallel">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
@@ -1168,6 +1170,7 @@ def OMP_Simd : Directive<[Spelling<"simd">]> {
   let allowedClauses = [
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
+    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_NonTemporal, 50>,
@@ -1176,7 +1179,6 @@ def OMP_Simd : Directive<[Spelling<"simd">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Collapse>,
-    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_Order, 50>,
     VersionedClause<OMPC_SafeLen>,
     VersionedClause<OMPC_SimdLen>,
@@ -1215,6 +1217,7 @@ def OMP_Target : Directive<[Spelling<"target">]> {
     VersionedClause<OMPC_Depend>,
     VersionedClause<OMPC_DynGroupprivate, 61>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_HasDeviceAddr, 51>,
     VersionedClause<OMPC_InReduction, 50>,
     VersionedClause<OMPC_IsDevicePtr>,
@@ -1227,7 +1230,6 @@ def OMP_Target : Directive<[Spelling<"target">]> {
     VersionedClause<OMPC_Default, 60>,
     VersionedClause<OMPC_DefaultMap>,
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_OMPX_Bare>,
     VersionedClause<OMPC_OMPX_DynCGroupMem>,
@@ -1239,10 +1241,12 @@ def OMP_Target : Directive<[Spelling<"target">]> {
 }
 def OMP_TargetData : Directive<[Spelling<"target data", 1, 52>,
                                 Spelling<"target_data", 60>]> {
+  let allowedClauses = [
+    VersionedClause<OMPC_If>,
+  ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default, 60>,
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Transparent, 60>,
   ];
   let requiredClauses = [
@@ -1257,10 +1261,10 @@ def OMP_TargetEnterData : Directive<[Spelling<"target enter data", 1, 52>,
                                      Spelling<"target_enter_data", 60>]> {
   let allowedClauses = [
     VersionedClause<OMPC_Depend>,
+    VersionedClause<OMPC_If>,
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_Replayable, 60>,
   ];
@@ -1274,10 +1278,10 @@ def OMP_TargetExitData : Directive<[Spelling<"target exit data", 1, 52>,
                                     Spelling<"target_exit_data", 60>]> {
   let allowedClauses = [
     VersionedClause<OMPC_Depend>,
+    VersionedClause<OMPC_If>,
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_Replayable, 60>,
   ];
@@ -1292,11 +1296,11 @@ def OMP_TargetUpdate : Directive<[Spelling<"target update", 1, 52>,
   let allowedClauses = [
     VersionedClause<OMPC_Depend>,
     VersionedClause<OMPC_From>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_To>,
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_Replayable, 60>,
   ];
@@ -1309,6 +1313,7 @@ def OMP_Task : Directive<[Spelling<"task">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Depend>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_InReduction>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Shared>,
@@ -1317,7 +1322,6 @@ def OMP_Task : Directive<[Spelling<"task">]> {
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Detach, 50>,
     VersionedClause<OMPC_Final>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_Priority>,
     VersionedClause<OMPC_Replayable, 60>,
@@ -1329,10 +1333,12 @@ def OMP_Task : Directive<[Spelling<"task">]> {
   let category = CA_Executable;
 }
 def OMP_Taskgraph : Directive<[Spelling<"taskgraph">]> {
+  let allowedClauses = [
+    VersionedClause<OMPC_If>,
+  ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_GraphId, 60>,
     VersionedClause<OMPC_GraphReset, 60>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoGroup>,
   ];
   let association = AS_Block;
@@ -1351,6 +1357,7 @@ def OMP_TaskLoop : Directive<[Spelling<"taskloop">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
     VersionedClause<OMPC_InReduction>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
@@ -1360,7 +1367,6 @@ def OMP_TaskLoop : Directive<[Spelling<"taskloop">]> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Final>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_NoGroup>,
     VersionedClause<OMPC_Priority>,
@@ -1396,6 +1402,7 @@ def OMP_Teams : Directive<[Spelling<"teams">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_DynGroupprivate, 61>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If, 52>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
@@ -1403,7 +1410,6 @@ def OMP_Teams : Directive<[Spelling<"teams">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If, 52>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_ThreadLimit>,
   ];
@@ -1494,6 +1500,7 @@ def OMP_DistributeParallelDo : Directive<[Spelling<"distribute parallel do">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_Private>,
@@ -1504,7 +1511,6 @@ def OMP_DistributeParallelDo : Directive<[Spelling<"distribute parallel do">]> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DistSchedule>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order, 50>,
@@ -1554,6 +1560,7 @@ def OMP_DistributeParallelFor
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -1564,7 +1571,6 @@ def OMP_DistributeParallelFor
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DistSchedule>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order, 50>,
@@ -1615,6 +1621,7 @@ def OMP_DistributeSimd : Directive<[Spelling<"distribute simd">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_NonTemporal, 50>,
@@ -1625,7 +1632,6 @@ def OMP_DistributeSimd : Directive<[Spelling<"distribute simd">]> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DistSchedule>,
-    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order, 50>,
@@ -1642,6 +1648,7 @@ def OMP_DoSimd : Directive<[Spelling<"do simd">]> {
   let allowedClauses = [
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_Private>,
@@ -1649,7 +1656,6 @@ def OMP_DoSimd : Directive<[Spelling<"do simd">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Collapse>,
-    VersionedClause<OMPC_If, 50>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_Order, 50>,
     VersionedClause<OMPC_Ordered>,
@@ -1700,6 +1706,7 @@ def OMP_target_loop : Directive<[Spelling<"target loop">]> {
     VersionedClause<OMPC_Depend>,
     VersionedClause<OMPC_DynGroupprivate, 61>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_IsDevicePtr>,
     VersionedClause<OMPC_HasDeviceAddr, 51>,
     VersionedClause<OMPC_LastPrivate>,
@@ -1716,7 +1723,6 @@ def OMP_target_loop : Directive<[Spelling<"target loop">]> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_DefaultMap>,
     VersionedClause<OMPC_Device>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NoWait>,
     VersionedClause<OMPC_OMPX_DynCGroupMem>,
     VersionedClause<OMPC_Order>,
@@ -1729,6 +1735,7 @@ def OMP_MaskedTaskloop : Directive<[Spelling<"masked taskloop">]> {
   let allowedClauses = [
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_InReduction>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Private>,
@@ -1741,7 +1748,6 @@ def OMP_MaskedTaskloop : Directive<[Spelling<"masked taskloop">]> {
     VersionedClause<OMPC_Filter>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_NoGroup>,
     VersionedClause<OMPC_NumTasks>,
@@ -1756,6 +1762,7 @@ def OMP_MaskedTaskloopSimd : Directive<[Spelling<"masked taskloop simd">]> {
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_InReduction>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
@@ -1770,7 +1777,6 @@ def OMP_MaskedTaskloopSimd : Directive<[Spelling<"masked taskloop simd">]> {
     VersionedClause<OMPC_Filter>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_NoGroup>,
     VersionedClause<OMPC_NumTasks>,
@@ -1787,6 +1793,7 @@ def OMP_MasterTaskloop : Directive<[Spelling<"master taskloop">]> {
   let allowedClauses = [
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_InReduction>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Private>,
@@ -1798,7 +1805,6 @@ def OMP_MasterTaskloop : Directive<[Spelling<"master taskloop">]> {
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_NoGroup>,
     VersionedClause<OMPC_NumTasks>,
@@ -1813,6 +1819,7 @@ def OMP_MasterTaskloopSimd : Directive<[Spelling<"master taskloop simd">]> {
     VersionedClause<OMPC_Aligned>,
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_InReduction>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
@@ -1826,7 +1833,6 @@ def OMP_MasterTaskloopSimd : Directive<[Spelling<"master taskloop simd">]> {
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_NoGroup>,
     VersionedClause<OMPC_NumTasks>,
@@ -1844,6 +1850,7 @@ def OMP_ParallelDo : Directive<[Spelling<"parallel do">]> {
     VersionedClause<OMPC_Allocate, 50>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_Private>,
@@ -1853,7 +1860,6 @@ def OMP_ParallelDo : Directive<[Spelling<"parallel do">]> {
   let allowedOnceClauses = [
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order, 50>,
@@ -1962,6 +1968,7 @@ def OMP_parallel_loop : Directive<[Spelling<"parallel loop">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -1972,7 +1979,6 @@ def OMP_parallel_loop : Directive<[Spelling<"parallel loop">]> {
     VersionedClause<OMPC_Bind, 50>,
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_Order>,
@@ -2010,6 +2016,7 @@ def OMP_ParallelMaskedTaskloop
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -2022,7 +2029,6 @@ def OMP_ParallelMaskedTaskloop
     VersionedClause<OMPC_Filter>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NoGroup>,
@@ -2043,6 +2049,7 @@ def OMP_ParallelMaskedTaskloopSimd
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_NonTemporal, 50>,
@@ -2057,7 +2064,6 @@ def OMP_ParallelMaskedTaskloopSimd
     VersionedClause<OMPC_Filter>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NoGroup>,
@@ -2079,6 +2085,7 @@ def OMP_ParallelMaster : Directive<[Spelling<"parallel master">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
@@ -2086,7 +2093,6 @@ def OMP_ParallelMaster : Directive<[Spelling<"parallel master">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
@@ -2101,6 +2107,7 @@ def OMP_ParallelMasterTaskloop
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -2112,7 +2119,6 @@ def OMP_ParallelMasterTaskloop
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NoGroup>,
@@ -2133,6 +2139,7 @@ def OMP_ParallelMasterTaskloopSimd
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_Linear>,
     VersionedClause<OMPC_NonTemporal, 50>,
@@ -2146,7 +2153,6 @@ def OMP_ParallelMasterTaskloopSimd
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_Final>,
     VersionedClause<OMPC_GrainSize>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Mergeable>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NoGroup>,
@@ -2168,6 +2174,7 @@ def OMP_ParallelSections : Directive<[Spelling<"parallel sections">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -2176,7 +2183,6 @@ def OMP_ParallelSections : Directive<[Spelling<"parallel sections">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
@@ -2190,13 +2196,13 @@ def OMP_ParallelWorkshare : Directive<[Spelling<"parallel workshare">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_Copyin>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
     VersionedClause<OMPC_Shared>,
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_Message, 60>,
     VersionedClause<OMPC_NumThreads>,
     VersionedClause<OMPC_ProcBind>,
@@ -2833,6 +2839,7 @@ def OMP_TeamsDistribute : Directive<[Spelling<"teams distribute">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_DynGroupprivate, 61>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
@@ -2843,7 +2850,6 @@ def OMP_TeamsDistribute : Directive<[Spelling<"teams distribute">]> {
     VersionedClause<OMPC_Collapse>,
     VersionedClause<OMPC_Default>,
     VersionedClause<OMPC_DistSchedule>,
-    VersionedClause<OMPC_If>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_Order, 50>,
     VersionedClause<OMPC_ThreadLimit>,
@@ -3016,6 +3022,7 @@ def OMP_TeamsWorkdistribute : Directive<[Spelling<"teams workdistribute">]> {
   let allowedClauses = [
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If, 52>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,
     VersionedClause<OMPC_Reduction>,
@@ -3023,7 +3030,6 @@ def OMP_TeamsWorkdistribute : Directive<[Spelling<"teams workdistribute">]> {
   ];
   let allowedOnceClauses = [
     VersionedClause<OMPC_Default>,
-    VersionedClause<OMPC_If, 52>,
     VersionedClause<OMPC_NumTeams>,
     VersionedClause<OMPC_ThreadLimit>,
   ];
@@ -3036,6 +3042,7 @@ def OMP_teams_loop : Directive<[Spelling<"teams loop">]> {
     VersionedClause<OMPC_Allocate>,
     VersionedClause<OMPC_DynGroupprivate, 61>,
     VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_If, 52>,
     VersionedClause<OMPC_LastPrivate>,
     VersionedClause<OMPC_OMPX_Attribute>,
     VersionedClause<OMPC_Private>,

>From 5a90c781c43c97a22bf05551a8a4166b492ebc8a Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 23 Jun 2026 12:47:00 -0500
Subject: [PATCH 2/2] Add testcase for -fopenmp-version=60

---
 flang/test/Semantics/OpenMP/if-clause-60.f90 | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 flang/test/Semantics/OpenMP/if-clause-60.f90

diff --git a/flang/test/Semantics/OpenMP/if-clause-60.f90 b/flang/test/Semantics/OpenMP/if-clause-60.f90
new file mode 100644
index 0000000000000..47cd41cf6ce46
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/if-clause-60.f90
@@ -0,0 +1,12 @@
+!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60
+
+subroutine f
+! Allowed in 6.0
+  !$omp taskgraph if(.true.)
+  !$omp end taskgraph
+
+!ERROR: PARALLEL LOOP is not a constituent of the TEAMS LOOP directive
+  !$omp teams loop if(parallel loop: .false.)
+  do i = 1, 10
+  end do
+end



More information about the flang-commits mailing list