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

Reply via email to