https://gcc.gnu.org/g:4c60b8e89c5d01e42bce348db1940ff3efd70402
commit 4c60b8e89c5d01e42bce348db1940ff3efd70402 Author: Tobias Burnus <[email protected]> Date: Mon Oct 19 15:50:44 2026 +0200 walk_tree_1: Fix tree-walking of OMP_METADIRECTIVE [PR128001] OpenMP's metadirective uses TREE_PURPOSE of TREE_LIST, which is not walked by default, leading to a missing 'omp declare target' attribute. Solution: Handle OMP_METADIRECTIVE explicitly. PR middle-end/128001 gcc/ChangeLog: * tree.cc (walk_tree_1): Add comment; handle OMP_METADIRECTIVE explicitly. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/metadirective-14.f90: New test. (cherry picked from commit 4a44f6b8991274c03e5bfee2c3ba3be343dce35b) Diff: --- .../gfortran.dg/gomp/metadirective-14.f90 | 43 ++++++++++++++++++++++ gcc/tree.cc | 13 ++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gfortran.dg/gomp/metadirective-14.f90 b/gcc/testsuite/gfortran.dg/gomp/metadirective-14.f90 new file mode 100644 index 000000000000..a1a09a4f6d4e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/metadirective-14.f90 @@ -0,0 +1,43 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-gimple" } +! +! PR middle-end/128001 +! +! Based on OpenMP example-document's metadirective.2.f90 +! + +! Ensure 'work_on_chunk' is marked as 'omp declare target' +! { dg-final { scan-tree-dump "__attribute__\\(\\(omp declare target\\)\\)\[\\r\\n\]+__attribute__\\(\\(fn spec \\(\"\\. w w \"\\)\\)\\)\[\\r\\n\]+void work_on_chunk" "gimple" } } + +program main + !use omp_lib + implicit none + integer, parameter :: N = 1000 + external :: work_on_chunk + integer :: i, idev + + do idev = 0, 0 ! omp_get_num_devices() - 1 + + !$omp target device(idev) + !$omp begin metadirective & + !$omp& when( implementation={vendor(nvidia)}, & + !$omp& device={arch("kepler")}: & + !$omp& teams num_teams(512) thread_limit(32) ) & + !$omp& when( implementation={vendor(amd)}, & + !$omp& device={arch("fiji" )}: & + !$omp& teams num_teams(512) thread_limit(64) ) & + !$omp& otherwise( teams ) + !$omp distribute parallel do + do i = 1, N + call work_on_chunk(idev, i) + end do + !$omp end metadirective + !$omp end target + + end do + +end program + +subroutine work_on_chunk(idev, i) + integer :: i, idev +end subroutine diff --git a/gcc/tree.cc b/gcc/tree.cc index a7dbaf61f115..134f96cea746 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -11717,7 +11717,8 @@ walk_type_fields (tree type, walk_tree_fn func, void *data, called with the DATA and the address of each sub-tree. If FUNC returns a non-NULL value, the traversal is stopped, and the value returned by FUNC is returned. If PSET is non-NULL it is used to record the nodes visited, - and to avoid visiting a node more than once. */ + and to avoid visiting a node more than once. + Note that TREE_PURPOSE is not walked. */ tree walk_tree_1 (tree *tp, walk_tree_fn func, void *data, @@ -11874,6 +11875,16 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); } + case OMP_METADIRECTIVE: + /* Handle this explicitly as TREE_PURPOSE is usually not walked. */ + for (tree t2 = OMP_METADIRECTIVE_VARIANTS (t); t2; t2 = TREE_CHAIN (t2)) + { + WALK_SUBTREE (OMP_METADIRECTIVE_VARIANT_SELECTOR (t2)); + WALK_SUBTREE (OMP_METADIRECTIVE_VARIANT_DIRECTIVE (t2)); + WALK_SUBTREE (OMP_METADIRECTIVE_VARIANT_BODY (t2)); + } + break; + case TARGET_EXPR: { int i, len;
