[flang-commits] [flang] [flang][OpenMP] Reject standalone block-associated variants (PR #213255)

via flang-commits flang-commits at lists.llvm.org
Fri Jul 31 04:57:10 PDT 2026


https://github.com/ssenthilnathan3 created https://github.com/llvm/llvm-project/pull/213255

standalone OpenMP metadirectives are `Association::none`, so they must not select a block-associated directive variant such as `parallel`.

this adds a semantic check in `check-omp-variant.cpp` to diagnose this case when the selected variant is actually selectable on the current target and a regression test in `flang/test/Semantics/OpenMP/metadirective-common.f90` for the issue reproducer.

closes #212635

>From ff602bc7f23cc0177d32cb3e6b268d7de5e7d20c Mon Sep 17 00:00:00 2001
From: "ssenthil1490 at gmail.com" <ssenthil1490 at gmail.com>
Date: Fri, 31 Jul 2026 17:17:01 +0530
Subject: [PATCH] [flang][OpenMP] Reject standalone block-associated variants

---
 flang/lib/Semantics/check-omp-variant.cpp         | 15 +++++++++++++++
 .../Semantics/OpenMP/metadirective-common.f90     |  9 +++++++++
 .../Semantics/OpenMP/metadirective-loop-nest.f90  |  2 +-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 0f8daf84d25ec..0bb799861ac33 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -716,8 +716,10 @@ void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) {
   llvm::omp::Directive dirId{x.DirId()};
   bool checkDefaultNoneInAssociatedLoop{
       GetDirectiveNest(MetadirectiveNest) != 0};
+  bool isDelimited{false};
   if (const parser::OpenMPConstruct *meta{GetCurrentConstruct()}) {
     if (parser::Unwrap<parser::OmpDelimitedMetadirectiveDirective>(meta->u)) {
+      isDelimited = true;
       checkDefaultNoneInAssociatedLoop = false;
       unsigned version{context_.langOptions().OpenMPVersion};
       switch (llvm::omp::getDirectiveAssociation(dirId)) {
@@ -735,6 +737,19 @@ void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) {
       }
     }
   }
+  if (!isDelimited && checkDefaultNoneInAssociatedLoop) {
+    OmpVariantMatchContext matchContext{context_};
+    if (currentWhenSelector_ &&
+        MayVariantBeSelected(currentWhenSelector_, context_, matchContext) &&
+        llvm::omp::getDirectiveAssociation(dirId) ==
+            llvm::omp::Association::Block) {
+      unsigned version{context_.langOptions().OpenMPVersion};
+      context_.Say(x.DirName().source,
+          "A standalone %s cannot contain a block-associated directive"_err_en_US,
+          parser::omp::GetUpperName(
+              llvm::omp::Directive::OMPD_metadirective, version));
+    }
+  }
 
   PushContextAndClauseSets(
       std::get<parser::OmpDirectiveName>(x.t).source, dirId);
diff --git a/flang/test/Semantics/OpenMP/metadirective-common.f90 b/flang/test/Semantics/OpenMP/metadirective-common.f90
index 3d219e9d9495a..04365b9d35195 100644
--- a/flang/test/Semantics/OpenMP/metadirective-common.f90
+++ b/flang/test/Semantics/OpenMP/metadirective-common.f90
@@ -45,3 +45,12 @@ subroutine f05
 !ERROR: 'context-selector' modifier is required
   !$omp & when(nothing)
 end
+
+! A standalone metadirective cannot contain a block-associated directive
+subroutine f06(x)
+  integer :: x
+  !$omp metadirective &
+!ERROR: A standalone METADIRECTIVE cannot contain a block-associated directive
+  !$omp & when(implementation={vendor(llvm)}: parallel num_threads(4)) otherwise(nothing)
+  x = 1
+end
diff --git a/flang/test/Semantics/OpenMP/metadirective-loop-nest.f90 b/flang/test/Semantics/OpenMP/metadirective-loop-nest.f90
index 9a19cbcc916a1..3982ee0f7cb9e 100644
--- a/flang/test/Semantics/OpenMP/metadirective-loop-nest.f90
+++ b/flang/test/Semantics/OpenMP/metadirective-loop-nest.f90
@@ -177,7 +177,7 @@ module no_loop_before_another_metadirective
   implicit none
   !ERROR: This construct should contain a DO-loop or a loop-nest-generating construct
   !$omp metadirective when(implementation={vendor(llvm)}: do) default(nothing)
-  !$omp metadirective when(implementation={vendor(llvm)}: parallel) default(nothing)
+  !$omp metadirective when(implementation={vendor(llvm)}: nothing) default(nothing)
 end module
 
 ! A loop in the enclosing subprogram cannot satisfy a variant from an



More information about the flang-commits mailing list