https://gcc.gnu.org/g:dbf4c574b92bc692a0380a2b5ee25028321e735f

commit r15-2935-gdbf4c574b92bc692a0380a2b5ee25028321e735f
Author: Andre Vehreschild <ve...@gcc.gnu.org>
Date:   Wed Jul 24 09:39:45 2024 +0200

    Fix Coarray in associate not a coarray. [PR110033]
    
    A coarray used in an associate did not become a coarray in the block of
    the associate.  This patch fixes that and the same also in select type
    statements.
    
            PR fortran/110033
    
    gcc/fortran/ChangeLog:
    
            * class.cc (gfc_is_class_scalar_expr): Coarray refs that ref
            only self, aka this image, are regarded as scalar, too.
            * resolve.cc (resolve_assoc_var): Ignore this image coarray refs
            and do not build a new class type.
            * trans-expr.cc (gfc_get_caf_token_offset): Get the caf token
            from the descriptor for associated variables.
            (gfc_conv_variable): Same.
            (gfc_trans_pointer_assignment): Assign token to temporary
            associate variable, too.
            (gfc_trans_scalar_assign): Add flag that assign is for associate
            and use it to assign the token.
            (is_assoc_assign): Detect that expressions are for associate
            assign.
            (gfc_trans_assignment_1): Treat associate assigns like pointer
            assignments where possible.
            * trans-stmt.cc (trans_associate_var): Set same_class only for
            class-targets.
            * trans.h (gfc_trans_scalar_assign): Add flag to
            trans_scalar_assign for marking associate assignments.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/coarray/associate_1.f90: New test.

Diff:
---
 gcc/fortran/class.cc                              | 38 +++++-----
 gcc/fortran/resolve.cc                            | 40 ++++++++---
 gcc/fortran/trans-expr.cc                         | 87 +++++++++++++++++++----
 gcc/fortran/trans-stmt.cc                         |  2 +-
 gcc/fortran/trans.h                               |  5 +-
 gcc/testsuite/gfortran.dg/coarray/associate_1.f90 | 36 ++++++++++
 6 files changed, 163 insertions(+), 45 deletions(-)

diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index 88fbba2818a..f9e0d416e48 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -379,27 +379,33 @@ gfc_is_class_scalar_expr (gfc_expr *e)
     return false;
 
   /* Is this a class object?  */
-  if (e->symtree
-       && e->symtree->n.sym->ts.type == BT_CLASS
-       && CLASS_DATA (e->symtree->n.sym)
-       && !CLASS_DATA (e->symtree->n.sym)->attr.dimension
-       && (e->ref == NULL
-           || (e->ref->type == REF_COMPONENT
-               && strcmp (e->ref->u.c.component->name, "_data") == 0
-               && e->ref->next == NULL)))
+  if (e->symtree && e->symtree->n.sym->ts.type == BT_CLASS
+      && CLASS_DATA (e->symtree->n.sym)
+      && !CLASS_DATA (e->symtree->n.sym)->attr.dimension
+      && (e->ref == NULL
+         || (e->ref->type == REF_COMPONENT
+             && strcmp (e->ref->u.c.component->name, "_data") == 0
+             && (e->ref->next == NULL
+                 || (e->ref->next->type == REF_ARRAY
+                     && e->ref->next->u.ar.codimen > 0
+                     && e->ref->next->u.ar.dimen == 0
+                     && e->ref->next->next == NULL)))))
     return true;
 
   /* Or is the final reference BT_CLASS or _data?  */
   for (ref = e->ref; ref; ref = ref->next)
     {
-      if (ref->type == REF_COMPONENT
-           && ref->u.c.component->ts.type == BT_CLASS
-           && CLASS_DATA (ref->u.c.component)
-           && !CLASS_DATA (ref->u.c.component)->attr.dimension
-           && (ref->next == NULL
-               || (ref->next->type == REF_COMPONENT
-                   && strcmp (ref->next->u.c.component->name, "_data") == 0
-                   && ref->next->next == NULL)))
+      if (ref->type == REF_COMPONENT && ref->u.c.component->ts.type == BT_CLASS
+         && CLASS_DATA (ref->u.c.component)
+         && !CLASS_DATA (ref->u.c.component)->attr.dimension
+         && (ref->next == NULL
+             || (ref->next->type == REF_COMPONENT
+                 && strcmp (ref->next->u.c.component->name, "_data") == 0
+                 && (ref->next->next == NULL
+                     || (ref->next->next->type == REF_ARRAY
+                         && ref->next->next->u.ar.codimen > 0
+                         && ref->next->next->u.ar.dimen == 0
+                         && ref->next->next->next == NULL)))))
        return true;
     }
 
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index ffc3721efbe..71312e0e415 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -9750,6 +9750,9 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target)
             correct this now.  */
          gfc_typespec *ts = &target->ts;
          gfc_ref *ref;
+         /* Internal_ref is true, when this is ref'ing only _data and co-ref.
+          */
+         bool internal_ref = true;
 
          for (ref = target->ref; ref != NULL; ref = ref->next)
            {
@@ -9757,26 +9760,41 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target)
                {
                case REF_COMPONENT:
                  ts = &ref->u.c.component->ts;
+                 internal_ref
+                   = target->ref == ref && ref->next
+                     && strncmp ("_data", ref->u.c.component->name, 5) == 0;
                  break;
                case REF_ARRAY:
                  if (ts->type == BT_CLASS)
                    ts = &ts->u.derived->components->ts;
+                 if (internal_ref && ref->u.ar.codimen > 0)
+                   for (int i = ref->u.ar.dimen;
+                        internal_ref
+                        && i < ref->u.ar.dimen + ref->u.ar.codimen;
+                        ++i)
+                     internal_ref
+                       = ref->u.ar.dimen_type[i] == DIMEN_THIS_IMAGE;
                  break;
                default:
                  break;
                }
            }
-         /* Create a scalar instance of the current class type.  Because the
-            rank of a class array goes into its name, the type has to be
-            rebuilt.  The alternative of (re-)setting just the attributes
-            and as in the current type, destroys the type also in other
-            places.  */
-         as = NULL;
-         sym->ts = *ts;
-         sym->ts.type = BT_CLASS;
-         attr = CLASS_DATA (sym) ? CLASS_DATA (sym)->attr : sym->attr;
-         gfc_change_class (&sym->ts, &attr, as, 0, 0);
-         sym->as = NULL;
+         /* Only rewrite the type of this symbol, when the refs are not the
+            internal ones for class and co-array this-image.  */
+         if (!internal_ref)
+           {
+             /* Create a scalar instance of the current class type.  Because
+                the rank of a class array goes into its name, the type has to
+                be rebuilt.  The alternative of (re-)setting just the
+                attributes and as in the current type, destroys the type also
+                in other places.  */
+             as = NULL;
+             sym->ts = *ts;
+             sym->ts.type = BT_CLASS;
+             attr = CLASS_DATA (sym) ? CLASS_DATA (sym)->attr : sym->attr;
+             gfc_change_class (&sym->ts, &attr, as, 0, 0);
+             sym->as = NULL;
+           }
        }
     }
 
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 9e4fba68550..c11abb07eb6 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -2437,7 +2437,8 @@ gfc_get_caf_token_offset (gfc_se *se, tree *token, tree 
*offset, tree caf_decl,
     {
       gcc_assert (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl))
                    == GFC_ARRAY_ALLOCATABLE
-                 || expr->symtree->n.sym->attr.select_type_temporary);
+                 || expr->symtree->n.sym->attr.select_type_temporary
+                 || expr->symtree->n.sym->assoc);
       *token = gfc_conv_descriptor_token (caf_decl);
     }
   else if (DECL_LANG_SPECIFIC (caf_decl)
@@ -3256,6 +3257,13 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
       else
         se->string_length = sym->ts.u.cl->backend_decl;
       gcc_assert (se->string_length);
+
+      /* For coarray strings return the pointer to the data and not the
+        descriptor.  */
+      if (sym->attr.codimension && sym->attr.associate_var
+         && !se->descriptor_only
+         && TREE_CODE (TREE_TYPE (se->expr)) != ARRAY_TYPE)
+       se->expr = gfc_conv_descriptor_data_get (se->expr);
     }
 
   /* Some expressions leak through that haven't been fixed up.  */
@@ -10536,10 +10544,25 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, 
gfc_expr * expr2)
       gfc_add_modify (&block, lse.expr,
                      fold_convert (TREE_TYPE (lse.expr), rse.expr));
 
-      /* Also set the tokens for pointer components in derived typed
-        coarrays.  */
       if (flag_coarray == GFC_FCOARRAY_LIB)
-       trans_caf_token_assign (&lse, &rse, expr1, expr2);
+       {
+         if (expr1->ref)
+           /* Also set the tokens for pointer components in derived typed
+              coarrays.  */
+           trans_caf_token_assign (&lse, &rse, expr1, expr2);
+         else if (gfc_caf_attr (expr1).codimension)
+           {
+             tree lhs_caf_decl, rhs_caf_decl, lhs_tok, rhs_tok;
+
+             lhs_caf_decl = gfc_get_tree_for_caf_expr (expr1);
+             rhs_caf_decl = gfc_get_tree_for_caf_expr (expr2);
+             gfc_get_caf_token_offset (&lse, &lhs_tok, nullptr, lhs_caf_decl,
+                                       NULL_TREE, expr1);
+             gfc_get_caf_token_offset (&rse, &rhs_tok, nullptr, rhs_caf_decl,
+                                       NULL_TREE, expr2);
+             gfc_add_modify (&block, lhs_tok, rhs_tok);
+           }
+       }
 
       gfc_add_block_to_block (&block, &rse.post);
       gfc_add_block_to_block (&block, &lse.post);
@@ -10981,8 +11004,9 @@ gfc_conv_string_parameter (gfc_se * se)
       the assignment from the temporary to the lhs.  */
 
 tree
-gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
-                        bool deep_copy, bool dealloc, bool in_coarray)
+gfc_trans_scalar_assign (gfc_se *lse, gfc_se *rse, gfc_typespec ts,
+                        bool deep_copy, bool dealloc, bool in_coarray,
+                        bool assoc_assign)
 {
   stmtblock_t block;
   tree tmp;
@@ -11103,6 +11127,21 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, 
gfc_typespec ts,
       gfc_add_block_to_block (&block, &lse->pre);
       gfc_add_block_to_block (&block, &rse->pre);
 
+      if (in_coarray)
+       {
+         if (flag_coarray == GFC_FCOARRAY_LIB && assoc_assign)
+           {
+             gfc_add_modify (&block, gfc_conv_descriptor_token (lse->expr),
+                             TYPE_LANG_SPECIFIC (
+                               TREE_TYPE (TREE_TYPE (rse->expr)))
+                               ->caf_token);
+           }
+         if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (lse->expr)))
+           lse->expr = gfc_conv_array_data (lse->expr);
+         if (flag_coarray == GFC_FCOARRAY_SINGLE && assoc_assign
+             && !POINTER_TYPE_P (TREE_TYPE (rse->expr)))
+           rse->expr = gfc_build_addr_expr (NULL_TREE, rse->expr);
+       }
       gfc_add_modify (&block, lse->expr,
                      fold_convert (TREE_TYPE (lse->expr), rse->expr));
     }
@@ -12290,6 +12329,15 @@ trans_class_assignment (stmtblock_t *block, gfc_expr 
*lhs, gfc_expr *rhs,
     }
 }
 
+bool
+is_assoc_assign (gfc_expr *lhs, gfc_expr *rhs)
+{
+  if (lhs->expr_type != EXPR_VARIABLE || rhs->expr_type != EXPR_VARIABLE)
+    return false;
+
+  return lhs->symtree->n.sym->assoc
+        && lhs->symtree->n.sym->assoc->target == rhs;
+}
 
 /* Subroutine of gfc_trans_assignment that actually scalarizes the
    assignment.  EXPR1 is the destination/LHS and EXPR2 is the source/RHS.
@@ -12323,6 +12371,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * 
expr2, bool init_flag,
   symbol_attribute lhs_caf_attr, rhs_caf_attr, lhs_attr;
   bool is_poly_assign;
   bool realloc_flag;
+  bool assoc_assign = false;
 
   /* Assignment of the form lhs = rhs.  */
   gfc_start_block (&block);
@@ -12378,6 +12427,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * 
expr2, bool init_flag,
                       || gfc_is_class_scalar_expr (expr2))
                   && lhs_attr.flavor != FL_PROCEDURE;
 
+  assoc_assign = is_assoc_assign (expr1, expr2);
+
   realloc_flag = flag_realloc_lhs
                 && gfc_is_reallocatable_lhs (expr1)
                 && expr2->rank
@@ -12471,11 +12522,13 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * 
expr2, bool init_flag,
   l_is_temp = (lss != gfc_ss_terminator && loop.temp_ss != NULL);
 
   /* Translate the expression.  */
-  rse.want_coarray = flag_coarray == GFC_FCOARRAY_LIB && init_flag
-      && lhs_caf_attr.codimension;
+  rse.want_coarray = flag_coarray == GFC_FCOARRAY_LIB
+                    && (init_flag || assoc_assign) && lhs_caf_attr.codimension;
+  rse.want_pointer = rse.want_coarray && !init_flag && !lhs_caf_attr.dimension;
   gfc_conv_expr (&rse, expr2);
 
-  /* Deal with the case of a scalar class function assigned to a derived type. 
 */
+  /* Deal with the case of a scalar class function assigned to a derived type.
+   */
   if (gfc_is_alloc_class_scalar_function (expr2)
       && expr1->ts.type == BT_DERIVED)
     {
@@ -12713,15 +12766,19 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * 
expr2, bool init_flag,
   else
     gfc_add_block_to_block (&body, &rse.pre);
 
+  if (flag_coarray != GFC_FCOARRAY_NONE && expr1->ts.type == BT_CHARACTER
+      && assoc_assign)
+    tmp = gfc_trans_pointer_assignment (expr1, expr2);
+
   /* If nothing else works, do it the old fashioned way!  */
   if (tmp == NULL_TREE)
-    tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
-                                  gfc_expr_is_variable (expr2)
-                                  || scalar_to_array
+    tmp
+      = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
+                                gfc_expr_is_variable (expr2) || scalar_to_array
                                   || expr2->expr_type == EXPR_ARRAY,
-                                  !(l_is_temp || init_flag) && dealloc,
-                                  expr1->symtree->n.sym->attr.codimension);
-
+                                !(l_is_temp || init_flag) && dealloc,
+                                expr1->symtree->n.sym->attr.codimension,
+                                assoc_assign);
 
   /* Add the lse pre block to the body  */
   gfc_add_block_to_block (&body, &lse.pre);
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 807fa8c6351..3b09a139dc0 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1754,7 +1754,7 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block 
*block)
                  && e->ts.type == BT_CLASS
                  && (gfc_is_class_scalar_expr (e)
                      || gfc_is_class_array_ref (e, NULL));
-  same_class = e->ts.type == BT_CLASS && sym->ts.type == BT_CLASS
+  same_class = class_target && sym->ts.type == BT_CLASS
               && strcmp (sym->ts.u.derived->name, e->ts.u.derived->name) == 0;
 
   unlimited = UNLIMITED_POLY (e);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index fdcce206756..d67fbe36a24 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -570,8 +570,9 @@ void gfc_conv_subref_array_arg (gfc_se *, gfc_expr *, int, 
sym_intent, bool,
 void gfc_conv_is_contiguous_expr (gfc_se *, gfc_expr *);
 
 /* Generate code for a scalar assignment.  */
-tree gfc_trans_scalar_assign (gfc_se *, gfc_se *, gfc_typespec, bool, bool,
-                             bool c = false);
+tree
+gfc_trans_scalar_assign (gfc_se *, gfc_se *, gfc_typespec, bool, bool,
+                        bool = false, bool = false);
 
 /* Translate COMMON blocks.  */
 void gfc_trans_common (gfc_namespace *);
diff --git a/gcc/testsuite/gfortran.dg/coarray/associate_1.f90 
b/gcc/testsuite/gfortran.dg/coarray/associate_1.f90
new file mode 100644
index 00000000000..ad1473de696
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/associate_1.f90
@@ -0,0 +1,36 @@
+!{ dg-do run }
+
+! Contributed by Neil Carlson  <neil.n.carl...@gmail.com>
+! Check PR110033 is fixed.
+
+program coarray_associate_1
+  type t
+    integer :: b = -1
+    logical :: l = .FALSE.
+  end type
+
+  integer :: x[*] = 10
+  class(t), allocatable :: c[:]
+
+  associate (y => x)
+    y = -1
+    y[1] = 35
+  end associate
+  allocate(c[*])
+  associate (f => c)
+    f%b = 17
+    f[1]%l = .TRUE.
+  end associate
+
+  if (this_image() == 1) then
+    if (x /= 35) stop 1
+    if (c%b /= 17) stop 2
+    if (.NOT. c%l) stop 3
+  else
+    if (x /= -1) stop 4
+    if (c%b /= 17) stop 5
+    if (c%l) stop 6
+  end if
+
+end
+

Reply via email to