From fb029d24c77130945d68ba4247121e397f3e81c6 Mon Sep 17 00:00:00 2001 From: Pranav Bhandarkar Date: Mon, 17 Nov 2025 14:42:29 -0600 Subject: [PATCH 1/3] [Flang] - Enhance testing for strictly-nested teams in target regions. This patch enhances the semantics test for checking that teams directives are strictly nested inside target directives. --- flang/lib/Semantics/check-omp-loop.cpp | 9 ++++++++ flang/lib/Semantics/check-omp-structure.cpp | 7 ++++++ .../Semantics/OpenMP/target-teams-nesting.f90 | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 flang/test/Semantics/OpenMP/target-teams-nesting.f90 diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp index aaaa2d6e78280..09005e3076d03 100644 --- a/flang/lib/Semantics/check-omp-loop.cpp +++ b/flang/lib/Semantics/check-omp-loop.cpp @@ -262,6 +262,15 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { EnterDirectiveNest(SIMDNest); } + if (CurrentDirectiveIsNested() && + llvm::omp::allTeamsSet.test(GetContext().directive) && + GetContextParent().directive == llvm::omp::Directive::OMPD_target && + !GetDirectiveNest(TargetBlockOnlyTeams)) { + context_.Say(GetContextParent().directiveSource, + "TARGET construct with nested TEAMS region contains statements or " + "directives outside of the TEAMS construct"_err_en_US); + } + // Combined target loop constructs are target device constructs. Keep track of // whether any such construct has been visited to later check that REQUIRES // directives for target-related options don't appear after them. diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 37b4404cc598f..472208949abad 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5215,6 +5215,13 @@ bool OmpStructureChecker::CheckTargetBlockOnlyTeams( if (dirId == llvm::omp::Directive::OMPD_teams) { nestedTeams = true; } + } else if (const auto *ompLoopConstruct{ + std::get_if( + &ompConstruct->u)}) { + llvm::omp::Directive dirId{ompLoopConstruct->BeginDir().DirId()}; + if (llvm::omp::allTeamsSet.test(dirId)) { + nestedTeams = true; + } } } diff --git a/flang/test/Semantics/OpenMP/target-teams-nesting.f90 b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 new file mode 100644 index 0000000000000..59786d4f9e397 --- /dev/null +++ b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 @@ -0,0 +1,22 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp + +program main + implicit none + integer, parameter :: n = 100 + integer, parameter :: expected = n+2 + integer :: i + integer :: counter + + counter = 0 + !ERROR: TARGET construct with nested TEAMS region contains statements or directives outside of the TEAMS construct + !$omp target map(tofrom:counter) + counter = counter+1 + !$omp teams distribute reduction(+:counter) + do i=1, n + counter = counter+1 + end do + counter = counter+1 + !$omp end target + + print '("Result: "I0)', counter + end program From 5c76adacac31975deb8552af963dba67b584fb01 Mon Sep 17 00:00:00 2001 From: Pranav Bhandarkar Date: Mon, 17 Nov 2025 14:52:18 -0600 Subject: [PATCH 2/3] use topTeamsSet not allTeamsSet --- flang/lib/Semantics/check-omp-loop.cpp | 2 +- flang/lib/Semantics/check-omp-structure.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp index 09005e3076d03..1cdd17b3a5b81 100644 --- a/flang/lib/Semantics/check-omp-loop.cpp +++ b/flang/lib/Semantics/check-omp-loop.cpp @@ -263,7 +263,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { } if (CurrentDirectiveIsNested() && - llvm::omp::allTeamsSet.test(GetContext().directive) && + llvm::omp::topTeamsSet.test(GetContext().directive) && GetContextParent().directive == llvm::omp::Directive::OMPD_target && !GetDirectiveNest(TargetBlockOnlyTeams)) { context_.Say(GetContextParent().directiveSource, diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 472208949abad..cd67178fe8bf9 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5219,7 +5219,7 @@ bool OmpStructureChecker::CheckTargetBlockOnlyTeams( std::get_if( &ompConstruct->u)}) { llvm::omp::Directive dirId{ompLoopConstruct->BeginDir().DirId()}; - if (llvm::omp::allTeamsSet.test(dirId)) { + if (llvm::omp::topTeamsSet.test(dirId)) { nestedTeams = true; } } From bfac21f5da9595b5634360a0aafa82216554b49a Mon Sep 17 00:00:00 2001 From: Pranav Bhandarkar Date: Thu, 20 Nov 2025 09:52:26 -0600 Subject: [PATCH 3/3] Remove unnecessary print from testcase --- flang/test/Semantics/OpenMP/target-teams-nesting.f90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/flang/test/Semantics/OpenMP/target-teams-nesting.f90 b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 index 59786d4f9e397..c1760afdd7752 100644 --- a/flang/test/Semantics/OpenMP/target-teams-nesting.f90 +++ b/flang/test/Semantics/OpenMP/target-teams-nesting.f90 @@ -17,6 +17,4 @@ program main end do counter = counter+1 !$omp end target - - print '("Result: "I0)', counter end program