LCOV - code coverage report
Current view: top level - gcc/fortran - coarray.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.0 % 952 828
Test Date: 2025-04-19 15:48:17 Functions: 100.0 % 20 20
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Rewrite the expression tree for coarrays.
       2                 :             :    Copyright (C) 2010-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by Andre Vehreschild.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify it under
       8                 :             : the terms of the GNU General Public License as published by the Free
       9                 :             : Software Foundation; either version 3, or (at your option) any later
      10                 :             : version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :             : for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : /* Rewrite the expression for coarrays where needed:
      22                 :             :    - coarray indexing operations need the indexing expression put into a
      23                 :             :      routine callable on the remote image
      24                 :             : 
      25                 :             :    This rewriter is meant to used for non-optimisational expression tree
      26                 :             :    rewrites.  When implementing early optimisation it is recommended to
      27                 :             :    do this in frontend-passes.cc.
      28                 :             : */
      29                 :             : 
      30                 :             : #include "config.h"
      31                 :             : #include "system.h"
      32                 :             : #include "coretypes.h"
      33                 :             : #include "options.h"
      34                 :             : #include "bitmap.h"
      35                 :             : #include "gfortran.h"
      36                 :             : 
      37                 :             : /* The code tree element that is currently processed.  */
      38                 :             : static gfc_code **current_code;
      39                 :             : 
      40                 :             : /* Code that is inserted into the current caf_accessor at the beginning.  */
      41                 :             : static gfc_code *caf_accessor_prepend = nullptr;
      42                 :             : 
      43                 :             : static bool caf_on_lhs = false;
      44                 :             : 
      45                 :             : static int caf_sym_cnt = 0;
      46                 :             : 
      47                 :             : static gfc_array_spec *
      48                 :          25 : get_arrayspec_from_expr (gfc_expr *expr)
      49                 :             : {
      50                 :          25 :   gfc_array_spec *src_as, *dst_as = NULL;
      51                 :          25 :   gfc_ref *ref;
      52                 :          25 :   gfc_array_ref mod_src_ar;
      53                 :          25 :   int dst_rank = 0;
      54                 :             : 
      55                 :          25 :   if (expr->rank == 0)
      56                 :             :     return NULL;
      57                 :             : 
      58                 :          25 :   if (expr->expr_type == EXPR_FUNCTION)
      59                 :           0 :     return gfc_copy_array_spec (expr->symtree->n.sym->as);
      60                 :             : 
      61                 :             :   /* Follow any component references.  */
      62                 :          25 :   if (expr->expr_type == EXPR_VARIABLE || expr->expr_type == EXPR_CONSTANT)
      63                 :             :     {
      64                 :          25 :       if (expr->symtree)
      65                 :          25 :         src_as = expr->symtree->n.sym->as;
      66                 :             :       else
      67                 :             :         src_as = NULL;
      68                 :             : 
      69                 :          50 :       for (ref = expr->ref; ref; ref = ref->next)
      70                 :             :         {
      71                 :          25 :           switch (ref->type)
      72                 :             :             {
      73                 :           0 :             case REF_COMPONENT:
      74                 :           0 :               src_as = ref->u.c.component->as;
      75                 :           0 :               continue;
      76                 :             : 
      77                 :           0 :             case REF_SUBSTRING:
      78                 :           0 :             case REF_INQUIRY:
      79                 :           0 :               continue;
      80                 :             : 
      81                 :          25 :             case REF_ARRAY:
      82                 :          25 :               switch (ref->u.ar.type)
      83                 :             :                 {
      84                 :             :                 case AR_ELEMENT:
      85                 :          25 :                   src_as = NULL;
      86                 :             :                   break;
      87                 :           0 :                 case AR_SECTION:
      88                 :           0 :                   {
      89                 :           0 :                     if (!dst_as)
      90                 :           0 :                       dst_as = gfc_get_array_spec ();
      91                 :           0 :                     memset (&mod_src_ar, 0, sizeof (gfc_array_ref));
      92                 :           0 :                     mod_src_ar = ref->u.ar;
      93                 :           0 :                     for (int dim = 0; dim < src_as->rank; ++dim)
      94                 :             :                       {
      95                 :           0 :                         switch (ref->u.ar.dimen_type[dim])
      96                 :             :                           {
      97                 :           0 :                           case DIMEN_ELEMENT:
      98                 :           0 :                             gfc_free_expr (mod_src_ar.start[dim]);
      99                 :           0 :                             mod_src_ar.start[dim] = NULL;
     100                 :           0 :                             break;
     101                 :           0 :                           case DIMEN_RANGE:
     102                 :           0 :                             dst_as->lower[dst_rank]
     103                 :           0 :                               = gfc_copy_expr (ref->u.ar.start[dim]);
     104                 :           0 :                             mod_src_ar.start[dst_rank]
     105                 :           0 :                               = gfc_copy_expr (ref->u.ar.start[dim]);
     106                 :           0 :                             if (ref->u.ar.end[dim])
     107                 :             :                               {
     108                 :           0 :                                 dst_as->upper[dst_rank]
     109                 :           0 :                                   = gfc_copy_expr (ref->u.ar.end[dim]);
     110                 :           0 :                                 mod_src_ar.end[dst_rank] = ref->u.ar.end[dim];
     111                 :           0 :                                 mod_src_ar.stride[dst_rank]
     112                 :           0 :                                   = ref->u.ar.stride[dim];
     113                 :             :                               }
     114                 :             :                             else
     115                 :           0 :                               dst_as->upper[dst_rank]
     116                 :           0 :                                 = gfc_copy_expr (ref->u.ar.as->upper[dim]);
     117                 :           0 :                             ++dst_rank;
     118                 :           0 :                             break;
     119                 :           0 :                           case DIMEN_STAR:
     120                 :           0 :                             dst_as->lower[dst_rank]
     121                 :           0 :                               = gfc_copy_expr (ref->u.ar.as->lower[dim]);
     122                 :           0 :                             mod_src_ar.start[dst_rank]
     123                 :           0 :                               = gfc_copy_expr (ref->u.ar.start[dim]);
     124                 :           0 :                             if (ref->u.ar.as->upper[dim])
     125                 :             :                               {
     126                 :           0 :                                 dst_as->upper[dst_rank]
     127                 :           0 :                                   = gfc_copy_expr (ref->u.ar.as->upper[dim]);
     128                 :           0 :                                 mod_src_ar.end[dst_rank] = ref->u.ar.end[dim];
     129                 :           0 :                                 mod_src_ar.stride[dst_rank]
     130                 :           0 :                                   = ref->u.ar.stride[dim];
     131                 :             :                               }
     132                 :           0 :                             ++dst_rank;
     133                 :           0 :                             break;
     134                 :           0 :                           case DIMEN_VECTOR:
     135                 :           0 :                             dst_as->lower[dst_rank]
     136                 :           0 :                               = gfc_get_constant_expr (BT_INTEGER,
     137                 :             :                                                        gfc_index_integer_kind,
     138                 :             :                                                        &expr->where);
     139                 :           0 :                             mpz_set_ui (dst_as->lower[dst_rank]->value.integer,
     140                 :             :                                         1);
     141                 :           0 :                             mod_src_ar.start[dst_rank]
     142                 :           0 :                               = gfc_copy_expr (ref->u.ar.start[dim]);
     143                 :           0 :                             dst_as->upper[dst_rank]
     144                 :           0 :                               = gfc_get_constant_expr (BT_INTEGER,
     145                 :             :                                                        gfc_index_integer_kind,
     146                 :             :                                                        &expr->where);
     147                 :           0 :                             mpz_set (dst_as->upper[dst_rank]->value.integer,
     148                 :           0 :                                      ref->u.ar.start[dim]->shape[0]);
     149                 :           0 :                             ++dst_rank;
     150                 :           0 :                             break;
     151                 :           0 :                           case DIMEN_THIS_IMAGE:
     152                 :           0 :                           case DIMEN_UNKNOWN:
     153                 :           0 :                             gcc_unreachable ();
     154                 :             :                           }
     155                 :           0 :                         if (ref->u.ar.dimen_type[dim] != DIMEN_ELEMENT)
     156                 :           0 :                           mod_src_ar.dimen_type[dst_rank]
     157                 :           0 :                             = ref->u.ar.dimen_type[dim];
     158                 :             :                       }
     159                 :           0 :                     dst_as->rank = dst_rank;
     160                 :           0 :                     dst_as->type = AS_EXPLICIT;
     161                 :           0 :                     ref->u.ar = mod_src_ar;
     162                 :           0 :                     ref->u.ar.dimen = dst_rank;
     163                 :           0 :                     break;
     164                 :             : 
     165                 :             :                   case AR_UNKNOWN:
     166                 :          25 :                     src_as = NULL;
     167                 :             :                     break;
     168                 :             : 
     169                 :          25 :                   case AR_FULL:
     170                 :          25 :                     if (dst_as)
     171                 :             :                       /* Prevent memory loss.  */
     172                 :           0 :                       gfc_free_array_spec (dst_as);
     173                 :          25 :                     dst_as = gfc_copy_array_spec (src_as);
     174                 :          25 :                     break;
     175                 :             :                   }
     176                 :             :                   break;
     177                 :             :                 }
     178                 :           0 :             }
     179                 :             :         }
     180                 :             :     }
     181                 :             :   else
     182                 :          25 :     src_as = NULL;
     183                 :             : 
     184                 :             :   return dst_as;
     185                 :             : }
     186                 :             : 
     187                 :             : static void
     188                 :         833 : remove_coarray_from_derived_type (gfc_symbol *base, gfc_namespace *ns,
     189                 :             :                                   gfc_array_spec *src_as = NULL)
     190                 :             : {
     191                 :         833 :   gfc_symbol *derived;
     192                 :         833 :   gfc_symbol *src_derived = base->ts.u.derived;
     193                 :             : 
     194                 :         833 :   if (!src_as)
     195                 :         803 :     src_as = src_derived->as;
     196                 :         833 :   gfc_get_symbol (src_derived->name, ns, &derived);
     197                 :         833 :   derived->attr.flavor = FL_DERIVED;
     198                 :         833 :   derived->attr.alloc_comp = src_derived->attr.alloc_comp;
     199                 :         833 :   if (src_as && src_as->rank != 0)
     200                 :             :     {
     201                 :          17 :       base->attr.dimension = 1;
     202                 :          17 :       base->as = gfc_copy_array_spec (src_as);
     203                 :          17 :       base->as->corank = 0;
     204                 :             :     }
     205                 :        4349 :   for (gfc_component *p = NULL, *c = src_derived->components; c; c = c->next)
     206                 :             :     {
     207                 :        3516 :       gfc_component *n = gfc_get_component ();
     208                 :        3516 :       *n = *c;
     209                 :        3516 :       if (n->as)
     210                 :        1613 :         n->as = gfc_copy_array_spec (c->as);
     211                 :        3516 :       n->backend_decl = NULL;
     212                 :        3516 :       n->initializer = NULL;
     213                 :        3516 :       n->param_list = NULL;
     214                 :        3516 :       if (p)
     215                 :        2683 :         p->next = n;
     216                 :             :       else
     217                 :         833 :         derived->components = n;
     218                 :             : 
     219                 :        3516 :       p = n;
     220                 :             :     }
     221                 :         833 :   derived->declared_at = base->declared_at;
     222                 :         833 :   gfc_set_sym_referenced (derived);
     223                 :         833 :   gfc_commit_symbol (derived);
     224                 :         833 :   base->ts.u.derived = derived;
     225                 :         833 :   gfc_commit_symbol (base);
     226                 :         833 : }
     227                 :             : 
     228                 :             : static void
     229                 :          30 : convert_coarray_class_to_derived_type (gfc_symbol *base, gfc_namespace *ns)
     230                 :             : {
     231                 :          30 :   gfc_symbol *src_derived = CLASS_DATA (base)->ts.u.derived;
     232                 :          30 :   gfc_array_spec *src_as = CLASS_DATA (base)->as;
     233                 :          60 :   const bool attr_allocatable
     234                 :          30 :     = src_as && src_as->rank && src_as->type == AS_DEFERRED;
     235                 :             : 
     236                 :          30 :   base->ts.type = BT_DERIVED;
     237                 :          30 :   base->ts.u.derived = src_derived;
     238                 :             : 
     239                 :          30 :   remove_coarray_from_derived_type (base, ns, src_as);
     240                 :             : 
     241                 :          30 :   base->attr.allocatable = attr_allocatable;
     242                 :          30 :   base->attr.pointer = 0; // Ensure, that it is no pointer.
     243                 :          30 : }
     244                 :             : 
     245                 :             : static void
     246                 :        1116 : move_coarray_ref (gfc_ref **from, gfc_expr *expr)
     247                 :             : {
     248                 :        1116 :   int i;
     249                 :        1116 :   gfc_ref *to = expr->ref;
     250                 :        1145 :   for (; to && to->next; to = to->next)
     251                 :             :     ;
     252                 :             : 
     253                 :        1116 :   if (!to)
     254                 :             :     {
     255                 :        1063 :       expr->ref = gfc_get_ref ();
     256                 :        1063 :       to = expr->ref;
     257                 :        1063 :       to->type = REF_ARRAY;
     258                 :             :     }
     259                 :        1116 :   gcc_assert (to->type == REF_ARRAY);
     260                 :        1116 :   to->u.ar.as = gfc_copy_array_spec ((*from)->u.ar.as);
     261                 :        1116 :   to->u.ar.codimen = (*from)->u.ar.codimen;
     262                 :        1116 :   to->u.ar.dimen = (*from)->u.ar.dimen;
     263                 :        1116 :   to->u.ar.type = AR_FULL;
     264                 :        1116 :   to->u.ar.stat = (*from)->u.ar.stat;
     265                 :        1116 :   (*from)->u.ar.stat = nullptr;
     266                 :        1116 :   to->u.ar.team = (*from)->u.ar.team;
     267                 :        1116 :   (*from)->u.ar.team = nullptr;
     268                 :        1116 :   to->u.ar.team_type = (*from)->u.ar.team_type;
     269                 :        1116 :   (*from)->u.ar.team_type = TEAM_UNSET;
     270                 :        1413 :   for (i = 0; i < to->u.ar.dimen; ++i)
     271                 :             :     {
     272                 :         297 :       to->u.ar.start[i] = nullptr;
     273                 :         297 :       to->u.ar.end[i] = nullptr;
     274                 :         297 :       to->u.ar.stride[i] = nullptr;
     275                 :             :     }
     276                 :        2246 :   for (i = (*from)->u.ar.dimen; i < (*from)->u.ar.dimen + (*from)->u.ar.codimen;
     277                 :             :        ++i)
     278                 :             :     {
     279                 :        1130 :       to->u.ar.dimen_type[i] = (*from)->u.ar.dimen_type[i];
     280                 :        1130 :       to->u.ar.start[i] = (*from)->u.ar.start[i];
     281                 :        1130 :       (*from)->u.ar.start[i] = nullptr;
     282                 :        1130 :       to->u.ar.end[i] = (*from)->u.ar.end[i];
     283                 :        1130 :       (*from)->u.ar.end[i] = nullptr;
     284                 :        1130 :       to->u.ar.stride[i] = (*from)->u.ar.stride[i];
     285                 :        1130 :       (*from)->u.ar.stride[i] = nullptr;
     286                 :             :     }
     287                 :        1116 :   (*from)->u.ar.codimen = 0;
     288                 :        1116 :   if ((*from)->u.ar.dimen == 0)
     289                 :             :     {
     290                 :         879 :       gfc_ref *nref = (*from)->next;
     291                 :         879 :       (*from)->next = nullptr;
     292                 :         879 :       gfc_free_ref_list (*from);
     293                 :         879 :       *from = nref;
     294                 :             :     }
     295                 :        1116 : }
     296                 :             : 
     297                 :             : static void
     298                 :        2232 : fixup_comp_refs (gfc_expr *expr)
     299                 :             : {
     300                 :        2232 :   bool class_ref = expr->symtree->n.sym->ts.type == BT_CLASS;
     301                 :        6133 :   gfc_symbol *type
     302                 :             :     = expr->symtree->n.sym->ts.type == BT_DERIVED
     303                 :        2232 :         ? expr->symtree->n.sym->ts.u.derived
     304                 :         587 :         : (class_ref ? CLASS_DATA (expr->symtree->n.sym)->ts.u.derived
     305                 :             :                      : nullptr);
     306                 :        1669 :   if (!type)
     307                 :             :     return;
     308                 :        1669 :   gfc_ref **pref = &(expr->ref);
     309                 :        1669 :   for (gfc_ref *ref = expr->ref; ref && type;)
     310                 :             :     {
     311                 :        2220 :       switch (ref->type)
     312                 :             :         {
     313                 :        1186 :         case REF_COMPONENT:
     314                 :        1186 :           gfc_find_component (type, ref->u.c.component->name, false, true,
     315                 :             :                               pref);
     316                 :        1186 :           if (!*pref)
     317                 :             :             {
     318                 :             :               /* This happens when there were errors previously.  Just don't
     319                 :             :                  crash.  */
     320                 :             :               ref = nullptr;
     321                 :             :               break;
     322                 :             :             }
     323                 :        1186 :           if (class_ref)
     324                 :             :             /* Link to the class type to allow for derived type resolution.  */
     325                 :           0 :             (*pref)->u.c.sym = ref->u.c.sym;
     326                 :        1186 :           (*pref)->next = ref->next;
     327                 :        1186 :           ref->next = NULL;
     328                 :        1186 :           gfc_free_ref_list (ref);
     329                 :        1186 :           ref = (*pref)->next;
     330                 :        2372 :           type = (*pref)->u.c.component->ts.type == BT_DERIVED
     331                 :        1186 :                    ? (*pref)->u.c.component->ts.u.derived
     332                 :             :                    : ((*pref)->u.c.component->ts.type == BT_CLASS
     333                 :         836 :                         ? CLASS_DATA ((*pref)->u.c.component)->ts.u.derived
     334                 :             :                         : nullptr);
     335                 :        1186 :           pref = &(*pref)->next;
     336                 :        1186 :           break;
     337                 :        1034 :         case REF_ARRAY:
     338                 :        1034 :           pref = &ref->next;
     339                 :        1034 :           ref = ref->next;
     340                 :        1034 :           break;
     341                 :           0 :         default:
     342                 :           0 :           gcc_unreachable ();
     343                 :        3889 :           break;
     344                 :             :         }
     345                 :             :     }
     346                 :             : }
     347                 :             : 
     348                 :             : static void
     349                 :        1116 : split_expr_at_caf_ref (gfc_expr *expr, gfc_namespace *ns,
     350                 :             :                        gfc_expr **post_caf_ref_expr, bool for_send)
     351                 :             : {
     352                 :        1116 :   gfc_ref *caf_ref = NULL;
     353                 :        1116 :   gfc_symtree *st;
     354                 :        1116 :   gfc_symbol *base;
     355                 :        1116 :   gfc_typespec *caf_ts;
     356                 :        1116 :   bool created;
     357                 :             : 
     358                 :        1116 :   gcc_assert (expr->expr_type == EXPR_VARIABLE);
     359                 :        1116 :   caf_ts = &expr->symtree->n.sym->ts;
     360                 :        1116 :   if (!expr->symtree->n.sym->attr.codimension)
     361                 :             :     {
     362                 :             :       /* The coarray is in some component.  Find it.  */
     363                 :          53 :       caf_ref = expr->ref;
     364                 :          82 :       while (caf_ref)
     365                 :             :         {
     366                 :          82 :           if (caf_ref->type == REF_ARRAY && caf_ref->u.ar.codimen != 0)
     367                 :             :             break;
     368                 :          29 :           if (caf_ref->type == REF_COMPONENT)
     369                 :          29 :             caf_ts = &caf_ref->u.c.component->ts;
     370                 :          29 :           caf_ref = caf_ref->next;
     371                 :             :         }
     372                 :             :     }
     373                 :             : 
     374                 :        1116 :   created = !gfc_get_sym_tree (!caf_ref ? expr->symtree->name : "base", ns, &st,
     375                 :             :                                false);
     376                 :        1116 :   gcc_assert (created);
     377                 :        1116 :   st->n.sym->attr.flavor = FL_PARAMETER;
     378                 :        1116 :   st->n.sym->attr.dummy = 1;
     379                 :        1116 :   st->n.sym->attr.intent = INTENT_IN;
     380                 :        1116 :   st->n.sym->ts = *caf_ts;
     381                 :        1116 :   st->n.sym->declared_at = expr->where;
     382                 :             : 
     383                 :        1116 :   *post_caf_ref_expr = gfc_get_variable_expr (st);
     384                 :        1116 :   (*post_caf_ref_expr)->where = expr->where;
     385                 :        1116 :   base = (*post_caf_ref_expr)->symtree->n.sym;
     386                 :             : 
     387                 :        1116 :   if (!caf_ref)
     388                 :             :     {
     389                 :        1063 :       (*post_caf_ref_expr)->ref = gfc_get_ref ();
     390                 :        1063 :       *(*post_caf_ref_expr)->ref = *expr->ref;
     391                 :        1063 :       expr->ref = nullptr;
     392                 :        1063 :       move_coarray_ref (&(*post_caf_ref_expr)->ref, expr);
     393                 :        1063 :       fixup_comp_refs (expr);
     394                 :             : 
     395                 :        1063 :       if (expr->symtree->n.sym->attr.dimension)
     396                 :             :         {
     397                 :         218 :           base->as = gfc_copy_array_spec (expr->symtree->n.sym->as);
     398                 :         218 :           base->as->corank = 0;
     399                 :         218 :           base->attr.dimension = 1;
     400                 :         218 :           base->attr.allocatable = expr->symtree->n.sym->attr.allocatable;
     401                 :         218 :           base->attr.pointer = expr->symtree->n.sym->attr.pointer
     402                 :         218 :                                || expr->symtree->n.sym->attr.associate_var;
     403                 :             :         }
     404                 :             :     }
     405                 :             :   else
     406                 :             :     {
     407                 :          53 :       (*post_caf_ref_expr)->ref = gfc_get_ref ();
     408                 :          53 :       *(*post_caf_ref_expr)->ref = *caf_ref;
     409                 :          53 :       caf_ref->next = nullptr;
     410                 :          53 :       move_coarray_ref (&(*post_caf_ref_expr)->ref, expr);
     411                 :          53 :       fixup_comp_refs (expr);
     412                 :             : 
     413                 :          53 :       if (caf_ref && caf_ref->u.ar.dimen)
     414                 :             :         {
     415                 :          19 :           base->as = gfc_copy_array_spec (caf_ref->u.ar.as);
     416                 :          19 :           base->as->corank = 0;
     417                 :          19 :           base->attr.dimension = 1;
     418                 :          19 :           base->attr.allocatable = caf_ref->u.ar.as->type != AS_EXPLICIT;
     419                 :             :         }
     420                 :          53 :       base->ts = *caf_ts;
     421                 :             :     }
     422                 :        1116 :   (*post_caf_ref_expr)->ts = expr->ts;
     423                 :        1116 :   if (base->ts.type == BT_CHARACTER)
     424                 :             :     {
     425                 :         107 :       base->ts.u.cl = gfc_get_charlen ();
     426                 :         107 :       *base->ts.u.cl = *(caf_ts->u.cl);
     427                 :         107 :       base->ts.deferred = 1;
     428                 :         107 :       base->ts.u.cl->length = nullptr;
     429                 :             :     }
     430                 :        1009 :   else if (base->ts.type == BT_DERIVED)
     431                 :         803 :     remove_coarray_from_derived_type (base, ns);
     432                 :         206 :   else if (base->ts.type == BT_CLASS)
     433                 :          30 :     convert_coarray_class_to_derived_type (base, ns);
     434                 :             : 
     435                 :        1116 :   gfc_expression_rank (*post_caf_ref_expr);
     436                 :        1116 :   if (for_send)
     437                 :         444 :     gfc_expression_rank (expr);
     438                 :             :   else
     439                 :         672 :     expr->rank = (*post_caf_ref_expr)->rank;
     440                 :        1116 : }
     441                 :             : 
     442                 :             : static void add_caf_get_from_remote (gfc_expr *e);
     443                 :             : 
     444                 :             : static gfc_component *
     445                 :         202 : find_comp (gfc_symbol *type, gfc_expr *e, int *cnt, const bool is_var)
     446                 :             : {
     447                 :         202 :   char *temp_name = nullptr;
     448                 :         202 :   gfc_component *comp = type->components;
     449                 :             : 
     450                 :             :   /* For variables:
     451                 :             :      - look up same name or create new
     452                 :             :      all else:
     453                 :             :      - create unique new
     454                 :             :   */
     455                 :         202 :   if (is_var)
     456                 :             :     {
     457                 :         202 :       ++(*cnt);
     458                 :         202 :       free (temp_name);
     459                 :         202 :       temp_name = xasprintf ("caf_temp_%s_%d", e->symtree->name, *cnt);
     460                 :         852 :       while (comp && strcmp (comp->name, temp_name) != 0)
     461                 :         448 :         comp = comp->next;
     462                 :         202 :       if (!comp)
     463                 :             :         {
     464                 :         198 :           const bool added = gfc_add_component (type, temp_name, &comp);
     465                 :         198 :           gcc_assert (added);
     466                 :             :         }
     467                 :             :     }
     468                 :             :   else
     469                 :             :     {
     470                 :             :       int r = -1;
     471                 :             :       /* Components are always appended, i.e., when searching to add a unique
     472                 :             :          one just iterating forward is sufficient.  */
     473                 :           0 :       do
     474                 :             :         {
     475                 :           0 :           ++(*cnt);
     476                 :           0 :           free (temp_name);
     477                 :           0 :           temp_name = xasprintf ("caf_temp_%s_%d", e->symtree->name, *cnt);
     478                 :             : 
     479                 :           0 :           while (comp && (r = strcmp (comp->name, temp_name)) <= 0)
     480                 :           0 :             comp = comp->next;
     481                 :             :         }
     482                 :           0 :       while (comp && r <= 0);
     483                 :           0 :       {
     484                 :           0 :         const bool added = gfc_add_component (type, temp_name, &comp);
     485                 :           0 :         gcc_assert (added);
     486                 :             :       }
     487                 :             :     }
     488                 :             : 
     489                 :         202 :   comp->loc = e->where;
     490                 :         202 :   comp->ts = e->ts;
     491                 :         202 :   free (temp_name);
     492                 :             : 
     493                 :         202 :   return comp;
     494                 :             : }
     495                 :             : 
     496                 :             : static void
     497                 :         202 : check_add_new_comp_handle_array (gfc_expr *e, gfc_symbol *type,
     498                 :             :                                  gfc_symbol *add_data)
     499                 :             : {
     500                 :         202 :   gfc_component *comp;
     501                 :         202 :   int cnt = -1;
     502                 :         202 :   gfc_symtree *caller_image;
     503                 :         202 :   gfc_code *pre_code = caf_accessor_prepend;
     504                 :         202 :   bool static_array_or_scalar = true;
     505                 :         202 :   symbol_attribute e_attr = gfc_expr_attr (e);
     506                 :             : 
     507                 :         202 :   gfc_free_shape (&e->shape, e->rank);
     508                 :             : 
     509                 :             :   /* When already code to prepend into the accessor exists, go to
     510                 :             :      the end of the chain.  */
     511                 :         404 :   for (; pre_code && pre_code->next; pre_code = pre_code->next)
     512                 :             :     ;
     513                 :             : 
     514                 :         202 :   comp = find_comp (type, e, &cnt,
     515                 :         202 :                     e->symtree->n.sym->attr.flavor == FL_VARIABLE
     516                 :         202 :                       || e->symtree->n.sym->attr.flavor == FL_PARAMETER);
     517                 :             : 
     518                 :         202 :   if (e->expr_type == EXPR_FUNCTION
     519                 :         202 :       || (e->expr_type == EXPR_VARIABLE && e_attr.dimension
     520                 :         202 :           && e_attr.allocatable))
     521                 :             :     {
     522                 :           1 :       gfc_code *code;
     523                 :           1 :       gfc_symtree *st;
     524                 :           1 :       const bool created
     525                 :           1 :         = !gfc_get_sym_tree (comp->name, gfc_current_ns, &st, false, &e->where);
     526                 :           1 :       gcc_assert (created);
     527                 :             : 
     528                 :           1 :       st->n.sym->ts = e->ts;
     529                 :           1 :       gfc_set_sym_referenced (st->n.sym);
     530                 :           1 :       code = gfc_get_code (EXEC_ASSIGN);
     531                 :           1 :       code->loc = e->where;
     532                 :           1 :       code->expr1 = gfc_get_variable_expr (st);
     533                 :           1 :       code->expr2 = XCNEW (gfc_expr);
     534                 :           1 :       *(code->expr2) = *e;
     535                 :           1 :       code->next = *current_code;
     536                 :           1 :       *current_code = code;
     537                 :             : 
     538                 :           1 :       if (e_attr.dimension)
     539                 :             :         {
     540                 :           1 :           gfc_array_spec *as = get_arrayspec_from_expr (e);
     541                 :           1 :           static_array_or_scalar = gfc_is_compile_time_shape (as);
     542                 :             : 
     543                 :           1 :           comp->attr.dimension = 1;
     544                 :           1 :           st->n.sym->attr.dimension = 1;
     545                 :           1 :           st->n.sym->as = as;
     546                 :             : 
     547                 :           1 :           if (!static_array_or_scalar)
     548                 :             :             {
     549                 :           1 :               comp->attr.allocatable = 1;
     550                 :           1 :               st->n.sym->attr.allocatable = 1;
     551                 :             :             }
     552                 :           1 :           code->expr1->rank = as->rank;
     553                 :           1 :           gfc_add_full_array_ref (code->expr1, gfc_copy_array_spec (as));
     554                 :           1 :           comp->as = gfc_copy_array_spec (as);
     555                 :             :         }
     556                 :             : 
     557                 :           1 :       gfc_expression_rank (code->expr1);
     558                 :           1 :       comp->initializer = gfc_get_variable_expr (st);
     559                 :           1 :       gfc_commit_symbol (st->n.sym);
     560                 :           1 :     }
     561                 :             :   else
     562                 :             :     {
     563                 :         201 :       comp->initializer = gfc_copy_expr (e);
     564                 :         201 :       if (e_attr.dimension)
     565                 :             :         {
     566                 :          24 :           comp->attr.dimension = 1;
     567                 :          24 :           comp->as = get_arrayspec_from_expr (e);
     568                 :             :         }
     569                 :             :     }
     570                 :         202 :   comp->initializer->where = e->where;
     571                 :         202 :   comp->attr.access = ACCESS_PRIVATE;
     572                 :         202 :   memset (e, 0, sizeof (gfc_expr));
     573                 :         202 :   e->ts = comp->initializer->ts;
     574                 :         202 :   e->expr_type = EXPR_VARIABLE;
     575                 :         202 :   e->where = comp->initializer->where;
     576                 :             : 
     577                 :         202 :   if (comp->as && comp->as->rank)
     578                 :             :     {
     579                 :          25 :       if (static_array_or_scalar)
     580                 :             :         {
     581                 :          24 :           e->ref = gfc_get_ref ();
     582                 :          24 :           e->ref->type = REF_ARRAY;
     583                 :          24 :           e->ref->u.ar.as = gfc_copy_array_spec (add_data->as);
     584                 :          24 :           e->ref->u.ar.codimen = 1;
     585                 :          24 :           e->ref->u.ar.dimen_type[0] = DIMEN_THIS_IMAGE;
     586                 :             :         }
     587                 :             :       else
     588                 :             :         {
     589                 :           1 :           gfc_code *c;
     590                 :           1 :           gfc_symtree *lv, *ad;
     591                 :           1 :           bool created = !gfc_get_sym_tree (comp->name, add_data->ns, &lv,
     592                 :           1 :                                             false, &e->where);
     593                 :           1 :           gcc_assert (created);
     594                 :             : 
     595                 :           1 :           lv->n.sym->ts = e->ts;
     596                 :           1 :           lv->n.sym->attr.dimension = 1;
     597                 :           1 :           lv->n.sym->attr.allocatable = 1;
     598                 :           1 :           lv->n.sym->attr.flavor = FL_VARIABLE;
     599                 :           1 :           lv->n.sym->as = gfc_copy_array_spec (comp->as);
     600                 :           1 :           gfc_set_sym_referenced (lv->n.sym);
     601                 :           1 :           gfc_commit_symbol (lv->n.sym);
     602                 :           1 :           c = gfc_get_code (EXEC_ASSIGN);
     603                 :           1 :           c->loc = e->where;
     604                 :           1 :           c->expr1 = gfc_get_variable_expr (lv);
     605                 :           1 :           c->expr1->where = e->where;
     606                 :             : 
     607                 :           1 :           created = !gfc_find_sym_tree (add_data->name, add_data->ns, 0, &ad);
     608                 :           1 :           gcc_assert (created);
     609                 :           1 :           c->expr2 = gfc_get_variable_expr (ad);
     610                 :           1 :           c->expr2->where = e->where;
     611                 :           1 :           c->expr2->ts = comp->initializer->ts;
     612                 :           1 :           c->expr2->ref = gfc_get_ref ();
     613                 :           1 :           c->expr2->ref->type = REF_ARRAY;
     614                 :           1 :           c->expr2->ref->u.ar.as = gfc_copy_array_spec (add_data->as);
     615                 :           1 :           c->expr2->ref->u.ar.codimen = 1;
     616                 :           1 :           c->expr2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
     617                 :           1 :           caller_image
     618                 :           1 :             = gfc_find_symtree_in_proc ("caller_image", add_data->ns);
     619                 :           1 :           gcc_assert (caller_image);
     620                 :           1 :           c->expr2->ref->u.ar.start[0] = gfc_get_variable_expr (caller_image);
     621                 :           1 :           c->expr2->ref->u.ar.start[0]->where = e->where;
     622                 :           1 :           created = gfc_find_component (ad->n.sym->ts.u.derived, comp->name,
     623                 :             :                                         false, true, &c->expr2->ref->next)
     624                 :             :                     != nullptr;
     625                 :           1 :           gcc_assert (created);
     626                 :           1 :           c->expr2->rank = comp->as->rank;
     627                 :           1 :           gfc_add_full_array_ref (c->expr2, gfc_copy_array_spec (comp->as));
     628                 :           1 :           gfc_set_sym_referenced (ad->n.sym);
     629                 :           1 :           gfc_commit_symbol (ad->n.sym);
     630                 :           1 :           if (pre_code)
     631                 :           0 :             pre_code->next = c;
     632                 :             :           else
     633                 :           1 :             caf_accessor_prepend = c;
     634                 :           1 :           add_caf_get_from_remote (c->expr2);
     635                 :             : 
     636                 :           1 :           e->symtree = lv;
     637                 :           1 :           gfc_expression_rank (e);
     638                 :           1 :           gfc_add_full_array_ref (e, gfc_copy_array_spec (comp->as));
     639                 :             :         }
     640                 :             :     }
     641                 :             :   else
     642                 :             :     {
     643                 :         177 :       e->ref = gfc_get_ref ();
     644                 :         177 :       e->ref->type = REF_ARRAY;
     645                 :         177 :       e->ref->u.ar.as = gfc_copy_array_spec (add_data->as);
     646                 :         177 :       e->ref->u.ar.codimen = 1;
     647                 :         177 :       e->ref->u.ar.dimen_type[0] = DIMEN_THIS_IMAGE;
     648                 :             :     }
     649                 :             : 
     650                 :         202 :   if (static_array_or_scalar)
     651                 :             :     {
     652                 :         201 :       const bool created
     653                 :         201 :         = gfc_find_component (add_data->ts.u.derived, comp->name, false, true,
     654                 :         201 :                               &e->ref);
     655                 :         201 :       gcc_assert (created);
     656                 :         201 :       e->symtree = gfc_find_symtree (add_data->ns->sym_root, add_data->name);
     657                 :         201 :       gcc_assert (e->symtree);
     658                 :         201 :       if (IS_CLASS_ARRAY (e->ref->u.c.component)
     659                 :         201 :           || e->ref->u.c.component->attr.dimension)
     660                 :             :         {
     661                 :          24 :           gfc_add_full_array_ref (e, e->ref->u.c.component->ts.type == BT_CLASS
     662                 :           0 :                                        ? CLASS_DATA (e->ref->u.c.component)->as
     663                 :             :                                        : e->ref->u.c.component->as);
     664                 :          48 :           e->ref->next->u.ar.dimen
     665                 :          24 :             = e->ref->u.c.component->ts.type == BT_CLASS
     666                 :          24 :                 ? CLASS_DATA (e->ref->u.c.component)->as->rank
     667                 :          24 :                 : e->ref->u.c.component->as->rank;
     668                 :             :         }
     669                 :         201 :       gfc_expression_rank (e);
     670                 :             :     }
     671                 :         202 : }
     672                 :             : 
     673                 :             : static void
     674                 :        4207 : check_add_new_component (gfc_symbol *type, gfc_expr *e, gfc_symbol *add_data)
     675                 :             : {
     676                 :        4245 :   if (e)
     677                 :             :     {
     678                 :         920 :       switch (e->expr_type)
     679                 :             :         {
     680                 :             :         case EXPR_CONSTANT:
     681                 :             :         case EXPR_NULL:
     682                 :             :           break;
     683                 :          40 :         case EXPR_OP:
     684                 :          40 :           check_add_new_component (type, e->value.op.op1, add_data);
     685                 :          40 :           if (e->value.op.op2)
     686                 :             :             check_add_new_component (type, e->value.op.op2, add_data);
     687                 :             :           break;
     688                 :           0 :         case EXPR_COMPCALL:
     689                 :           0 :           for (gfc_actual_arglist *actual = e->value.compcall.actual; actual;
     690                 :           0 :                actual = actual->next)
     691                 :           0 :             check_add_new_component (type, actual->expr, add_data);
     692                 :             :           break;
     693                 :          60 :         case EXPR_FUNCTION:
     694                 :          60 :           if (!e->symtree->n.sym->attr.pure
     695                 :          60 :               && !e->symtree->n.sym->attr.elemental)
     696                 :             :             /* Treat non-pure/non-elemental functions.  */
     697                 :           0 :             check_add_new_comp_handle_array (e, type, add_data);
     698                 :             :           else
     699                 :         120 :             for (gfc_actual_arglist *actual = e->value.function.actual; actual;
     700                 :          60 :                  actual = actual->next)
     701                 :          60 :               check_add_new_component (type, actual->expr, add_data);
     702                 :             :           break;
     703                 :         202 :         case EXPR_VARIABLE:
     704                 :         202 :             check_add_new_comp_handle_array (e, type, add_data);
     705                 :         202 :             break;
     706                 :           0 :         case EXPR_ARRAY:
     707                 :           0 :         case EXPR_PPC:
     708                 :           0 :         case EXPR_STRUCTURE:
     709                 :           0 :         case EXPR_SUBSTRING:
     710                 :           0 :           gcc_unreachable ();
     711                 :             :         default:;
     712                 :             :         }
     713                 :             :     }
     714                 :        4207 : }
     715                 :             : 
     716                 :             : static gfc_symbol *
     717                 :        1116 : create_caf_add_data_parameter_type (gfc_expr *expr, gfc_namespace *ns,
     718                 :             :                                     gfc_symbol *add_data)
     719                 :             : {
     720                 :        1116 :   static int type_cnt = 0;
     721                 :        1116 :   char tname[GFC_MAX_SYMBOL_LEN + 1];
     722                 :        1116 :   char *name;
     723                 :        1116 :   gfc_symbol *type;
     724                 :             : 
     725                 :        1116 :   gcc_assert (expr->expr_type == EXPR_VARIABLE);
     726                 :             : 
     727                 :        1116 :   strcpy (tname, expr->symtree->name);
     728                 :        1116 :   name = xasprintf ("@_caf_add_data_t_%s_%d", tname, ++type_cnt);
     729                 :        1116 :   gfc_get_symbol (name, ns, &type);
     730                 :             : 
     731                 :        1116 :   type->attr.flavor = FL_DERIVED;
     732                 :        1116 :   add_data->ts.u.derived = type;
     733                 :        1116 :   add_data->attr.codimension = 1;
     734                 :        1116 :   add_data->as = gfc_get_array_spec ();
     735                 :        1116 :   add_data->as->corank = 1;
     736                 :        1116 :   add_data->as->type = AS_EXPLICIT;
     737                 :        1116 :   add_data->as->cotype = AS_DEFERRED;
     738                 :        1116 :   add_data->as->lower[0]
     739                 :        1116 :     = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
     740                 :             :                              &expr->where);
     741                 :        1116 :   mpz_init (add_data->as->lower[0]->value.integer);
     742                 :        1116 :   mpz_set_si (add_data->as->lower[0]->value.integer, 1);
     743                 :             : 
     744                 :        3186 :   for (gfc_ref *ref = expr->ref; ref; ref = ref->next)
     745                 :             :     {
     746                 :        2070 :       if (ref->type == REF_ARRAY)
     747                 :             :         {
     748                 :             :           gfc_array_ref *ar = &ref->u.ar;
     749                 :        2282 :           for (int i = 0; i < ar->dimen; ++i)
     750                 :             :             {
     751                 :        1369 :               check_add_new_component (type, ar->start[i], add_data);
     752                 :        1369 :               check_add_new_component (type, ar->end[i], add_data);
     753                 :        1369 :               check_add_new_component (type, ar->stride[i], add_data);
     754                 :             :             }
     755                 :             :         }
     756                 :             :     }
     757                 :             : 
     758                 :        1116 :   type->declared_at = expr->where;
     759                 :        1116 :   gfc_set_sym_referenced (type);
     760                 :        1116 :   gfc_commit_symbol (type);
     761                 :        1116 :   return type;
     762                 :             : }
     763                 :             : 
     764                 :             : static void
     765                 :        1116 : remove_caf_ref (gfc_expr *expr, const bool conv_to_this_image_cafref = false)
     766                 :             : {
     767                 :        1116 :   gfc_ref *ref = expr->ref;
     768                 :        3186 :   while (ref && (ref->type != REF_ARRAY || ref->u.ar.codimen == 0))
     769                 :             :     {
     770                 :        2070 :       ref = ref->next;
     771                 :             :     }
     772                 :        1116 :   if (ref && ref->type == REF_ARRAY && ref->u.ar.codimen != 0)
     773                 :             :     {
     774                 :           0 :       if (ref->u.ar.dimen != 0)
     775                 :             :         {
     776                 :           0 :           ref->u.ar.codimen = 0;
     777                 :           0 :           ref = ref->next;
     778                 :             :         }
     779                 :             :       else
     780                 :             :         {
     781                 :           0 :           if (conv_to_this_image_cafref)
     782                 :             :             {
     783                 :           0 :               for (int i = ref->u.ar.dimen;
     784                 :           0 :                    i < ref->u.ar.dimen + ref->u.ar.codimen; ++i)
     785                 :           0 :                 ref->u.ar.dimen_type[i] = DIMEN_THIS_IMAGE;
     786                 :             :             }
     787                 :             :           else
     788                 :             :             {
     789                 :           0 :               expr->ref = ref->next;
     790                 :           0 :               ref->next = NULL;
     791                 :           0 :               gfc_free_ref_list (ref);
     792                 :           0 :               ref = expr->ref;
     793                 :             :             }
     794                 :             :         }
     795                 :             :     }
     796                 :        1116 :   fixup_comp_refs (expr);
     797                 :        1116 : }
     798                 :             : 
     799                 :             : static gfc_expr *
     800                 :         672 : create_get_callback (gfc_expr *expr)
     801                 :             : {
     802                 :         672 :   gfc_namespace *ns;
     803                 :         672 :   gfc_symbol *extproc, *proc, *buffer, *free_buffer, *base, *get_data,
     804                 :             :     *old_buffer_data, *caller_image;
     805                 :         672 :   char tname[GFC_MAX_SYMBOL_LEN + 1];
     806                 :         672 :   char *name;
     807                 :         672 :   const char *mname;
     808                 :         672 :   gfc_expr *cb, *post_caf_ref_expr;
     809                 :         672 :   gfc_code *code;
     810                 :         672 :   int expr_rank = expr->rank;
     811                 :         672 :   gfc_code *backup_caf_accessor_prepend = caf_accessor_prepend;
     812                 :         672 :   caf_accessor_prepend = nullptr;
     813                 :             : 
     814                 :             :   /* Find the top-level namespace.  */
     815                 :         750 :   for (ns = gfc_current_ns; ns->parent; ns = ns->parent)
     816                 :             :     ;
     817                 :             : 
     818                 :         672 :   if (expr->expr_type == EXPR_VARIABLE)
     819                 :         672 :     strcpy (tname, expr->symtree->name);
     820                 :             :   else
     821                 :           0 :     strcpy (tname, "dummy");
     822                 :         672 :   if (expr->symtree->n.sym->module)
     823                 :           3 :     mname = expr->symtree->n.sym->module;
     824                 :             :   else
     825                 :             :     mname = "main";
     826                 :         672 :   name = xasprintf ("_caf_accessor_%s_%s_%d", mname, tname, ++caf_sym_cnt);
     827                 :         672 :   gfc_get_symbol (name, ns, &extproc);
     828                 :         672 :   extproc->declared_at = expr->where;
     829                 :         672 :   gfc_set_sym_referenced (extproc);
     830                 :         672 :   ++extproc->refs;
     831                 :         672 :   gfc_commit_symbol (extproc);
     832                 :             : 
     833                 :             :   /* Set up namespace.  */
     834                 :         672 :   gfc_namespace *sub_ns = gfc_get_namespace (ns, 0);
     835                 :         672 :   sub_ns->sibling = ns->contained;
     836                 :         672 :   ns->contained = sub_ns;
     837                 :         672 :   sub_ns->resolved = 1;
     838                 :             :   /* Set up procedure symbol.  */
     839                 :         672 :   gfc_find_symbol (name, sub_ns, 1, &proc);
     840                 :         672 :   sub_ns->proc_name = proc;
     841                 :         672 :   proc->attr.if_source = IFSRC_DECL;
     842                 :         672 :   proc->attr.access = ACCESS_PUBLIC;
     843                 :         672 :   gfc_add_subroutine (&proc->attr, name, NULL);
     844                 :         672 :   proc->attr.host_assoc = 1;
     845                 :         672 :   proc->attr.always_explicit = 1;
     846                 :         672 :   ++proc->refs;
     847                 :         672 :   proc->declared_at = expr->where;
     848                 :         672 :   gfc_commit_symbol (proc);
     849                 :         672 :   free (name);
     850                 :             : 
     851                 :         672 :   split_expr_at_caf_ref (expr, sub_ns, &post_caf_ref_expr, false);
     852                 :             : 
     853                 :         672 :   if (ns->proc_name->attr.flavor == FL_MODULE)
     854                 :           1 :     proc->module = ns->proc_name->name;
     855                 :         672 :   gfc_set_sym_referenced (proc);
     856                 :             :   /* Set up formal arguments.  */
     857                 :         672 :   gfc_formal_arglist **argptr = &proc->formal;
     858                 :             : #define ADD_ARG(name, nsym, stype, skind, sintent)                             \
     859                 :             :   gfc_get_symbol (name, sub_ns, &nsym);                                        \
     860                 :             :   nsym->ts.type = stype;                                                       \
     861                 :             :   nsym->ts.kind = skind;                                                       \
     862                 :             :   nsym->attr.flavor = FL_PARAMETER;                                            \
     863                 :             :   nsym->attr.dummy = 1;                                                        \
     864                 :             :   nsym->attr.intent = sintent;                                                 \
     865                 :             :   nsym->declared_at = expr->where;                                             \
     866                 :             :   gfc_set_sym_referenced (nsym);                                               \
     867                 :             :   *argptr = gfc_get_formal_arglist ();                                         \
     868                 :             :   (*argptr)->sym = nsym;                                                       \
     869                 :             :   argptr = &(*argptr)->next
     870                 :             : 
     871                 :         672 :   name = xasprintf ("add_data_%s_%s_%d", mname, tname, caf_sym_cnt);
     872                 :         672 :   ADD_ARG (name, get_data, BT_DERIVED, 0, INTENT_IN);
     873                 :         672 :   gfc_commit_symbol (get_data);
     874                 :         672 :   free (name);
     875                 :             : 
     876                 :         672 :   ADD_ARG ("caller_image", caller_image, BT_INTEGER, gfc_default_integer_kind,
     877                 :             :            INTENT_IN);
     878                 :         672 :   gfc_commit_symbol (caller_image);
     879                 :             : 
     880                 :         672 :   ADD_ARG ("buffer", buffer, expr->ts.type, expr->ts.kind, INTENT_INOUT);
     881                 :         672 :   buffer->ts = expr->ts;
     882                 :         672 :   if (expr_rank)
     883                 :             :     {
     884                 :         402 :       buffer->as = gfc_get_array_spec ();
     885                 :         402 :       buffer->as->rank = expr_rank;
     886                 :         402 :       if (expr->shape)
     887                 :             :         {
     888                 :         227 :           buffer->as->type = AS_EXPLICIT;
     889                 :         566 :           for (int d = 0; d < expr_rank; ++d)
     890                 :             :             {
     891                 :         339 :               buffer->as->lower[d]
     892                 :         339 :                 = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
     893                 :             :                                          &gfc_current_locus);
     894                 :         339 :               gfc_mpz_set_hwi (buffer->as->lower[d]->value.integer, 1);
     895                 :         339 :               buffer->as->upper[d]
     896                 :         339 :                 = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
     897                 :             :                                          &gfc_current_locus);
     898                 :         339 :               gfc_mpz_set_hwi (buffer->as->upper[d]->value.integer,
     899                 :         339 :                                gfc_mpz_get_hwi (expr->shape[d]));
     900                 :             :             }
     901                 :         227 :           buffer->attr.allocatable = 1;
     902                 :             :         }
     903                 :             :       else
     904                 :             :         {
     905                 :         175 :           buffer->as->type = AS_DEFERRED;
     906                 :         175 :           buffer->attr.allocatable = 1;
     907                 :             :         }
     908                 :         402 :       buffer->attr.dimension = 1;
     909                 :             :     }
     910                 :             :   else
     911                 :         270 :     buffer->attr.pointer = 1;
     912                 :         672 :   if (buffer->ts.type == BT_CHARACTER)
     913                 :             :     {
     914                 :          49 :       buffer->ts.u.cl = gfc_get_charlen ();
     915                 :          49 :       *buffer->ts.u.cl = *expr->ts.u.cl;
     916                 :          49 :       buffer->ts.u.cl->length = gfc_copy_expr (expr->ts.u.cl->length);
     917                 :             :     }
     918                 :         672 :   gfc_commit_symbol (buffer);
     919                 :             : 
     920                 :         672 :   ADD_ARG ("free_buffer", free_buffer, BT_LOGICAL, gfc_default_logical_kind,
     921                 :             :            INTENT_OUT);
     922                 :         672 :   gfc_commit_symbol (free_buffer);
     923                 :             : 
     924                 :             :   // ADD_ARG (expr->symtree->name, base, BT_VOID, INTENT_IN);
     925                 :         672 :   base = post_caf_ref_expr->symtree->n.sym;
     926                 :         672 :   gfc_set_sym_referenced (base);
     927                 :         672 :   gfc_commit_symbol (base);
     928                 :         672 :   *argptr = gfc_get_formal_arglist ();
     929                 :         672 :   (*argptr)->sym = base;
     930                 :         672 :   argptr = &(*argptr)->next;
     931                 :         672 :   gfc_commit_symbol (base);
     932                 :             : #undef ADD_ARG
     933                 :             : 
     934                 :             :   /* Set up code.  */
     935                 :         672 :   if (expr->rank != 0)
     936                 :             :     {
     937                 :             :       /* Code: old_buffer_ptr = C_LOC (buffer);  */
     938                 :         402 :       code = sub_ns->code = gfc_get_code (EXEC_ASSIGN);
     939                 :         402 :       gfc_get_symbol ("old_buffer_data", sub_ns, &old_buffer_data);
     940                 :         402 :       old_buffer_data->ts.type = BT_VOID;
     941                 :         402 :       old_buffer_data->attr.flavor = FL_VARIABLE;
     942                 :         402 :       old_buffer_data->declared_at = expr->where;
     943                 :         402 :       gfc_set_sym_referenced (old_buffer_data);
     944                 :         402 :       gfc_commit_symbol (old_buffer_data);
     945                 :         402 :       code->loc = expr->where;
     946                 :         402 :       code->expr1 = gfc_lval_expr_from_sym (old_buffer_data);
     947                 :         402 :       code->expr2 = gfc_build_intrinsic_call (ns, GFC_ISYM_C_LOC, "C_LOC",
     948                 :             :                                               gfc_current_locus, 1,
     949                 :             :                                               gfc_lval_expr_from_sym (buffer));
     950                 :         402 :       code->next = gfc_get_code (EXEC_ASSIGN);
     951                 :         402 :       code = code->next;
     952                 :             :     }
     953                 :             :   else
     954                 :         270 :     code = sub_ns->code = gfc_get_code (EXEC_POINTER_ASSIGN);
     955                 :             : 
     956                 :             :   /* Code: buffer = expr;  */
     957                 :         672 :   code->loc = expr->where;
     958                 :         672 :   code->expr1 = gfc_lval_expr_from_sym (buffer);
     959                 :         672 :   code->expr2 = post_caf_ref_expr;
     960                 :         672 :   remove_caf_ref (post_caf_ref_expr);
     961                 :         672 :   get_data->ts.u.derived
     962                 :         672 :     = create_caf_add_data_parameter_type (code->expr2, ns, get_data);
     963                 :         672 :   if (code->expr2->rank == 0 && code->expr2->ts.type != BT_CHARACTER)
     964                 :         237 :     code->expr2 = gfc_build_intrinsic_call (ns, GFC_ISYM_C_LOC, "C_LOC",
     965                 :             :                                             gfc_current_locus, 1, code->expr2);
     966                 :             : 
     967                 :             :   /* Code: *free_buffer = old_buffer_ptr /= C_LOC (buffer); for rank != 0 or
     968                 :             :    *       *free_buffer = 0; for rank == 0.  */
     969                 :         672 :   code->next = gfc_get_code (EXEC_ASSIGN);
     970                 :         672 :   code = code->next;
     971                 :         672 :   code->loc = expr->where;
     972                 :         672 :   code->expr1 = gfc_lval_expr_from_sym (free_buffer);
     973                 :         672 :   if (expr->rank != 0)
     974                 :             :     {
     975                 :         402 :       code->expr2 = gfc_get_operator_expr (
     976                 :             :         &gfc_current_locus, INTRINSIC_NE_OS,
     977                 :             :         gfc_lval_expr_from_sym (old_buffer_data),
     978                 :             :         gfc_build_intrinsic_call (ns, GFC_ISYM_C_LOC, "C_LOC",
     979                 :             :                                   gfc_current_locus, 1,
     980                 :             :                                   gfc_lval_expr_from_sym (buffer)));
     981                 :         402 :       code->expr2->ts.type = BT_LOGICAL;
     982                 :         402 :       code->expr2->ts.kind = gfc_default_logical_kind;
     983                 :             :     }
     984                 :             :   else
     985                 :             :     {
     986                 :         270 :       code->expr2 = gfc_get_logical_expr (gfc_default_logical_kind,
     987                 :             :                                           &gfc_current_locus, false);
     988                 :             :     }
     989                 :             : 
     990                 :         672 :   cb = gfc_lval_expr_from_sym (extproc);
     991                 :         672 :   cb->ts.interface = extproc;
     992                 :             : 
     993                 :         672 :   if (caf_accessor_prepend)
     994                 :             :     {
     995                 :             :       gfc_code *c = caf_accessor_prepend;
     996                 :             :       /* Find last in chain.  */
     997                 :           1 :       for (; c->next; c = c->next)
     998                 :             :         ;
     999                 :           1 :       c->next = sub_ns->code;
    1000                 :           1 :       sub_ns->code = caf_accessor_prepend;
    1001                 :             :     }
    1002                 :         672 :   caf_accessor_prepend = backup_caf_accessor_prepend;
    1003                 :         672 :   return cb;
    1004                 :             : }
    1005                 :             : 
    1006                 :             : void
    1007                 :         730 : add_caf_get_from_remote (gfc_expr *e)
    1008                 :             : {
    1009                 :         730 :   gfc_expr *wrapper, *tmp_expr, *get_from_remote_expr,
    1010                 :             :     *get_from_remote_hash_expr;
    1011                 :         730 :   gfc_ref *ref;
    1012                 :         730 :   int n;
    1013                 :             : 
    1014                 :         773 :   for (ref = e->ref; ref; ref = ref->next)
    1015                 :         773 :     if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
    1016                 :             :       break;
    1017                 :         730 :   if (ref == NULL)
    1018                 :             :     return;
    1019                 :             : 
    1020                 :        1349 :   for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++)
    1021                 :         767 :     if (ref->u.ar.dimen_type[n] != DIMEN_ELEMENT)
    1022                 :             :       return;
    1023                 :             : 
    1024                 :         582 :   tmp_expr = XCNEW (gfc_expr);
    1025                 :         582 :   *tmp_expr = *e;
    1026                 :         582 :   get_from_remote_expr = create_get_callback (tmp_expr);
    1027                 :         582 :   get_from_remote_hash_expr = gfc_get_expr ();
    1028                 :         582 :   get_from_remote_hash_expr->expr_type = EXPR_CONSTANT;
    1029                 :         582 :   get_from_remote_hash_expr->ts.type = BT_INTEGER;
    1030                 :         582 :   get_from_remote_hash_expr->ts.kind = gfc_default_integer_kind;
    1031                 :         582 :   get_from_remote_hash_expr->where = tmp_expr->where;
    1032                 :         582 :   mpz_init_set_ui (get_from_remote_hash_expr->value.integer,
    1033                 :         582 :                    gfc_hash_value (get_from_remote_expr->symtree->n.sym));
    1034                 :         582 :   wrapper = gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_CAF_GET,
    1035                 :             :                                       "caf_get", tmp_expr->where, 3, tmp_expr,
    1036                 :             :                                       get_from_remote_hash_expr,
    1037                 :             :                                       get_from_remote_expr);
    1038                 :         582 :   gfc_add_caf_accessor (get_from_remote_hash_expr, get_from_remote_expr);
    1039                 :         582 :   wrapper->ts = e->ts;
    1040                 :         582 :   wrapper->rank = e->rank;
    1041                 :         582 :   wrapper->corank = e->corank;
    1042                 :         582 :   if (e->rank)
    1043                 :         358 :     wrapper->shape = gfc_copy_shape (e->shape, e->rank);
    1044                 :         582 :   *e = *wrapper;
    1045                 :         582 :   free (wrapper);
    1046                 :             : }
    1047                 :             : 
    1048                 :             : static gfc_expr *
    1049                 :          66 : create_allocated_callback (gfc_expr *expr)
    1050                 :             : {
    1051                 :          66 :   gfc_namespace *ns;
    1052                 :          66 :   gfc_symbol *extproc, *proc, *result, *base, *add_data, *caller_image;
    1053                 :          66 :   char tname[GFC_MAX_SYMBOL_LEN + 1];
    1054                 :          66 :   char *name;
    1055                 :          66 :   const char *mname;
    1056                 :          66 :   gfc_expr *cb, *post_caf_ref_expr;
    1057                 :          66 :   gfc_code *code;
    1058                 :          66 :   gfc_code *backup_caf_accessor_prepend = caf_accessor_prepend;
    1059                 :          66 :   caf_accessor_prepend = nullptr;
    1060                 :          66 :   gfc_expr swp;
    1061                 :             : 
    1062                 :             :   /* Find the top-level namespace.  */
    1063                 :          66 :   for (ns = gfc_current_ns; ns->parent; ns = ns->parent)
    1064                 :             :     ;
    1065                 :             : 
    1066                 :          66 :   if (expr->value.function.actual->expr->expr_type == EXPR_VARIABLE)
    1067                 :          66 :     strcpy (tname, expr->value.function.actual->expr->symtree->name);
    1068                 :             :   else
    1069                 :           0 :     strcpy (tname, "dummy");
    1070                 :          66 :   if (expr->value.function.actual->expr->symtree->n.sym->module)
    1071                 :           0 :     mname = expr->value.function.actual->expr->symtree->n.sym->module;
    1072                 :             :   else
    1073                 :             :     mname = "main";
    1074                 :          66 :   name = xasprintf ("_caf_present_%s_%s_%d", mname, tname, ++caf_sym_cnt);
    1075                 :          66 :   gfc_get_symbol (name, ns, &extproc);
    1076                 :          66 :   extproc->declared_at = expr->where;
    1077                 :          66 :   gfc_set_sym_referenced (extproc);
    1078                 :          66 :   ++extproc->refs;
    1079                 :          66 :   gfc_commit_symbol (extproc);
    1080                 :             : 
    1081                 :             :   /* Set up namespace.  */
    1082                 :          66 :   gfc_namespace *sub_ns = gfc_get_namespace (ns, 0);
    1083                 :          66 :   sub_ns->sibling = ns->contained;
    1084                 :          66 :   ns->contained = sub_ns;
    1085                 :          66 :   sub_ns->resolved = 1;
    1086                 :             :   /* Set up procedure symbol.  */
    1087                 :          66 :   gfc_find_symbol (name, sub_ns, 1, &proc);
    1088                 :          66 :   sub_ns->proc_name = proc;
    1089                 :          66 :   proc->attr.if_source = IFSRC_DECL;
    1090                 :          66 :   proc->attr.access = ACCESS_PUBLIC;
    1091                 :          66 :   gfc_add_subroutine (&proc->attr, name, NULL);
    1092                 :          66 :   proc->attr.host_assoc = 1;
    1093                 :          66 :   proc->attr.always_explicit = 1;
    1094                 :          66 :   proc->declared_at = expr->where;
    1095                 :          66 :   ++proc->refs;
    1096                 :          66 :   gfc_commit_symbol (proc);
    1097                 :          66 :   free (name);
    1098                 :             : 
    1099                 :          66 :   split_expr_at_caf_ref (expr->value.function.actual->expr, sub_ns,
    1100                 :             :                          &post_caf_ref_expr, true);
    1101                 :             : 
    1102                 :          66 :   if (ns->proc_name->attr.flavor == FL_MODULE)
    1103                 :           0 :     proc->module = ns->proc_name->name;
    1104                 :          66 :   gfc_set_sym_referenced (proc);
    1105                 :             :   /* Set up formal arguments.  */
    1106                 :          66 :   gfc_formal_arglist **argptr = &proc->formal;
    1107                 :             : #define ADD_ARG(name, nsym, stype, skind, sintent)                             \
    1108                 :             :   gfc_get_symbol (name, sub_ns, &nsym);                                        \
    1109                 :             :   nsym->ts.type = stype;                                                       \
    1110                 :             :   nsym->ts.kind = skind;                                                       \
    1111                 :             :   nsym->attr.flavor = FL_PARAMETER;                                            \
    1112                 :             :   nsym->attr.dummy = 1;                                                        \
    1113                 :             :   nsym->attr.intent = sintent;                                                 \
    1114                 :             :   nsym->declared_at = expr->where;                                             \
    1115                 :             :   gfc_set_sym_referenced (nsym);                                               \
    1116                 :             :   *argptr = gfc_get_formal_arglist ();                                         \
    1117                 :             :   (*argptr)->sym = nsym;                                                       \
    1118                 :             :   argptr = &(*argptr)->next
    1119                 :             : 
    1120                 :          66 :   name = xasprintf ("add_data_%s_%s_%d", mname, tname, ++caf_sym_cnt);
    1121                 :          66 :   ADD_ARG (name, add_data, BT_DERIVED, 0, INTENT_IN);
    1122                 :          66 :   gfc_commit_symbol (add_data);
    1123                 :          66 :   free (name);
    1124                 :          66 :   ADD_ARG ("caller_image", caller_image, BT_INTEGER, gfc_default_integer_kind,
    1125                 :             :            INTENT_IN);
    1126                 :          66 :   gfc_commit_symbol (caller_image);
    1127                 :             : 
    1128                 :          66 :   ADD_ARG ("result", result, BT_LOGICAL, gfc_default_logical_kind, INTENT_OUT);
    1129                 :          66 :   gfc_commit_symbol (result);
    1130                 :             : 
    1131                 :             :   // ADD_ARG (expr->symtree->name, base, BT_VOID, INTENT_IN);
    1132                 :          66 :   base = post_caf_ref_expr->symtree->n.sym;
    1133                 :          66 :   gfc_set_sym_referenced (base);
    1134                 :          66 :   gfc_commit_symbol (base);
    1135                 :          66 :   *argptr = gfc_get_formal_arglist ();
    1136                 :          66 :   (*argptr)->sym = base;
    1137                 :          66 :   argptr = &(*argptr)->next;
    1138                 :          66 :   gfc_commit_symbol (base);
    1139                 :             : #undef ADD_ARG
    1140                 :             : 
    1141                 :             :   /* Set up code.  */
    1142                 :             :   /* Code: result = post_caf_ref_expr;  */
    1143                 :          66 :   code = sub_ns->code = gfc_get_code (EXEC_ASSIGN);
    1144                 :          66 :   code->loc = expr->where;
    1145                 :          66 :   code->expr1 = gfc_lval_expr_from_sym (result);
    1146                 :          66 :   swp = *expr;
    1147                 :          66 :   *expr = *swp.value.function.actual->expr;
    1148                 :          66 :   swp.value.function.actual->expr = nullptr;
    1149                 :          66 :   code->expr2 = gfc_copy_expr (&swp);
    1150                 :          66 :   code->expr2->value.function.actual->expr = post_caf_ref_expr;
    1151                 :             : 
    1152                 :          66 :   remove_caf_ref (code->expr2->value.function.actual->expr, true);
    1153                 :          66 :   add_data->ts.u.derived
    1154                 :          66 :     = create_caf_add_data_parameter_type (post_caf_ref_expr, ns, add_data);
    1155                 :             : 
    1156                 :          66 :   cb = gfc_lval_expr_from_sym (extproc);
    1157                 :          66 :   cb->ts.interface = extproc;
    1158                 :             : 
    1159                 :          66 :   if (caf_accessor_prepend)
    1160                 :             :     {
    1161                 :             :       gfc_code *c = caf_accessor_prepend;
    1162                 :             :       /* Find last in chain.  */
    1163                 :           0 :       for (; c->next; c = c->next)
    1164                 :             :         ;
    1165                 :           0 :       c->next = sub_ns->code;
    1166                 :           0 :       sub_ns->code = caf_accessor_prepend;
    1167                 :             :     }
    1168                 :          66 :   caf_accessor_prepend = backup_caf_accessor_prepend;
    1169                 :          66 :   return cb;
    1170                 :             : }
    1171                 :             : 
    1172                 :             : static void
    1173                 :          66 : rewrite_caf_allocated (gfc_expr **e)
    1174                 :             : {
    1175                 :          66 :   gfc_expr *present_fn_expr, *present_hash_expr, *wrapper;
    1176                 :             : 
    1177                 :          66 :   present_fn_expr = create_allocated_callback (*e);
    1178                 :             : 
    1179                 :          66 :   present_hash_expr = gfc_get_expr ();
    1180                 :          66 :   present_hash_expr->expr_type = EXPR_CONSTANT;
    1181                 :          66 :   present_hash_expr->ts.type = BT_INTEGER;
    1182                 :          66 :   present_hash_expr->ts.kind = gfc_default_integer_kind;
    1183                 :          66 :   present_hash_expr->where = (*e)->where;
    1184                 :          66 :   mpz_init_set_ui (present_hash_expr->value.integer,
    1185                 :          66 :                    gfc_hash_value (present_fn_expr->symtree->n.sym));
    1186                 :          66 :   wrapper
    1187                 :          66 :     = gfc_build_intrinsic_call (gfc_current_ns,
    1188                 :             :                                 GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE,
    1189                 :             :                                 "caf_is_present_on_remote", (*e)->where, 3, *e,
    1190                 :             :                                 present_hash_expr, present_fn_expr);
    1191                 :          66 :   gfc_add_caf_accessor (present_hash_expr, present_fn_expr);
    1192                 :          66 :   *e = wrapper;
    1193                 :          66 : }
    1194                 :             : 
    1195                 :             : static gfc_expr *
    1196                 :         378 : create_send_callback (gfc_expr *expr, gfc_expr *rhs)
    1197                 :             : {
    1198                 :         378 :   gfc_namespace *ns;
    1199                 :         378 :   gfc_symbol *extproc, *proc, *buffer, *base, *send_data, *caller_image;
    1200                 :         378 :   char tname[GFC_MAX_SYMBOL_LEN + 1];
    1201                 :         378 :   char *name;
    1202                 :         378 :   const char *mname;
    1203                 :         378 :   gfc_expr *cb, *post_caf_ref_expr;
    1204                 :         378 :   gfc_code *code;
    1205                 :         378 :   gfc_code *backup_caf_accessor_prepend = caf_accessor_prepend;
    1206                 :         378 :   caf_accessor_prepend = nullptr;
    1207                 :             : 
    1208                 :             :   /* Find the top-level namespace.  */
    1209                 :         458 :   for (ns = gfc_current_ns; ns->parent; ns = ns->parent)
    1210                 :             :     ;
    1211                 :             : 
    1212                 :         378 :   if (expr->expr_type == EXPR_VARIABLE)
    1213                 :         378 :     strcpy (tname, expr->symtree->name);
    1214                 :             :   else
    1215                 :           0 :     strcpy (tname, "dummy");
    1216                 :         378 :   if (expr->symtree->n.sym->module)
    1217                 :           0 :     mname = expr->symtree->n.sym->module;
    1218                 :             :   else
    1219                 :             :     mname = "main";
    1220                 :         378 :   name = xasprintf ("_caf_accessor_%s_%s_%d", mname, tname, ++caf_sym_cnt);
    1221                 :         378 :   gfc_get_symbol (name, ns, &extproc);
    1222                 :         378 :   extproc->declared_at = expr->where;
    1223                 :         378 :   gfc_set_sym_referenced (extproc);
    1224                 :         378 :   ++extproc->refs;
    1225                 :         378 :   gfc_commit_symbol (extproc);
    1226                 :             : 
    1227                 :             :   /* Set up namespace.  */
    1228                 :         378 :   gfc_namespace *sub_ns = gfc_get_namespace (ns, 0);
    1229                 :         378 :   sub_ns->sibling = ns->contained;
    1230                 :         378 :   ns->contained = sub_ns;
    1231                 :         378 :   sub_ns->resolved = 1;
    1232                 :             :   /* Set up procedure symbol.  */
    1233                 :         378 :   gfc_find_symbol (name, sub_ns, 1, &proc);
    1234                 :         378 :   sub_ns->proc_name = proc;
    1235                 :         378 :   proc->attr.if_source = IFSRC_DECL;
    1236                 :         378 :   proc->attr.access = ACCESS_PUBLIC;
    1237                 :         378 :   gfc_add_subroutine (&proc->attr, name, NULL);
    1238                 :         378 :   proc->attr.host_assoc = 1;
    1239                 :         378 :   proc->attr.always_explicit = 1;
    1240                 :         378 :   ++proc->refs;
    1241                 :         378 :   proc->declared_at = expr->where;
    1242                 :         378 :   gfc_commit_symbol (proc);
    1243                 :         378 :   free (name);
    1244                 :             : 
    1245                 :         378 :   split_expr_at_caf_ref (expr, sub_ns, &post_caf_ref_expr, true);
    1246                 :             : 
    1247                 :         378 :   if (ns->proc_name->attr.flavor == FL_MODULE)
    1248                 :           1 :     proc->module = ns->proc_name->name;
    1249                 :         378 :   gfc_set_sym_referenced (proc);
    1250                 :             :   /* Set up formal arguments.  */
    1251                 :         378 :   gfc_formal_arglist **argptr = &proc->formal;
    1252                 :             : #define ADD_ARG(name, nsym, stype, skind, sintent)                             \
    1253                 :             :   gfc_get_symbol (name, sub_ns, &nsym);                                        \
    1254                 :             :   nsym->ts.type = stype;                                                       \
    1255                 :             :   nsym->ts.kind = skind;                                                       \
    1256                 :             :   nsym->attr.flavor = FL_PARAMETER;                                            \
    1257                 :             :   nsym->attr.dummy = 1;                                                        \
    1258                 :             :   nsym->attr.intent = sintent;                                                 \
    1259                 :             :   nsym->declared_at = expr->where;                                             \
    1260                 :             :   gfc_set_sym_referenced (nsym);                                               \
    1261                 :             :   *argptr = gfc_get_formal_arglist ();                                         \
    1262                 :             :   (*argptr)->sym = nsym;                                                       \
    1263                 :             :   argptr = &(*argptr)->next
    1264                 :             : 
    1265                 :         378 :   name = xasprintf ("add_send_data_%s_%s_%d", mname, tname, caf_sym_cnt);
    1266                 :         378 :   ADD_ARG (name, send_data, BT_DERIVED, 0, INTENT_IN);
    1267                 :         378 :   gfc_commit_symbol (send_data);
    1268                 :         378 :   free (name);
    1269                 :             : 
    1270                 :         378 :   ADD_ARG ("caller_image", caller_image, BT_INTEGER, gfc_default_integer_kind,
    1271                 :             :            INTENT_IN);
    1272                 :         378 :   gfc_commit_symbol (caller_image);
    1273                 :             : 
    1274                 :             :   // ADD_ARG (expr->symtree->name, base, BT_VOID, INTENT_IN);
    1275                 :         378 :   base = post_caf_ref_expr->symtree->n.sym;
    1276                 :         378 :   base->attr.intent = INTENT_INOUT;
    1277                 :         378 :   gfc_set_sym_referenced (base);
    1278                 :         378 :   gfc_commit_symbol (base);
    1279                 :         378 :   *argptr = gfc_get_formal_arglist ();
    1280                 :         378 :   (*argptr)->sym = base;
    1281                 :         378 :   argptr = &(*argptr)->next;
    1282                 :         378 :   gfc_commit_symbol (base);
    1283                 :             : 
    1284                 :         378 :   ADD_ARG ("buffer", buffer, rhs->ts.type, rhs->ts.kind, INTENT_IN);
    1285                 :         378 :   buffer->ts = rhs->ts;
    1286                 :         378 :   if (rhs->rank)
    1287                 :             :     {
    1288                 :         166 :       buffer->as = gfc_get_array_spec ();
    1289                 :         166 :       buffer->as->rank = rhs->rank;
    1290                 :         166 :       buffer->as->type = AS_DEFERRED;
    1291                 :         166 :       buffer->attr.allocatable = 1;
    1292                 :         166 :       buffer->attr.dimension = 1;
    1293                 :             :     }
    1294                 :         378 :   if (buffer->ts.type == BT_CHARACTER)
    1295                 :             :     {
    1296                 :          58 :       buffer->ts.u.cl = gfc_get_charlen ();
    1297                 :          58 :       *buffer->ts.u.cl = *rhs->ts.u.cl;
    1298                 :          58 :       buffer->ts.deferred = 1;
    1299                 :          58 :       buffer->ts.u.cl->length = gfc_copy_expr (rhs->ts.u.cl->length);
    1300                 :             :     }
    1301                 :         378 :   gfc_commit_symbol (buffer);
    1302                 :             : #undef ADD_ARG
    1303                 :             : 
    1304                 :             :   /* Set up code.  */
    1305                 :             :   /* Code: base = buffer;  */
    1306                 :         378 :   code = sub_ns->code = gfc_get_code (EXEC_ASSIGN);
    1307                 :         378 :   code->loc = expr->where;
    1308                 :         378 :   code->expr1 = post_caf_ref_expr;
    1309                 :         378 :   if (code->expr1->ts.type == BT_CHARACTER
    1310                 :          58 :       && code->expr1->ts.kind != buffer->ts.kind)
    1311                 :             :     {
    1312                 :          28 :       bool converted;
    1313                 :          28 :       code->expr2 = gfc_lval_expr_from_sym (buffer);
    1314                 :          28 :       converted = gfc_convert_chartype (code->expr2, &code->expr1->ts);
    1315                 :          28 :       gcc_assert (converted);
    1316                 :             :     }
    1317                 :         350 :   else if (code->expr1->ts.type != buffer->ts.type)
    1318                 :             :     {
    1319                 :         126 :       bool converted;
    1320                 :         126 :       code->expr2 = gfc_lval_expr_from_sym (buffer);
    1321                 :         252 :       converted = gfc_convert_type_warn (code->expr2, &code->expr1->ts, 0, 0,
    1322                 :         126 :                                          buffer->attr.dimension);
    1323                 :         126 :       gcc_assert (converted);
    1324                 :             :     }
    1325                 :             :   else
    1326                 :         224 :     code->expr2 = gfc_lval_expr_from_sym (buffer);
    1327                 :         378 :   remove_caf_ref (post_caf_ref_expr);
    1328                 :         378 :   send_data->ts.u.derived
    1329                 :         378 :     = create_caf_add_data_parameter_type (code->expr1, ns, send_data);
    1330                 :             : 
    1331                 :         378 :   cb = gfc_lval_expr_from_sym (extproc);
    1332                 :         378 :   cb->ts.interface = extproc;
    1333                 :             : 
    1334                 :         378 :   if (caf_accessor_prepend)
    1335                 :             :     {
    1336                 :             :       gfc_code *c = caf_accessor_prepend;
    1337                 :             :       /* Find last in chain.  */
    1338                 :           0 :       for (; c->next; c = c->next)
    1339                 :             :         ;
    1340                 :           0 :       c->next = sub_ns->code;
    1341                 :           0 :       sub_ns->code = caf_accessor_prepend;
    1342                 :             :     }
    1343                 :         378 :   caf_accessor_prepend = backup_caf_accessor_prepend;
    1344                 :         378 :   return cb;
    1345                 :             : }
    1346                 :             : 
    1347                 :             : static void
    1348                 :         378 : rewrite_caf_send (gfc_code *c)
    1349                 :             : {
    1350                 :         378 :   gfc_expr *send_to_remote_expr, *send_to_remote_hash_expr, *lhs, *rhs;
    1351                 :         378 :   gfc_actual_arglist *arg = c->ext.actual;
    1352                 :             : 
    1353                 :         378 :   lhs = arg->expr;
    1354                 :         378 :   arg = arg->next;
    1355                 :         378 :   rhs = arg->expr;
    1356                 :             :   /* Detect an already rewritten caf_send.  */
    1357                 :         378 :   if (arg->next && arg->next->expr->expr_type == EXPR_CONSTANT
    1358                 :           0 :       && arg->next->next && arg->next->next->expr->expr_type == EXPR_VARIABLE)
    1359                 :             :     return;
    1360                 :             : 
    1361                 :         378 :   send_to_remote_expr = create_send_callback (lhs, rhs);
    1362                 :         378 :   send_to_remote_hash_expr = gfc_get_expr ();
    1363                 :         378 :   send_to_remote_hash_expr->expr_type = EXPR_CONSTANT;
    1364                 :         378 :   send_to_remote_hash_expr->ts.type = BT_INTEGER;
    1365                 :         378 :   send_to_remote_hash_expr->ts.kind = gfc_default_integer_kind;
    1366                 :         378 :   send_to_remote_hash_expr->where = lhs->where;
    1367                 :         378 :   mpz_init_set_ui (send_to_remote_hash_expr->value.integer,
    1368                 :         378 :                    gfc_hash_value (send_to_remote_expr->symtree->n.sym));
    1369                 :         378 :   arg->next = gfc_get_actual_arglist ();
    1370                 :         378 :   arg = arg->next;
    1371                 :         378 :   arg->expr = send_to_remote_hash_expr;
    1372                 :         378 :   arg->next = gfc_get_actual_arglist ();
    1373                 :         378 :   arg = arg->next;
    1374                 :         378 :   arg->expr = send_to_remote_expr;
    1375                 :         378 :   gfc_add_caf_accessor (send_to_remote_hash_expr, send_to_remote_expr);
    1376                 :             : 
    1377                 :         378 :   if (gfc_is_coindexed (rhs))
    1378                 :             :     {
    1379                 :          90 :       gfc_expr *get_from_remote_expr, *get_from_remote_hash_expr;
    1380                 :             : 
    1381                 :          90 :       c->resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SENDGET);
    1382                 :          90 :       get_from_remote_expr = create_get_callback (rhs);
    1383                 :          90 :       get_from_remote_hash_expr = gfc_get_expr ();
    1384                 :          90 :       get_from_remote_hash_expr->expr_type = EXPR_CONSTANT;
    1385                 :          90 :       get_from_remote_hash_expr->ts.type = BT_INTEGER;
    1386                 :          90 :       get_from_remote_hash_expr->ts.kind = gfc_default_integer_kind;
    1387                 :          90 :       get_from_remote_hash_expr->where = rhs->where;
    1388                 :          90 :       mpz_init_set_ui (get_from_remote_hash_expr->value.integer,
    1389                 :          90 :                        gfc_hash_value (get_from_remote_expr->symtree->n.sym));
    1390                 :          90 :       arg->next = gfc_get_actual_arglist ();
    1391                 :          90 :       arg = arg->next;
    1392                 :          90 :       arg->expr = get_from_remote_hash_expr;
    1393                 :          90 :       arg->next = gfc_get_actual_arglist ();
    1394                 :          90 :       arg = arg->next;
    1395                 :          90 :       arg->expr = get_from_remote_expr;
    1396                 :          90 :       gfc_add_caf_accessor (get_from_remote_hash_expr, get_from_remote_expr);
    1397                 :             :     }
    1398                 :             : }
    1399                 :             : 
    1400                 :             : static int
    1401                 :       46141 : coindexed_expr_callback (gfc_expr **e, int *walk_subtrees,
    1402                 :             :                          void *data ATTRIBUTE_UNUSED)
    1403                 :             : {
    1404                 :       46141 :   *walk_subtrees = 1;
    1405                 :             : 
    1406                 :       46141 :   switch ((*e)->expr_type)
    1407                 :             :     {
    1408                 :       17581 :     case EXPR_VARIABLE:
    1409                 :       17581 :       if (!caf_on_lhs && gfc_is_coindexed (*e))
    1410                 :             :         {
    1411                 :         729 :           add_caf_get_from_remote (*e);
    1412                 :         729 :           *walk_subtrees = 0;
    1413                 :             :         }
    1414                 :             :       /* Clear the flag to rewrite caf_gets in sub expressions of the lhs.  */
    1415                 :       17581 :       caf_on_lhs = false;
    1416                 :       17581 :       break;
    1417                 :        5253 :     case EXPR_FUNCTION:
    1418                 :        5253 :       if ((*e)->value.function.isym)
    1419                 :        5200 :         switch ((*e)->value.function.isym->id)
    1420                 :             :           {
    1421                 :         377 :           case GFC_ISYM_ALLOCATED:
    1422                 :         377 :             if ((*e)->value.function.actual->expr
    1423                 :         377 :                 && gfc_is_coindexed ((*e)->value.function.actual->expr))
    1424                 :             :               {
    1425                 :          66 :                 rewrite_caf_allocated (e);
    1426                 :          66 :                 *walk_subtrees = 0;
    1427                 :             :               }
    1428                 :             :             break;
    1429                 :           2 :           case GFC_ISYM_CAF_GET:
    1430                 :           2 :           case GFC_ISYM_CAF_IS_PRESENT_ON_REMOTE:
    1431                 :           2 :             *walk_subtrees = 0;
    1432                 :           2 :             break;
    1433                 :             :           default:
    1434                 :             :             break;
    1435                 :             :           }
    1436                 :             :     default:
    1437                 :             :       break;
    1438                 :             :     }
    1439                 :             : 
    1440                 :       46141 :   return 0;
    1441                 :             : }
    1442                 :             : 
    1443                 :             : static int
    1444                 :       11591 : coindexed_code_callback (gfc_code **c, int *walk_subtrees,
    1445                 :             :                          void *data ATTRIBUTE_UNUSED)
    1446                 :             : {
    1447                 :       11591 :   int ws = 1;
    1448                 :       11591 :   current_code = c;
    1449                 :             : 
    1450                 :       11591 :   switch ((*c)->op)
    1451                 :             :     {
    1452                 :        4408 :     case EXEC_ASSIGN:
    1453                 :        4408 :     case EXEC_POINTER_ASSIGN:
    1454                 :        4408 :       caf_on_lhs = true;
    1455                 :        4408 :       coindexed_expr_callback (&((*c)->expr1), &ws, NULL);
    1456                 :        4408 :       caf_on_lhs = false;
    1457                 :        4408 :       ws = 1;
    1458                 :        4408 :       coindexed_expr_callback (&((*c)->expr2), &ws, NULL);
    1459                 :        4408 :       *walk_subtrees = ws;
    1460                 :        4408 :       break;
    1461                 :          68 :     case EXEC_LOCK:
    1462                 :          68 :     case EXEC_UNLOCK:
    1463                 :          68 :     case EXEC_EVENT_POST:
    1464                 :          68 :     case EXEC_EVENT_WAIT:
    1465                 :          68 :       *walk_subtrees = 0;
    1466                 :          68 :       break;
    1467                 :         691 :     case EXEC_CALL:
    1468                 :         691 :       *walk_subtrees = 1;
    1469                 :         691 :       if ((*c)->resolved_isym)
    1470                 :         555 :         switch ((*c)->resolved_isym->id)
    1471                 :             :           {
    1472                 :         378 :           case GFC_ISYM_CAF_SEND:
    1473                 :         378 :             rewrite_caf_send (*c);
    1474                 :         378 :             *walk_subtrees = 0;
    1475                 :         378 :             break;
    1476                 :           0 :           case GFC_ISYM_CAF_SENDGET:
    1477                 :             :             /* Seldomly this routine is called again with the symbol already
    1478                 :             :                changed to CAF_SENDGET.  Do not process the subtree again.  The
    1479                 :             :                rewrite has already been done by rewrite_caf_send ().  */
    1480                 :           0 :             *walk_subtrees = 0;
    1481                 :           0 :             break;
    1482                 :          91 :           case GFC_ISYM_ATOMIC_ADD:
    1483                 :          91 :           case GFC_ISYM_ATOMIC_AND:
    1484                 :          91 :           case GFC_ISYM_ATOMIC_CAS:
    1485                 :          91 :           case GFC_ISYM_ATOMIC_DEF:
    1486                 :          91 :           case GFC_ISYM_ATOMIC_FETCH_ADD:
    1487                 :          91 :           case GFC_ISYM_ATOMIC_FETCH_AND:
    1488                 :          91 :           case GFC_ISYM_ATOMIC_FETCH_OR:
    1489                 :          91 :           case GFC_ISYM_ATOMIC_FETCH_XOR:
    1490                 :          91 :           case GFC_ISYM_ATOMIC_OR:
    1491                 :          91 :           case GFC_ISYM_ATOMIC_REF:
    1492                 :          91 :           case GFC_ISYM_ATOMIC_XOR:
    1493                 :          91 :             *walk_subtrees = 0;
    1494                 :          91 :             break;
    1495                 :             :           default:
    1496                 :             :             break;
    1497                 :             :           }
    1498                 :             :       break;
    1499                 :        6424 :     default:
    1500                 :        6424 :       *walk_subtrees = 1;
    1501                 :        6424 :       break;
    1502                 :             :     }
    1503                 :       11591 :   return 0;
    1504                 :             : }
    1505                 :             : 
    1506                 :             : void
    1507                 :        1503 : gfc_coarray_rewrite (gfc_namespace *ns)
    1508                 :             : {
    1509                 :        1503 :   gfc_namespace *saved_ns = gfc_current_ns;
    1510                 :        1503 :   gfc_current_ns = ns;
    1511                 :             : 
    1512                 :        1503 :   if (flag_coarray == GFC_FCOARRAY_LIB)
    1513                 :             :     {
    1514                 :        1503 :       gfc_code_walker (&ns->code, coindexed_code_callback,
    1515                 :             :                        coindexed_expr_callback, NULL);
    1516                 :             : 
    1517                 :        2660 :       for (gfc_namespace *cns = ns->contained; cns; cns = cns->sibling)
    1518                 :        1157 :         gfc_coarray_rewrite (cns);
    1519                 :             :     }
    1520                 :             : 
    1521                 :        1503 :   gfc_current_ns = saved_ns;
    1522                 :        1503 : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.