This patch fixes "exit data" for (C++) reference-to-pointer struct components with array sections, such as:
struct S { int *&ptr; [...] }; ... #pragma omp target exit data map(from: str->ptr, str->ptr[0:n]) Such exits need two "detach" operations. We need to unmap both the pointer and the slice. That idiom is recognized by omp_resolve_clause_dependencies, but before omp_build_struct_sibling_lists finishes the resulting mapping nodes are represented like this: GOMP_MAP_FROM GOMP_MAP_DETACH GOMP_MAP_ATTACH_DETACH And at the moment, that won't be recognized as a single mapping group as it should be. This patch fixes that. (This is covered by a test case added in later patches in this series, e.g. libgomp/testsuite/libgomp.c++/array-shaping-8.C.) 2023-07-03 Julian Brown <jul...@codesourcery.com> gcc/ * gimplify.cc (omp_get_attachment): Handle GOMP_MAP_DETACH here. (omp_group_last): Handle *, GOMP_MAP_DETACH, GOMP_MAP_ATTACH_DETACH groups for "exit data" of reference-to-pointer component array sections. (omp_group_base): Handle GOMP_MAP_DETACH. --- gcc/gimplify.cc | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 20aba45110f..6280eb7e028 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -9171,6 +9171,7 @@ omp_get_attachment (omp_mapping_group *grp) case GOMP_MAP_ATTACH_DETACH: case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION: + case GOMP_MAP_DETACH: return OMP_CLAUSE_DECL (node); default: @@ -9247,23 +9248,43 @@ omp_group_last (tree *start_p) == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION) || (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION) + || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER || omp_map_clause_descriptor_p (nc))) { - grp_last_p = &OMP_CLAUSE_CHAIN (c); - c = nc; tree nc2 = OMP_CLAUSE_CHAIN (nc); + if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH) + { + /* In the specific case we're doing "exit data" on an array + slice of a reference-to-pointer struct component, we will see + DETACH followed by ATTACH_DETACH here. We want to treat that + as a single group. In other cases DETACH might represent a + stand-alone "detach" clause, so we don't want to consider + that part of the group. */ + if (nc2 + && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH) + goto consume_two_nodes; + else + break; + } if (nc2 && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION) && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH) { + consume_two_nodes: grp_last_p = &OMP_CLAUSE_CHAIN (nc); c = nc2; - nc2 = OMP_CLAUSE_CHAIN (nc2); + nc = OMP_CLAUSE_CHAIN (nc2); + } + else + { + grp_last_p = &OMP_CLAUSE_CHAIN (c); + c = nc; + nc = nc2; } - nc = nc2; } break; @@ -9416,6 +9437,7 @@ omp_group_base (omp_mapping_group *grp, unsigned int *chained, case GOMP_MAP_ALWAYS_POINTER: case GOMP_MAP_ATTACH_DETACH: case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION: + case GOMP_MAP_DETACH: return *grp->grp_start; default: -- 2.25.1