Skip to content

Conversation

@bhandarkar-pranav
Copy link
Contributor

This patch enhances the semantics test for checking that teams directives are strictly nested inside target directives.

Fixes #153173

This patch enhances the semantics test for checking that teams directives
are strictly nested inside target directives.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:openmp flang:semantics labels Nov 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 17, 2025

@llvm/pr-subscribers-flang-openmp

@llvm/pr-subscribers-flang-semantics

Author: Pranav Bhandarkar (bhandarkar-pranav)

Changes

This patch enhances the semantics test for checking that teams directives are strictly nested inside target directives.

Fixes #153173


Full diff: https://github.com/llvm/llvm-project/pull/168437.diff

3 Files Affected:

  • (modified) flang/lib/Semantics/check-omp-loop.cpp (+9)
  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+7)
  • (added) flang/test/Semantics/OpenMP/target-teams-nesting.f90 (+22)
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<parser::OpenMPLoopConstruct>(
+                         &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

@github-actions
Copy link

🐧 Linux x64 Test Results

  • 4059 tests passed
  • 202 tests skipped

counter = counter+1
!$omp end target

print '("Result: "I0)', counter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no need for the print statement here.

Comment on lines +265 to +268
if (CurrentDirectiveIsNested() &&
llvm::omp::topTeamsSet.test(GetContext().directive) &&
GetContextParent().directive == llvm::omp::Directive::OMPD_target &&
!GetDirectiveNest(TargetBlockOnlyTeams)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly relevant to this PR since a similar check is used somewhere else. But for the following example:

!$omp target ....
  !$omp teams ....
    !$omp target ....
      .... some statement ....
      !$omp teams ....
        ....
....

Would the semantic check trigger in this case? I think it won't since GetDirectiveNest(TargetBlockOnlyTeams) will return a non-zero result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:openmp flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing Flang semantics check causes ICE

3 participants