LCOV - code coverage report
Current view: top level - gcc/fortran - coarray.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.4 % 961 840
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-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.