[flang-commits] [flang] [flang][OpenMP] Reject standalone block-associated variants (PR #213255)
via flang-commits
flang-commits at lists.llvm.org
Mon Aug 3 21:56:14 PDT 2026
https://github.com/ssenthilnathan3 updated https://github.com/llvm/llvm-project/pull/213255
>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 1/2] [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
>From aa49bdb8dee27042bcb0b4598750c5dc20a92810 Mon Sep 17 00:00:00 2001
From: "ssenthil1490 at gmail.com" <ssenthil1490 at gmail.com>
Date: Tue, 4 Aug 2026 10:23:59 +0530
Subject: [PATCH 2/2] Add regression test for standalone block-associated
variant check
---
flang/lib/Semantics/check-omp-variant.cpp | 20 +++++++++----------
.../Parser/OpenMP/metadirective-dirspec.f90 | 11 ++++++----
.../Semantics/OpenMP/metadirective-common.f90 | 10 ++++++++++
3 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 0bb799861ac33..c3f09b48cc19b 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -738,16 +738,16 @@ 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));
+ if (llvm::omp::getDirectiveAssociation(dirId) ==
+ llvm::omp::Association::Block) {
+ OmpVariantMatchContext matchContext{context_};
+ if (MayVariantBeSelected(currentWhenSelector_, context_, matchContext)) {
+ 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));
+ }
}
}
diff --git a/flang/test/Parser/OpenMP/metadirective-dirspec.f90 b/flang/test/Parser/OpenMP/metadirective-dirspec.f90
index d63db6c93cf40..b4adc93f45198 100644
--- a/flang/test/Parser/OpenMP/metadirective-dirspec.f90
+++ b/flang/test/Parser/OpenMP/metadirective-dirspec.f90
@@ -31,13 +31,16 @@ subroutine f00(x)
subroutine f01(x)
integer :: x
- !$omp metadirective when(user={condition(.true.)}: &
+ ! condition(.false.) prevents block-associated variant from being
+ ! selected so the semantic check does not fire, while still testing
+ ! directive-specification parsing with an argument and ResolveCriticalName.
+ !$omp metadirective when(user={condition(.false.)}: &
!$omp & critical(x))
end
!UNPARSE: SUBROUTINE f01 (x)
!UNPARSE: INTEGER x
-!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: CRITICAL(x))
+!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.false._4)}: CRITICAL(x))
!UNPARSE: END SUBROUTINE
!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective
@@ -47,9 +50,9 @@ subroutine f01(x)
!PARSE-TREE: | | | OmpTraitSelector
!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition
!PARSE-TREE: | | | | Properties
-!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4'
+!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.false._4'
!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant
-!PARSE-TREE: | | | | | | | bool = 'true'
+!PARSE-TREE: | | | | | | | bool = 'false'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = critical
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpObject -> Designator -> DataRef -> Name = 'x'
diff --git a/flang/test/Semantics/OpenMP/metadirective-common.f90 b/flang/test/Semantics/OpenMP/metadirective-common.f90
index 04365b9d35195..77678413351c0 100644
--- a/flang/test/Semantics/OpenMP/metadirective-common.f90
+++ b/flang/test/Semantics/OpenMP/metadirective-common.f90
@@ -54,3 +54,13 @@ subroutine f06(x)
!$omp & when(implementation={vendor(llvm)}: parallel num_threads(4)) otherwise(nothing)
x = 1
end
+
+! The fallback (otherwise/default) variant is also checked
+subroutine f07(x)
+ integer :: x
+ !$omp metadirective &
+ !$omp & when(implementation={vendor(llvm)}: nothing) &
+!ERROR: A standalone METADIRECTIVE cannot contain a block-associated directive
+ !$omp & otherwise(parallel num_threads(4))
+ x = 1
+end
More information about the flang-commits
mailing list