https://gcc.gnu.org/g:78c615d3c43991cae685c634b36aa97b434ba8cc
commit 78c615d3c43991cae685c634b36aa97b434ba8cc Author: Sandra Loosemore <[email protected]> Date: Wed Jul 1 23:33:59 2026 +0000 OpenMP: Reprocess expanded clauses after 'declare mapper' instantiation This patch reprocesses expanded clauses after 'declare mapper' instantiation -- checking things such as duplicated clauses, illegal use of strided accesses, and so forth. This includes parts of OG15 commit 9c46ffc2964. Tobias has refactored the code differently (using different names for the refactored functions) on mainline for GCC 17; I have previously applied versions of those patches to OG16, and this is the leftover parts from OG15 adapted to use the new names, etc. gcc/fortran/ * gfortran.h (gfc_omp_clauses): Add NS field. * openmp.cc (resolve_omp_clauses): Record namespace containing clauses. (resolve_omp_mapper_clauses): New function. (gfc_resolve_omp_directive): Add NS parameter to resolve_omp_clauses calls. (gfc_omp_instantiate_mappers): Call resolve_omp_mapper_clauses if we instantiate any mappers. gcc/testsuite/ * gfortran.dg/gomp/declare-mapper-26.f90: New test. * gfortran.dg/gomp/declare-mapper-29.f90: New test. Co-Authored-By: Julian Brown <[email protected]> Co-Authored-By: Tobias Burnus <[email protected]> Diff: --- gcc/fortran/gfortran.h | 1 + gcc/fortran/openmp.cc | 81 +++++++++++++++++++--- .../gfortran.dg/gomp/declare-mapper-26.f90 | 28 ++++++++ .../gfortran.dg/gomp/declare-mapper-29.f90 | 22 ++++++ 4 files changed, 122 insertions(+), 10 deletions(-) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 824ae37dedbf..f0a3b0eb0297 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1685,6 +1685,7 @@ typedef struct gfc_omp_clauses struct gfc_omp_assumptions *assume; struct gfc_expr_list *sizes_list; const char *critical_name; + gfc_namespace *ns; enum gfc_omp_default_sharing default_sharing; enum gfc_omp_atomic_op atomic_op; enum gfc_omp_defaultmap defaultmap[OMP_DEFAULTMAP_CAT_NUM]; diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 655586ec99b8..817eda344790 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -9836,6 +9836,7 @@ resolve_omp_clauses_aff_dep_map_cache (gfc_code *code, gfc_array_ref *ar = &lastslice->u.ar; for (i = 0; i < ar->dimen; i++) if (ar->stride[i] + && code && code->op != EXEC_OACC_UPDATE && code->op != EXEC_OMP_TARGET_UPDATE) { @@ -10021,7 +10022,13 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, if (omp_clauses == NULL) return; - if (ns == NULL) + /* If we're invoking any declared mappers as a result of these clauses, + we may need to know the namespace their directive was originally + defined within in order to resolve clauses again after substitution. + Record it here. */ + if (ns) + omp_clauses->ns = ns; + else ns = gfc_current_ns; check_omp_clauses_dupl_syms (code, omp_clauses, openacc); @@ -10280,22 +10287,23 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, && n->sym->result == n->sym && n->sym->attr.function) { - if (ns->proc_name == n->sym - || (ns->parent && ns->parent->proc_name == n->sym)) + if (gfc_current_ns->proc_name == n->sym + || (gfc_current_ns->parent + && gfc_current_ns->parent->proc_name == n->sym)) continue; - if (ns->proc_name->attr.entry_master) + if (gfc_current_ns->proc_name->attr.entry_master) { - gfc_entry_list *el = ns->entries; + gfc_entry_list *el = gfc_current_ns->entries; for (; el; el = el->next) if (el->sym == n->sym) break; if (el) continue; } - if (ns->parent - && ns->parent->proc_name->attr.entry_master) + if (gfc_current_ns->parent + && gfc_current_ns->parent->proc_name->attr.entry_master) { - gfc_entry_list *el = ns->parent->entries; + gfc_entry_list *el = gfc_current_ns->parent->entries; for (; el; el = el->next) if (el->sym == n->sym) break; @@ -11176,6 +11184,48 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, } +/* This very simplified version of the above function is for use after mapper + instantiation. It avoids dealing with anything other than basic + verification for map/to/from clauses. */ + +static void +resolve_omp_mapper_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, + gfc_namespace *ns ATTRIBUTE_UNUSED) +{ + gfc_omp_namelist *n; + enum gfc_omp_list_type list; + + check_omp_clauses_dupl_syms (code, omp_clauses, false); + + for (list = OMP_LIST_MAP; list <= OMP_LIST_FROM; + list = gfc_omp_list_type (list + 1)) + if ((n = omp_clauses->lists[list]) != NULL) + { + const char *name = NULL; + switch (list) + { + case OMP_LIST_MAP: + if (name == NULL) + name = "MAP"; + /* Fallthrough. */ + case OMP_LIST_TO: + if (name == NULL) + name = "TO"; + /* Fallthrough. */ + case OMP_LIST_FROM: + if (name == NULL) + name = "FROM"; + for (; n != NULL; n = n->next) + resolve_omp_clauses_aff_dep_map_cache (code, n, name, list, + omp_clauses, false); + break; + default: + ; + } + } +} + + /* Return true if SYM is ever referenced in EXPR except in the SE node. */ static bool @@ -13840,11 +13890,11 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_WORKSHARE: case EXEC_OMP_DEPOBJ: if (code->ext.omp_clauses) - resolve_omp_clauses (code, code->ext.omp_clauses, NULL); + resolve_omp_clauses (code, code->ext.omp_clauses, ns); break; case EXEC_OMP_TARGET_UPDATE: if (code->ext.omp_clauses) - resolve_omp_clauses (code, code->ext.omp_clauses, NULL); + resolve_omp_clauses (code, code->ext.omp_clauses, ns); if (code->ext.omp_clauses == NULL || (code->ext.omp_clauses->lists[OMP_LIST_TO] == NULL && code->ext.omp_clauses->lists[OMP_LIST_FROM] == NULL)) @@ -14511,6 +14561,7 @@ gfc_omp_instantiate_mappers (gfc_code *code ATTRIBUTE_UNUSED, gfc_omp_clauses *c { gfc_omp_namelist *clause = clauses->lists[list]; gfc_omp_namelist **clausep = &clauses->lists[list]; + bool invoked_mappers = false; for (; clause; clause = *clausep) { @@ -14537,10 +14588,20 @@ gfc_omp_instantiate_mappers (gfc_code *code ATTRIBUTE_UNUSED, gfc_omp_clauses *c clausep = gfc_omp_instantiate_mapper (clausep, clause, outer_map_op, clause->u3.udm->udm, cd, list); *clausep = clause->next; + invoked_mappers = true; } else clausep = &clause->next; } + + if (invoked_mappers) + { + gfc_namespace *old_ns = gfc_current_ns; + if (clauses->ns) + gfc_current_ns = clauses->ns; + resolve_omp_mapper_clauses (code, clauses, gfc_current_ns); + gfc_current_ns = old_ns; + } } /* Resolve !$omp declare mapper constructs. */ diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-mapper-26.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-mapper-26.f90 new file mode 100644 index 000000000000..c408b37f5a97 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/declare-mapper-26.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } + +type t +integer, allocatable :: arr(:) +end type t + +!$omp declare mapper(even: T :: tv) map(tv%arr(2::2)) + +type(t) :: var + +allocate(var%arr(100)) + +var%arr = 0 + +! You can't do this, the mapper specifies a noncontiguous access. +!$omp target enter data map(mapper(even), to: var) +! { dg-error {Stride should not be specified for array section in MAP clause} "" { target *-*-* } .-1 } + +var%arr = 1 + +! But this is fine. (Re-enabled by later patch.) +!!$omp target update to(mapper(even): var) + +! As 'enter data'. +!$omp target exit data map(mapper(even), delete: var) +! { dg-error {Stride should not be specified for array section in MAP clause} "" { target *-*-* } .-1 } + +end diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-mapper-29.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-mapper-29.f90 new file mode 100644 index 000000000000..e2039e80e579 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/declare-mapper-29.f90 @@ -0,0 +1,22 @@ +! { dg-do compile } + +! Check duplicate clause detection after mapper expansion. + +type t +integer :: x +end type t + +real(4) :: unrelated +type(t) :: tvar + +!$omp declare mapper (t :: var) map(unrelated) map(var%x) + +tvar%x = 0 +unrelated = 5 + +!$omp target firstprivate(unrelated) map(tofrom: tvar) +! { dg-error "Symbol .unrelated. present on both data and map clauses" "" { target *-*-* } .-1 } +tvar%x = unrelated +!$omp end target + +end
