LCOV - code coverage report
Current view: top level - gcc/fortran - trans-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.7 % 7048 6674
Test Date: 2026-03-28 14:25:54 Functions: 96.1 % 155 149
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Expression translation
       2              :    Copyright (C) 2002-2026 Free Software Foundation, Inc.
       3              :    Contributed by Paul Brook <paul@nowt.org>
       4              :    and Steven Bosscher <s.bosscher@student.tudelft.nl>
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it under
       9              : the terms of the GNU General Public License as published by the Free
      10              : Software Foundation; either version 3, or (at your option) any later
      11              : version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : /* trans-expr.cc-- generate GENERIC trees for gfc_expr.  */
      23              : 
      24              : #define INCLUDE_MEMORY
      25              : #include "config.h"
      26              : #include "system.h"
      27              : #include "coretypes.h"
      28              : #include "options.h"
      29              : #include "tree.h"
      30              : #include "gfortran.h"
      31              : #include "trans.h"
      32              : #include "stringpool.h"
      33              : #include "diagnostic-core.h"  /* For fatal_error.  */
      34              : #include "fold-const.h"
      35              : #include "langhooks.h"
      36              : #include "arith.h"
      37              : #include "constructor.h"
      38              : #include "trans-const.h"
      39              : #include "trans-types.h"
      40              : #include "trans-array.h"
      41              : /* Only for gfc_trans_assign and gfc_trans_pointer_assign.  */
      42              : #include "trans-stmt.h"
      43              : #include "dependency.h"
      44              : #include "gimplify.h"
      45              : #include "tm.h"               /* For CHAR_TYPE_SIZE.  */
      46              : 
      47              : 
      48              : /* Calculate the number of characters in a string.  */
      49              : 
      50              : static tree
      51        36069 : gfc_get_character_len (tree type)
      52              : {
      53        36069 :   tree len;
      54              : 
      55        36069 :   gcc_assert (type && TREE_CODE (type) == ARRAY_TYPE
      56              :               && TYPE_STRING_FLAG (type));
      57              : 
      58        36069 :   len = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
      59        36069 :   len = (len) ? (len) : (integer_zero_node);
      60        36069 :   return fold_convert (gfc_charlen_type_node, len);
      61              : }
      62              : 
      63              : 
      64              : 
      65              : /* Calculate the number of bytes in a string.  */
      66              : 
      67              : tree
      68        36069 : gfc_get_character_len_in_bytes (tree type)
      69              : {
      70        36069 :   tree tmp, len;
      71              : 
      72        36069 :   gcc_assert (type && TREE_CODE (type) == ARRAY_TYPE
      73              :               && TYPE_STRING_FLAG (type));
      74              : 
      75        36069 :   tmp = TYPE_SIZE_UNIT (TREE_TYPE (type));
      76        72138 :   tmp = (tmp && !integer_zerop (tmp))
      77        72138 :     ? (fold_convert (gfc_charlen_type_node, tmp)) : (NULL_TREE);
      78        36069 :   len = gfc_get_character_len (type);
      79        36069 :   if (tmp && len && !integer_zerop (len))
      80        35297 :     len = fold_build2_loc (input_location, MULT_EXPR,
      81              :                            gfc_charlen_type_node, len, tmp);
      82        36069 :   return len;
      83              : }
      84              : 
      85              : 
      86              : /* Convert a scalar to an array descriptor. To be used for assumed-rank
      87              :    arrays.  */
      88              : 
      89              : static tree
      90         6269 : get_scalar_to_descriptor_type (tree scalar, symbol_attribute attr)
      91              : {
      92         6269 :   enum gfc_array_kind akind;
      93         6269 :   tree *lbound = NULL, *ubound = NULL;
      94         6269 :   int codim = 0;
      95              : 
      96         6269 :   if (attr.pointer)
      97              :     akind = GFC_ARRAY_POINTER_CONT;
      98         5917 :   else if (attr.allocatable)
      99              :     akind = GFC_ARRAY_ALLOCATABLE;
     100              :   else
     101         5148 :     akind = GFC_ARRAY_ASSUMED_SHAPE_CONT;
     102              : 
     103         6269 :   if (POINTER_TYPE_P (TREE_TYPE (scalar)))
     104         5322 :     scalar = TREE_TYPE (scalar);
     105         6269 :   if (TYPE_LANG_SPECIFIC (TREE_TYPE (scalar)))
     106              :     {
     107         4727 :       struct lang_type *lang_specific = TYPE_LANG_SPECIFIC (TREE_TYPE (scalar));
     108         4727 :       codim = lang_specific->corank;
     109         4727 :       lbound = lang_specific->lbound;
     110         4727 :       ubound = lang_specific->ubound;
     111              :     }
     112         6269 :   return gfc_get_array_type_bounds (TREE_TYPE (scalar), 0, codim, lbound,
     113              :                                     ubound, 1, akind,
     114         6269 :                                     !(attr.pointer || attr.target));
     115              : }
     116              : 
     117              : tree
     118         5591 : gfc_conv_scalar_to_descriptor (gfc_se *se, tree scalar, symbol_attribute attr)
     119              : {
     120         5591 :   tree desc, type, etype;
     121              : 
     122         5591 :   type = get_scalar_to_descriptor_type (scalar, attr);
     123         5591 :   etype = TREE_TYPE (scalar);
     124         5591 :   desc = gfc_create_var (type, "desc");
     125         5591 :   DECL_ARTIFICIAL (desc) = 1;
     126              : 
     127         5591 :   if (CONSTANT_CLASS_P (scalar))
     128              :     {
     129           54 :       tree tmp;
     130           54 :       tmp = gfc_create_var (TREE_TYPE (scalar), "scalar");
     131           54 :       gfc_add_modify (&se->pre, tmp, scalar);
     132           54 :       scalar = tmp;
     133              :     }
     134         5591 :   if (!POINTER_TYPE_P (TREE_TYPE (scalar)))
     135          947 :     scalar = gfc_build_addr_expr (NULL_TREE, scalar);
     136         4644 :   else if (TREE_TYPE (etype) && TREE_CODE (TREE_TYPE (etype)) == ARRAY_TYPE)
     137          158 :     etype = TREE_TYPE (etype);
     138         5591 :   gfc_add_modify (&se->pre, gfc_conv_descriptor_dtype (desc),
     139              :                   gfc_get_dtype_rank_type (0, etype));
     140         5591 :   gfc_conv_descriptor_data_set (&se->pre, desc, scalar);
     141         5591 :   gfc_conv_descriptor_span_set (&se->pre, desc,
     142              :                                 gfc_conv_descriptor_elem_len (desc));
     143              : 
     144              :   /* Copy pointer address back - but only if it could have changed and
     145              :      if the actual argument is a pointer and not, e.g., NULL().  */
     146         5591 :   if ((attr.pointer || attr.allocatable) && attr.intent != INTENT_IN)
     147          846 :     gfc_add_modify (&se->post, scalar,
     148          423 :                     fold_convert (TREE_TYPE (scalar),
     149              :                                   gfc_conv_descriptor_data_get (desc)));
     150         5591 :   return desc;
     151              : }
     152              : 
     153              : 
     154              : /* Get the coarray token from the ultimate array or component ref.
     155              :    Returns a NULL_TREE, when the ref object is not allocatable or pointer.  */
     156              : 
     157              : tree
     158          508 : gfc_get_ultimate_alloc_ptr_comps_caf_token (gfc_se *outerse, gfc_expr *expr)
     159              : {
     160          508 :   gfc_symbol *sym = expr->symtree->n.sym;
     161         1016 :   bool is_coarray = sym->ts.type == BT_CLASS
     162          508 :                       ? CLASS_DATA (sym)->attr.codimension
     163          463 :                       : sym->attr.codimension;
     164          508 :   gfc_expr *caf_expr = gfc_copy_expr (expr);
     165          508 :   gfc_ref *ref = caf_expr->ref, *last_caf_ref = NULL;
     166              : 
     167         1610 :   while (ref)
     168              :     {
     169         1102 :       if (ref->type == REF_COMPONENT
     170          415 :           && (ref->u.c.component->attr.allocatable
     171          104 :               || ref->u.c.component->attr.pointer)
     172          413 :           && (is_coarray || ref->u.c.component->attr.codimension))
     173         1102 :           last_caf_ref = ref;
     174         1102 :       ref = ref->next;
     175              :     }
     176              : 
     177          508 :   if (last_caf_ref == NULL)
     178              :     {
     179          178 :       gfc_free_expr (caf_expr);
     180          178 :       return NULL_TREE;
     181              :     }
     182              : 
     183          143 :   tree comp = last_caf_ref->u.c.component->caf_token
     184          330 :                 ? gfc_comp_caf_token (last_caf_ref->u.c.component)
     185              :                 : NULL_TREE,
     186              :        caf;
     187          330 :   gfc_se se;
     188          330 :   bool comp_ref = !last_caf_ref->u.c.component->attr.dimension;
     189          330 :   if (comp == NULL_TREE && comp_ref)
     190              :     {
     191           46 :       gfc_free_expr (caf_expr);
     192           46 :       return NULL_TREE;
     193              :     }
     194          284 :   gfc_init_se (&se, outerse);
     195          284 :   gfc_free_ref_list (last_caf_ref->next);
     196          284 :   last_caf_ref->next = NULL;
     197          284 :   caf_expr->rank = comp_ref ? 0 : last_caf_ref->u.c.component->as->rank;
     198          568 :   caf_expr->corank = last_caf_ref->u.c.component->as
     199          284 :                        ? last_caf_ref->u.c.component->as->corank
     200              :                        : expr->corank;
     201          284 :   se.want_pointer = comp_ref;
     202          284 :   gfc_conv_expr (&se, caf_expr);
     203          284 :   gfc_add_block_to_block (&outerse->pre, &se.pre);
     204              : 
     205          284 :   if (TREE_CODE (se.expr) == COMPONENT_REF && comp_ref)
     206          143 :     se.expr = TREE_OPERAND (se.expr, 0);
     207          284 :   gfc_free_expr (caf_expr);
     208              : 
     209          284 :   if (comp_ref)
     210          143 :     caf = fold_build3_loc (input_location, COMPONENT_REF,
     211          143 :                            TREE_TYPE (comp), se.expr, comp, NULL_TREE);
     212              :   else
     213          141 :     caf = gfc_conv_descriptor_token (se.expr);
     214          284 :   return gfc_build_addr_expr (NULL_TREE, caf);
     215              : }
     216              : 
     217              : 
     218              : /* This is the seed for an eventual trans-class.c
     219              : 
     220              :    The following parameters should not be used directly since they might
     221              :    in future implementations.  Use the corresponding APIs.  */
     222              : #define CLASS_DATA_FIELD 0
     223              : #define CLASS_VPTR_FIELD 1
     224              : #define CLASS_LEN_FIELD 2
     225              : #define VTABLE_HASH_FIELD 0
     226              : #define VTABLE_SIZE_FIELD 1
     227              : #define VTABLE_EXTENDS_FIELD 2
     228              : #define VTABLE_DEF_INIT_FIELD 3
     229              : #define VTABLE_COPY_FIELD 4
     230              : #define VTABLE_FINAL_FIELD 5
     231              : #define VTABLE_DEALLOCATE_FIELD 6
     232              : 
     233              : 
     234              : tree
     235           40 : gfc_class_set_static_fields (tree decl, tree vptr, tree data)
     236              : {
     237           40 :   tree tmp;
     238           40 :   tree field;
     239           40 :   vec<constructor_elt, va_gc> *init = NULL;
     240              : 
     241           40 :   field = TYPE_FIELDS (TREE_TYPE (decl));
     242           40 :   tmp = gfc_advance_chain (field, CLASS_DATA_FIELD);
     243           40 :   CONSTRUCTOR_APPEND_ELT (init, tmp, data);
     244              : 
     245           40 :   tmp = gfc_advance_chain (field, CLASS_VPTR_FIELD);
     246           40 :   CONSTRUCTOR_APPEND_ELT (init, tmp, vptr);
     247              : 
     248           40 :   return build_constructor (TREE_TYPE (decl), init);
     249              : }
     250              : 
     251              : 
     252              : tree
     253        31664 : gfc_class_data_get (tree decl)
     254              : {
     255        31664 :   tree data;
     256        31664 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     257         5340 :     decl = build_fold_indirect_ref_loc (input_location, decl);
     258        31664 :   data = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
     259              :                             CLASS_DATA_FIELD);
     260        31664 :   return fold_build3_loc (input_location, COMPONENT_REF,
     261        31664 :                           TREE_TYPE (data), decl, data,
     262        31664 :                           NULL_TREE);
     263              : }
     264              : 
     265              : 
     266              : tree
     267        44948 : gfc_class_vptr_get (tree decl)
     268              : {
     269        44948 :   tree vptr;
     270              :   /* For class arrays decl may be a temporary descriptor handle, the vptr is
     271              :      then available through the saved descriptor.  */
     272        27681 :   if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
     273        46724 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
     274         1273 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     275        44948 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     276         2338 :     decl = build_fold_indirect_ref_loc (input_location, decl);
     277        44948 :   vptr = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
     278              :                             CLASS_VPTR_FIELD);
     279        44948 :   return fold_build3_loc (input_location, COMPONENT_REF,
     280        44948 :                           TREE_TYPE (vptr), decl, vptr,
     281        44948 :                           NULL_TREE);
     282              : }
     283              : 
     284              : 
     285              : tree
     286         6662 : gfc_class_len_get (tree decl)
     287              : {
     288         6662 :   tree len;
     289              :   /* For class arrays decl may be a temporary descriptor handle, the len is
     290              :      then available through the saved descriptor.  */
     291         4791 :   if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
     292         6911 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
     293           85 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     294         6662 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     295          662 :     decl = build_fold_indirect_ref_loc (input_location, decl);
     296         6662 :   len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
     297              :                            CLASS_LEN_FIELD);
     298         6662 :   return fold_build3_loc (input_location, COMPONENT_REF,
     299         6662 :                           TREE_TYPE (len), decl, len,
     300         6662 :                           NULL_TREE);
     301              : }
     302              : 
     303              : 
     304              : /* Try to get the _len component of a class.  When the class is not unlimited
     305              :    poly, i.e. no _len field exists, then return a zero node.  */
     306              : 
     307              : static tree
     308         4913 : gfc_class_len_or_zero_get (tree decl)
     309              : {
     310         4913 :   tree len;
     311              :   /* For class arrays decl may be a temporary descriptor handle, the vptr is
     312              :      then available through the saved descriptor.  */
     313         2927 :   if (VAR_P (decl) && DECL_LANG_SPECIFIC (decl)
     314         4961 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
     315            0 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     316         4913 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     317           12 :     decl = build_fold_indirect_ref_loc (input_location, decl);
     318         4913 :   len = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (decl)),
     319              :                            CLASS_LEN_FIELD);
     320         6772 :   return len != NULL_TREE ? fold_build3_loc (input_location, COMPONENT_REF,
     321         1859 :                                              TREE_TYPE (len), decl, len,
     322              :                                              NULL_TREE)
     323         3054 :     : build_zero_cst (gfc_charlen_type_node);
     324              : }
     325              : 
     326              : 
     327              : tree
     328         4753 : gfc_resize_class_size_with_len (stmtblock_t * block, tree class_expr, tree size)
     329              : {
     330         4753 :   tree tmp;
     331         4753 :   tree tmp2;
     332         4753 :   tree type;
     333              : 
     334         4753 :   tmp = gfc_class_len_or_zero_get (class_expr);
     335              : 
     336              :   /* Include the len value in the element size if present.  */
     337         4753 :   if (!integer_zerop (tmp))
     338              :     {
     339         1699 :       type = TREE_TYPE (size);
     340         1699 :       if (block)
     341              :         {
     342          986 :           size = gfc_evaluate_now (size, block);
     343          986 :           tmp = gfc_evaluate_now (fold_convert (type , tmp), block);
     344              :         }
     345              :       else
     346          713 :         tmp = fold_convert (type , tmp);
     347         1699 :       tmp2 = fold_build2_loc (input_location, MULT_EXPR,
     348              :                               type, size, tmp);
     349         1699 :       tmp = fold_build2_loc (input_location, GT_EXPR,
     350              :                              logical_type_node, tmp,
     351              :                              build_zero_cst (type));
     352         1699 :       size = fold_build3_loc (input_location, COND_EXPR,
     353              :                               type, tmp, tmp2, size);
     354              :     }
     355              :   else
     356              :     return size;
     357              : 
     358         1699 :   if (block)
     359          986 :     size = gfc_evaluate_now (size, block);
     360              : 
     361              :   return size;
     362              : }
     363              : 
     364              : 
     365              : /* Get the specified FIELD from the VPTR.  */
     366              : 
     367              : static tree
     368        21069 : vptr_field_get (tree vptr, int fieldno)
     369              : {
     370        21069 :   tree field;
     371        21069 :   vptr = build_fold_indirect_ref_loc (input_location, vptr);
     372        21069 :   field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (vptr)),
     373              :                              fieldno);
     374        21069 :   field = fold_build3_loc (input_location, COMPONENT_REF,
     375        21069 :                            TREE_TYPE (field), vptr, field,
     376              :                            NULL_TREE);
     377        21069 :   gcc_assert (field);
     378        21069 :   return field;
     379              : }
     380              : 
     381              : 
     382              : /* Get the field from the class' vptr.  */
     383              : 
     384              : static tree
     385         9788 : class_vtab_field_get (tree decl, int fieldno)
     386              : {
     387         9788 :   tree vptr;
     388         9788 :   vptr = gfc_class_vptr_get (decl);
     389         9788 :   return vptr_field_get (vptr, fieldno);
     390              : }
     391              : 
     392              : 
     393              : /* Define a macro for creating the class_vtab_* and vptr_* accessors in
     394              :    unison.  */
     395              : #define VTAB_GET_FIELD_GEN(name, field) tree \
     396              : gfc_class_vtab_## name ##_get (tree cl) \
     397              : { \
     398              :   return class_vtab_field_get (cl, field); \
     399              : } \
     400              :  \
     401              : tree \
     402              : gfc_vptr_## name ##_get (tree vptr) \
     403              : { \
     404              :   return vptr_field_get (vptr, field); \
     405              : }
     406              : 
     407          183 : VTAB_GET_FIELD_GEN (hash, VTABLE_HASH_FIELD)
     408            0 : VTAB_GET_FIELD_GEN (extends, VTABLE_EXTENDS_FIELD)
     409            0 : VTAB_GET_FIELD_GEN (def_init, VTABLE_DEF_INIT_FIELD)
     410         4330 : VTAB_GET_FIELD_GEN (copy, VTABLE_COPY_FIELD)
     411         1812 : VTAB_GET_FIELD_GEN (final, VTABLE_FINAL_FIELD)
     412         1023 : VTAB_GET_FIELD_GEN (deallocate, VTABLE_DEALLOCATE_FIELD)
     413              : #undef VTAB_GET_FIELD_GEN
     414              : 
     415              : /* The size field is returned as an array index type.  Therefore treat
     416              :    it and only it specially.  */
     417              : 
     418              : tree
     419         7814 : gfc_class_vtab_size_get (tree cl)
     420              : {
     421         7814 :   tree size;
     422         7814 :   size = class_vtab_field_get (cl, VTABLE_SIZE_FIELD);
     423              :   /* Always return size as an array index type.  */
     424         7814 :   size = fold_convert (gfc_array_index_type, size);
     425         7814 :   gcc_assert (size);
     426         7814 :   return size;
     427              : }
     428              : 
     429              : tree
     430         5907 : gfc_vptr_size_get (tree vptr)
     431              : {
     432         5907 :   tree size;
     433         5907 :   size = vptr_field_get (vptr, VTABLE_SIZE_FIELD);
     434              :   /* Always return size as an array index type.  */
     435         5907 :   size = fold_convert (gfc_array_index_type, size);
     436         5907 :   gcc_assert (size);
     437         5907 :   return size;
     438              : }
     439              : 
     440              : 
     441              : #undef CLASS_DATA_FIELD
     442              : #undef CLASS_VPTR_FIELD
     443              : #undef CLASS_LEN_FIELD
     444              : #undef VTABLE_HASH_FIELD
     445              : #undef VTABLE_SIZE_FIELD
     446              : #undef VTABLE_EXTENDS_FIELD
     447              : #undef VTABLE_DEF_INIT_FIELD
     448              : #undef VTABLE_COPY_FIELD
     449              : #undef VTABLE_FINAL_FIELD
     450              : 
     451              : 
     452              : /* IF ts is null (default), search for the last _class ref in the chain
     453              :    of references of the expression and cut the chain there.  Although
     454              :    this routine is similiar to class.cc:gfc_add_component_ref (), there
     455              :    is a significant difference: gfc_add_component_ref () concentrates
     456              :    on an array ref that is the last ref in the chain and is oblivious
     457              :    to the kind of refs following.
     458              :    ELSE IF ts is non-null the cut is at the class entity or component
     459              :    that is followed by an array reference, which is not an element.
     460              :    These calls come from trans-array.cc:build_class_array_ref, which
     461              :    handles scalarized class array references.*/
     462              : 
     463              : gfc_expr *
     464         9318 : gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold,
     465              :                                     gfc_typespec **ts)
     466              : {
     467         9318 :   gfc_expr *base_expr;
     468         9318 :   gfc_ref *ref, *class_ref, *tail = NULL, *array_ref;
     469              : 
     470              :   /* Find the last class reference.  */
     471         9318 :   class_ref = NULL;
     472         9318 :   array_ref = NULL;
     473              : 
     474         9318 :   if (ts)
     475              :     {
     476          405 :       if (e->symtree
     477          380 :           && e->symtree->n.sym->ts.type == BT_CLASS)
     478          380 :         *ts = &e->symtree->n.sym->ts;
     479              :       else
     480           25 :         *ts = NULL;
     481              :     }
     482              : 
     483        23433 :   for (ref = e->ref; ref; ref = ref->next)
     484              :     {
     485        14505 :       if (ts)
     486              :         {
     487          978 :           if (ref->type == REF_COMPONENT
     488          460 :               && ref->u.c.component->ts.type == BT_CLASS
     489            0 :               && ref->next && ref->next->type == REF_COMPONENT
     490            0 :               && !strcmp (ref->next->u.c.component->name, "_data")
     491            0 :               && ref->next->next
     492            0 :               && ref->next->next->type == REF_ARRAY
     493            0 :               && ref->next->next->u.ar.type != AR_ELEMENT)
     494              :             {
     495            0 :               *ts = &ref->u.c.component->ts;
     496            0 :               class_ref = ref;
     497            0 :               break;
     498              :             }
     499              : 
     500          978 :           if (ref->next == NULL)
     501              :             break;
     502              :         }
     503              :       else
     504              :         {
     505        13527 :           if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
     506        13527 :             array_ref = ref;
     507              : 
     508        13527 :           if (ref->type == REF_COMPONENT
     509         8151 :               && ref->u.c.component->ts.type == BT_CLASS)
     510              :             {
     511              :               /* Component to the right of a part reference with nonzero
     512              :                  rank must not have the ALLOCATABLE attribute.  If attempts
     513              :                  are made to reference such a component reference, an error
     514              :                  results followed by an ICE.  */
     515         1609 :               if (array_ref
     516           10 :                   && CLASS_DATA (ref->u.c.component)->attr.allocatable)
     517              :                 return NULL;
     518              :               class_ref = ref;
     519              :             }
     520              :         }
     521              :     }
     522              : 
     523         9308 :   if (ts && *ts == NULL)
     524              :     return NULL;
     525              : 
     526              :   /* Remove and store all subsequent references after the
     527              :      CLASS reference.  */
     528         9283 :   if (class_ref)
     529              :     {
     530         1407 :       tail = class_ref->next;
     531         1407 :       class_ref->next = NULL;
     532              :     }
     533         7876 :   else if (e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
     534              :     {
     535         7858 :       tail = e->ref;
     536         7858 :       e->ref = NULL;
     537              :     }
     538              : 
     539         9283 :   if (is_mold)
     540           61 :     base_expr = gfc_expr_to_initialize (e);
     541              :   else
     542         9222 :     base_expr = gfc_copy_expr (e);
     543              : 
     544              :   /* Restore the original tail expression.  */
     545         9283 :   if (class_ref)
     546              :     {
     547         1407 :       gfc_free_ref_list (class_ref->next);
     548         1407 :       class_ref->next = tail;
     549              :     }
     550         7876 :   else if (e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
     551              :     {
     552         7858 :       gfc_free_ref_list (e->ref);
     553         7858 :       e->ref = tail;
     554              :     }
     555              :   return base_expr;
     556              : }
     557              : 
     558              : /* Reset the vptr to the declared type, e.g. after deallocation.
     559              :    Use the variable in CLASS_CONTAINER if available.  Otherwise, recreate
     560              :    one with e or class_type.  At least one of the two has to be set.  The
     561              :    generated assignment code is added at the end of BLOCK.  */
     562              : 
     563              : void
     564        10860 : gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container,
     565              :                 gfc_symbol *class_type)
     566              : {
     567        10860 :   tree vptr = NULL_TREE;
     568              : 
     569        10860 :   if (class_container != NULL_TREE)
     570         6404 :     vptr = gfc_get_vptr_from_expr (class_container);
     571              : 
     572         6404 :   if (vptr == NULL_TREE)
     573              :     {
     574         4463 :       gfc_se se;
     575         4463 :       gcc_assert (e);
     576              : 
     577              :       /* Evaluate the expression and obtain the vptr from it.  */
     578         4463 :       gfc_init_se (&se, NULL);
     579         4463 :       if (e->rank)
     580         2221 :         gfc_conv_expr_descriptor (&se, e);
     581              :       else
     582         2242 :         gfc_conv_expr (&se, e);
     583         4463 :       gfc_add_block_to_block (block, &se.pre);
     584              : 
     585         4463 :       vptr = gfc_get_vptr_from_expr (se.expr);
     586              :     }
     587              : 
     588              :   /* If a vptr is not found, we can do nothing more.  */
     589         4463 :   if (vptr == NULL_TREE)
     590              :     return;
     591              : 
     592        10850 :   if (UNLIMITED_POLY (e)
     593         9824 :       || UNLIMITED_POLY (class_type)
     594              :       /* When the class_type's source is not a symbol (e.g. a component's ts),
     595              :          then look at the _data-components type.  */
     596         1515 :       || (class_type != NULL && class_type->ts.type == BT_UNKNOWN
     597         1515 :           && class_type->components && class_type->components->ts.u.derived
     598         1509 :           && class_type->components->ts.u.derived->attr.unlimited_polymorphic))
     599         1194 :     gfc_add_modify (block, vptr, build_int_cst (TREE_TYPE (vptr), 0));
     600              :   else
     601              :     {
     602         9656 :       gfc_symbol *vtab, *type = nullptr;
     603         9656 :       tree vtable;
     604              : 
     605         9656 :       if (e)
     606         8309 :         type = e->ts.u.derived;
     607         1347 :       else if (class_type)
     608              :         {
     609         1347 :           if (class_type->ts.type == BT_CLASS)
     610            0 :             type = CLASS_DATA (class_type)->ts.u.derived;
     611              :           else
     612              :             type = class_type;
     613              :         }
     614         8309 :       gcc_assert (type);
     615              :       /* Return the vptr to the address of the declared type.  */
     616         9656 :       vtab = gfc_find_derived_vtab (type);
     617         9656 :       vtable = vtab->backend_decl;
     618         9656 :       if (vtable == NULL_TREE)
     619           76 :         vtable = gfc_get_symbol_decl (vtab);
     620         9656 :       vtable = gfc_build_addr_expr (NULL, vtable);
     621         9656 :       vtable = fold_convert (TREE_TYPE (vptr), vtable);
     622         9656 :       gfc_add_modify (block, vptr, vtable);
     623              :     }
     624              : }
     625              : 
     626              : /* Set the vptr of a class in to from the type given in from.  If from is NULL,
     627              :    then reset the vptr to the default or to.  */
     628              : 
     629              : void
     630          216 : gfc_class_set_vptr (stmtblock_t *block, tree to, tree from)
     631              : {
     632          216 :   tree tmp, vptr_ref;
     633          216 :   gfc_symbol *type;
     634              : 
     635          216 :   vptr_ref = gfc_get_vptr_from_expr (to);
     636          252 :   if (POINTER_TYPE_P (TREE_TYPE (from))
     637          216 :       && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (from))))
     638              :     {
     639           44 :       gfc_add_modify (block, vptr_ref,
     640           22 :                       fold_convert (TREE_TYPE (vptr_ref),
     641              :                                     gfc_get_vptr_from_expr (from)));
     642          238 :       return;
     643              :     }
     644          194 :   tmp = gfc_get_vptr_from_expr (from);
     645          194 :   if (tmp)
     646              :     {
     647          158 :       gfc_add_modify (block, vptr_ref,
     648          158 :                       fold_convert (TREE_TYPE (vptr_ref), tmp));
     649          158 :       return;
     650              :     }
     651           36 :   if (VAR_P (from)
     652           36 :       && strncmp (IDENTIFIER_POINTER (DECL_NAME (from)), "__vtab", 6) == 0)
     653              :     {
     654           36 :       gfc_add_modify (block, vptr_ref,
     655           36 :                       gfc_build_addr_expr (TREE_TYPE (vptr_ref), from));
     656           36 :       return;
     657              :     }
     658            0 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (from)))
     659            0 :       && GFC_CLASS_TYPE_P (
     660              :         TREE_TYPE (TREE_OPERAND (TREE_OPERAND (from, 0), 0))))
     661              :     {
     662            0 :       gfc_add_modify (block, vptr_ref,
     663            0 :                       fold_convert (TREE_TYPE (vptr_ref),
     664              :                                     gfc_get_vptr_from_expr (TREE_OPERAND (
     665              :                                       TREE_OPERAND (from, 0), 0))));
     666            0 :       return;
     667              :     }
     668              : 
     669              :   /* If nothing of the above matches, set the vtype according to the type.  */
     670            0 :   tmp = TREE_TYPE (from);
     671            0 :   if (POINTER_TYPE_P (tmp))
     672            0 :     tmp = TREE_TYPE (tmp);
     673            0 :   gfc_find_symbol (IDENTIFIER_POINTER (TYPE_NAME (tmp)), gfc_current_ns, 1,
     674              :                    &type);
     675            0 :   tmp = gfc_find_derived_vtab (type)->backend_decl;
     676            0 :   gcc_assert (tmp);
     677            0 :   gfc_add_modify (block, vptr_ref,
     678            0 :                   gfc_build_addr_expr (TREE_TYPE (vptr_ref), tmp));
     679              : }
     680              : 
     681              : /* Reset the len for unlimited polymorphic objects.  */
     682              : 
     683              : void
     684          630 : gfc_reset_len (stmtblock_t *block, gfc_expr *expr)
     685              : {
     686          630 :   gfc_expr *e;
     687          630 :   gfc_se se_len;
     688          630 :   e = gfc_find_and_cut_at_last_class_ref (expr);
     689          630 :   if (e == NULL)
     690            0 :     return;
     691          630 :   gfc_add_len_component (e);
     692          630 :   gfc_init_se (&se_len, NULL);
     693          630 :   gfc_conv_expr (&se_len, e);
     694          630 :   gfc_add_modify (block, se_len.expr,
     695          630 :                   fold_convert (TREE_TYPE (se_len.expr), integer_zero_node));
     696          630 :   gfc_free_expr (e);
     697              : }
     698              : 
     699              : 
     700              : /* Obtain the last class reference in a gfc_expr. Return NULL_TREE if no class
     701              :    reference is found. Note that it is up to the caller to avoid using this
     702              :    for expressions other than variables.  */
     703              : 
     704              : tree
     705         1391 : gfc_get_class_from_gfc_expr (gfc_expr *e)
     706              : {
     707         1391 :   gfc_expr *class_expr;
     708         1391 :   gfc_se cse;
     709         1391 :   class_expr = gfc_find_and_cut_at_last_class_ref (e);
     710         1391 :   if (class_expr == NULL)
     711              :     return NULL_TREE;
     712         1391 :   gfc_init_se (&cse, NULL);
     713         1391 :   gfc_conv_expr (&cse, class_expr);
     714         1391 :   gfc_free_expr (class_expr);
     715         1391 :   return cse.expr;
     716              : }
     717              : 
     718              : 
     719              : /* Obtain the last class reference in an expression.
     720              :    Return NULL_TREE if no class reference is found.  */
     721              : 
     722              : tree
     723       106003 : gfc_get_class_from_expr (tree expr)
     724              : {
     725       106003 :   tree tmp;
     726       106003 :   tree type;
     727       106003 :   bool array_descr_found = false;
     728       106003 :   bool comp_after_descr_found = false;
     729              : 
     730       273421 :   for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
     731              :     {
     732       273421 :       if (CONSTANT_CLASS_P (tmp))
     733              :         return NULL_TREE;
     734              : 
     735       273384 :       type = TREE_TYPE (tmp);
     736       317125 :       while (type)
     737              :         {
     738       309251 :           if (GFC_CLASS_TYPE_P (type))
     739              :             return tmp;
     740       289785 :           if (GFC_DESCRIPTOR_TYPE_P (type))
     741        34644 :             array_descr_found = true;
     742       289785 :           if (type != TYPE_CANONICAL (type))
     743        43741 :             type = TYPE_CANONICAL (type);
     744              :           else
     745              :             type = NULL_TREE;
     746              :         }
     747       253918 :       if (VAR_P (tmp) || TREE_CODE (tmp) == PARM_DECL)
     748              :         break;
     749              : 
     750              :       /* Avoid walking up the reference chain too far.  For class arrays, the
     751              :          array descriptor is a direct component (through a pointer) of the class
     752              :          container.  So there is exactly one COMPONENT_REF between a class
     753              :          container and its child array descriptor.  After seeing an array
     754              :          descriptor, we can give up on the second COMPONENT_REF we see, if no
     755              :          class container was found until that point.  */
     756       167418 :       if (array_descr_found)
     757              :         {
     758         7355 :           if (comp_after_descr_found)
     759              :             {
     760           12 :               if (TREE_CODE (tmp) == COMPONENT_REF)
     761              :                 return NULL_TREE;
     762              :             }
     763         7343 :           else if (TREE_CODE (tmp) == COMPONENT_REF)
     764         7355 :             comp_after_descr_found = true;
     765              :         }
     766              :     }
     767              : 
     768        86500 :   if (POINTER_TYPE_P (TREE_TYPE (tmp)))
     769        58080 :     tmp = build_fold_indirect_ref_loc (input_location, tmp);
     770              : 
     771        86500 :   if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
     772              :     return tmp;
     773              : 
     774              :   return NULL_TREE;
     775              : }
     776              : 
     777              : 
     778              : /* Obtain the vptr of the last class reference in an expression.
     779              :    Return NULL_TREE if no class reference is found.  */
     780              : 
     781              : tree
     782        11479 : gfc_get_vptr_from_expr (tree expr)
     783              : {
     784        11479 :   tree tmp;
     785              : 
     786        11479 :   tmp = gfc_get_class_from_expr (expr);
     787              : 
     788        11479 :   if (tmp != NULL_TREE)
     789        11420 :     return gfc_class_vptr_get (tmp);
     790              : 
     791              :   return NULL_TREE;
     792              : }
     793              : 
     794              : static void
     795         2311 : copy_coarray_desc_part (stmtblock_t *block, tree dest, tree src)
     796              : {
     797         2311 :   tree src_type = TREE_TYPE (src);
     798         2311 :   if (TYPE_LANG_SPECIFIC (src_type) && TYPE_LANG_SPECIFIC (src_type)->corank)
     799              :     {
     800          135 :       struct lang_type *lang_specific = TYPE_LANG_SPECIFIC (src_type);
     801          270 :       for (int c = 0; c < lang_specific->corank; ++c)
     802              :         {
     803          135 :           int dim = lang_specific->rank + c;
     804          135 :           tree codim = gfc_rank_cst[dim];
     805              : 
     806          135 :           if (lang_specific->lbound[dim])
     807           54 :             gfc_conv_descriptor_lbound_set (block, dest, codim,
     808              :                                             lang_specific->lbound[dim]);
     809              :           else
     810           81 :             gfc_conv_descriptor_lbound_set (
     811              :               block, dest, codim, gfc_conv_descriptor_lbound_get (src, codim));
     812          135 :           if (dim + 1 < lang_specific->corank)
     813              :             {
     814            0 :               if (lang_specific->ubound[dim])
     815            0 :                 gfc_conv_descriptor_ubound_set (block, dest, codim,
     816              :                                                 lang_specific->ubound[dim]);
     817              :               else
     818            0 :                 gfc_conv_descriptor_ubound_set (
     819              :                   block, dest, codim,
     820              :                   gfc_conv_descriptor_ubound_get (src, codim));
     821              :             }
     822              :         }
     823              :     }
     824         2311 : }
     825              : 
     826              : void
     827         1989 : gfc_class_array_data_assign (stmtblock_t *block, tree lhs_desc, tree rhs_desc,
     828              :                              bool lhs_type)
     829              : {
     830         1989 :   tree lhs_dim, rhs_dim, type;
     831              : 
     832         1989 :   gfc_conv_descriptor_data_set (block, lhs_desc,
     833              :                                 gfc_conv_descriptor_data_get (rhs_desc));
     834         1989 :   gfc_conv_descriptor_offset_set (block, lhs_desc,
     835              :                                   gfc_conv_descriptor_offset_get (rhs_desc));
     836              : 
     837         1989 :   gfc_add_modify (block, gfc_conv_descriptor_dtype (lhs_desc),
     838              :                   gfc_conv_descriptor_dtype (rhs_desc));
     839              : 
     840              :   /* Assign the dimension as range-ref.  */
     841         1989 :   lhs_dim = gfc_get_descriptor_dimension (lhs_desc);
     842         1989 :   rhs_dim = gfc_get_descriptor_dimension (rhs_desc);
     843              : 
     844         1989 :   type = lhs_type ? TREE_TYPE (lhs_dim) : TREE_TYPE (rhs_dim);
     845         1989 :   lhs_dim = build4_loc (input_location, ARRAY_RANGE_REF, type, lhs_dim,
     846              :                         gfc_index_zero_node, NULL_TREE, NULL_TREE);
     847         1989 :   rhs_dim = build4_loc (input_location, ARRAY_RANGE_REF, type, rhs_dim,
     848              :                         gfc_index_zero_node, NULL_TREE, NULL_TREE);
     849         1989 :   gfc_add_modify (block, lhs_dim, rhs_dim);
     850              : 
     851              :   /* The corank dimensions are not copied by the ARRAY_RANGE_REF.  */
     852         1989 :   copy_coarray_desc_part (block, lhs_desc, rhs_desc);
     853         1989 : }
     854              : 
     855              : /* Takes a derived type expression and returns the address of a temporary
     856              :    class object of the 'declared' type.  If opt_vptr_src is not NULL, this is
     857              :    used for the temporary class object.
     858              :    optional_alloc_ptr is false when the dummy is neither allocatable
     859              :    nor a pointer; that's only relevant for the optional handling.
     860              :    The optional argument 'derived_array' is used to preserve the parmse
     861              :    expression for deallocation of allocatable components. Assumed rank
     862              :    formal arguments made this necessary.  */
     863              : void
     864         4895 : gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym,
     865              :                            tree opt_vptr_src, bool optional,
     866              :                            bool optional_alloc_ptr, const char *proc_name,
     867              :                            tree *derived_array)
     868              : {
     869         4895 :   tree cond_optional = NULL_TREE;
     870         4895 :   gfc_ss *ss;
     871         4895 :   tree ctree;
     872         4895 :   tree var;
     873         4895 :   tree tmp;
     874         4895 :   tree packed = NULL_TREE;
     875              : 
     876              :   /* The derived type needs to be converted to a temporary CLASS object.  */
     877         4895 :   tmp = gfc_typenode_for_spec (&fsym->ts);
     878         4895 :   var = gfc_create_var (tmp, "class");
     879              : 
     880              :   /* Set the vptr.  */
     881         4895 :   if (opt_vptr_src)
     882          116 :     gfc_class_set_vptr (&parmse->pre, var, opt_vptr_src);
     883              :   else
     884         4779 :     gfc_reset_vptr (&parmse->pre, e, var);
     885              : 
     886              :   /* Now set the data field.  */
     887         4895 :   ctree = gfc_class_data_get (var);
     888              : 
     889         4895 :   if (flag_coarray == GFC_FCOARRAY_LIB && CLASS_DATA (fsym)->attr.codimension)
     890              :     {
     891            4 :       tree token;
     892            4 :       tmp = gfc_get_tree_for_caf_expr (e);
     893            4 :       if (POINTER_TYPE_P (TREE_TYPE (tmp)))
     894            2 :         tmp = build_fold_indirect_ref (tmp);
     895            4 :       gfc_get_caf_token_offset (parmse, &token, nullptr, tmp, NULL_TREE, e);
     896            4 :       gfc_add_modify (&parmse->pre, gfc_conv_descriptor_token (ctree), token);
     897              :     }
     898              : 
     899         4895 :   if (optional)
     900          576 :     cond_optional = gfc_conv_expr_present (e->symtree->n.sym);
     901              : 
     902              :   /* Set the _len as early as possible.  */
     903         4895 :   if (fsym->ts.u.derived->components->ts.type == BT_DERIVED
     904         4895 :       && fsym->ts.u.derived->components->ts.u.derived->attr
     905         4895 :            .unlimited_polymorphic)
     906              :     {
     907              :       /* Take care about initializing the _len component correctly.  */
     908          386 :       tree len_tree = gfc_class_len_get (var);
     909          386 :       if (UNLIMITED_POLY (e))
     910              :         {
     911           12 :           gfc_expr *len;
     912           12 :           gfc_se se;
     913              : 
     914           12 :           len = gfc_find_and_cut_at_last_class_ref (e);
     915           12 :           gfc_add_len_component (len);
     916           12 :           gfc_init_se (&se, NULL);
     917           12 :           gfc_conv_expr (&se, len);
     918           12 :           if (optional)
     919            0 :             tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (se.expr),
     920              :                               cond_optional, se.expr,
     921            0 :                               fold_convert (TREE_TYPE (se.expr),
     922              :                                             integer_zero_node));
     923              :           else
     924           12 :             tmp = se.expr;
     925           12 :           gfc_free_expr (len);
     926           12 :         }
     927              :       else
     928          374 :         tmp = integer_zero_node;
     929          386 :       gfc_add_modify (&parmse->pre, len_tree,
     930          386 :                       fold_convert (TREE_TYPE (len_tree), tmp));
     931              :     }
     932              : 
     933         4895 :   if (parmse->expr && POINTER_TYPE_P (TREE_TYPE (parmse->expr)))
     934              :     {
     935              :       /* If there is a ready made pointer to a derived type, use it
     936              :          rather than evaluating the expression again.  */
     937          522 :       tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
     938          522 :       gfc_add_modify (&parmse->pre, ctree, tmp);
     939              :     }
     940         4373 :   else if (parmse->ss && parmse->ss->info && parmse->ss->info->useflags)
     941              :     {
     942              :       /* For an array reference in an elemental procedure call we need
     943              :          to retain the ss to provide the scalarized array reference.  */
     944          253 :       gfc_conv_expr_reference (parmse, e);
     945          253 :       tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
     946          253 :       if (optional)
     947            0 :         tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
     948              :                           cond_optional, tmp,
     949            0 :                           fold_convert (TREE_TYPE (tmp), null_pointer_node));
     950          253 :       gfc_add_modify (&parmse->pre, ctree, tmp);
     951              :     }
     952              :   else
     953              :     {
     954         4120 :       ss = gfc_walk_expr (e);
     955         4120 :       if (ss == gfc_ss_terminator)
     956              :         {
     957         2908 :           parmse->ss = NULL;
     958         2908 :           gfc_conv_expr_reference (parmse, e);
     959              : 
     960              :           /* Scalar to an assumed-rank array.  */
     961         2908 :           if (fsym->ts.u.derived->components->as)
     962              :             {
     963          322 :               tree type;
     964          322 :               type = get_scalar_to_descriptor_type (parmse->expr,
     965              :                                                     gfc_expr_attr (e));
     966          322 :               gfc_add_modify (&parmse->pre, gfc_conv_descriptor_dtype (ctree),
     967              :                               gfc_get_dtype (type));
     968          322 :               copy_coarray_desc_part (&parmse->pre, ctree, parmse->expr);
     969          322 :               if (optional)
     970          192 :                 parmse->expr = build3_loc (input_location, COND_EXPR,
     971           96 :                                            TREE_TYPE (parmse->expr),
     972              :                                            cond_optional, parmse->expr,
     973           96 :                                            fold_convert (TREE_TYPE (parmse->expr),
     974              :                                                          null_pointer_node));
     975          322 :               gfc_conv_descriptor_data_set (&parmse->pre, ctree, parmse->expr);
     976              :             }
     977              :           else
     978              :             {
     979         2586 :               tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
     980         2586 :               if (optional)
     981          132 :                 tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
     982              :                                   cond_optional, tmp,
     983          132 :                                   fold_convert (TREE_TYPE (tmp),
     984              :                                                 null_pointer_node));
     985         2586 :               gfc_add_modify (&parmse->pre, ctree, tmp);
     986              :             }
     987              :         }
     988              :       else
     989              :         {
     990         1212 :           stmtblock_t block;
     991         1212 :           gfc_init_block (&block);
     992         1212 :           gfc_ref *ref;
     993         1212 :           int dim;
     994         1212 :           tree lbshift = NULL_TREE;
     995              : 
     996              :           /* Array refs with sections indicate, that a for a formal argument
     997              :              expecting contiguous repacking needs to be done.  */
     998         2273 :           for (ref = e->ref; ref; ref = ref->next)
     999         1211 :             if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION)
    1000              :               break;
    1001         1212 :           if (IS_CLASS_ARRAY (fsym)
    1002         1104 :               && (CLASS_DATA (fsym)->as->type == AS_EXPLICIT
    1003          846 :                   || CLASS_DATA (fsym)->as->type == AS_ASSUMED_SIZE)
    1004          354 :               && (ref || e->rank != fsym->ts.u.derived->components->as->rank))
    1005          144 :             fsym->attr.contiguous = 1;
    1006              : 
    1007              :           /* Detect any array references with vector subscripts.  */
    1008         2417 :           for (ref = e->ref; ref; ref = ref->next)
    1009         1211 :             if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT
    1010         1169 :                 && ref->u.ar.type != AR_FULL)
    1011              :               {
    1012          336 :                 for (dim = 0; dim < ref->u.ar.dimen; dim++)
    1013          192 :                   if (ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
    1014              :                     break;
    1015          150 :                 if (dim < ref->u.ar.dimen)
    1016              :                   break;
    1017              :               }
    1018              :           /* Array references with vector subscripts and non-variable
    1019              :              expressions need be converted to a one-based descriptor.  */
    1020         1212 :           if (ref || e->expr_type != EXPR_VARIABLE)
    1021           49 :             lbshift = gfc_index_one_node;
    1022              : 
    1023         1212 :           parmse->expr = var;
    1024         1212 :           gfc_conv_array_parameter (parmse, e, false, fsym, proc_name, nullptr,
    1025              :                                     &lbshift, &packed);
    1026              : 
    1027         1212 :           if (derived_array && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (parmse->expr)))
    1028              :             {
    1029         1116 :               *derived_array
    1030         1116 :                 = gfc_create_var (TREE_TYPE (parmse->expr), "array");
    1031         1116 :               gfc_add_modify (&block, *derived_array, parmse->expr);
    1032              :             }
    1033              : 
    1034         1212 :           if (optional)
    1035              :             {
    1036          348 :               tmp = gfc_finish_block (&block);
    1037              : 
    1038          348 :               gfc_init_block (&block);
    1039          348 :               gfc_conv_descriptor_data_set (&block, ctree, null_pointer_node);
    1040          348 :               if (derived_array && *derived_array != NULL_TREE)
    1041          348 :                 gfc_conv_descriptor_data_set (&block, *derived_array,
    1042              :                                               null_pointer_node);
    1043              : 
    1044          348 :               tmp = build3_v (COND_EXPR, cond_optional, tmp,
    1045              :                               gfc_finish_block (&block));
    1046          348 :               gfc_add_expr_to_block (&parmse->pre, tmp);
    1047              :             }
    1048              :           else
    1049          864 :             gfc_add_block_to_block (&parmse->pre, &block);
    1050              :         }
    1051              :     }
    1052              : 
    1053              :   /* Pass the address of the class object.  */
    1054         4895 :   if (packed)
    1055           96 :     parmse->expr = packed;
    1056              :   else
    1057         4799 :     parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
    1058              : 
    1059         4895 :   if (optional && optional_alloc_ptr)
    1060           84 :     parmse->expr
    1061           84 :       = build3_loc (input_location, COND_EXPR, TREE_TYPE (parmse->expr),
    1062              :                     cond_optional, parmse->expr,
    1063           84 :                     fold_convert (TREE_TYPE (parmse->expr), null_pointer_node));
    1064         4895 : }
    1065              : 
    1066              : /* Create a new class container, which is required as scalar coarrays
    1067              :    have an array descriptor while normal scalars haven't. Optionally,
    1068              :    NULL pointer checks are added if the argument is OPTIONAL.  */
    1069              : 
    1070              : static void
    1071           48 : class_scalar_coarray_to_class (gfc_se *parmse, gfc_expr *e,
    1072              :                                gfc_typespec class_ts, bool optional)
    1073              : {
    1074           48 :   tree var, ctree, tmp;
    1075           48 :   stmtblock_t block;
    1076           48 :   gfc_ref *ref;
    1077           48 :   gfc_ref *class_ref;
    1078              : 
    1079           48 :   gfc_init_block (&block);
    1080              : 
    1081           48 :   class_ref = NULL;
    1082          144 :   for (ref = e->ref; ref; ref = ref->next)
    1083              :     {
    1084           96 :       if (ref->type == REF_COMPONENT
    1085           48 :             && ref->u.c.component->ts.type == BT_CLASS)
    1086           96 :         class_ref = ref;
    1087              :     }
    1088              : 
    1089           48 :   if (class_ref == NULL
    1090           48 :         && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
    1091           48 :     tmp = e->symtree->n.sym->backend_decl;
    1092              :   else
    1093              :     {
    1094              :       /* Remove everything after the last class reference, convert the
    1095              :          expression and then recover its tailend once more.  */
    1096            0 :       gfc_se tmpse;
    1097            0 :       ref = class_ref->next;
    1098            0 :       class_ref->next = NULL;
    1099            0 :       gfc_init_se (&tmpse, NULL);
    1100            0 :       gfc_conv_expr (&tmpse, e);
    1101            0 :       class_ref->next = ref;
    1102            0 :       tmp = tmpse.expr;
    1103              :     }
    1104              : 
    1105           48 :   var = gfc_typenode_for_spec (&class_ts);
    1106           48 :   var = gfc_create_var (var, "class");
    1107              : 
    1108           48 :   ctree = gfc_class_vptr_get (var);
    1109           96 :   gfc_add_modify (&block, ctree,
    1110           48 :                   fold_convert (TREE_TYPE (ctree), gfc_class_vptr_get (tmp)));
    1111              : 
    1112           48 :   ctree = gfc_class_data_get (var);
    1113           48 :   tmp = gfc_conv_descriptor_data_get (
    1114           48 :     gfc_class_data_get (GFC_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (tmp)))
    1115              :                           ? tmp
    1116           24 :                           : GFC_DECL_SAVED_DESCRIPTOR (tmp)));
    1117           48 :   gfc_add_modify (&block, ctree, fold_convert (TREE_TYPE (ctree), tmp));
    1118              : 
    1119              :   /* Pass the address of the class object.  */
    1120           48 :   parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
    1121              : 
    1122           48 :   if (optional)
    1123              :     {
    1124           48 :       tree cond = gfc_conv_expr_present (e->symtree->n.sym);
    1125           48 :       tree tmp2;
    1126              : 
    1127           48 :       tmp = gfc_finish_block (&block);
    1128              : 
    1129           48 :       gfc_init_block (&block);
    1130           48 :       tmp2 = gfc_class_data_get (var);
    1131           48 :       gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2),
    1132              :                                                   null_pointer_node));
    1133           48 :       tmp2 = gfc_finish_block (&block);
    1134              : 
    1135           48 :       tmp = build3_loc (input_location, COND_EXPR, void_type_node,
    1136              :                         cond, tmp, tmp2);
    1137           48 :       gfc_add_expr_to_block (&parmse->pre, tmp);
    1138              :     }
    1139              :   else
    1140            0 :     gfc_add_block_to_block (&parmse->pre, &block);
    1141           48 : }
    1142              : 
    1143              : 
    1144              : /* Takes an intrinsic type expression and returns the address of a temporary
    1145              :    class object of the 'declared' type.  */
    1146              : void
    1147          882 : gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
    1148              :                              gfc_typespec class_ts)
    1149              : {
    1150          882 :   gfc_symbol *vtab;
    1151          882 :   gfc_ss *ss;
    1152          882 :   tree ctree;
    1153          882 :   tree var;
    1154          882 :   tree tmp;
    1155          882 :   int dim;
    1156          882 :   bool unlimited_poly;
    1157              : 
    1158         1764 :   unlimited_poly = class_ts.type == BT_CLASS
    1159          882 :                    && class_ts.u.derived->components->ts.type == BT_DERIVED
    1160          882 :                    && class_ts.u.derived->components->ts.u.derived
    1161          882 :                                                 ->attr.unlimited_polymorphic;
    1162              : 
    1163              :   /* The intrinsic type needs to be converted to a temporary
    1164              :      CLASS object.  */
    1165          882 :   tmp = gfc_typenode_for_spec (&class_ts);
    1166          882 :   var = gfc_create_var (tmp, "class");
    1167              : 
    1168              :   /* Force a temporary for component or substring references.  */
    1169          882 :   if (unlimited_poly
    1170          882 :       && class_ts.u.derived->components->attr.dimension
    1171          623 :       && !class_ts.u.derived->components->attr.allocatable
    1172          623 :       && !class_ts.u.derived->components->attr.class_pointer
    1173         1505 :       && is_subref_array (e))
    1174           17 :     parmse->force_tmp = 1;
    1175              : 
    1176              :   /* Set the vptr.  */
    1177          882 :   ctree = gfc_class_vptr_get (var);
    1178              : 
    1179          882 :   vtab = gfc_find_vtab (&e->ts);
    1180          882 :   gcc_assert (vtab);
    1181          882 :   tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
    1182          882 :   gfc_add_modify (&parmse->pre, ctree,
    1183          882 :                   fold_convert (TREE_TYPE (ctree), tmp));
    1184              : 
    1185              :   /* Now set the data field.  */
    1186          882 :   ctree = gfc_class_data_get (var);
    1187          882 :   if (parmse->ss && parmse->ss->info->useflags)
    1188              :     {
    1189              :       /* For an array reference in an elemental procedure call we need
    1190              :          to retain the ss to provide the scalarized array reference.  */
    1191           36 :       gfc_conv_expr_reference (parmse, e);
    1192           36 :       tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
    1193           36 :       gfc_add_modify (&parmse->pre, ctree, tmp);
    1194              :     }
    1195              :   else
    1196              :     {
    1197          846 :       ss = gfc_walk_expr (e);
    1198          846 :       if (ss == gfc_ss_terminator)
    1199              :         {
    1200          247 :           parmse->ss = NULL;
    1201          247 :           gfc_conv_expr_reference (parmse, e);
    1202          247 :           if (class_ts.u.derived->components->as
    1203           24 :               && class_ts.u.derived->components->as->type == AS_ASSUMED_RANK)
    1204              :             {
    1205           24 :               tmp = gfc_conv_scalar_to_descriptor (parmse, parmse->expr,
    1206              :                                                    gfc_expr_attr (e));
    1207           24 :               tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
    1208           24 :                                      TREE_TYPE (ctree), tmp);
    1209              :             }
    1210              :           else
    1211          223 :               tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
    1212          247 :           gfc_add_modify (&parmse->pre, ctree, tmp);
    1213              :         }
    1214              :       else
    1215              :         {
    1216          599 :           parmse->ss = ss;
    1217          599 :           gfc_conv_expr_descriptor (parmse, e);
    1218              : 
    1219              :           /* Array references with vector subscripts and non-variable expressions
    1220              :              need be converted to a one-based descriptor.  */
    1221          599 :           if (e->expr_type != EXPR_VARIABLE)
    1222              :             {
    1223          368 :               for (dim = 0; dim < e->rank; ++dim)
    1224          193 :                 gfc_conv_shift_descriptor_lbound (&parmse->pre, parmse->expr,
    1225              :                                                   dim, gfc_index_one_node);
    1226              :             }
    1227              : 
    1228          599 :           if (class_ts.u.derived->components->as->rank != e->rank)
    1229              :             {
    1230           49 :               tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
    1231           49 :                                      TREE_TYPE (ctree), parmse->expr);
    1232           49 :               gfc_add_modify (&parmse->pre, ctree, tmp);
    1233              :             }
    1234              :           else
    1235          550 :             gfc_add_modify (&parmse->pre, ctree, parmse->expr);
    1236              :         }
    1237              :     }
    1238              : 
    1239          882 :   gcc_assert (class_ts.type == BT_CLASS);
    1240          882 :   if (unlimited_poly)
    1241              :     {
    1242          882 :       ctree = gfc_class_len_get (var);
    1243              :       /* When the actual arg is a char array, then set the _len component of the
    1244              :          unlimited polymorphic entity to the length of the string.  */
    1245          882 :       if (e->ts.type == BT_CHARACTER)
    1246              :         {
    1247              :           /* Start with parmse->string_length because this seems to be set to a
    1248              :            correct value more often.  */
    1249          175 :           if (parmse->string_length)
    1250              :             tmp = parmse->string_length;
    1251              :           /* When the string_length is not yet set, then try the backend_decl of
    1252              :            the cl.  */
    1253            0 :           else if (e->ts.u.cl->backend_decl)
    1254              :             tmp = e->ts.u.cl->backend_decl;
    1255              :           /* If both of the above approaches fail, then try to generate an
    1256              :            expression from the input, which is only feasible currently, when the
    1257              :            expression can be evaluated to a constant one.  */
    1258              :           else
    1259              :             {
    1260              :               /* Try to simplify the expression.  */
    1261            0 :               gfc_simplify_expr (e, 0);
    1262            0 :               if (e->expr_type == EXPR_CONSTANT && !e->ts.u.cl->resolved)
    1263              :                 {
    1264              :                   /* Amazingly all data is present to compute the length of a
    1265              :                    constant string, but the expression is not yet there.  */
    1266            0 :                   e->ts.u.cl->length = gfc_get_constant_expr (BT_INTEGER,
    1267              :                                                               gfc_charlen_int_kind,
    1268              :                                                               &e->where);
    1269            0 :                   mpz_set_ui (e->ts.u.cl->length->value.integer,
    1270            0 :                               e->value.character.length);
    1271            0 :                   gfc_conv_const_charlen (e->ts.u.cl);
    1272            0 :                   e->ts.u.cl->resolved = 1;
    1273            0 :                   tmp = e->ts.u.cl->backend_decl;
    1274              :                 }
    1275              :               else
    1276              :                 {
    1277            0 :                   gfc_error ("Cannot compute the length of the char array "
    1278              :                              "at %L.", &e->where);
    1279              :                 }
    1280              :             }
    1281              :         }
    1282              :       else
    1283          707 :         tmp = integer_zero_node;
    1284              : 
    1285          882 :       gfc_add_modify (&parmse->pre, ctree, fold_convert (TREE_TYPE (ctree), tmp));
    1286              :     }
    1287              : 
    1288              :   /* Pass the address of the class object.  */
    1289          882 :   parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
    1290          882 : }
    1291              : 
    1292              : 
    1293              : /* Takes a scalarized class array expression and returns the
    1294              :    address of a temporary scalar class object of the 'declared'
    1295              :    type.
    1296              :    OOP-TODO: This could be improved by adding code that branched on
    1297              :    the dynamic type being the same as the declared type. In this case
    1298              :    the original class expression can be passed directly.
    1299              :    optional_alloc_ptr is false when the dummy is neither allocatable
    1300              :    nor a pointer; that's relevant for the optional handling.
    1301              :    Set copyback to true if class container's _data and _vtab pointers
    1302              :    might get modified.  */
    1303              : 
    1304              : void
    1305         3579 : gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
    1306              :                          bool elemental, bool copyback, bool optional,
    1307              :                          bool optional_alloc_ptr)
    1308              : {
    1309         3579 :   tree ctree;
    1310         3579 :   tree var;
    1311         3579 :   tree tmp;
    1312         3579 :   tree vptr;
    1313         3579 :   tree cond = NULL_TREE;
    1314         3579 :   tree slen = NULL_TREE;
    1315         3579 :   gfc_ref *ref;
    1316         3579 :   gfc_ref *class_ref;
    1317         3579 :   stmtblock_t block;
    1318         3579 :   bool full_array = false;
    1319              : 
    1320              :   /* If this is the data field of a class temporary, the class expression
    1321              :      can be obtained and returned directly.  */
    1322         3579 :   if (e->expr_type != EXPR_VARIABLE
    1323          174 :       && TREE_CODE (parmse->expr) == COMPONENT_REF
    1324           30 :       && !GFC_CLASS_TYPE_P (TREE_TYPE (parmse->expr))
    1325         3609 :       && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (parmse->expr, 0))))
    1326              :     {
    1327           30 :       parmse->expr = TREE_OPERAND (parmse->expr, 0);
    1328           30 :       if (!VAR_P (parmse->expr))
    1329            0 :         parmse->expr = gfc_evaluate_now (parmse->expr, &parmse->pre);
    1330           30 :       parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
    1331          168 :       return;
    1332              :     }
    1333              : 
    1334         3549 :   gfc_init_block (&block);
    1335              : 
    1336         3549 :   class_ref = NULL;
    1337         7114 :   for (ref = e->ref; ref; ref = ref->next)
    1338              :     {
    1339         6738 :       if (ref->type == REF_COMPONENT
    1340         3599 :             && ref->u.c.component->ts.type == BT_CLASS)
    1341         6738 :         class_ref = ref;
    1342              : 
    1343         6738 :       if (ref->next == NULL)
    1344              :         break;
    1345              :     }
    1346              : 
    1347         3549 :   if ((ref == NULL || class_ref == ref)
    1348          488 :       && !(gfc_is_class_array_function (e) && parmse->class_vptr != NULL_TREE)
    1349         4019 :       && (!class_ts.u.derived->components->as
    1350          379 :           || class_ts.u.derived->components->as->rank != -1))
    1351              :     return;
    1352              : 
    1353              :   /* Test for FULL_ARRAY.  */
    1354         3411 :   if (e->rank == 0
    1355         3411 :       && ((gfc_expr_attr (e).codimension && gfc_expr_attr (e).dimension)
    1356          494 :           || (class_ts.u.derived->components->as
    1357          366 :               && class_ts.u.derived->components->as->type == AS_ASSUMED_RANK)))
    1358          411 :     full_array = true;
    1359              :   else
    1360         3000 :     gfc_is_class_array_ref (e, &full_array);
    1361              : 
    1362              :   /* The derived type needs to be converted to a temporary
    1363              :      CLASS object.  */
    1364         3411 :   tmp = gfc_typenode_for_spec (&class_ts);
    1365         3411 :   var = gfc_create_var (tmp, "class");
    1366              : 
    1367              :   /* Set the data.  */
    1368         3411 :   ctree = gfc_class_data_get (var);
    1369         3411 :   if (class_ts.u.derived->components->as
    1370         3151 :       && e->rank != class_ts.u.derived->components->as->rank)
    1371              :     {
    1372          965 :       if (e->rank == 0)
    1373              :         {
    1374          356 :           tree type = get_scalar_to_descriptor_type (parmse->expr,
    1375              :                                                      gfc_expr_attr (e));
    1376          356 :           gfc_add_modify (&block, gfc_conv_descriptor_dtype (ctree),
    1377              :                           gfc_get_dtype (type));
    1378              : 
    1379          356 :           tmp = gfc_class_data_get (parmse->expr);
    1380          356 :           if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
    1381           12 :             tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    1382              : 
    1383          356 :           gfc_conv_descriptor_data_set (&block, ctree, tmp);
    1384              :         }
    1385              :       else
    1386          609 :         gfc_class_array_data_assign (&block, ctree, parmse->expr, false);
    1387              :     }
    1388              :   else
    1389              :     {
    1390         2446 :       if (TREE_TYPE (parmse->expr) != TREE_TYPE (ctree))
    1391         1418 :         parmse->expr = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
    1392         1418 :                                         TREE_TYPE (ctree), parmse->expr);
    1393         2446 :       gfc_add_modify (&block, ctree, parmse->expr);
    1394              :     }
    1395              : 
    1396              :   /* Return the data component, except in the case of scalarized array
    1397              :      references, where nullification of the cannot occur and so there
    1398              :      is no need.  */
    1399         3411 :   if (!elemental && full_array && copyback)
    1400              :     {
    1401         1149 :       if (class_ts.u.derived->components->as
    1402         1149 :           && e->rank != class_ts.u.derived->components->as->rank)
    1403              :         {
    1404          270 :           if (e->rank == 0)
    1405              :             {
    1406          102 :               tmp = gfc_class_data_get (parmse->expr);
    1407          204 :               gfc_add_modify (&parmse->post, tmp,
    1408          102 :                               fold_convert (TREE_TYPE (tmp),
    1409              :                                          gfc_conv_descriptor_data_get (ctree)));
    1410              :             }
    1411              :           else
    1412          168 :             gfc_class_array_data_assign (&parmse->post, parmse->expr, ctree,
    1413              :                                          true);
    1414              :         }
    1415              :       else
    1416          879 :         gfc_add_modify (&parmse->post, parmse->expr, ctree);
    1417              :     }
    1418              : 
    1419              :   /* Set the vptr.  */
    1420         3411 :   ctree = gfc_class_vptr_get (var);
    1421              : 
    1422              :   /* The vptr is the second field of the actual argument.
    1423              :      First we have to find the corresponding class reference.  */
    1424              : 
    1425         3411 :   tmp = NULL_TREE;
    1426         3411 :   if (gfc_is_class_array_function (e)
    1427         3411 :       && parmse->class_vptr != NULL_TREE)
    1428              :     tmp = parmse->class_vptr;
    1429         3393 :   else if (class_ref == NULL
    1430         2949 :            && e->symtree && e->symtree->n.sym->ts.type == BT_CLASS)
    1431              :     {
    1432         2949 :       tmp = e->symtree->n.sym->backend_decl;
    1433              : 
    1434         2949 :       if (TREE_CODE (tmp) == FUNCTION_DECL)
    1435            6 :         tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
    1436              : 
    1437         2949 :       if (DECL_LANG_SPECIFIC (tmp) && GFC_DECL_SAVED_DESCRIPTOR (tmp))
    1438          373 :         tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
    1439              : 
    1440         2949 :       slen = build_zero_cst (size_type_node);
    1441              :     }
    1442          444 :   else if (parmse->class_container != NULL_TREE)
    1443              :     /* Don't redundantly evaluate the expression if the required information
    1444              :        is already available.  */
    1445              :     tmp = parmse->class_container;
    1446              :   else
    1447              :     {
    1448              :       /* Remove everything after the last class reference, convert the
    1449              :          expression and then recover its tailend once more.  */
    1450           18 :       gfc_se tmpse;
    1451           18 :       ref = class_ref->next;
    1452           18 :       class_ref->next = NULL;
    1453           18 :       gfc_init_se (&tmpse, NULL);
    1454           18 :       gfc_conv_expr (&tmpse, e);
    1455           18 :       class_ref->next = ref;
    1456           18 :       tmp = tmpse.expr;
    1457           18 :       slen = tmpse.string_length;
    1458              :     }
    1459              : 
    1460         3411 :   gcc_assert (tmp != NULL_TREE);
    1461              : 
    1462              :   /* Dereference if needs be.  */
    1463         3411 :   if (TREE_CODE (TREE_TYPE (tmp)) == REFERENCE_TYPE)
    1464          321 :     tmp = build_fold_indirect_ref_loc (input_location, tmp);
    1465              : 
    1466         3411 :   if (!(gfc_is_class_array_function (e) && parmse->class_vptr))
    1467         3393 :     vptr = gfc_class_vptr_get (tmp);
    1468              :   else
    1469              :     vptr = tmp;
    1470              : 
    1471         3411 :   gfc_add_modify (&block, ctree,
    1472         3411 :                   fold_convert (TREE_TYPE (ctree), vptr));
    1473              : 
    1474              :   /* Return the vptr component, except in the case of scalarized array
    1475              :      references, where the dynamic type cannot change.  */
    1476         3411 :   if (!elemental && full_array && copyback)
    1477         1149 :     gfc_add_modify (&parmse->post, vptr,
    1478         1149 :                     fold_convert (TREE_TYPE (vptr), ctree));
    1479              : 
    1480              :   /* For unlimited polymorphic objects also set the _len component.  */
    1481         3411 :   if (class_ts.type == BT_CLASS
    1482         3411 :       && class_ts.u.derived->components
    1483         3411 :       && class_ts.u.derived->components->ts.u
    1484         3411 :                       .derived->attr.unlimited_polymorphic)
    1485              :     {
    1486         1109 :       ctree = gfc_class_len_get (var);
    1487         1109 :       if (UNLIMITED_POLY (e))
    1488          913 :         tmp = gfc_class_len_get (tmp);
    1489          196 :       else if (e->ts.type == BT_CHARACTER)
    1490              :         {
    1491            0 :           gcc_assert (slen != NULL_TREE);
    1492              :           tmp = slen;
    1493              :         }
    1494              :       else
    1495          196 :         tmp = build_zero_cst (size_type_node);
    1496         1109 :       gfc_add_modify (&parmse->pre, ctree,
    1497         1109 :                       fold_convert (TREE_TYPE (ctree), tmp));
    1498              : 
    1499              :       /* Return the len component, except in the case of scalarized array
    1500              :         references, where the dynamic type cannot change.  */
    1501         1109 :       if (!elemental && full_array && copyback
    1502          440 :           && (UNLIMITED_POLY (e) || VAR_P (tmp)))
    1503          428 :           gfc_add_modify (&parmse->post, tmp,
    1504          428 :                           fold_convert (TREE_TYPE (tmp), ctree));
    1505              :     }
    1506              : 
    1507         3411 :   if (optional)
    1508              :     {
    1509          510 :       tree tmp2;
    1510              : 
    1511          510 :       cond = gfc_conv_expr_present (e->symtree->n.sym);
    1512              :       /* parmse->pre may contain some preparatory instructions for the
    1513              :          temporary array descriptor.  Those may only be executed when the
    1514              :          optional argument is set, therefore add parmse->pre's instructions
    1515              :          to block, which is later guarded by an if (optional_arg_given).  */
    1516          510 :       gfc_add_block_to_block (&parmse->pre, &block);
    1517          510 :       block.head = parmse->pre.head;
    1518          510 :       parmse->pre.head = NULL_TREE;
    1519          510 :       tmp = gfc_finish_block (&block);
    1520              : 
    1521          510 :       if (optional_alloc_ptr)
    1522          102 :         tmp2 = build_empty_stmt (input_location);
    1523              :       else
    1524              :         {
    1525          408 :           gfc_init_block (&block);
    1526              : 
    1527          408 :           tmp2 = gfc_conv_descriptor_data_get (gfc_class_data_get (var));
    1528          408 :           gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2),
    1529              :                                                       null_pointer_node));
    1530          408 :           tmp2 = gfc_finish_block (&block);
    1531              :         }
    1532              : 
    1533          510 :       tmp = build3_loc (input_location, COND_EXPR, void_type_node,
    1534              :                         cond, tmp, tmp2);
    1535          510 :       gfc_add_expr_to_block (&parmse->pre, tmp);
    1536              : 
    1537          510 :       if (!elemental && full_array && copyback)
    1538              :         {
    1539           30 :           tmp2 = build_empty_stmt (input_location);
    1540           30 :           tmp = gfc_finish_block (&parmse->post);
    1541           30 :           tmp = build3_loc (input_location, COND_EXPR, void_type_node,
    1542              :                             cond, tmp, tmp2);
    1543           30 :           gfc_add_expr_to_block (&parmse->post, tmp);
    1544              :         }
    1545              :     }
    1546              :   else
    1547         2901 :     gfc_add_block_to_block (&parmse->pre, &block);
    1548              : 
    1549              :   /* Pass the address of the class object.  */
    1550         3411 :   parmse->expr = gfc_build_addr_expr (NULL_TREE, var);
    1551              : 
    1552         3411 :   if (optional && optional_alloc_ptr)
    1553          204 :     parmse->expr = build3_loc (input_location, COND_EXPR,
    1554          102 :                                TREE_TYPE (parmse->expr),
    1555              :                                cond, parmse->expr,
    1556          102 :                                fold_convert (TREE_TYPE (parmse->expr),
    1557              :                                              null_pointer_node));
    1558              : }
    1559              : 
    1560              : 
    1561              : /* Given a class array declaration and an index, returns the address
    1562              :    of the referenced element.  */
    1563              : 
    1564              : static tree
    1565          712 : gfc_get_class_array_ref (tree index, tree class_decl, tree data_comp,
    1566              :                          bool unlimited)
    1567              : {
    1568          712 :   tree data, size, tmp, ctmp, offset, ptr;
    1569              : 
    1570          712 :   data = data_comp != NULL_TREE ? data_comp :
    1571            0 :                                   gfc_class_data_get (class_decl);
    1572          712 :   size = gfc_class_vtab_size_get (class_decl);
    1573              : 
    1574          712 :   if (unlimited)
    1575              :     {
    1576          200 :       tmp = fold_convert (gfc_array_index_type,
    1577              :                           gfc_class_len_get (class_decl));
    1578          200 :       ctmp = fold_build2_loc (input_location, MULT_EXPR,
    1579              :                               gfc_array_index_type, size, tmp);
    1580          200 :       tmp = fold_build2_loc (input_location, GT_EXPR,
    1581              :                              logical_type_node, tmp,
    1582          200 :                              build_zero_cst (TREE_TYPE (tmp)));
    1583          200 :       size = fold_build3_loc (input_location, COND_EXPR,
    1584              :                               gfc_array_index_type, tmp, ctmp, size);
    1585              :     }
    1586              : 
    1587          712 :   offset = fold_build2_loc (input_location, MULT_EXPR,
    1588              :                             gfc_array_index_type,
    1589              :                             index, size);
    1590              : 
    1591          712 :   data = gfc_conv_descriptor_data_get (data);
    1592          712 :   ptr = fold_convert (pvoid_type_node, data);
    1593          712 :   ptr = fold_build_pointer_plus_loc (input_location, ptr, offset);
    1594          712 :   return fold_convert (TREE_TYPE (data), ptr);
    1595              : }
    1596              : 
    1597              : 
    1598              : /* Copies one class expression to another, assuming that if either
    1599              :    'to' or 'from' are arrays they are packed.  Should 'from' be
    1600              :    NULL_TREE, the initialization expression for 'to' is used, assuming
    1601              :    that the _vptr is set.  */
    1602              : 
    1603              : tree
    1604          758 : gfc_copy_class_to_class (tree from, tree to, tree nelems, bool unlimited)
    1605              : {
    1606          758 :   tree fcn;
    1607          758 :   tree fcn_type;
    1608          758 :   tree from_data;
    1609          758 :   tree from_len;
    1610          758 :   tree to_data;
    1611          758 :   tree to_len;
    1612          758 :   tree to_ref;
    1613          758 :   tree from_ref;
    1614          758 :   vec<tree, va_gc> *args;
    1615          758 :   tree tmp;
    1616          758 :   tree stdcopy;
    1617          758 :   tree extcopy;
    1618          758 :   tree index;
    1619          758 :   bool is_from_desc = false, is_to_class = false;
    1620              : 
    1621          758 :   args = NULL;
    1622              :   /* To prevent warnings on uninitialized variables.  */
    1623          758 :   from_len = to_len = NULL_TREE;
    1624              : 
    1625          758 :   if (from != NULL_TREE)
    1626          758 :     fcn = gfc_class_vtab_copy_get (from);
    1627              :   else
    1628            0 :     fcn = gfc_class_vtab_copy_get (to);
    1629              : 
    1630          758 :   fcn_type = TREE_TYPE (TREE_TYPE (fcn));
    1631              : 
    1632          758 :   if (from != NULL_TREE)
    1633              :     {
    1634          758 :       is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from));
    1635          758 :       if (is_from_desc)
    1636              :         {
    1637            0 :           from_data = from;
    1638            0 :           from = GFC_DECL_SAVED_DESCRIPTOR (from);
    1639              :         }
    1640              :       else
    1641              :         {
    1642              :           /* Check that from is a class.  When the class is part of a coarray,
    1643              :              then from is a common pointer and is to be used as is.  */
    1644         1516 :           tmp = POINTER_TYPE_P (TREE_TYPE (from))
    1645          758 :               ? build_fold_indirect_ref (from) : from;
    1646         1516 :           from_data =
    1647          758 :               (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
    1648            0 :                || (DECL_P (tmp) && GFC_DECL_CLASS (tmp)))
    1649          758 :               ? gfc_class_data_get (from) : from;
    1650          758 :           is_from_desc = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (from_data));
    1651              :         }
    1652              :      }
    1653              :   else
    1654            0 :     from_data = gfc_class_vtab_def_init_get (to);
    1655              : 
    1656          758 :   if (unlimited)
    1657              :     {
    1658          160 :       if (from != NULL_TREE && unlimited)
    1659          160 :         from_len = gfc_class_len_or_zero_get (from);
    1660              :       else
    1661            0 :         from_len = build_zero_cst (size_type_node);
    1662              :     }
    1663              : 
    1664          758 :   if (GFC_CLASS_TYPE_P (TREE_TYPE (to)))
    1665              :     {
    1666          758 :       is_to_class = true;
    1667          758 :       to_data = gfc_class_data_get (to);
    1668          758 :       if (unlimited)
    1669          160 :         to_len = gfc_class_len_get (to);
    1670              :     }
    1671              :   else
    1672              :     /* When to is a BT_DERIVED and not a BT_CLASS, then to_data == to.  */
    1673            0 :     to_data = to;
    1674              : 
    1675          758 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (to_data)))
    1676              :     {
    1677          356 :       stmtblock_t loopbody;
    1678          356 :       stmtblock_t body;
    1679          356 :       stmtblock_t ifbody;
    1680          356 :       gfc_loopinfo loop;
    1681              : 
    1682          356 :       gfc_init_block (&body);
    1683          356 :       tmp = fold_build2_loc (input_location, MINUS_EXPR,
    1684              :                              gfc_array_index_type, nelems,
    1685              :                              gfc_index_one_node);
    1686          356 :       nelems = gfc_evaluate_now (tmp, &body);
    1687          356 :       index = gfc_create_var (gfc_array_index_type, "S");
    1688              : 
    1689          356 :       if (is_from_desc)
    1690              :         {
    1691          356 :           from_ref = gfc_get_class_array_ref (index, from, from_data,
    1692              :                                               unlimited);
    1693          356 :           vec_safe_push (args, from_ref);
    1694              :         }
    1695              :       else
    1696            0 :         vec_safe_push (args, from_data);
    1697              : 
    1698          356 :       if (is_to_class)
    1699          356 :         to_ref = gfc_get_class_array_ref (index, to, to_data, unlimited);
    1700              :       else
    1701              :         {
    1702            0 :           tmp = gfc_conv_array_data (to);
    1703            0 :           tmp = build_fold_indirect_ref_loc (input_location, tmp);
    1704            0 :           to_ref = gfc_build_addr_expr (NULL_TREE,
    1705              :                                         gfc_build_array_ref (tmp, index, to));
    1706              :         }
    1707          356 :       vec_safe_push (args, to_ref);
    1708              : 
    1709              :       /* Add bounds check.  */
    1710          356 :       if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) > 0 && is_from_desc)
    1711              :         {
    1712           25 :           const char *name = "<<unknown>>";
    1713           25 :           int dim, rank;
    1714              : 
    1715           25 :           if (DECL_P (to))
    1716            0 :             name = IDENTIFIER_POINTER (DECL_NAME (to));
    1717              : 
    1718           25 :           rank = GFC_TYPE_ARRAY_RANK (TREE_TYPE (from_data));
    1719           55 :           for (dim = 1; dim <= rank; dim++)
    1720              :             {
    1721           30 :               tree from_len, to_len, cond;
    1722           30 :               char *msg;
    1723              : 
    1724           30 :               from_len = gfc_conv_descriptor_size (from_data, dim);
    1725           30 :               from_len = fold_convert (long_integer_type_node, from_len);
    1726           30 :               to_len = gfc_conv_descriptor_size (to_data, dim);
    1727           30 :               to_len = fold_convert (long_integer_type_node, to_len);
    1728           30 :               msg = xasprintf ("Array bound mismatch for dimension %d "
    1729              :                                "of array '%s' (%%ld/%%ld)",
    1730              :                                dim, name);
    1731           30 :               cond = fold_build2_loc (input_location, NE_EXPR,
    1732              :                                       logical_type_node, from_len, to_len);
    1733           30 :               gfc_trans_runtime_check (true, false, cond, &body,
    1734              :                                        NULL, msg, to_len, from_len);
    1735           30 :               free (msg);
    1736              :             }
    1737              :         }
    1738              : 
    1739          356 :       tmp = build_call_vec (fcn_type, fcn, args);
    1740              : 
    1741              :       /* Build the body of the loop.  */
    1742          356 :       gfc_init_block (&loopbody);
    1743          356 :       gfc_add_expr_to_block (&loopbody, tmp);
    1744              : 
    1745              :       /* Build the loop and return.  */
    1746          356 :       gfc_init_loopinfo (&loop);
    1747          356 :       loop.dimen = 1;
    1748          356 :       loop.from[0] = gfc_index_zero_node;
    1749          356 :       loop.loopvar[0] = index;
    1750          356 :       loop.to[0] = nelems;
    1751          356 :       gfc_trans_scalarizing_loops (&loop, &loopbody);
    1752          356 :       gfc_init_block (&ifbody);
    1753          356 :       gfc_add_block_to_block (&ifbody, &loop.pre);
    1754          356 :       stdcopy = gfc_finish_block (&ifbody);
    1755              :       /* In initialization mode from_len is a constant zero.  */
    1756          356 :       if (unlimited && !integer_zerop (from_len))
    1757              :         {
    1758          100 :           vec_safe_push (args, from_len);
    1759          100 :           vec_safe_push (args, to_len);
    1760          100 :           tmp = build_call_vec (fcn_type, fcn, args);
    1761              :           /* Build the body of the loop.  */
    1762          100 :           gfc_init_block (&loopbody);
    1763          100 :           gfc_add_expr_to_block (&loopbody, tmp);
    1764              : 
    1765              :           /* Build the loop and return.  */
    1766          100 :           gfc_init_loopinfo (&loop);
    1767          100 :           loop.dimen = 1;
    1768          100 :           loop.from[0] = gfc_index_zero_node;
    1769          100 :           loop.loopvar[0] = index;
    1770          100 :           loop.to[0] = nelems;
    1771          100 :           gfc_trans_scalarizing_loops (&loop, &loopbody);
    1772          100 :           gfc_init_block (&ifbody);
    1773          100 :           gfc_add_block_to_block (&ifbody, &loop.pre);
    1774          100 :           extcopy = gfc_finish_block (&ifbody);
    1775              : 
    1776          100 :           tmp = fold_build2_loc (input_location, GT_EXPR,
    1777              :                                  logical_type_node, from_len,
    1778          100 :                                  build_zero_cst (TREE_TYPE (from_len)));
    1779          100 :           tmp = fold_build3_loc (input_location, COND_EXPR,
    1780              :                                  void_type_node, tmp, extcopy, stdcopy);
    1781          100 :           gfc_add_expr_to_block (&body, tmp);
    1782          100 :           tmp = gfc_finish_block (&body);
    1783              :         }
    1784              :       else
    1785              :         {
    1786          256 :           gfc_add_expr_to_block (&body, stdcopy);
    1787          256 :           tmp = gfc_finish_block (&body);
    1788              :         }
    1789          356 :       gfc_cleanup_loop (&loop);
    1790              :     }
    1791              :   else
    1792              :     {
    1793          402 :       gcc_assert (!is_from_desc);
    1794          402 :       vec_safe_push (args, from_data);
    1795          402 :       vec_safe_push (args, to_data);
    1796          402 :       stdcopy = build_call_vec (fcn_type, fcn, args);
    1797              : 
    1798              :       /* In initialization mode from_len is a constant zero.  */
    1799          402 :       if (unlimited && !integer_zerop (from_len))
    1800              :         {
    1801           60 :           vec_safe_push (args, from_len);
    1802           60 :           vec_safe_push (args, to_len);
    1803           60 :           extcopy = build_call_vec (fcn_type, unshare_expr (fcn), args);
    1804           60 :           tmp = fold_build2_loc (input_location, GT_EXPR,
    1805              :                                  logical_type_node, from_len,
    1806           60 :                                  build_zero_cst (TREE_TYPE (from_len)));
    1807           60 :           tmp = fold_build3_loc (input_location, COND_EXPR,
    1808              :                                  void_type_node, tmp, extcopy, stdcopy);
    1809              :         }
    1810              :       else
    1811              :         tmp = stdcopy;
    1812              :     }
    1813              : 
    1814              :   /* Only copy _def_init to to_data, when it is not a NULL-pointer.  */
    1815          758 :   if (from == NULL_TREE)
    1816              :     {
    1817            0 :       tree cond;
    1818            0 :       cond = fold_build2_loc (input_location, NE_EXPR,
    1819              :                               logical_type_node,
    1820              :                               from_data, null_pointer_node);
    1821            0 :       tmp = fold_build3_loc (input_location, COND_EXPR,
    1822              :                              void_type_node, cond,
    1823              :                              tmp, build_empty_stmt (input_location));
    1824              :     }
    1825              : 
    1826          758 :   return tmp;
    1827              : }
    1828              : 
    1829              : 
    1830              : static tree
    1831          106 : gfc_trans_class_array_init_assign (gfc_expr *rhs, gfc_expr *lhs, gfc_expr *obj)
    1832              : {
    1833          106 :   gfc_actual_arglist *actual;
    1834          106 :   gfc_expr *ppc;
    1835          106 :   gfc_code *ppc_code;
    1836          106 :   tree res;
    1837              : 
    1838          106 :   actual = gfc_get_actual_arglist ();
    1839          106 :   actual->expr = gfc_copy_expr (rhs);
    1840          106 :   actual->next = gfc_get_actual_arglist ();
    1841          106 :   actual->next->expr = gfc_copy_expr (lhs);
    1842          106 :   ppc = gfc_copy_expr (obj);
    1843          106 :   gfc_add_vptr_component (ppc);
    1844          106 :   gfc_add_component_ref (ppc, "_copy");
    1845          106 :   ppc_code = gfc_get_code (EXEC_CALL);
    1846          106 :   ppc_code->resolved_sym = ppc->symtree->n.sym;
    1847              :   /* Although '_copy' is set to be elemental in class.cc, it is
    1848              :      not staying that way.  Find out why, sometime....  */
    1849          106 :   ppc_code->resolved_sym->attr.elemental = 1;
    1850          106 :   ppc_code->ext.actual = actual;
    1851          106 :   ppc_code->expr1 = ppc;
    1852              :   /* Since '_copy' is elemental, the scalarizer will take care
    1853              :      of arrays in gfc_trans_call.  */
    1854          106 :   res = gfc_trans_call (ppc_code, false, NULL, NULL, false);
    1855          106 :   gfc_free_statements (ppc_code);
    1856              : 
    1857          106 :   if (UNLIMITED_POLY(obj))
    1858              :     {
    1859              :       /* Check if rhs is non-NULL. */
    1860           24 :       gfc_se src;
    1861           24 :       gfc_init_se (&src, NULL);
    1862           24 :       gfc_conv_expr (&src, rhs);
    1863           24 :       src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
    1864           24 :       tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1865           24 :                                    src.expr, fold_convert (TREE_TYPE (src.expr),
    1866              :                                                            null_pointer_node));
    1867           24 :       res = build3_loc (input_location, COND_EXPR, TREE_TYPE (res), cond, res,
    1868              :                         build_empty_stmt (input_location));
    1869              :     }
    1870              : 
    1871          106 :   return res;
    1872              : }
    1873              : 
    1874              : /* Special case for initializing a polymorphic dummy with INTENT(OUT).
    1875              :    A MEMCPY is needed to copy the full data from the default initializer
    1876              :    of the dynamic type.  */
    1877              : 
    1878              : tree
    1879          461 : gfc_trans_class_init_assign (gfc_code *code)
    1880              : {
    1881          461 :   stmtblock_t block;
    1882          461 :   tree tmp;
    1883          461 :   bool cmp_flag = true;
    1884          461 :   gfc_se dst,src,memsz;
    1885          461 :   gfc_expr *lhs, *rhs, *sz;
    1886          461 :   gfc_component *cmp;
    1887          461 :   gfc_symbol *sym;
    1888          461 :   gfc_ref *ref;
    1889              : 
    1890          461 :   gfc_start_block (&block);
    1891              : 
    1892          461 :   lhs = gfc_copy_expr (code->expr1);
    1893              : 
    1894          461 :   rhs = gfc_copy_expr (code->expr1);
    1895          461 :   gfc_add_vptr_component (rhs);
    1896              : 
    1897              :   /* Make sure that the component backend_decls have been built, which
    1898              :      will not have happened if the derived types concerned have not
    1899              :      been referenced.  */
    1900          461 :   gfc_get_derived_type (rhs->ts.u.derived);
    1901          461 :   gfc_add_def_init_component (rhs);
    1902              :   /* The _def_init is always scalar.  */
    1903          461 :   rhs->rank = 0;
    1904              : 
    1905              :   /* Check def_init for initializers.  If this is an INTENT(OUT) dummy with all
    1906              :      default initializer components NULL, use the passed value even though
    1907              :      F2018(8.5.10) asserts that it should considered to be undefined. This is
    1908              :      needed for consistency with other brands.  */
    1909          461 :   sym = code->expr1->expr_type == EXPR_VARIABLE ? code->expr1->symtree->n.sym
    1910              :                                                 : NULL;
    1911          461 :   if (code->op != EXEC_ALLOCATE
    1912          400 :       && sym && sym->attr.dummy
    1913          400 :       && sym->attr.intent == INTENT_OUT)
    1914              :     {
    1915          400 :       ref = rhs->ref;
    1916          800 :       while (ref && ref->next)
    1917              :         ref = ref->next;
    1918          400 :       cmp = ref->u.c.component->ts.u.derived->components;
    1919          611 :       for (; cmp; cmp = cmp->next)
    1920              :         {
    1921          428 :           if (cmp->initializer)
    1922              :             break;
    1923          211 :           else if (!cmp->next)
    1924          146 :             cmp_flag = false;
    1925              :         }
    1926              :     }
    1927              : 
    1928          461 :   if (code->expr1->ts.type == BT_CLASS
    1929          438 :       && CLASS_DATA (code->expr1)->attr.dimension)
    1930              :     {
    1931          106 :       gfc_array_spec *tmparr = gfc_get_array_spec ();
    1932          106 :       *tmparr = *CLASS_DATA (code->expr1)->as;
    1933              :       /* Adding the array ref to the class expression results in correct
    1934              :          indexing to the dynamic type.  */
    1935          106 :       gfc_add_full_array_ref (lhs, tmparr);
    1936          106 :       tmp = gfc_trans_class_array_init_assign (rhs, lhs, code->expr1);
    1937          106 :     }
    1938          355 :   else if (cmp_flag)
    1939              :     {
    1940              :       /* Scalar initialization needs the _data component.  */
    1941          222 :       gfc_add_data_component (lhs);
    1942          222 :       sz = gfc_copy_expr (code->expr1);
    1943          222 :       gfc_add_vptr_component (sz);
    1944          222 :       gfc_add_size_component (sz);
    1945              : 
    1946          222 :       gfc_init_se (&dst, NULL);
    1947          222 :       gfc_init_se (&src, NULL);
    1948          222 :       gfc_init_se (&memsz, NULL);
    1949          222 :       gfc_conv_expr (&dst, lhs);
    1950          222 :       gfc_conv_expr (&src, rhs);
    1951          222 :       gfc_conv_expr (&memsz, sz);
    1952          222 :       gfc_add_block_to_block (&block, &src.pre);
    1953          222 :       src.expr = gfc_build_addr_expr (NULL_TREE, src.expr);
    1954              : 
    1955          222 :       tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz.expr);
    1956              : 
    1957          222 :       if (UNLIMITED_POLY(code->expr1))
    1958              :         {
    1959              :           /* Check if _def_init is non-NULL. */
    1960            7 :           tree cond = fold_build2_loc (input_location, NE_EXPR,
    1961              :                                        logical_type_node, src.expr,
    1962            7 :                                        fold_convert (TREE_TYPE (src.expr),
    1963              :                                                      null_pointer_node));
    1964            7 :           tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
    1965              :                             tmp, build_empty_stmt (input_location));
    1966              :         }
    1967              :     }
    1968              :   else
    1969          133 :     tmp = build_empty_stmt (input_location);
    1970              : 
    1971          461 :   if (code->expr1->symtree->n.sym->attr.dummy
    1972          410 :       && (code->expr1->symtree->n.sym->attr.optional
    1973          404 :           || code->expr1->symtree->n.sym->ns->proc_name->attr.entry_master))
    1974              :     {
    1975            6 :       tree present = gfc_conv_expr_present (code->expr1->symtree->n.sym);
    1976            6 :       tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
    1977              :                         present, tmp,
    1978              :                         build_empty_stmt (input_location));
    1979              :     }
    1980              : 
    1981          461 :   gfc_add_expr_to_block (&block, tmp);
    1982          461 :   gfc_free_expr (lhs);
    1983          461 :   gfc_free_expr (rhs);
    1984              : 
    1985          461 :   return gfc_finish_block (&block);
    1986              : }
    1987              : 
    1988              : 
    1989              : /* Class valued elemental function calls or class array elements arriving
    1990              :    in gfc_trans_scalar_assign come here.  Wherever possible the vptr copy
    1991              :    is used to ensure that the rhs dynamic type is assigned to the lhs.  */
    1992              : 
    1993              : static bool
    1994          776 : trans_scalar_class_assign (stmtblock_t *block, gfc_se *lse, gfc_se *rse)
    1995              : {
    1996          776 :   tree fcn;
    1997          776 :   tree rse_expr;
    1998          776 :   tree class_data;
    1999          776 :   tree tmp;
    2000          776 :   tree zero;
    2001          776 :   tree cond;
    2002          776 :   tree final_cond;
    2003          776 :   stmtblock_t inner_block;
    2004          776 :   bool is_descriptor;
    2005          776 :   bool not_call_expr = TREE_CODE (rse->expr) != CALL_EXPR;
    2006          776 :   bool not_lhs_array_type;
    2007              : 
    2008              :   /* Temporaries arising from dependencies in assignment get cast as a
    2009              :      character type of the dynamic size of the rhs. Use the vptr copy
    2010              :      for this case.  */
    2011          776 :   tmp = TREE_TYPE (lse->expr);
    2012          776 :   not_lhs_array_type = !(tmp && TREE_CODE (tmp) == ARRAY_TYPE
    2013            0 :                          && TYPE_MAX_VALUE (TYPE_DOMAIN (tmp)) != NULL_TREE);
    2014              : 
    2015              :   /* Use ordinary assignment if the rhs is not a call expression or
    2016              :      the lhs is not a class entity or an array(ie. character) type.  */
    2017          728 :   if ((not_call_expr && gfc_get_class_from_expr (lse->expr) == NULL_TREE)
    2018         1049 :       && not_lhs_array_type)
    2019              :     return false;
    2020              : 
    2021              :   /* Ordinary assignment can be used if both sides are class expressions
    2022              :      since the dynamic type is preserved by copying the vptr.  This
    2023              :      should only occur, where temporaries are involved.  */
    2024          503 :   if (GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
    2025          503 :       && GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
    2026              :     return false;
    2027              : 
    2028              :   /* Fix the class expression and the class data of the rhs.  */
    2029          442 :   if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))
    2030          442 :       || not_call_expr)
    2031              :     {
    2032          442 :       tmp = gfc_get_class_from_expr (rse->expr);
    2033          442 :       if (tmp == NULL_TREE)
    2034              :         return false;
    2035          140 :       rse_expr = gfc_evaluate_now (tmp, block);
    2036              :     }
    2037              :   else
    2038            0 :     rse_expr = gfc_evaluate_now (rse->expr, block);
    2039              : 
    2040          140 :   class_data = gfc_class_data_get (rse_expr);
    2041              : 
    2042              :   /* Check that the rhs data is not null.  */
    2043          140 :   is_descriptor = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (class_data));
    2044          140 :   if (is_descriptor)
    2045          140 :     class_data = gfc_conv_descriptor_data_get (class_data);
    2046          140 :   class_data = gfc_evaluate_now (class_data, block);
    2047              : 
    2048          140 :   zero = build_int_cst (TREE_TYPE (class_data), 0);
    2049          140 :   cond = fold_build2_loc (input_location, NE_EXPR,
    2050              :                           logical_type_node,
    2051              :                           class_data, zero);
    2052              : 
    2053              :   /* Copy the rhs to the lhs.  */
    2054          140 :   fcn = gfc_vptr_copy_get (gfc_class_vptr_get (rse_expr));
    2055          140 :   fcn = build_fold_indirect_ref_loc (input_location, fcn);
    2056          140 :   tmp = gfc_evaluate_now (gfc_build_addr_expr (NULL, rse->expr), block);
    2057          140 :   tmp = is_descriptor ? tmp : class_data;
    2058          140 :   tmp = build_call_expr_loc (input_location, fcn, 2, tmp,
    2059              :                              gfc_build_addr_expr (NULL, lse->expr));
    2060          140 :   gfc_add_expr_to_block (block, tmp);
    2061              : 
    2062              :   /* Only elemental function results need to be finalised and freed.  */
    2063          140 :   if (not_call_expr)
    2064              :     return true;
    2065              : 
    2066              :   /* Finalize the class data if needed.  */
    2067            0 :   gfc_init_block (&inner_block);
    2068            0 :   fcn = gfc_vptr_final_get (gfc_class_vptr_get (rse_expr));
    2069            0 :   zero = build_int_cst (TREE_TYPE (fcn), 0);
    2070            0 :   final_cond = fold_build2_loc (input_location, NE_EXPR,
    2071              :                                 logical_type_node, fcn, zero);
    2072            0 :   fcn = build_fold_indirect_ref_loc (input_location, fcn);
    2073            0 :   tmp = build_call_expr_loc (input_location, fcn, 1, class_data);
    2074            0 :   tmp = build3_v (COND_EXPR, final_cond,
    2075              :                   tmp, build_empty_stmt (input_location));
    2076            0 :   gfc_add_expr_to_block (&inner_block, tmp);
    2077              : 
    2078              :   /* Free the class data.  */
    2079            0 :   tmp = gfc_call_free (class_data);
    2080            0 :   tmp = build3_v (COND_EXPR, cond, tmp,
    2081              :                   build_empty_stmt (input_location));
    2082            0 :   gfc_add_expr_to_block (&inner_block, tmp);
    2083              : 
    2084              :   /* Finish the inner block and subject it to the condition on the
    2085              :      class data being non-zero.  */
    2086            0 :   tmp = gfc_finish_block (&inner_block);
    2087            0 :   tmp = build3_v (COND_EXPR, cond, tmp,
    2088              :                   build_empty_stmt (input_location));
    2089            0 :   gfc_add_expr_to_block (block, tmp);
    2090              : 
    2091            0 :   return true;
    2092              : }
    2093              : 
    2094              : /* End of prototype trans-class.c  */
    2095              : 
    2096              : 
    2097              : static void
    2098        12534 : realloc_lhs_warning (bt type, bool array, locus *where)
    2099              : {
    2100        12534 :   if (array && type != BT_CLASS && type != BT_DERIVED && warn_realloc_lhs)
    2101           25 :     gfc_warning (OPT_Wrealloc_lhs,
    2102              :                  "Code for reallocating the allocatable array at %L will "
    2103              :                  "be added", where);
    2104        12509 :   else if (warn_realloc_lhs_all)
    2105            4 :     gfc_warning (OPT_Wrealloc_lhs_all,
    2106              :                  "Code for reallocating the allocatable variable at %L "
    2107              :                  "will be added", where);
    2108        12534 : }
    2109              : 
    2110              : 
    2111              : static void gfc_apply_interface_mapping_to_expr (gfc_interface_mapping *,
    2112              :                                                  gfc_expr *);
    2113              : 
    2114              : /* Copy the scalarization loop variables.  */
    2115              : 
    2116              : static void
    2117      1268344 : gfc_copy_se_loopvars (gfc_se * dest, gfc_se * src)
    2118              : {
    2119      1268344 :   dest->ss = src->ss;
    2120      1268344 :   dest->loop = src->loop;
    2121      1268344 : }
    2122              : 
    2123              : 
    2124              : /* Initialize a simple expression holder.
    2125              : 
    2126              :    Care must be taken when multiple se are created with the same parent.
    2127              :    The child se must be kept in sync.  The easiest way is to delay creation
    2128              :    of a child se until after the previous se has been translated.  */
    2129              : 
    2130              : void
    2131      4579133 : gfc_init_se (gfc_se * se, gfc_se * parent)
    2132              : {
    2133      4579133 :   memset (se, 0, sizeof (gfc_se));
    2134      4579133 :   gfc_init_block (&se->pre);
    2135      4579133 :   gfc_init_block (&se->finalblock);
    2136      4579133 :   gfc_init_block (&se->post);
    2137              : 
    2138      4579133 :   se->parent = parent;
    2139              : 
    2140      4579133 :   if (parent)
    2141      1268344 :     gfc_copy_se_loopvars (se, parent);
    2142      4579133 : }
    2143              : 
    2144              : 
    2145              : /* Advances to the next SS in the chain.  Use this rather than setting
    2146              :    se->ss = se->ss->next because all the parents needs to be kept in sync.
    2147              :    See gfc_init_se.  */
    2148              : 
    2149              : void
    2150       238664 : gfc_advance_se_ss_chain (gfc_se * se)
    2151              : {
    2152       238664 :   gfc_se *p;
    2153              : 
    2154       238664 :   gcc_assert (se != NULL && se->ss != NULL && se->ss != gfc_ss_terminator);
    2155              : 
    2156              :   p = se;
    2157              :   /* Walk down the parent chain.  */
    2158       627230 :   while (p != NULL)
    2159              :     {
    2160              :       /* Simple consistency check.  */
    2161       388566 :       gcc_assert (p->parent == NULL || p->parent->ss == p->ss
    2162              :                   || p->parent->ss->nested_ss == p->ss);
    2163              : 
    2164       388566 :       p->ss = p->ss->next;
    2165              : 
    2166       388566 :       p = p->parent;
    2167              :     }
    2168       238664 : }
    2169              : 
    2170              : 
    2171              : /* Ensures the result of the expression as either a temporary variable
    2172              :    or a constant so that it can be used repeatedly.  */
    2173              : 
    2174              : void
    2175         8046 : gfc_make_safe_expr (gfc_se * se)
    2176              : {
    2177         8046 :   tree var;
    2178              : 
    2179         8046 :   if (CONSTANT_CLASS_P (se->expr))
    2180              :     return;
    2181              : 
    2182              :   /* We need a temporary for this result.  */
    2183          208 :   var = gfc_create_var (TREE_TYPE (se->expr), NULL);
    2184          208 :   gfc_add_modify (&se->pre, var, se->expr);
    2185          208 :   se->expr = var;
    2186              : }
    2187              : 
    2188              : 
    2189              : /* Return an expression which determines if a dummy parameter is present.
    2190              :    Also used for arguments to procedures with multiple entry points.  */
    2191              : 
    2192              : tree
    2193        11589 : gfc_conv_expr_present (gfc_symbol * sym, bool use_saved_desc)
    2194              : {
    2195        11589 :   tree decl, orig_decl, cond;
    2196              : 
    2197        11589 :   gcc_assert (sym->attr.dummy);
    2198        11589 :   orig_decl = decl = gfc_get_symbol_decl (sym);
    2199              : 
    2200              :   /* Intrinsic scalars and derived types with VALUE attribute which are passed
    2201              :      by value use a hidden argument to denote the presence status.  */
    2202        11589 :   if (sym->attr.value && !sym->attr.dimension && sym->ts.type != BT_CLASS)
    2203              :     {
    2204         1052 :       char name[GFC_MAX_SYMBOL_LEN + 2];
    2205         1052 :       tree tree_name;
    2206              : 
    2207         1052 :       gcc_assert (TREE_CODE (decl) == PARM_DECL);
    2208         1052 :       name[0] = '.';
    2209         1052 :       strcpy (&name[1], sym->name);
    2210         1052 :       tree_name = get_identifier (name);
    2211              : 
    2212              :       /* Walk function argument list to find hidden arg.  */
    2213         1052 :       cond = DECL_ARGUMENTS (DECL_CONTEXT (decl));
    2214         5320 :       for ( ; cond != NULL_TREE; cond = TREE_CHAIN (cond))
    2215         5320 :         if (DECL_NAME (cond) == tree_name
    2216         5320 :             && DECL_ARTIFICIAL (cond))
    2217              :           break;
    2218              : 
    2219         1052 :       gcc_assert (cond);
    2220         1052 :       return cond;
    2221              :     }
    2222              : 
    2223              :   /* Assumed-shape arrays use a local variable for the array data;
    2224              :      the actual PARAM_DECL is in a saved decl.  As the local variable
    2225              :      is NULL, it can be checked instead, unless use_saved_desc is
    2226              :      requested.  */
    2227              : 
    2228        10537 :   if (use_saved_desc && TREE_CODE (decl) != PARM_DECL)
    2229              :     {
    2230          822 :       gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
    2231              :              || GFC_ARRAY_TYPE_P (TREE_TYPE (decl)));
    2232          822 :       decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
    2233              :     }
    2234              : 
    2235        10537 :   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, decl,
    2236        10537 :                           fold_convert (TREE_TYPE (decl), null_pointer_node));
    2237              : 
    2238              :   /* Fortran 2008 allows to pass null pointers and non-associated pointers
    2239              :      as actual argument to denote absent dummies. For array descriptors,
    2240              :      we thus also need to check the array descriptor.  For BT_CLASS, it
    2241              :      can also occur for scalars and F2003 due to type->class wrapping and
    2242              :      class->class wrapping.  Note further that BT_CLASS always uses an
    2243              :      array descriptor for arrays, also for explicit-shape/assumed-size.
    2244              :      For assumed-rank arrays, no local variable is generated, hence,
    2245              :      the following also applies with !use_saved_desc.  */
    2246              : 
    2247        10537 :   if ((use_saved_desc || TREE_CODE (orig_decl) == PARM_DECL)
    2248         7496 :       && !sym->attr.allocatable
    2249         6284 :       && ((sym->ts.type != BT_CLASS && !sym->attr.pointer)
    2250         2296 :           || (sym->ts.type == BT_CLASS
    2251         1041 :               && !CLASS_DATA (sym)->attr.allocatable
    2252          567 :               && !CLASS_DATA (sym)->attr.class_pointer))
    2253         4195 :       && ((gfc_option.allow_std & GFC_STD_F2008) != 0
    2254            6 :           || sym->ts.type == BT_CLASS))
    2255              :     {
    2256         4189 :       tree tmp;
    2257              : 
    2258         4189 :       if ((sym->as && (sym->as->type == AS_ASSUMED_SHAPE
    2259         1492 :                        || sym->as->type == AS_ASSUMED_RANK
    2260         1404 :                        || sym->attr.codimension))
    2261         3321 :           || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as))
    2262              :         {
    2263         1039 :           tmp = build_fold_indirect_ref_loc (input_location, decl);
    2264         1039 :           if (sym->ts.type == BT_CLASS)
    2265          171 :             tmp = gfc_class_data_get (tmp);
    2266         1039 :           tmp = gfc_conv_array_data (tmp);
    2267              :         }
    2268         3150 :       else if (sym->ts.type == BT_CLASS)
    2269           36 :         tmp = gfc_class_data_get (decl);
    2270              :       else
    2271              :         tmp = NULL_TREE;
    2272              : 
    2273         1075 :       if (tmp != NULL_TREE)
    2274              :         {
    2275         1075 :           tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
    2276         1075 :                                  fold_convert (TREE_TYPE (tmp), null_pointer_node));
    2277         1075 :           cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    2278              :                                   logical_type_node, cond, tmp);
    2279              :         }
    2280              :     }
    2281              : 
    2282              :   return cond;
    2283              : }
    2284              : 
    2285              : 
    2286              : /* Converts a missing, dummy argument into a null or zero.  */
    2287              : 
    2288              : void
    2289          844 : gfc_conv_missing_dummy (gfc_se * se, gfc_expr * arg, gfc_typespec ts, int kind)
    2290              : {
    2291          844 :   tree present;
    2292          844 :   tree tmp;
    2293              : 
    2294          844 :   present = gfc_conv_expr_present (arg->symtree->n.sym);
    2295              : 
    2296          844 :   if (kind > 0)
    2297              :     {
    2298              :       /* Create a temporary and convert it to the correct type.  */
    2299           54 :       tmp = gfc_get_int_type (kind);
    2300           54 :       tmp = fold_convert (tmp, build_fold_indirect_ref_loc (input_location,
    2301              :                                                         se->expr));
    2302              : 
    2303              :       /* Test for a NULL value.  */
    2304           54 :       tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), present,
    2305           54 :                         tmp, fold_convert (TREE_TYPE (tmp), integer_one_node));
    2306           54 :       tmp = gfc_evaluate_now (tmp, &se->pre);
    2307           54 :       se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
    2308              :     }
    2309              :   else
    2310              :     {
    2311          790 :       tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
    2312              :                         present, se->expr,
    2313          790 :                         build_zero_cst (TREE_TYPE (se->expr)));
    2314          790 :       tmp = gfc_evaluate_now (tmp, &se->pre);
    2315          790 :       se->expr = tmp;
    2316              :     }
    2317              : 
    2318          844 :   if (ts.type == BT_CHARACTER)
    2319              :     {
    2320              :       /* Handle deferred-length dummies that pass the character length by
    2321              :          reference so that the value can be returned.  */
    2322          244 :       if (ts.deferred && INDIRECT_REF_P (se->string_length))
    2323              :         {
    2324           18 :           tmp = gfc_build_addr_expr (NULL_TREE, se->string_length);
    2325           18 :           tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
    2326              :                                  present, tmp, null_pointer_node);
    2327           18 :           tmp = gfc_evaluate_now (tmp, &se->pre);
    2328           18 :           tmp = build_fold_indirect_ref_loc (input_location, tmp);
    2329              :         }
    2330              :       else
    2331              :         {
    2332          226 :           tmp = build_int_cst (gfc_charlen_type_node, 0);
    2333          226 :           tmp = fold_build3_loc (input_location, COND_EXPR,
    2334              :                                  gfc_charlen_type_node,
    2335              :                                  present, se->string_length, tmp);
    2336          226 :           tmp = gfc_evaluate_now (tmp, &se->pre);
    2337              :         }
    2338          244 :       se->string_length = tmp;
    2339              :     }
    2340          844 :   return;
    2341              : }
    2342              : 
    2343              : 
    2344              : /* Get the character length of an expression, looking through gfc_refs
    2345              :    if necessary.  */
    2346              : 
    2347              : tree
    2348        20116 : gfc_get_expr_charlen (gfc_expr *e)
    2349              : {
    2350        20116 :   gfc_ref *r;
    2351        20116 :   tree length;
    2352        20116 :   tree previous = NULL_TREE;
    2353        20116 :   gfc_se se;
    2354              : 
    2355        20116 :   gcc_assert (e->expr_type == EXPR_VARIABLE
    2356              :               && e->ts.type == BT_CHARACTER);
    2357              : 
    2358        20116 :   length = NULL; /* To silence compiler warning.  */
    2359              : 
    2360        20116 :   if (is_subref_array (e) && e->ts.u.cl->length)
    2361              :     {
    2362          767 :       gfc_se tmpse;
    2363          767 :       gfc_init_se (&tmpse, NULL);
    2364          767 :       gfc_conv_expr_type (&tmpse, e->ts.u.cl->length, gfc_charlen_type_node);
    2365          767 :       e->ts.u.cl->backend_decl = tmpse.expr;
    2366          767 :       return tmpse.expr;
    2367              :     }
    2368              : 
    2369              :   /* First candidate: if the variable is of type CHARACTER, the
    2370              :      expression's length could be the length of the character
    2371              :      variable.  */
    2372        19349 :   if (e->symtree->n.sym->ts.type == BT_CHARACTER)
    2373        19061 :     length = e->symtree->n.sym->ts.u.cl->backend_decl;
    2374              : 
    2375              :   /* Look through the reference chain for component references.  */
    2376        38829 :   for (r = e->ref; r; r = r->next)
    2377              :     {
    2378        19480 :       previous = length;
    2379        19480 :       switch (r->type)
    2380              :         {
    2381          288 :         case REF_COMPONENT:
    2382          288 :           if (r->u.c.component->ts.type == BT_CHARACTER)
    2383          288 :             length = r->u.c.component->ts.u.cl->backend_decl;
    2384              :           break;
    2385              : 
    2386              :         case REF_ARRAY:
    2387              :           /* Do nothing.  */
    2388              :           break;
    2389              : 
    2390           20 :         case REF_SUBSTRING:
    2391           20 :           gfc_init_se (&se, NULL);
    2392           20 :           gfc_conv_expr_type (&se, r->u.ss.start, gfc_charlen_type_node);
    2393           20 :           length = se.expr;
    2394           20 :           if (r->u.ss.end)
    2395            0 :             gfc_conv_expr_type (&se, r->u.ss.end, gfc_charlen_type_node);
    2396              :           else
    2397           20 :             se.expr = previous;
    2398           20 :           length = fold_build2_loc (input_location, MINUS_EXPR,
    2399              :                                     gfc_charlen_type_node,
    2400              :                                     se.expr, length);
    2401           20 :           length = fold_build2_loc (input_location, PLUS_EXPR,
    2402              :                                     gfc_charlen_type_node, length,
    2403              :                                     gfc_index_one_node);
    2404           20 :           break;
    2405              : 
    2406            0 :         default:
    2407            0 :           gcc_unreachable ();
    2408        19480 :           break;
    2409              :         }
    2410              :     }
    2411              : 
    2412        19349 :   gcc_assert (length != NULL);
    2413              :   return length;
    2414              : }
    2415              : 
    2416              : 
    2417              : /* Return for an expression the backend decl of the coarray.  */
    2418              : 
    2419              : tree
    2420         2046 : gfc_get_tree_for_caf_expr (gfc_expr *expr)
    2421              : {
    2422         2046 :   tree caf_decl;
    2423         2046 :   bool found = false;
    2424         2046 :   gfc_ref *ref;
    2425              : 
    2426         2046 :   gcc_assert (expr && expr->expr_type == EXPR_VARIABLE);
    2427              : 
    2428              :   /* Not-implemented diagnostic.  */
    2429         2046 :   if (expr->symtree->n.sym->ts.type == BT_CLASS
    2430           39 :       && UNLIMITED_POLY (expr->symtree->n.sym)
    2431            0 :       && CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
    2432            0 :     gfc_error ("Sorry, coindexed access to an unlimited polymorphic object at "
    2433              :                "%L is not supported", &expr->where);
    2434              : 
    2435         4323 :   for (ref = expr->ref; ref; ref = ref->next)
    2436         2277 :     if (ref->type == REF_COMPONENT)
    2437              :       {
    2438          195 :         if (ref->u.c.component->ts.type == BT_CLASS
    2439            0 :             && UNLIMITED_POLY (ref->u.c.component)
    2440            0 :             && CLASS_DATA (ref->u.c.component)->attr.codimension)
    2441            0 :           gfc_error ("Sorry, coindexed access to an unlimited polymorphic "
    2442              :                      "component at %L is not supported", &expr->where);
    2443              :       }
    2444              : 
    2445              :   /* Make sure the backend_decl is present before accessing it.  */
    2446         2046 :   caf_decl = expr->symtree->n.sym->backend_decl == NULL_TREE
    2447         2046 :       ? gfc_get_symbol_decl (expr->symtree->n.sym)
    2448              :       : expr->symtree->n.sym->backend_decl;
    2449              : 
    2450         2046 :   if (expr->symtree->n.sym->ts.type == BT_CLASS)
    2451              :     {
    2452           39 :       if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
    2453           45 :           && GFC_DECL_SAVED_DESCRIPTOR (caf_decl))
    2454            6 :         caf_decl = GFC_DECL_SAVED_DESCRIPTOR (caf_decl);
    2455              : 
    2456           39 :       if (expr->ref && expr->ref->type == REF_ARRAY)
    2457              :         {
    2458           28 :           caf_decl = gfc_class_data_get (caf_decl);
    2459           28 :           if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
    2460              :             return caf_decl;
    2461              :         }
    2462           11 :       else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
    2463            2 :                && GFC_DECL_TOKEN (caf_decl)
    2464           13 :                && CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
    2465              :         return caf_decl;
    2466              : 
    2467           23 :       for (ref = expr->ref; ref; ref = ref->next)
    2468              :         {
    2469           18 :           if (ref->type == REF_COMPONENT
    2470            9 :               && strcmp (ref->u.c.component->name, "_data") != 0)
    2471              :             {
    2472            0 :               caf_decl = gfc_class_data_get (caf_decl);
    2473            0 :               if (CLASS_DATA (expr->symtree->n.sym)->attr.codimension)
    2474              :                 return caf_decl;
    2475              :               break;
    2476              :             }
    2477           18 :           else if (ref->type == REF_ARRAY && ref->u.ar.dimen)
    2478              :             break;
    2479              :         }
    2480              :     }
    2481         2016 :   if (expr->symtree->n.sym->attr.codimension)
    2482              :     return caf_decl;
    2483              : 
    2484              :   /* The following code assumes that the coarray is a component reachable via
    2485              :      only scalar components/variables; the Fortran standard guarantees this.  */
    2486              : 
    2487           46 :   for (ref = expr->ref; ref; ref = ref->next)
    2488           46 :     if (ref->type == REF_COMPONENT)
    2489              :       {
    2490           46 :         gfc_component *comp = ref->u.c.component;
    2491              : 
    2492           46 :         if (POINTER_TYPE_P (TREE_TYPE (caf_decl)))
    2493            0 :           caf_decl = build_fold_indirect_ref_loc (input_location, caf_decl);
    2494           46 :         caf_decl = fold_build3_loc (input_location, COMPONENT_REF,
    2495           46 :                                     TREE_TYPE (comp->backend_decl), caf_decl,
    2496              :                                     comp->backend_decl, NULL_TREE);
    2497           46 :         if (comp->ts.type == BT_CLASS)
    2498              :           {
    2499            0 :             caf_decl = gfc_class_data_get (caf_decl);
    2500            0 :             if (CLASS_DATA (comp)->attr.codimension)
    2501              :               {
    2502              :                 found = true;
    2503              :                 break;
    2504              :               }
    2505              :           }
    2506           46 :         if (comp->attr.codimension)
    2507              :           {
    2508              :             found = true;
    2509              :             break;
    2510              :           }
    2511              :       }
    2512           46 :   gcc_assert (found && caf_decl);
    2513              :   return caf_decl;
    2514              : }
    2515              : 
    2516              : 
    2517              : /* Obtain the Coarray token - and optionally also the offset.  */
    2518              : 
    2519              : void
    2520         1917 : gfc_get_caf_token_offset (gfc_se *se, tree *token, tree *offset, tree caf_decl,
    2521              :                           tree se_expr, gfc_expr *expr)
    2522              : {
    2523         1917 :   tree tmp;
    2524              : 
    2525         1917 :   gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
    2526              : 
    2527              :   /* Coarray token.  */
    2528         1917 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
    2529          546 :       *token = gfc_conv_descriptor_token (caf_decl);
    2530         1369 :   else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
    2531         1570 :            && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
    2532            6 :     *token = GFC_DECL_TOKEN (caf_decl);
    2533              :   else
    2534              :     {
    2535         1365 :       gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (caf_decl))
    2536              :                   && GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (caf_decl)) != NULL_TREE);
    2537         1365 :       *token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (caf_decl));
    2538              :     }
    2539              : 
    2540         1917 :   if (offset == NULL)
    2541              :     return;
    2542              : 
    2543              :   /* Offset between the coarray base address and the address wanted.  */
    2544          179 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl))
    2545          179 :       && (GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_ALLOCATABLE
    2546            0 :           || GFC_TYPE_ARRAY_AKIND (TREE_TYPE (caf_decl)) == GFC_ARRAY_POINTER))
    2547            0 :     *offset = build_int_cst (gfc_array_index_type, 0);
    2548          179 :   else if (DECL_P (caf_decl) && DECL_LANG_SPECIFIC (caf_decl)
    2549          179 :            && GFC_DECL_CAF_OFFSET (caf_decl) != NULL_TREE)
    2550            0 :     *offset = GFC_DECL_CAF_OFFSET (caf_decl);
    2551          179 :   else if (GFC_TYPE_ARRAY_CAF_OFFSET (TREE_TYPE (caf_decl)) != NULL_TREE)
    2552            0 :     *offset = GFC_TYPE_ARRAY_CAF_OFFSET (TREE_TYPE (caf_decl));
    2553              :   else
    2554          179 :     *offset = build_int_cst (gfc_array_index_type, 0);
    2555              : 
    2556          179 :   if (POINTER_TYPE_P (TREE_TYPE (se_expr))
    2557          179 :       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se_expr))))
    2558              :     {
    2559            0 :       tmp = build_fold_indirect_ref_loc (input_location, se_expr);
    2560            0 :       tmp = gfc_conv_descriptor_data_get (tmp);
    2561              :     }
    2562          179 :   else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se_expr)))
    2563            0 :     tmp = gfc_conv_descriptor_data_get (se_expr);
    2564              :   else
    2565              :     {
    2566          179 :       gcc_assert (POINTER_TYPE_P (TREE_TYPE (se_expr)));
    2567              :       tmp = se_expr;
    2568              :     }
    2569              : 
    2570          179 :   *offset = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    2571              :                              *offset, fold_convert (gfc_array_index_type, tmp));
    2572              : 
    2573          179 :   if (expr->symtree->n.sym->ts.type == BT_DERIVED
    2574            0 :       && expr->symtree->n.sym->attr.codimension
    2575            0 :       && expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
    2576              :     {
    2577            0 :       gfc_expr *base_expr = gfc_copy_expr (expr);
    2578            0 :       gfc_ref *ref = base_expr->ref;
    2579            0 :       gfc_se base_se;
    2580              : 
    2581              :       // Iterate through the refs until the last one.
    2582            0 :       while (ref->next)
    2583              :           ref = ref->next;
    2584              : 
    2585            0 :       if (ref->type == REF_ARRAY
    2586            0 :           && ref->u.ar.type != AR_FULL)
    2587              :         {
    2588            0 :           const int ranksum = ref->u.ar.dimen + ref->u.ar.codimen;
    2589            0 :           int i;
    2590            0 :           for (i = 0; i < ranksum; ++i)
    2591              :             {
    2592            0 :               ref->u.ar.start[i] = NULL;
    2593            0 :               ref->u.ar.end[i] = NULL;
    2594              :             }
    2595            0 :           ref->u.ar.type = AR_FULL;
    2596              :         }
    2597            0 :       gfc_init_se (&base_se, NULL);
    2598            0 :       if (gfc_caf_attr (base_expr).dimension)
    2599              :         {
    2600            0 :           gfc_conv_expr_descriptor (&base_se, base_expr);
    2601            0 :           tmp = gfc_conv_descriptor_data_get (base_se.expr);
    2602              :         }
    2603              :       else
    2604              :         {
    2605            0 :           gfc_conv_expr (&base_se, base_expr);
    2606            0 :           tmp = base_se.expr;
    2607              :         }
    2608              : 
    2609            0 :       gfc_free_expr (base_expr);
    2610            0 :       gfc_add_block_to_block (&se->pre, &base_se.pre);
    2611            0 :       gfc_add_block_to_block (&se->post, &base_se.post);
    2612            0 :     }
    2613          179 :   else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_decl)))
    2614            0 :     tmp = gfc_conv_descriptor_data_get (caf_decl);
    2615          179 :   else if (INDIRECT_REF_P (caf_decl))
    2616            0 :     tmp = TREE_OPERAND (caf_decl, 0);
    2617              :   else
    2618              :     {
    2619          179 :       gcc_assert (POINTER_TYPE_P (TREE_TYPE (caf_decl)));
    2620              :       tmp = caf_decl;
    2621              :     }
    2622              : 
    2623          179 :   *offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    2624              :                             fold_convert (gfc_array_index_type, *offset),
    2625              :                             fold_convert (gfc_array_index_type, tmp));
    2626              : }
    2627              : 
    2628              : 
    2629              : /* Convert the coindex of a coarray into an image index; the result is
    2630              :    image_num =  (idx(1)-lcobound(1)+1) + (idx(2)-lcobound(2))*extent(1)
    2631              :               + (idx(3)-lcobound(3))*extend(1)*extent(2) + ...  */
    2632              : 
    2633              : tree
    2634         1628 : gfc_caf_get_image_index (stmtblock_t *block, gfc_expr *e, tree desc)
    2635              : {
    2636         1628 :   gfc_ref *ref;
    2637         1628 :   tree lbound, ubound, extent, tmp, img_idx;
    2638         1628 :   gfc_se se;
    2639         1628 :   int i;
    2640              : 
    2641         1659 :   for (ref = e->ref; ref; ref = ref->next)
    2642         1659 :     if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0)
    2643              :       break;
    2644         1628 :   gcc_assert (ref != NULL);
    2645              : 
    2646         1628 :   if (ref->u.ar.dimen_type[ref->u.ar.dimen] == DIMEN_THIS_IMAGE)
    2647           95 :     return build_call_expr_loc (input_location, gfor_fndecl_caf_this_image, 1,
    2648           95 :                                 null_pointer_node);
    2649              : 
    2650         1533 :   img_idx = build_zero_cst (gfc_array_index_type);
    2651         1533 :   extent = build_one_cst (gfc_array_index_type);
    2652         1533 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
    2653          626 :     for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
    2654              :       {
    2655          319 :         gfc_init_se (&se, NULL);
    2656          319 :         gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
    2657          319 :         gfc_add_block_to_block (block, &se.pre);
    2658          319 :         lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
    2659          319 :         tmp = fold_build2_loc (input_location, MINUS_EXPR,
    2660          319 :                                TREE_TYPE (lbound), se.expr, lbound);
    2661          319 :         tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
    2662              :                                extent, tmp);
    2663          319 :         img_idx = fold_build2_loc (input_location, PLUS_EXPR,
    2664          319 :                                    TREE_TYPE (tmp), img_idx, tmp);
    2665          319 :         if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
    2666              :           {
    2667           12 :             ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
    2668           12 :             tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
    2669           12 :             extent = fold_build2_loc (input_location, MULT_EXPR,
    2670           12 :                                       TREE_TYPE (tmp), extent, tmp);
    2671              :           }
    2672              :       }
    2673              :   else
    2674         2468 :     for (i = ref->u.ar.dimen; i < ref->u.ar.dimen + ref->u.ar.codimen; i++)
    2675              :       {
    2676         1242 :         gfc_init_se (&se, NULL);
    2677         1242 :         gfc_conv_expr_type (&se, ref->u.ar.start[i], gfc_array_index_type);
    2678         1242 :         gfc_add_block_to_block (block, &se.pre);
    2679         1242 :         lbound = GFC_TYPE_ARRAY_LBOUND (TREE_TYPE (desc), i);
    2680         1242 :         tmp = fold_build2_loc (input_location, MINUS_EXPR,
    2681         1242 :                                TREE_TYPE (lbound), se.expr, lbound);
    2682         1242 :         tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
    2683              :                                extent, tmp);
    2684         1242 :         img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
    2685              :                                    img_idx, tmp);
    2686         1242 :         if (i < ref->u.ar.dimen + ref->u.ar.codimen - 1)
    2687              :           {
    2688           16 :             ubound = GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (desc), i);
    2689           16 :             tmp = fold_build2_loc (input_location, MINUS_EXPR,
    2690           16 :                                    TREE_TYPE (ubound), ubound, lbound);
    2691           16 :             tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
    2692           16 :                                    tmp, build_one_cst (TREE_TYPE (tmp)));
    2693           16 :             extent = fold_build2_loc (input_location, MULT_EXPR,
    2694           16 :                                       TREE_TYPE (tmp), extent, tmp);
    2695              :           }
    2696              :       }
    2697         1533 :   img_idx = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (img_idx),
    2698         1533 :                              img_idx, build_one_cst (TREE_TYPE (img_idx)));
    2699         1533 :   return fold_convert (integer_type_node, img_idx);
    2700              : }
    2701              : 
    2702              : 
    2703              : /* For each character array constructor subexpression without a ts.u.cl->length,
    2704              :    replace it by its first element (if there aren't any elements, the length
    2705              :    should already be set to zero).  */
    2706              : 
    2707              : static void
    2708          105 : flatten_array_ctors_without_strlen (gfc_expr* e)
    2709              : {
    2710          105 :   gfc_actual_arglist* arg;
    2711          105 :   gfc_constructor* c;
    2712              : 
    2713          105 :   if (!e)
    2714              :     return;
    2715              : 
    2716          105 :   switch (e->expr_type)
    2717              :     {
    2718              : 
    2719            0 :     case EXPR_OP:
    2720            0 :       flatten_array_ctors_without_strlen (e->value.op.op1);
    2721            0 :       flatten_array_ctors_without_strlen (e->value.op.op2);
    2722            0 :       break;
    2723              : 
    2724            0 :     case EXPR_COMPCALL:
    2725              :       /* TODO: Implement as with EXPR_FUNCTION when needed.  */
    2726            0 :       gcc_unreachable ();
    2727              : 
    2728           12 :     case EXPR_FUNCTION:
    2729           36 :       for (arg = e->value.function.actual; arg; arg = arg->next)
    2730           24 :         flatten_array_ctors_without_strlen (arg->expr);
    2731              :       break;
    2732              : 
    2733            0 :     case EXPR_ARRAY:
    2734              : 
    2735              :       /* We've found what we're looking for.  */
    2736            0 :       if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
    2737              :         {
    2738            0 :           gfc_constructor *c;
    2739            0 :           gfc_expr* new_expr;
    2740              : 
    2741            0 :           gcc_assert (e->value.constructor);
    2742              : 
    2743            0 :           c = gfc_constructor_first (e->value.constructor);
    2744            0 :           new_expr = c->expr;
    2745            0 :           c->expr = NULL;
    2746              : 
    2747            0 :           flatten_array_ctors_without_strlen (new_expr);
    2748            0 :           gfc_replace_expr (e, new_expr);
    2749            0 :           break;
    2750              :         }
    2751              : 
    2752              :       /* Otherwise, fall through to handle constructor elements.  */
    2753            0 :       gcc_fallthrough ();
    2754            0 :     case EXPR_STRUCTURE:
    2755            0 :       for (c = gfc_constructor_first (e->value.constructor);
    2756            0 :            c; c = gfc_constructor_next (c))
    2757            0 :         flatten_array_ctors_without_strlen (c->expr);
    2758              :       break;
    2759              : 
    2760              :     default:
    2761              :       break;
    2762              : 
    2763              :     }
    2764              : }
    2765              : 
    2766              : 
    2767              : /* Generate code to initialize a string length variable. Returns the
    2768              :    value.  For array constructors, cl->length might be NULL and in this case,
    2769              :    the first element of the constructor is needed.  expr is the original
    2770              :    expression so we can access it but can be NULL if this is not needed.  */
    2771              : 
    2772              : void
    2773         3817 : gfc_conv_string_length (gfc_charlen * cl, gfc_expr * expr, stmtblock_t * pblock)
    2774              : {
    2775         3817 :   gfc_se se;
    2776              : 
    2777         3817 :   gfc_init_se (&se, NULL);
    2778              : 
    2779         3817 :   if (!cl->length && cl->backend_decl && VAR_P (cl->backend_decl))
    2780         1361 :     return;
    2781              : 
    2782              :   /* If cl->length is NULL, use gfc_conv_expr to obtain the string length but
    2783              :      "flatten" array constructors by taking their first element; all elements
    2784              :      should be the same length or a cl->length should be present.  */
    2785         2549 :   if (!cl->length)
    2786              :     {
    2787          174 :       gfc_expr* expr_flat;
    2788          174 :       if (!expr)
    2789              :         return;
    2790           81 :       expr_flat = gfc_copy_expr (expr);
    2791           81 :       flatten_array_ctors_without_strlen (expr_flat);
    2792           81 :       gfc_resolve_expr (expr_flat);
    2793           81 :       if (expr_flat->rank)
    2794           12 :         gfc_conv_expr_descriptor (&se, expr_flat);
    2795              :       else
    2796           69 :         gfc_conv_expr (&se, expr_flat);
    2797           81 :       if (expr_flat->expr_type != EXPR_VARIABLE)
    2798           75 :         gfc_add_block_to_block (pblock, &se.pre);
    2799           81 :       se.expr = convert (gfc_charlen_type_node, se.string_length);
    2800           81 :       gfc_add_block_to_block (pblock, &se.post);
    2801           81 :       gfc_free_expr (expr_flat);
    2802              :     }
    2803              :   else
    2804              :     {
    2805              :       /* Convert cl->length.  */
    2806         2375 :       gfc_conv_expr_type (&se, cl->length, gfc_charlen_type_node);
    2807         2375 :       se.expr = fold_build2_loc (input_location, MAX_EXPR,
    2808              :                                  gfc_charlen_type_node, se.expr,
    2809         2375 :                                  build_zero_cst (TREE_TYPE (se.expr)));
    2810         2375 :       gfc_add_block_to_block (pblock, &se.pre);
    2811              :     }
    2812              : 
    2813         2456 :   if (cl->backend_decl && VAR_P (cl->backend_decl))
    2814         1540 :     gfc_add_modify (pblock, cl->backend_decl, se.expr);
    2815              :   else
    2816          916 :     cl->backend_decl = gfc_evaluate_now (se.expr, pblock);
    2817              : }
    2818              : 
    2819              : 
    2820              : static void
    2821         6843 : gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
    2822              :                     const char *name, locus *where)
    2823              : {
    2824         6843 :   tree tmp;
    2825         6843 :   tree type;
    2826         6843 :   tree fault;
    2827         6843 :   gfc_se start;
    2828         6843 :   gfc_se end;
    2829         6843 :   char *msg;
    2830         6843 :   mpz_t length;
    2831              : 
    2832         6843 :   type = gfc_get_character_type (kind, ref->u.ss.length);
    2833         6843 :   type = build_pointer_type (type);
    2834              : 
    2835         6843 :   gfc_init_se (&start, se);
    2836         6843 :   gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
    2837         6843 :   gfc_add_block_to_block (&se->pre, &start.pre);
    2838              : 
    2839         6843 :   if (integer_onep (start.expr))
    2840         2317 :     gfc_conv_string_parameter (se);
    2841              :   else
    2842              :     {
    2843         4526 :       tmp = start.expr;
    2844         4526 :       STRIP_NOPS (tmp);
    2845              :       /* Avoid multiple evaluation of substring start.  */
    2846         4526 :       if (!CONSTANT_CLASS_P (tmp) && !DECL_P (tmp))
    2847         1697 :         start.expr = gfc_evaluate_now (start.expr, &se->pre);
    2848              : 
    2849              :       /* Change the start of the string.  */
    2850         4526 :       if (((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
    2851         1194 :             || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
    2852         3452 :            && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
    2853         5600 :           || (POINTER_TYPE_P (TREE_TYPE (se->expr))
    2854         1074 :               && TREE_CODE (TREE_TYPE (TREE_TYPE (se->expr))) != ARRAY_TYPE))
    2855              :         tmp = se->expr;
    2856              :       else
    2857         1066 :         tmp = build_fold_indirect_ref_loc (input_location,
    2858              :                                        se->expr);
    2859              :       /* For BIND(C), a BT_CHARACTER is not an ARRAY_TYPE.  */
    2860         4526 :       if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
    2861              :         {
    2862         4398 :           tmp = gfc_build_array_ref (tmp, start.expr, NULL_TREE, true);
    2863         4398 :           se->expr = gfc_build_addr_expr (type, tmp);
    2864              :         }
    2865          128 :       else if (POINTER_TYPE_P (TREE_TYPE (tmp)))
    2866              :         {
    2867            8 :           tree diff;
    2868            8 :           diff = fold_build2 (MINUS_EXPR, gfc_charlen_type_node, start.expr,
    2869              :                               build_one_cst (gfc_charlen_type_node));
    2870            8 :           diff = fold_convert (size_type_node, diff);
    2871            8 :           se->expr
    2872            8 :             = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp, diff);
    2873              :         }
    2874              :     }
    2875              : 
    2876              :   /* Length = end + 1 - start.  */
    2877         6843 :   gfc_init_se (&end, se);
    2878         6843 :   if (ref->u.ss.end == NULL)
    2879          202 :     end.expr = se->string_length;
    2880              :   else
    2881              :     {
    2882         6641 :       gfc_conv_expr_type (&end, ref->u.ss.end, gfc_charlen_type_node);
    2883         6641 :       gfc_add_block_to_block (&se->pre, &end.pre);
    2884              :     }
    2885         6843 :   tmp = end.expr;
    2886         6843 :   STRIP_NOPS (tmp);
    2887         6843 :   if (!CONSTANT_CLASS_P (tmp) && !DECL_P (tmp))
    2888         2299 :     end.expr = gfc_evaluate_now (end.expr, &se->pre);
    2889              : 
    2890         6843 :   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    2891          474 :       && !gfc_contains_implied_index_p (ref->u.ss.start)
    2892         7298 :       && !gfc_contains_implied_index_p (ref->u.ss.end))
    2893              :     {
    2894          455 :       tree nonempty = fold_build2_loc (input_location, LE_EXPR,
    2895              :                                        logical_type_node, start.expr,
    2896              :                                        end.expr);
    2897              : 
    2898              :       /* Check lower bound.  */
    2899          455 :       fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
    2900              :                                start.expr,
    2901          455 :                                build_one_cst (TREE_TYPE (start.expr)));
    2902          455 :       fault = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    2903              :                                logical_type_node, nonempty, fault);
    2904          455 :       if (name)
    2905          454 :         msg = xasprintf ("Substring out of bounds: lower bound (%%ld) of '%s' "
    2906              :                          "is less than one", name);
    2907              :       else
    2908            1 :         msg = xasprintf ("Substring out of bounds: lower bound (%%ld) "
    2909              :                          "is less than one");
    2910          455 :       gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
    2911              :                                fold_convert (long_integer_type_node,
    2912              :                                              start.expr));
    2913          455 :       free (msg);
    2914              : 
    2915              :       /* Check upper bound.  */
    2916          455 :       fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
    2917              :                                end.expr, se->string_length);
    2918          455 :       fault = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    2919              :                                logical_type_node, nonempty, fault);
    2920          455 :       if (name)
    2921          454 :         msg = xasprintf ("Substring out of bounds: upper bound (%%ld) of '%s' "
    2922              :                          "exceeds string length (%%ld)", name);
    2923              :       else
    2924            1 :         msg = xasprintf ("Substring out of bounds: upper bound (%%ld) "
    2925              :                          "exceeds string length (%%ld)");
    2926          455 :       gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
    2927              :                                fold_convert (long_integer_type_node, end.expr),
    2928              :                                fold_convert (long_integer_type_node,
    2929              :                                              se->string_length));
    2930          455 :       free (msg);
    2931              :     }
    2932              : 
    2933              :   /* Try to calculate the length from the start and end expressions.  */
    2934         6843 :   if (ref->u.ss.end
    2935         6843 :       && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &length))
    2936              :     {
    2937         5626 :       HOST_WIDE_INT i_len;
    2938              : 
    2939         5626 :       i_len = gfc_mpz_get_hwi (length) + 1;
    2940         5626 :       if (i_len < 0)
    2941              :         i_len = 0;
    2942              : 
    2943         5626 :       tmp = build_int_cst (gfc_charlen_type_node, i_len);
    2944         5626 :       mpz_clear (length);  /* Was initialized by gfc_dep_difference.  */
    2945              :     }
    2946              :   else
    2947              :     {
    2948         1217 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_charlen_type_node,
    2949              :                              fold_convert (gfc_charlen_type_node, end.expr),
    2950              :                              fold_convert (gfc_charlen_type_node, start.expr));
    2951         1217 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_charlen_type_node,
    2952              :                              build_int_cst (gfc_charlen_type_node, 1), tmp);
    2953         1217 :       tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_charlen_type_node,
    2954              :                              tmp, build_int_cst (gfc_charlen_type_node, 0));
    2955              :     }
    2956              : 
    2957         6843 :   se->string_length = tmp;
    2958         6843 : }
    2959              : 
    2960              : 
    2961              : /* Convert a derived type component reference.  */
    2962              : 
    2963              : void
    2964       173559 : gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
    2965              : {
    2966       173559 :   gfc_component *c;
    2967       173559 :   tree tmp;
    2968       173559 :   tree decl;
    2969       173559 :   tree field;
    2970       173559 :   tree context;
    2971              : 
    2972       173559 :   c = ref->u.c.component;
    2973              : 
    2974       173559 :   if (c->backend_decl == NULL_TREE
    2975            6 :       && ref->u.c.sym != NULL)
    2976            6 :     gfc_get_derived_type (ref->u.c.sym);
    2977              : 
    2978       173559 :   field = c->backend_decl;
    2979       173559 :   gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
    2980       173559 :   decl = se->expr;
    2981       173559 :   context = DECL_FIELD_CONTEXT (field);
    2982              : 
    2983              :   /* Components can correspond to fields of different containing
    2984              :      types, as components are created without context, whereas
    2985              :      a concrete use of a component has the type of decl as context.
    2986              :      So, if the type doesn't match, we search the corresponding
    2987              :      FIELD_DECL in the parent type.  To not waste too much time
    2988              :      we cache this result in norestrict_decl.
    2989              :      On the other hand, if the context is a UNION or a MAP (a
    2990              :      RECORD_TYPE within a UNION_TYPE) always use the given FIELD_DECL.  */
    2991              : 
    2992       173559 :   if (context != TREE_TYPE (decl)
    2993       173559 :       && !(   TREE_CODE (TREE_TYPE (field)) == UNION_TYPE /* Field is union */
    2994        11979 :            || TREE_CODE (context) == UNION_TYPE))         /* Field is map */
    2995              :     {
    2996        11979 :       tree f2 = c->norestrict_decl;
    2997        20315 :       if (!f2 || DECL_FIELD_CONTEXT (f2) != TREE_TYPE (decl))
    2998         7262 :         for (f2 = TYPE_FIELDS (TREE_TYPE (decl)); f2; f2 = DECL_CHAIN (f2))
    2999         7262 :           if (TREE_CODE (f2) == FIELD_DECL
    3000         7262 :               && DECL_NAME (f2) == DECL_NAME (field))
    3001              :             break;
    3002        11979 :       gcc_assert (f2);
    3003        11979 :       c->norestrict_decl = f2;
    3004        11979 :       field = f2;
    3005              :     }
    3006              : 
    3007       173559 :   if (ref->u.c.sym && ref->u.c.sym->ts.type == BT_CLASS
    3008            0 :       && strcmp ("_data", c->name) == 0)
    3009              :     {
    3010              :       /* Found a ref to the _data component.  Store the associated ref to
    3011              :          the vptr in se->class_vptr.  */
    3012            0 :       se->class_vptr = gfc_class_vptr_get (decl);
    3013              :     }
    3014              :   else
    3015       173559 :     se->class_vptr = NULL_TREE;
    3016              : 
    3017       173559 :   tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
    3018              :                          decl, field, NULL_TREE);
    3019              : 
    3020       173559 :   se->expr = tmp;
    3021              : 
    3022              :   /* Allocatable deferred char arrays are to be handled by the gfc_deferred_
    3023              :      strlen () conditional below.  */
    3024       173559 :   if (c->ts.type == BT_CHARACTER && !c->attr.proc_pointer
    3025         8741 :       && !c->ts.deferred
    3026         5602 :       && !c->attr.pdt_string)
    3027              :     {
    3028         5428 :       tmp = c->ts.u.cl->backend_decl;
    3029              :       /* Components must always be constant length.  */
    3030         5428 :       gcc_assert (tmp && INTEGER_CST_P (tmp));
    3031         5428 :       se->string_length = tmp;
    3032              :     }
    3033              : 
    3034       173559 :   if (gfc_deferred_strlen (c, &field))
    3035              :     {
    3036         3313 :       tmp = fold_build3_loc (input_location, COMPONENT_REF,
    3037         3313 :                              TREE_TYPE (field),
    3038              :                              decl, field, NULL_TREE);
    3039         3313 :       se->string_length = tmp;
    3040              :     }
    3041              : 
    3042       173559 :   if (((c->attr.pointer || c->attr.allocatable)
    3043       101711 :        && (!c->attr.dimension && !c->attr.codimension)
    3044        55057 :        && c->ts.type != BT_CHARACTER)
    3045       120706 :       || c->attr.proc_pointer)
    3046        59097 :     se->expr = build_fold_indirect_ref_loc (input_location,
    3047              :                                         se->expr);
    3048       173559 : }
    3049              : 
    3050              : 
    3051              : /* This function deals with component references to components of the
    3052              :    parent type for derived type extensions.  */
    3053              : void
    3054        63069 : conv_parent_component_references (gfc_se * se, gfc_ref * ref)
    3055              : {
    3056        63069 :   gfc_component *c;
    3057        63069 :   gfc_component *cmp;
    3058        63069 :   gfc_symbol *dt;
    3059        63069 :   gfc_ref parent;
    3060              : 
    3061        63069 :   dt = ref->u.c.sym;
    3062        63069 :   c = ref->u.c.component;
    3063              : 
    3064              :   /* Return if the component is in this type, i.e. not in the parent type.  */
    3065       108634 :   for (cmp = dt->components; cmp; cmp = cmp->next)
    3066        98425 :     if (c == cmp)
    3067        52860 :       return;
    3068              : 
    3069              :   /* Build a gfc_ref to recursively call gfc_conv_component_ref.  */
    3070        10209 :   parent.type = REF_COMPONENT;
    3071        10209 :   parent.next = NULL;
    3072        10209 :   parent.u.c.sym = dt;
    3073        10209 :   parent.u.c.component = dt->components;
    3074              : 
    3075        10209 :   if (dt->backend_decl == NULL)
    3076            0 :     gfc_get_derived_type (dt);
    3077              : 
    3078              :   /* Build the reference and call self.  */
    3079        10209 :   gfc_conv_component_ref (se, &parent);
    3080        10209 :   parent.u.c.sym = dt->components->ts.u.derived;
    3081        10209 :   parent.u.c.component = c;
    3082        10209 :   conv_parent_component_references (se, &parent);
    3083              : }
    3084              : 
    3085              : 
    3086              : static void
    3087          537 : conv_inquiry (gfc_se * se, gfc_ref * ref, gfc_expr *expr, gfc_typespec *ts)
    3088              : {
    3089          537 :   tree res = se->expr;
    3090              : 
    3091          537 :   switch (ref->u.i)
    3092              :     {
    3093          259 :     case INQUIRY_RE:
    3094          518 :       res = fold_build1_loc (input_location, REALPART_EXPR,
    3095          259 :                              TREE_TYPE (TREE_TYPE (res)), res);
    3096          259 :       break;
    3097              : 
    3098          233 :     case INQUIRY_IM:
    3099          466 :       res = fold_build1_loc (input_location, IMAGPART_EXPR,
    3100          233 :                              TREE_TYPE (TREE_TYPE (res)), res);
    3101          233 :       break;
    3102              : 
    3103            7 :     case INQUIRY_KIND:
    3104            7 :       res = build_int_cst (gfc_typenode_for_spec (&expr->ts),
    3105            7 :                            ts->kind);
    3106            7 :       se->string_length = NULL_TREE;
    3107            7 :       break;
    3108              : 
    3109           38 :     case INQUIRY_LEN:
    3110           38 :       res = fold_convert (gfc_typenode_for_spec (&expr->ts),
    3111              :                           se->string_length);
    3112           38 :       se->string_length = NULL_TREE;
    3113           38 :       break;
    3114              : 
    3115            0 :     default:
    3116            0 :       gcc_unreachable ();
    3117              :     }
    3118          537 :   se->expr = res;
    3119          537 : }
    3120              : 
    3121              : /* Dereference VAR where needed if it is a pointer, reference, etc.
    3122              :    according to Fortran semantics.  */
    3123              : 
    3124              : tree
    3125      1434382 : gfc_maybe_dereference_var (gfc_symbol *sym, tree var, bool descriptor_only_p,
    3126              :                            bool is_classarray)
    3127              : {
    3128      1434382 :   if (!POINTER_TYPE_P (TREE_TYPE (var)))
    3129              :     return var;
    3130       288727 :   if (is_CFI_desc (sym, NULL))
    3131        11892 :     return build_fold_indirect_ref_loc (input_location, var);
    3132              : 
    3133              :   /* Characters are entirely different from other types, they are treated
    3134              :      separately.  */
    3135       276835 :   if (sym->ts.type == BT_CHARACTER)
    3136              :     {
    3137              :       /* Dereference character pointer dummy arguments
    3138              :          or results.  */
    3139        32471 :       if ((sym->attr.pointer || sym->attr.allocatable
    3140        18831 :            || (sym->as && sym->as->type == AS_ASSUMED_RANK))
    3141        13976 :           && (sym->attr.dummy
    3142        10680 :               || sym->attr.function
    3143        10306 :               || sym->attr.result))
    3144         4334 :         var = build_fold_indirect_ref_loc (input_location, var);
    3145              :     }
    3146       244364 :   else if (!sym->attr.value)
    3147              :     {
    3148              :       /* Dereference temporaries for class array dummy arguments.  */
    3149       168746 :       if (sym->attr.dummy && is_classarray
    3150       251025 :           && GFC_ARRAY_TYPE_P (TREE_TYPE (var)))
    3151              :         {
    3152         5157 :           if (!descriptor_only_p)
    3153         2626 :             var = GFC_DECL_SAVED_DESCRIPTOR (var);
    3154              : 
    3155         5157 :           var = build_fold_indirect_ref_loc (input_location, var);
    3156              :         }
    3157              : 
    3158              :       /* Dereference non-character scalar dummy arguments.  */
    3159       243560 :       if (sym->attr.dummy && !sym->attr.dimension
    3160       103089 :           && !(sym->attr.codimension && sym->attr.allocatable)
    3161       103023 :           && (sym->ts.type != BT_CLASS
    3162        19092 :               || (!CLASS_DATA (sym)->attr.dimension
    3163        11157 :                   && !(CLASS_DATA (sym)->attr.codimension
    3164          283 :                        && CLASS_DATA (sym)->attr.allocatable))))
    3165        94947 :         var = build_fold_indirect_ref_loc (input_location, var);
    3166              : 
    3167              :       /* Dereference scalar hidden result.  */
    3168       243560 :       if (flag_f2c && sym->ts.type == BT_COMPLEX
    3169          286 :           && (sym->attr.function || sym->attr.result)
    3170          108 :           && !sym->attr.dimension && !sym->attr.pointer
    3171           60 :           && !sym->attr.always_explicit)
    3172           36 :         var = build_fold_indirect_ref_loc (input_location, var);
    3173              : 
    3174              :       /* Dereference non-character, non-class pointer variables.
    3175              :          These must be dummies, results, or scalars.  */
    3176       243560 :       if (!is_classarray
    3177       235652 :           && (sym->attr.pointer || sym->attr.allocatable
    3178       187265 :               || gfc_is_associate_pointer (sym)
    3179       182624 :               || (sym->as && sym->as->type == AS_ASSUMED_RANK))
    3180       318212 :           && (sym->attr.dummy
    3181        35198 :               || sym->attr.function
    3182        34268 :               || sym->attr.result
    3183        33174 :               || (!sym->attr.dimension
    3184        33169 :                   && (!sym->attr.codimension || !sym->attr.allocatable))))
    3185        74647 :         var = build_fold_indirect_ref_loc (input_location, var);
    3186              :       /* Now treat the class array pointer variables accordingly.  */
    3187       168913 :       else if (sym->ts.type == BT_CLASS
    3188        19535 :                && sym->attr.dummy
    3189        19092 :                && (CLASS_DATA (sym)->attr.dimension
    3190        11157 :                    || CLASS_DATA (sym)->attr.codimension)
    3191         8218 :                && ((CLASS_DATA (sym)->as
    3192         8218 :                     && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK)
    3193         7221 :                    || CLASS_DATA (sym)->attr.allocatable
    3194         5890 :                    || CLASS_DATA (sym)->attr.class_pointer))
    3195         2919 :         var = build_fold_indirect_ref_loc (input_location, var);
    3196              :       /* And the case where a non-dummy, non-result, non-function,
    3197              :          non-allocable and non-pointer classarray is present.  This case was
    3198              :          previously covered by the first if, but with introducing the
    3199              :          condition !is_classarray there, that case has to be covered
    3200              :          explicitly.  */
    3201       165994 :       else if (sym->ts.type == BT_CLASS
    3202        16616 :                && !sym->attr.dummy
    3203          443 :                && !sym->attr.function
    3204          443 :                && !sym->attr.result
    3205          443 :                && (CLASS_DATA (sym)->attr.dimension
    3206            4 :                    || CLASS_DATA (sym)->attr.codimension)
    3207          443 :                && (sym->assoc
    3208            0 :                    || !CLASS_DATA (sym)->attr.allocatable)
    3209          443 :                && !CLASS_DATA (sym)->attr.class_pointer)
    3210          443 :         var = build_fold_indirect_ref_loc (input_location, var);
    3211              :     }
    3212              : 
    3213              :   return var;
    3214              : }
    3215              : 
    3216              : /* Return the contents of a variable. Also handles reference/pointer
    3217              :    variables (all Fortran pointer references are implicit).  */
    3218              : 
    3219              : static void
    3220      1584912 : gfc_conv_variable (gfc_se * se, gfc_expr * expr)
    3221              : {
    3222      1584912 :   gfc_ss *ss;
    3223      1584912 :   gfc_ref *ref;
    3224      1584912 :   gfc_symbol *sym;
    3225      1584912 :   tree parent_decl = NULL_TREE;
    3226      1584912 :   int parent_flag;
    3227      1584912 :   bool return_value;
    3228      1584912 :   bool alternate_entry;
    3229      1584912 :   bool entry_master;
    3230      1584912 :   bool is_classarray;
    3231      1584912 :   bool first_time = true;
    3232              : 
    3233      1584912 :   sym = expr->symtree->n.sym;
    3234      1584912 :   is_classarray = IS_CLASS_COARRAY_OR_ARRAY (sym);
    3235      1584912 :   ss = se->ss;
    3236      1584912 :   if (ss != NULL)
    3237              :     {
    3238       130398 :       gfc_ss_info *ss_info = ss->info;
    3239              : 
    3240              :       /* Check that something hasn't gone horribly wrong.  */
    3241       130398 :       gcc_assert (ss != gfc_ss_terminator);
    3242       130398 :       gcc_assert (ss_info->expr == expr);
    3243              : 
    3244              :       /* A scalarized term.  We already know the descriptor.  */
    3245       130398 :       se->expr = ss_info->data.array.descriptor;
    3246       130398 :       se->string_length = ss_info->string_length;
    3247       130398 :       ref = ss_info->data.array.ref;
    3248       130398 :       if (ref)
    3249       130080 :         gcc_assert (ref->type == REF_ARRAY
    3250              :                     && ref->u.ar.type != AR_ELEMENT);
    3251              :       else
    3252          318 :         gfc_conv_tmp_array_ref (se);
    3253              :     }
    3254              :   else
    3255              :     {
    3256      1454514 :       tree se_expr = NULL_TREE;
    3257              : 
    3258      1454514 :       se->expr = gfc_get_symbol_decl (sym);
    3259              : 
    3260              :       /* Deal with references to a parent results or entries by storing
    3261              :          the current_function_decl and moving to the parent_decl.  */
    3262      1454514 :       return_value = sym->attr.function && sym->result == sym;
    3263        18600 :       alternate_entry = sym->attr.function && sym->attr.entry
    3264      1455593 :                         && sym->result == sym;
    3265      2909028 :       entry_master = sym->attr.result
    3266        14214 :                      && sym->ns->proc_name->attr.entry_master
    3267      1454895 :                      && !gfc_return_by_reference (sym->ns->proc_name);
    3268      1454514 :       if (current_function_decl)
    3269      1434402 :         parent_decl = DECL_CONTEXT (current_function_decl);
    3270              : 
    3271      1454514 :       if ((se->expr == parent_decl && return_value)
    3272      1454403 :            || (sym->ns && sym->ns->proc_name
    3273      1449489 :                && parent_decl
    3274      1429377 :                && sym->ns->proc_name->backend_decl == parent_decl
    3275        37510 :                && (alternate_entry || entry_master)))
    3276              :         parent_flag = 1;
    3277              :       else
    3278      1454370 :         parent_flag = 0;
    3279              : 
    3280              :       /* Special case for assigning the return value of a function.
    3281              :          Self recursive functions must have an explicit return value.  */
    3282      1454514 :       if (return_value && (se->expr == current_function_decl || parent_flag))
    3283        10234 :         se_expr = gfc_get_fake_result_decl (sym, parent_flag);
    3284              : 
    3285              :       /* Similarly for alternate entry points.  */
    3286      1444280 :       else if (alternate_entry
    3287         1046 :                && (sym->ns->proc_name->backend_decl == current_function_decl
    3288            0 :                    || parent_flag))
    3289              :         {
    3290         1046 :           gfc_entry_list *el = NULL;
    3291              : 
    3292         1615 :           for (el = sym->ns->entries; el; el = el->next)
    3293         1615 :             if (sym == el->sym)
    3294              :               {
    3295         1046 :                 se_expr = gfc_get_fake_result_decl (sym, parent_flag);
    3296         1046 :                 break;
    3297              :               }
    3298              :         }
    3299              : 
    3300      1443234 :       else if (entry_master
    3301          295 :                && (sym->ns->proc_name->backend_decl == current_function_decl
    3302            0 :                    || parent_flag))
    3303          295 :         se_expr = gfc_get_fake_result_decl (sym, parent_flag);
    3304              : 
    3305        11575 :       if (se_expr)
    3306        11575 :         se->expr = se_expr;
    3307              : 
    3308              :       /* Procedure actual arguments.  Look out for temporary variables
    3309              :          with the same attributes as function values.  */
    3310      1442939 :       else if (!sym->attr.temporary
    3311      1442871 :                && sym->attr.flavor == FL_PROCEDURE
    3312        22243 :                && se->expr != current_function_decl)
    3313              :         {
    3314        22176 :           if (!sym->attr.dummy && !sym->attr.proc_pointer)
    3315              :             {
    3316        20636 :               gcc_assert (TREE_CODE (se->expr) == FUNCTION_DECL);
    3317        20636 :               se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
    3318              :             }
    3319        22176 :           return;
    3320              :         }
    3321              : 
    3322      1432338 :       if (sym->ts.type == BT_CLASS
    3323        71381 :           && sym->attr.class_ok
    3324        71139 :           && sym->ts.u.derived->attr.is_class)
    3325              :         {
    3326        27511 :           if (is_classarray && DECL_LANG_SPECIFIC (se->expr)
    3327        78451 :               && GFC_DECL_SAVED_DESCRIPTOR (se->expr))
    3328         5299 :             se->class_container = GFC_DECL_SAVED_DESCRIPTOR (se->expr);
    3329              :           else
    3330        65840 :             se->class_container = se->expr;
    3331              :         }
    3332              : 
    3333              :       /* Dereference the expression, where needed.  */
    3334      1432338 :       if (se->class_container && CLASS_DATA (sym)->attr.codimension
    3335         2042 :           && !CLASS_DATA (sym)->attr.dimension)
    3336          877 :         se->expr
    3337          877 :           = gfc_maybe_dereference_var (sym, se->class_container,
    3338          877 :                                        se->descriptor_only, is_classarray);
    3339              :       else
    3340      1431461 :         se->expr
    3341      1431461 :           = gfc_maybe_dereference_var (sym, se->expr, se->descriptor_only,
    3342              :                                        is_classarray);
    3343              : 
    3344      1432338 :       ref = expr->ref;
    3345              :     }
    3346              : 
    3347              :   /* For character variables, also get the length.  */
    3348      1562736 :   if (sym->ts.type == BT_CHARACTER)
    3349              :     {
    3350              :       /* If the character length of an entry isn't set, get the length from
    3351              :          the master function instead.  */
    3352       164158 :       if (sym->attr.entry && !sym->ts.u.cl->backend_decl)
    3353            0 :         se->string_length = sym->ns->proc_name->ts.u.cl->backend_decl;
    3354              :       else
    3355       164158 :         se->string_length = sym->ts.u.cl->backend_decl;
    3356       164158 :       gcc_assert (se->string_length);
    3357              : 
    3358              :       /* For coarray strings return the pointer to the data and not the
    3359              :          descriptor.  */
    3360         5143 :       if (sym->attr.codimension && sym->attr.associate_var
    3361            6 :           && !se->descriptor_only
    3362       164164 :           && TREE_CODE (TREE_TYPE (se->expr)) != ARRAY_TYPE)
    3363            6 :         se->expr = gfc_conv_descriptor_data_get (se->expr);
    3364              :     }
    3365              : 
    3366              :   /* F202Y: Runtime warning that an assumed rank object is associated
    3367              :      with an assumed size object.  */
    3368      1562736 :   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    3369        89135 :       && (gfc_option.allow_std & GFC_STD_F202Y)
    3370      1562970 :       && expr->rank == -1 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
    3371              :     {
    3372           60 :       tree dim, lower, upper, cond;
    3373           60 :       char *msg;
    3374              : 
    3375           60 :       dim = fold_convert (signed_char_type_node,
    3376              :                           gfc_conv_descriptor_rank (se->expr));
    3377           60 :       dim = fold_build2_loc (input_location, MINUS_EXPR, signed_char_type_node,
    3378              :                              dim, build_int_cst (signed_char_type_node, 1));
    3379           60 :       lower = gfc_conv_descriptor_lbound_get (se->expr, dim);
    3380           60 :       upper = gfc_conv_descriptor_ubound_get (se->expr, dim);
    3381              : 
    3382           60 :       msg = xasprintf ("Assumed rank object %s is associated with an "
    3383              :                        "assumed size object", sym->name);
    3384           60 :       cond = fold_build2_loc (input_location, LT_EXPR,
    3385              :                               logical_type_node, upper, lower);
    3386           60 :       gfc_trans_runtime_check (false, true, cond, &se->pre,
    3387              :                                &gfc_current_locus, msg);
    3388           60 :       free (msg);
    3389              :     }
    3390              : 
    3391              :   /* Some expressions leak through that haven't been fixed up.  */
    3392      1562736 :   if (IS_INFERRED_TYPE (expr) && expr->ref)
    3393          404 :     gfc_fixup_inferred_type_refs (expr);
    3394              : 
    3395      1562736 :   gfc_typespec *ts = &sym->ts;
    3396      1989447 :   while (ref)
    3397              :     {
    3398       770372 :       switch (ref->type)
    3399              :         {
    3400       600154 :         case REF_ARRAY:
    3401              :           /* Return the descriptor if that's what we want and this is an array
    3402              :              section reference.  */
    3403       600154 :           if (se->descriptor_only && ref->u.ar.type != AR_ELEMENT)
    3404              :             return;
    3405              : /* TODO: Pointers to single elements of array sections, eg elemental subs.  */
    3406              :           /* Return the descriptor for array pointers and allocations.  */
    3407       265732 :           if (se->want_pointer
    3408        23385 :               && ref->next == NULL && (se->descriptor_only))
    3409              :             return;
    3410              : 
    3411       256493 :           gfc_conv_array_ref (se, &ref->u.ar, expr, &expr->where);
    3412              :           /* Return a pointer to an element.  */
    3413       256493 :           break;
    3414              : 
    3415       163096 :         case REF_COMPONENT:
    3416       163096 :           ts = &ref->u.c.component->ts;
    3417       163096 :           if (first_time && IS_CLASS_ARRAY (sym) && sym->attr.dummy
    3418         5673 :               && se->descriptor_only && !CLASS_DATA (sym)->attr.allocatable
    3419         2998 :               && !CLASS_DATA (sym)->attr.class_pointer && CLASS_DATA (sym)->as
    3420         2998 :               && CLASS_DATA (sym)->as->type != AS_ASSUMED_RANK
    3421         2531 :               && strcmp ("_data", ref->u.c.component->name) == 0)
    3422              :             /* Skip the first ref of a _data component, because for class
    3423              :                arrays that one is already done by introducing a temporary
    3424              :                array descriptor.  */
    3425              :             break;
    3426              : 
    3427       160565 :           if (ref->u.c.sym->attr.extension)
    3428        52769 :             conv_parent_component_references (se, ref);
    3429              : 
    3430       160565 :           gfc_conv_component_ref (se, ref);
    3431              : 
    3432       160565 :           if (ref->u.c.component->ts.type == BT_CLASS
    3433        11801 :               && ref->u.c.component->attr.class_ok
    3434        11801 :               && ref->u.c.component->ts.u.derived->attr.is_class)
    3435        11801 :             se->class_container = se->expr;
    3436       148764 :           else if (!(ref->u.c.sym->attr.flavor == FL_DERIVED
    3437       146270 :                      && ref->u.c.sym->attr.is_class))
    3438        81798 :             se->class_container = NULL_TREE;
    3439              : 
    3440       160565 :           if (!ref->next && ref->u.c.sym->attr.codimension
    3441            0 :               && se->want_pointer && se->descriptor_only)
    3442              :             return;
    3443              : 
    3444              :           break;
    3445              : 
    3446         6585 :         case REF_SUBSTRING:
    3447         6585 :           gfc_conv_substring (se, ref, expr->ts.kind,
    3448         6585 :                               expr->symtree->name, &expr->where);
    3449         6585 :           break;
    3450              : 
    3451          537 :         case REF_INQUIRY:
    3452          537 :           conv_inquiry (se, ref, expr, ts);
    3453          537 :           break;
    3454              : 
    3455            0 :         default:
    3456            0 :           gcc_unreachable ();
    3457       426711 :           break;
    3458              :         }
    3459       426711 :       first_time = false;
    3460       426711 :       ref = ref->next;
    3461              :     }
    3462              :   /* Pointer assignment, allocation or pass by reference.  Arrays are handled
    3463              :      separately.  */
    3464      1219075 :   if (se->want_pointer)
    3465              :     {
    3466       132235 :       if (expr->ts.type == BT_CHARACTER && !gfc_is_proc_ptr_comp (expr))
    3467         7974 :         gfc_conv_string_parameter (se);
    3468              :       else
    3469       124261 :         se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
    3470              :     }
    3471              : }
    3472              : 
    3473              : 
    3474              : /* Unary ops are easy... Or they would be if ! was a valid op.  */
    3475              : 
    3476              : static void
    3477        28734 : gfc_conv_unary_op (enum tree_code code, gfc_se * se, gfc_expr * expr)
    3478              : {
    3479        28734 :   gfc_se operand;
    3480        28734 :   tree type;
    3481              : 
    3482        28734 :   gcc_assert (expr->ts.type != BT_CHARACTER);
    3483              :   /* Initialize the operand.  */
    3484        28734 :   gfc_init_se (&operand, se);
    3485        28734 :   gfc_conv_expr_val (&operand, expr->value.op.op1);
    3486        28734 :   gfc_add_block_to_block (&se->pre, &operand.pre);
    3487              : 
    3488        28734 :   type = gfc_typenode_for_spec (&expr->ts);
    3489              : 
    3490              :   /* TRUTH_NOT_EXPR is not a "true" unary operator in GCC.
    3491              :      We must convert it to a compare to 0 (e.g. EQ_EXPR (op1, 0)).
    3492              :      All other unary operators have an equivalent GIMPLE unary operator.  */
    3493        28734 :   if (code == TRUTH_NOT_EXPR)
    3494        20134 :     se->expr = fold_build2_loc (input_location, EQ_EXPR, type, operand.expr,
    3495              :                                 build_int_cst (type, 0));
    3496              :   else
    3497         8600 :     se->expr = fold_build1_loc (input_location, code, type, operand.expr);
    3498              : 
    3499        28734 : }
    3500              : 
    3501              : /* Expand power operator to optimal multiplications when a value is raised
    3502              :    to a constant integer n. See section 4.6.3, "Evaluation of Powers" of
    3503              :    Donald E. Knuth, "Seminumerical Algorithms", Vol. 2, "The Art of Computer
    3504              :    Programming", 3rd Edition, 1998.  */
    3505              : 
    3506              : /* This code is mostly duplicated from expand_powi in the backend.
    3507              :    We establish the "optimal power tree" lookup table with the defined size.
    3508              :    The items in the table are the exponents used to calculate the index
    3509              :    exponents. Any integer n less than the value can get an "addition chain",
    3510              :    with the first node being one.  */
    3511              : #define POWI_TABLE_SIZE 256
    3512              : 
    3513              : /* The table is from builtins.cc.  */
    3514              : static const unsigned char powi_table[POWI_TABLE_SIZE] =
    3515              :   {
    3516              :       0,   1,   1,   2,   2,   3,   3,   4,  /*   0 -   7 */
    3517              :       4,   6,   5,   6,   6,  10,   7,   9,  /*   8 -  15 */
    3518              :       8,  16,   9,  16,  10,  12,  11,  13,  /*  16 -  23 */
    3519              :      12,  17,  13,  18,  14,  24,  15,  26,  /*  24 -  31 */
    3520              :      16,  17,  17,  19,  18,  33,  19,  26,  /*  32 -  39 */
    3521              :      20,  25,  21,  40,  22,  27,  23,  44,  /*  40 -  47 */
    3522              :      24,  32,  25,  34,  26,  29,  27,  44,  /*  48 -  55 */
    3523              :      28,  31,  29,  34,  30,  60,  31,  36,  /*  56 -  63 */
    3524              :      32,  64,  33,  34,  34,  46,  35,  37,  /*  64 -  71 */
    3525              :      36,  65,  37,  50,  38,  48,  39,  69,  /*  72 -  79 */
    3526              :      40,  49,  41,  43,  42,  51,  43,  58,  /*  80 -  87 */
    3527              :      44,  64,  45,  47,  46,  59,  47,  76,  /*  88 -  95 */
    3528              :      48,  65,  49,  66,  50,  67,  51,  66,  /*  96 - 103 */
    3529              :      52,  70,  53,  74,  54, 104,  55,  74,  /* 104 - 111 */
    3530              :      56,  64,  57,  69,  58,  78,  59,  68,  /* 112 - 119 */
    3531              :      60,  61,  61,  80,  62,  75,  63,  68,  /* 120 - 127 */
    3532              :      64,  65,  65, 128,  66, 129,  67,  90,  /* 128 - 135 */
    3533              :      68,  73,  69, 131,  70,  94,  71,  88,  /* 136 - 143 */
    3534              :      72, 128,  73,  98,  74, 132,  75, 121,  /* 144 - 151 */
    3535              :      76, 102,  77, 124,  78, 132,  79, 106,  /* 152 - 159 */
    3536              :      80,  97,  81, 160,  82,  99,  83, 134,  /* 160 - 167 */
    3537              :      84,  86,  85,  95,  86, 160,  87, 100,  /* 168 - 175 */
    3538              :      88, 113,  89,  98,  90, 107,  91, 122,  /* 176 - 183 */
    3539              :      92, 111,  93, 102,  94, 126,  95, 150,  /* 184 - 191 */
    3540              :      96, 128,  97, 130,  98, 133,  99, 195,  /* 192 - 199 */
    3541              :     100, 128, 101, 123, 102, 164, 103, 138,  /* 200 - 207 */
    3542              :     104, 145, 105, 146, 106, 109, 107, 149,  /* 208 - 215 */
    3543              :     108, 200, 109, 146, 110, 170, 111, 157,  /* 216 - 223 */
    3544              :     112, 128, 113, 130, 114, 182, 115, 132,  /* 224 - 231 */
    3545              :     116, 200, 117, 132, 118, 158, 119, 206,  /* 232 - 239 */
    3546              :     120, 240, 121, 162, 122, 147, 123, 152,  /* 240 - 247 */
    3547              :     124, 166, 125, 214, 126, 138, 127, 153,  /* 248 - 255 */
    3548              :   };
    3549              : 
    3550              : /* If n is larger than lookup table's max index, we use the "window
    3551              :    method".  */
    3552              : #define POWI_WINDOW_SIZE 3
    3553              : 
    3554              : /* Recursive function to expand the power operator. The temporary
    3555              :    values are put in tmpvar. The function returns tmpvar[1] ** n.  */
    3556              : static tree
    3557       178323 : gfc_conv_powi (gfc_se * se, unsigned HOST_WIDE_INT n, tree * tmpvar)
    3558              : {
    3559       178323 :   tree op0;
    3560       178323 :   tree op1;
    3561       178323 :   tree tmp;
    3562       178323 :   int digit;
    3563              : 
    3564       178323 :   if (n < POWI_TABLE_SIZE)
    3565              :     {
    3566       137336 :       if (tmpvar[n])
    3567              :         return tmpvar[n];
    3568              : 
    3569        56612 :       op0 = gfc_conv_powi (se, n - powi_table[n], tmpvar);
    3570        56612 :       op1 = gfc_conv_powi (se, powi_table[n], tmpvar);
    3571              :     }
    3572        40987 :   else if (n & 1)
    3573              :     {
    3574        10015 :       digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
    3575        10015 :       op0 = gfc_conv_powi (se, n - digit, tmpvar);
    3576        10015 :       op1 = gfc_conv_powi (se, digit, tmpvar);
    3577              :     }
    3578              :   else
    3579              :     {
    3580        30972 :       op0 = gfc_conv_powi (se, n >> 1, tmpvar);
    3581        30972 :       op1 = op0;
    3582              :     }
    3583              : 
    3584        97599 :   tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (op0), op0, op1);
    3585        97599 :   tmp = gfc_evaluate_now (tmp, &se->pre);
    3586              : 
    3587        97599 :   if (n < POWI_TABLE_SIZE)
    3588        56612 :     tmpvar[n] = tmp;
    3589              : 
    3590              :   return tmp;
    3591              : }
    3592              : 
    3593              : 
    3594              : /* Expand lhs ** rhs. rhs is a constant integer. If it expands successfully,
    3595              :    return 1. Else return 0 and a call to runtime library functions
    3596              :    will have to be built.  */
    3597              : static int
    3598         3305 : gfc_conv_cst_int_power (gfc_se * se, tree lhs, tree rhs)
    3599              : {
    3600         3305 :   tree cond;
    3601         3305 :   tree tmp;
    3602         3305 :   tree type;
    3603         3305 :   tree vartmp[POWI_TABLE_SIZE];
    3604         3305 :   HOST_WIDE_INT m;
    3605         3305 :   unsigned HOST_WIDE_INT n;
    3606         3305 :   int sgn;
    3607         3305 :   wi::tree_to_wide_ref wrhs = wi::to_wide (rhs);
    3608              : 
    3609              :   /* If exponent is too large, we won't expand it anyway, so don't bother
    3610              :      with large integer values.  */
    3611         3305 :   if (!wi::fits_shwi_p (wrhs))
    3612              :     return 0;
    3613              : 
    3614         2945 :   m = wrhs.to_shwi ();
    3615              :   /* Use the wide_int's routine to reliably get the absolute value on all
    3616              :      platforms.  Then convert it to a HOST_WIDE_INT like above.  */
    3617         2945 :   n = wi::abs (wrhs).to_shwi ();
    3618              : 
    3619         2945 :   type = TREE_TYPE (lhs);
    3620         2945 :   sgn = tree_int_cst_sgn (rhs);
    3621              : 
    3622         2945 :   if (((FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations)
    3623         5890 :        || optimize_size) && (m > 2 || m < -1))
    3624              :     return 0;
    3625              : 
    3626              :   /* rhs == 0  */
    3627         1639 :   if (sgn == 0)
    3628              :     {
    3629          282 :       se->expr = gfc_build_const (type, integer_one_node);
    3630          282 :       return 1;
    3631              :     }
    3632              : 
    3633              :   /* If rhs < 0 and lhs is an integer, the result is -1, 0 or 1.  */
    3634         1357 :   if ((sgn == -1) && (TREE_CODE (type) == INTEGER_TYPE))
    3635              :     {
    3636          220 :       tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    3637          220 :                              lhs, build_int_cst (TREE_TYPE (lhs), -1));
    3638          220 :       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    3639          220 :                               lhs, build_int_cst (TREE_TYPE (lhs), 1));
    3640              : 
    3641              :       /* If rhs is even,
    3642              :          result = (lhs == 1 || lhs == -1) ? 1 : 0.  */
    3643          220 :       if ((n & 1) == 0)
    3644              :         {
    3645          104 :           tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
    3646              :                                  logical_type_node, tmp, cond);
    3647          104 :           se->expr = fold_build3_loc (input_location, COND_EXPR, type,
    3648              :                                       tmp, build_int_cst (type, 1),
    3649              :                                       build_int_cst (type, 0));
    3650          104 :           return 1;
    3651              :         }
    3652              :       /* If rhs is odd,
    3653              :          result = (lhs == 1) ? 1 : (lhs == -1) ? -1 : 0.  */
    3654          116 :       tmp = fold_build3_loc (input_location, COND_EXPR, type, tmp,
    3655              :                              build_int_cst (type, -1),
    3656              :                              build_int_cst (type, 0));
    3657          116 :       se->expr = fold_build3_loc (input_location, COND_EXPR, type,
    3658              :                                   cond, build_int_cst (type, 1), tmp);
    3659          116 :       return 1;
    3660              :     }
    3661              : 
    3662         1137 :   memset (vartmp, 0, sizeof (vartmp));
    3663         1137 :   vartmp[1] = lhs;
    3664         1137 :   if (sgn == -1)
    3665              :     {
    3666          141 :       tmp = gfc_build_const (type, integer_one_node);
    3667          141 :       vartmp[1] = fold_build2_loc (input_location, RDIV_EXPR, type, tmp,
    3668              :                                    vartmp[1]);
    3669              :     }
    3670              : 
    3671         1137 :   se->expr = gfc_conv_powi (se, n, vartmp);
    3672              : 
    3673         1137 :   return 1;
    3674              : }
    3675              : 
    3676              : /* Convert lhs**rhs, for constant rhs, when both are unsigned.
    3677              :    Method:
    3678              :    if (rhs == 0)      ! Checked here.
    3679              :      return 1;
    3680              :    if (lhs & 1 == 1)  ! odd_cnd
    3681              :      {
    3682              :        if (bit_size(rhs) < bit_size(lhs))  ! Checked here.
    3683              :          return lhs ** rhs;
    3684              : 
    3685              :        mask = 1 << (bit_size(a) - 1) / 2;
    3686              :        return lhs ** (n & rhs);
    3687              :      }
    3688              :    if (rhs > bit_size(lhs))  ! Checked here.
    3689              :      return 0;
    3690              : 
    3691              :    return lhs ** rhs;
    3692              : */
    3693              : 
    3694              : static int
    3695        15120 : gfc_conv_cst_uint_power (gfc_se * se, tree lhs, tree rhs)
    3696              : {
    3697        15120 :   tree type = TREE_TYPE (lhs);
    3698        15120 :   tree tmp, is_odd, odd_branch, even_branch;
    3699        15120 :   unsigned HOST_WIDE_INT lhs_prec, rhs_prec;
    3700        15120 :   wi::tree_to_wide_ref wrhs = wi::to_wide (rhs);
    3701        15120 :   unsigned HOST_WIDE_INT n, n_odd;
    3702        15120 :   tree vartmp_odd[POWI_TABLE_SIZE], vartmp_even[POWI_TABLE_SIZE];
    3703              : 
    3704              :   /* Anything ** 0 is one.  */
    3705        15120 :   if (integer_zerop (rhs))
    3706              :     {
    3707         1800 :       se->expr = build_int_cst (type, 1);
    3708         1800 :       return 1;
    3709              :     }
    3710              : 
    3711        13320 :   if (!wi::fits_uhwi_p (wrhs))
    3712              :     return 0;
    3713              : 
    3714        12960 :   n = wrhs.to_uhwi ();
    3715              : 
    3716              :   /* tmp = a & 1; . */
    3717        12960 :   tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type,
    3718              :                          lhs, build_int_cst (type, 1));
    3719        12960 :   is_odd = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    3720              :                             tmp, build_int_cst (type, 1));
    3721              : 
    3722        12960 :   lhs_prec = TYPE_PRECISION (type);
    3723        12960 :   rhs_prec = TYPE_PRECISION (TREE_TYPE (rhs));
    3724              : 
    3725        12960 :   if (rhs_prec >= lhs_prec && lhs_prec <= HOST_BITS_PER_WIDE_INT)
    3726              :     {
    3727         7044 :       unsigned HOST_WIDE_INT mask = (HOST_WIDE_INT_1U << (lhs_prec - 1)) - 1;
    3728         7044 :       n_odd = n & mask;
    3729              :     }
    3730              :   else
    3731              :     n_odd = n;
    3732              : 
    3733        12960 :   memset (vartmp_odd, 0, sizeof (vartmp_odd));
    3734        12960 :   vartmp_odd[0] = build_int_cst (type, 1);
    3735        12960 :   vartmp_odd[1] = lhs;
    3736        12960 :   odd_branch = gfc_conv_powi (se, n_odd, vartmp_odd);
    3737        12960 :   even_branch = NULL_TREE;
    3738              : 
    3739        12960 :   if (n > lhs_prec)
    3740         4260 :     even_branch = build_int_cst (type, 0);
    3741              :   else
    3742              :     {
    3743         8700 :       if (n_odd != n)
    3744              :         {
    3745            0 :           memset (vartmp_even, 0, sizeof (vartmp_even));
    3746            0 :           vartmp_even[0] = build_int_cst (type, 1);
    3747            0 :           vartmp_even[1] = lhs;
    3748            0 :           even_branch = gfc_conv_powi (se, n, vartmp_even);
    3749              :         }
    3750              :     }
    3751         4260 :   if (even_branch != NULL_TREE)
    3752         4260 :     se->expr = fold_build3_loc (input_location, COND_EXPR, type, is_odd,
    3753              :                                 odd_branch, even_branch);
    3754              :   else
    3755         8700 :     se->expr = odd_branch;
    3756              : 
    3757              :   return 1;
    3758              : }
    3759              : 
    3760              : /* Power op (**).  Constant integer exponent and powers of 2 have special
    3761              :    handling.  */
    3762              : 
    3763              : static void
    3764        49129 : gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
    3765              : {
    3766        49129 :   tree gfc_int4_type_node;
    3767        49129 :   int kind;
    3768        49129 :   int ikind;
    3769        49129 :   int res_ikind_1, res_ikind_2;
    3770        49129 :   gfc_se lse;
    3771        49129 :   gfc_se rse;
    3772        49129 :   tree fndecl = NULL;
    3773              : 
    3774        49129 :   gfc_init_se (&lse, se);
    3775        49129 :   gfc_conv_expr_val (&lse, expr->value.op.op1);
    3776        49129 :   lse.expr = gfc_evaluate_now (lse.expr, &lse.pre);
    3777        49129 :   gfc_add_block_to_block (&se->pre, &lse.pre);
    3778              : 
    3779        49129 :   gfc_init_se (&rse, se);
    3780        49129 :   gfc_conv_expr_val (&rse, expr->value.op.op2);
    3781        49129 :   gfc_add_block_to_block (&se->pre, &rse.pre);
    3782              : 
    3783        49129 :   if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
    3784              :     {
    3785        17563 :       if (expr->value.op.op2->ts.type == BT_INTEGER)
    3786              :         {
    3787         2292 :           if (gfc_conv_cst_int_power (se, lse.expr, rse.expr))
    3788        20418 :             return;
    3789              :         }
    3790        15271 :       else if (expr->value.op.op2->ts.type == BT_UNSIGNED)
    3791              :         {
    3792        15120 :           if (gfc_conv_cst_uint_power (se, lse.expr, rse.expr))
    3793              :             return;
    3794              :         }
    3795              :     }
    3796              : 
    3797        32730 :   if ((expr->value.op.op2->ts.type == BT_INTEGER
    3798        31468 :        || expr->value.op.op2->ts.type == BT_UNSIGNED)
    3799        31862 :       && expr->value.op.op2->expr_type == EXPR_CONSTANT)
    3800         1013 :     if (gfc_conv_cst_int_power (se, lse.expr, rse.expr))
    3801              :       return;
    3802              : 
    3803        32730 :   if (INTEGER_CST_P (lse.expr)
    3804        15371 :       && TREE_CODE (TREE_TYPE (rse.expr)) == INTEGER_TYPE
    3805        48101 :       && expr->value.op.op2->ts.type == BT_INTEGER)
    3806              :     {
    3807          251 :       wi::tree_to_wide_ref wlhs = wi::to_wide (lse.expr);
    3808          251 :       HOST_WIDE_INT v;
    3809          251 :       unsigned HOST_WIDE_INT w;
    3810          251 :       int kind, ikind, bit_size;
    3811              : 
    3812          251 :       v = wlhs.to_shwi ();
    3813          251 :       w = absu_hwi (v);
    3814              : 
    3815          251 :       kind = expr->value.op.op1->ts.kind;
    3816          251 :       ikind = gfc_validate_kind (BT_INTEGER, kind, false);
    3817          251 :       bit_size = gfc_integer_kinds[ikind].bit_size;
    3818              : 
    3819          251 :       if (v == 1)
    3820              :         {
    3821              :           /* 1**something is always 1.  */
    3822           35 :           se->expr = build_int_cst (TREE_TYPE (lse.expr), 1);
    3823          239 :           return;
    3824              :         }
    3825          216 :       else if (v == -1)
    3826              :         {
    3827              :           /* (-1)**n is 1 - ((n & 1) << 1) */
    3828           34 :           tree type;
    3829           34 :           tree tmp;
    3830              : 
    3831           34 :           type = TREE_TYPE (lse.expr);
    3832           34 :           tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type,
    3833              :                                  rse.expr, build_int_cst (type, 1));
    3834           34 :           tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type,
    3835              :                                  tmp, build_int_cst (type, 1));
    3836           34 :           tmp = fold_build2_loc (input_location, MINUS_EXPR, type,
    3837              :                                  build_int_cst (type, 1), tmp);
    3838           34 :           se->expr = tmp;
    3839           34 :           return;
    3840              :         }
    3841          182 :       else if (w > 0 && ((w & (w-1)) == 0) && ((w >> (bit_size-1)) == 0))
    3842              :         {
    3843              :           /* Here v is +/- 2**e.  The further simplification uses
    3844              :              2**n = 1<<n, 4**n = 1<<(n+n), 8**n = 1 <<(3*n), 16**n =
    3845              :              1<<(4*n), etc., but we have to make sure to return zero
    3846              :              if the number of bits is too large. */
    3847          170 :           tree lshift;
    3848          170 :           tree type;
    3849          170 :           tree shift;
    3850          170 :           tree ge;
    3851          170 :           tree cond;
    3852          170 :           tree num_bits;
    3853          170 :           tree cond2;
    3854          170 :           tree tmp1;
    3855              : 
    3856          170 :           type = TREE_TYPE (lse.expr);
    3857              : 
    3858          170 :           if (w == 2)
    3859          110 :             shift = rse.expr;
    3860           60 :           else if (w == 4)
    3861           12 :             shift = fold_build2_loc (input_location, PLUS_EXPR,
    3862           12 :                                      TREE_TYPE (rse.expr),
    3863              :                                        rse.expr, rse.expr);
    3864              :           else
    3865              :             {
    3866              :               /* use popcount for fast log2(w) */
    3867           48 :               int e = wi::popcount (w-1);
    3868           96 :               shift = fold_build2_loc (input_location, MULT_EXPR,
    3869           48 :                                        TREE_TYPE (rse.expr),
    3870           48 :                                        build_int_cst (TREE_TYPE (rse.expr), e),
    3871              :                                        rse.expr);
    3872              :             }
    3873              : 
    3874          170 :           lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type,
    3875              :                                     build_int_cst (type, 1), shift);
    3876          170 :           ge = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
    3877              :                                 rse.expr, build_int_cst (type, 0));
    3878          170 :           cond = fold_build3_loc (input_location, COND_EXPR, type, ge, lshift,
    3879              :                                  build_int_cst (type, 0));
    3880          170 :           num_bits = build_int_cst (TREE_TYPE (rse.expr), TYPE_PRECISION (type));
    3881          170 :           cond2 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
    3882              :                                    rse.expr, num_bits);
    3883          170 :           tmp1 = fold_build3_loc (input_location, COND_EXPR, type, cond2,
    3884              :                                   build_int_cst (type, 0), cond);
    3885          170 :           if (v > 0)
    3886              :             {
    3887          128 :               se->expr = tmp1;
    3888              :             }
    3889              :           else
    3890              :             {
    3891              :               /* for v < 0, calculate v**n = |v|**n * (-1)**n */
    3892           42 :               tree tmp2;
    3893           42 :               tmp2 = fold_build2_loc (input_location, BIT_AND_EXPR, type,
    3894              :                                       rse.expr, build_int_cst (type, 1));
    3895           42 :               tmp2 = fold_build2_loc (input_location, LSHIFT_EXPR, type,
    3896              :                                       tmp2, build_int_cst (type, 1));
    3897           42 :               tmp2 = fold_build2_loc (input_location, MINUS_EXPR, type,
    3898              :                                       build_int_cst (type, 1), tmp2);
    3899           42 :               se->expr = fold_build2_loc (input_location, MULT_EXPR, type,
    3900              :                                           tmp1, tmp2);
    3901              :             }
    3902          170 :           return;
    3903              :         }
    3904              :     }
    3905              :   /* Handle unsigned separate from signed above, things would be too
    3906              :      complicated otherwise.  */
    3907              : 
    3908        32491 :   if (INTEGER_CST_P (lse.expr) && expr->value.op.op1->ts.type == BT_UNSIGNED)
    3909              :     {
    3910        15120 :       gfc_expr * op1 = expr->value.op.op1;
    3911        15120 :       tree type;
    3912              : 
    3913        15120 :       type = TREE_TYPE (lse.expr);
    3914              : 
    3915        15120 :       if (mpz_cmp_ui (op1->value.integer, 1) == 0)
    3916              :         {
    3917              :           /* 1**something is always 1.  */
    3918         1260 :           se->expr = build_int_cst (type, 1);
    3919         1260 :           return;
    3920              :         }
    3921              : 
    3922              :       /* Simplify 2u**x to a shift, with the value set to zero if it falls
    3923              :        outside the range.  */
    3924        26460 :       if (mpz_popcount (op1->value.integer) == 1)
    3925              :         {
    3926         2520 :           tree prec_m1, lim, shift, lshift, cond, tmp;
    3927         2520 :           tree rtype = TREE_TYPE (rse.expr);
    3928         2520 :           int e = mpz_scan1 (op1->value.integer, 0);
    3929              : 
    3930         2520 :           shift = fold_build2_loc (input_location, MULT_EXPR,
    3931         2520 :                                    rtype, build_int_cst (rtype, e),
    3932              :                                    rse.expr);
    3933         2520 :           lshift = fold_build2_loc (input_location, LSHIFT_EXPR, type,
    3934              :                                     build_int_cst (type, 1), shift);
    3935         5040 :           prec_m1 = fold_build2_loc (input_location, MINUS_EXPR, rtype,
    3936         2520 :                                      build_int_cst (rtype, TYPE_PRECISION (type)),
    3937              :                                      build_int_cst (rtype, 1));
    3938         2520 :           lim = fold_build2_loc (input_location, TRUNC_DIV_EXPR, rtype,
    3939         2520 :                                  prec_m1, build_int_cst (rtype, e));
    3940         2520 :           cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
    3941              :                                   rse.expr, lim);
    3942         2520 :           tmp = fold_build3_loc (input_location, COND_EXPR, type, cond,
    3943              :                                  build_int_cst (type, 0), lshift);
    3944         2520 :           se->expr = tmp;
    3945         2520 :           return;
    3946              :         }
    3947              :     }
    3948              : 
    3949        28711 :   gfc_int4_type_node = gfc_get_int_type (4);
    3950              : 
    3951              :   /* In case of integer operands with kinds 1 or 2, we call the integer kind 4
    3952              :      library routine.  But in the end, we have to convert the result back
    3953              :      if this case applies -- with res_ikind_K, we keep track whether operand K
    3954              :      falls into this case.  */
    3955        28711 :   res_ikind_1 = -1;
    3956        28711 :   res_ikind_2 = -1;
    3957              : 
    3958        28711 :   kind = expr->value.op.op1->ts.kind;
    3959        28711 :   switch (expr->value.op.op2->ts.type)
    3960              :     {
    3961         1023 :     case BT_INTEGER:
    3962         1023 :       ikind = expr->value.op.op2->ts.kind;
    3963         1023 :       switch (ikind)
    3964              :         {
    3965          144 :         case 1:
    3966          144 :         case 2:
    3967          144 :           rse.expr = convert (gfc_int4_type_node, rse.expr);
    3968          144 :           res_ikind_2 = ikind;
    3969              :           /* Fall through.  */
    3970              : 
    3971              :         case 4:
    3972              :           ikind = 0;
    3973              :           break;
    3974              : 
    3975              :         case 8:
    3976              :           ikind = 1;
    3977              :           break;
    3978              : 
    3979            6 :         case 16:
    3980            6 :           ikind = 2;
    3981            6 :           break;
    3982              : 
    3983            0 :         default:
    3984            0 :           gcc_unreachable ();
    3985              :         }
    3986         1023 :       switch (kind)
    3987              :         {
    3988            0 :         case 1:
    3989            0 :         case 2:
    3990            0 :           if (expr->value.op.op1->ts.type == BT_INTEGER)
    3991              :             {
    3992            0 :               lse.expr = convert (gfc_int4_type_node, lse.expr);
    3993            0 :               res_ikind_1 = kind;
    3994              :             }
    3995              :           else
    3996            0 :             gcc_unreachable ();
    3997              :           /* Fall through.  */
    3998              : 
    3999              :         case 4:
    4000              :           kind = 0;
    4001              :           break;
    4002              : 
    4003              :         case 8:
    4004              :           kind = 1;
    4005              :           break;
    4006              : 
    4007            6 :         case 10:
    4008            6 :           kind = 2;
    4009            6 :           break;
    4010              : 
    4011           18 :         case 16:
    4012           18 :           kind = 3;
    4013           18 :           break;
    4014              : 
    4015            0 :         default:
    4016            0 :           gcc_unreachable ();
    4017              :         }
    4018              : 
    4019         1023 :       switch (expr->value.op.op1->ts.type)
    4020              :         {
    4021          129 :         case BT_INTEGER:
    4022          129 :           if (kind == 3) /* Case 16 was not handled properly above.  */
    4023              :             kind = 2;
    4024          129 :           fndecl = gfor_fndecl_math_powi[kind][ikind].integer;
    4025          129 :           break;
    4026              : 
    4027          662 :         case BT_REAL:
    4028              :           /* Use builtins for real ** int4.  */
    4029          662 :           if (ikind == 0)
    4030              :             {
    4031          565 :               switch (kind)
    4032              :                 {
    4033          392 :                 case 0:
    4034          392 :                   fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
    4035          392 :                   break;
    4036              : 
    4037          155 :                 case 1:
    4038          155 :                   fndecl = builtin_decl_explicit (BUILT_IN_POWI);
    4039          155 :                   break;
    4040              : 
    4041            6 :                 case 2:
    4042            6 :                   fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
    4043            6 :                   break;
    4044              : 
    4045           12 :                 case 3:
    4046              :                   /* Use the __builtin_powil() only if real(kind=16) is
    4047              :                      actually the C long double type.  */
    4048           12 :                   if (!gfc_real16_is_float128)
    4049            0 :                     fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
    4050              :                   break;
    4051              : 
    4052              :                 default:
    4053              :                   gcc_unreachable ();
    4054              :                 }
    4055              :             }
    4056              : 
    4057              :           /* If we don't have a good builtin for this, go for the
    4058              :              library function.  */
    4059          553 :           if (!fndecl)
    4060          109 :             fndecl = gfor_fndecl_math_powi[kind][ikind].real;
    4061              :           break;
    4062              : 
    4063          232 :         case BT_COMPLEX:
    4064          232 :           fndecl = gfor_fndecl_math_powi[kind][ikind].cmplx;
    4065          232 :           break;
    4066              : 
    4067            0 :         default:
    4068            0 :           gcc_unreachable ();
    4069              :         }
    4070              :       break;
    4071              : 
    4072          139 :     case BT_REAL:
    4073          139 :       fndecl = gfc_builtin_decl_for_float_kind (BUILT_IN_POW, kind);
    4074          139 :       break;
    4075              : 
    4076          729 :     case BT_COMPLEX:
    4077          729 :       fndecl = gfc_builtin_decl_for_float_kind (BUILT_IN_CPOW, kind);
    4078          729 :       break;
    4079              : 
    4080        26820 :     case BT_UNSIGNED:
    4081        26820 :       {
    4082              :         /* Valid kinds for unsigned are 1, 2, 4, 8, 16.  Instead of using a
    4083              :            large switch statement, let's just use __builtin_ctz.  */
    4084        26820 :         int base = __builtin_ctz (expr->value.op.op1->ts.kind);
    4085        26820 :         int expon = __builtin_ctz (expr->value.op.op2->ts.kind);
    4086        26820 :         fndecl = gfor_fndecl_unsigned_pow_list[base][expon];
    4087              :       }
    4088        26820 :       break;
    4089              : 
    4090            0 :     default:
    4091            0 :       gcc_unreachable ();
    4092        28711 :       break;
    4093              :     }
    4094              : 
    4095        28711 :   se->expr = build_call_expr_loc (input_location,
    4096              :                               fndecl, 2, lse.expr, rse.expr);
    4097              : 
    4098              :   /* Convert the result back if it is of wrong integer kind.  */
    4099        28711 :   if (res_ikind_1 != -1 && res_ikind_2 != -1)
    4100              :     {
    4101              :       /* We want the maximum of both operand kinds as result.  */
    4102            0 :       if (res_ikind_1 < res_ikind_2)
    4103            0 :         res_ikind_1 = res_ikind_2;
    4104            0 :       se->expr = convert (gfc_get_int_type (res_ikind_1), se->expr);
    4105              :     }
    4106              : }
    4107              : 
    4108              : 
    4109              : /* Generate code to allocate a string temporary.  */
    4110              : 
    4111              : tree
    4112         4914 : gfc_conv_string_tmp (gfc_se * se, tree type, tree len)
    4113              : {
    4114         4914 :   tree var;
    4115         4914 :   tree tmp;
    4116              : 
    4117         4914 :   if (gfc_can_put_var_on_stack (len))
    4118              :     {
    4119              :       /* Create a temporary variable to hold the result.  */
    4120         4584 :       tmp = fold_build2_loc (input_location, MINUS_EXPR,
    4121         2292 :                              TREE_TYPE (len), len,
    4122         2292 :                              build_int_cst (TREE_TYPE (len), 1));
    4123         2292 :       tmp = build_range_type (gfc_charlen_type_node, size_zero_node, tmp);
    4124              : 
    4125         2292 :       if (TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
    4126         2262 :         tmp = build_array_type (TREE_TYPE (TREE_TYPE (type)), tmp);
    4127              :       else
    4128           30 :         tmp = build_array_type (TREE_TYPE (type), tmp);
    4129              : 
    4130         2292 :       var = gfc_create_var (tmp, "str");
    4131         2292 :       var = gfc_build_addr_expr (type, var);
    4132              :     }
    4133              :   else
    4134              :     {
    4135              :       /* Allocate a temporary to hold the result.  */
    4136         2622 :       var = gfc_create_var (type, "pstr");
    4137         2622 :       gcc_assert (POINTER_TYPE_P (type));
    4138         2622 :       tmp = TREE_TYPE (type);
    4139         2622 :       if (TREE_CODE (tmp) == ARRAY_TYPE)
    4140         2580 :         tmp = TREE_TYPE (tmp);
    4141         2622 :       tmp = TYPE_SIZE_UNIT (tmp);
    4142         2622 :       tmp = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
    4143              :                             fold_convert (size_type_node, len),
    4144              :                             fold_convert (size_type_node, tmp));
    4145         2622 :       tmp = gfc_call_malloc (&se->pre, type, tmp);
    4146         2622 :       gfc_add_modify (&se->pre, var, tmp);
    4147              : 
    4148              :       /* Free the temporary afterwards.  */
    4149         2622 :       tmp = gfc_call_free (var);
    4150         2622 :       gfc_add_expr_to_block (&se->post, tmp);
    4151              :     }
    4152              : 
    4153         4914 :   return var;
    4154              : }
    4155              : 
    4156              : 
    4157              : /* Handle a string concatenation operation.  A temporary will be allocated to
    4158              :    hold the result.  */
    4159              : 
    4160              : static void
    4161         1281 : gfc_conv_concat_op (gfc_se * se, gfc_expr * expr)
    4162              : {
    4163         1281 :   gfc_se lse, rse;
    4164         1281 :   tree len, type, var, tmp, fndecl;
    4165              : 
    4166         1281 :   gcc_assert (expr->value.op.op1->ts.type == BT_CHARACTER
    4167              :               && expr->value.op.op2->ts.type == BT_CHARACTER);
    4168         1281 :   gcc_assert (expr->value.op.op1->ts.kind == expr->value.op.op2->ts.kind);
    4169              : 
    4170         1281 :   gfc_init_se (&lse, se);
    4171         1281 :   gfc_conv_expr (&lse, expr->value.op.op1);
    4172         1281 :   gfc_conv_string_parameter (&lse);
    4173         1281 :   gfc_init_se (&rse, se);
    4174         1281 :   gfc_conv_expr (&rse, expr->value.op.op2);
    4175         1281 :   gfc_conv_string_parameter (&rse);
    4176              : 
    4177         1281 :   gfc_add_block_to_block (&se->pre, &lse.pre);
    4178         1281 :   gfc_add_block_to_block (&se->pre, &rse.pre);
    4179              : 
    4180         1281 :   type = gfc_get_character_type (expr->ts.kind, expr->ts.u.cl);
    4181         1281 :   len = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
    4182         1281 :   if (len == NULL_TREE)
    4183              :     {
    4184         1063 :       len = fold_build2_loc (input_location, PLUS_EXPR,
    4185              :                              gfc_charlen_type_node,
    4186              :                              fold_convert (gfc_charlen_type_node,
    4187              :                                            lse.string_length),
    4188              :                              fold_convert (gfc_charlen_type_node,
    4189              :                                            rse.string_length));
    4190              :     }
    4191              : 
    4192         1281 :   type = build_pointer_type (type);
    4193              : 
    4194         1281 :   var = gfc_conv_string_tmp (se, type, len);
    4195              : 
    4196              :   /* Do the actual concatenation.  */
    4197         1281 :   if (expr->ts.kind == 1)
    4198         1190 :     fndecl = gfor_fndecl_concat_string;
    4199           91 :   else if (expr->ts.kind == 4)
    4200           91 :     fndecl = gfor_fndecl_concat_string_char4;
    4201              :   else
    4202            0 :     gcc_unreachable ();
    4203              : 
    4204         1281 :   tmp = build_call_expr_loc (input_location,
    4205              :                          fndecl, 6, len, var, lse.string_length, lse.expr,
    4206              :                          rse.string_length, rse.expr);
    4207         1281 :   gfc_add_expr_to_block (&se->pre, tmp);
    4208              : 
    4209              :   /* Add the cleanup for the operands.  */
    4210         1281 :   gfc_add_block_to_block (&se->pre, &rse.post);
    4211         1281 :   gfc_add_block_to_block (&se->pre, &lse.post);
    4212              : 
    4213         1281 :   se->expr = var;
    4214         1281 :   se->string_length = len;
    4215         1281 : }
    4216              : 
    4217              : /* Translates an op expression. Common (binary) cases are handled by this
    4218              :    function, others are passed on. Recursion is used in either case.
    4219              :    We use the fact that (op1.ts == op2.ts) (except for the power
    4220              :    operator **).
    4221              :    Operators need no special handling for scalarized expressions as long as
    4222              :    they call gfc_conv_simple_val to get their operands.
    4223              :    Character strings get special handling.  */
    4224              : 
    4225              : static void
    4226       502478 : gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)
    4227              : {
    4228       502478 :   enum tree_code code;
    4229       502478 :   gfc_se lse;
    4230       502478 :   gfc_se rse;
    4231       502478 :   tree tmp, type;
    4232       502478 :   int lop;
    4233       502478 :   int checkstring;
    4234              : 
    4235       502478 :   checkstring = 0;
    4236       502478 :   lop = 0;
    4237       502478 :   switch (expr->value.op.op)
    4238              :     {
    4239        15409 :     case INTRINSIC_PARENTHESES:
    4240        15409 :       if ((expr->ts.type == BT_REAL || expr->ts.type == BT_COMPLEX)
    4241         3800 :           && flag_protect_parens)
    4242              :         {
    4243         3667 :           gfc_conv_unary_op (PAREN_EXPR, se, expr);
    4244         3667 :           gcc_assert (FLOAT_TYPE_P (TREE_TYPE (se->expr)));
    4245        90892 :           return;
    4246              :         }
    4247              : 
    4248              :       /* Fallthrough.  */
    4249        11748 :     case INTRINSIC_UPLUS:
    4250        11748 :       gfc_conv_expr (se, expr->value.op.op1);
    4251        11748 :       return;
    4252              : 
    4253         4933 :     case INTRINSIC_UMINUS:
    4254         4933 :       gfc_conv_unary_op (NEGATE_EXPR, se, expr);
    4255         4933 :       return;
    4256              : 
    4257        20134 :     case INTRINSIC_NOT:
    4258        20134 :       gfc_conv_unary_op (TRUTH_NOT_EXPR, se, expr);
    4259        20134 :       return;
    4260              : 
    4261              :     case INTRINSIC_PLUS:
    4262              :       code = PLUS_EXPR;
    4263              :       break;
    4264              : 
    4265        28532 :     case INTRINSIC_MINUS:
    4266        28532 :       code = MINUS_EXPR;
    4267        28532 :       break;
    4268              : 
    4269        32028 :     case INTRINSIC_TIMES:
    4270        32028 :       code = MULT_EXPR;
    4271        32028 :       break;
    4272              : 
    4273         6771 :     case INTRINSIC_DIVIDE:
    4274              :       /* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is
    4275              :          an integer or unsigned, we must round towards zero, so we use a
    4276              :          TRUNC_DIV_EXPR.  */
    4277         6771 :       if (expr->ts.type == BT_INTEGER || expr->ts.type == BT_UNSIGNED)
    4278              :         code = TRUNC_DIV_EXPR;
    4279              :       else
    4280       411586 :         code = RDIV_EXPR;
    4281              :       break;
    4282              : 
    4283        49129 :     case INTRINSIC_POWER:
    4284        49129 :       gfc_conv_power_op (se, expr);
    4285        49129 :       return;
    4286              : 
    4287         1281 :     case INTRINSIC_CONCAT:
    4288         1281 :       gfc_conv_concat_op (se, expr);
    4289         1281 :       return;
    4290              : 
    4291         4786 :     case INTRINSIC_AND:
    4292         4786 :       code = flag_frontend_optimize ? TRUTH_ANDIF_EXPR : TRUTH_AND_EXPR;
    4293              :       lop = 1;
    4294              :       break;
    4295              : 
    4296        55828 :     case INTRINSIC_OR:
    4297        55828 :       code = flag_frontend_optimize ? TRUTH_ORIF_EXPR : TRUTH_OR_EXPR;
    4298              :       lop = 1;
    4299              :       break;
    4300              : 
    4301              :       /* EQV and NEQV only work on logicals, but since we represent them
    4302              :          as integers, we can use EQ_EXPR and NE_EXPR for them in GIMPLE.  */
    4303        12608 :     case INTRINSIC_EQ:
    4304        12608 :     case INTRINSIC_EQ_OS:
    4305        12608 :     case INTRINSIC_EQV:
    4306        12608 :       code = EQ_EXPR;
    4307        12608 :       checkstring = 1;
    4308        12608 :       lop = 1;
    4309        12608 :       break;
    4310              : 
    4311       204878 :     case INTRINSIC_NE:
    4312       204878 :     case INTRINSIC_NE_OS:
    4313       204878 :     case INTRINSIC_NEQV:
    4314       204878 :       code = NE_EXPR;
    4315       204878 :       checkstring = 1;
    4316       204878 :       lop = 1;
    4317       204878 :       break;
    4318              : 
    4319        11877 :     case INTRINSIC_GT:
    4320        11877 :     case INTRINSIC_GT_OS:
    4321        11877 :       code = GT_EXPR;
    4322        11877 :       checkstring = 1;
    4323        11877 :       lop = 1;
    4324        11877 :       break;
    4325              : 
    4326         1661 :     case INTRINSIC_GE:
    4327         1661 :     case INTRINSIC_GE_OS:
    4328         1661 :       code = GE_EXPR;
    4329         1661 :       checkstring = 1;
    4330         1661 :       lop = 1;
    4331         1661 :       break;
    4332              : 
    4333         4331 :     case INTRINSIC_LT:
    4334         4331 :     case INTRINSIC_LT_OS:
    4335         4331 :       code = LT_EXPR;
    4336         4331 :       checkstring = 1;
    4337         4331 :       lop = 1;
    4338         4331 :       break;
    4339              : 
    4340         2590 :     case INTRINSIC_LE:
    4341         2590 :     case INTRINSIC_LE_OS:
    4342         2590 :       code = LE_EXPR;
    4343         2590 :       checkstring = 1;
    4344         2590 :       lop = 1;
    4345         2590 :       break;
    4346              : 
    4347            0 :     case INTRINSIC_USER:
    4348            0 :     case INTRINSIC_ASSIGN:
    4349              :       /* These should be converted into function calls by the frontend.  */
    4350            0 :       gcc_unreachable ();
    4351              : 
    4352            0 :     default:
    4353            0 :       fatal_error (input_location, "Unknown intrinsic op");
    4354       411586 :       return;
    4355              :     }
    4356              : 
    4357              :   /* The only exception to this is **, which is handled separately anyway.  */
    4358       411586 :   gcc_assert (expr->value.op.op1->ts.type == expr->value.op.op2->ts.type);
    4359              : 
    4360       411586 :   if (checkstring && expr->value.op.op1->ts.type != BT_CHARACTER)
    4361       378376 :     checkstring = 0;
    4362              : 
    4363              :   /* lhs */
    4364       411586 :   gfc_init_se (&lse, se);
    4365       411586 :   gfc_conv_expr (&lse, expr->value.op.op1);
    4366       411586 :   gfc_add_block_to_block (&se->pre, &lse.pre);
    4367              : 
    4368              :   /* rhs */
    4369       411586 :   gfc_init_se (&rse, se);
    4370       411586 :   gfc_conv_expr (&rse, expr->value.op.op2);
    4371       411586 :   gfc_add_block_to_block (&se->pre, &rse.pre);
    4372              : 
    4373       411586 :   if (checkstring)
    4374              :     {
    4375        33210 :       gfc_conv_string_parameter (&lse);
    4376        33210 :       gfc_conv_string_parameter (&rse);
    4377              : 
    4378        66420 :       lse.expr = gfc_build_compare_string (lse.string_length, lse.expr,
    4379              :                                            rse.string_length, rse.expr,
    4380        33210 :                                            expr->value.op.op1->ts.kind,
    4381              :                                            code);
    4382        33210 :       rse.expr = build_int_cst (TREE_TYPE (lse.expr), 0);
    4383        33210 :       gfc_add_block_to_block (&lse.post, &rse.post);
    4384              :     }
    4385              : 
    4386       411586 :   type = gfc_typenode_for_spec (&expr->ts);
    4387              : 
    4388       411586 :   if (lop)
    4389              :     {
    4390              :       // Inhibit overeager optimization of Cray pointer comparisons (PR106692).
    4391       298559 :       if (expr->value.op.op1->expr_type == EXPR_VARIABLE
    4392       168268 :           && expr->value.op.op1->ts.type == BT_INTEGER
    4393        72501 :           && expr->value.op.op1->symtree
    4394        72501 :           && expr->value.op.op1->symtree->n.sym->attr.cray_pointer)
    4395           12 :         TREE_THIS_VOLATILE (lse.expr) = 1;
    4396              : 
    4397       298559 :       if (expr->value.op.op2->expr_type == EXPR_VARIABLE
    4398        71984 :           && expr->value.op.op2->ts.type == BT_INTEGER
    4399        12755 :           && expr->value.op.op2->symtree
    4400        12755 :           && expr->value.op.op2->symtree->n.sym->attr.cray_pointer)
    4401           12 :         TREE_THIS_VOLATILE (rse.expr) = 1;
    4402              : 
    4403              :       /* The result of logical ops is always logical_type_node.  */
    4404       298559 :       tmp = fold_build2_loc (input_location, code, logical_type_node,
    4405              :                              lse.expr, rse.expr);
    4406       298559 :       se->expr = convert (type, tmp);
    4407              :     }
    4408              :   else
    4409       113027 :     se->expr = fold_build2_loc (input_location, code, type, lse.expr, rse.expr);
    4410              : 
    4411              :   /* Add the post blocks.  */
    4412       411586 :   gfc_add_block_to_block (&se->post, &rse.post);
    4413       411586 :   gfc_add_block_to_block (&se->post, &lse.post);
    4414              : }
    4415              : 
    4416              : static void
    4417          139 : gfc_conv_conditional_expr (gfc_se *se, gfc_expr *expr)
    4418              : {
    4419          139 :   gfc_se cond_se, true_se, false_se;
    4420          139 :   tree condition, true_val, false_val;
    4421          139 :   tree type;
    4422              : 
    4423          139 :   gfc_init_se (&cond_se, se);
    4424          139 :   gfc_init_se (&true_se, se);
    4425          139 :   gfc_init_se (&false_se, se);
    4426              : 
    4427          139 :   gfc_conv_expr (&cond_se, expr->value.conditional.condition);
    4428          139 :   gfc_add_block_to_block (&se->pre, &cond_se.pre);
    4429          139 :   condition = gfc_evaluate_now (cond_se.expr, &se->pre);
    4430              : 
    4431          139 :   true_se.want_pointer = se->want_pointer;
    4432          139 :   gfc_conv_expr (&true_se, expr->value.conditional.true_expr);
    4433          139 :   true_val = true_se.expr;
    4434          139 :   false_se.want_pointer = se->want_pointer;
    4435          139 :   gfc_conv_expr (&false_se, expr->value.conditional.false_expr);
    4436          139 :   false_val = false_se.expr;
    4437              : 
    4438          139 :   if (true_se.pre.head != NULL_TREE || false_se.pre.head != NULL_TREE)
    4439           24 :     gfc_add_expr_to_block (
    4440              :       &se->pre,
    4441              :       fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,
    4442           24 :                        true_se.pre.head != NULL_TREE
    4443            6 :                          ? gfc_finish_block (&true_se.pre)
    4444           18 :                          : build_empty_stmt (input_location),
    4445           24 :                        false_se.pre.head != NULL_TREE
    4446           24 :                          ? gfc_finish_block (&false_se.pre)
    4447            0 :                          : build_empty_stmt (input_location)));
    4448              : 
    4449          139 :   if (true_se.post.head != NULL_TREE || false_se.post.head != NULL_TREE)
    4450            6 :     gfc_add_expr_to_block (
    4451              :       &se->post,
    4452              :       fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,
    4453            6 :                        true_se.post.head != NULL_TREE
    4454            0 :                          ? gfc_finish_block (&true_se.post)
    4455            6 :                          : build_empty_stmt (input_location),
    4456            6 :                        false_se.post.head != NULL_TREE
    4457            6 :                          ? gfc_finish_block (&false_se.post)
    4458            0 :                          : build_empty_stmt (input_location)));
    4459              : 
    4460          139 :   type = gfc_typenode_for_spec (&expr->ts);
    4461          139 :   if (se->want_pointer)
    4462           18 :     type = build_pointer_type (type);
    4463              : 
    4464          139 :   se->expr = fold_build3_loc (input_location, COND_EXPR, type, condition,
    4465              :                               true_val, false_val);
    4466          139 :   if (expr->ts.type == BT_CHARACTER)
    4467           54 :     se->string_length
    4468           54 :       = fold_build3_loc (input_location, COND_EXPR, gfc_charlen_type_node,
    4469              :                          condition, true_se.string_length,
    4470              :                          false_se.string_length);
    4471          139 : }
    4472              : 
    4473              : /* If a string's length is one, we convert it to a single character.  */
    4474              : 
    4475              : tree
    4476       137990 : gfc_string_to_single_character (tree len, tree str, int kind)
    4477              : {
    4478              : 
    4479       137990 :   if (len == NULL
    4480       137990 :       || !tree_fits_uhwi_p (len)
    4481       253382 :       || !POINTER_TYPE_P (TREE_TYPE (str)))
    4482              :     return NULL_TREE;
    4483              : 
    4484       115340 :   if (TREE_INT_CST_LOW (len) == 1)
    4485              :     {
    4486        22201 :       str = fold_convert (gfc_get_pchar_type (kind), str);
    4487        22201 :       return build_fold_indirect_ref_loc (input_location, str);
    4488              :     }
    4489              : 
    4490        93139 :   if (kind == 1
    4491        75769 :       && TREE_CODE (str) == ADDR_EXPR
    4492        65130 :       && TREE_CODE (TREE_OPERAND (str, 0)) == ARRAY_REF
    4493        46861 :       && TREE_CODE (TREE_OPERAND (TREE_OPERAND (str, 0), 0)) == STRING_CST
    4494        28481 :       && array_ref_low_bound (TREE_OPERAND (str, 0))
    4495        28481 :          == TREE_OPERAND (TREE_OPERAND (str, 0), 1)
    4496        28481 :       && TREE_INT_CST_LOW (len) > 1
    4497       119864 :       && TREE_INT_CST_LOW (len)
    4498              :          == (unsigned HOST_WIDE_INT)
    4499        26725 :             TREE_STRING_LENGTH (TREE_OPERAND (TREE_OPERAND (str, 0), 0)))
    4500              :     {
    4501        26725 :       tree ret = fold_convert (gfc_get_pchar_type (kind), str);
    4502        26725 :       ret = build_fold_indirect_ref_loc (input_location, ret);
    4503        26725 :       if (TREE_CODE (ret) == INTEGER_CST)
    4504              :         {
    4505        26725 :           tree string_cst = TREE_OPERAND (TREE_OPERAND (str, 0), 0);
    4506        26725 :           int i, length = TREE_STRING_LENGTH (string_cst);
    4507        26725 :           const char *ptr = TREE_STRING_POINTER (string_cst);
    4508              : 
    4509        39878 :           for (i = 1; i < length; i++)
    4510        39205 :             if (ptr[i] != ' ')
    4511              :               return NULL_TREE;
    4512              : 
    4513              :           return ret;
    4514              :         }
    4515              :     }
    4516              : 
    4517              :   return NULL_TREE;
    4518              : }
    4519              : 
    4520              : 
    4521              : static void
    4522          172 : conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr)
    4523              : {
    4524          172 :   gcc_assert (expr);
    4525              : 
    4526              :   /* We used to modify the tree here. Now it is done earlier in
    4527              :      the front-end, so we only check it here to avoid regressions.  */
    4528          172 :   if (sym->backend_decl)
    4529              :     {
    4530           67 :       gcc_assert (TREE_CODE (TREE_TYPE (sym->backend_decl)) == INTEGER_TYPE);
    4531           67 :       gcc_assert (TYPE_UNSIGNED (TREE_TYPE (sym->backend_decl)) == 1);
    4532           67 :       gcc_assert (TYPE_PRECISION (TREE_TYPE (sym->backend_decl)) == CHAR_TYPE_SIZE);
    4533           67 :       gcc_assert (DECL_BY_REFERENCE (sym->backend_decl) == 0);
    4534              :     }
    4535              : 
    4536              :   /* If we have a constant character expression, make it into an
    4537              :       integer of type C char.  */
    4538          172 :   if ((*expr)->expr_type == EXPR_CONSTANT)
    4539              :     {
    4540          166 :       gfc_typespec ts;
    4541          166 :       gfc_clear_ts (&ts);
    4542              : 
    4543          332 :       gfc_expr *tmp = gfc_get_int_expr (gfc_default_character_kind, NULL,
    4544          166 :                                         (*expr)->value.character.string[0]);
    4545          166 :       gfc_replace_expr (*expr, tmp);
    4546              :     }
    4547            6 :   else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE)
    4548              :     {
    4549            6 :       if ((*expr)->ref == NULL)
    4550              :         {
    4551            6 :           se->expr = gfc_string_to_single_character
    4552            6 :             (integer_one_node,
    4553            6 :               gfc_build_addr_expr (gfc_get_pchar_type ((*expr)->ts.kind),
    4554              :                                   gfc_get_symbol_decl
    4555            6 :                                   ((*expr)->symtree->n.sym)),
    4556              :               (*expr)->ts.kind);
    4557              :         }
    4558              :       else
    4559              :         {
    4560            0 :           gfc_conv_variable (se, *expr);
    4561            0 :           se->expr = gfc_string_to_single_character
    4562            0 :             (integer_one_node,
    4563              :               gfc_build_addr_expr (gfc_get_pchar_type ((*expr)->ts.kind),
    4564              :                                   se->expr),
    4565            0 :               (*expr)->ts.kind);
    4566              :         }
    4567              :     }
    4568          172 : }
    4569              : 
    4570              : /* Helper function for gfc_build_compare_string.  Return LEN_TRIM value
    4571              :    if STR is a string literal, otherwise return -1.  */
    4572              : 
    4573              : static int
    4574        31438 : gfc_optimize_len_trim (tree len, tree str, int kind)
    4575              : {
    4576        31438 :   if (kind == 1
    4577        26396 :       && TREE_CODE (str) == ADDR_EXPR
    4578        23067 :       && TREE_CODE (TREE_OPERAND (str, 0)) == ARRAY_REF
    4579        14811 :       && TREE_CODE (TREE_OPERAND (TREE_OPERAND (str, 0), 0)) == STRING_CST
    4580         9389 :       && array_ref_low_bound (TREE_OPERAND (str, 0))
    4581         9389 :          == TREE_OPERAND (TREE_OPERAND (str, 0), 1)
    4582         9389 :       && tree_fits_uhwi_p (len)
    4583         9389 :       && tree_to_uhwi (len) >= 1
    4584        31438 :       && tree_to_uhwi (len)
    4585         9345 :          == (unsigned HOST_WIDE_INT)
    4586         9345 :             TREE_STRING_LENGTH (TREE_OPERAND (TREE_OPERAND (str, 0), 0)))
    4587              :     {
    4588         9345 :       tree folded = fold_convert (gfc_get_pchar_type (kind), str);
    4589         9345 :       folded = build_fold_indirect_ref_loc (input_location, folded);
    4590         9345 :       if (TREE_CODE (folded) == INTEGER_CST)
    4591              :         {
    4592         9345 :           tree string_cst = TREE_OPERAND (TREE_OPERAND (str, 0), 0);
    4593         9345 :           int length = TREE_STRING_LENGTH (string_cst);
    4594         9345 :           const char *ptr = TREE_STRING_POINTER (string_cst);
    4595              : 
    4596        14254 :           for (; length > 0; length--)
    4597        14254 :             if (ptr[length - 1] != ' ')
    4598              :               break;
    4599              : 
    4600              :           return length;
    4601              :         }
    4602              :     }
    4603              :   return -1;
    4604              : }
    4605              : 
    4606              : /* Helper to build a call to memcmp.  */
    4607              : 
    4608              : static tree
    4609        12703 : build_memcmp_call (tree s1, tree s2, tree n)
    4610              : {
    4611        12703 :   tree tmp;
    4612              : 
    4613        12703 :   if (!POINTER_TYPE_P (TREE_TYPE (s1)))
    4614            0 :     s1 = gfc_build_addr_expr (pvoid_type_node, s1);
    4615              :   else
    4616        12703 :     s1 = fold_convert (pvoid_type_node, s1);
    4617              : 
    4618        12703 :   if (!POINTER_TYPE_P (TREE_TYPE (s2)))
    4619            0 :     s2 = gfc_build_addr_expr (pvoid_type_node, s2);
    4620              :   else
    4621        12703 :     s2 = fold_convert (pvoid_type_node, s2);
    4622              : 
    4623        12703 :   n = fold_convert (size_type_node, n);
    4624              : 
    4625        12703 :   tmp = build_call_expr_loc (input_location,
    4626              :                              builtin_decl_explicit (BUILT_IN_MEMCMP),
    4627              :                              3, s1, s2, n);
    4628              : 
    4629        12703 :   return fold_convert (integer_type_node, tmp);
    4630              : }
    4631              : 
    4632              : /* Compare two strings. If they are all single characters, the result is the
    4633              :    subtraction of them. Otherwise, we build a library call.  */
    4634              : 
    4635              : tree
    4636        33309 : gfc_build_compare_string (tree len1, tree str1, tree len2, tree str2, int kind,
    4637              :                           enum tree_code code)
    4638              : {
    4639        33309 :   tree sc1;
    4640        33309 :   tree sc2;
    4641        33309 :   tree fndecl;
    4642              : 
    4643        33309 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (str1)));
    4644        33309 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (str2)));
    4645              : 
    4646        33309 :   sc1 = gfc_string_to_single_character (len1, str1, kind);
    4647        33309 :   sc2 = gfc_string_to_single_character (len2, str2, kind);
    4648              : 
    4649        33309 :   if (sc1 != NULL_TREE && sc2 != NULL_TREE)
    4650              :     {
    4651              :       /* Deal with single character specially.  */
    4652         4755 :       sc1 = fold_convert (integer_type_node, sc1);
    4653         4755 :       sc2 = fold_convert (integer_type_node, sc2);
    4654         4755 :       return fold_build2_loc (input_location, MINUS_EXPR, integer_type_node,
    4655         4755 :                               sc1, sc2);
    4656              :     }
    4657              : 
    4658        28554 :   if ((code == EQ_EXPR || code == NE_EXPR)
    4659        27992 :       && optimize
    4660        23578 :       && INTEGER_CST_P (len1) && INTEGER_CST_P (len2))
    4661              :     {
    4662              :       /* If one string is a string literal with LEN_TRIM longer
    4663              :          than the length of the second string, the strings
    4664              :          compare unequal.  */
    4665        15719 :       int len = gfc_optimize_len_trim (len1, str1, kind);
    4666        15719 :       if (len > 0 && compare_tree_int (len2, len) < 0)
    4667            0 :         return integer_one_node;
    4668        15719 :       len = gfc_optimize_len_trim (len2, str2, kind);
    4669        15719 :       if (len > 0 && compare_tree_int (len1, len) < 0)
    4670            0 :         return integer_one_node;
    4671              :     }
    4672              : 
    4673              :   /* We can compare via memcpy if the strings are known to be equal
    4674              :      in length and they are
    4675              :      - kind=1
    4676              :      - kind=4 and the comparison is for (in)equality.  */
    4677              : 
    4678        19019 :   if (INTEGER_CST_P (len1) && INTEGER_CST_P (len2)
    4679        18681 :       && tree_int_cst_equal (len1, len2)
    4680        41317 :       && (kind == 1 || code == EQ_EXPR || code == NE_EXPR))
    4681              :     {
    4682        12703 :       tree tmp;
    4683        12703 :       tree chartype;
    4684              : 
    4685        12703 :       chartype = gfc_get_char_type (kind);
    4686        12703 :       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE(len1),
    4687        12703 :                              fold_convert (TREE_TYPE(len1),
    4688              :                                            TYPE_SIZE_UNIT(chartype)),
    4689              :                              len1);
    4690        12703 :       return build_memcmp_call (str1, str2, tmp);
    4691              :     }
    4692              : 
    4693              :   /* Build a call for the comparison.  */
    4694        15851 :   if (kind == 1)
    4695        13008 :     fndecl = gfor_fndecl_compare_string;
    4696         2843 :   else if (kind == 4)
    4697         2843 :     fndecl = gfor_fndecl_compare_string_char4;
    4698              :   else
    4699            0 :     gcc_unreachable ();
    4700              : 
    4701        15851 :   return build_call_expr_loc (input_location, fndecl, 4,
    4702        15851 :                               len1, str1, len2, str2);
    4703              : }
    4704              : 
    4705              : 
    4706              : /* Return the backend_decl for a procedure pointer component.  */
    4707              : 
    4708              : static tree
    4709         1894 : get_proc_ptr_comp (gfc_expr *e)
    4710              : {
    4711         1894 :   gfc_se comp_se;
    4712         1894 :   gfc_expr *e2;
    4713         1894 :   expr_t old_type;
    4714              : 
    4715         1894 :   gfc_init_se (&comp_se, NULL);
    4716         1894 :   e2 = gfc_copy_expr (e);
    4717              :   /* We have to restore the expr type later so that gfc_free_expr frees
    4718              :      the exact same thing that was allocated.
    4719              :      TODO: This is ugly.  */
    4720         1894 :   old_type = e2->expr_type;
    4721         1894 :   e2->expr_type = EXPR_VARIABLE;
    4722         1894 :   gfc_conv_expr (&comp_se, e2);
    4723         1894 :   e2->expr_type = old_type;
    4724         1894 :   gfc_free_expr (e2);
    4725         1894 :   return build_fold_addr_expr_loc (input_location, comp_se.expr);
    4726              : }
    4727              : 
    4728              : 
    4729              : /* Convert a typebound function reference from a class object.  */
    4730              : static void
    4731           80 : conv_base_obj_fcn_val (gfc_se * se, tree base_object, gfc_expr * expr)
    4732              : {
    4733           80 :   gfc_ref *ref;
    4734           80 :   tree var;
    4735              : 
    4736           80 :   if (!VAR_P (base_object))
    4737              :     {
    4738            0 :       var = gfc_create_var (TREE_TYPE (base_object), NULL);
    4739            0 :       gfc_add_modify (&se->pre, var, base_object);
    4740              :     }
    4741           80 :   se->expr = gfc_class_vptr_get (base_object);
    4742           80 :   se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
    4743           80 :   ref = expr->ref;
    4744          308 :   while (ref && ref->next)
    4745              :     ref = ref->next;
    4746           80 :   gcc_assert (ref && ref->type == REF_COMPONENT);
    4747           80 :   if (ref->u.c.sym->attr.extension)
    4748            0 :     conv_parent_component_references (se, ref);
    4749           80 :   gfc_conv_component_ref (se, ref);
    4750           80 :   se->expr = build_fold_addr_expr_loc (input_location, se->expr);
    4751           80 : }
    4752              : 
    4753              : static tree
    4754       126339 : get_builtin_fn (gfc_symbol * sym)
    4755              : {
    4756       126339 :   if (!gfc_option.disable_omp_is_initial_device
    4757       126335 :       && flag_openmp && sym->attr.function && sym->ts.type == BT_LOGICAL
    4758          613 :       && !strcmp (sym->name, "omp_is_initial_device"))
    4759           23 :     return builtin_decl_explicit (BUILT_IN_OMP_IS_INITIAL_DEVICE);
    4760              : 
    4761       126316 :   if (!gfc_option.disable_omp_get_initial_device
    4762       126309 :       && flag_openmp && sym->attr.function && sym->ts.type == BT_INTEGER
    4763         4118 :       && !strcmp (sym->name, "omp_get_initial_device"))
    4764           29 :     return builtin_decl_explicit (BUILT_IN_OMP_GET_INITIAL_DEVICE);
    4765              : 
    4766       126287 :   if (!gfc_option.disable_omp_get_num_devices
    4767       126280 :       && flag_openmp && sym->attr.function && sym->ts.type == BT_INTEGER
    4768         4089 :       && !strcmp (sym->name, "omp_get_num_devices"))
    4769           80 :     return builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_DEVICES);
    4770              : 
    4771       126207 :   if (!gfc_option.disable_acc_on_device
    4772       126027 :       && flag_openacc && sym->attr.function && sym->ts.type == BT_LOGICAL
    4773         1163 :       && !strcmp (sym->name, "acc_on_device_h"))
    4774          390 :     return builtin_decl_explicit (BUILT_IN_ACC_ON_DEVICE);
    4775              : 
    4776              :   return NULL_TREE;
    4777              : }
    4778              : 
    4779              : static tree
    4780          522 : update_builtin_function (tree fn_call, gfc_symbol *sym)
    4781              : {
    4782          522 :   tree fn = TREE_OPERAND (CALL_EXPR_FN (fn_call), 0);
    4783              : 
    4784          522 :   if (DECL_FUNCTION_CODE (fn) == BUILT_IN_OMP_IS_INITIAL_DEVICE)
    4785              :      /* In Fortran omp_is_initial_device returns logical(4)
    4786              :         but the builtin uses 'int'.  */
    4787           23 :     return fold_convert (TREE_TYPE (TREE_TYPE (sym->backend_decl)), fn_call);
    4788              : 
    4789          499 :   else if (DECL_FUNCTION_CODE (fn) == BUILT_IN_ACC_ON_DEVICE)
    4790              :     {
    4791              :       /* Likewise for the return type; additionally, the argument it a
    4792              :          call-by-value int, Fortran has a by-reference 'integer(4)'.  */
    4793          390 :       tree arg = build_fold_indirect_ref_loc (input_location,
    4794          390 :                                               CALL_EXPR_ARG (fn_call, 0));
    4795          390 :       CALL_EXPR_ARG (fn_call, 0) = fold_convert (integer_type_node, arg);
    4796          390 :       return fold_convert (TREE_TYPE (TREE_TYPE (sym->backend_decl)), fn_call);
    4797              :     }
    4798              :   return fn_call;
    4799              : }
    4800              : 
    4801              : static void
    4802       129037 : conv_function_val (gfc_se * se, bool *is_builtin, gfc_symbol * sym,
    4803              :                    gfc_expr * expr, gfc_actual_arglist *actual_args)
    4804              : {
    4805       129037 :   tree tmp;
    4806              : 
    4807       129037 :   if (gfc_is_proc_ptr_comp (expr))
    4808         1894 :     tmp = get_proc_ptr_comp (expr);
    4809       127143 :   else if (sym->attr.dummy)
    4810              :     {
    4811          804 :       tmp = gfc_get_symbol_decl (sym);
    4812          804 :       if (sym->attr.proc_pointer)
    4813           83 :         tmp = build_fold_indirect_ref_loc (input_location,
    4814              :                                        tmp);
    4815          804 :       gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
    4816              :               && TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) == FUNCTION_TYPE);
    4817              :     }
    4818              :   else
    4819              :     {
    4820       126339 :       if (!sym->backend_decl)
    4821        31569 :         sym->backend_decl = gfc_get_extern_function_decl (sym, actual_args);
    4822              : 
    4823       126339 :       if ((tmp = get_builtin_fn (sym)) != NULL_TREE)
    4824          522 :         *is_builtin = true;
    4825              :       else
    4826              :         {
    4827       125817 :           TREE_USED (sym->backend_decl) = 1;
    4828       125817 :           tmp = sym->backend_decl;
    4829              :         }
    4830              : 
    4831       126339 :       if (sym->attr.cray_pointee)
    4832              :         {
    4833              :           /* TODO - make the cray pointee a pointer to a procedure,
    4834              :              assign the pointer to it and use it for the call.  This
    4835              :              will do for now!  */
    4836           19 :           tmp = convert (build_pointer_type (TREE_TYPE (tmp)),
    4837           19 :                          gfc_get_symbol_decl (sym->cp_pointer));
    4838           19 :           tmp = gfc_evaluate_now (tmp, &se->pre);
    4839              :         }
    4840              : 
    4841       126339 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
    4842              :         {
    4843       125759 :           gcc_assert (TREE_CODE (tmp) == FUNCTION_DECL);
    4844       125759 :           tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    4845              :         }
    4846              :     }
    4847       129037 :   se->expr = tmp;
    4848       129037 : }
    4849              : 
    4850              : 
    4851              : /* Initialize MAPPING.  */
    4852              : 
    4853              : void
    4854       129154 : gfc_init_interface_mapping (gfc_interface_mapping * mapping)
    4855              : {
    4856       129154 :   mapping->syms = NULL;
    4857       129154 :   mapping->charlens = NULL;
    4858       129154 : }
    4859              : 
    4860              : 
    4861              : /* Free all memory held by MAPPING (but not MAPPING itself).  */
    4862              : 
    4863              : void
    4864       129154 : gfc_free_interface_mapping (gfc_interface_mapping * mapping)
    4865              : {
    4866       129154 :   gfc_interface_sym_mapping *sym;
    4867       129154 :   gfc_interface_sym_mapping *nextsym;
    4868       129154 :   gfc_charlen *cl;
    4869       129154 :   gfc_charlen *nextcl;
    4870              : 
    4871       169376 :   for (sym = mapping->syms; sym; sym = nextsym)
    4872              :     {
    4873        40222 :       nextsym = sym->next;
    4874        40222 :       sym->new_sym->n.sym->formal = NULL;
    4875        40222 :       gfc_free_symbol (sym->new_sym->n.sym);
    4876        40222 :       gfc_free_expr (sym->expr);
    4877        40222 :       free (sym->new_sym);
    4878        40222 :       free (sym);
    4879              :     }
    4880       133723 :   for (cl = mapping->charlens; cl; cl = nextcl)
    4881              :     {
    4882         4569 :       nextcl = cl->next;
    4883         4569 :       gfc_free_expr (cl->length);
    4884         4569 :       free (cl);
    4885              :     }
    4886       129154 : }
    4887              : 
    4888              : 
    4889              : /* Return a copy of gfc_charlen CL.  Add the returned structure to
    4890              :    MAPPING so that it will be freed by gfc_free_interface_mapping.  */
    4891              : 
    4892              : static gfc_charlen *
    4893         4569 : gfc_get_interface_mapping_charlen (gfc_interface_mapping * mapping,
    4894              :                                    gfc_charlen * cl)
    4895              : {
    4896         4569 :   gfc_charlen *new_charlen;
    4897              : 
    4898         4569 :   new_charlen = gfc_get_charlen ();
    4899         4569 :   new_charlen->next = mapping->charlens;
    4900         4569 :   new_charlen->length = gfc_copy_expr (cl->length);
    4901              : 
    4902         4569 :   mapping->charlens = new_charlen;
    4903         4569 :   return new_charlen;
    4904              : }
    4905              : 
    4906              : 
    4907              : /* A subroutine of gfc_add_interface_mapping.  Return a descriptorless
    4908              :    array variable that can be used as the actual argument for dummy
    4909              :    argument SYM, except in the case of assumed rank dummies of
    4910              :    non-intrinsic functions where the descriptor must be passed. Add any
    4911              :    initialization code to BLOCK. PACKED is as for gfc_get_nodesc_array_type
    4912              :    and DATA points to the first element in the passed array.  */
    4913              : 
    4914              : static tree
    4915         8382 : gfc_get_interface_mapping_array (stmtblock_t * block, gfc_symbol * sym,
    4916              :                                  gfc_packed packed, tree data, tree len,
    4917              :                                  bool assumed_rank_formal)
    4918              : {
    4919         8382 :   tree type;
    4920         8382 :   tree var;
    4921              : 
    4922         8382 :   if (len != NULL_TREE && (TREE_CONSTANT (len) || VAR_P (len)))
    4923           58 :     type = gfc_get_character_type_len (sym->ts.kind, len);
    4924              :   else
    4925         8324 :     type = gfc_typenode_for_spec (&sym->ts);
    4926              : 
    4927         8382 :   if (assumed_rank_formal)
    4928           13 :     type = TREE_TYPE (data);
    4929              :   else
    4930         8369 :     type = gfc_get_nodesc_array_type (type, sym->as, packed,
    4931         8345 :                                     !sym->attr.target && !sym->attr.pointer
    4932        16714 :                                     && !sym->attr.proc_pointer);
    4933              : 
    4934         8382 :   var = gfc_create_var (type, "ifm");
    4935         8382 :   gfc_add_modify (block, var, fold_convert (type, data));
    4936              : 
    4937         8382 :   return var;
    4938              : }
    4939              : 
    4940              : 
    4941              : /* A subroutine of gfc_add_interface_mapping.  Set the stride, upper bounds
    4942              :    and offset of descriptorless array type TYPE given that it has the same
    4943              :    size as DESC.  Add any set-up code to BLOCK.  */
    4944              : 
    4945              : static void
    4946         8112 : gfc_set_interface_mapping_bounds (stmtblock_t * block, tree type, tree desc)
    4947              : {
    4948         8112 :   int n;
    4949         8112 :   tree dim;
    4950         8112 :   tree offset;
    4951         8112 :   tree tmp;
    4952              : 
    4953         8112 :   offset = gfc_index_zero_node;
    4954         9214 :   for (n = 0; n < GFC_TYPE_ARRAY_RANK (type); n++)
    4955              :     {
    4956         1102 :       dim = gfc_rank_cst[n];
    4957         1102 :       GFC_TYPE_ARRAY_STRIDE (type, n) = gfc_conv_array_stride (desc, n);
    4958         1102 :       if (GFC_TYPE_ARRAY_LBOUND (type, n) == NULL_TREE)
    4959              :         {
    4960            1 :           GFC_TYPE_ARRAY_LBOUND (type, n)
    4961            1 :                 = gfc_conv_descriptor_lbound_get (desc, dim);
    4962            1 :           GFC_TYPE_ARRAY_UBOUND (type, n)
    4963            2 :                 = gfc_conv_descriptor_ubound_get (desc, dim);
    4964              :         }
    4965         1101 :       else if (GFC_TYPE_ARRAY_UBOUND (type, n) == NULL_TREE)
    4966              :         {
    4967         1075 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
    4968              :                                  gfc_array_index_type,
    4969              :                                  gfc_conv_descriptor_ubound_get (desc, dim),
    4970              :                                  gfc_conv_descriptor_lbound_get (desc, dim));
    4971         3225 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    4972              :                                  gfc_array_index_type,
    4973         1075 :                                  GFC_TYPE_ARRAY_LBOUND (type, n), tmp);
    4974         1075 :           tmp = gfc_evaluate_now (tmp, block);
    4975         1075 :           GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;
    4976              :         }
    4977         4408 :       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    4978         1102 :                              GFC_TYPE_ARRAY_LBOUND (type, n),
    4979         1102 :                              GFC_TYPE_ARRAY_STRIDE (type, n));
    4980         1102 :       offset = fold_build2_loc (input_location, MINUS_EXPR,
    4981              :                                 gfc_array_index_type, offset, tmp);
    4982              :     }
    4983         8112 :   offset = gfc_evaluate_now (offset, block);
    4984         8112 :   GFC_TYPE_ARRAY_OFFSET (type) = offset;
    4985         8112 : }
    4986              : 
    4987              : 
    4988              : /* Extend MAPPING so that it maps dummy argument SYM to the value stored
    4989              :    in SE.  The caller may still use se->expr and se->string_length after
    4990              :    calling this function.  */
    4991              : 
    4992              : void
    4993        40222 : gfc_add_interface_mapping (gfc_interface_mapping * mapping,
    4994              :                            gfc_symbol * sym, gfc_se * se,
    4995              :                            gfc_expr *expr)
    4996              : {
    4997        40222 :   gfc_interface_sym_mapping *sm;
    4998        40222 :   tree desc;
    4999        40222 :   tree tmp;
    5000        40222 :   tree value;
    5001        40222 :   gfc_symbol *new_sym;
    5002        40222 :   gfc_symtree *root;
    5003        40222 :   gfc_symtree *new_symtree;
    5004              : 
    5005              :   /* Create a new symbol to represent the actual argument.  */
    5006        40222 :   new_sym = gfc_new_symbol (sym->name, NULL);
    5007        40222 :   new_sym->ts = sym->ts;
    5008        40222 :   new_sym->as = gfc_copy_array_spec (sym->as);
    5009        40222 :   new_sym->attr.referenced = 1;
    5010        40222 :   new_sym->attr.dimension = sym->attr.dimension;
    5011        40222 :   new_sym->attr.contiguous = sym->attr.contiguous;
    5012        40222 :   new_sym->attr.codimension = sym->attr.codimension;
    5013        40222 :   new_sym->attr.pointer = sym->attr.pointer;
    5014        40222 :   new_sym->attr.allocatable = sym->attr.allocatable;
    5015        40222 :   new_sym->attr.flavor = sym->attr.flavor;
    5016        40222 :   new_sym->attr.function = sym->attr.function;
    5017              : 
    5018              :   /* Ensure that the interface is available and that
    5019              :      descriptors are passed for array actual arguments.  */
    5020        40222 :   if (sym->attr.flavor == FL_PROCEDURE)
    5021              :     {
    5022           36 :       new_sym->formal = expr->symtree->n.sym->formal;
    5023           36 :       new_sym->attr.always_explicit
    5024           36 :             = expr->symtree->n.sym->attr.always_explicit;
    5025              :     }
    5026              : 
    5027              :   /* Create a fake symtree for it.  */
    5028        40222 :   root = NULL;
    5029        40222 :   new_symtree = gfc_new_symtree (&root, sym->name);
    5030        40222 :   new_symtree->n.sym = new_sym;
    5031        40222 :   gcc_assert (new_symtree == root);
    5032              : 
    5033              :   /* Create a dummy->actual mapping.  */
    5034        40222 :   sm = XCNEW (gfc_interface_sym_mapping);
    5035        40222 :   sm->next = mapping->syms;
    5036        40222 :   sm->old = sym;
    5037        40222 :   sm->new_sym = new_symtree;
    5038        40222 :   sm->expr = gfc_copy_expr (expr);
    5039        40222 :   mapping->syms = sm;
    5040              : 
    5041              :   /* Stabilize the argument's value.  */
    5042        40222 :   if (!sym->attr.function && se)
    5043        40124 :     se->expr = gfc_evaluate_now (se->expr, &se->pre);
    5044              : 
    5045        40222 :   if (sym->ts.type == BT_CHARACTER)
    5046              :     {
    5047              :       /* Create a copy of the dummy argument's length.  */
    5048         2785 :       new_sym->ts.u.cl = gfc_get_interface_mapping_charlen (mapping, sym->ts.u.cl);
    5049         2785 :       sm->expr->ts.u.cl = new_sym->ts.u.cl;
    5050              : 
    5051              :       /* If the length is specified as "*", record the length that
    5052              :          the caller is passing.  We should use the callee's length
    5053              :          in all other cases.  */
    5054         2785 :       if (!new_sym->ts.u.cl->length && se)
    5055              :         {
    5056         2557 :           se->string_length = gfc_evaluate_now (se->string_length, &se->pre);
    5057         2557 :           new_sym->ts.u.cl->backend_decl = se->string_length;
    5058              :         }
    5059              :     }
    5060              : 
    5061        40208 :   if (!se)
    5062           62 :     return;
    5063              : 
    5064              :   /* Use the passed value as-is if the argument is a function.  */
    5065        40160 :   if (sym->attr.flavor == FL_PROCEDURE)
    5066           36 :     value = se->expr;
    5067              : 
    5068              :   /* If the argument is a pass-by-value scalar, use the value as is.  */
    5069        40124 :   else if (!sym->attr.dimension && sym->attr.value)
    5070           78 :     value = se->expr;
    5071              : 
    5072              :   /* If the argument is either a string or a pointer to a string,
    5073              :      convert it to a boundless character type.  */
    5074        40046 :   else if (!sym->attr.dimension && sym->ts.type == BT_CHARACTER)
    5075              :     {
    5076         1216 :       se->string_length = gfc_evaluate_now (se->string_length, &se->pre);
    5077         1216 :       tmp = gfc_get_character_type_len (sym->ts.kind, se->string_length);
    5078         1216 :       tmp = build_pointer_type (tmp);
    5079         1216 :       if (sym->attr.pointer)
    5080          126 :         value = build_fold_indirect_ref_loc (input_location,
    5081              :                                          se->expr);
    5082              :       else
    5083         1090 :         value = se->expr;
    5084         1216 :       value = fold_convert (tmp, value);
    5085              :     }
    5086              : 
    5087              :   /* If the argument is a scalar, a pointer to an array or an allocatable,
    5088              :      dereference it.  */
    5089        38830 :   else if (!sym->attr.dimension || sym->attr.pointer || sym->attr.allocatable)
    5090        28951 :     value = build_fold_indirect_ref_loc (input_location,
    5091              :                                      se->expr);
    5092              : 
    5093              :   /* For character(*), use the actual argument's descriptor.  */
    5094         9879 :   else if (sym->ts.type == BT_CHARACTER && !new_sym->ts.u.cl->length)
    5095         1497 :     value = build_fold_indirect_ref_loc (input_location,
    5096              :                                          se->expr);
    5097              : 
    5098              :   /* If the argument is an array descriptor, use it to determine
    5099              :      information about the actual argument's shape.  */
    5100         8382 :   else if (POINTER_TYPE_P (TREE_TYPE (se->expr))
    5101         8382 :            && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
    5102              :     {
    5103         8112 :       bool assumed_rank_formal = false;
    5104              : 
    5105              :       /* Get the actual argument's descriptor.  */
    5106         8112 :       desc = build_fold_indirect_ref_loc (input_location,
    5107              :                                       se->expr);
    5108              : 
    5109              :       /* Create the replacement variable.  */
    5110         8112 :       if (sym->as && sym->as->type == AS_ASSUMED_RANK
    5111         7334 :           && !(sym->ns && sym->ns->proc_name
    5112         7334 :                && sym->ns->proc_name->attr.proc == PROC_INTRINSIC))
    5113              :         {
    5114              :           assumed_rank_formal = true;
    5115              :           tmp = desc;
    5116              :         }
    5117              :       else
    5118         8099 :         tmp = gfc_conv_descriptor_data_get (desc);
    5119              : 
    5120         8112 :       value = gfc_get_interface_mapping_array (&se->pre, sym,
    5121              :                                                PACKED_NO, tmp,
    5122              :                                                se->string_length,
    5123              :                                                assumed_rank_formal);
    5124              : 
    5125              :       /* Use DESC to work out the upper bounds, strides and offset.  */
    5126         8112 :       gfc_set_interface_mapping_bounds (&se->pre, TREE_TYPE (value), desc);
    5127              :     }
    5128              :   else
    5129              :     /* Otherwise we have a packed array.  */
    5130          270 :     value = gfc_get_interface_mapping_array (&se->pre, sym,
    5131              :                                              PACKED_FULL, se->expr,
    5132              :                                              se->string_length,
    5133              :                                              false);
    5134              : 
    5135        40160 :   new_sym->backend_decl = value;
    5136              : }
    5137              : 
    5138              : 
    5139              : /* Called once all dummy argument mappings have been added to MAPPING,
    5140              :    but before the mapping is used to evaluate expressions.  Pre-evaluate
    5141              :    the length of each argument, adding any initialization code to PRE and
    5142              :    any finalization code to POST.  */
    5143              : 
    5144              : static void
    5145       129117 : gfc_finish_interface_mapping (gfc_interface_mapping * mapping,
    5146              :                               stmtblock_t * pre, stmtblock_t * post)
    5147              : {
    5148       129117 :   gfc_interface_sym_mapping *sym;
    5149       129117 :   gfc_expr *expr;
    5150       129117 :   gfc_se se;
    5151              : 
    5152       169277 :   for (sym = mapping->syms; sym; sym = sym->next)
    5153        40160 :     if (sym->new_sym->n.sym->ts.type == BT_CHARACTER
    5154         2771 :         && !sym->new_sym->n.sym->ts.u.cl->backend_decl)
    5155              :       {
    5156          214 :         expr = sym->new_sym->n.sym->ts.u.cl->length;
    5157          214 :         gfc_apply_interface_mapping_to_expr (mapping, expr);
    5158          214 :         gfc_init_se (&se, NULL);
    5159          214 :         gfc_conv_expr (&se, expr);
    5160          214 :         se.expr = fold_convert (gfc_charlen_type_node, se.expr);
    5161          214 :         se.expr = gfc_evaluate_now (se.expr, &se.pre);
    5162          214 :         gfc_add_block_to_block (pre, &se.pre);
    5163          214 :         gfc_add_block_to_block (post, &se.post);
    5164              : 
    5165          214 :         sym->new_sym->n.sym->ts.u.cl->backend_decl = se.expr;
    5166              :       }
    5167       129117 : }
    5168              : 
    5169              : 
    5170              : /* Like gfc_apply_interface_mapping_to_expr, but applied to
    5171              :    constructor C.  */
    5172              : 
    5173              : static void
    5174           47 : gfc_apply_interface_mapping_to_cons (gfc_interface_mapping * mapping,
    5175              :                                      gfc_constructor_base base)
    5176              : {
    5177           47 :   gfc_constructor *c;
    5178          428 :   for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
    5179              :     {
    5180          381 :       gfc_apply_interface_mapping_to_expr (mapping, c->expr);
    5181          381 :       if (c->iterator)
    5182              :         {
    5183            6 :           gfc_apply_interface_mapping_to_expr (mapping, c->iterator->start);
    5184            6 :           gfc_apply_interface_mapping_to_expr (mapping, c->iterator->end);
    5185            6 :           gfc_apply_interface_mapping_to_expr (mapping, c->iterator->step);
    5186              :         }
    5187              :     }
    5188           47 : }
    5189              : 
    5190              : 
    5191              : /* Like gfc_apply_interface_mapping_to_expr, but applied to
    5192              :    reference REF.  */
    5193              : 
    5194              : static void
    5195        12507 : gfc_apply_interface_mapping_to_ref (gfc_interface_mapping * mapping,
    5196              :                                     gfc_ref * ref)
    5197              : {
    5198        12507 :   int n;
    5199              : 
    5200        13956 :   for (; ref; ref = ref->next)
    5201         1449 :     switch (ref->type)
    5202              :       {
    5203              :       case REF_ARRAY:
    5204         2879 :         for (n = 0; n < ref->u.ar.dimen; n++)
    5205              :           {
    5206         1632 :             gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.start[n]);
    5207         1632 :             gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.end[n]);
    5208         1632 :             gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.stride[n]);
    5209              :           }
    5210              :         break;
    5211              : 
    5212              :       case REF_COMPONENT:
    5213              :       case REF_INQUIRY:
    5214              :         break;
    5215              : 
    5216           43 :       case REF_SUBSTRING:
    5217           43 :         gfc_apply_interface_mapping_to_expr (mapping, ref->u.ss.start);
    5218           43 :         gfc_apply_interface_mapping_to_expr (mapping, ref->u.ss.end);
    5219           43 :         break;
    5220              :       }
    5221        12507 : }
    5222              : 
    5223              : 
    5224              : /* Convert intrinsic function calls into result expressions.  */
    5225              : 
    5226              : static bool
    5227         2196 : gfc_map_intrinsic_function (gfc_expr *expr, gfc_interface_mapping *mapping)
    5228              : {
    5229         2196 :   gfc_symbol *sym;
    5230         2196 :   gfc_expr *new_expr;
    5231         2196 :   gfc_expr *arg1;
    5232         2196 :   gfc_expr *arg2;
    5233         2196 :   int d, dup;
    5234              : 
    5235         2196 :   arg1 = expr->value.function.actual->expr;
    5236         2196 :   if (expr->value.function.actual->next)
    5237         2075 :     arg2 = expr->value.function.actual->next->expr;
    5238              :   else
    5239              :     arg2 = NULL;
    5240              : 
    5241         2196 :   sym = arg1->symtree->n.sym;
    5242              : 
    5243         2196 :   if (sym->attr.dummy)
    5244              :     return false;
    5245              : 
    5246         2172 :   new_expr = NULL;
    5247              : 
    5248         2172 :   switch (expr->value.function.isym->id)
    5249              :     {
    5250          929 :     case GFC_ISYM_LEN:
    5251              :       /* TODO figure out why this condition is necessary.  */
    5252          929 :       if (sym->attr.function
    5253           43 :           && (arg1->ts.u.cl->length == NULL
    5254           42 :               || (arg1->ts.u.cl->length->expr_type != EXPR_CONSTANT
    5255           42 :                   && arg1->ts.u.cl->length->expr_type != EXPR_VARIABLE)))
    5256              :         return false;
    5257              : 
    5258          886 :       new_expr = gfc_copy_expr (arg1->ts.u.cl->length);
    5259          886 :       break;
    5260              : 
    5261          228 :     case GFC_ISYM_LEN_TRIM:
    5262          228 :       new_expr = gfc_copy_expr (arg1);
    5263          228 :       gfc_apply_interface_mapping_to_expr (mapping, new_expr);
    5264              : 
    5265          228 :       if (!new_expr)
    5266              :         return false;
    5267              : 
    5268          228 :       gfc_replace_expr (arg1, new_expr);
    5269          228 :       return true;
    5270              : 
    5271          588 :     case GFC_ISYM_SIZE:
    5272          588 :       if (!sym->as || sym->as->rank == 0)
    5273              :         return false;
    5274              : 
    5275          530 :       if (arg2 && arg2->expr_type == EXPR_CONSTANT)
    5276              :         {
    5277          360 :           dup = mpz_get_si (arg2->value.integer);
    5278          360 :           d = dup - 1;
    5279              :         }
    5280              :       else
    5281              :         {
    5282          530 :           dup = sym->as->rank;
    5283          530 :           d = 0;
    5284              :         }
    5285              : 
    5286          542 :       for (; d < dup; d++)
    5287              :         {
    5288          530 :           gfc_expr *tmp;
    5289              : 
    5290          530 :           if (!sym->as->upper[d] || !sym->as->lower[d])
    5291              :             {
    5292          518 :               gfc_free_expr (new_expr);
    5293          518 :               return false;
    5294              :             }
    5295              : 
    5296           12 :           tmp = gfc_add (gfc_copy_expr (sym->as->upper[d]),
    5297              :                                         gfc_get_int_expr (gfc_default_integer_kind,
    5298              :                                                           NULL, 1));
    5299           12 :           tmp = gfc_subtract (tmp, gfc_copy_expr (sym->as->lower[d]));
    5300           12 :           if (new_expr)
    5301            0 :             new_expr = gfc_multiply (new_expr, tmp);
    5302              :           else
    5303              :             new_expr = tmp;
    5304              :         }
    5305              :       break;
    5306              : 
    5307           44 :     case GFC_ISYM_LBOUND:
    5308           44 :     case GFC_ISYM_UBOUND:
    5309              :         /* TODO These implementations of lbound and ubound do not limit if
    5310              :            the size < 0, according to F95's 13.14.53 and 13.14.113.  */
    5311              : 
    5312           44 :       if (!sym->as || sym->as->rank == 0)
    5313              :         return false;
    5314              : 
    5315           44 :       if (arg2 && arg2->expr_type == EXPR_CONSTANT)
    5316           38 :         d = mpz_get_si (arg2->value.integer) - 1;
    5317              :       else
    5318              :         return false;
    5319              : 
    5320           38 :       if (expr->value.function.isym->id == GFC_ISYM_LBOUND)
    5321              :         {
    5322           23 :           if (sym->as->lower[d])
    5323           23 :             new_expr = gfc_copy_expr (sym->as->lower[d]);
    5324              :         }
    5325              :       else
    5326              :         {
    5327           15 :           if (sym->as->upper[d])
    5328            9 :             new_expr = gfc_copy_expr (sym->as->upper[d]);
    5329              :         }
    5330              :       break;
    5331              : 
    5332              :     default:
    5333              :       break;
    5334              :     }
    5335              : 
    5336         1319 :   gfc_apply_interface_mapping_to_expr (mapping, new_expr);
    5337         1319 :   if (!new_expr)
    5338              :     return false;
    5339              : 
    5340          113 :   gfc_replace_expr (expr, new_expr);
    5341          113 :   return true;
    5342              : }
    5343              : 
    5344              : 
    5345              : static void
    5346           24 : gfc_map_fcn_formal_to_actual (gfc_expr *expr, gfc_expr *map_expr,
    5347              :                               gfc_interface_mapping * mapping)
    5348              : {
    5349           24 :   gfc_formal_arglist *f;
    5350           24 :   gfc_actual_arglist *actual;
    5351              : 
    5352           24 :   actual = expr->value.function.actual;
    5353           24 :   f = gfc_sym_get_dummy_args (map_expr->symtree->n.sym);
    5354              : 
    5355           72 :   for (; f && actual; f = f->next, actual = actual->next)
    5356              :     {
    5357           24 :       if (!actual->expr)
    5358            0 :         continue;
    5359              : 
    5360           24 :       gfc_add_interface_mapping (mapping, f->sym, NULL, actual->expr);
    5361              :     }
    5362              : 
    5363           24 :   if (map_expr->symtree->n.sym->attr.dimension)
    5364              :     {
    5365            6 :       int d;
    5366            6 :       gfc_array_spec *as;
    5367              : 
    5368            6 :       as = gfc_copy_array_spec (map_expr->symtree->n.sym->as);
    5369              : 
    5370           18 :       for (d = 0; d < as->rank; d++)
    5371              :         {
    5372            6 :           gfc_apply_interface_mapping_to_expr (mapping, as->lower[d]);
    5373            6 :           gfc_apply_interface_mapping_to_expr (mapping, as->upper[d]);
    5374              :         }
    5375              : 
    5376            6 :       expr->value.function.esym->as = as;
    5377              :     }
    5378              : 
    5379           24 :   if (map_expr->symtree->n.sym->ts.type == BT_CHARACTER)
    5380              :     {
    5381            0 :       expr->value.function.esym->ts.u.cl->length
    5382            0 :         = gfc_copy_expr (map_expr->symtree->n.sym->ts.u.cl->length);
    5383              : 
    5384            0 :       gfc_apply_interface_mapping_to_expr (mapping,
    5385            0 :                         expr->value.function.esym->ts.u.cl->length);
    5386              :     }
    5387           24 : }
    5388              : 
    5389              : 
    5390              : /* EXPR is a copy of an expression that appeared in the interface
    5391              :    associated with MAPPING.  Walk it recursively looking for references to
    5392              :    dummy arguments that MAPPING maps to actual arguments.  Replace each such
    5393              :    reference with a reference to the associated actual argument.  */
    5394              : 
    5395              : static void
    5396        20962 : gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping,
    5397              :                                      gfc_expr * expr)
    5398              : {
    5399        22515 :   gfc_interface_sym_mapping *sym;
    5400        22515 :   gfc_actual_arglist *actual;
    5401              : 
    5402        22515 :   if (!expr)
    5403              :     return;
    5404              : 
    5405              :   /* Copying an expression does not copy its length, so do that here.  */
    5406        12507 :   if (expr->ts.type == BT_CHARACTER && expr->ts.u.cl)
    5407              :     {
    5408         1784 :       expr->ts.u.cl = gfc_get_interface_mapping_charlen (mapping, expr->ts.u.cl);
    5409         1784 :       gfc_apply_interface_mapping_to_expr (mapping, expr->ts.u.cl->length);
    5410              :     }
    5411              : 
    5412              :   /* Apply the mapping to any references.  */
    5413        12507 :   gfc_apply_interface_mapping_to_ref (mapping, expr->ref);
    5414              : 
    5415              :   /* ...and to the expression's symbol, if it has one.  */
    5416              :   /* TODO Find out why the condition on expr->symtree had to be moved into
    5417              :      the loop rather than being outside it, as originally.  */
    5418        29786 :   for (sym = mapping->syms; sym; sym = sym->next)
    5419        17279 :     if (expr->symtree && !strcmp (sym->old->name, expr->symtree->n.sym->name))
    5420              :       {
    5421         3352 :         if (sym->new_sym->n.sym->backend_decl)
    5422         3308 :           expr->symtree = sym->new_sym;
    5423           44 :         else if (sym->expr)
    5424           44 :           gfc_replace_expr (expr, gfc_copy_expr (sym->expr));
    5425              :       }
    5426              : 
    5427              :       /* ...and to subexpressions in expr->value.  */
    5428        12507 :   switch (expr->expr_type)
    5429              :     {
    5430              :     case EXPR_VARIABLE:
    5431              :     case EXPR_CONSTANT:
    5432              :     case EXPR_NULL:
    5433              :     case EXPR_SUBSTRING:
    5434              :       break;
    5435              : 
    5436         1553 :     case EXPR_OP:
    5437         1553 :       gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op1);
    5438         1553 :       gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op2);
    5439         1553 :       break;
    5440              : 
    5441            0 :     case EXPR_CONDITIONAL:
    5442            0 :       gfc_apply_interface_mapping_to_expr (mapping,
    5443            0 :                                            expr->value.conditional.true_expr);
    5444            0 :       gfc_apply_interface_mapping_to_expr (mapping,
    5445            0 :                                            expr->value.conditional.false_expr);
    5446            0 :       break;
    5447              : 
    5448         2939 :     case EXPR_FUNCTION:
    5449         9430 :       for (actual = expr->value.function.actual; actual; actual = actual->next)
    5450         6491 :         gfc_apply_interface_mapping_to_expr (mapping, actual->expr);
    5451              : 
    5452         2939 :       if (expr->value.function.esym == NULL
    5453         2626 :             && expr->value.function.isym != NULL
    5454         2614 :             && expr->value.function.actual
    5455         2613 :             && expr->value.function.actual->expr
    5456         2613 :             && expr->value.function.actual->expr->symtree
    5457         5135 :             && gfc_map_intrinsic_function (expr, mapping))
    5458              :         break;
    5459              : 
    5460         6118 :       for (sym = mapping->syms; sym; sym = sym->next)
    5461         3520 :         if (sym->old == expr->value.function.esym)
    5462              :           {
    5463           24 :             expr->value.function.esym = sym->new_sym->n.sym;
    5464           24 :             gfc_map_fcn_formal_to_actual (expr, sym->expr, mapping);
    5465           24 :             expr->value.function.esym->result = sym->new_sym->n.sym;
    5466              :           }
    5467              :       break;
    5468              : 
    5469           47 :     case EXPR_ARRAY:
    5470           47 :     case EXPR_STRUCTURE:
    5471           47 :       gfc_apply_interface_mapping_to_cons (mapping, expr->value.constructor);
    5472           47 :       break;
    5473              : 
    5474            0 :     case EXPR_COMPCALL:
    5475            0 :     case EXPR_PPC:
    5476            0 :     case EXPR_UNKNOWN:
    5477            0 :       gcc_unreachable ();
    5478              :       break;
    5479              :     }
    5480              : 
    5481              :   return;
    5482              : }
    5483              : 
    5484              : 
    5485              : /* Evaluate interface expression EXPR using MAPPING.  Store the result
    5486              :    in SE.  */
    5487              : 
    5488              : void
    5489         3980 : gfc_apply_interface_mapping (gfc_interface_mapping * mapping,
    5490              :                              gfc_se * se, gfc_expr * expr)
    5491              : {
    5492         3980 :   expr = gfc_copy_expr (expr);
    5493         3980 :   gfc_apply_interface_mapping_to_expr (mapping, expr);
    5494         3980 :   gfc_conv_expr (se, expr);
    5495         3980 :   se->expr = gfc_evaluate_now (se->expr, &se->pre);
    5496         3980 :   gfc_free_expr (expr);
    5497         3980 : }
    5498              : 
    5499              : 
    5500              : /* Returns a reference to a temporary array into which a component of
    5501              :    an actual argument derived type array is copied and then returned
    5502              :    after the function call.  */
    5503              : void
    5504         2408 : gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
    5505              :                            sym_intent intent, bool formal_ptr,
    5506              :                            const gfc_symbol *fsym, const char *proc_name,
    5507              :                            gfc_symbol *sym, bool check_contiguous)
    5508              : {
    5509         2408 :   gfc_se lse;
    5510         2408 :   gfc_se rse;
    5511         2408 :   gfc_ss *lss;
    5512         2408 :   gfc_ss *rss;
    5513         2408 :   gfc_loopinfo loop;
    5514         2408 :   gfc_loopinfo loop2;
    5515         2408 :   gfc_array_info *info;
    5516         2408 :   tree offset;
    5517         2408 :   tree tmp_index;
    5518         2408 :   tree tmp;
    5519         2408 :   tree base_type;
    5520         2408 :   tree size;
    5521         2408 :   stmtblock_t body;
    5522         2408 :   int n;
    5523         2408 :   int dimen;
    5524         2408 :   gfc_se work_se;
    5525         2408 :   gfc_se *parmse;
    5526         2408 :   bool pass_optional;
    5527         2408 :   bool readonly;
    5528              : 
    5529         2408 :   pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
    5530              : 
    5531         2397 :   if (pass_optional || check_contiguous)
    5532              :     {
    5533         1359 :       gfc_init_se (&work_se, NULL);
    5534         1359 :       parmse = &work_se;
    5535              :     }
    5536              :   else
    5537              :     parmse = se;
    5538              : 
    5539         2408 :   if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
    5540              :     {
    5541              :       /* We will create a temporary array, so let us warn.  */
    5542          868 :       char * msg;
    5543              : 
    5544          868 :       if (fsym && proc_name)
    5545          868 :         msg = xasprintf ("An array temporary was created for argument "
    5546          868 :                          "'%s' of procedure '%s'", fsym->name, proc_name);
    5547              :       else
    5548            0 :         msg = xasprintf ("An array temporary was created");
    5549              : 
    5550          868 :       tmp = build_int_cst (logical_type_node, 1);
    5551          868 :       gfc_trans_runtime_check (false, true, tmp, &parmse->pre,
    5552              :                                &expr->where, msg);
    5553          868 :       free (msg);
    5554              :     }
    5555              : 
    5556         2408 :   gfc_init_se (&lse, NULL);
    5557         2408 :   gfc_init_se (&rse, NULL);
    5558              : 
    5559              :   /* Walk the argument expression.  */
    5560         2408 :   rss = gfc_walk_expr (expr);
    5561              : 
    5562         2408 :   gcc_assert (rss != gfc_ss_terminator);
    5563              : 
    5564              :   /* Initialize the scalarizer.  */
    5565         2408 :   gfc_init_loopinfo (&loop);
    5566         2408 :   gfc_add_ss_to_loop (&loop, rss);
    5567              : 
    5568              :   /* Calculate the bounds of the scalarization.  */
    5569         2408 :   gfc_conv_ss_startstride (&loop);
    5570              : 
    5571              :   /* Build an ss for the temporary.  */
    5572         2408 :   if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
    5573          136 :     gfc_conv_string_length (expr->ts.u.cl, expr, &parmse->pre);
    5574              : 
    5575         2408 :   base_type = gfc_typenode_for_spec (&expr->ts);
    5576         2408 :   if (GFC_ARRAY_TYPE_P (base_type)
    5577         2408 :                 || GFC_DESCRIPTOR_TYPE_P (base_type))
    5578            0 :     base_type = gfc_get_element_type (base_type);
    5579              : 
    5580         2408 :   if (expr->ts.type == BT_CLASS)
    5581          121 :     base_type = gfc_typenode_for_spec (&CLASS_DATA (expr)->ts);
    5582              : 
    5583         3572 :   loop.temp_ss = gfc_get_temp_ss (base_type, ((expr->ts.type == BT_CHARACTER)
    5584         1164 :                                               ? expr->ts.u.cl->backend_decl
    5585              :                                               : NULL),
    5586              :                                   loop.dimen);
    5587              : 
    5588         2408 :   parmse->string_length = loop.temp_ss->info->string_length;
    5589              : 
    5590              :   /* Associate the SS with the loop.  */
    5591         2408 :   gfc_add_ss_to_loop (&loop, loop.temp_ss);
    5592              : 
    5593              :   /* Setup the scalarizing loops.  */
    5594         2408 :   gfc_conv_loop_setup (&loop, &expr->where);
    5595              : 
    5596              :   /* Pass the temporary descriptor back to the caller.  */
    5597         2408 :   info = &loop.temp_ss->info->data.array;
    5598         2408 :   parmse->expr = info->descriptor;
    5599              : 
    5600              :   /* Setup the gfc_se structures.  */
    5601         2408 :   gfc_copy_loopinfo_to_se (&lse, &loop);
    5602         2408 :   gfc_copy_loopinfo_to_se (&rse, &loop);
    5603              : 
    5604         2408 :   rse.ss = rss;
    5605         2408 :   lse.ss = loop.temp_ss;
    5606         2408 :   gfc_mark_ss_chain_used (rss, 1);
    5607         2408 :   gfc_mark_ss_chain_used (loop.temp_ss, 1);
    5608              : 
    5609              :   /* Start the scalarized loop body.  */
    5610         2408 :   gfc_start_scalarized_body (&loop, &body);
    5611              : 
    5612              :   /* Translate the expression.  */
    5613         2408 :   gfc_conv_expr (&rse, expr);
    5614              : 
    5615         2408 :   gfc_conv_tmp_array_ref (&lse);
    5616              : 
    5617         2408 :   if (intent != INTENT_OUT)
    5618              :     {
    5619         2370 :       tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
    5620         2370 :       gfc_add_expr_to_block (&body, tmp);
    5621         2370 :       gcc_assert (rse.ss == gfc_ss_terminator);
    5622         2370 :       gfc_trans_scalarizing_loops (&loop, &body);
    5623              :     }
    5624              :   else
    5625              :     {
    5626              :       /* Make sure that the temporary declaration survives by merging
    5627              :        all the loop declarations into the current context.  */
    5628           85 :       for (n = 0; n < loop.dimen; n++)
    5629              :         {
    5630           47 :           gfc_merge_block_scope (&body);
    5631           47 :           body = loop.code[loop.order[n]];
    5632              :         }
    5633           38 :       gfc_merge_block_scope (&body);
    5634              :     }
    5635              : 
    5636              :   /* Add the post block after the second loop, so that any
    5637              :      freeing of allocated memory is done at the right time.  */
    5638         2408 :   gfc_add_block_to_block (&parmse->pre, &loop.pre);
    5639              : 
    5640              :   /**********Copy the temporary back again.*********/
    5641              : 
    5642         2408 :   gfc_init_se (&lse, NULL);
    5643         2408 :   gfc_init_se (&rse, NULL);
    5644              : 
    5645              :   /* Walk the argument expression.  */
    5646         2408 :   lss = gfc_walk_expr (expr);
    5647         2408 :   rse.ss = loop.temp_ss;
    5648         2408 :   lse.ss = lss;
    5649              : 
    5650              :   /* Initialize the scalarizer.  */
    5651         2408 :   gfc_init_loopinfo (&loop2);
    5652         2408 :   gfc_add_ss_to_loop (&loop2, lss);
    5653              : 
    5654         2408 :   dimen = rse.ss->dimen;
    5655              : 
    5656              :   /* Skip the write-out loop for this case.  */
    5657         2408 :   if (gfc_is_class_array_function (expr))
    5658           13 :     goto class_array_fcn;
    5659              : 
    5660              :   /* Calculate the bounds of the scalarization.  */
    5661         2395 :   gfc_conv_ss_startstride (&loop2);
    5662              : 
    5663              :   /* Setup the scalarizing loops.  */
    5664         2395 :   gfc_conv_loop_setup (&loop2, &expr->where);
    5665              : 
    5666         2395 :   gfc_copy_loopinfo_to_se (&lse, &loop2);
    5667         2395 :   gfc_copy_loopinfo_to_se (&rse, &loop2);
    5668              : 
    5669         2395 :   gfc_mark_ss_chain_used (lss, 1);
    5670         2395 :   gfc_mark_ss_chain_used (loop.temp_ss, 1);
    5671              : 
    5672              :   /* Declare the variable to hold the temporary offset and start the
    5673              :      scalarized loop body.  */
    5674         2395 :   offset = gfc_create_var (gfc_array_index_type, NULL);
    5675         2395 :   gfc_start_scalarized_body (&loop2, &body);
    5676              : 
    5677              :   /* Build the offsets for the temporary from the loop variables.  The
    5678              :      temporary array has lbounds of zero and strides of one in all
    5679              :      dimensions, so this is very simple.  The offset is only computed
    5680              :      outside the innermost loop, so the overall transfer could be
    5681              :      optimized further.  */
    5682         2395 :   info = &rse.ss->info->data.array;
    5683              : 
    5684         2395 :   tmp_index = gfc_index_zero_node;
    5685         3745 :   for (n = dimen - 1; n > 0; n--)
    5686              :     {
    5687         1350 :       tree tmp_str;
    5688         1350 :       tmp = rse.loop->loopvar[n];
    5689         1350 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    5690              :                              tmp, rse.loop->from[n]);
    5691         1350 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    5692              :                              tmp, tmp_index);
    5693              : 
    5694         2700 :       tmp_str = fold_build2_loc (input_location, MINUS_EXPR,
    5695              :                                  gfc_array_index_type,
    5696         1350 :                                  rse.loop->to[n-1], rse.loop->from[n-1]);
    5697         1350 :       tmp_str = fold_build2_loc (input_location, PLUS_EXPR,
    5698              :                                  gfc_array_index_type,
    5699              :                                  tmp_str, gfc_index_one_node);
    5700              : 
    5701         1350 :       tmp_index = fold_build2_loc (input_location, MULT_EXPR,
    5702              :                                    gfc_array_index_type, tmp, tmp_str);
    5703              :     }
    5704              : 
    5705         4790 :   tmp_index = fold_build2_loc (input_location, MINUS_EXPR,
    5706              :                                gfc_array_index_type,
    5707         2395 :                                tmp_index, rse.loop->from[0]);
    5708         2395 :   gfc_add_modify (&rse.loop->code[0], offset, tmp_index);
    5709              : 
    5710         4790 :   tmp_index = fold_build2_loc (input_location, PLUS_EXPR,
    5711              :                                gfc_array_index_type,
    5712         2395 :                                rse.loop->loopvar[0], offset);
    5713              : 
    5714              :   /* Now use the offset for the reference.  */
    5715         2395 :   tmp = build_fold_indirect_ref_loc (input_location,
    5716              :                                  info->data);
    5717         2395 :   rse.expr = gfc_build_array_ref (tmp, tmp_index, NULL);
    5718              : 
    5719         2395 :   if (expr->ts.type == BT_CHARACTER)
    5720         1164 :     rse.string_length = expr->ts.u.cl->backend_decl;
    5721              : 
    5722         2395 :   gfc_conv_expr (&lse, expr);
    5723              : 
    5724         2395 :   gcc_assert (lse.ss == gfc_ss_terminator);
    5725              : 
    5726         2395 :   tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true);
    5727         2395 :   gfc_add_expr_to_block (&body, tmp);
    5728              : 
    5729              :   /* Generate the copying loops.  */
    5730         2395 :   gfc_trans_scalarizing_loops (&loop2, &body);
    5731              : 
    5732              :   /* Wrap the whole thing up by adding the second loop to the post-block
    5733              :      and following it by the post-block of the first loop.  In this way,
    5734              :      if the temporary needs freeing, it is done after use!
    5735              :      If input expr is read-only, e.g. a PARAMETER array, copying back
    5736              :      modified values is undefined behavior.  */
    5737         4790 :   readonly = (expr->expr_type == EXPR_VARIABLE
    5738         2341 :               && expr->symtree
    5739         4736 :               && expr->symtree->n.sym->attr.flavor == FL_PARAMETER);
    5740              : 
    5741         2395 :   if ((intent != INTENT_IN) && !readonly)
    5742              :     {
    5743         1166 :       gfc_add_block_to_block (&parmse->post, &loop2.pre);
    5744         1166 :       gfc_add_block_to_block (&parmse->post, &loop2.post);
    5745              :     }
    5746              : 
    5747         1229 : class_array_fcn:
    5748              : 
    5749         2408 :   gfc_add_block_to_block (&parmse->post, &loop.post);
    5750              : 
    5751         2408 :   gfc_cleanup_loop (&loop);
    5752         2408 :   gfc_cleanup_loop (&loop2);
    5753              : 
    5754              :   /* Pass the string length to the argument expression.  */
    5755         2408 :   if (expr->ts.type == BT_CHARACTER)
    5756         1164 :     parmse->string_length = expr->ts.u.cl->backend_decl;
    5757              : 
    5758              :   /* Determine the offset for pointer formal arguments and set the
    5759              :      lbounds to one.  */
    5760         2408 :   if (formal_ptr)
    5761              :     {
    5762           18 :       size = gfc_index_one_node;
    5763           18 :       offset = gfc_index_zero_node;
    5764           36 :       for (n = 0; n < dimen; n++)
    5765              :         {
    5766           18 :           tmp = gfc_conv_descriptor_ubound_get (parmse->expr,
    5767              :                                                 gfc_rank_cst[n]);
    5768           18 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    5769              :                                  gfc_array_index_type, tmp,
    5770              :                                  gfc_index_one_node);
    5771           18 :           gfc_conv_descriptor_ubound_set (&parmse->pre,
    5772              :                                           parmse->expr,
    5773              :                                           gfc_rank_cst[n],
    5774              :                                           tmp);
    5775           18 :           gfc_conv_descriptor_lbound_set (&parmse->pre,
    5776              :                                           parmse->expr,
    5777              :                                           gfc_rank_cst[n],
    5778              :                                           gfc_index_one_node);
    5779           18 :           size = gfc_evaluate_now (size, &parmse->pre);
    5780           18 :           offset = fold_build2_loc (input_location, MINUS_EXPR,
    5781              :                                     gfc_array_index_type,
    5782              :                                     offset, size);
    5783           18 :           offset = gfc_evaluate_now (offset, &parmse->pre);
    5784           36 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
    5785              :                                  gfc_array_index_type,
    5786           18 :                                  rse.loop->to[n], rse.loop->from[n]);
    5787           18 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
    5788              :                                  gfc_array_index_type,
    5789              :                                  tmp, gfc_index_one_node);
    5790           18 :           size = fold_build2_loc (input_location, MULT_EXPR,
    5791              :                                   gfc_array_index_type, size, tmp);
    5792              :         }
    5793              : 
    5794           18 :       gfc_conv_descriptor_offset_set (&parmse->pre, parmse->expr,
    5795              :                                       offset);
    5796              :     }
    5797              : 
    5798              :   /* We want either the address for the data or the address of the descriptor,
    5799              :      depending on the mode of passing array arguments.  */
    5800         2408 :   if (g77)
    5801          437 :     parmse->expr = gfc_conv_descriptor_data_get (parmse->expr);
    5802              :   else
    5803         1971 :     parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
    5804              : 
    5805              :   /* Basically make this into
    5806              : 
    5807              :      if (present)
    5808              :        {
    5809              :          if (contiguous)
    5810              :            {
    5811              :              pointer = a;
    5812              :            }
    5813              :          else
    5814              :            {
    5815              :              parmse->pre();
    5816              :              pointer = parmse->expr;
    5817              :            }
    5818              :        }
    5819              :      else
    5820              :        pointer = NULL;
    5821              : 
    5822              :      foo (pointer);
    5823              :      if (present && !contiguous)
    5824              :            se->post();
    5825              : 
    5826              :      */
    5827              : 
    5828         2408 :   if (pass_optional || check_contiguous)
    5829              :     {
    5830         1359 :       tree type;
    5831         1359 :       stmtblock_t else_block;
    5832         1359 :       tree pre_stmts, post_stmts;
    5833         1359 :       tree pointer;
    5834         1359 :       tree else_stmt;
    5835         1359 :       tree present_var = NULL_TREE;
    5836         1359 :       tree cont_var = NULL_TREE;
    5837         1359 :       tree post_cond;
    5838              : 
    5839         1359 :       type = TREE_TYPE (parmse->expr);
    5840         1359 :       if (POINTER_TYPE_P (type) && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))
    5841         1027 :         type = TREE_TYPE (type);
    5842         1359 :       pointer = gfc_create_var (type, "arg_ptr");
    5843              : 
    5844         1359 :       if (check_contiguous)
    5845              :         {
    5846         1359 :           gfc_se cont_se, array_se;
    5847         1359 :           stmtblock_t if_block, else_block;
    5848         1359 :           tree if_stmt, else_stmt;
    5849         1359 :           mpz_t size;
    5850         1359 :           bool size_set;
    5851              : 
    5852         1359 :           cont_var = gfc_create_var (boolean_type_node, "contiguous");
    5853              : 
    5854              :           /* If the size is known to be one at compile-time, set
    5855              :              cont_var to true unconditionally.  This may look
    5856              :              inelegant, but we're only doing this during
    5857              :              optimization, so the statements will be optimized away,
    5858              :              and this saves complexity here.  */
    5859              : 
    5860         1359 :           size_set = gfc_array_size (expr, &size);
    5861         1359 :           if (size_set && mpz_cmp_ui (size, 1) == 0)
    5862              :             {
    5863            6 :               gfc_add_modify (&se->pre, cont_var,
    5864              :                               build_one_cst (boolean_type_node));
    5865              :             }
    5866              :           else
    5867              :             {
    5868              :               /* cont_var = is_contiguous (expr); .  */
    5869         1353 :               gfc_init_se (&cont_se, parmse);
    5870         1353 :               gfc_conv_is_contiguous_expr (&cont_se, expr);
    5871         1353 :               gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
    5872         1353 :               gfc_add_modify (&se->pre, cont_var, cont_se.expr);
    5873         1353 :               gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
    5874              :             }
    5875              : 
    5876         1359 :           if (size_set)
    5877         1145 :             mpz_clear (size);
    5878              : 
    5879              :           /* arrayse->expr = descriptor of a.  */
    5880         1359 :           gfc_init_se (&array_se, se);
    5881         1359 :           gfc_conv_expr_descriptor (&array_se, expr);
    5882         1359 :           gfc_add_block_to_block (&se->pre, &(&array_se)->pre);
    5883         1359 :           gfc_add_block_to_block (&se->pre, &(&array_se)->post);
    5884              : 
    5885              :           /* if_stmt = { descriptor ? pointer = a : pointer = &a[0]; } .  */
    5886         1359 :           gfc_init_block (&if_block);
    5887         1359 :           if (GFC_DESCRIPTOR_TYPE_P (type))
    5888         1027 :             gfc_add_modify (&if_block, pointer, array_se.expr);
    5889              :           else
    5890              :             {
    5891          332 :               tmp = gfc_conv_array_data (array_se.expr);
    5892          332 :               tmp = fold_convert (type, tmp);
    5893          332 :               gfc_add_modify (&if_block, pointer, tmp);
    5894              :             }
    5895         1359 :           if_stmt = gfc_finish_block (&if_block);
    5896              : 
    5897              :           /* else_stmt = { parmse->pre(); pointer = parmse->expr; } .  */
    5898         1359 :           gfc_init_block (&else_block);
    5899         1359 :           gfc_add_block_to_block (&else_block, &parmse->pre);
    5900         1691 :           tmp = (GFC_DESCRIPTOR_TYPE_P (type)
    5901         1359 :                  ? build_fold_indirect_ref_loc (input_location, parmse->expr)
    5902              :                  : parmse->expr);
    5903         1359 :           gfc_add_modify (&else_block, pointer, tmp);
    5904         1359 :           else_stmt = gfc_finish_block (&else_block);
    5905              : 
    5906              :           /* And put the above into an if statement.  */
    5907         1359 :           pre_stmts = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    5908              :                                        gfc_likely (cont_var,
    5909              :                                                    PRED_FORTRAN_CONTIGUOUS),
    5910              :                                        if_stmt, else_stmt);
    5911              :         }
    5912              :       else
    5913              :         {
    5914              :           /* pointer = pramse->expr;  .  */
    5915            0 :           gfc_add_modify (&parmse->pre, pointer, parmse->expr);
    5916            0 :           pre_stmts = gfc_finish_block (&parmse->pre);
    5917              :         }
    5918              : 
    5919         1359 :       if (pass_optional)
    5920              :         {
    5921           11 :           present_var = gfc_create_var (boolean_type_node, "present");
    5922              : 
    5923              :           /* present_var = present(sym); .  */
    5924           11 :           tmp = gfc_conv_expr_present (sym);
    5925           11 :           tmp = fold_convert (boolean_type_node, tmp);
    5926           11 :           gfc_add_modify (&se->pre, present_var, tmp);
    5927              : 
    5928              :           /* else_stmt = { pointer = NULL; } .  */
    5929           11 :           gfc_init_block (&else_block);
    5930           11 :           if (GFC_DESCRIPTOR_TYPE_P (type))
    5931            0 :             gfc_conv_descriptor_data_set (&else_block, pointer,
    5932              :                                           null_pointer_node);
    5933              :           else
    5934           11 :             gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
    5935           11 :           else_stmt = gfc_finish_block (&else_block);
    5936              : 
    5937           11 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    5938              :                                  gfc_likely (present_var,
    5939              :                                              PRED_FORTRAN_ABSENT_DUMMY),
    5940              :                                  pre_stmts, else_stmt);
    5941           11 :           gfc_add_expr_to_block (&se->pre, tmp);
    5942              :         }
    5943              :       else
    5944         1348 :         gfc_add_expr_to_block (&se->pre, pre_stmts);
    5945              : 
    5946         1359 :       post_stmts = gfc_finish_block (&parmse->post);
    5947              : 
    5948              :       /* Put together the post stuff, plus the optional
    5949              :          deallocation.  */
    5950         1359 :       if (check_contiguous)
    5951              :         {
    5952              :           /* !cont_var.  */
    5953         1359 :           tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
    5954              :                                  cont_var,
    5955              :                                  build_zero_cst (boolean_type_node));
    5956         1359 :           tmp = gfc_unlikely (tmp, PRED_FORTRAN_CONTIGUOUS);
    5957              : 
    5958         1359 :           if (pass_optional)
    5959              :             {
    5960           11 :               tree present_likely = gfc_likely (present_var,
    5961              :                                                 PRED_FORTRAN_ABSENT_DUMMY);
    5962           11 :               post_cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    5963              :                                            boolean_type_node, present_likely,
    5964              :                                            tmp);
    5965              :             }
    5966              :           else
    5967              :             post_cond = tmp;
    5968              :         }
    5969              :       else
    5970              :         {
    5971            0 :           gcc_assert (pass_optional);
    5972              :           post_cond = present_var;
    5973              :         }
    5974              : 
    5975         1359 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, post_cond,
    5976              :                              post_stmts, build_empty_stmt (input_location));
    5977         1359 :       gfc_add_expr_to_block (&se->post, tmp);
    5978         1359 :       if (GFC_DESCRIPTOR_TYPE_P (type))
    5979              :         {
    5980         1027 :           type = TREE_TYPE (parmse->expr);
    5981         1027 :           if (POINTER_TYPE_P (type))
    5982              :             {
    5983         1027 :               pointer = gfc_build_addr_expr (type, pointer);
    5984         1027 :               if (pass_optional)
    5985              :                 {
    5986            0 :                   tmp = gfc_likely (present_var, PRED_FORTRAN_ABSENT_DUMMY);
    5987            0 :                   pointer = fold_build3_loc (input_location, COND_EXPR, type,
    5988              :                                              tmp, pointer,
    5989              :                                              fold_convert (type,
    5990              :                                                            null_pointer_node));
    5991              :                 }
    5992              :             }
    5993              :           else
    5994            0 :             gcc_assert (!pass_optional);
    5995              :         }
    5996         1359 :       se->expr = pointer;
    5997              :     }
    5998              : 
    5999         2408 :   return;
    6000              : }
    6001              : 
    6002              : 
    6003              : /* Generate the code for argument list functions.  */
    6004              : 
    6005              : static void
    6006         5822 : conv_arglist_function (gfc_se *se, gfc_expr *expr, const char *name)
    6007              : {
    6008              :   /* Pass by value for g77 %VAL(arg), pass the address
    6009              :      indirectly for %LOC, else by reference.  Thus %REF
    6010              :      is a "do-nothing" and %LOC is the same as an F95
    6011              :      pointer.  */
    6012         5822 :   if (strcmp (name, "%VAL") == 0)
    6013         5810 :     gfc_conv_expr (se, expr);
    6014           12 :   else if (strcmp (name, "%LOC") == 0)
    6015              :     {
    6016            6 :       gfc_conv_expr_reference (se, expr);
    6017            6 :       se->expr = gfc_build_addr_expr (NULL, se->expr);
    6018              :     }
    6019            6 :   else if (strcmp (name, "%REF") == 0)
    6020            6 :     gfc_conv_expr_reference (se, expr);
    6021              :   else
    6022            0 :     gfc_error ("Unknown argument list function at %L", &expr->where);
    6023         5822 : }
    6024              : 
    6025              : 
    6026              : /* This function tells whether the middle-end representation of the expression
    6027              :    E given as input may point to data otherwise accessible through a variable
    6028              :    (sub-)reference.
    6029              :    It is assumed that the only expressions that may alias are variables,
    6030              :    and array constructors if ARRAY_MAY_ALIAS is true and some of its elements
    6031              :    may alias.
    6032              :    This function is used to decide whether freeing an expression's allocatable
    6033              :    components is safe or should be avoided.
    6034              : 
    6035              :    If ARRAY_MAY_ALIAS is true, an array constructor may alias if some of
    6036              :    its elements are copied from a variable.  This ARRAY_MAY_ALIAS trick
    6037              :    is necessary because for array constructors, aliasing depends on how
    6038              :    the array is used:
    6039              :     - If E is an array constructor used as argument to an elemental procedure,
    6040              :       the array, which is generated through shallow copy by the scalarizer,
    6041              :       is used directly and can alias the expressions it was copied from.
    6042              :     - If E is an array constructor used as argument to a non-elemental
    6043              :       procedure,the scalarizer is used in gfc_conv_expr_descriptor to generate
    6044              :       the array as in the previous case, but then that array is used
    6045              :       to initialize a new descriptor through deep copy.  There is no alias
    6046              :       possible in that case.
    6047              :    Thus, the ARRAY_MAY_ALIAS flag is necessary to distinguish the two cases
    6048              :    above.  */
    6049              : 
    6050              : static bool
    6051         7569 : expr_may_alias_variables (gfc_expr *e, bool array_may_alias)
    6052              : {
    6053         7569 :   gfc_constructor *c;
    6054              : 
    6055         7569 :   if (e->expr_type == EXPR_VARIABLE)
    6056              :     return true;
    6057          544 :   else if (e->expr_type == EXPR_FUNCTION)
    6058              :     {
    6059          161 :       gfc_symbol *proc_ifc = gfc_get_proc_ifc_for_expr (e);
    6060              : 
    6061          161 :       if (proc_ifc->result != NULL
    6062          161 :           && ((proc_ifc->result->ts.type == BT_CLASS
    6063           25 :                && proc_ifc->result->ts.u.derived->attr.is_class
    6064           25 :                && CLASS_DATA (proc_ifc->result)->attr.class_pointer)
    6065          161 :               || proc_ifc->result->attr.pointer))
    6066              :         return true;
    6067              :       else
    6068              :         return false;
    6069              :     }
    6070          383 :   else if (e->expr_type != EXPR_ARRAY || !array_may_alias)
    6071              :     return false;
    6072              : 
    6073           79 :   for (c = gfc_constructor_first (e->value.constructor);
    6074          233 :        c; c = gfc_constructor_next (c))
    6075          189 :     if (c->expr
    6076          189 :         && expr_may_alias_variables (c->expr, array_may_alias))
    6077              :       return true;
    6078              : 
    6079              :   return false;
    6080              : }
    6081              : 
    6082              : 
    6083              : /* A helper function to set the dtype for unallocated or unassociated
    6084              :    entities.  */
    6085              : 
    6086              : static void
    6087          891 : set_dtype_for_unallocated (gfc_se *parmse, gfc_expr *e)
    6088              : {
    6089          891 :   tree tmp;
    6090          891 :   tree desc;
    6091          891 :   tree cond;
    6092          891 :   tree type;
    6093          891 :   stmtblock_t block;
    6094              : 
    6095              :   /* TODO Figure out how to handle optional dummies.  */
    6096          891 :   if (e && e->expr_type == EXPR_VARIABLE
    6097          807 :       && e->symtree->n.sym->attr.optional)
    6098          108 :     return;
    6099              : 
    6100          819 :   desc = parmse->expr;
    6101          819 :   if (desc == NULL_TREE)
    6102              :     return;
    6103              : 
    6104          819 :   if (POINTER_TYPE_P (TREE_TYPE (desc)))
    6105          819 :     desc = build_fold_indirect_ref_loc (input_location, desc);
    6106          819 :   if (GFC_CLASS_TYPE_P (TREE_TYPE (desc)))
    6107          192 :     desc = gfc_class_data_get (desc);
    6108          819 :   if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
    6109              :     return;
    6110              : 
    6111          783 :   gfc_init_block (&block);
    6112          783 :   tmp = gfc_conv_descriptor_data_get (desc);
    6113          783 :   cond = fold_build2_loc (input_location, EQ_EXPR,
    6114              :                           logical_type_node, tmp,
    6115          783 :                           build_int_cst (TREE_TYPE (tmp), 0));
    6116          783 :   tmp = gfc_conv_descriptor_dtype (desc);
    6117          783 :   type = gfc_get_element_type (TREE_TYPE (desc));
    6118         1566 :   tmp = fold_build2_loc (input_location, MODIFY_EXPR,
    6119          783 :                          TREE_TYPE (tmp), tmp,
    6120              :                          gfc_get_dtype_rank_type (e->rank, type));
    6121          783 :   gfc_add_expr_to_block (&block, tmp);
    6122          783 :   cond = build3_v (COND_EXPR, cond,
    6123              :                    gfc_finish_block (&block),
    6124              :                    build_empty_stmt (input_location));
    6125          783 :   gfc_add_expr_to_block (&parmse->pre, cond);
    6126              : }
    6127              : 
    6128              : 
    6129              : 
    6130              : /* Provide an interface between gfortran array descriptors and the F2018:18.4
    6131              :    ISO_Fortran_binding array descriptors. */
    6132              : 
    6133              : static void
    6134         6537 : gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
    6135              : {
    6136         6537 :   stmtblock_t block, block2;
    6137         6537 :   tree cfi, gfc, tmp, tmp2;
    6138         6537 :   tree present = NULL;
    6139         6537 :   tree gfc_strlen = NULL;
    6140         6537 :   tree rank;
    6141         6537 :   gfc_se se;
    6142              : 
    6143         6537 :   if (fsym->attr.optional
    6144         1094 :       && e->expr_type == EXPR_VARIABLE
    6145         1094 :       && e->symtree->n.sym->attr.optional)
    6146          103 :     present = gfc_conv_expr_present (e->symtree->n.sym);
    6147              : 
    6148         6537 :   gfc_init_block (&block);
    6149              : 
    6150              :   /* Convert original argument to a tree. */
    6151         6537 :   gfc_init_se (&se, NULL);
    6152         6537 :   if (e->rank == 0)
    6153              :     {
    6154          687 :       se.want_pointer = 1;
    6155          687 :       gfc_conv_expr (&se, e);
    6156          687 :       gfc = se.expr;
    6157              :     }
    6158              :   else
    6159              :     {
    6160              :       /* If the actual argument can be noncontiguous, copy-in/out is required,
    6161              :          if the dummy has either the CONTIGUOUS attribute or is an assumed-
    6162              :          length assumed-length/assumed-size CHARACTER array.  This only
    6163              :          applies if the actual argument is a "variable"; if it's some
    6164              :          non-lvalue expression, we are going to evaluate it to a
    6165              :          temporary below anyway.  */
    6166         5850 :       se.force_no_tmp = 1;
    6167         5850 :       if ((fsym->attr.contiguous
    6168         4769 :            || (fsym->ts.type == BT_CHARACTER && !fsym->ts.u.cl->length
    6169         1375 :                && (fsym->as->type == AS_ASSUMED_SIZE
    6170          937 :                    || fsym->as->type == AS_EXPLICIT)))
    6171         2023 :           && !gfc_is_simply_contiguous (e, false, true)
    6172         6883 :           && gfc_expr_is_variable (e))
    6173              :         {
    6174         1027 :           bool optional = fsym->attr.optional;
    6175         1027 :           fsym->attr.optional = 0;
    6176         1027 :           gfc_conv_subref_array_arg (&se, e, false, fsym->attr.intent,
    6177         1027 :                                      fsym->attr.pointer, fsym,
    6178         1027 :                                      fsym->ns->proc_name->name, NULL,
    6179              :                                      /* check_contiguous= */ true);
    6180         1027 :           fsym->attr.optional = optional;
    6181              :         }
    6182              :       else
    6183         4823 :         gfc_conv_expr_descriptor (&se, e);
    6184         5850 :       gfc = se.expr;
    6185              :       /* For dt(:)%var the elem_len*stride != sm, hence, GFC uses
    6186              :          elem_len = sizeof(dt) and base_addr = dt(lb) instead.
    6187              :          gfc_get_dataptr_offset fixes the base_addr; for elem_len, see below.
    6188              :          While sm is fine as it uses span*stride and not elem_len.  */
    6189         5850 :       if (POINTER_TYPE_P (TREE_TYPE (gfc)))
    6190         1027 :         gfc = build_fold_indirect_ref_loc (input_location, gfc);
    6191         4823 :       else if (is_subref_array (e) && e->ts.type != BT_CHARACTER)
    6192           12 :          gfc_get_dataptr_offset (&se.pre, gfc, gfc, NULL, true, e);
    6193              :     }
    6194         6537 :   if (e->ts.type == BT_CHARACTER)
    6195              :     {
    6196         3409 :       if (se.string_length)
    6197              :         gfc_strlen = se.string_length;
    6198          883 :       else if (e->ts.u.cl->backend_decl)
    6199              :         gfc_strlen = e->ts.u.cl->backend_decl;
    6200              :       else
    6201            0 :         gcc_unreachable ();
    6202              :     }
    6203         6537 :   gfc_add_block_to_block (&block, &se.pre);
    6204              : 
    6205              :   /* Create array descriptor and set version, rank, attribute, type. */
    6206        12769 :   cfi = gfc_create_var (gfc_get_cfi_type (e->rank < 0
    6207              :                                           ? GFC_MAX_DIMENSIONS : e->rank,
    6208              :                                           false), "cfi");
    6209              :   /* Convert to CFI_cdesc_t, which has dim[] to avoid TBAA issues,*/
    6210         6537 :   if (fsym->attr.dimension && fsym->as->type == AS_ASSUMED_RANK)
    6211              :     {
    6212         2516 :       tmp = gfc_get_cfi_type (-1, !fsym->attr.pointer && !fsym->attr.target);
    6213         2338 :       tmp = build_pointer_type (tmp);
    6214         2338 :       parmse->expr = cfi = gfc_build_addr_expr (tmp, cfi);
    6215         2338 :       cfi = build_fold_indirect_ref_loc (input_location, cfi);
    6216              :     }
    6217              :   else
    6218         4199 :     parmse->expr = gfc_build_addr_expr (NULL, cfi);
    6219              : 
    6220         6537 :   tmp = gfc_get_cfi_desc_version (cfi);
    6221         6537 :   gfc_add_modify (&block, tmp,
    6222         6537 :                   build_int_cst (TREE_TYPE (tmp), CFI_VERSION));
    6223         6537 :   if (e->rank < 0)
    6224          305 :     rank = fold_convert (signed_char_type_node, gfc_conv_descriptor_rank (gfc));
    6225              :   else
    6226         6232 :     rank = build_int_cst (signed_char_type_node, e->rank);
    6227         6537 :   tmp = gfc_get_cfi_desc_rank (cfi);
    6228         6537 :   gfc_add_modify (&block, tmp, rank);
    6229         6537 :   int itype = CFI_type_other;
    6230         6537 :   if (e->ts.f90_type == BT_VOID)
    6231           96 :     itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
    6232           96 :              ? CFI_type_cfunptr : CFI_type_cptr);
    6233              :   else
    6234              :     {
    6235         6441 :       if (e->expr_type == EXPR_NULL && e->ts.type == BT_UNKNOWN)
    6236            1 :         e->ts = fsym->ts;
    6237         6441 :       switch (e->ts.type)
    6238              :         {
    6239         2296 :         case BT_INTEGER:
    6240         2296 :         case BT_LOGICAL:
    6241         2296 :         case BT_REAL:
    6242         2296 :         case BT_COMPLEX:
    6243         2296 :           itype = CFI_type_from_type_kind (e->ts.type, e->ts.kind);
    6244         2296 :           break;
    6245         3410 :         case BT_CHARACTER:
    6246         3410 :           itype = CFI_type_from_type_kind (CFI_type_Character, e->ts.kind);
    6247         3410 :           break;
    6248              :         case BT_DERIVED:
    6249         6537 :           itype = CFI_type_struct;
    6250              :           break;
    6251            0 :         case BT_VOID:
    6252            0 :           itype = (e->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR
    6253            0 :                    ? CFI_type_cfunptr : CFI_type_cptr);
    6254              :           break;
    6255              :         case BT_ASSUMED:
    6256              :           itype = CFI_type_other;  // FIXME: Or CFI_type_cptr ?
    6257              :           break;
    6258            1 :         case BT_CLASS:
    6259            1 :           if (fsym->ts.type == BT_ASSUMED)
    6260              :             {
    6261              :               // F2017: 7.3.2.2: "An entity that is declared using the TYPE(*)
    6262              :               // type specifier is assumed-type and is an unlimited polymorphic
    6263              :               //  entity." The actual argument _data component is passed.
    6264              :               itype = CFI_type_other;  // FIXME: Or CFI_type_cptr ?
    6265              :               break;
    6266              :             }
    6267              :           else
    6268            0 :             gcc_unreachable ();
    6269              : 
    6270            0 :         case BT_UNSIGNED:
    6271            0 :           gfc_internal_error ("Unsigned not yet implemented");
    6272              : 
    6273            0 :         case BT_PROCEDURE:
    6274            0 :         case BT_HOLLERITH:
    6275            0 :         case BT_UNION:
    6276            0 :         case BT_BOZ:
    6277            0 :         case BT_UNKNOWN:
    6278              :           // FIXME: Really unreachable? Or reachable for type(*) ? If so, CFI_type_other?
    6279            0 :           gcc_unreachable ();
    6280              :         }
    6281              :     }
    6282              : 
    6283         6537 :   tmp = gfc_get_cfi_desc_type (cfi);
    6284         6537 :   gfc_add_modify (&block, tmp,
    6285         6537 :                   build_int_cst (TREE_TYPE (tmp), itype));
    6286              : 
    6287         6537 :   int attr = CFI_attribute_other;
    6288         6537 :   if (fsym->attr.pointer)
    6289              :     attr = CFI_attribute_pointer;
    6290         5774 :   else if (fsym->attr.allocatable)
    6291          433 :     attr = CFI_attribute_allocatable;
    6292         6537 :   tmp = gfc_get_cfi_desc_attribute (cfi);
    6293         6537 :   gfc_add_modify (&block, tmp,
    6294         6537 :                   build_int_cst (TREE_TYPE (tmp), attr));
    6295              : 
    6296              :   /* The cfi-base_addr assignment could be skipped for 'pointer, intent(out)'.
    6297              :      That is very sensible for undefined pointers, but the C code might assume
    6298              :      that the pointer retains the value, in particular, if it was NULL.  */
    6299         6537 :   if (e->rank == 0)
    6300              :     {
    6301          687 :       tmp = gfc_get_cfi_desc_base_addr (cfi);
    6302          687 :       gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), gfc));
    6303              :     }
    6304              :   else
    6305              :     {
    6306         5850 :       tmp = gfc_get_cfi_desc_base_addr (cfi);
    6307         5850 :       tmp2 = gfc_conv_descriptor_data_get (gfc);
    6308         5850 :       gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), tmp2));
    6309              :     }
    6310              : 
    6311              :   /* Set elem_len if known - must be before the next if block.
    6312              :      Note that allocatable implies 'len=:'.  */
    6313         6537 :   if (e->ts.type != BT_ASSUMED && e->ts.type != BT_CHARACTER )
    6314              :     {
    6315              :       /* Length is known at compile time; use 'block' for it.  */
    6316         3073 :       tmp = size_in_bytes (gfc_typenode_for_spec (&e->ts));
    6317         3073 :       tmp2 = gfc_get_cfi_desc_elem_len (cfi);
    6318         3073 :       gfc_add_modify (&block, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
    6319              :     }
    6320              : 
    6321         6537 :   if (fsym->attr.pointer && fsym->attr.intent == INTENT_OUT)
    6322           91 :     goto done;
    6323              : 
    6324              :   /* When allocatable + intent out, free the cfi descriptor.  */
    6325         6446 :   if (fsym->attr.allocatable && fsym->attr.intent == INTENT_OUT)
    6326              :     {
    6327           90 :       tmp = gfc_get_cfi_desc_base_addr (cfi);
    6328           90 :       tree call = builtin_decl_explicit (BUILT_IN_FREE);
    6329           90 :       call = build_call_expr_loc (input_location, call, 1, tmp);
    6330           90 :       gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
    6331           90 :       gfc_add_modify (&block, tmp,
    6332           90 :                       fold_convert (TREE_TYPE (tmp), null_pointer_node));
    6333           90 :       goto done;
    6334              :     }
    6335              : 
    6336              :   /* If not unallocated/unassociated. */
    6337         6356 :   gfc_init_block (&block2);
    6338              : 
    6339              :   /* Set elem_len, which may be only known at run time. */
    6340         6356 :   if (e->ts.type == BT_CHARACTER
    6341         3410 :       && (e->expr_type != EXPR_NULL || gfc_strlen != NULL_TREE))
    6342              :     {
    6343         3408 :       gcc_assert (gfc_strlen);
    6344         3409 :       tmp = gfc_strlen;
    6345         3409 :       if (e->ts.kind != 1)
    6346         1117 :         tmp = fold_build2_loc (input_location, MULT_EXPR,
    6347              :                                gfc_charlen_type_node, tmp,
    6348              :                                build_int_cst (gfc_charlen_type_node,
    6349         1117 :                                               e->ts.kind));
    6350         3409 :       tmp2 = gfc_get_cfi_desc_elem_len (cfi);
    6351         3409 :       gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
    6352              :     }
    6353         2947 :   else if (e->ts.type == BT_ASSUMED)
    6354              :     {
    6355           54 :       tmp = gfc_conv_descriptor_elem_len (gfc);
    6356           54 :       tmp2 = gfc_get_cfi_desc_elem_len (cfi);
    6357           54 :       gfc_add_modify (&block2, tmp2, fold_convert (TREE_TYPE (tmp2), tmp));
    6358              :     }
    6359              : 
    6360         6356 :   if (e->ts.type == BT_ASSUMED)
    6361              :     {
    6362              :       /* Note: type(*) implies assumed-shape/assumed-rank if fsym requires
    6363              :          an CFI descriptor.  Use the type in the descriptor as it provide
    6364              :          mode information. (Quality of implementation feature.)  */
    6365           54 :       tree cond;
    6366           54 :       tree ctype = gfc_get_cfi_desc_type (cfi);
    6367           54 :       tree type = fold_convert (TREE_TYPE (ctype),
    6368              :                                 gfc_conv_descriptor_type (gfc));
    6369           54 :       tree kind = fold_convert (TREE_TYPE (ctype),
    6370              :                                 gfc_conv_descriptor_elem_len (gfc));
    6371           54 :       kind = fold_build2_loc (input_location, LSHIFT_EXPR, TREE_TYPE (type),
    6372           54 :                               kind, build_int_cst (TREE_TYPE (type),
    6373              :                                                    CFI_type_kind_shift));
    6374              : 
    6375              :       /* if (BT_VOID) CFI_type_cptr else CFI_type_other  */
    6376              :       /* Note: BT_VOID is could also be CFI_type_funcptr, but assume c_ptr. */
    6377           54 :       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6378           54 :                               build_int_cst (TREE_TYPE (type), BT_VOID));
    6379           54 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
    6380           54 :                              build_int_cst (TREE_TYPE (type), CFI_type_cptr));
    6381           54 :       tmp2 = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    6382              :                               ctype,
    6383           54 :                               build_int_cst (TREE_TYPE (type), CFI_type_other));
    6384           54 :       tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    6385              :                               tmp, tmp2);
    6386              :       /* if (BT_DERIVED) CFI_type_struct else  < tmp2 >  */
    6387           54 :       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6388           54 :                               build_int_cst (TREE_TYPE (type), BT_DERIVED));
    6389           54 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, ctype,
    6390           54 :                              build_int_cst (TREE_TYPE (type), CFI_type_struct));
    6391           54 :       tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    6392              :                               tmp, tmp2);
    6393              :       /* if (BT_CHARACTER) CFI_type_Character + kind=1 else  < tmp2 >  */
    6394              :       /* Note: could also be kind=4, with cfi->elem_len = gfc->elem_len*4.  */
    6395           54 :       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6396           54 :                               build_int_cst (TREE_TYPE (type), BT_CHARACTER));
    6397           54 :       tmp = build_int_cst (TREE_TYPE (type),
    6398              :                            CFI_type_from_type_kind (CFI_type_Character, 1));
    6399           54 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    6400              :                              ctype, tmp);
    6401           54 :       tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    6402              :                               tmp, tmp2);
    6403              :       /* if (BT_COMPLEX) CFI_type_Complex + kind/2 else  < tmp2 >  */
    6404           54 :       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6405           54 :                               build_int_cst (TREE_TYPE (type), BT_COMPLEX));
    6406           54 :       tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (type),
    6407           54 :                              kind, build_int_cst (TREE_TYPE (type), 2));
    6408           54 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type), tmp,
    6409           54 :                              build_int_cst (TREE_TYPE (type),
    6410              :                                             CFI_type_Complex));
    6411           54 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    6412              :                              ctype, tmp);
    6413           54 :       tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    6414              :                               tmp, tmp2);
    6415              :       /* if (BT_INTEGER || BT_LOGICAL || BT_REAL) type + kind else  <tmp2>  */
    6416           54 :       cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6417           54 :                               build_int_cst (TREE_TYPE (type), BT_INTEGER));
    6418           54 :       tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6419           54 :                               build_int_cst (TREE_TYPE (type), BT_LOGICAL));
    6420           54 :       cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
    6421              :                               cond, tmp);
    6422           54 :       tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, type,
    6423           54 :                               build_int_cst (TREE_TYPE (type), BT_REAL));
    6424           54 :       cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, boolean_type_node,
    6425              :                               cond, tmp);
    6426           54 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (type),
    6427              :                              type, kind);
    6428           54 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
    6429              :                              ctype, tmp);
    6430           54 :       tmp2 = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    6431              :                               tmp, tmp2);
    6432           54 :       gfc_add_expr_to_block (&block2, tmp2);
    6433              :     }
    6434              : 
    6435         6356 :   if (e->rank != 0)
    6436              :     {
    6437              :       /* Loop: for (i = 0; i < rank; ++i).  */
    6438         5735 :       tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
    6439              :       /* Loop body.  */
    6440         5735 :       stmtblock_t loop_body;
    6441         5735 :       gfc_init_block (&loop_body);
    6442              :       /* cfi->dim[i].lower_bound = (allocatable/pointer)
    6443              :                                    ? gfc->dim[i].lbound : 0 */
    6444         5735 :       if (fsym->attr.pointer || fsym->attr.allocatable)
    6445          648 :         tmp = gfc_conv_descriptor_lbound_get (gfc, idx);
    6446              :       else
    6447         5087 :         tmp = gfc_index_zero_node;
    6448         5735 :       gfc_add_modify (&loop_body, gfc_get_cfi_dim_lbound (cfi, idx), tmp);
    6449              :       /* cfi->dim[i].extent = gfc->dim[i].ubound - gfc->dim[i].lbound + 1.  */
    6450         5735 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    6451              :                              gfc_conv_descriptor_ubound_get (gfc, idx),
    6452              :                              gfc_conv_descriptor_lbound_get (gfc, idx));
    6453         5735 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    6454              :                              tmp, gfc_index_one_node);
    6455         5735 :       gfc_add_modify (&loop_body, gfc_get_cfi_dim_extent (cfi, idx), tmp);
    6456              :       /* d->dim[n].sm = gfc->dim[i].stride  * gfc->span); */
    6457         5735 :       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    6458              :                              gfc_conv_descriptor_stride_get (gfc, idx),
    6459              :                              gfc_conv_descriptor_span_get (gfc));
    6460         5735 :       gfc_add_modify (&loop_body, gfc_get_cfi_dim_sm (cfi, idx), tmp);
    6461              : 
    6462              :       /* Generate loop.  */
    6463        11470 :       gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
    6464         5735 :                            rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
    6465              :                            gfc_finish_block (&loop_body));
    6466              : 
    6467         5735 :       if (e->expr_type == EXPR_VARIABLE
    6468         5573 :           && e->ref
    6469         5573 :           && e->ref->u.ar.type == AR_FULL
    6470         2732 :           && e->symtree->n.sym->attr.dummy
    6471          988 :           && e->symtree->n.sym->as
    6472          988 :           && e->symtree->n.sym->as->type == AS_ASSUMED_SIZE)
    6473              :         {
    6474          138 :           tmp = gfc_get_cfi_dim_extent (cfi, gfc_rank_cst[e->rank-1]),
    6475          138 :           gfc_add_modify (&block2, tmp, build_int_cst (TREE_TYPE (tmp), -1));
    6476              :         }
    6477              :     }
    6478              : 
    6479         6356 :   if (fsym->attr.allocatable || fsym->attr.pointer)
    6480              :     {
    6481         1015 :       tmp = gfc_get_cfi_desc_base_addr (cfi),
    6482         1015 :       tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    6483              :                              tmp, null_pointer_node);
    6484         1015 :       tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
    6485              :                       build_empty_stmt (input_location));
    6486         1015 :       gfc_add_expr_to_block (&block, tmp);
    6487              :     }
    6488              :   else
    6489         5341 :     gfc_add_block_to_block (&block, &block2);
    6490              : 
    6491              : 
    6492         6537 : done:
    6493         6537 :   if (present)
    6494              :     {
    6495          103 :       parmse->expr = build3_loc (input_location, COND_EXPR,
    6496          103 :                                  TREE_TYPE (parmse->expr),
    6497              :                                  present, parmse->expr, null_pointer_node);
    6498          103 :       tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
    6499              :                       build_empty_stmt (input_location));
    6500          103 :       gfc_add_expr_to_block (&parmse->pre, tmp);
    6501              :     }
    6502              :   else
    6503         6434 :     gfc_add_block_to_block (&parmse->pre, &block);
    6504              : 
    6505         6537 :   gfc_init_block (&block);
    6506              : 
    6507         6537 :   if ((!fsym->attr.allocatable && !fsym->attr.pointer)
    6508         1196 :       || fsym->attr.intent == INTENT_IN)
    6509         5550 :     goto post_call;
    6510              : 
    6511          987 :   gfc_init_block (&block2);
    6512          987 :   if (e->rank == 0)
    6513              :     {
    6514          428 :       tmp = gfc_get_cfi_desc_base_addr (cfi);
    6515          428 :       gfc_add_modify (&block, gfc, fold_convert (TREE_TYPE (gfc), tmp));
    6516              :     }
    6517              :   else
    6518              :     {
    6519          559 :       tmp = gfc_get_cfi_desc_base_addr (cfi);
    6520          559 :       gfc_conv_descriptor_data_set (&block, gfc, tmp);
    6521              : 
    6522          559 :       if (fsym->attr.allocatable)
    6523              :         {
    6524              :           /* gfc->span = cfi->elem_len.  */
    6525          252 :           tmp = fold_convert (gfc_array_index_type,
    6526              :                               gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]));
    6527              :         }
    6528              :       else
    6529              :         {
    6530              :           /* gfc->span = ((cfi->dim[0].sm % cfi->elem_len)
    6531              :                           ? cfi->dim[0].sm : cfi->elem_len).  */
    6532          307 :           tmp = gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]);
    6533          307 :           tmp2 = fold_convert (gfc_array_index_type,
    6534              :                                gfc_get_cfi_desc_elem_len (cfi));
    6535          307 :           tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
    6536              :                                  gfc_array_index_type, tmp, tmp2);
    6537          307 :           tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    6538              :                              tmp, gfc_index_zero_node);
    6539          307 :           tmp = build3_loc (input_location, COND_EXPR, gfc_array_index_type, tmp,
    6540              :                             gfc_get_cfi_dim_sm (cfi, gfc_rank_cst[0]), tmp2);
    6541              :         }
    6542          559 :       gfc_conv_descriptor_span_set (&block2, gfc, tmp);
    6543              : 
    6544              :       /* Calculate offset + set lbound, ubound and stride.  */
    6545          559 :       gfc_conv_descriptor_offset_set (&block2, gfc, gfc_index_zero_node);
    6546              :       /* Loop: for (i = 0; i < rank; ++i).  */
    6547          559 :       tree idx = gfc_create_var (TREE_TYPE (rank), "idx");
    6548              :       /* Loop body.  */
    6549          559 :       stmtblock_t loop_body;
    6550          559 :       gfc_init_block (&loop_body);
    6551              :       /* gfc->dim[i].lbound = ... */
    6552          559 :       tmp = gfc_get_cfi_dim_lbound (cfi, idx);
    6553          559 :       gfc_conv_descriptor_lbound_set (&loop_body, gfc, idx, tmp);
    6554              : 
    6555              :       /* gfc->dim[i].ubound = gfc->dim[i].lbound + cfi->dim[i].extent - 1. */
    6556          559 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    6557              :                              gfc_conv_descriptor_lbound_get (gfc, idx),
    6558              :                              gfc_index_one_node);
    6559          559 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    6560              :                              gfc_get_cfi_dim_extent (cfi, idx), tmp);
    6561          559 :       gfc_conv_descriptor_ubound_set (&loop_body, gfc, idx, tmp);
    6562              : 
    6563              :       /* gfc->dim[i].stride = cfi->dim[i].sm / cfi>elem_len */
    6564          559 :       tmp = gfc_get_cfi_dim_sm (cfi, idx);
    6565          559 :       tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
    6566              :                              gfc_array_index_type, tmp,
    6567              :                              fold_convert (gfc_array_index_type,
    6568              :                                            gfc_get_cfi_desc_elem_len (cfi)));
    6569          559 :       gfc_conv_descriptor_stride_set (&loop_body, gfc, idx, tmp);
    6570              : 
    6571              :       /* gfc->offset -= gfc->dim[i].stride * gfc->dim[i].lbound. */
    6572          559 :       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    6573              :                              gfc_conv_descriptor_stride_get (gfc, idx),
    6574              :                              gfc_conv_descriptor_lbound_get (gfc, idx));
    6575          559 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    6576              :                              gfc_conv_descriptor_offset_get (gfc), tmp);
    6577          559 :       gfc_conv_descriptor_offset_set (&loop_body, gfc, tmp);
    6578              :       /* Generate loop.  */
    6579         1118 :       gfc_simple_for_loop (&block2, idx, build_int_cst (TREE_TYPE (idx), 0),
    6580          559 :                            rank, LT_EXPR, build_int_cst (TREE_TYPE (idx), 1),
    6581              :                            gfc_finish_block (&loop_body));
    6582              :     }
    6583              : 
    6584          987 :   if (e->ts.type == BT_CHARACTER && !e->ts.u.cl->length)
    6585              :     {
    6586           60 :       tmp = fold_convert (gfc_charlen_type_node,
    6587              :                           gfc_get_cfi_desc_elem_len (cfi));
    6588           60 :       if (e->ts.kind != 1)
    6589           24 :         tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
    6590              :                                gfc_charlen_type_node, tmp,
    6591              :                                build_int_cst (gfc_charlen_type_node,
    6592           24 :                                               e->ts.kind));
    6593           60 :       gfc_add_modify (&block2, gfc_strlen, tmp);
    6594              :     }
    6595              : 
    6596          987 :   tmp = gfc_get_cfi_desc_base_addr (cfi),
    6597          987 :   tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
    6598              :                          tmp, null_pointer_node);
    6599          987 :   tmp = build3_v (COND_EXPR, tmp, gfc_finish_block (&block2),
    6600              :                   build_empty_stmt (input_location));
    6601          987 :   gfc_add_expr_to_block (&block, tmp);
    6602              : 
    6603         6537 : post_call:
    6604         6537 :   gfc_add_block_to_block (&block, &se.post);
    6605         6537 :   if (present && block.head)
    6606              :     {
    6607            6 :       tmp = build3_v (COND_EXPR, present, gfc_finish_block (&block),
    6608              :                       build_empty_stmt (input_location));
    6609            6 :       gfc_add_expr_to_block (&parmse->post, tmp);
    6610              :     }
    6611         6531 :   else if (block.head)
    6612         1564 :     gfc_add_block_to_block (&parmse->post, &block);
    6613         6537 : }
    6614              : 
    6615              : 
    6616              : /* Create "conditional temporary" to handle scalar dummy variables with the
    6617              :    OPTIONAL+VALUE attribute that shall not be dereferenced.  Use null value
    6618              :    as fallback.  Does not handle CLASS.  */
    6619              : 
    6620              : static void
    6621          234 : conv_cond_temp (gfc_se * parmse, gfc_expr * e, tree cond)
    6622              : {
    6623          234 :   tree temp;
    6624          234 :   gcc_assert (e && e->ts.type != BT_CLASS);
    6625          234 :   gcc_assert (e->rank == 0);
    6626          234 :   temp = gfc_create_var (TREE_TYPE (parmse->expr), "condtemp");
    6627          234 :   TREE_STATIC (temp) = 1;
    6628          234 :   TREE_CONSTANT (temp) = 1;
    6629          234 :   TREE_READONLY (temp) = 1;
    6630          234 :   DECL_INITIAL (temp) = build_zero_cst (TREE_TYPE (temp));
    6631          234 :   parmse->expr = fold_build3_loc (input_location, COND_EXPR,
    6632          234 :                                   TREE_TYPE (parmse->expr),
    6633              :                                   cond, parmse->expr, temp);
    6634          234 :   parmse->expr = gfc_evaluate_now (parmse->expr, &parmse->pre);
    6635          234 : }
    6636              : 
    6637              : 
    6638              : /* Returns true if the type specified in TS is a character type whose length
    6639              :    is constant.  Otherwise returns false.  */
    6640              : 
    6641              : static bool
    6642        21968 : gfc_const_length_character_type_p (gfc_typespec *ts)
    6643              : {
    6644        21968 :   return (ts->type == BT_CHARACTER
    6645          467 :           && ts->u.cl
    6646          467 :           && ts->u.cl->length
    6647          467 :           && ts->u.cl->length->expr_type == EXPR_CONSTANT
    6648        22435 :           && ts->u.cl->length->ts.type == BT_INTEGER);
    6649              : }
    6650              : 
    6651              : 
    6652              : /* Helper function for the handling of (currently) scalar dummy variables
    6653              :    with the VALUE attribute.  Argument parmse should already be set up.  */
    6654              : static void
    6655        22401 : conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym,
    6656              :                   vec<tree, va_gc> *& optionalargs)
    6657              : {
    6658        22401 :   tree tmp;
    6659              : 
    6660        22401 :   gcc_assert (fsym && fsym->attr.value && !fsym->attr.dimension);
    6661              : 
    6662        22401 :   if (IS_PDT (e))
    6663              :     {
    6664            6 :       tmp = gfc_create_var (TREE_TYPE (parmse->expr), "PDT");
    6665            6 :       gfc_add_modify (&parmse->pre, tmp, parmse->expr);
    6666            6 :       gfc_add_expr_to_block (&parmse->pre,
    6667            6 :                              gfc_copy_alloc_comp (e->ts.u.derived,
    6668              :                                                   parmse->expr, tmp,
    6669              :                                                   e->rank, 0));
    6670            6 :       parmse->expr = tmp;
    6671            6 :       tmp = gfc_deallocate_pdt_comp (e->ts.u.derived, tmp, e->rank);
    6672            6 :       gfc_add_expr_to_block (&parmse->post, tmp);
    6673            6 :       return;
    6674              :     }
    6675              : 
    6676              :   /* Absent actual argument for optional scalar dummy.  */
    6677        22395 :   if ((e == NULL || e->expr_type == EXPR_NULL) && fsym->attr.optional)
    6678              :     {
    6679              :       /* For scalar arguments with VALUE attribute which are passed by
    6680              :          value, pass "0" and a hidden argument for the optional status.  */
    6681          427 :       if (fsym->ts.type == BT_CHARACTER)
    6682              :         {
    6683              :           /* Pass a NULL pointer for an absent CHARACTER arg and a length of
    6684              :              zero.  */
    6685           90 :           parmse->expr = null_pointer_node;
    6686           90 :           parmse->string_length = build_int_cst (gfc_charlen_type_node, 0);
    6687              :         }
    6688          337 :       else if (gfc_bt_struct (fsym->ts.type)
    6689           30 :                && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING))
    6690              :         {
    6691              :           /* Pass null struct.  Types c_ptr and c_funptr from ISO_C_BINDING
    6692              :              are pointers and passed as such below.  */
    6693           24 :           tree temp = gfc_create_var (gfc_sym_type (fsym), "absent");
    6694           24 :           TREE_CONSTANT (temp) = 1;
    6695           24 :           TREE_READONLY (temp) = 1;
    6696           24 :           DECL_INITIAL (temp) = build_zero_cst (TREE_TYPE (temp));
    6697           24 :           parmse->expr = temp;
    6698           24 :         }
    6699              :       else
    6700          313 :         parmse->expr = fold_convert (gfc_sym_type (fsym),
    6701              :                                      integer_zero_node);
    6702          427 :       vec_safe_push (optionalargs, boolean_false_node);
    6703              : 
    6704          427 :       return;
    6705              :     }
    6706              : 
    6707              :   /* Truncate a too long constant character actual argument.  */
    6708        21968 :   if (gfc_const_length_character_type_p (&fsym->ts)
    6709          467 :       && e->expr_type == EXPR_CONSTANT
    6710        22051 :       && mpz_cmp_ui (fsym->ts.u.cl->length->value.integer,
    6711              :                      e->value.character.length) < 0)
    6712              :     {
    6713           17 :       gfc_charlen_t flen = mpz_get_ui (fsym->ts.u.cl->length->value.integer);
    6714              : 
    6715              :       /* Truncate actual string argument.  */
    6716           17 :       gfc_conv_expr (parmse, e);
    6717           34 :       parmse->expr = gfc_build_wide_string_const (e->ts.kind, flen,
    6718           17 :                                                   e->value.character.string);
    6719           17 :       parmse->string_length = build_int_cst (gfc_charlen_type_node, flen);
    6720              : 
    6721           17 :       if (flen == 1)
    6722              :         {
    6723           14 :           tree slen1 = build_int_cst (gfc_charlen_type_node, 1);
    6724           14 :           gfc_conv_string_parameter (parmse);
    6725           14 :           parmse->expr = gfc_string_to_single_character (slen1, parmse->expr,
    6726              :                                                          e->ts.kind);
    6727              :         }
    6728              : 
    6729              :       /* Indicate value,optional scalar dummy argument as present.  */
    6730           17 :       if (fsym->attr.optional)
    6731            1 :         vec_safe_push (optionalargs, boolean_true_node);
    6732           17 :       return;
    6733              :     }
    6734              : 
    6735              :   /* gfortran argument passing conventions:
    6736              :      actual arguments to CHARACTER(len=1),VALUE
    6737              :      dummy arguments are actually passed by value.
    6738              :      Strings are truncated to length 1.  */
    6739        21951 :   if (gfc_length_one_character_type_p (&fsym->ts))
    6740              :     {
    6741          378 :       if (e->expr_type == EXPR_CONSTANT
    6742           54 :           && e->value.character.length > 1)
    6743              :         {
    6744            0 :           e->value.character.length = 1;
    6745            0 :           gfc_conv_expr (parmse, e);
    6746              :         }
    6747              : 
    6748          378 :       tree slen1 = build_int_cst (gfc_charlen_type_node, 1);
    6749          378 :       gfc_conv_string_parameter (parmse);
    6750          378 :       parmse->expr = gfc_string_to_single_character (slen1, parmse->expr,
    6751              :                                                      e->ts.kind);
    6752              :       /* Truncate resulting string to length 1.  */
    6753          378 :       parmse->string_length = slen1;
    6754              :     }
    6755              : 
    6756        21951 :   if (fsym->attr.optional && fsym->ts.type != BT_CLASS)
    6757              :     {
    6758              :       /* F2018:15.5.2.12 Argument presence and
    6759              :          restrictions on arguments not present.  */
    6760          823 :       if (e->expr_type == EXPR_VARIABLE
    6761          650 :           && e->rank == 0
    6762         1419 :           && (gfc_expr_attr (e).allocatable
    6763          482 :               || gfc_expr_attr (e).pointer))
    6764              :         {
    6765          198 :           gfc_se argse;
    6766          198 :           tree cond;
    6767          198 :           gfc_init_se (&argse, NULL);
    6768          198 :           argse.want_pointer = 1;
    6769          198 :           gfc_conv_expr (&argse, e);
    6770          198 :           cond = fold_convert (TREE_TYPE (argse.expr), null_pointer_node);
    6771          198 :           cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    6772              :                                   argse.expr, cond);
    6773          198 :           if (e->symtree->n.sym->attr.dummy)
    6774           24 :             cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    6775              :                                     logical_type_node,
    6776              :                                     gfc_conv_expr_present (e->symtree->n.sym),
    6777              :                                     cond);
    6778          198 :           vec_safe_push (optionalargs, fold_convert (boolean_type_node, cond));
    6779              :           /* Create "conditional temporary".  */
    6780          198 :           conv_cond_temp (parmse, e, cond);
    6781              :         }
    6782          625 :       else if (e->expr_type != EXPR_VARIABLE
    6783          452 :                || !e->symtree->n.sym->attr.optional
    6784          260 :                || (e->ref != NULL && e->ref->type != REF_ARRAY))
    6785          365 :         vec_safe_push (optionalargs, boolean_true_node);
    6786              :       else
    6787              :         {
    6788          260 :           tmp = gfc_conv_expr_present (e->symtree->n.sym);
    6789          260 :           if (gfc_bt_struct (fsym->ts.type)
    6790           36 :               && !(fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING))
    6791           36 :             conv_cond_temp (parmse, e, tmp);
    6792          224 :           else if (e->ts.type != BT_CHARACTER && !e->symtree->n.sym->attr.value)
    6793           84 :             parmse->expr
    6794          168 :               = fold_build3_loc (input_location, COND_EXPR,
    6795           84 :                                  TREE_TYPE (parmse->expr),
    6796              :                                  tmp, parmse->expr,
    6797           84 :                                  fold_convert (TREE_TYPE (parmse->expr),
    6798              :                                                integer_zero_node));
    6799              : 
    6800          520 :           vec_safe_push (optionalargs,
    6801          260 :                          fold_convert (boolean_type_node, tmp));
    6802              :         }
    6803              :     }
    6804              : }
    6805              : 
    6806              : 
    6807              : /* Helper function for the handling of NULL() actual arguments associated with
    6808              :    non-optional dummy variables.  Argument parmse should already be set up.  */
    6809              : static void
    6810          426 : conv_null_actual (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym)
    6811              : {
    6812          426 :   gcc_assert (fsym && e->expr_type == EXPR_NULL);
    6813              : 
    6814              :   /* Obtain the character length for a NULL() actual with a character
    6815              :      MOLD argument.  Otherwise substitute a suitable dummy length.
    6816              :      Here we handle only non-optional dummies of non-bind(c) procedures.  */
    6817          426 :   if (fsym->ts.type == BT_CHARACTER)
    6818              :     {
    6819          216 :       if (e->ts.type == BT_CHARACTER
    6820          162 :           && e->symtree->n.sym->ts.type == BT_CHARACTER)
    6821              :         {
    6822              :           /* MOLD is present.  Substitute a temporary character NULL pointer.
    6823              :              For an assumed-rank dummy we need a descriptor that passes the
    6824              :              correct rank.  */
    6825          162 :           if (fsym->as && fsym->as->type == AS_ASSUMED_RANK)
    6826              :             {
    6827           54 :               tree rank;
    6828           54 :               tree tmp = parmse->expr;
    6829           54 :               tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr);
    6830           54 :               rank = gfc_conv_descriptor_rank (tmp);
    6831           54 :               gfc_add_modify (&parmse->pre, rank,
    6832           54 :                               build_int_cst (TREE_TYPE (rank), e->rank));
    6833           54 :               parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
    6834           54 :             }
    6835              :           else
    6836              :             {
    6837          108 :               tree tmp = gfc_create_var (TREE_TYPE (parmse->expr), "null");
    6838          108 :               gfc_add_modify (&parmse->pre, tmp,
    6839          108 :                               build_zero_cst (TREE_TYPE (tmp)));
    6840          108 :               parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
    6841              :             }
    6842              : 
    6843              :           /* Ensure that a usable length is available.  */
    6844          162 :           if (parmse->string_length == NULL_TREE)
    6845              :             {
    6846          162 :               gfc_typespec *ts = &e->symtree->n.sym->ts;
    6847              : 
    6848          162 :               if (ts->u.cl->length != NULL
    6849          108 :                   && ts->u.cl->length->expr_type == EXPR_CONSTANT)
    6850          108 :                 gfc_conv_const_charlen (ts->u.cl);
    6851              : 
    6852          162 :               if (ts->u.cl->backend_decl)
    6853          162 :                 parmse->string_length = ts->u.cl->backend_decl;
    6854              :             }
    6855              :         }
    6856           54 :       else if (e->ts.type == BT_UNKNOWN && parmse->string_length == NULL_TREE)
    6857              :         {
    6858              :           /* MOLD is not present.  Pass length of associated dummy character
    6859              :              argument if constant, or zero.  */
    6860           54 :           if (fsym->ts.u.cl->length != NULL
    6861           18 :               && fsym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
    6862              :             {
    6863           18 :               gfc_conv_const_charlen (fsym->ts.u.cl);
    6864           18 :               parmse->string_length = fsym->ts.u.cl->backend_decl;
    6865              :             }
    6866              :           else
    6867              :             {
    6868           36 :               parmse->string_length = gfc_create_var (gfc_charlen_type_node,
    6869              :                                                       "slen");
    6870           36 :               gfc_add_modify (&parmse->pre, parmse->string_length,
    6871              :                               build_zero_cst (gfc_charlen_type_node));
    6872              :             }
    6873              :         }
    6874              :     }
    6875          210 :   else if (fsym->ts.type == BT_DERIVED)
    6876              :     {
    6877          210 :       if (e->ts.type != BT_UNKNOWN)
    6878              :         /* MOLD is present.  Pass a corresponding temporary NULL pointer.
    6879              :            For an assumed-rank dummy we provide a descriptor that passes
    6880              :            the correct rank.  */
    6881              :         {
    6882          138 :           tree rank;
    6883          138 :           tree tmp = parmse->expr;
    6884              : 
    6885          138 :           tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, gfc_expr_attr (e));
    6886          138 :           rank = gfc_conv_descriptor_rank (tmp);
    6887          138 :           gfc_add_modify (&parmse->pre, rank,
    6888          138 :                           build_int_cst (TREE_TYPE (rank), e->rank));
    6889          138 :           gfc_conv_descriptor_data_set (&parmse->pre, tmp, null_pointer_node);
    6890          138 :           parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
    6891              :         }
    6892              :       else
    6893              :         /* MOLD is not present.  Use attributes from dummy argument, which is
    6894              :            not allowed to be assumed-rank.  */
    6895              :         {
    6896           72 :           int dummy_rank;
    6897           72 :           tree tmp = parmse->expr;
    6898              : 
    6899           72 :           if ((fsym->attr.allocatable || fsym->attr.pointer)
    6900           72 :               && fsym->attr.intent == INTENT_UNKNOWN)
    6901           36 :             fsym->attr.intent = INTENT_IN;
    6902           72 :           tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr);
    6903           72 :           dummy_rank = fsym->as ? fsym->as->rank : 0;
    6904           24 :           if (dummy_rank > 0)
    6905              :             {
    6906           24 :               tree rank = gfc_conv_descriptor_rank (tmp);
    6907           24 :               gfc_add_modify (&parmse->pre, rank,
    6908           24 :                               build_int_cst (TREE_TYPE (rank), dummy_rank));
    6909              :             }
    6910           72 :           gfc_conv_descriptor_data_set (&parmse->pre, tmp, null_pointer_node);
    6911           72 :           parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
    6912              :         }
    6913              :     }
    6914          426 : }
    6915              : 
    6916              : 
    6917              : /* Generate code for a procedure call.  Note can return se->post != NULL.
    6918              :    If se->direct_byref is set then se->expr contains the return parameter.
    6919              :    Return nonzero, if the call has alternate specifiers.
    6920              :    'expr' is only needed for procedure pointer components.  */
    6921              : 
    6922              : int
    6923       134882 : gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
    6924              :                          gfc_actual_arglist * args, gfc_expr * expr,
    6925              :                          vec<tree, va_gc> *append_args)
    6926              : {
    6927       134882 :   gfc_interface_mapping mapping;
    6928       134882 :   vec<tree, va_gc> *arglist;
    6929       134882 :   vec<tree, va_gc> *retargs;
    6930       134882 :   tree tmp;
    6931       134882 :   tree fntype;
    6932       134882 :   gfc_se parmse;
    6933       134882 :   gfc_array_info *info;
    6934       134882 :   int byref;
    6935       134882 :   int parm_kind;
    6936       134882 :   tree type;
    6937       134882 :   tree var;
    6938       134882 :   tree len;
    6939       134882 :   tree base_object;
    6940       134882 :   vec<tree, va_gc> *stringargs;
    6941       134882 :   vec<tree, va_gc> *optionalargs;
    6942       134882 :   tree result = NULL;
    6943       134882 :   gfc_formal_arglist *formal;
    6944       134882 :   gfc_actual_arglist *arg;
    6945       134882 :   int has_alternate_specifier = 0;
    6946       134882 :   bool need_interface_mapping;
    6947       134882 :   bool is_builtin;
    6948       134882 :   bool callee_alloc;
    6949       134882 :   bool ulim_copy;
    6950       134882 :   gfc_typespec ts;
    6951       134882 :   gfc_charlen cl;
    6952       134882 :   gfc_expr *e;
    6953       134882 :   gfc_symbol *fsym;
    6954       134882 :   enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY};
    6955       134882 :   gfc_component *comp = NULL;
    6956       134882 :   int arglen;
    6957       134882 :   unsigned int argc;
    6958       134882 :   tree arg1_cntnr = NULL_TREE;
    6959       134882 :   arglist = NULL;
    6960       134882 :   retargs = NULL;
    6961       134882 :   stringargs = NULL;
    6962       134882 :   optionalargs = NULL;
    6963       134882 :   var = NULL_TREE;
    6964       134882 :   len = NULL_TREE;
    6965       134882 :   gfc_clear_ts (&ts);
    6966       134882 :   gfc_intrinsic_sym *isym = expr && expr->rank ?
    6967              :                             expr->value.function.isym : NULL;
    6968              : 
    6969       134882 :   comp = gfc_get_proc_ptr_comp (expr);
    6970              : 
    6971       269764 :   bool elemental_proc = (comp
    6972         2023 :                          && comp->ts.interface
    6973         1969 :                          && comp->ts.interface->attr.elemental)
    6974         1830 :                         || (comp && comp->attr.elemental)
    6975       136712 :                         || sym->attr.elemental;
    6976              : 
    6977       134882 :   if (se->ss != NULL)
    6978              :     {
    6979        24659 :       if (!elemental_proc)
    6980              :         {
    6981        21334 :           gcc_assert (se->ss->info->type == GFC_SS_FUNCTION);
    6982        21334 :           if (se->ss->info->useflags)
    6983              :             {
    6984         5765 :               gcc_assert ((!comp && gfc_return_by_reference (sym)
    6985              :                            && sym->result->attr.dimension)
    6986              :                           || (comp && comp->attr.dimension)
    6987              :                           || gfc_is_class_array_function (expr));
    6988         5765 :               gcc_assert (se->loop != NULL);
    6989              :               /* Access the previously obtained result.  */
    6990         5765 :               gfc_conv_tmp_array_ref (se);
    6991         5765 :               return 0;
    6992              :             }
    6993              :         }
    6994        18894 :       info = &se->ss->info->data.array;
    6995              :     }
    6996              :   else
    6997              :     info = NULL;
    6998              : 
    6999       129117 :   stmtblock_t post, clobbers, dealloc_blk;
    7000       129117 :   gfc_init_block (&post);
    7001       129117 :   gfc_init_block (&clobbers);
    7002       129117 :   gfc_init_block (&dealloc_blk);
    7003       129117 :   gfc_init_interface_mapping (&mapping);
    7004       129117 :   if (!comp)
    7005              :     {
    7006       127143 :       formal = gfc_sym_get_dummy_args (sym);
    7007       127143 :       need_interface_mapping = sym->attr.dimension ||
    7008       111826 :                                (sym->ts.type == BT_CHARACTER
    7009         3118 :                                 && sym->ts.u.cl->length
    7010         2379 :                                 && sym->ts.u.cl->length->expr_type
    7011              :                                    != EXPR_CONSTANT);
    7012              :     }
    7013              :   else
    7014              :     {
    7015         1974 :       formal = comp->ts.interface ? comp->ts.interface->formal : NULL;
    7016         1974 :       need_interface_mapping = comp->attr.dimension ||
    7017         1905 :                                (comp->ts.type == BT_CHARACTER
    7018          229 :                                 && comp->ts.u.cl->length
    7019          220 :                                 && comp->ts.u.cl->length->expr_type
    7020              :                                    != EXPR_CONSTANT);
    7021              :     }
    7022              : 
    7023       129117 :   base_object = NULL_TREE;
    7024              :   /* For _vprt->_copy () routines no formal symbol is present.  Nevertheless
    7025              :      is the third and fourth argument to such a function call a value
    7026              :      denoting the number of elements to copy (i.e., most of the time the
    7027              :      length of a deferred length string).  */
    7028       258234 :   ulim_copy = (formal == NULL)
    7029        31584 :                && UNLIMITED_POLY (sym)
    7030       129197 :                && comp && (strcmp ("_copy", comp->name) == 0);
    7031              : 
    7032              :   /* Scan for allocatable actual arguments passed to allocatable dummy
    7033              :      arguments with INTENT(OUT).  As the corresponding actual arguments are
    7034              :      deallocated before execution of the procedure, we evaluate actual
    7035              :      argument expressions to avoid problems with possible dependencies.  */
    7036       129117 :   bool force_eval_args = false;
    7037       129117 :   gfc_formal_arglist *tmp_formal;
    7038       397303 :   for (arg = args, tmp_formal = formal; arg != NULL;
    7039       234895 :        arg = arg->next, tmp_formal = tmp_formal ? tmp_formal->next : NULL)
    7040              :     {
    7041       268686 :       e = arg->expr;
    7042       268686 :       fsym = tmp_formal ? tmp_formal->sym : NULL;
    7043       255312 :       if (e && fsym
    7044       223448 :           && e->expr_type == EXPR_VARIABLE
    7045        97812 :           && fsym->attr.intent == INTENT_OUT
    7046         6281 :           && (fsym->ts.type == BT_CLASS && fsym->attr.class_ok
    7047         6281 :               ? CLASS_DATA (fsym)->attr.allocatable
    7048         4753 :               : fsym->attr.allocatable)
    7049          500 :           && e->symtree
    7050          500 :           && e->symtree->n.sym
    7051       523998 :           && gfc_variable_attr (e, NULL).allocatable)
    7052              :         {
    7053              :           force_eval_args = true;
    7054              :           break;
    7055              :         }
    7056              :     }
    7057              : 
    7058              :   /* Evaluate the arguments.  */
    7059       398205 :   for (arg = args, argc = 0; arg != NULL;
    7060       269088 :        arg = arg->next, formal = formal ? formal->next : NULL, ++argc)
    7061              :     {
    7062       269088 :       bool finalized = false;
    7063       269088 :       tree derived_array = NULL_TREE;
    7064       269088 :       symbol_attribute *attr;
    7065              : 
    7066       269088 :       e = arg->expr;
    7067       269088 :       fsym = formal ? formal->sym : NULL;
    7068       504885 :       parm_kind = MISSING;
    7069              : 
    7070       235797 :       attr = fsym ? &(fsym->ts.type == BT_CLASS ? CLASS_DATA (fsym)->attr
    7071              :                                                 : fsym->attr)
    7072              :                   : nullptr;
    7073              :       /* If the procedure requires an explicit interface, the actual
    7074              :          argument is passed according to the corresponding formal
    7075              :          argument.  If the corresponding formal argument is a POINTER,
    7076              :          ALLOCATABLE or assumed shape, we do not use g77's calling
    7077              :          convention, and pass the address of the array descriptor
    7078              :          instead.  Otherwise we use g77's calling convention, in other words
    7079              :          pass the array data pointer without descriptor.  */
    7080       235744 :       bool nodesc_arg = fsym != NULL
    7081       235744 :                         && !(fsym->attr.pointer || fsym->attr.allocatable)
    7082       226697 :                         && fsym->as
    7083        40065 :                         && fsym->as->type != AS_ASSUMED_SHAPE
    7084        24626 :                         && fsym->as->type != AS_ASSUMED_RANK;
    7085       269088 :       if (comp)
    7086         2721 :         nodesc_arg = nodesc_arg || !comp->attr.always_explicit;
    7087              :       else
    7088       266367 :         nodesc_arg
    7089              :           = nodesc_arg
    7090       266367 :             || !(sym->attr.always_explicit || (attr && attr->codimension));
    7091              : 
    7092              :       /* Class array expressions are sometimes coming completely unadorned
    7093              :          with either arrayspec or _data component.  Correct that here.
    7094              :          OOP-TODO: Move this to the frontend.  */
    7095       269088 :       if (e && e->expr_type == EXPR_VARIABLE
    7096       111898 :             && !e->ref
    7097        51288 :             && e->ts.type == BT_CLASS
    7098         2603 :             && (CLASS_DATA (e)->attr.codimension
    7099         2603 :                 || CLASS_DATA (e)->attr.dimension))
    7100              :         {
    7101            0 :           gfc_typespec temp_ts = e->ts;
    7102            0 :           gfc_add_class_array_ref (e);
    7103            0 :           e->ts = temp_ts;
    7104              :         }
    7105              : 
    7106       269088 :       if (e == NULL
    7107       255708 :           || (e->expr_type == EXPR_NULL
    7108          745 :               && fsym
    7109          745 :               && fsym->attr.value
    7110           72 :               && fsym->attr.optional
    7111           72 :               && !fsym->attr.dimension
    7112           72 :               && fsym->ts.type != BT_CLASS))
    7113              :         {
    7114        13452 :           if (se->ignore_optional)
    7115              :             {
    7116              :               /* Some intrinsics have already been resolved to the correct
    7117              :                  parameters.  */
    7118          422 :               continue;
    7119              :             }
    7120        13254 :           else if (arg->label)
    7121              :             {
    7122          224 :               has_alternate_specifier = 1;
    7123          224 :               continue;
    7124              :             }
    7125              :           else
    7126              :             {
    7127        13030 :               gfc_init_se (&parmse, NULL);
    7128              : 
    7129              :               /* For scalar arguments with VALUE attribute which are passed by
    7130              :                  value, pass "0" and a hidden argument gives the optional
    7131              :                  status.  */
    7132        13030 :               if (fsym && fsym->attr.optional && fsym->attr.value
    7133          427 :                   && !fsym->attr.dimension && fsym->ts.type != BT_CLASS)
    7134              :                 {
    7135          427 :                   conv_dummy_value (&parmse, e, fsym, optionalargs);
    7136              :                 }
    7137              :               else
    7138              :                 {
    7139              :                   /* Pass a NULL pointer for an absent arg.  */
    7140        12603 :                   parmse.expr = null_pointer_node;
    7141              : 
    7142              :                   /* Is it an absent character dummy?  */
    7143        12603 :                   bool absent_char = false;
    7144        12603 :                   gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
    7145              : 
    7146              :                   /* Fall back to inferred type only if no formal.  */
    7147        12603 :                   if (fsym)
    7148        11545 :                     absent_char = (fsym->ts.type == BT_CHARACTER);
    7149         1058 :                   else if (dummy_arg)
    7150         1058 :                     absent_char = (gfc_dummy_arg_get_typespec (*dummy_arg).type
    7151              :                                    == BT_CHARACTER);
    7152        12603 :                   if (absent_char)
    7153         1115 :                     parmse.string_length = build_int_cst (gfc_charlen_type_node,
    7154              :                                                           0);
    7155              :                 }
    7156              :             }
    7157              :         }
    7158       255636 :       else if (e->expr_type == EXPR_NULL
    7159          673 :                && (e->ts.type == BT_UNKNOWN || e->ts.type == BT_DERIVED)
    7160          371 :                && fsym && attr && (attr->pointer || attr->allocatable)
    7161          293 :                && fsym->ts.type == BT_DERIVED)
    7162              :         {
    7163          210 :           gfc_init_se (&parmse, NULL);
    7164          210 :           gfc_conv_expr_reference (&parmse, e);
    7165          210 :           conv_null_actual (&parmse, e, fsym);
    7166              :         }
    7167       255426 :       else if (arg->expr->expr_type == EXPR_NULL
    7168          463 :                && fsym && !fsym->attr.pointer
    7169          163 :                && (fsym->ts.type != BT_CLASS
    7170            6 :                    || !CLASS_DATA (fsym)->attr.class_pointer))
    7171              :         {
    7172              :           /* Pass a NULL pointer to denote an absent arg.  */
    7173          163 :           gcc_assert (fsym->attr.optional && !fsym->attr.allocatable
    7174              :                       && (fsym->ts.type != BT_CLASS
    7175              :                           || !CLASS_DATA (fsym)->attr.allocatable));
    7176          163 :           gfc_init_se (&parmse, NULL);
    7177          163 :           parmse.expr = null_pointer_node;
    7178          163 :           if (fsym->ts.type == BT_CHARACTER)
    7179           42 :             parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
    7180              :         }
    7181       255263 :       else if (fsym && fsym->ts.type == BT_CLASS
    7182        10856 :                  && e->ts.type == BT_DERIVED)
    7183              :         {
    7184              :           /* The derived type needs to be converted to a temporary
    7185              :              CLASS object.  */
    7186         4373 :           gfc_init_se (&parmse, se);
    7187         4373 :           gfc_conv_derived_to_class (&parmse, e, fsym, NULL_TREE,
    7188         4373 :                                      fsym->attr.optional
    7189         1008 :                                        && e->expr_type == EXPR_VARIABLE
    7190         5381 :                                        && e->symtree->n.sym->attr.optional,
    7191         4373 :                                      CLASS_DATA (fsym)->attr.class_pointer
    7192         4373 :                                        || CLASS_DATA (fsym)->attr.allocatable,
    7193              :                                      sym->name, &derived_array);
    7194              :         }
    7195       219026 :       else if (UNLIMITED_POLY (fsym) && e->ts.type != BT_CLASS
    7196          906 :                && e->ts.type != BT_PROCEDURE
    7197          882 :                && (gfc_expr_attr (e).flavor != FL_PROCEDURE
    7198           12 :                    || gfc_expr_attr (e).proc != PROC_UNKNOWN))
    7199              :         {
    7200              :           /* The intrinsic type needs to be converted to a temporary
    7201              :              CLASS object for the unlimited polymorphic formal.  */
    7202          882 :           gfc_find_vtab (&e->ts);
    7203          882 :           gfc_init_se (&parmse, se);
    7204          882 :           gfc_conv_intrinsic_to_class (&parmse, e, fsym->ts);
    7205              : 
    7206              :         }
    7207       250008 :       else if (se->ss && se->ss->info->useflags)
    7208              :         {
    7209         5579 :           gfc_ss *ss;
    7210              : 
    7211         5579 :           ss = se->ss;
    7212              : 
    7213              :           /* An elemental function inside a scalarized loop.  */
    7214         5579 :           gfc_init_se (&parmse, se);
    7215         5579 :           parm_kind = ELEMENTAL;
    7216              : 
    7217              :           /* When no fsym is present, ulim_copy is set and this is a third or
    7218              :              fourth argument, use call-by-value instead of by reference to
    7219              :              hand the length properties to the copy routine (i.e., most of the
    7220              :              time this will be a call to a __copy_character_* routine where the
    7221              :              third and fourth arguments are the lengths of a deferred length
    7222              :              char array).  */
    7223         5579 :           if ((fsym && fsym->attr.value)
    7224         5345 :               || (ulim_copy && (argc == 2 || argc == 3)))
    7225          234 :             gfc_conv_expr (&parmse, e);
    7226         5345 :           else if (e->expr_type == EXPR_ARRAY)
    7227              :             {
    7228          306 :               gfc_conv_expr (&parmse, e);
    7229          306 :               if (e->ts.type != BT_CHARACTER)
    7230          263 :                 parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
    7231              :             }
    7232              :           else
    7233         5039 :             gfc_conv_expr_reference (&parmse, e);
    7234              : 
    7235         5579 :           if (e->ts.type == BT_CHARACTER && !e->rank
    7236          174 :               && e->expr_type == EXPR_FUNCTION)
    7237           12 :             parmse.expr = build_fold_indirect_ref_loc (input_location,
    7238              :                                                        parmse.expr);
    7239              : 
    7240         5529 :           if (fsym && fsym->ts.type == BT_DERIVED
    7241         6967 :               && gfc_is_class_container_ref (e))
    7242              :             {
    7243           24 :               parmse.expr = gfc_class_data_get (parmse.expr);
    7244              : 
    7245           24 :               if (fsym->attr.optional && e->expr_type == EXPR_VARIABLE
    7246           24 :                   && e->symtree->n.sym->attr.optional)
    7247              :                 {
    7248            0 :                   tree cond = gfc_conv_expr_present (e->symtree->n.sym);
    7249            0 :                   parmse.expr = build3_loc (input_location, COND_EXPR,
    7250            0 :                                         TREE_TYPE (parmse.expr),
    7251              :                                         cond, parmse.expr,
    7252            0 :                                         fold_convert (TREE_TYPE (parmse.expr),
    7253              :                                                       null_pointer_node));
    7254              :                 }
    7255              :             }
    7256              : 
    7257              :           /* Scalar dummy arguments of intrinsic type or derived type with
    7258              :              VALUE attribute.  */
    7259         5579 :           if (fsym
    7260         5529 :               && fsym->attr.value
    7261          234 :               && fsym->ts.type != BT_CLASS)
    7262          234 :             conv_dummy_value (&parmse, e, fsym, optionalargs);
    7263              : 
    7264              :           /* If we are passing an absent array as optional dummy to an
    7265              :              elemental procedure, make sure that we pass NULL when the data
    7266              :              pointer is NULL.  We need this extra conditional because of
    7267              :              scalarization which passes arrays elements to the procedure,
    7268              :              ignoring the fact that the array can be absent/unallocated/...  */
    7269         5345 :           else if (ss->info->can_be_null_ref
    7270          415 :                    && ss->info->type != GFC_SS_REFERENCE)
    7271              :             {
    7272          193 :               tree descriptor_data;
    7273              : 
    7274          193 :               descriptor_data = ss->info->data.array.data;
    7275          193 :               tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    7276              :                                      descriptor_data,
    7277          193 :                                      fold_convert (TREE_TYPE (descriptor_data),
    7278              :                                                    null_pointer_node));
    7279          193 :               parmse.expr
    7280          386 :                 = fold_build3_loc (input_location, COND_EXPR,
    7281          193 :                                    TREE_TYPE (parmse.expr),
    7282              :                                    gfc_unlikely (tmp, PRED_FORTRAN_ABSENT_DUMMY),
    7283          193 :                                    fold_convert (TREE_TYPE (parmse.expr),
    7284              :                                                  null_pointer_node),
    7285              :                                    parmse.expr);
    7286              :             }
    7287              : 
    7288              :           /* The scalarizer does not repackage the reference to a class
    7289              :              array - instead it returns a pointer to the data element.  */
    7290         5579 :           if (fsym && fsym->ts.type == BT_CLASS && e->ts.type == BT_CLASS)
    7291          162 :             gfc_conv_class_to_class (&parmse, e, fsym->ts, true,
    7292          162 :                                      fsym->attr.intent != INTENT_IN
    7293          162 :                                      && (CLASS_DATA (fsym)->attr.class_pointer
    7294           12 :                                          || CLASS_DATA (fsym)->attr.allocatable),
    7295          162 :                                      fsym->attr.optional
    7296            0 :                                      && e->expr_type == EXPR_VARIABLE
    7297          162 :                                      && e->symtree->n.sym->attr.optional,
    7298          162 :                                      CLASS_DATA (fsym)->attr.class_pointer
    7299          162 :                                      || CLASS_DATA (fsym)->attr.allocatable);
    7300              :         }
    7301              :       else
    7302              :         {
    7303       244429 :           bool scalar;
    7304       244429 :           gfc_ss *argss;
    7305              : 
    7306       244429 :           gfc_init_se (&parmse, NULL);
    7307              : 
    7308              :           /* Check whether the expression is a scalar or not; we cannot use
    7309              :              e->rank as it can be nonzero for functions arguments.  */
    7310       244429 :           argss = gfc_walk_expr (e);
    7311       244429 :           scalar = argss == gfc_ss_terminator;
    7312       244429 :           if (!scalar)
    7313        59734 :             gfc_free_ss_chain (argss);
    7314              : 
    7315              :           /* Special handling for passing scalar polymorphic coarrays;
    7316              :              otherwise one passes "class->_data.data" instead of "&class".  */
    7317       244429 :           if (e->rank == 0 && e->ts.type == BT_CLASS
    7318         3551 :               && fsym && fsym->ts.type == BT_CLASS
    7319         3129 :               && CLASS_DATA (fsym)->attr.codimension
    7320           55 :               && !CLASS_DATA (fsym)->attr.dimension)
    7321              :             {
    7322           55 :               gfc_add_class_array_ref (e);
    7323           55 :               parmse.want_coarray = 1;
    7324           55 :               scalar = false;
    7325              :             }
    7326              : 
    7327              :           /* A scalar or transformational function.  */
    7328       244429 :           if (scalar)
    7329              :             {
    7330       184640 :               if (e->expr_type == EXPR_VARIABLE
    7331        54749 :                     && e->symtree->n.sym->attr.cray_pointee
    7332          390 :                     && fsym && fsym->attr.flavor == FL_PROCEDURE)
    7333              :                 {
    7334              :                     /* The Cray pointer needs to be converted to a pointer to
    7335              :                        a type given by the expression.  */
    7336            6 :                     gfc_conv_expr (&parmse, e);
    7337            6 :                     type = build_pointer_type (TREE_TYPE (parmse.expr));
    7338            6 :                     tmp = gfc_get_symbol_decl (e->symtree->n.sym->cp_pointer);
    7339            6 :                     parmse.expr = convert (type, tmp);
    7340              :                 }
    7341              : 
    7342       184634 :               else if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
    7343              :                 /* Implement F2018, 18.3.6, list item (5), bullet point 2.  */
    7344          687 :                 gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
    7345              : 
    7346       183947 :               else if (fsym && fsym->attr.value)
    7347              :                 {
    7348        21912 :                   if (fsym->ts.type == BT_CHARACTER
    7349          543 :                       && fsym->ts.is_c_interop
    7350          181 :                       && fsym->ns->proc_name != NULL
    7351          181 :                       && fsym->ns->proc_name->attr.is_bind_c)
    7352              :                     {
    7353          172 :                       parmse.expr = NULL;
    7354          172 :                       conv_scalar_char_value (fsym, &parmse, &e);
    7355          172 :                       if (parmse.expr == NULL)
    7356          166 :                         gfc_conv_expr (&parmse, e);
    7357              :                     }
    7358              :                   else
    7359              :                     {
    7360        21740 :                       gfc_conv_expr (&parmse, e);
    7361        21740 :                       conv_dummy_value (&parmse, e, fsym, optionalargs);
    7362              :                     }
    7363              :                 }
    7364              : 
    7365       162035 :               else if (arg->name && arg->name[0] == '%')
    7366              :                 /* Argument list functions %VAL, %LOC and %REF are signalled
    7367              :                    through arg->name.  */
    7368         5822 :                 conv_arglist_function (&parmse, arg->expr, arg->name);
    7369       156213 :               else if ((e->expr_type == EXPR_FUNCTION)
    7370         8185 :                         && ((e->value.function.esym
    7371         2154 :                              && e->value.function.esym->result->attr.pointer)
    7372         8090 :                             || (!e->value.function.esym
    7373         6031 :                                 && e->symtree->n.sym->attr.pointer))
    7374           95 :                         && fsym && fsym->attr.target)
    7375              :                 /* Make sure the function only gets called once.  */
    7376            8 :                 gfc_conv_expr_reference (&parmse, e);
    7377       156205 :               else if (e->expr_type == EXPR_FUNCTION
    7378         8177 :                        && e->symtree->n.sym->result
    7379         7142 :                        && e->symtree->n.sym->result != e->symtree->n.sym
    7380          138 :                        && e->symtree->n.sym->result->attr.proc_pointer)
    7381              :                 {
    7382              :                   /* Functions returning procedure pointers.  */
    7383           18 :                   gfc_conv_expr (&parmse, e);
    7384           18 :                   if (fsym && fsym->attr.proc_pointer)
    7385            6 :                     parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
    7386              :                 }
    7387              : 
    7388              :               else
    7389              :                 {
    7390       156187 :                   bool defer_to_dealloc_blk = false;
    7391       156187 :                   if (e->ts.type == BT_CLASS && fsym
    7392         3484 :                       && fsym->ts.type == BT_CLASS
    7393         3062 :                       && (!CLASS_DATA (fsym)->as
    7394          356 :                           || CLASS_DATA (fsym)->as->type != AS_ASSUMED_RANK)
    7395         2706 :                       && CLASS_DATA (e)->attr.codimension)
    7396              :                     {
    7397           48 :                       gcc_assert (!CLASS_DATA (fsym)->attr.codimension);
    7398           48 :                       gcc_assert (!CLASS_DATA (fsym)->as);
    7399           48 :                       gfc_add_class_array_ref (e);
    7400           48 :                       parmse.want_coarray = 1;
    7401           48 :                       gfc_conv_expr_reference (&parmse, e);
    7402           48 :                       class_scalar_coarray_to_class (&parmse, e, fsym->ts,
    7403           48 :                                      fsym->attr.optional
    7404           48 :                                      && e->expr_type == EXPR_VARIABLE);
    7405              :                     }
    7406       156139 :                   else if (e->ts.type == BT_CLASS && fsym
    7407         3436 :                            && fsym->ts.type == BT_CLASS
    7408         3014 :                            && !CLASS_DATA (fsym)->as
    7409         2658 :                            && !CLASS_DATA (e)->as
    7410         2548 :                            && strcmp (fsym->ts.u.derived->name,
    7411              :                                       e->ts.u.derived->name))
    7412              :                     {
    7413         1625 :                       type = gfc_typenode_for_spec (&fsym->ts);
    7414         1625 :                       var = gfc_create_var (type, fsym->name);
    7415         1625 :                       gfc_conv_expr (&parmse, e);
    7416         1625 :                       if (fsym->attr.optional
    7417          153 :                           && e->expr_type == EXPR_VARIABLE
    7418          153 :                           && e->symtree->n.sym->attr.optional)
    7419              :                         {
    7420           66 :                           stmtblock_t block;
    7421           66 :                           tree cond;
    7422           66 :                           tmp = gfc_build_addr_expr (NULL_TREE, parmse.expr);
    7423           66 :                           cond = fold_build2_loc (input_location, NE_EXPR,
    7424              :                                                   logical_type_node, tmp,
    7425           66 :                                                   fold_convert (TREE_TYPE (tmp),
    7426              :                                                             null_pointer_node));
    7427           66 :                           gfc_start_block (&block);
    7428           66 :                           gfc_add_modify (&block, var,
    7429              :                                           fold_build1_loc (input_location,
    7430              :                                                            VIEW_CONVERT_EXPR,
    7431              :                                                            type, parmse.expr));
    7432           66 :                           gfc_add_expr_to_block (&parmse.pre,
    7433              :                                  fold_build3_loc (input_location,
    7434              :                                          COND_EXPR, void_type_node,
    7435              :                                          cond, gfc_finish_block (&block),
    7436              :                                          build_empty_stmt (input_location)));
    7437           66 :                           parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
    7438          132 :                           parmse.expr = build3_loc (input_location, COND_EXPR,
    7439           66 :                                          TREE_TYPE (parmse.expr),
    7440              :                                          cond, parmse.expr,
    7441           66 :                                          fold_convert (TREE_TYPE (parmse.expr),
    7442              :                                                        null_pointer_node));
    7443           66 :                         }
    7444              :                       else
    7445              :                         {
    7446              :                           /* Since the internal representation of unlimited
    7447              :                              polymorphic expressions includes an extra field
    7448              :                              that other class objects do not, a cast to the
    7449              :                              formal type does not work.  */
    7450         1559 :                           if (!UNLIMITED_POLY (e) && UNLIMITED_POLY (fsym))
    7451              :                             {
    7452           91 :                               tree efield;
    7453              : 
    7454              :                               /* Evaluate arguments just once, when they have
    7455              :                                  side effects.  */
    7456           91 :                               if (TREE_SIDE_EFFECTS (parmse.expr))
    7457              :                                 {
    7458           25 :                                   tree cldata, zero;
    7459              : 
    7460           25 :                                   parmse.expr = gfc_evaluate_now (parmse.expr,
    7461              :                                                                   &parmse.pre);
    7462              : 
    7463              :                                   /* Prevent memory leak, when old component
    7464              :                                      was allocated already.  */
    7465           25 :                                   cldata = gfc_class_data_get (parmse.expr);
    7466           25 :                                   zero = build_int_cst (TREE_TYPE (cldata),
    7467              :                                                         0);
    7468           25 :                                   tmp = fold_build2_loc (input_location, NE_EXPR,
    7469              :                                                          logical_type_node,
    7470              :                                                          cldata, zero);
    7471           25 :                                   tmp = build3_v (COND_EXPR, tmp,
    7472              :                                                   gfc_call_free (cldata),
    7473              :                                                   build_empty_stmt (
    7474              :                                                     input_location));
    7475           25 :                                   gfc_add_expr_to_block (&parmse.finalblock,
    7476              :                                                          tmp);
    7477           25 :                                   gfc_add_modify (&parmse.finalblock,
    7478              :                                                   cldata, zero);
    7479              :                                 }
    7480              : 
    7481              :                               /* Set the _data field.  */
    7482           91 :                               tmp = gfc_class_data_get (var);
    7483           91 :                               efield = fold_convert (TREE_TYPE (tmp),
    7484              :                                         gfc_class_data_get (parmse.expr));
    7485           91 :                               gfc_add_modify (&parmse.pre, tmp, efield);
    7486              : 
    7487              :                               /* Set the _vptr field.  */
    7488           91 :                               tmp = gfc_class_vptr_get (var);
    7489           91 :                               efield = fold_convert (TREE_TYPE (tmp),
    7490              :                                         gfc_class_vptr_get (parmse.expr));
    7491           91 :                               gfc_add_modify (&parmse.pre, tmp, efield);
    7492              : 
    7493              :                               /* Set the _len field.  */
    7494           91 :                               tmp = gfc_class_len_get (var);
    7495           91 :                               gfc_add_modify (&parmse.pre, tmp,
    7496           91 :                                               build_int_cst (TREE_TYPE (tmp), 0));
    7497           91 :                             }
    7498              :                           else
    7499              :                             {
    7500         1468 :                               tmp = fold_build1_loc (input_location,
    7501              :                                                      VIEW_CONVERT_EXPR,
    7502              :                                                      type, parmse.expr);
    7503         1468 :                               gfc_add_modify (&parmse.pre, var, tmp);
    7504         1559 :                                               ;
    7505              :                             }
    7506         1559 :                           parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
    7507              :                         }
    7508              :                     }
    7509              :                   else
    7510              :                     {
    7511       154514 :                       gfc_conv_expr_reference (&parmse, e);
    7512              : 
    7513       154514 :                       gfc_symbol *dsym = fsym;
    7514       154514 :                       gfc_dummy_arg *dummy;
    7515              : 
    7516              :                       /* Use associated dummy as fallback for formal
    7517              :                          argument if there is no explicit interface.  */
    7518       154514 :                       if (dsym == NULL
    7519        27403 :                           && (dummy = arg->associated_dummy)
    7520        24884 :                           && dummy->intrinsicness == GFC_NON_INTRINSIC_DUMMY_ARG
    7521       177995 :                           && dummy->u.non_intrinsic->sym)
    7522              :                         dsym = dummy->u.non_intrinsic->sym;
    7523              : 
    7524       154514 :                       if (dsym
    7525       150592 :                           && dsym->attr.intent == INTENT_OUT
    7526         3222 :                           && !dsym->attr.allocatable
    7527         3080 :                           && !dsym->attr.pointer
    7528         3062 :                           && e->expr_type == EXPR_VARIABLE
    7529         3061 :                           && e->ref == NULL
    7530         2952 :                           && e->symtree
    7531         2952 :                           && e->symtree->n.sym
    7532         2952 :                           && !e->symtree->n.sym->attr.dimension
    7533         2952 :                           && e->ts.type != BT_CHARACTER
    7534         2850 :                           && e->ts.type != BT_CLASS
    7535         2620 :                           && (e->ts.type != BT_DERIVED
    7536          492 :                               || (dsym->ts.type == BT_DERIVED
    7537          492 :                                   && e->ts.u.derived == dsym->ts.u.derived
    7538              :                                   /* Types with allocatable components are
    7539              :                                      excluded from clobbering because we need
    7540              :                                      the unclobbered pointers to free the
    7541              :                                      allocatable components in the callee.
    7542              :                                      Same goes for finalizable types or types
    7543              :                                      with finalizable components, we need to
    7544              :                                      pass the unclobbered values to the
    7545              :                                      finalization routines.
    7546              :                                      For parameterized types, it's less clear
    7547              :                                      but they may not have a constant size
    7548              :                                      so better exclude them in any case.  */
    7549          477 :                                   && !e->ts.u.derived->attr.alloc_comp
    7550          351 :                                   && !e->ts.u.derived->attr.pdt_type
    7551          351 :                                   && !gfc_is_finalizable (e->ts.u.derived, NULL)))
    7552       156951 :                           && !sym->attr.elemental)
    7553              :                         {
    7554         1104 :                           tree var;
    7555         1104 :                           var = build_fold_indirect_ref_loc (input_location,
    7556              :                                                              parmse.expr);
    7557         1104 :                           tree clobber = build_clobber (TREE_TYPE (var));
    7558         1104 :                           gfc_add_modify (&clobbers, var, clobber);
    7559              :                         }
    7560              :                     }
    7561              :                   /* Catch base objects that are not variables.  */
    7562       156187 :                   if (e->ts.type == BT_CLASS
    7563         3484 :                         && e->expr_type != EXPR_VARIABLE
    7564          306 :                         && expr && e == expr->base_expr)
    7565           80 :                     base_object = build_fold_indirect_ref_loc (input_location,
    7566              :                                                                parmse.expr);
    7567              : 
    7568              :                   /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
    7569              :                      allocated on entry, it must be deallocated.  */
    7570       128784 :                   if (fsym && fsym->attr.intent == INTENT_OUT
    7571         3151 :                       && (fsym->attr.allocatable
    7572         3009 :                           || (fsym->ts.type == BT_CLASS
    7573          259 :                               && CLASS_DATA (fsym)->attr.allocatable))
    7574       156478 :                       && !is_CFI_desc (fsym, NULL))
    7575              :                     {
    7576          291 :                       stmtblock_t block;
    7577          291 :                       tree ptr;
    7578              : 
    7579          291 :                       defer_to_dealloc_blk = true;
    7580              : 
    7581          291 :                       parmse.expr = gfc_evaluate_data_ref_now (parmse.expr,
    7582              :                                                                &parmse.pre);
    7583              : 
    7584          291 :                       if (parmse.class_container != NULL_TREE)
    7585          156 :                         parmse.class_container
    7586          156 :                             = gfc_evaluate_data_ref_now (parmse.class_container,
    7587              :                                                          &parmse.pre);
    7588              : 
    7589          291 :                       gfc_init_block  (&block);
    7590          291 :                       ptr = parmse.expr;
    7591          291 :                       if (e->ts.type == BT_CLASS)
    7592          156 :                         ptr = gfc_class_data_get (ptr);
    7593              : 
    7594          291 :                       tree cls = parmse.class_container;
    7595          291 :                       tmp = gfc_deallocate_scalar_with_status (ptr, NULL_TREE,
    7596              :                                                                NULL_TREE, true,
    7597              :                                                                e, e->ts, cls);
    7598          291 :                       gfc_add_expr_to_block (&block, tmp);
    7599          291 :                       gfc_add_modify (&block, ptr,
    7600          291 :                                       fold_convert (TREE_TYPE (ptr),
    7601              :                                                     null_pointer_node));
    7602              : 
    7603          291 :                       if (fsym->ts.type == BT_CLASS)
    7604          149 :                         gfc_reset_vptr (&block, nullptr,
    7605              :                                         build_fold_indirect_ref (parmse.expr),
    7606          149 :                                         fsym->ts.u.derived);
    7607              : 
    7608          291 :                       if (fsym->attr.optional
    7609           42 :                           && e->expr_type == EXPR_VARIABLE
    7610           42 :                           && e->symtree->n.sym->attr.optional)
    7611              :                         {
    7612           36 :                           tmp = fold_build3_loc (input_location, COND_EXPR,
    7613              :                                      void_type_node,
    7614           18 :                                      gfc_conv_expr_present (e->symtree->n.sym),
    7615              :                                             gfc_finish_block (&block),
    7616              :                                             build_empty_stmt (input_location));
    7617              :                         }
    7618              :                       else
    7619          273 :                         tmp = gfc_finish_block (&block);
    7620              : 
    7621          291 :                       gfc_add_expr_to_block (&dealloc_blk, tmp);
    7622              :                     }
    7623              : 
    7624              :                   /* A class array element needs converting back to be a
    7625              :                      class object, if the formal argument is a class object.  */
    7626       156187 :                   if (fsym && fsym->ts.type == BT_CLASS
    7627         3086 :                         && e->ts.type == BT_CLASS
    7628         3062 :                         && ((CLASS_DATA (fsym)->as
    7629          356 :                              && CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
    7630         2706 :                             || CLASS_DATA (e)->attr.dimension))
    7631              :                     {
    7632          466 :                       gfc_se class_se = parmse;
    7633          466 :                       gfc_init_block (&class_se.pre);
    7634          466 :                       gfc_init_block (&class_se.post);
    7635              : 
    7636          466 :                       gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
    7637          466 :                                      fsym->attr.intent != INTENT_IN
    7638          466 :                                      && (CLASS_DATA (fsym)->attr.class_pointer
    7639          267 :                                          || CLASS_DATA (fsym)->attr.allocatable),
    7640          466 :                                      fsym->attr.optional
    7641          198 :                                      && e->expr_type == EXPR_VARIABLE
    7642          664 :                                      && e->symtree->n.sym->attr.optional,
    7643          466 :                                      CLASS_DATA (fsym)->attr.class_pointer
    7644          466 :                                      || CLASS_DATA (fsym)->attr.allocatable);
    7645              : 
    7646          466 :                       parmse.expr = class_se.expr;
    7647          442 :                       stmtblock_t *class_pre_block = defer_to_dealloc_blk
    7648          466 :                                                      ? &dealloc_blk
    7649              :                                                      : &parmse.pre;
    7650          466 :                       gfc_add_block_to_block (class_pre_block, &class_se.pre);
    7651          466 :                       gfc_add_block_to_block (&parmse.post, &class_se.post);
    7652              :                     }
    7653              : 
    7654       128784 :                   if (fsym && (fsym->ts.type == BT_DERIVED
    7655       116934 :                                || fsym->ts.type == BT_ASSUMED)
    7656        12717 :                       && e->ts.type == BT_CLASS
    7657          410 :                       && !CLASS_DATA (e)->attr.dimension
    7658          374 :                       && !CLASS_DATA (e)->attr.codimension)
    7659              :                     {
    7660          374 :                       parmse.expr = gfc_class_data_get (parmse.expr);
    7661              :                       /* The result is a class temporary, whose _data component
    7662              :                          must be freed to avoid a memory leak.  */
    7663          374 :                       if (e->expr_type == EXPR_FUNCTION
    7664           23 :                           && CLASS_DATA (e)->attr.allocatable)
    7665              :                         {
    7666           19 :                           tree zero;
    7667              : 
    7668              :                           /* Finalize the expression.  */
    7669           19 :                           gfc_finalize_tree_expr (&parmse, NULL,
    7670           19 :                                                   gfc_expr_attr (e), e->rank);
    7671           19 :                           gfc_add_block_to_block (&parmse.post,
    7672              :                                                   &parmse.finalblock);
    7673              : 
    7674              :                           /* Then free the class _data.  */
    7675           19 :                           zero = build_int_cst (TREE_TYPE (parmse.expr), 0);
    7676           19 :                           tmp = fold_build2_loc (input_location, NE_EXPR,
    7677              :                                                  logical_type_node,
    7678              :                                                  parmse.expr, zero);
    7679           19 :                           tmp = build3_v (COND_EXPR, tmp,
    7680              :                                           gfc_call_free (parmse.expr),
    7681              :                                           build_empty_stmt (input_location));
    7682           19 :                           gfc_add_expr_to_block (&parmse.post, tmp);
    7683           19 :                           gfc_add_modify (&parmse.post, parmse.expr, zero);
    7684              :                         }
    7685              :                     }
    7686              : 
    7687              :                   /* Wrap scalar variable in a descriptor. We need to convert
    7688              :                      the address of a pointer back to the pointer itself before,
    7689              :                      we can assign it to the data field.  */
    7690              : 
    7691       128784 :                   if (fsym && fsym->as && fsym->as->type == AS_ASSUMED_RANK
    7692         1314 :                       && fsym->ts.type != BT_CLASS && e->expr_type != EXPR_NULL)
    7693              :                     {
    7694         1242 :                       tmp = parmse.expr;
    7695         1242 :                       if (TREE_CODE (tmp) == ADDR_EXPR)
    7696          736 :                         tmp = TREE_OPERAND (tmp, 0);
    7697         1242 :                       parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp,
    7698              :                                                                    fsym->attr);
    7699         1242 :                       parmse.expr = gfc_build_addr_expr (NULL_TREE,
    7700              :                                                          parmse.expr);
    7701              :                     }
    7702       127542 :                   else if (fsym && e->expr_type != EXPR_NULL
    7703       127244 :                       && ((fsym->attr.pointer
    7704         1740 :                            && fsym->attr.flavor != FL_PROCEDURE)
    7705       125510 :                           || (fsym->attr.proc_pointer
    7706          157 :                               && !(e->expr_type == EXPR_VARIABLE
    7707          157 :                                    && e->symtree->n.sym->attr.dummy))
    7708       125365 :                           || (fsym->attr.proc_pointer
    7709           12 :                               && e->expr_type == EXPR_VARIABLE
    7710           12 :                               && gfc_is_proc_ptr_comp (e))
    7711       125359 :                           || (fsym->attr.allocatable
    7712         1039 :                               && fsym->attr.flavor != FL_PROCEDURE)))
    7713              :                     {
    7714              :                       /* Scalar pointer dummy args require an extra level of
    7715              :                          indirection. The null pointer already contains
    7716              :                          this level of indirection.  */
    7717         2918 :                       parm_kind = SCALAR_POINTER;
    7718         2918 :                       parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
    7719              :                     }
    7720              :                 }
    7721              :             }
    7722        59789 :           else if (e->ts.type == BT_CLASS
    7723         2687 :                     && fsym && fsym->ts.type == BT_CLASS
    7724         2341 :                     && (CLASS_DATA (fsym)->attr.dimension
    7725           55 :                         || CLASS_DATA (fsym)->attr.codimension))
    7726              :             {
    7727              :               /* Pass a class array.  */
    7728         2341 :               gfc_conv_expr_descriptor (&parmse, e);
    7729         2341 :               bool defer_to_dealloc_blk = false;
    7730              : 
    7731         2341 :               if (fsym->attr.optional
    7732          798 :                   && e->expr_type == EXPR_VARIABLE
    7733          798 :                   && e->symtree->n.sym->attr.optional)
    7734              :                 {
    7735          438 :                   stmtblock_t block;
    7736              : 
    7737          438 :                   gfc_init_block (&block);
    7738          438 :                   gfc_add_block_to_block (&block, &parmse.pre);
    7739              : 
    7740          876 :                   tree t = fold_build3_loc (input_location, COND_EXPR,
    7741              :                              void_type_node,
    7742          438 :                              gfc_conv_expr_present (e->symtree->n.sym),
    7743              :                                     gfc_finish_block (&block),
    7744              :                                     build_empty_stmt (input_location));
    7745              : 
    7746          438 :                   gfc_add_expr_to_block (&parmse.pre, t);
    7747              :                 }
    7748              : 
    7749              :               /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
    7750              :                  allocated on entry, it must be deallocated.  */
    7751         2341 :               if (fsym->attr.intent == INTENT_OUT
    7752          141 :                   && CLASS_DATA (fsym)->attr.allocatable)
    7753              :                 {
    7754          110 :                   stmtblock_t block;
    7755          110 :                   tree ptr;
    7756              : 
    7757              :                   /* In case the data reference to deallocate is dependent on
    7758              :                      its own content, save the resulting pointer to a variable
    7759              :                      and only use that variable from now on, before the
    7760              :                      expression becomes invalid.  */
    7761          110 :                   parmse.expr = gfc_evaluate_data_ref_now (parmse.expr,
    7762              :                                                            &parmse.pre);
    7763              : 
    7764          110 :                   if (parmse.class_container != NULL_TREE)
    7765          110 :                     parmse.class_container
    7766          110 :                         = gfc_evaluate_data_ref_now (parmse.class_container,
    7767              :                                                      &parmse.pre);
    7768              : 
    7769          110 :                   gfc_init_block  (&block);
    7770          110 :                   ptr = parmse.expr;
    7771          110 :                   ptr = gfc_class_data_get (ptr);
    7772              : 
    7773          110 :                   tree cls = parmse.class_container;
    7774          110 :                   tmp = gfc_deallocate_with_status (ptr, NULL_TREE,
    7775              :                                                     NULL_TREE, NULL_TREE,
    7776              :                                                     NULL_TREE, true, e,
    7777              :                                                     GFC_CAF_COARRAY_NOCOARRAY,
    7778              :                                                     cls);
    7779          110 :                   gfc_add_expr_to_block (&block, tmp);
    7780          110 :                   tmp = fold_build2_loc (input_location, MODIFY_EXPR,
    7781              :                                          void_type_node, ptr,
    7782              :                                          null_pointer_node);
    7783          110 :                   gfc_add_expr_to_block (&block, tmp);
    7784          110 :                   gfc_reset_vptr (&block, e, parmse.class_container);
    7785              : 
    7786          110 :                   if (fsym->attr.optional
    7787           30 :                       && e->expr_type == EXPR_VARIABLE
    7788           30 :                       && (!e->ref
    7789           30 :                           || (e->ref->type == REF_ARRAY
    7790            0 :                               && e->ref->u.ar.type != AR_FULL))
    7791            0 :                       && e->symtree->n.sym->attr.optional)
    7792              :                     {
    7793            0 :                       tmp = fold_build3_loc (input_location, COND_EXPR,
    7794              :                                     void_type_node,
    7795            0 :                                     gfc_conv_expr_present (e->symtree->n.sym),
    7796              :                                     gfc_finish_block (&block),
    7797              :                                     build_empty_stmt (input_location));
    7798              :                     }
    7799              :                   else
    7800          110 :                     tmp = gfc_finish_block (&block);
    7801              : 
    7802          110 :                   gfc_add_expr_to_block (&dealloc_blk, tmp);
    7803          110 :                   defer_to_dealloc_blk = true;
    7804              :                 }
    7805              : 
    7806         2341 :               gfc_se class_se = parmse;
    7807         2341 :               gfc_init_block (&class_se.pre);
    7808         2341 :               gfc_init_block (&class_se.post);
    7809              : 
    7810         2341 :               if (e->expr_type != EXPR_VARIABLE)
    7811              :                 {
    7812              :                   int n;
    7813              :                   /* Set the bounds and offset correctly.  */
    7814           48 :                   for (n = 0; n < e->rank; n++)
    7815           24 :                     gfc_conv_shift_descriptor_lbound (&class_se.pre,
    7816              :                                                       class_se.expr,
    7817              :                                                       n, gfc_index_one_node);
    7818              :                 }
    7819              : 
    7820              :               /* The conversion does not repackage the reference to a class
    7821              :                  array - _data descriptor.  */
    7822         2341 :               gfc_conv_class_to_class (&class_se, e, fsym->ts, false,
    7823         2341 :                                      fsym->attr.intent != INTENT_IN
    7824         2341 :                                      && (CLASS_DATA (fsym)->attr.class_pointer
    7825         1205 :                                          || CLASS_DATA (fsym)->attr.allocatable),
    7826         2341 :                                      fsym->attr.optional
    7827          798 :                                      && e->expr_type == EXPR_VARIABLE
    7828         3139 :                                      && e->symtree->n.sym->attr.optional,
    7829         2341 :                                      CLASS_DATA (fsym)->attr.class_pointer
    7830         2341 :                                      || CLASS_DATA (fsym)->attr.allocatable);
    7831              : 
    7832         2341 :               parmse.expr = class_se.expr;
    7833         2231 :               stmtblock_t *class_pre_block = defer_to_dealloc_blk
    7834         2341 :                                              ? &dealloc_blk
    7835              :                                              : &parmse.pre;
    7836         2341 :               gfc_add_block_to_block (class_pre_block, &class_se.pre);
    7837         2341 :               gfc_add_block_to_block (&parmse.post, &class_se.post);
    7838         2341 :             }
    7839              :           else
    7840              :             {
    7841              :               /* If the argument is a function call that may not create
    7842              :                  a temporary for the result, we have to check that we
    7843              :                  can do it, i.e. that there is no alias between this
    7844              :                  argument and another one.  */
    7845        57448 :               if (gfc_get_noncopying_intrinsic_argument (e) != NULL)
    7846              :                 {
    7847          358 :                   gfc_expr *iarg;
    7848          358 :                   sym_intent intent;
    7849              : 
    7850          358 :                   if (fsym != NULL)
    7851          349 :                     intent = fsym->attr.intent;
    7852              :                   else
    7853              :                     intent = INTENT_UNKNOWN;
    7854              : 
    7855          358 :                   if (gfc_check_fncall_dependency (e, intent, sym, args,
    7856              :                                                    NOT_ELEMENTAL))
    7857           21 :                     parmse.force_tmp = 1;
    7858              : 
    7859          358 :                   iarg = e->value.function.actual->expr;
    7860              : 
    7861              :                   /* Temporary needed if aliasing due to host association.  */
    7862          358 :                   if (sym->attr.contained
    7863          114 :                         && !sym->attr.pure
    7864          114 :                         && !sym->attr.implicit_pure
    7865           36 :                         && !sym->attr.use_assoc
    7866           36 :                         && iarg->expr_type == EXPR_VARIABLE
    7867           36 :                         && sym->ns == iarg->symtree->n.sym->ns)
    7868           36 :                     parmse.force_tmp = 1;
    7869              : 
    7870              :                   /* Ditto within module.  */
    7871          358 :                   if (sym->attr.use_assoc
    7872            6 :                         && !sym->attr.pure
    7873            6 :                         && !sym->attr.implicit_pure
    7874            0 :                         && iarg->expr_type == EXPR_VARIABLE
    7875            0 :                         && sym->module == iarg->symtree->n.sym->module)
    7876            0 :                     parmse.force_tmp = 1;
    7877              :                 }
    7878              : 
    7879              :               /* Special case for assumed-rank arrays: when passing an
    7880              :                  argument to a nonallocatable/nonpointer dummy, the bounds have
    7881              :                  to be reset as otherwise a last-dim ubound of -1 is
    7882              :                  indistinguishable from an assumed-size array in the callee.  */
    7883        57448 :               if (!sym->attr.is_bind_c && e && fsym && fsym->as
    7884        34478 :                   && fsym->as->type == AS_ASSUMED_RANK
    7885        11845 :                   && e->rank != -1
    7886        11556 :                   && e->expr_type == EXPR_VARIABLE
    7887        11115 :                   && ((fsym->ts.type == BT_CLASS
    7888            0 :                        && !CLASS_DATA (fsym)->attr.class_pointer
    7889            0 :                        && !CLASS_DATA (fsym)->attr.allocatable)
    7890        11115 :                       || (fsym->ts.type != BT_CLASS
    7891        11115 :                           && !fsym->attr.pointer && !fsym->attr.allocatable)))
    7892              :                 {
    7893              :                   /* Change AR_FULL to a (:,:,:) ref to force bounds update. */
    7894        10572 :                   gfc_ref *ref;
    7895        10818 :                   for (ref = e->ref; ref->next; ref = ref->next)
    7896              :                     {
    7897          318 :                       if (ref->next->type == REF_INQUIRY)
    7898              :                         break;
    7899          270 :                       if (ref->type == REF_ARRAY
    7900           24 :                           && ref->u.ar.type != AR_ELEMENT)
    7901              :                         break;
    7902        10572 :                     };
    7903        10572 :                   if (ref->u.ar.type == AR_FULL
    7904         9846 :                       && ref->u.ar.as->type != AS_ASSUMED_SIZE)
    7905         9726 :                     ref->u.ar.type = AR_SECTION;
    7906              :                 }
    7907              : 
    7908        57448 :               if (sym->attr.is_bind_c && e && is_CFI_desc (fsym, NULL))
    7909              :                 /* Implement F2018, 18.3.6, list item (5), bullet point 2.  */
    7910         5850 :                 gfc_conv_gfc_desc_to_cfi_desc (&parmse, e, fsym);
    7911              : 
    7912        51598 :               else if (e->expr_type == EXPR_VARIABLE
    7913        40242 :                     && is_subref_array (e)
    7914        52374 :                     && !(fsym && fsym->attr.pointer))
    7915              :                 /* The actual argument is a component reference to an
    7916              :                    array of derived types.  In this case, the argument
    7917              :                    is converted to a temporary, which is passed and then
    7918              :                    written back after the procedure call.  */
    7919          523 :                 gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
    7920          481 :                                 fsym ? fsym->attr.intent : INTENT_INOUT,
    7921          523 :                                 fsym && fsym->attr.pointer);
    7922              : 
    7923        51075 :               else if (e->ts.type == BT_CLASS && CLASS_DATA (e)->as
    7924          345 :                        && CLASS_DATA (e)->as->type == AS_ASSUMED_SIZE
    7925           18 :                        && nodesc_arg && fsym->ts.type == BT_DERIVED)
    7926              :                 /* An assumed size class actual argument being passed to
    7927              :                    a 'no descriptor' formal argument just requires the
    7928              :                    data pointer to be passed. For class dummy arguments
    7929              :                    this is stored in the symbol backend decl..  */
    7930            6 :                 parmse.expr = e->symtree->n.sym->backend_decl;
    7931              : 
    7932        51069 :               else if (gfc_is_class_array_ref (e, NULL)
    7933        51069 :                        && fsym && fsym->ts.type == BT_DERIVED)
    7934              :                 /* The actual argument is a component reference to an
    7935              :                    array of derived types.  In this case, the argument
    7936              :                    is converted to a temporary, which is passed and then
    7937              :                    written back after the procedure call.
    7938              :                    OOP-TODO: Insert code so that if the dynamic type is
    7939              :                    the same as the declared type, copy-in/copy-out does
    7940              :                    not occur.  */
    7941          108 :                 gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
    7942          108 :                                            fsym->attr.intent,
    7943          108 :                                            fsym->attr.pointer);
    7944              : 
    7945        50961 :               else if (gfc_is_class_array_function (e)
    7946        50961 :                        && fsym && fsym->ts.type == BT_DERIVED)
    7947              :                 /* See previous comment.  For function actual argument,
    7948              :                    the write out is not needed so the intent is set as
    7949              :                    intent in.  */
    7950              :                 {
    7951           13 :                   e->must_finalize = 1;
    7952           13 :                   gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
    7953           13 :                                              INTENT_IN, fsym->attr.pointer);
    7954              :                 }
    7955        47387 :               else if (fsym && fsym->attr.contiguous
    7956           60 :                        && (fsym->attr.target
    7957         1677 :                            ? gfc_is_not_contiguous (e)
    7958         1617 :                            : !gfc_is_simply_contiguous (e, false, true))
    7959        52940 :                        && gfc_expr_is_variable (e))
    7960              :                 {
    7961          303 :                   gfc_conv_subref_array_arg (&parmse, e, nodesc_arg,
    7962          303 :                                              fsym->attr.intent,
    7963          303 :                                              fsym->attr.pointer);
    7964              :                 }
    7965              :               else
    7966              :                 /* This is where we introduce a temporary to store the
    7967              :                    result of a non-lvalue array expression.  */
    7968        50645 :                 gfc_conv_array_parameter (&parmse, e, nodesc_arg, fsym,
    7969              :                                           sym->name, NULL);
    7970              : 
    7971              :               /* If an ALLOCATABLE dummy argument has INTENT(OUT) and is
    7972              :                  allocated on entry, it must be deallocated.
    7973              :                  CFI descriptors are handled elsewhere.  */
    7974        53845 :               if (fsym && fsym->attr.allocatable
    7975         1747 :                   && fsym->attr.intent == INTENT_OUT
    7976        57223 :                   && !is_CFI_desc (fsym, NULL))
    7977              :                 {
    7978          157 :                   if (fsym->ts.type == BT_DERIVED
    7979           45 :                       && fsym->ts.u.derived->attr.alloc_comp)
    7980              :                   {
    7981              :                     // deallocate the components first
    7982            9 :                     tmp = gfc_deallocate_alloc_comp (fsym->ts.u.derived,
    7983              :                                                      parmse.expr, e->rank);
    7984              :                     /* But check whether dummy argument is optional.  */
    7985            9 :                     if (tmp != NULL_TREE
    7986            9 :                         && fsym->attr.optional
    7987            6 :                         && e->expr_type == EXPR_VARIABLE
    7988            6 :                         && e->symtree->n.sym->attr.optional)
    7989              :                       {
    7990            6 :                         tree present;
    7991            6 :                         present = gfc_conv_expr_present (e->symtree->n.sym);
    7992            6 :                         tmp = build3_v (COND_EXPR, present, tmp,
    7993              :                                         build_empty_stmt (input_location));
    7994              :                       }
    7995            9 :                     if (tmp != NULL_TREE)
    7996            9 :                       gfc_add_expr_to_block (&dealloc_blk, tmp);
    7997              :                   }
    7998              : 
    7999          157 :                   tmp = parmse.expr;
    8000              :                   /* With bind(C), the actual argument is replaced by a bind-C
    8001              :                      descriptor; in this case, the data component arrives here,
    8002              :                      which shall not be dereferenced, but still freed and
    8003              :                      nullified.  */
    8004          157 :                   if  (TREE_TYPE(tmp) != pvoid_type_node)
    8005          157 :                     tmp = build_fold_indirect_ref_loc (input_location,
    8006              :                                                        parmse.expr);
    8007          157 :                   tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
    8008              :                                                     NULL_TREE, NULL_TREE, true,
    8009              :                                                     e,
    8010              :                                                     GFC_CAF_COARRAY_NOCOARRAY);
    8011          157 :                   if (fsym->attr.optional
    8012           48 :                       && e->expr_type == EXPR_VARIABLE
    8013           48 :                       && e->symtree->n.sym->attr.optional)
    8014           48 :                     tmp = fold_build3_loc (input_location, COND_EXPR,
    8015              :                                      void_type_node,
    8016           24 :                                      gfc_conv_expr_present (e->symtree->n.sym),
    8017              :                                        tmp, build_empty_stmt (input_location));
    8018          157 :                   gfc_add_expr_to_block (&dealloc_blk, tmp);
    8019              :                 }
    8020              :             }
    8021              :         }
    8022              :       /* Special case for an assumed-rank dummy argument. */
    8023       268666 :       if (!sym->attr.is_bind_c && e && fsym && e->rank > 0
    8024        55677 :           && (fsym->ts.type == BT_CLASS
    8025        55677 :               ? (CLASS_DATA (fsym)->as
    8026         4318 :                  && CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)
    8027        51359 :               : (fsym->as && fsym->as->type == AS_ASSUMED_RANK)))
    8028              :         {
    8029        12695 :           if (fsym->ts.type == BT_CLASS
    8030        12695 :               ? (CLASS_DATA (fsym)->attr.class_pointer
    8031         1055 :                  || CLASS_DATA (fsym)->attr.allocatable)
    8032        11640 :               : (fsym->attr.pointer || fsym->attr.allocatable))
    8033              :             {
    8034              :               /* Unallocated allocatable arrays and unassociated pointer
    8035              :                  arrays need their dtype setting if they are argument
    8036              :                  associated with assumed rank dummies to set the rank.  */
    8037          891 :               set_dtype_for_unallocated (&parmse, e);
    8038              :             }
    8039        11804 :           else if (e->expr_type == EXPR_VARIABLE
    8040        11325 :                    && e->symtree->n.sym->attr.dummy
    8041          698 :                    && (e->ts.type == BT_CLASS
    8042          891 :                        ? (e->ref && e->ref->next
    8043          193 :                           && e->ref->next->type == REF_ARRAY
    8044          193 :                           && e->ref->next->u.ar.type == AR_FULL
    8045          386 :                           && e->ref->next->u.ar.as->type == AS_ASSUMED_SIZE)
    8046          505 :                        : (e->ref && e->ref->type == REF_ARRAY
    8047          505 :                           && e->ref->u.ar.type == AR_FULL
    8048          733 :                           && e->ref->u.ar.as->type == AS_ASSUMED_SIZE)))
    8049              :             {
    8050              :               /* Assumed-size actual to assumed-rank dummy requires
    8051              :                  dim[rank-1].ubound = -1. */
    8052          180 :               tree minus_one;
    8053          180 :               tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
    8054          180 :               if (fsym->ts.type == BT_CLASS)
    8055           60 :                 tmp = gfc_class_data_get (tmp);
    8056          180 :               minus_one = build_int_cst (gfc_array_index_type, -1);
    8057          180 :               gfc_conv_descriptor_ubound_set (&parmse.pre, tmp,
    8058          180 :                                               gfc_rank_cst[e->rank - 1],
    8059              :                                               minus_one);
    8060              :             }
    8061              :         }
    8062              : 
    8063              :       /* The case with fsym->attr.optional is that of a user subroutine
    8064              :          with an interface indicating an optional argument.  When we call
    8065              :          an intrinsic subroutine, however, fsym is NULL, but we might still
    8066              :          have an optional argument, so we proceed to the substitution
    8067              :          just in case.  Arguments passed to bind(c) procedures via CFI
    8068              :          descriptors are handled elsewhere.  */
    8069       255708 :       if (e && (fsym == NULL || fsym->attr.optional)
    8070       329049 :           && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
    8071              :         {
    8072              :           /* If an optional argument is itself an optional dummy argument,
    8073              :              check its presence and substitute a null if absent.  This is
    8074              :              only needed when passing an array to an elemental procedure
    8075              :              as then array elements are accessed - or no NULL pointer is
    8076              :              allowed and a "1" or "0" should be passed if not present.
    8077              :              When passing a non-array-descriptor full array to a
    8078              :              non-array-descriptor dummy, no check is needed. For
    8079              :              array-descriptor actual to array-descriptor dummy, see
    8080              :              PR 41911 for why a check has to be inserted.
    8081              :              fsym == NULL is checked as intrinsics required the descriptor
    8082              :              but do not always set fsym.
    8083              :              Also, it is necessary to pass a NULL pointer to library routines
    8084              :              which usually ignore optional arguments, so they can handle
    8085              :              these themselves.  */
    8086        59289 :           if (e->expr_type == EXPR_VARIABLE
    8087        26413 :               && e->symtree->n.sym->attr.optional
    8088         2421 :               && (((e->rank != 0 && elemental_proc)
    8089         2246 :                    || e->representation.length || e->ts.type == BT_CHARACTER
    8090         2020 :                    || (e->rank == 0 && e->symtree->n.sym->attr.value)
    8091         1910 :                    || (e->rank != 0
    8092         1070 :                        && (fsym == NULL
    8093         1034 :                            || (fsym->as
    8094          272 :                                && (fsym->as->type == AS_ASSUMED_SHAPE
    8095          235 :                                    || fsym->as->type == AS_ASSUMED_RANK
    8096          117 :                                    || fsym->as->type == AS_DEFERRED)))))
    8097         1685 :                   || se->ignore_optional))
    8098          764 :             gfc_conv_missing_dummy (&parmse, e, fsym ? fsym->ts : e->ts,
    8099          764 :                                     e->representation.length);
    8100              :         }
    8101              : 
    8102              :       /* Make the class container for the first argument available with class
    8103              :          valued transformational functions.  */
    8104       268666 :       if (argc == 0 && e && e->ts.type == BT_CLASS
    8105         4943 :           && isym && isym->transformational
    8106           84 :           && se->ss && se->ss->info)
    8107              :         {
    8108           84 :           arg1_cntnr = parmse.expr;
    8109           84 :           if (POINTER_TYPE_P (TREE_TYPE (arg1_cntnr)))
    8110           84 :             arg1_cntnr = build_fold_indirect_ref_loc (input_location, arg1_cntnr);
    8111           84 :           arg1_cntnr = gfc_get_class_from_expr (arg1_cntnr);
    8112           84 :           se->ss->info->class_container = arg1_cntnr;
    8113              :         }
    8114              : 
    8115              :       /* Obtain the character length of an assumed character length procedure
    8116              :          from the typespec of the actual argument.  */
    8117       268666 :       if (e
    8118       255708 :           && parmse.string_length == NULL_TREE
    8119       220283 :           && e->ts.type == BT_PROCEDURE
    8120         1875 :           && e->symtree->n.sym->ts.type == BT_CHARACTER
    8121           21 :           && e->symtree->n.sym->ts.u.cl->length != NULL
    8122           21 :           && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
    8123              :         {
    8124           13 :           gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
    8125           13 :           parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
    8126              :         }
    8127              : 
    8128       268666 :       if (fsym && e)
    8129              :         {
    8130              :           /* Obtain the character length for a NULL() actual with a character
    8131              :              MOLD argument.  Otherwise substitute a suitable dummy length.
    8132              :              Here we handle non-optional dummies of non-bind(c) procedures.  */
    8133       223844 :           if (e->expr_type == EXPR_NULL
    8134          745 :               && fsym->ts.type == BT_CHARACTER
    8135          296 :               && !fsym->attr.optional
    8136       224062 :               && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
    8137          216 :             conv_null_actual (&parmse, e, fsym);
    8138              :         }
    8139              : 
    8140              :       /* If any actual argument of the procedure is allocatable and passed
    8141              :          to an allocatable dummy with INTENT(OUT), we conservatively
    8142              :          evaluate actual argument expressions before deallocations are
    8143              :          performed and the procedure is executed.  May create temporaries.
    8144              :          This ensures we conform to F2023:15.5.3, 15.5.4.  */
    8145       255708 :       if (e && fsym && force_eval_args
    8146         1103 :           && fsym->attr.intent != INTENT_OUT
    8147       269075 :           && !gfc_is_constant_expr (e))
    8148          268 :         parmse.expr = gfc_evaluate_now (parmse.expr, &parmse.pre);
    8149              : 
    8150       268666 :       if (fsym && need_interface_mapping && e)
    8151        40160 :         gfc_add_interface_mapping (&mapping, fsym, &parmse, e);
    8152              : 
    8153       268666 :       gfc_add_block_to_block (&se->pre, &parmse.pre);
    8154       268666 :       gfc_add_block_to_block (&post, &parmse.post);
    8155       268666 :       gfc_add_block_to_block (&se->finalblock, &parmse.finalblock);
    8156              : 
    8157              :       /* Allocated allocatable components of derived types must be
    8158              :          deallocated for non-variable scalars, array arguments to elemental
    8159              :          procedures, and array arguments with descriptor to non-elemental
    8160              :          procedures.  As bounds information for descriptorless arrays is no
    8161              :          longer available here, they are dealt with in trans-array.cc
    8162              :          (gfc_conv_array_parameter).  */
    8163       255708 :       if (e && (e->ts.type == BT_DERIVED || e->ts.type == BT_CLASS)
    8164        27703 :             && e->ts.u.derived->attr.alloc_comp
    8165         7512 :             && (e->rank == 0 || elemental_proc || !nodesc_arg)
    8166       276046 :             && !expr_may_alias_variables (e, elemental_proc))
    8167              :         {
    8168          354 :           int parm_rank;
    8169              :           /* It is known the e returns a structure type with at least one
    8170              :              allocatable component.  When e is a function, ensure that the
    8171              :              function is called once only by using a temporary variable.  */
    8172          354 :           if (!DECL_P (parmse.expr) && e->expr_type == EXPR_FUNCTION)
    8173          140 :             parmse.expr = gfc_evaluate_now_loc (input_location,
    8174              :                                                 parmse.expr, &se->pre);
    8175              : 
    8176          354 :           if ((fsym && fsym->attr.value) || e->expr_type == EXPR_ARRAY)
    8177          140 :             tmp = parmse.expr;
    8178              :           else
    8179          214 :             tmp = build_fold_indirect_ref_loc (input_location,
    8180              :                                                parmse.expr);
    8181              : 
    8182          354 :           parm_rank = e->rank;
    8183          354 :           switch (parm_kind)
    8184              :             {
    8185              :             case (ELEMENTAL):
    8186              :             case (SCALAR):
    8187          354 :               parm_rank = 0;
    8188              :               break;
    8189              : 
    8190            0 :             case (SCALAR_POINTER):
    8191            0 :               tmp = build_fold_indirect_ref_loc (input_location,
    8192              :                                              tmp);
    8193            0 :               break;
    8194              :             }
    8195              : 
    8196          354 :           if (e->ts.type == BT_DERIVED && fsym && fsym->ts.type == BT_CLASS)
    8197              :             {
    8198              :               /* The derived type is passed to gfc_deallocate_alloc_comp.
    8199              :                  Therefore, class actuals can be handled correctly but derived
    8200              :                  types passed to class formals need the _data component.  */
    8201           82 :               tmp = gfc_class_data_get (tmp);
    8202           82 :               if (!CLASS_DATA (fsym)->attr.dimension)
    8203              :                 {
    8204           56 :                   if (UNLIMITED_POLY (fsym))
    8205              :                     {
    8206           12 :                       tree type = gfc_typenode_for_spec (&e->ts);
    8207           12 :                       type = build_pointer_type (type);
    8208           12 :                       tmp = fold_convert (type, tmp);
    8209              :                     }
    8210           56 :                   tmp = build_fold_indirect_ref_loc (input_location, tmp);
    8211              :                 }
    8212              :             }
    8213              : 
    8214          354 :           if (e->expr_type == EXPR_OP
    8215           24 :                 && e->value.op.op == INTRINSIC_PARENTHESES
    8216           24 :                 && e->value.op.op1->expr_type == EXPR_VARIABLE)
    8217              :             {
    8218           24 :               tree local_tmp;
    8219           24 :               local_tmp = gfc_evaluate_now (tmp, &se->pre);
    8220           24 :               local_tmp = gfc_copy_alloc_comp (e->ts.u.derived, local_tmp, tmp,
    8221              :                                                parm_rank, 0);
    8222           24 :               gfc_add_expr_to_block (&se->post, local_tmp);
    8223              :             }
    8224              : 
    8225              :           /* Items of array expressions passed to a polymorphic formal arguments
    8226              :              create their own clean up, so prevent double free.  */
    8227          354 :           if (!finalized && !e->must_finalize
    8228          353 :               && !(e->expr_type == EXPR_ARRAY && fsym
    8229           74 :                    && fsym->ts.type == BT_CLASS))
    8230              :             {
    8231          333 :               bool scalar_res_outside_loop;
    8232          987 :               scalar_res_outside_loop = e->expr_type == EXPR_FUNCTION
    8233          151 :                                         && parm_rank == 0
    8234          472 :                                         && parmse.loop;
    8235              : 
    8236              :               /* Scalars passed to an assumed rank argument are converted to
    8237              :                  a descriptor. Obtain the data field before deallocating any
    8238              :                  allocatable components.  */
    8239          292 :               if (parm_rank == 0 && e->expr_type != EXPR_ARRAY
    8240          588 :                   && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    8241           19 :                 tmp = gfc_conv_descriptor_data_get (tmp);
    8242              : 
    8243          333 :               if (scalar_res_outside_loop)
    8244              :                 {
    8245              :                   /* Go through the ss chain to find the argument and use
    8246              :                      the stored value.  */
    8247           30 :                   gfc_ss *tmp_ss = parmse.loop->ss;
    8248           72 :                   for (; tmp_ss; tmp_ss = tmp_ss->next)
    8249           60 :                     if (tmp_ss->info
    8250           48 :                         && tmp_ss->info->expr == e
    8251           18 :                         && tmp_ss->info->data.scalar.value != NULL_TREE)
    8252              :                       {
    8253           18 :                         tmp = tmp_ss->info->data.scalar.value;
    8254           18 :                         break;
    8255              :                       }
    8256              :                 }
    8257              : 
    8258          333 :               STRIP_NOPS (tmp);
    8259              : 
    8260          333 :               if (derived_array != NULL_TREE)
    8261            0 :                 tmp = gfc_deallocate_alloc_comp (e->ts.u.derived,
    8262              :                                                  derived_array,
    8263              :                                                  parm_rank);
    8264          333 :               else if ((e->ts.type == BT_CLASS
    8265           24 :                         && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
    8266          333 :                        || e->ts.type == BT_DERIVED)
    8267          333 :                 tmp = gfc_deallocate_alloc_comp (e->ts.u.derived, tmp,
    8268              :                                                  parm_rank, 0, true);
    8269            0 :               else if (e->ts.type == BT_CLASS)
    8270            0 :                 tmp = gfc_deallocate_alloc_comp (CLASS_DATA (e)->ts.u.derived,
    8271              :                                                  tmp, parm_rank);
    8272              : 
    8273          333 :               if (scalar_res_outside_loop)
    8274           30 :                 gfc_add_expr_to_block (&parmse.loop->post, tmp);
    8275              :               else
    8276          303 :                 gfc_prepend_expr_to_block (&post, tmp);
    8277              :             }
    8278              :         }
    8279              : 
    8280              :       /* Add argument checking of passing an unallocated/NULL actual to
    8281              :          a nonallocatable/nonpointer dummy.  */
    8282              : 
    8283       268666 :       if (gfc_option.rtcheck & GFC_RTCHECK_POINTER && e != NULL)
    8284              :         {
    8285         6546 :           symbol_attribute attr;
    8286         6546 :           char *msg;
    8287         6546 :           tree cond;
    8288         6546 :           tree tmp;
    8289         6546 :           symbol_attribute fsym_attr;
    8290              : 
    8291         6546 :           if (fsym)
    8292              :             {
    8293         6385 :               if (fsym->ts.type == BT_CLASS)
    8294              :                 {
    8295          321 :                   fsym_attr = CLASS_DATA (fsym)->attr;
    8296          321 :                   fsym_attr.pointer = fsym_attr.class_pointer;
    8297              :                 }
    8298              :               else
    8299         6064 :                 fsym_attr = fsym->attr;
    8300              :             }
    8301              : 
    8302         6546 :           if (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION)
    8303         4094 :             attr = gfc_expr_attr (e);
    8304              :           else
    8305         6081 :             goto end_pointer_check;
    8306              : 
    8307              :           /*  In Fortran 2008 it's allowed to pass a NULL pointer/nonallocated
    8308              :               allocatable to an optional dummy, cf. 12.5.2.12.  */
    8309         4094 :           if (fsym != NULL && fsym->attr.optional && !attr.proc_pointer
    8310         1038 :               && (gfc_option.allow_std & GFC_STD_F2008) != 0)
    8311         1032 :             goto end_pointer_check;
    8312              : 
    8313         3062 :           if (attr.optional)
    8314              :             {
    8315              :               /* If the actual argument is an optional pointer/allocatable and
    8316              :                  the formal argument takes an nonpointer optional value,
    8317              :                  it is invalid to pass a non-present argument on, even
    8318              :                  though there is no technical reason for this in gfortran.
    8319              :                  See Fortran 2003, Section 12.4.1.6 item (7)+(8).  */
    8320           60 :               tree present, null_ptr, type;
    8321              : 
    8322           60 :               if (attr.allocatable
    8323            0 :                   && (fsym == NULL || !fsym_attr.allocatable))
    8324            0 :                 msg = xasprintf ("Allocatable actual argument '%s' is not "
    8325              :                                  "allocated or not present",
    8326            0 :                                  e->symtree->n.sym->name);
    8327           60 :               else if (attr.pointer
    8328           12 :                        && (fsym == NULL || !fsym_attr.pointer))
    8329           12 :                 msg = xasprintf ("Pointer actual argument '%s' is not "
    8330              :                                  "associated or not present",
    8331           12 :                                  e->symtree->n.sym->name);
    8332           48 :               else if (attr.proc_pointer && !e->value.function.actual
    8333            0 :                        && (fsym == NULL || !fsym_attr.proc_pointer))
    8334            0 :                 msg = xasprintf ("Proc-pointer actual argument '%s' is not "
    8335              :                                  "associated or not present",
    8336            0 :                                  e->symtree->n.sym->name);
    8337              :               else
    8338           48 :                 goto end_pointer_check;
    8339              : 
    8340           12 :               present = gfc_conv_expr_present (e->symtree->n.sym);
    8341           12 :               type = TREE_TYPE (present);
    8342           12 :               present = fold_build2_loc (input_location, EQ_EXPR,
    8343              :                                          logical_type_node, present,
    8344              :                                          fold_convert (type,
    8345              :                                                        null_pointer_node));
    8346           12 :               type = TREE_TYPE (parmse.expr);
    8347           12 :               null_ptr = fold_build2_loc (input_location, EQ_EXPR,
    8348              :                                           logical_type_node, parmse.expr,
    8349              :                                           fold_convert (type,
    8350              :                                                         null_pointer_node));
    8351           12 :               cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
    8352              :                                       logical_type_node, present, null_ptr);
    8353              :             }
    8354              :           else
    8355              :             {
    8356         3002 :               if (attr.allocatable
    8357          256 :                   && (fsym == NULL || !fsym_attr.allocatable))
    8358          190 :                 msg = xasprintf ("Allocatable actual argument '%s' is not "
    8359          190 :                                  "allocated", e->symtree->n.sym->name);
    8360         2812 :               else if (attr.pointer
    8361          272 :                        && (fsym == NULL || !fsym_attr.pointer))
    8362          184 :                 msg = xasprintf ("Pointer actual argument '%s' is not "
    8363          184 :                                  "associated", e->symtree->n.sym->name);
    8364         2628 :               else if (attr.proc_pointer && !e->value.function.actual
    8365           80 :                        && (fsym == NULL
    8366           50 :                            || (!fsym_attr.proc_pointer && !fsym_attr.optional)))
    8367           79 :                 msg = xasprintf ("Proc-pointer actual argument '%s' is not "
    8368           79 :                                  "associated", e->symtree->n.sym->name);
    8369              :               else
    8370         2549 :                 goto end_pointer_check;
    8371              : 
    8372          453 :               tmp = parmse.expr;
    8373          453 :               if (fsym && fsym->ts.type == BT_CLASS && !attr.proc_pointer)
    8374              :                 {
    8375           76 :                   if (POINTER_TYPE_P (TREE_TYPE (tmp)))
    8376           70 :                     tmp = build_fold_indirect_ref_loc (input_location, tmp);
    8377           76 :                   tmp = gfc_class_data_get (tmp);
    8378           76 :                   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    8379            3 :                     tmp = gfc_conv_descriptor_data_get (tmp);
    8380              :                 }
    8381              : 
    8382              :               /* If the argument is passed by value, we need to strip the
    8383              :                  INDIRECT_REF.  */
    8384          453 :               if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
    8385           12 :                 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    8386              : 
    8387          453 :               cond = fold_build2_loc (input_location, EQ_EXPR,
    8388              :                                       logical_type_node, tmp,
    8389          453 :                                       fold_convert (TREE_TYPE (tmp),
    8390              :                                                     null_pointer_node));
    8391              :             }
    8392              : 
    8393          465 :           gfc_trans_runtime_check (true, false, cond, &se->pre, &e->where,
    8394              :                                    msg);
    8395          465 :           free (msg);
    8396              :         }
    8397       262120 :       end_pointer_check:
    8398              : 
    8399              :       /* Deferred length dummies pass the character length by reference
    8400              :          so that the value can be returned.  */
    8401       268666 :       if (parmse.string_length && fsym && fsym->ts.deferred)
    8402              :         {
    8403          794 :           if (INDIRECT_REF_P (parmse.string_length))
    8404              :             {
    8405              :               /* In chains of functions/procedure calls the string_length already
    8406              :                  is a pointer to the variable holding the length.  Therefore
    8407              :                  remove the deref on call.  */
    8408           90 :               tmp = parmse.string_length;
    8409           90 :               parmse.string_length = TREE_OPERAND (parmse.string_length, 0);
    8410              :             }
    8411              :           else
    8412              :             {
    8413          704 :               tmp = parmse.string_length;
    8414          704 :               if (!VAR_P (tmp) && TREE_CODE (tmp) != COMPONENT_REF)
    8415           61 :                 tmp = gfc_evaluate_now (parmse.string_length, &se->pre);
    8416          704 :               parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp);
    8417              :             }
    8418              : 
    8419          794 :           if (e && e->expr_type == EXPR_VARIABLE
    8420          637 :               && fsym->attr.allocatable
    8421          367 :               && e->ts.u.cl->backend_decl
    8422          367 :               && VAR_P (e->ts.u.cl->backend_decl))
    8423              :             {
    8424          283 :               if (INDIRECT_REF_P (tmp))
    8425            0 :                 tmp = TREE_OPERAND (tmp, 0);
    8426          283 :               gfc_add_modify (&se->post, e->ts.u.cl->backend_decl,
    8427              :                               fold_convert (gfc_charlen_type_node, tmp));
    8428              :             }
    8429              :         }
    8430              : 
    8431              :       /* Character strings are passed as two parameters, a length and a
    8432              :          pointer - except for Bind(c) and c_ptrs which only pass the pointer.
    8433              :          An unlimited polymorphic formal argument likewise does not
    8434              :          need the length.  */
    8435       268666 :       if (parmse.string_length != NULL_TREE
    8436        36823 :           && !sym->attr.is_bind_c
    8437        36127 :           && !(fsym && fsym->ts.type == BT_DERIVED && fsym->ts.u.derived
    8438            6 :                && fsym->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR
    8439            6 :                && fsym->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING )
    8440        30247 :           && !(fsym && fsym->ts.type == BT_ASSUMED)
    8441        30138 :           && !(fsym && UNLIMITED_POLY (fsym)))
    8442        35837 :         vec_safe_push (stringargs, parmse.string_length);
    8443              : 
    8444              :       /* When calling __copy for character expressions to unlimited
    8445              :          polymorphic entities, the dst argument needs a string length.  */
    8446        51486 :       if (sym->name[0] == '_' && e && e->ts.type == BT_CHARACTER
    8447         5321 :           && startswith (sym->name, "__vtab_CHARACTER")
    8448            0 :           && arg->next && arg->next->expr
    8449            0 :           && (arg->next->expr->ts.type == BT_DERIVED
    8450            0 :               || arg->next->expr->ts.type == BT_CLASS)
    8451       268666 :           && arg->next->expr->ts.u.derived->attr.unlimited_polymorphic)
    8452            0 :         vec_safe_push (stringargs, parmse.string_length);
    8453              : 
    8454              :       /* For descriptorless coarrays and assumed-shape coarray dummies, we
    8455              :          pass the token and the offset as additional arguments.  */
    8456       268666 :       if (fsym && e == NULL && flag_coarray == GFC_FCOARRAY_LIB
    8457          122 :           && attr->codimension && !attr->allocatable)
    8458              :         {
    8459              :           /* Token and offset.  */
    8460            5 :           vec_safe_push (stringargs, null_pointer_node);
    8461            5 :           vec_safe_push (stringargs, build_int_cst (gfc_array_index_type, 0));
    8462            5 :           gcc_assert (fsym->attr.optional);
    8463              :         }
    8464       235739 :       else if (fsym && flag_coarray == GFC_FCOARRAY_LIB && attr->codimension
    8465          145 :                && !attr->allocatable)
    8466              :         {
    8467          123 :           tree caf_decl, caf_type, caf_desc = NULL_TREE;
    8468          123 :           tree offset, tmp2;
    8469              : 
    8470          123 :           caf_decl = gfc_get_tree_for_caf_expr (e);
    8471          123 :           caf_type = TREE_TYPE (caf_decl);
    8472          123 :           if (POINTER_TYPE_P (caf_type)
    8473          123 :               && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (caf_type)))
    8474            3 :             caf_desc = TREE_TYPE (caf_type);
    8475          120 :           else if (GFC_DESCRIPTOR_TYPE_P (caf_type))
    8476              :             caf_desc = caf_type;
    8477              : 
    8478           51 :           if (caf_desc
    8479           51 :               && (GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_ALLOCATABLE
    8480            0 :                   || GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_POINTER))
    8481              :             {
    8482          102 :               tmp = POINTER_TYPE_P (TREE_TYPE (caf_decl))
    8483           54 :                       ? build_fold_indirect_ref (caf_decl)
    8484              :                       : caf_decl;
    8485           51 :               tmp = gfc_conv_descriptor_token (tmp);
    8486              :             }
    8487           72 :           else if (DECL_LANG_SPECIFIC (caf_decl)
    8488           72 :                    && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
    8489           12 :             tmp = GFC_DECL_TOKEN (caf_decl);
    8490              :           else
    8491              :             {
    8492           60 :               gcc_assert (GFC_ARRAY_TYPE_P (caf_type)
    8493              :                           && GFC_TYPE_ARRAY_CAF_TOKEN (caf_type) != NULL_TREE);
    8494           60 :               tmp = GFC_TYPE_ARRAY_CAF_TOKEN (caf_type);
    8495              :             }
    8496              : 
    8497          123 :           vec_safe_push (stringargs, tmp);
    8498              : 
    8499          123 :           if (caf_desc
    8500          123 :               && GFC_TYPE_ARRAY_AKIND (caf_desc) == GFC_ARRAY_ALLOCATABLE)
    8501           51 :             offset = build_int_cst (gfc_array_index_type, 0);
    8502           72 :           else if (DECL_LANG_SPECIFIC (caf_decl)
    8503           72 :                    && GFC_DECL_CAF_OFFSET (caf_decl) != NULL_TREE)
    8504           12 :             offset = GFC_DECL_CAF_OFFSET (caf_decl);
    8505           60 :           else if (GFC_TYPE_ARRAY_CAF_OFFSET (caf_type) != NULL_TREE)
    8506            0 :             offset = GFC_TYPE_ARRAY_CAF_OFFSET (caf_type);
    8507              :           else
    8508           60 :             offset = build_int_cst (gfc_array_index_type, 0);
    8509              : 
    8510          123 :           if (caf_desc)
    8511              :             {
    8512          102 :               tmp = POINTER_TYPE_P (TREE_TYPE (caf_decl))
    8513           54 :                       ? build_fold_indirect_ref (caf_decl)
    8514              :                       : caf_decl;
    8515           51 :               tmp = gfc_conv_descriptor_data_get (tmp);
    8516              :             }
    8517              :           else
    8518              :             {
    8519           72 :               gcc_assert (POINTER_TYPE_P (caf_type));
    8520           72 :               tmp = caf_decl;
    8521              :             }
    8522              : 
    8523          108 :           tmp2 = fsym->ts.type == BT_CLASS
    8524          123 :                  ? gfc_class_data_get (parmse.expr) : parmse.expr;
    8525          123 :           if ((fsym->ts.type != BT_CLASS
    8526          108 :                && (fsym->as->type == AS_ASSUMED_SHAPE
    8527           59 :                    || fsym->as->type == AS_ASSUMED_RANK))
    8528           74 :               || (fsym->ts.type == BT_CLASS
    8529           15 :                   && (CLASS_DATA (fsym)->as->type == AS_ASSUMED_SHAPE
    8530           10 :                       || CLASS_DATA (fsym)->as->type == AS_ASSUMED_RANK)))
    8531              :             {
    8532           54 :               if (fsym->ts.type == BT_CLASS)
    8533            5 :                 gcc_assert (!POINTER_TYPE_P (TREE_TYPE (tmp2)));
    8534              :               else
    8535              :                 {
    8536           49 :                   gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
    8537           49 :                   tmp2 = build_fold_indirect_ref_loc (input_location, tmp2);
    8538              :                 }
    8539           54 :               gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)));
    8540           54 :               tmp2 = gfc_conv_descriptor_data_get (tmp2);
    8541              :             }
    8542           69 :           else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp2)))
    8543           10 :             tmp2 = gfc_conv_descriptor_data_get (tmp2);
    8544              :           else
    8545              :             {
    8546           59 :               gcc_assert (POINTER_TYPE_P (TREE_TYPE (tmp2)));
    8547              :             }
    8548              : 
    8549          123 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
    8550              :                                  gfc_array_index_type,
    8551              :                                  fold_convert (gfc_array_index_type, tmp2),
    8552              :                                  fold_convert (gfc_array_index_type, tmp));
    8553          123 :           offset = fold_build2_loc (input_location, PLUS_EXPR,
    8554              :                                     gfc_array_index_type, offset, tmp);
    8555              : 
    8556          123 :           vec_safe_push (stringargs, offset);
    8557              :         }
    8558              : 
    8559       268666 :       vec_safe_push (arglist, parmse.expr);
    8560              :     }
    8561              : 
    8562       129117 :   gfc_add_block_to_block (&se->pre, &dealloc_blk);
    8563       129117 :   gfc_add_block_to_block (&se->pre, &clobbers);
    8564       129117 :   gfc_finish_interface_mapping (&mapping, &se->pre, &se->post);
    8565              : 
    8566       129117 :   if (comp)
    8567         1974 :     ts = comp->ts;
    8568       127143 :   else if (sym->ts.type == BT_CLASS)
    8569          850 :     ts = CLASS_DATA (sym)->ts;
    8570              :   else
    8571       126293 :     ts = sym->ts;
    8572              : 
    8573       129117 :   if (ts.type == BT_CHARACTER && sym->attr.is_bind_c)
    8574          186 :     se->string_length = build_int_cst (gfc_charlen_type_node, 1);
    8575       128931 :   else if (ts.type == BT_CHARACTER)
    8576              :     {
    8577         4982 :       if (ts.u.cl->length == NULL)
    8578              :         {
    8579              :           /* Assumed character length results are not allowed by C418 of the 2003
    8580              :              standard and are trapped in resolve.cc; except in the case of SPREAD
    8581              :              (and other intrinsics?) and dummy functions.  In the case of SPREAD,
    8582              :              we take the character length of the first argument for the result.
    8583              :              For dummies, we have to look through the formal argument list for
    8584              :              this function and use the character length found there.
    8585              :              Likewise, we handle the case of deferred-length character dummy
    8586              :              arguments to intrinsics that determine the characteristics of
    8587              :              the result, which cannot be deferred-length.  */
    8588         2300 :           if (expr->value.function.isym)
    8589         1701 :             ts.deferred = false;
    8590         2300 :           if (ts.deferred)
    8591          592 :             cl.backend_decl = gfc_create_var (gfc_charlen_type_node, "slen");
    8592         1708 :           else if (!sym->attr.dummy)
    8593         1701 :             cl.backend_decl = (*stringargs)[0];
    8594              :           else
    8595              :             {
    8596            7 :               formal = gfc_sym_get_dummy_args (sym->ns->proc_name);
    8597           26 :               for (; formal; formal = formal->next)
    8598           12 :                 if (strcmp (formal->sym->name, sym->name) == 0)
    8599            7 :                   cl.backend_decl = formal->sym->ts.u.cl->backend_decl;
    8600              :             }
    8601         2300 :           len = cl.backend_decl;
    8602              :         }
    8603              :       else
    8604              :         {
    8605         2682 :           tree tmp;
    8606              : 
    8607              :           /* Calculate the length of the returned string.  */
    8608         2682 :           gfc_init_se (&parmse, NULL);
    8609         2682 :           if (need_interface_mapping)
    8610         1867 :             gfc_apply_interface_mapping (&mapping, &parmse, ts.u.cl->length);
    8611              :           else
    8612          815 :             gfc_conv_expr (&parmse, ts.u.cl->length);
    8613         2682 :           gfc_add_block_to_block (&se->pre, &parmse.pre);
    8614         2682 :           gfc_add_block_to_block (&se->post, &parmse.post);
    8615         2682 :           tmp = parmse.expr;
    8616              :           /* TODO: It would be better to have the charlens as
    8617              :              gfc_charlen_type_node already when the interface is
    8618              :              created instead of converting it here (see PR 84615).  */
    8619         2682 :           tmp = fold_build2_loc (input_location, MAX_EXPR,
    8620              :                                  gfc_charlen_type_node,
    8621              :                                  fold_convert (gfc_charlen_type_node, tmp),
    8622              :                                  build_zero_cst (gfc_charlen_type_node));
    8623         2682 :           cl.backend_decl = tmp;
    8624              :         }
    8625              : 
    8626              :       /* Set up a charlen structure for it.  */
    8627         4982 :       cl.next = NULL;
    8628         4982 :       cl.length = NULL;
    8629         4982 :       ts.u.cl = &cl;
    8630              : 
    8631         4982 :       len = cl.backend_decl;
    8632              :     }
    8633              : 
    8634         1974 :   byref = (comp && (comp->attr.dimension
    8635         1905 :            || (comp->ts.type == BT_CHARACTER && !sym->attr.is_bind_c)))
    8636       129117 :            || (!comp && gfc_return_by_reference (sym));
    8637              : 
    8638        18608 :   if (byref)
    8639              :     {
    8640        18608 :       if (se->direct_byref)
    8641              :         {
    8642              :           /* Sometimes, too much indirection can be applied; e.g. for
    8643              :              function_result = array_valued_recursive_function.  */
    8644         6962 :           if (TREE_TYPE (TREE_TYPE (se->expr))
    8645         6962 :                 && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))
    8646         6980 :                 && GFC_DESCRIPTOR_TYPE_P
    8647              :                         (TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr)))))
    8648           18 :             se->expr = build_fold_indirect_ref_loc (input_location,
    8649              :                                                     se->expr);
    8650              : 
    8651              :           /* If the lhs of an assignment x = f(..) is allocatable and
    8652              :              f2003 is allowed, we must do the automatic reallocation.
    8653              :              TODO - deal with intrinsics, without using a temporary.  */
    8654         6962 :           if (flag_realloc_lhs
    8655         6887 :                 && se->ss && se->ss->loop_chain
    8656          185 :                 && se->ss->loop_chain->is_alloc_lhs
    8657          185 :                 && !expr->value.function.isym
    8658          185 :                 && sym->result->as != NULL)
    8659              :             {
    8660              :               /* Evaluate the bounds of the result, if known.  */
    8661          185 :               gfc_set_loop_bounds_from_array_spec (&mapping, se,
    8662              :                                                    sym->result->as);
    8663              : 
    8664              :               /* Perform the automatic reallocation.  */
    8665          185 :               tmp = gfc_alloc_allocatable_for_assignment (se->loop,
    8666              :                                                           expr, NULL);
    8667          185 :               gfc_add_expr_to_block (&se->pre, tmp);
    8668              : 
    8669              :               /* Pass the temporary as the first argument.  */
    8670          185 :               result = info->descriptor;
    8671              :             }
    8672              :           else
    8673         6777 :             result = build_fold_indirect_ref_loc (input_location,
    8674              :                                                   se->expr);
    8675         6962 :           vec_safe_push (retargs, se->expr);
    8676              :         }
    8677        11646 :       else if (comp && comp->attr.dimension)
    8678              :         {
    8679           66 :           gcc_assert (se->loop && info);
    8680              : 
    8681              :           /* Set the type of the array. vtable charlens are not always reliable.
    8682              :              Use the interface, if possible.  */
    8683           66 :           if (comp->ts.type == BT_CHARACTER
    8684            1 :               && expr->symtree->n.sym->ts.type == BT_CLASS
    8685            1 :               && comp->ts.interface && comp->ts.interface->result)
    8686            1 :             tmp = gfc_typenode_for_spec (&comp->ts.interface->result->ts);
    8687              :           else
    8688           65 :             tmp = gfc_typenode_for_spec (&comp->ts);
    8689           66 :           gcc_assert (se->ss->dimen == se->loop->dimen);
    8690              : 
    8691              :           /* Evaluate the bounds of the result, if known.  */
    8692           66 :           gfc_set_loop_bounds_from_array_spec (&mapping, se, comp->as);
    8693              : 
    8694              :           /* If the lhs of an assignment x = f(..) is allocatable and
    8695              :              f2003 is allowed, we must not generate the function call
    8696              :              here but should just send back the results of the mapping.
    8697              :              This is signalled by the function ss being flagged.  */
    8698           66 :           if (flag_realloc_lhs && se->ss && se->ss->is_alloc_lhs)
    8699              :             {
    8700            0 :               gfc_free_interface_mapping (&mapping);
    8701            0 :               return has_alternate_specifier;
    8702              :             }
    8703              : 
    8704              :           /* Create a temporary to store the result.  In case the function
    8705              :              returns a pointer, the temporary will be a shallow copy and
    8706              :              mustn't be deallocated.  */
    8707           66 :           callee_alloc = comp->attr.allocatable || comp->attr.pointer;
    8708           66 :           gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
    8709              :                                        tmp, NULL_TREE, false,
    8710              :                                        !comp->attr.pointer, callee_alloc,
    8711           66 :                                        &se->ss->info->expr->where);
    8712              : 
    8713              :           /* Pass the temporary as the first argument.  */
    8714           66 :           result = info->descriptor;
    8715           66 :           tmp = gfc_build_addr_expr (NULL_TREE, result);
    8716           66 :           vec_safe_push (retargs, tmp);
    8717              :         }
    8718        11351 :       else if (!comp && sym->result->attr.dimension)
    8719              :         {
    8720         8358 :           gcc_assert (se->loop && info);
    8721              : 
    8722              :           /* Set the type of the array.  */
    8723         8358 :           tmp = gfc_typenode_for_spec (&ts);
    8724         8358 :           tmp = arg1_cntnr ? TREE_TYPE (arg1_cntnr) : tmp;
    8725         8358 :           gcc_assert (se->ss->dimen == se->loop->dimen);
    8726              : 
    8727              :           /* Evaluate the bounds of the result, if known.  */
    8728         8358 :           gfc_set_loop_bounds_from_array_spec (&mapping, se, sym->result->as);
    8729              : 
    8730              :           /* If the lhs of an assignment x = f(..) is allocatable and
    8731              :              f2003 is allowed, we must not generate the function call
    8732              :              here but should just send back the results of the mapping.
    8733              :              This is signalled by the function ss being flagged.  */
    8734         8358 :           if (flag_realloc_lhs && se->ss && se->ss->is_alloc_lhs)
    8735              :             {
    8736            0 :               gfc_free_interface_mapping (&mapping);
    8737            0 :               return has_alternate_specifier;
    8738              :             }
    8739              : 
    8740              :           /* Create a temporary to store the result.  In case the function
    8741              :              returns a pointer, the temporary will be a shallow copy and
    8742              :              mustn't be deallocated.  */
    8743         8358 :           callee_alloc = sym->attr.allocatable || sym->attr.pointer;
    8744         8358 :           gfc_trans_create_temp_array (&se->pre, &se->post, se->ss,
    8745              :                                        tmp, NULL_TREE, false,
    8746              :                                        !sym->attr.pointer, callee_alloc,
    8747         8358 :                                        &se->ss->info->expr->where);
    8748              : 
    8749              :           /* Pass the temporary as the first argument.  */
    8750         8358 :           result = info->descriptor;
    8751         8358 :           tmp = gfc_build_addr_expr (NULL_TREE, result);
    8752         8358 :           vec_safe_push (retargs, tmp);
    8753              :         }
    8754         3222 :       else if (ts.type == BT_CHARACTER)
    8755              :         {
    8756              :           /* Pass the string length.  */
    8757         3161 :           type = gfc_get_character_type (ts.kind, ts.u.cl);
    8758         3161 :           type = build_pointer_type (type);
    8759              : 
    8760              :           /* Emit a DECL_EXPR for the VLA type.  */
    8761         3161 :           tmp = TREE_TYPE (type);
    8762         3161 :           if (TYPE_SIZE (tmp)
    8763         3161 :               && TREE_CODE (TYPE_SIZE (tmp)) != INTEGER_CST)
    8764              :             {
    8765         1922 :               tmp = build_decl (input_location, TYPE_DECL, NULL_TREE, tmp);
    8766         1922 :               DECL_ARTIFICIAL (tmp) = 1;
    8767         1922 :               DECL_IGNORED_P (tmp) = 1;
    8768         1922 :               tmp = fold_build1_loc (input_location, DECL_EXPR,
    8769         1922 :                                      TREE_TYPE (tmp), tmp);
    8770         1922 :               gfc_add_expr_to_block (&se->pre, tmp);
    8771              :             }
    8772              : 
    8773              :           /* Return an address to a char[0:len-1]* temporary for
    8774              :              character pointers.  */
    8775         3161 :           if ((!comp && (sym->attr.pointer || sym->attr.allocatable))
    8776          229 :                || (comp && (comp->attr.pointer || comp->attr.allocatable)))
    8777              :             {
    8778          635 :               var = gfc_create_var (type, "pstr");
    8779              : 
    8780          635 :               if ((!comp && sym->attr.allocatable)
    8781           21 :                   || (comp && comp->attr.allocatable))
    8782              :                 {
    8783          348 :                   gfc_add_modify (&se->pre, var,
    8784          348 :                                   fold_convert (TREE_TYPE (var),
    8785              :                                                 null_pointer_node));
    8786          348 :                   tmp = gfc_call_free (var);
    8787          348 :                   gfc_add_expr_to_block (&se->post, tmp);
    8788              :                 }
    8789              : 
    8790              :               /* Provide an address expression for the function arguments.  */
    8791          635 :               var = gfc_build_addr_expr (NULL_TREE, var);
    8792              :             }
    8793              :           else
    8794         2526 :             var = gfc_conv_string_tmp (se, type, len);
    8795              : 
    8796         3161 :           vec_safe_push (retargs, var);
    8797              :         }
    8798              :       else
    8799              :         {
    8800           61 :           gcc_assert (flag_f2c && ts.type == BT_COMPLEX);
    8801              : 
    8802           61 :           type = gfc_get_complex_type (ts.kind);
    8803           61 :           var = gfc_build_addr_expr (NULL_TREE, gfc_create_var (type, "cmplx"));
    8804           61 :           vec_safe_push (retargs, var);
    8805              :         }
    8806              : 
    8807              :       /* Add the string length to the argument list.  */
    8808        18608 :       if (ts.type == BT_CHARACTER && ts.deferred)
    8809              :         {
    8810          592 :           tmp = len;
    8811          592 :           if (!VAR_P (tmp))
    8812            0 :             tmp = gfc_evaluate_now (len, &se->pre);
    8813          592 :           TREE_STATIC (tmp) = 1;
    8814          592 :           gfc_add_modify (&se->pre, tmp,
    8815          592 :                           build_int_cst (TREE_TYPE (tmp), 0));
    8816          592 :           tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    8817          592 :           vec_safe_push (retargs, tmp);
    8818              :         }
    8819        18016 :       else if (ts.type == BT_CHARACTER)
    8820         4390 :         vec_safe_push (retargs, len);
    8821              :     }
    8822              : 
    8823       129117 :   gfc_free_interface_mapping (&mapping);
    8824              : 
    8825              :   /* We need to glom RETARGS + ARGLIST + STRINGARGS + APPEND_ARGS.  */
    8826       240498 :   arglen = (vec_safe_length (arglist) + vec_safe_length (optionalargs)
    8827       154403 :             + vec_safe_length (stringargs) + vec_safe_length (append_args));
    8828       129117 :   vec_safe_reserve (retargs, arglen);
    8829              : 
    8830              :   /* Add the return arguments.  */
    8831       129117 :   vec_safe_splice (retargs, arglist);
    8832              : 
    8833              :   /* Add the hidden present status for optional+value to the arguments.  */
    8834       129117 :   vec_safe_splice (retargs, optionalargs);
    8835              : 
    8836              :   /* Add the hidden string length parameters to the arguments.  */
    8837       129117 :   vec_safe_splice (retargs, stringargs);
    8838              : 
    8839              :   /* We may want to append extra arguments here.  This is used e.g. for
    8840              :      calls to libgfortran_matmul_??, which need extra information.  */
    8841       129117 :   vec_safe_splice (retargs, append_args);
    8842              : 
    8843       129117 :   arglist = retargs;
    8844              : 
    8845              :   /* Generate the actual call.  */
    8846       129117 :   is_builtin = false;
    8847       129117 :   if (base_object == NULL_TREE)
    8848       129037 :     conv_function_val (se, &is_builtin, sym, expr, args);
    8849              :   else
    8850           80 :     conv_base_obj_fcn_val (se, base_object, expr);
    8851              : 
    8852              :   /* If there are alternate return labels, function type should be
    8853              :      integer.  Can't modify the type in place though, since it can be shared
    8854              :      with other functions.  For dummy arguments, the typing is done to
    8855              :      this result, even if it has to be repeated for each call.  */
    8856       129117 :   if (has_alternate_specifier
    8857       129117 :       && TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) != integer_type_node)
    8858              :     {
    8859            7 :       if (!sym->attr.dummy)
    8860              :         {
    8861            0 :           TREE_TYPE (sym->backend_decl)
    8862            0 :                 = build_function_type (integer_type_node,
    8863            0 :                       TYPE_ARG_TYPES (TREE_TYPE (sym->backend_decl)));
    8864            0 :           se->expr = gfc_build_addr_expr (NULL_TREE, sym->backend_decl);
    8865              :         }
    8866              :       else
    8867            7 :         TREE_TYPE (TREE_TYPE (TREE_TYPE (se->expr))) = integer_type_node;
    8868              :     }
    8869              : 
    8870       129117 :   fntype = TREE_TYPE (TREE_TYPE (se->expr));
    8871       129117 :   se->expr = build_call_vec (TREE_TYPE (fntype), se->expr, arglist);
    8872              : 
    8873       129117 :   if (is_builtin)
    8874          522 :     se->expr = update_builtin_function (se->expr, sym);
    8875              : 
    8876              :   /* Allocatable scalar function results must be freed and nullified
    8877              :      after use. This necessitates the creation of a temporary to
    8878              :      hold the result to prevent duplicate calls.  */
    8879       129117 :   symbol_attribute attr =  comp ? comp->attr : sym->attr;
    8880       129117 :   bool allocatable = attr.allocatable && !attr.dimension;
    8881       132304 :   gfc_symbol *der = comp ?
    8882         1974 :                     comp->ts.type == BT_DERIVED ? comp->ts.u.derived : NULL
    8883              :                          :
    8884       127143 :                     sym->ts.type == BT_DERIVED ? sym->ts.u.derived : NULL;
    8885         3187 :   bool finalizable = der != NULL && der->ns->proc_name
    8886         6371 :                             && gfc_is_finalizable (der, NULL);
    8887              : 
    8888       129117 :   if (!byref && finalizable)
    8889          182 :     gfc_finalize_tree_expr (se, der, attr, expr->rank);
    8890              : 
    8891       129117 :   if (!byref && sym->ts.type != BT_CHARACTER
    8892       110323 :       && allocatable && !finalizable)
    8893              :     {
    8894          230 :       tmp = gfc_create_var (TREE_TYPE (se->expr), NULL);
    8895          230 :       gfc_add_modify (&se->pre, tmp, se->expr);
    8896          230 :       se->expr = tmp;
    8897          230 :       tmp = gfc_call_free (tmp);
    8898          230 :       gfc_add_expr_to_block (&post, tmp);
    8899          230 :       gfc_add_modify (&post, se->expr, build_int_cst (TREE_TYPE (se->expr), 0));
    8900              :     }
    8901              : 
    8902              :   /* If we have a pointer function, but we don't want a pointer, e.g.
    8903              :      something like
    8904              :         x = f()
    8905              :      where f is pointer valued, we have to dereference the result.  */
    8906       129117 :   if (!se->want_pointer && !byref
    8907       109907 :       && ((!comp && (sym->attr.pointer || sym->attr.allocatable))
    8908         1632 :           || (comp && (comp->attr.pointer || comp->attr.allocatable))))
    8909          456 :     se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
    8910              : 
    8911              :   /* f2c calling conventions require a scalar default real function to
    8912              :      return a double precision result.  Convert this back to default
    8913              :      real.  We only care about the cases that can happen in Fortran 77.
    8914              :   */
    8915       129117 :   if (flag_f2c && sym->ts.type == BT_REAL
    8916           98 :       && sym->ts.kind == gfc_default_real_kind
    8917           74 :       && !sym->attr.pointer
    8918           55 :       && !sym->attr.allocatable
    8919           43 :       && !sym->attr.always_explicit)
    8920           43 :     se->expr = fold_convert (gfc_get_real_type (sym->ts.kind), se->expr);
    8921              : 
    8922              :   /* A pure function may still have side-effects - it may modify its
    8923              :      parameters.  */
    8924       129117 :   TREE_SIDE_EFFECTS (se->expr) = 1;
    8925              : #if 0
    8926              :   if (!sym->attr.pure)
    8927              :     TREE_SIDE_EFFECTS (se->expr) = 1;
    8928              : #endif
    8929              : 
    8930       129117 :   if (byref)
    8931              :     {
    8932              :       /* Add the function call to the pre chain.  There is no expression.  */
    8933        18608 :       gfc_add_expr_to_block (&se->pre, se->expr);
    8934        18608 :       se->expr = NULL_TREE;
    8935              : 
    8936        18608 :       if (!se->direct_byref)
    8937              :         {
    8938        11646 :           if ((sym->attr.dimension && !comp) || (comp && comp->attr.dimension))
    8939              :             {
    8940         8424 :               if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    8941              :                 {
    8942              :                   /* Check the data pointer hasn't been modified.  This would
    8943              :                      happen in a function returning a pointer.  */
    8944          251 :                   tmp = gfc_conv_descriptor_data_get (info->descriptor);
    8945          251 :                   tmp = fold_build2_loc (input_location, NE_EXPR,
    8946              :                                          logical_type_node,
    8947              :                                          tmp, info->data);
    8948          251 :                   gfc_trans_runtime_check (true, false, tmp, &se->pre, NULL,
    8949              :                                            gfc_msg_fault);
    8950              :                 }
    8951         8424 :               se->expr = info->descriptor;
    8952              :               /* Bundle in the string length.  */
    8953         8424 :               se->string_length = len;
    8954              : 
    8955         8424 :               if (finalizable)
    8956            6 :                 gfc_finalize_tree_expr (se, der, attr, expr->rank);
    8957              :             }
    8958         3222 :           else if (ts.type == BT_CHARACTER)
    8959              :             {
    8960              :               /* Dereference for character pointer results.  */
    8961         3161 :               if ((!comp && (sym->attr.pointer || sym->attr.allocatable))
    8962          229 :                   || (comp && (comp->attr.pointer || comp->attr.allocatable)))
    8963          635 :                 se->expr = build_fold_indirect_ref_loc (input_location, var);
    8964              :               else
    8965         2526 :                 se->expr = var;
    8966              : 
    8967         3161 :               se->string_length = len;
    8968              :             }
    8969              :           else
    8970              :             {
    8971           61 :               gcc_assert (ts.type == BT_COMPLEX && flag_f2c);
    8972           61 :               se->expr = build_fold_indirect_ref_loc (input_location, var);
    8973              :             }
    8974              :         }
    8975              :     }
    8976              : 
    8977              :   /* Associate the rhs class object's meta-data with the result, when the
    8978              :      result is a temporary.  */
    8979       111386 :   if (args && args->expr && args->expr->ts.type == BT_CLASS
    8980         4943 :       && sym->ts.type == BT_CLASS && result != NULL_TREE && DECL_P (result)
    8981       129149 :       && !GFC_CLASS_TYPE_P (TREE_TYPE (result)))
    8982              :     {
    8983           32 :       gfc_se parmse;
    8984           32 :       gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (args->expr);
    8985              : 
    8986           32 :       gfc_init_se (&parmse, NULL);
    8987           32 :       parmse.data_not_needed = 1;
    8988           32 :       gfc_conv_expr (&parmse, class_expr);
    8989           32 :       if (!DECL_LANG_SPECIFIC (result))
    8990           32 :         gfc_allocate_lang_decl (result);
    8991           32 :       GFC_DECL_SAVED_DESCRIPTOR (result) = parmse.expr;
    8992           32 :       gfc_free_expr (class_expr);
    8993              :       /* -fcheck= can add diagnostic code, which has to be placed before
    8994              :          the call. */
    8995           32 :       if (parmse.pre.head != NULL)
    8996           12 :           gfc_add_expr_to_block (&se->pre, parmse.pre.head);
    8997           32 :       gcc_assert (parmse.post.head == NULL_TREE);
    8998              :     }
    8999              : 
    9000              :   /* Follow the function call with the argument post block.  */
    9001       129117 :   if (byref)
    9002              :     {
    9003        18608 :       gfc_add_block_to_block (&se->pre, &post);
    9004              : 
    9005              :       /* Transformational functions of derived types with allocatable
    9006              :          components must have the result allocatable components copied when the
    9007              :          argument is actually given.  This is unnecessry for REDUCE because the
    9008              :          wrapper for the OPERATION function takes care of this.  */
    9009        18608 :       arg = expr->value.function.actual;
    9010        18608 :       if (result && arg && expr->rank
    9011        14557 :           && isym && isym->transformational
    9012        12988 :           && isym->id != GFC_ISYM_REDUCE
    9013        12862 :           && arg->expr
    9014        12802 :           && arg->expr->ts.type == BT_DERIVED
    9015          229 :           && arg->expr->ts.u.derived->attr.alloc_comp)
    9016              :         {
    9017           36 :           tree tmp2;
    9018              :           /* Copy the allocatable components.  We have to use a
    9019              :              temporary here to prevent source allocatable components
    9020              :              from being corrupted.  */
    9021           36 :           tmp2 = gfc_evaluate_now (result, &se->pre);
    9022           36 :           tmp = gfc_copy_alloc_comp (arg->expr->ts.u.derived,
    9023              :                                      result, tmp2, expr->rank, 0);
    9024           36 :           gfc_add_expr_to_block (&se->pre, tmp);
    9025           36 :           tmp = gfc_copy_allocatable_data (result, tmp2, TREE_TYPE(tmp2),
    9026              :                                            expr->rank);
    9027           36 :           gfc_add_expr_to_block (&se->pre, tmp);
    9028              : 
    9029              :           /* Finally free the temporary's data field.  */
    9030           36 :           tmp = gfc_conv_descriptor_data_get (tmp2);
    9031           36 :           tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
    9032              :                                             NULL_TREE, NULL_TREE, true,
    9033              :                                             NULL, GFC_CAF_COARRAY_NOCOARRAY);
    9034           36 :           gfc_add_expr_to_block (&se->pre, tmp);
    9035              :         }
    9036              :     }
    9037              :   else
    9038              :     {
    9039              :       /* For a function with a class array result, save the result as
    9040              :          a temporary, set the info fields needed by the scalarizer and
    9041              :          call the finalization function of the temporary. Note that the
    9042              :          nullification of allocatable components needed by the result
    9043              :          is done in gfc_trans_assignment_1.  */
    9044        34406 :       if (expr && (gfc_is_class_array_function (expr)
    9045        34084 :                    || gfc_is_alloc_class_scalar_function (expr))
    9046          841 :           && se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
    9047       111338 :           && expr->must_finalize)
    9048              :         {
    9049              :           /* TODO Eliminate the doubling of temporaries.  This
    9050              :              one is necessary to ensure no memory leakage.  */
    9051          321 :           se->expr = gfc_evaluate_now (se->expr, &se->pre);
    9052              : 
    9053              :           /* Finalize the result, if necessary.  */
    9054          642 :           attr = expr->value.function.esym
    9055          321 :                  ? CLASS_DATA (expr->value.function.esym->result)->attr
    9056           14 :                  : CLASS_DATA (expr)->attr;
    9057          321 :           if (!((gfc_is_class_array_function (expr)
    9058          108 :                  || gfc_is_alloc_class_scalar_function (expr))
    9059          321 :                 && attr.pointer))
    9060          276 :             gfc_finalize_tree_expr (se, NULL, attr, expr->rank);
    9061              :         }
    9062       110509 :       gfc_add_block_to_block (&se->post, &post);
    9063              :     }
    9064              : 
    9065              :   return has_alternate_specifier;
    9066              : }
    9067              : 
    9068              : 
    9069              : /* Fill a character string with spaces.  */
    9070              : 
    9071              : static tree
    9072        30377 : fill_with_spaces (tree start, tree type, tree size)
    9073              : {
    9074        30377 :   stmtblock_t block, loop;
    9075        30377 :   tree i, el, exit_label, cond, tmp;
    9076              : 
    9077              :   /* For a simple char type, we can call memset().  */
    9078        30377 :   if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
    9079        50166 :     return build_call_expr_loc (input_location,
    9080              :                             builtin_decl_explicit (BUILT_IN_MEMSET),
    9081              :                             3, start,
    9082              :                             build_int_cst (gfc_get_int_type (gfc_c_int_kind),
    9083        25083 :                                            lang_hooks.to_target_charset (' ')),
    9084              :                                 fold_convert (size_type_node, size));
    9085              : 
    9086              :   /* Otherwise, we use a loop:
    9087              :         for (el = start, i = size; i > 0; el--, i+= TYPE_SIZE_UNIT (type))
    9088              :           *el = (type) ' ';
    9089              :    */
    9090              : 
    9091              :   /* Initialize variables.  */
    9092         5294 :   gfc_init_block (&block);
    9093         5294 :   i = gfc_create_var (sizetype, "i");
    9094         5294 :   gfc_add_modify (&block, i, fold_convert (sizetype, size));
    9095         5294 :   el = gfc_create_var (build_pointer_type (type), "el");
    9096         5294 :   gfc_add_modify (&block, el, fold_convert (TREE_TYPE (el), start));
    9097         5294 :   exit_label = gfc_build_label_decl (NULL_TREE);
    9098         5294 :   TREE_USED (exit_label) = 1;
    9099              : 
    9100              : 
    9101              :   /* Loop body.  */
    9102         5294 :   gfc_init_block (&loop);
    9103              : 
    9104              :   /* Exit condition.  */
    9105         5294 :   cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, i,
    9106              :                           build_zero_cst (sizetype));
    9107         5294 :   tmp = build1_v (GOTO_EXPR, exit_label);
    9108         5294 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
    9109              :                          build_empty_stmt (input_location));
    9110         5294 :   gfc_add_expr_to_block (&loop, tmp);
    9111              : 
    9112              :   /* Assignment.  */
    9113         5294 :   gfc_add_modify (&loop,
    9114              :                   fold_build1_loc (input_location, INDIRECT_REF, type, el),
    9115         5294 :                   build_int_cst (type, lang_hooks.to_target_charset (' ')));
    9116              : 
    9117              :   /* Increment loop variables.  */
    9118         5294 :   gfc_add_modify (&loop, i,
    9119              :                   fold_build2_loc (input_location, MINUS_EXPR, sizetype, i,
    9120         5294 :                                    TYPE_SIZE_UNIT (type)));
    9121         5294 :   gfc_add_modify (&loop, el,
    9122              :                   fold_build_pointer_plus_loc (input_location,
    9123         5294 :                                                el, TYPE_SIZE_UNIT (type)));
    9124              : 
    9125              :   /* Making the loop... actually loop!  */
    9126         5294 :   tmp = gfc_finish_block (&loop);
    9127         5294 :   tmp = build1_v (LOOP_EXPR, tmp);
    9128         5294 :   gfc_add_expr_to_block (&block, tmp);
    9129              : 
    9130              :   /* The exit label.  */
    9131         5294 :   tmp = build1_v (LABEL_EXPR, exit_label);
    9132         5294 :   gfc_add_expr_to_block (&block, tmp);
    9133              : 
    9134              : 
    9135         5294 :   return gfc_finish_block (&block);
    9136              : }
    9137              : 
    9138              : 
    9139              : /* Generate code to copy a string.  */
    9140              : 
    9141              : void
    9142        35479 : gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
    9143              :                        int dkind, tree slength, tree src, int skind)
    9144              : {
    9145        35479 :   tree tmp, dlen, slen;
    9146        35479 :   tree dsc;
    9147        35479 :   tree ssc;
    9148        35479 :   tree cond;
    9149        35479 :   tree cond2;
    9150        35479 :   tree tmp2;
    9151        35479 :   tree tmp3;
    9152        35479 :   tree tmp4;
    9153        35479 :   tree chartype;
    9154        35479 :   stmtblock_t tempblock;
    9155              : 
    9156        35479 :   gcc_assert (dkind == skind);
    9157              : 
    9158        35479 :   if (slength != NULL_TREE)
    9159              :     {
    9160        35479 :       slen = gfc_evaluate_now (fold_convert (gfc_charlen_type_node, slength), block);
    9161        35479 :       ssc = gfc_string_to_single_character (slen, src, skind);
    9162              :     }
    9163              :   else
    9164              :     {
    9165            0 :       slen = build_one_cst (gfc_charlen_type_node);
    9166            0 :       ssc =  src;
    9167              :     }
    9168              : 
    9169        35479 :   if (dlength != NULL_TREE)
    9170              :     {
    9171        35479 :       dlen = gfc_evaluate_now (fold_convert (gfc_charlen_type_node, dlength), block);
    9172        35479 :       dsc = gfc_string_to_single_character (dlen, dest, dkind);
    9173              :     }
    9174              :   else
    9175              :     {
    9176            0 :       dlen = build_one_cst (gfc_charlen_type_node);
    9177            0 :       dsc =  dest;
    9178              :     }
    9179              : 
    9180              :   /* Assign directly if the types are compatible.  */
    9181        35479 :   if (dsc != NULL_TREE && ssc != NULL_TREE
    9182        35479 :       && TREE_TYPE (dsc) == TREE_TYPE (ssc))
    9183              :     {
    9184         5102 :       gfc_add_modify (block, dsc, ssc);
    9185         5102 :       return;
    9186              :     }
    9187              : 
    9188              :   /* The string copy algorithm below generates code like
    9189              : 
    9190              :      if (destlen > 0)
    9191              :        {
    9192              :          if (srclen < destlen)
    9193              :            {
    9194              :              memmove (dest, src, srclen);
    9195              :              // Pad with spaces.
    9196              :              memset (&dest[srclen], ' ', destlen - srclen);
    9197              :            }
    9198              :          else
    9199              :            {
    9200              :              // Truncate if too long.
    9201              :              memmove (dest, src, destlen);
    9202              :            }
    9203              :        }
    9204              :   */
    9205              : 
    9206              :   /* Do nothing if the destination length is zero.  */
    9207        30377 :   cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, dlen,
    9208        30377 :                           build_zero_cst (TREE_TYPE (dlen)));
    9209              : 
    9210              :   /* For non-default character kinds, we have to multiply the string
    9211              :      length by the base type size.  */
    9212        30377 :   chartype = gfc_get_char_type (dkind);
    9213        30377 :   slen = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (slen),
    9214              :                           slen,
    9215        30377 :                           fold_convert (TREE_TYPE (slen),
    9216              :                                         TYPE_SIZE_UNIT (chartype)));
    9217        30377 :   dlen = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (dlen),
    9218              :                           dlen,
    9219        30377 :                           fold_convert (TREE_TYPE (dlen),
    9220              :                                         TYPE_SIZE_UNIT (chartype)));
    9221              : 
    9222        30377 :   if (dlength && POINTER_TYPE_P (TREE_TYPE (dest)))
    9223        30329 :     dest = fold_convert (pvoid_type_node, dest);
    9224              :   else
    9225           48 :     dest = gfc_build_addr_expr (pvoid_type_node, dest);
    9226              : 
    9227        30377 :   if (slength && POINTER_TYPE_P (TREE_TYPE (src)))
    9228        30373 :     src = fold_convert (pvoid_type_node, src);
    9229              :   else
    9230            4 :     src = gfc_build_addr_expr (pvoid_type_node, src);
    9231              : 
    9232              :   /* Truncate string if source is too long.  */
    9233        30377 :   cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, slen,
    9234              :                            dlen);
    9235              : 
    9236              :   /* Pre-evaluate pointers unless one of the IF arms will be optimized away.  */
    9237        30377 :   if (!CONSTANT_CLASS_P (cond2))
    9238              :     {
    9239         9308 :       dest = gfc_evaluate_now (dest, block);
    9240         9308 :       src = gfc_evaluate_now (src, block);
    9241              :     }
    9242              : 
    9243              :   /* Copy and pad with spaces.  */
    9244        30377 :   tmp3 = build_call_expr_loc (input_location,
    9245              :                               builtin_decl_explicit (BUILT_IN_MEMMOVE),
    9246              :                               3, dest, src,
    9247              :                               fold_convert (size_type_node, slen));
    9248              : 
    9249              :   /* Wstringop-overflow appears at -O3 even though this warning is not
    9250              :      explicitly available in fortran nor can it be switched off. If the
    9251              :      source length is a constant, its negative appears as a very large
    9252              :      positive number and triggers the warning in BUILTIN_MEMSET. Fixing
    9253              :      the result of the MINUS_EXPR suppresses this spurious warning.  */
    9254        30377 :   tmp = fold_build2_loc (input_location, MINUS_EXPR,
    9255        30377 :                          TREE_TYPE(dlen), dlen, slen);
    9256        30377 :   if (slength && TREE_CONSTANT (slength))
    9257        26860 :     tmp = gfc_evaluate_now (tmp, block);
    9258              : 
    9259        30377 :   tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
    9260        30377 :   tmp4 = fill_with_spaces (tmp4, chartype, tmp);
    9261              : 
    9262        30377 :   gfc_init_block (&tempblock);
    9263        30377 :   gfc_add_expr_to_block (&tempblock, tmp3);
    9264        30377 :   gfc_add_expr_to_block (&tempblock, tmp4);
    9265        30377 :   tmp3 = gfc_finish_block (&tempblock);
    9266              : 
    9267              :   /* The truncated memmove if the slen >= dlen.  */
    9268        30377 :   tmp2 = build_call_expr_loc (input_location,
    9269              :                               builtin_decl_explicit (BUILT_IN_MEMMOVE),
    9270              :                               3, dest, src,
    9271              :                               fold_convert (size_type_node, dlen));
    9272              : 
    9273              :   /* The whole copy_string function is there.  */
    9274        30377 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
    9275              :                          tmp3, tmp2);
    9276        30377 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
    9277              :                          build_empty_stmt (input_location));
    9278        30377 :   gfc_add_expr_to_block (block, tmp);
    9279              : }
    9280              : 
    9281              : 
    9282              : /* Translate a statement function.
    9283              :    The value of a statement function reference is obtained by evaluating the
    9284              :    expression using the values of the actual arguments for the values of the
    9285              :    corresponding dummy arguments.  */
    9286              : 
    9287              : static void
    9288          269 : gfc_conv_statement_function (gfc_se * se, gfc_expr * expr)
    9289              : {
    9290          269 :   gfc_symbol *sym;
    9291          269 :   gfc_symbol *fsym;
    9292          269 :   gfc_formal_arglist *fargs;
    9293          269 :   gfc_actual_arglist *args;
    9294          269 :   gfc_se lse;
    9295          269 :   gfc_se rse;
    9296          269 :   gfc_saved_var *saved_vars;
    9297          269 :   tree *temp_vars;
    9298          269 :   tree type;
    9299          269 :   tree tmp;
    9300          269 :   int n;
    9301              : 
    9302          269 :   sym = expr->symtree->n.sym;
    9303          269 :   args = expr->value.function.actual;
    9304          269 :   gfc_init_se (&lse, NULL);
    9305          269 :   gfc_init_se (&rse, NULL);
    9306              : 
    9307          269 :   n = 0;
    9308          727 :   for (fargs = gfc_sym_get_dummy_args (sym); fargs; fargs = fargs->next)
    9309          458 :     n++;
    9310          269 :   saved_vars = XCNEWVEC (gfc_saved_var, n);
    9311          269 :   temp_vars = XCNEWVEC (tree, n);
    9312              : 
    9313          727 :   for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
    9314          458 :        fargs = fargs->next, n++)
    9315              :     {
    9316              :       /* Each dummy shall be specified, explicitly or implicitly, to be
    9317              :          scalar.  */
    9318          458 :       gcc_assert (fargs->sym->attr.dimension == 0);
    9319          458 :       fsym = fargs->sym;
    9320              : 
    9321          458 :       if (fsym->ts.type == BT_CHARACTER)
    9322              :         {
    9323              :           /* Copy string arguments.  */
    9324           48 :           tree arglen;
    9325              : 
    9326           48 :           gcc_assert (fsym->ts.u.cl && fsym->ts.u.cl->length
    9327              :                       && fsym->ts.u.cl->length->expr_type == EXPR_CONSTANT);
    9328              : 
    9329              :           /* Create a temporary to hold the value.  */
    9330           48 :           if (fsym->ts.u.cl->backend_decl == NULL_TREE)
    9331            1 :              fsym->ts.u.cl->backend_decl
    9332            1 :                 = gfc_conv_constant_to_tree (fsym->ts.u.cl->length);
    9333              : 
    9334           48 :           type = gfc_get_character_type (fsym->ts.kind, fsym->ts.u.cl);
    9335           48 :           temp_vars[n] = gfc_create_var (type, fsym->name);
    9336              : 
    9337           48 :           arglen = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
    9338              : 
    9339           48 :           gfc_conv_expr (&rse, args->expr);
    9340           48 :           gfc_conv_string_parameter (&rse);
    9341           48 :           gfc_add_block_to_block (&se->pre, &lse.pre);
    9342           48 :           gfc_add_block_to_block (&se->pre, &rse.pre);
    9343              : 
    9344           48 :           gfc_trans_string_copy (&se->pre, arglen, temp_vars[n], fsym->ts.kind,
    9345              :                                  rse.string_length, rse.expr, fsym->ts.kind);
    9346           48 :           gfc_add_block_to_block (&se->pre, &lse.post);
    9347           48 :           gfc_add_block_to_block (&se->pre, &rse.post);
    9348              :         }
    9349              :       else
    9350              :         {
    9351              :           /* For everything else, just evaluate the expression.  */
    9352              : 
    9353              :           /* Create a temporary to hold the value.  */
    9354          410 :           type = gfc_typenode_for_spec (&fsym->ts);
    9355          410 :           temp_vars[n] = gfc_create_var (type, fsym->name);
    9356              : 
    9357          410 :           gfc_conv_expr (&lse, args->expr);
    9358              : 
    9359          410 :           gfc_add_block_to_block (&se->pre, &lse.pre);
    9360          410 :           gfc_add_modify (&se->pre, temp_vars[n], lse.expr);
    9361          410 :           gfc_add_block_to_block (&se->pre, &lse.post);
    9362              :         }
    9363              : 
    9364          458 :       args = args->next;
    9365              :     }
    9366              : 
    9367              :   /* Use the temporary variables in place of the real ones.  */
    9368          727 :   for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
    9369          458 :        fargs = fargs->next, n++)
    9370          458 :     gfc_shadow_sym (fargs->sym, temp_vars[n], &saved_vars[n]);
    9371              : 
    9372          269 :   gfc_conv_expr (se, sym->value);
    9373              : 
    9374          269 :   if (sym->ts.type == BT_CHARACTER)
    9375              :     {
    9376           55 :       gfc_conv_const_charlen (sym->ts.u.cl);
    9377              : 
    9378              :       /* Force the expression to the correct length.  */
    9379           55 :       if (!INTEGER_CST_P (se->string_length)
    9380          101 :           || tree_int_cst_lt (se->string_length,
    9381           46 :                               sym->ts.u.cl->backend_decl))
    9382              :         {
    9383           31 :           type = gfc_get_character_type (sym->ts.kind, sym->ts.u.cl);
    9384           31 :           tmp = gfc_create_var (type, sym->name);
    9385           31 :           tmp = gfc_build_addr_expr (build_pointer_type (type), tmp);
    9386           31 :           gfc_trans_string_copy (&se->pre, sym->ts.u.cl->backend_decl, tmp,
    9387              :                                  sym->ts.kind, se->string_length, se->expr,
    9388              :                                  sym->ts.kind);
    9389           31 :           se->expr = tmp;
    9390              :         }
    9391           55 :       se->string_length = sym->ts.u.cl->backend_decl;
    9392              :     }
    9393              : 
    9394              :   /* Restore the original variables.  */
    9395          727 :   for (fargs = gfc_sym_get_dummy_args (sym), n = 0; fargs;
    9396          458 :        fargs = fargs->next, n++)
    9397          458 :     gfc_restore_sym (fargs->sym, &saved_vars[n]);
    9398          269 :   free (temp_vars);
    9399          269 :   free (saved_vars);
    9400          269 : }
    9401              : 
    9402              : 
    9403              : /* Translate a function expression.  */
    9404              : 
    9405              : static void
    9406       308232 : gfc_conv_function_expr (gfc_se * se, gfc_expr * expr)
    9407              : {
    9408       308232 :   gfc_symbol *sym;
    9409              : 
    9410       308232 :   if (expr->value.function.isym)
    9411              :     {
    9412       258060 :       gfc_conv_intrinsic_function (se, expr);
    9413       258060 :       return;
    9414              :     }
    9415              : 
    9416              :   /* expr.value.function.esym is the resolved (specific) function symbol for
    9417              :      most functions.  However this isn't set for dummy procedures.  */
    9418        50172 :   sym = expr->value.function.esym;
    9419        50172 :   if (!sym)
    9420         1616 :     sym = expr->symtree->n.sym;
    9421              : 
    9422              :   /* The IEEE_ARITHMETIC functions are caught here. */
    9423        50172 :   if (sym->from_intmod == INTMOD_IEEE_ARITHMETIC)
    9424        13939 :     if (gfc_conv_ieee_arithmetic_function (se, expr))
    9425              :       return;
    9426              : 
    9427              :   /* We distinguish statement functions from general functions to improve
    9428              :      runtime performance.  */
    9429        37715 :   if (sym->attr.proc == PROC_ST_FUNCTION)
    9430              :     {
    9431          269 :       gfc_conv_statement_function (se, expr);
    9432          269 :       return;
    9433              :     }
    9434              : 
    9435        37446 :   gfc_conv_procedure_call (se, sym, expr->value.function.actual, expr,
    9436              :                            NULL);
    9437              : }
    9438              : 
    9439              : 
    9440              : /* Determine whether the given EXPR_CONSTANT is a zero initializer.  */
    9441              : 
    9442              : static bool
    9443        39127 : is_zero_initializer_p (gfc_expr * expr)
    9444              : {
    9445        39127 :   if (expr->expr_type != EXPR_CONSTANT)
    9446              :     return false;
    9447              : 
    9448              :   /* We ignore constants with prescribed memory representations for now.  */
    9449        11356 :   if (expr->representation.string)
    9450              :     return false;
    9451              : 
    9452        11338 :   switch (expr->ts.type)
    9453              :     {
    9454         5220 :     case BT_INTEGER:
    9455         5220 :       return mpz_cmp_si (expr->value.integer, 0) == 0;
    9456              : 
    9457         4817 :     case BT_REAL:
    9458         4817 :       return mpfr_zero_p (expr->value.real)
    9459         4817 :              && MPFR_SIGN (expr->value.real) >= 0;
    9460              : 
    9461          925 :     case BT_LOGICAL:
    9462          925 :       return expr->value.logical == 0;
    9463              : 
    9464          242 :     case BT_COMPLEX:
    9465          242 :       return mpfr_zero_p (mpc_realref (expr->value.complex))
    9466          154 :              && MPFR_SIGN (mpc_realref (expr->value.complex)) >= 0
    9467          154 :              && mpfr_zero_p (mpc_imagref (expr->value.complex))
    9468          384 :              && MPFR_SIGN (mpc_imagref (expr->value.complex)) >= 0;
    9469              : 
    9470              :     default:
    9471              :       break;
    9472              :     }
    9473              :   return false;
    9474              : }
    9475              : 
    9476              : 
    9477              : static void
    9478        35238 : gfc_conv_array_constructor_expr (gfc_se * se, gfc_expr * expr)
    9479              : {
    9480        35238 :   gfc_ss *ss;
    9481              : 
    9482        35238 :   ss = se->ss;
    9483        35238 :   gcc_assert (ss != NULL && ss != gfc_ss_terminator);
    9484        35238 :   gcc_assert (ss->info->expr == expr && ss->info->type == GFC_SS_CONSTRUCTOR);
    9485              : 
    9486        35238 :   gfc_conv_tmp_array_ref (se);
    9487        35238 : }
    9488              : 
    9489              : 
    9490              : /* Build a static initializer.  EXPR is the expression for the initial value.
    9491              :    The other parameters describe the variable of the component being
    9492              :    initialized. EXPR may be null.  */
    9493              : 
    9494              : tree
    9495       139947 : gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type,
    9496              :                       bool array, bool pointer, bool procptr)
    9497              : {
    9498       139947 :   gfc_se se;
    9499              : 
    9500       139947 :   if (flag_coarray != GFC_FCOARRAY_LIB && ts->type == BT_DERIVED
    9501        44800 :       && ts->u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
    9502          165 :       && ts->u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
    9503           57 :     return build_constructor (type, NULL);
    9504              : 
    9505       139890 :   if (!(expr || pointer || procptr))
    9506              :     return NULL_TREE;
    9507              : 
    9508              :   /* Check if we have ISOCBINDING_NULL_PTR or ISOCBINDING_NULL_FUNPTR
    9509              :      (these are the only two iso_c_binding derived types that can be
    9510              :      used as initialization expressions).  If so, we need to modify
    9511              :      the 'expr' to be that for a (void *).  */
    9512       131554 :   if (expr != NULL && expr->ts.type == BT_DERIVED
    9513        40587 :       && expr->ts.is_iso_c && expr->ts.u.derived)
    9514              :     {
    9515          186 :       if (TREE_CODE (type) == ARRAY_TYPE)
    9516            4 :         return build_constructor (type, NULL);
    9517          182 :       else if (POINTER_TYPE_P (type))
    9518          182 :         return build_int_cst (type, 0);
    9519              :       else
    9520            0 :         gcc_unreachable ();
    9521              :     }
    9522              : 
    9523       131368 :   if (array && !procptr)
    9524              :     {
    9525         8582 :       tree ctor;
    9526              :       /* Arrays need special handling.  */
    9527         8582 :       if (pointer)
    9528          773 :         ctor = gfc_build_null_descriptor (type);
    9529              :       /* Special case assigning an array to zero.  */
    9530         7809 :       else if (is_zero_initializer_p (expr))
    9531          217 :         ctor = build_constructor (type, NULL);
    9532              :       else
    9533         7592 :         ctor = gfc_conv_array_initializer (type, expr);
    9534         8582 :       TREE_STATIC (ctor) = 1;
    9535         8582 :       return ctor;
    9536              :     }
    9537       122786 :   else if (pointer || procptr)
    9538              :     {
    9539        59675 :       if (ts->type == BT_CLASS && !procptr)
    9540              :         {
    9541         1744 :           gfc_init_se (&se, NULL);
    9542         1744 :           gfc_conv_structure (&se, gfc_class_initializer (ts, expr), 1);
    9543         1744 :           gcc_assert (TREE_CODE (se.expr) == CONSTRUCTOR);
    9544         1744 :           TREE_STATIC (se.expr) = 1;
    9545         1744 :           return se.expr;
    9546              :         }
    9547        57931 :       else if (!expr || expr->expr_type == EXPR_NULL)
    9548        31269 :         return fold_convert (type, null_pointer_node);
    9549              :       else
    9550              :         {
    9551        26662 :           gfc_init_se (&se, NULL);
    9552        26662 :           se.want_pointer = 1;
    9553        26662 :           gfc_conv_expr (&se, expr);
    9554        26662 :           gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR);
    9555              :           return se.expr;
    9556              :         }
    9557              :     }
    9558              :   else
    9559              :     {
    9560        63111 :       switch (ts->type)
    9561              :         {
    9562        18943 :         case_bt_struct:
    9563        18943 :         case BT_CLASS:
    9564        18943 :           gfc_init_se (&se, NULL);
    9565        18943 :           if (ts->type == BT_CLASS && expr->expr_type == EXPR_NULL)
    9566          757 :             gfc_conv_structure (&se, gfc_class_initializer (ts, expr), 1);
    9567              :           else
    9568        18186 :             gfc_conv_structure (&se, expr, 1);
    9569        18943 :           gcc_assert (TREE_CODE (se.expr) == CONSTRUCTOR);
    9570        18943 :           TREE_STATIC (se.expr) = 1;
    9571        18943 :           return se.expr;
    9572              : 
    9573         2669 :         case BT_CHARACTER:
    9574         2669 :           if (expr->expr_type == EXPR_CONSTANT)
    9575              :             {
    9576         2668 :               tree ctor = gfc_conv_string_init (ts->u.cl->backend_decl, expr);
    9577         2668 :               TREE_STATIC (ctor) = 1;
    9578         2668 :               return ctor;
    9579              :             }
    9580              : 
    9581              :           /* Fallthrough.  */
    9582        41500 :         default:
    9583        41500 :           gfc_init_se (&se, NULL);
    9584        41500 :           gfc_conv_constant (&se, expr);
    9585        41500 :           gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR);
    9586              :           return se.expr;
    9587              :         }
    9588              :     }
    9589              : }
    9590              : 
    9591              : static tree
    9592          950 : gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
    9593              : {
    9594          950 :   gfc_se rse;
    9595          950 :   gfc_se lse;
    9596          950 :   gfc_ss *rss;
    9597          950 :   gfc_ss *lss;
    9598          950 :   gfc_array_info *lss_array;
    9599          950 :   stmtblock_t body;
    9600          950 :   stmtblock_t block;
    9601          950 :   gfc_loopinfo loop;
    9602          950 :   int n;
    9603          950 :   tree tmp;
    9604              : 
    9605          950 :   gfc_start_block (&block);
    9606              : 
    9607              :   /* Initialize the scalarizer.  */
    9608          950 :   gfc_init_loopinfo (&loop);
    9609              : 
    9610          950 :   gfc_init_se (&lse, NULL);
    9611          950 :   gfc_init_se (&rse, NULL);
    9612              : 
    9613              :   /* Walk the rhs.  */
    9614          950 :   rss = gfc_walk_expr (expr);
    9615          950 :   if (rss == gfc_ss_terminator)
    9616              :     /* The rhs is scalar.  Add a ss for the expression.  */
    9617          208 :     rss = gfc_get_scalar_ss (gfc_ss_terminator, expr);
    9618              : 
    9619              :   /* Create a SS for the destination.  */
    9620          950 :   lss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
    9621              :                           GFC_SS_COMPONENT);
    9622          950 :   lss_array = &lss->info->data.array;
    9623          950 :   lss_array->shape = gfc_get_shape (cm->as->rank);
    9624          950 :   lss_array->descriptor = dest;
    9625          950 :   lss_array->data = gfc_conv_array_data (dest);
    9626          950 :   lss_array->offset = gfc_conv_array_offset (dest);
    9627         1957 :   for (n = 0; n < cm->as->rank; n++)
    9628              :     {
    9629         1007 :       lss_array->start[n] = gfc_conv_array_lbound (dest, n);
    9630         1007 :       lss_array->stride[n] = gfc_index_one_node;
    9631              : 
    9632         1007 :       mpz_init (lss_array->shape[n]);
    9633         1007 :       mpz_sub (lss_array->shape[n], cm->as->upper[n]->value.integer,
    9634         1007 :                cm->as->lower[n]->value.integer);
    9635         1007 :       mpz_add_ui (lss_array->shape[n], lss_array->shape[n], 1);
    9636              :     }
    9637              : 
    9638              :   /* Associate the SS with the loop.  */
    9639          950 :   gfc_add_ss_to_loop (&loop, lss);
    9640          950 :   gfc_add_ss_to_loop (&loop, rss);
    9641              : 
    9642              :   /* Calculate the bounds of the scalarization.  */
    9643          950 :   gfc_conv_ss_startstride (&loop);
    9644              : 
    9645              :   /* Setup the scalarizing loops.  */
    9646          950 :   gfc_conv_loop_setup (&loop, &expr->where);
    9647              : 
    9648              :   /* Setup the gfc_se structures.  */
    9649          950 :   gfc_copy_loopinfo_to_se (&lse, &loop);
    9650          950 :   gfc_copy_loopinfo_to_se (&rse, &loop);
    9651              : 
    9652          950 :   rse.ss = rss;
    9653          950 :   gfc_mark_ss_chain_used (rss, 1);
    9654          950 :   lse.ss = lss;
    9655          950 :   gfc_mark_ss_chain_used (lss, 1);
    9656              : 
    9657              :   /* Start the scalarized loop body.  */
    9658          950 :   gfc_start_scalarized_body (&loop, &body);
    9659              : 
    9660          950 :   gfc_conv_tmp_array_ref (&lse);
    9661          950 :   if (cm->ts.type == BT_CHARACTER)
    9662          176 :     lse.string_length = cm->ts.u.cl->backend_decl;
    9663              : 
    9664          950 :   gfc_conv_expr (&rse, expr);
    9665              : 
    9666          950 :   tmp = gfc_trans_scalar_assign (&lse, &rse, cm->ts, true, false);
    9667          950 :   gfc_add_expr_to_block (&body, tmp);
    9668              : 
    9669          950 :   gcc_assert (rse.ss == gfc_ss_terminator);
    9670              : 
    9671              :   /* Generate the copying loops.  */
    9672          950 :   gfc_trans_scalarizing_loops (&loop, &body);
    9673              : 
    9674              :   /* Wrap the whole thing up.  */
    9675          950 :   gfc_add_block_to_block (&block, &loop.pre);
    9676          950 :   gfc_add_block_to_block (&block, &loop.post);
    9677              : 
    9678          950 :   gcc_assert (lss_array->shape != NULL);
    9679          950 :   gfc_free_shape (&lss_array->shape, cm->as->rank);
    9680          950 :   gfc_cleanup_loop (&loop);
    9681              : 
    9682          950 :   return gfc_finish_block (&block);
    9683              : }
    9684              : 
    9685              : 
    9686              : static stmtblock_t *final_block;
    9687              : static tree
    9688         1268 : gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm,
    9689              :                                  gfc_expr * expr)
    9690              : {
    9691         1268 :   gfc_se se;
    9692         1268 :   stmtblock_t block;
    9693         1268 :   tree offset;
    9694         1268 :   int n;
    9695         1268 :   tree tmp;
    9696         1268 :   tree tmp2;
    9697         1268 :   gfc_array_spec *as;
    9698         1268 :   gfc_expr *arg = NULL;
    9699              : 
    9700         1268 :   gfc_start_block (&block);
    9701         1268 :   gfc_init_se (&se, NULL);
    9702              : 
    9703              :   /* Get the descriptor for the expressions.  */
    9704         1268 :   se.want_pointer = 0;
    9705         1268 :   gfc_conv_expr_descriptor (&se, expr);
    9706         1268 :   gfc_add_block_to_block (&block, &se.pre);
    9707         1268 :   gfc_add_modify (&block, dest, se.expr);
    9708         1268 :   if (cm->ts.type == BT_CHARACTER
    9709         1268 :       && gfc_deferred_strlen (cm, &tmp))
    9710              :     {
    9711           30 :       tmp = fold_build3_loc (input_location, COMPONENT_REF,
    9712           30 :                              TREE_TYPE (tmp),
    9713           30 :                              TREE_OPERAND (dest, 0),
    9714              :                              tmp, NULL_TREE);
    9715           30 :       gfc_add_modify (&block, tmp,
    9716           30 :                               fold_convert (TREE_TYPE (tmp),
    9717              :                               se.string_length));
    9718           30 :       cm->ts.u.cl->backend_decl = gfc_create_var (gfc_charlen_type_node,
    9719              :                                                   "slen");
    9720           30 :       gfc_add_modify (&block, cm->ts.u.cl->backend_decl, se.string_length);
    9721              :     }
    9722              : 
    9723              :   /* Deal with arrays of derived types with allocatable components.  */
    9724         1268 :   if (gfc_bt_struct (cm->ts.type)
    9725          187 :         && cm->ts.u.derived->attr.alloc_comp)
    9726              :     // TODO: Fix caf_mode
    9727          107 :     tmp = gfc_copy_alloc_comp (cm->ts.u.derived,
    9728              :                                se.expr, dest,
    9729          107 :                                cm->as->rank, 0);
    9730         1161 :   else if (cm->ts.type == BT_CLASS && expr->ts.type == BT_DERIVED
    9731           36 :            && CLASS_DATA(cm)->attr.allocatable)
    9732              :     {
    9733           36 :       if (cm->ts.u.derived->attr.alloc_comp)
    9734              :         // TODO: Fix caf_mode
    9735            0 :         tmp = gfc_copy_alloc_comp (expr->ts.u.derived,
    9736              :                                    se.expr, dest,
    9737              :                                    expr->rank, 0);
    9738              :       else
    9739              :         {
    9740           36 :           tmp = TREE_TYPE (dest);
    9741           36 :           tmp = gfc_duplicate_allocatable (dest, se.expr,
    9742              :                                            tmp, expr->rank, NULL_TREE);
    9743              :         }
    9744              :     }
    9745         1125 :   else if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
    9746           30 :     tmp = gfc_duplicate_allocatable (dest, se.expr,
    9747              :                                      gfc_typenode_for_spec (&cm->ts),
    9748           30 :                                      cm->as->rank, NULL_TREE);
    9749              :   else
    9750         1095 :     tmp = gfc_duplicate_allocatable (dest, se.expr,
    9751         1095 :                                      TREE_TYPE(cm->backend_decl),
    9752         1095 :                                      cm->as->rank, NULL_TREE);
    9753              : 
    9754              : 
    9755         1268 :   gfc_add_expr_to_block (&block, tmp);
    9756         1268 :   gfc_add_block_to_block (&block, &se.post);
    9757              : 
    9758         1268 :   if (final_block && !cm->attr.allocatable
    9759           96 :       && expr->expr_type == EXPR_ARRAY)
    9760              :     {
    9761           96 :       tree data_ptr;
    9762           96 :       data_ptr = gfc_conv_descriptor_data_get (dest);
    9763           96 :       gfc_add_expr_to_block (final_block, gfc_call_free (data_ptr));
    9764           96 :     }
    9765         1172 :   else if (final_block && cm->attr.allocatable)
    9766          162 :     gfc_add_block_to_block (final_block, &se.finalblock);
    9767              : 
    9768         1268 :   if (expr->expr_type != EXPR_VARIABLE)
    9769         1147 :     gfc_conv_descriptor_data_set (&block, se.expr,
    9770              :                                   null_pointer_node);
    9771              : 
    9772              :   /* We need to know if the argument of a conversion function is a
    9773              :      variable, so that the correct lower bound can be used.  */
    9774         1268 :   if (expr->expr_type == EXPR_FUNCTION
    9775           56 :         && expr->value.function.isym
    9776           44 :         && expr->value.function.isym->conversion
    9777           44 :         && expr->value.function.actual->expr
    9778           44 :         && expr->value.function.actual->expr->expr_type == EXPR_VARIABLE)
    9779           44 :     arg = expr->value.function.actual->expr;
    9780              : 
    9781              :   /* Obtain the array spec of full array references.  */
    9782           44 :   if (arg)
    9783           44 :     as = gfc_get_full_arrayspec_from_expr (arg);
    9784              :   else
    9785         1224 :     as = gfc_get_full_arrayspec_from_expr (expr);
    9786              : 
    9787              :   /* Shift the lbound and ubound of temporaries to being unity,
    9788              :      rather than zero, based. Always calculate the offset.  */
    9789         1268 :   gfc_conv_descriptor_offset_set (&block, dest, gfc_index_zero_node);
    9790         1268 :   offset = gfc_conv_descriptor_offset_get (dest);
    9791         1268 :   tmp2 =gfc_create_var (gfc_array_index_type, NULL);
    9792              : 
    9793         2592 :   for (n = 0; n < expr->rank; n++)
    9794              :     {
    9795         1324 :       tree span;
    9796         1324 :       tree lbound;
    9797              : 
    9798              :       /* Obtain the correct lbound - ISO/IEC TR 15581:2001 page 9.
    9799              :          TODO It looks as if gfc_conv_expr_descriptor should return
    9800              :          the correct bounds and that the following should not be
    9801              :          necessary.  This would simplify gfc_conv_intrinsic_bound
    9802              :          as well.  */
    9803         1324 :       if (as && as->lower[n])
    9804              :         {
    9805           80 :           gfc_se lbse;
    9806           80 :           gfc_init_se (&lbse, NULL);
    9807           80 :           gfc_conv_expr (&lbse, as->lower[n]);
    9808           80 :           gfc_add_block_to_block (&block, &lbse.pre);
    9809           80 :           lbound = gfc_evaluate_now (lbse.expr, &block);
    9810           80 :         }
    9811         1244 :       else if (as && arg)
    9812              :         {
    9813           34 :           tmp = gfc_get_symbol_decl (arg->symtree->n.sym);
    9814           34 :           lbound = gfc_conv_descriptor_lbound_get (tmp,
    9815              :                                         gfc_rank_cst[n]);
    9816              :         }
    9817         1210 :       else if (as)
    9818           64 :         lbound = gfc_conv_descriptor_lbound_get (dest,
    9819              :                                                 gfc_rank_cst[n]);
    9820              :       else
    9821         1146 :         lbound = gfc_index_one_node;
    9822              : 
    9823         1324 :       lbound = fold_convert (gfc_array_index_type, lbound);
    9824              : 
    9825              :       /* Shift the bounds and set the offset accordingly.  */
    9826         1324 :       tmp = gfc_conv_descriptor_ubound_get (dest, gfc_rank_cst[n]);
    9827         1324 :       span = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    9828              :                 tmp, gfc_conv_descriptor_lbound_get (dest, gfc_rank_cst[n]));
    9829         1324 :       tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
    9830              :                              span, lbound);
    9831         1324 :       gfc_conv_descriptor_ubound_set (&block, dest,
    9832              :                                       gfc_rank_cst[n], tmp);
    9833         1324 :       gfc_conv_descriptor_lbound_set (&block, dest,
    9834              :                                       gfc_rank_cst[n], lbound);
    9835              : 
    9836         1324 :       tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
    9837              :                          gfc_conv_descriptor_lbound_get (dest,
    9838              :                                                          gfc_rank_cst[n]),
    9839              :                          gfc_conv_descriptor_stride_get (dest,
    9840              :                                                          gfc_rank_cst[n]));
    9841         1324 :       gfc_add_modify (&block, tmp2, tmp);
    9842         1324 :       tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
    9843              :                              offset, tmp2);
    9844         1324 :       gfc_conv_descriptor_offset_set (&block, dest, tmp);
    9845              :     }
    9846              : 
    9847         1268 :   if (arg)
    9848              :     {
    9849              :       /* If a conversion expression has a null data pointer
    9850              :          argument, nullify the allocatable component.  */
    9851           44 :       tree non_null_expr;
    9852           44 :       tree null_expr;
    9853              : 
    9854           44 :       if (arg->symtree->n.sym->attr.allocatable
    9855           12 :             || arg->symtree->n.sym->attr.pointer)
    9856              :         {
    9857           32 :           non_null_expr = gfc_finish_block (&block);
    9858           32 :           gfc_start_block (&block);
    9859           32 :           gfc_conv_descriptor_data_set (&block, dest,
    9860              :                                         null_pointer_node);
    9861           32 :           null_expr = gfc_finish_block (&block);
    9862           32 :           tmp = gfc_conv_descriptor_data_get (arg->symtree->n.sym->backend_decl);
    9863           32 :           tmp = build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
    9864           32 :                             fold_convert (TREE_TYPE (tmp), null_pointer_node));
    9865           32 :           return build3_v (COND_EXPR, tmp,
    9866              :                            null_expr, non_null_expr);
    9867              :         }
    9868              :     }
    9869              : 
    9870         1236 :   return gfc_finish_block (&block);
    9871              : }
    9872              : 
    9873              : 
    9874              : /* Allocate or reallocate scalar component, as necessary.  */
    9875              : 
    9876              : static void
    9877          398 : alloc_scalar_allocatable_subcomponent (stmtblock_t *block, tree comp,
    9878              :                                        gfc_component *cm, gfc_expr *expr2,
    9879              :                                        tree slen)
    9880              : {
    9881          398 :   tree tmp;
    9882          398 :   tree ptr;
    9883          398 :   tree size;
    9884          398 :   tree size_in_bytes;
    9885          398 :   tree lhs_cl_size = NULL_TREE;
    9886          398 :   gfc_se se;
    9887              : 
    9888          398 :   if (!comp)
    9889            0 :     return;
    9890              : 
    9891          398 :   if (!expr2 || expr2->rank)
    9892              :     return;
    9893              : 
    9894          398 :   realloc_lhs_warning (expr2->ts.type, false, &expr2->where);
    9895              : 
    9896          398 :   if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
    9897              :     {
    9898          139 :       gcc_assert (expr2->ts.type == BT_CHARACTER);
    9899          139 :       size = expr2->ts.u.cl->backend_decl;
    9900          139 :       if (!size || !VAR_P (size))
    9901          139 :         size = gfc_create_var (TREE_TYPE (slen), "slen");
    9902          139 :       gfc_add_modify (block, size, slen);
    9903              : 
    9904          139 :       gfc_deferred_strlen (cm, &tmp);
    9905          139 :       lhs_cl_size = fold_build3_loc (input_location, COMPONENT_REF,
    9906              :                                      gfc_charlen_type_node,
    9907          139 :                                      TREE_OPERAND (comp, 0),
    9908              :                                      tmp, NULL_TREE);
    9909              : 
    9910          139 :       tmp = TREE_TYPE (gfc_typenode_for_spec (&cm->ts));
    9911          139 :       tmp = TYPE_SIZE_UNIT (tmp);
    9912          278 :       size_in_bytes = fold_build2_loc (input_location, MULT_EXPR,
    9913          139 :                                        TREE_TYPE (tmp), tmp,
    9914          139 :                                        fold_convert (TREE_TYPE (tmp), size));
    9915              :     }
    9916          259 :   else if (cm->ts.type == BT_CLASS)
    9917              :     {
    9918          103 :       if (expr2->ts.type != BT_CLASS)
    9919              :         {
    9920          103 :           if (expr2->ts.type == BT_CHARACTER)
    9921              :             {
    9922           24 :               gfc_init_se (&se, NULL);
    9923           24 :               gfc_conv_expr (&se, expr2);
    9924           24 :               size = build_int_cst (gfc_charlen_type_node, expr2->ts.kind);
    9925           24 :               size = fold_build2_loc (input_location, MULT_EXPR,
    9926              :                                       gfc_charlen_type_node,
    9927              :                                       se.string_length, size);
    9928           24 :               size = fold_convert (size_type_node, size);
    9929              :             }
    9930              :           else
    9931              :             {
    9932           79 :               if (expr2->ts.type == BT_DERIVED)
    9933           48 :                 tmp = gfc_get_symbol_decl (expr2->ts.u.derived);
    9934              :               else
    9935           31 :                 tmp = gfc_typenode_for_spec (&expr2->ts);
    9936           79 :               size = TYPE_SIZE_UNIT (tmp);
    9937              :             }
    9938              :         }
    9939              :       else
    9940              :         {
    9941            0 :           gfc_expr *e2vtab;
    9942            0 :           e2vtab = gfc_find_and_cut_at_last_class_ref (expr2);
    9943            0 :           gfc_add_vptr_component (e2vtab);
    9944            0 :           gfc_add_size_component (e2vtab);
    9945            0 :           gfc_init_se (&se, NULL);
    9946            0 :           gfc_conv_expr (&se, e2vtab);
    9947            0 :           gfc_add_block_to_block (block, &se.pre);
    9948            0 :           size = fold_convert (size_type_node, se.expr);
    9949            0 :           gfc_free_expr (e2vtab);
    9950              :         }
    9951              :       size_in_bytes = size;
    9952              :     }
    9953              :   else
    9954              :     {
    9955              :       /* Otherwise use the length in bytes of the rhs.  */
    9956          156 :       size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&cm->ts));
    9957          156 :       size_in_bytes = size;
    9958              :     }
    9959              : 
    9960          398 :   size_in_bytes = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
    9961              :                                    size_in_bytes, size_one_node);
    9962              : 
    9963          398 :   if (cm->ts.type == BT_DERIVED && cm->ts.u.derived->attr.alloc_comp)
    9964              :     {
    9965            0 :       tmp = build_call_expr_loc (input_location,
    9966              :                                  builtin_decl_explicit (BUILT_IN_CALLOC),
    9967              :                                  2, build_one_cst (size_type_node),
    9968              :                                  size_in_bytes);
    9969            0 :       tmp = fold_convert (TREE_TYPE (comp), tmp);
    9970            0 :       gfc_add_modify (block, comp, tmp);
    9971              :     }
    9972              :   else
    9973              :     {
    9974          398 :       tmp = build_call_expr_loc (input_location,
    9975              :                                  builtin_decl_explicit (BUILT_IN_MALLOC),
    9976              :                                  1, size_in_bytes);
    9977          398 :       if (GFC_CLASS_TYPE_P (TREE_TYPE (comp)))
    9978          103 :         ptr = gfc_class_data_get (comp);
    9979              :       else
    9980              :         ptr = comp;
    9981          398 :       tmp = fold_convert (TREE_TYPE (ptr), tmp);
    9982          398 :       gfc_add_modify (block, ptr, tmp);
    9983              :     }
    9984              : 
    9985          398 :   if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
    9986              :     /* Update the lhs character length.  */
    9987          139 :     gfc_add_modify (block, lhs_cl_size,
    9988          139 :                     fold_convert (TREE_TYPE (lhs_cl_size), size));
    9989              : }
    9990              : 
    9991              : 
    9992              : /* Assign a single component of a derived type constructor.  */
    9993              : 
    9994              : static tree
    9995        29019 : gfc_trans_subcomponent_assign (tree dest, gfc_component * cm,
    9996              :                                gfc_expr * expr, bool init)
    9997              : {
    9998        29019 :   gfc_se se;
    9999        29019 :   gfc_se lse;
   10000        29019 :   stmtblock_t block;
   10001        29019 :   tree tmp;
   10002        29019 :   tree vtab;
   10003              : 
   10004        29019 :   gfc_start_block (&block);
   10005              : 
   10006        29019 :   if (cm->attr.pointer || cm->attr.proc_pointer)
   10007              :     {
   10008              :       /* Only care about pointers here, not about allocatables.  */
   10009         2634 :       gfc_init_se (&se, NULL);
   10010              :       /* Pointer component.  */
   10011         2634 :       if ((cm->attr.dimension || cm->attr.codimension)
   10012          670 :           && !cm->attr.proc_pointer)
   10013              :         {
   10014              :           /* Array pointer.  */
   10015          654 :           if (expr->expr_type == EXPR_NULL)
   10016          648 :             gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
   10017              :           else
   10018              :             {
   10019            6 :               se.direct_byref = 1;
   10020            6 :               se.expr = dest;
   10021            6 :               gfc_conv_expr_descriptor (&se, expr);
   10022            6 :               gfc_add_block_to_block (&block, &se.pre);
   10023            6 :               gfc_add_block_to_block (&block, &se.post);
   10024              :             }
   10025              :         }
   10026              :       else
   10027              :         {
   10028              :           /* Scalar pointers.  */
   10029         1980 :           se.want_pointer = 1;
   10030         1980 :           gfc_conv_expr (&se, expr);
   10031         1980 :           gfc_add_block_to_block (&block, &se.pre);
   10032              : 
   10033         1980 :           if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
   10034           12 :               && expr->symtree->n.sym->attr.dummy)
   10035           12 :             se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
   10036              : 
   10037         1980 :           gfc_add_modify (&block, dest,
   10038         1980 :                                fold_convert (TREE_TYPE (dest), se.expr));
   10039         1980 :           gfc_add_block_to_block (&block, &se.post);
   10040              :         }
   10041              :     }
   10042        26385 :   else if (cm->ts.type == BT_CLASS && expr->expr_type == EXPR_NULL)
   10043              :     {
   10044              :       /* NULL initialization for CLASS components.  */
   10045          922 :       tmp = gfc_trans_structure_assign (dest,
   10046              :                                         gfc_class_initializer (&cm->ts, expr),
   10047              :                                         false);
   10048          922 :       gfc_add_expr_to_block (&block, tmp);
   10049              :     }
   10050        25463 :   else if ((cm->attr.dimension || cm->attr.codimension)
   10051              :            && !cm->attr.proc_pointer)
   10052              :     {
   10053         4817 :       if (cm->attr.allocatable && expr->expr_type == EXPR_NULL)
   10054              :         {
   10055         2635 :           gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
   10056         2635 :           if (cm->attr.codimension && flag_coarray == GFC_FCOARRAY_LIB)
   10057            2 :             gfc_add_modify (&block, gfc_conv_descriptor_token (dest),
   10058              :                             null_pointer_node);
   10059              :         }
   10060         2182 :       else if (cm->attr.allocatable || cm->attr.pdt_array)
   10061              :         {
   10062         1232 :           tmp = gfc_trans_alloc_subarray_assign (dest, cm, expr);
   10063         1232 :           gfc_add_expr_to_block (&block, tmp);
   10064              :         }
   10065              :       else
   10066              :         {
   10067          950 :           tmp = gfc_trans_subarray_assign (dest, cm, expr);
   10068          950 :           gfc_add_expr_to_block (&block, tmp);
   10069              :         }
   10070              :     }
   10071        20646 :   else if (cm->ts.type == BT_CLASS
   10072          145 :            && CLASS_DATA (cm)->attr.dimension
   10073           36 :            && CLASS_DATA (cm)->attr.allocatable
   10074           36 :            && expr->ts.type == BT_DERIVED)
   10075              :     {
   10076           36 :       vtab = gfc_get_symbol_decl (gfc_find_vtab (&expr->ts));
   10077           36 :       vtab = gfc_build_addr_expr (NULL_TREE, vtab);
   10078           36 :       tmp = gfc_class_vptr_get (dest);
   10079           36 :       gfc_add_modify (&block, tmp,
   10080           36 :                       fold_convert (TREE_TYPE (tmp), vtab));
   10081           36 :       tmp = gfc_class_data_get (dest);
   10082           36 :       tmp = gfc_trans_alloc_subarray_assign (tmp, cm, expr);
   10083           36 :       gfc_add_expr_to_block (&block, tmp);
   10084              :     }
   10085        20610 :   else if (cm->attr.allocatable && expr->expr_type == EXPR_NULL
   10086         1748 :            && (init
   10087         1621 :                || (cm->ts.type == BT_CHARACTER
   10088          131 :                    && !(cm->ts.deferred || cm->attr.pdt_string))))
   10089              :     {
   10090              :       /* NULL initialization for allocatable components.
   10091              :          Deferred-length character is dealt with later.  */
   10092          151 :       gfc_add_modify (&block, dest, fold_convert (TREE_TYPE (dest),
   10093              :                                                   null_pointer_node));
   10094              :     }
   10095        20459 :   else if (init && (cm->attr.allocatable
   10096        13425 :            || (cm->ts.type == BT_CLASS && CLASS_DATA (cm)->attr.allocatable
   10097          109 :                && expr->ts.type != BT_CLASS)))
   10098              :     {
   10099          398 :       tree size;
   10100              : 
   10101          398 :       gfc_init_se (&se, NULL);
   10102          398 :       gfc_conv_expr (&se, expr);
   10103              : 
   10104              :       /* The remainder of these instructions follow the if (cm->attr.pointer)
   10105              :          if (!cm->attr.dimension) part above.  */
   10106          398 :       gfc_add_block_to_block (&block, &se.pre);
   10107              :       /* Take care about non-array allocatable components here.  The alloc_*
   10108              :          routine below is motivated by the alloc_scalar_allocatable_for_
   10109              :          assignment() routine, but with the realloc portions removed and
   10110              :          different input.  */
   10111          398 :       alloc_scalar_allocatable_subcomponent (&block, dest, cm, expr,
   10112              :                                              se.string_length);
   10113              : 
   10114          398 :       if (expr->symtree && expr->symtree->n.sym->attr.proc_pointer
   10115            0 :           && expr->symtree->n.sym->attr.dummy)
   10116            0 :         se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
   10117              : 
   10118          398 :       if (cm->ts.type == BT_CLASS)
   10119              :         {
   10120          103 :           tmp = gfc_class_data_get (dest);
   10121          103 :           tmp = build_fold_indirect_ref_loc (input_location, tmp);
   10122          103 :           vtab = gfc_get_symbol_decl (gfc_find_vtab (&expr->ts));
   10123          103 :           vtab = gfc_build_addr_expr (NULL_TREE, vtab);
   10124          103 :           gfc_add_modify (&block, gfc_class_vptr_get (dest),
   10125          103 :                  fold_convert (TREE_TYPE (gfc_class_vptr_get (dest)), vtab));
   10126              :         }
   10127              :       else
   10128          295 :         tmp = build_fold_indirect_ref_loc (input_location, dest);
   10129              : 
   10130              :       /* For deferred strings insert a memcpy.  */
   10131          398 :       if (cm->ts.type == BT_CHARACTER && cm->ts.deferred)
   10132              :         {
   10133          139 :           gcc_assert (se.string_length || expr->ts.u.cl->backend_decl);
   10134          139 :           size = size_of_string_in_bytes (cm->ts.kind, se.string_length
   10135              :                                                 ? se.string_length
   10136            0 :                                                 : expr->ts.u.cl->backend_decl);
   10137          139 :           tmp = gfc_build_memcpy_call (tmp, se.expr, size);
   10138          139 :           gfc_add_expr_to_block (&block, tmp);
   10139              :         }
   10140          259 :       else if (cm->ts.type == BT_CLASS)
   10141              :         {
   10142              :           /* Fix the expression for memcpy.  */
   10143          103 :           if (expr->expr_type != EXPR_VARIABLE)
   10144           73 :             se.expr = gfc_evaluate_now (se.expr, &block);
   10145              : 
   10146          103 :           if (expr->ts.type == BT_CHARACTER)
   10147              :             {
   10148           24 :               size = build_int_cst (gfc_charlen_type_node, expr->ts.kind);
   10149           24 :               size = fold_build2_loc (input_location, MULT_EXPR,
   10150              :                                       gfc_charlen_type_node,
   10151              :                                       se.string_length, size);
   10152           24 :               size = fold_convert (size_type_node, size);
   10153              :             }
   10154              :           else
   10155           79 :             size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr->ts));
   10156              : 
   10157              :           /* Now copy the expression to the constructor component _data.  */
   10158          103 :           gfc_add_expr_to_block (&block,
   10159              :                                  gfc_build_memcpy_call (tmp, se.expr, size));
   10160              : 
   10161              :           /* Fill the unlimited polymorphic _len field.  */
   10162          103 :           if (UNLIMITED_POLY (cm) && expr->ts.type == BT_CHARACTER)
   10163              :             {
   10164           24 :               tmp = gfc_class_len_get (gfc_get_class_from_expr (tmp));
   10165           24 :               gfc_add_modify (&block, tmp,
   10166           24 :                               fold_convert (TREE_TYPE (tmp),
   10167              :                               se.string_length));
   10168              :             }
   10169              :         }
   10170              :       else
   10171          156 :         gfc_add_modify (&block, tmp,
   10172          156 :                         fold_convert (TREE_TYPE (tmp), se.expr));
   10173          398 :       gfc_add_block_to_block (&block, &se.post);
   10174          398 :     }
   10175        20061 :   else if (expr->ts.type == BT_UNION)
   10176              :     {
   10177           13 :       tree tmp;
   10178           13 :       gfc_constructor *c = gfc_constructor_first (expr->value.constructor);
   10179              :       /* We mark that the entire union should be initialized with a contrived
   10180              :          EXPR_NULL expression at the beginning.  */
   10181           13 :       if (c != NULL && c->n.component == NULL
   10182            7 :           && c->expr != NULL && c->expr->expr_type == EXPR_NULL)
   10183              :         {
   10184            6 :           tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
   10185            6 :                             dest, build_constructor (TREE_TYPE (dest), NULL));
   10186            6 :           gfc_add_expr_to_block (&block, tmp);
   10187            6 :           c = gfc_constructor_next (c);
   10188              :         }
   10189              :       /* The following constructor expression, if any, represents a specific
   10190              :          map intializer, as given by the user.  */
   10191           13 :       if (c != NULL && c->expr != NULL)
   10192              :         {
   10193            6 :           gcc_assert (expr->expr_type == EXPR_STRUCTURE);
   10194            6 :           tmp = gfc_trans_structure_assign (dest, expr, expr->symtree != NULL);
   10195            6 :           gfc_add_expr_to_block (&block, tmp);
   10196              :         }
   10197              :     }
   10198        20048 :   else if (expr->ts.type == BT_DERIVED && expr->ts.f90_type != BT_VOID)
   10199              :     {
   10200         3123 :       if (expr->expr_type != EXPR_STRUCTURE)
   10201              :         {
   10202          452 :           tree dealloc = NULL_TREE;
   10203          452 :           gfc_init_se (&se, NULL);
   10204          452 :           gfc_conv_expr (&se, expr);
   10205          452 :           gfc_add_block_to_block (&block, &se.pre);
   10206              :           /* Prevent repeat evaluations in gfc_copy_alloc_comp by fixing the
   10207              :              expression in  a temporary variable and deallocate the allocatable
   10208              :              components. Then we can the copy the expression to the result.  */
   10209          452 :           if (cm->ts.u.derived->attr.alloc_comp
   10210          330 :               && expr->expr_type != EXPR_VARIABLE)
   10211              :             {
   10212          300 :               se.expr = gfc_evaluate_now (se.expr, &block);
   10213          300 :               dealloc = gfc_deallocate_alloc_comp (cm->ts.u.derived, se.expr,
   10214              :                                                    expr->rank);
   10215              :             }
   10216          452 :           gfc_add_modify (&block, dest,
   10217          452 :                           fold_convert (TREE_TYPE (dest), se.expr));
   10218          452 :           if (cm->ts.u.derived->attr.alloc_comp
   10219          330 :               && expr->expr_type != EXPR_NULL)
   10220              :             {
   10221              :               // TODO: Fix caf_mode
   10222           48 :               tmp = gfc_copy_alloc_comp (cm->ts.u.derived, se.expr,
   10223              :                                          dest, expr->rank, 0);
   10224           48 :               gfc_add_expr_to_block (&block, tmp);
   10225           48 :               if (dealloc != NULL_TREE)
   10226           18 :                 gfc_add_expr_to_block (&block, dealloc);
   10227              :             }
   10228          452 :           gfc_add_block_to_block (&block, &se.post);
   10229              :         }
   10230              :       else
   10231              :         {
   10232              :           /* Nested constructors.  */
   10233         2671 :           tmp = gfc_trans_structure_assign (dest, expr, expr->symtree != NULL);
   10234         2671 :           gfc_add_expr_to_block (&block, tmp);
   10235              :         }
   10236              :     }
   10237        16925 :   else if (gfc_deferred_strlen (cm, &tmp))
   10238              :     {
   10239          125 :       tree strlen;
   10240          125 :       strlen = tmp;
   10241          125 :       gcc_assert (strlen);
   10242          125 :       strlen = fold_build3_loc (input_location, COMPONENT_REF,
   10243          125 :                                 TREE_TYPE (strlen),
   10244          125 :                                 TREE_OPERAND (dest, 0),
   10245              :                                 strlen, NULL_TREE);
   10246              : 
   10247          125 :       if (expr->expr_type == EXPR_NULL)
   10248              :         {
   10249          107 :           tmp = build_int_cst (TREE_TYPE (cm->backend_decl), 0);
   10250          107 :           gfc_add_modify (&block, dest, tmp);
   10251          107 :           tmp = build_int_cst (TREE_TYPE (strlen), 0);
   10252          107 :           gfc_add_modify (&block, strlen, tmp);
   10253              :         }
   10254              :       else
   10255              :         {
   10256           18 :           tree size;
   10257           18 :           gfc_init_se (&se, NULL);
   10258           18 :           gfc_conv_expr (&se, expr);
   10259           18 :           size = size_of_string_in_bytes (cm->ts.kind, se.string_length);
   10260           18 :           size = fold_convert (size_type_node, size);
   10261           18 :           tmp = build_call_expr_loc (input_location,
   10262              :                                      builtin_decl_explicit (BUILT_IN_MALLOC),
   10263              :                                      1, size);
   10264           18 :           gfc_add_modify (&block, dest,
   10265           18 :                           fold_convert (TREE_TYPE (dest), tmp));
   10266           18 :           gfc_add_modify (&block, strlen,
   10267           18 :                           fold_convert (TREE_TYPE (strlen), se.string_length));
   10268           18 :           tmp = gfc_build_memcpy_call (dest, se.expr, size);
   10269           18 :           gfc_add_expr_to_block (&block, tmp);
   10270              :         }
   10271              :     }
   10272        16800 :   else if (!cm->attr.artificial)
   10273              :     {
   10274              :       /* Scalar component (excluding deferred parameters).  */
   10275        16685 :       gfc_init_se (&se, NULL);
   10276        16685 :       gfc_init_se (&lse, NULL);
   10277              : 
   10278        16685 :       gfc_conv_expr (&se, expr);
   10279        16685 :       if (cm->ts.type == BT_CHARACTER)
   10280         1051 :         lse.string_length = cm->ts.u.cl->backend_decl;
   10281        16685 :       lse.expr = dest;
   10282        16685 :       tmp = gfc_trans_scalar_assign (&lse, &se, cm->ts, false, false);
   10283        16685 :       gfc_add_expr_to_block (&block, tmp);
   10284              :     }
   10285        29019 :   return gfc_finish_block (&block);
   10286              : }
   10287              : 
   10288              : /* Assign a derived type constructor to a variable.  */
   10289              : 
   10290              : tree
   10291        20202 : gfc_trans_structure_assign (tree dest, gfc_expr * expr, bool init, bool coarray)
   10292              : {
   10293        20202 :   gfc_constructor *c;
   10294        20202 :   gfc_component *cm;
   10295        20202 :   stmtblock_t block;
   10296        20202 :   tree field;
   10297        20202 :   tree tmp;
   10298        20202 :   gfc_se se;
   10299              : 
   10300        20202 :   gfc_start_block (&block);
   10301              : 
   10302        20202 :   if (expr->ts.u.derived->from_intmod == INTMOD_ISO_C_BINDING
   10303          172 :       && (expr->ts.u.derived->intmod_sym_id == ISOCBINDING_PTR
   10304            9 :           || expr->ts.u.derived->intmod_sym_id == ISOCBINDING_FUNPTR))
   10305              :     {
   10306          172 :       gfc_se lse;
   10307              : 
   10308          172 :       gfc_init_se (&se, NULL);
   10309          172 :       gfc_init_se (&lse, NULL);
   10310          172 :       gfc_conv_expr (&se, gfc_constructor_first (expr->value.constructor)->expr);
   10311          172 :       lse.expr = dest;
   10312          172 :       gfc_add_modify (&block, lse.expr,
   10313          172 :                       fold_convert (TREE_TYPE (lse.expr), se.expr));
   10314              : 
   10315          172 :       return gfc_finish_block (&block);
   10316              :     }
   10317              : 
   10318              :   /* Make sure that the derived type has been completely built.  */
   10319        20030 :   if (!expr->ts.u.derived->backend_decl
   10320        20030 :       || !TYPE_FIELDS (expr->ts.u.derived->backend_decl))
   10321              :     {
   10322          224 :       tmp = gfc_typenode_for_spec (&expr->ts);
   10323          224 :       gcc_assert (tmp);
   10324              :     }
   10325              : 
   10326        20030 :   cm = expr->ts.u.derived->components;
   10327              : 
   10328              : 
   10329        20030 :   if (coarray)
   10330          223 :     gfc_init_se (&se, NULL);
   10331              : 
   10332        20030 :   for (c = gfc_constructor_first (expr->value.constructor);
   10333        52157 :        c; c = gfc_constructor_next (c), cm = cm->next)
   10334              :     {
   10335              :       /* Skip absent members in default initializers.  */
   10336        32127 :       if (!c->expr && !cm->attr.allocatable)
   10337         3108 :         continue;
   10338              : 
   10339              :       /* Register the component with the caf-lib before it is initialized.
   10340              :          Register only allocatable components, that are not coarray'ed
   10341              :          components (%comp[*]).  Only register when the constructor is the
   10342              :          null-expression.  */
   10343        29019 :       if (coarray && !cm->attr.codimension
   10344          513 :           && (cm->attr.allocatable || cm->attr.pointer)
   10345          177 :           && (!c->expr || c->expr->expr_type == EXPR_NULL))
   10346              :         {
   10347          175 :           tree token, desc, size;
   10348          350 :           bool is_array = cm->ts.type == BT_CLASS
   10349          175 :               ? CLASS_DATA (cm)->attr.dimension : cm->attr.dimension;
   10350              : 
   10351          175 :           field = cm->backend_decl;
   10352          175 :           field = fold_build3_loc (input_location, COMPONENT_REF,
   10353          175 :                                    TREE_TYPE (field), dest, field, NULL_TREE);
   10354          175 :           if (cm->ts.type == BT_CLASS)
   10355            0 :             field = gfc_class_data_get (field);
   10356              : 
   10357          175 :           token
   10358              :             = is_array
   10359          175 :                 ? gfc_conv_descriptor_token (field)
   10360           52 :                 : fold_build3_loc (input_location, COMPONENT_REF,
   10361           52 :                                    TREE_TYPE (gfc_comp_caf_token (cm)), dest,
   10362           52 :                                    gfc_comp_caf_token (cm), NULL_TREE);
   10363              : 
   10364          175 :           if (is_array)
   10365              :             {
   10366              :               /* The _caf_register routine looks at the rank of the array
   10367              :                  descriptor to decide whether the data registered is an array
   10368              :                  or not.  */
   10369          123 :               int rank = cm->ts.type == BT_CLASS ? CLASS_DATA (cm)->as->rank
   10370          123 :                                                  : cm->as->rank;
   10371              :               /* When the rank is not known just set a positive rank, which
   10372              :                  suffices to recognize the data as array.  */
   10373          123 :               if (rank < 0)
   10374            0 :                 rank = 1;
   10375          123 :               size = build_zero_cst (size_type_node);
   10376          123 :               desc = field;
   10377          123 :               gfc_add_modify (&block, gfc_conv_descriptor_rank (desc),
   10378          123 :                               build_int_cst (signed_char_type_node, rank));
   10379              :             }
   10380              :           else
   10381              :             {
   10382           52 :               desc = gfc_conv_scalar_to_descriptor (&se, field,
   10383           52 :                                                     cm->ts.type == BT_CLASS
   10384           52 :                                                     ? CLASS_DATA (cm)->attr
   10385              :                                                     : cm->attr);
   10386           52 :               size = TYPE_SIZE_UNIT (TREE_TYPE (field));
   10387              :             }
   10388          175 :           gfc_add_block_to_block (&block, &se.pre);
   10389          175 :           tmp =  build_call_expr_loc (input_location, gfor_fndecl_caf_register,
   10390              :                                       7, size, build_int_cst (
   10391              :                                         integer_type_node,
   10392              :                                         GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY),
   10393              :                                       gfc_build_addr_expr (pvoid_type_node,
   10394              :                                                            token),
   10395              :                                       gfc_build_addr_expr (NULL_TREE, desc),
   10396              :                                       null_pointer_node, null_pointer_node,
   10397              :                                       integer_zero_node);
   10398          175 :           gfc_add_expr_to_block (&block, tmp);
   10399              :         }
   10400        29019 :       field = cm->backend_decl;
   10401        29019 :       gcc_assert(field);
   10402        29019 :       tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
   10403              :                              dest, field, NULL_TREE);
   10404        29019 :       if (!c->expr)
   10405              :         {
   10406            0 :           gfc_expr *e = gfc_get_null_expr (NULL);
   10407            0 :           tmp = gfc_trans_subcomponent_assign (tmp, cm, e, init);
   10408            0 :           gfc_free_expr (e);
   10409              :         }
   10410              :       else
   10411        29019 :         tmp = gfc_trans_subcomponent_assign (tmp, cm, c->expr, init);
   10412        29019 :       gfc_add_expr_to_block (&block, tmp);
   10413              :     }
   10414        20030 :   return gfc_finish_block (&block);
   10415              : }
   10416              : 
   10417              : static void
   10418           21 : gfc_conv_union_initializer (vec<constructor_elt, va_gc> *&v,
   10419              :                             gfc_component *un, gfc_expr *init)
   10420              : {
   10421           21 :   gfc_constructor *ctor;
   10422              : 
   10423           21 :   if (un->ts.type != BT_UNION || un == NULL || init == NULL)
   10424              :     return;
   10425              : 
   10426           21 :   ctor = gfc_constructor_first (init->value.constructor);
   10427              : 
   10428           21 :   if (ctor == NULL || ctor->expr == NULL)
   10429              :     return;
   10430              : 
   10431           21 :   gcc_assert (init->expr_type == EXPR_STRUCTURE);
   10432              : 
   10433              :   /* If we have an 'initialize all' constructor, do it first.  */
   10434           21 :   if (ctor->expr->expr_type == EXPR_NULL)
   10435              :     {
   10436            9 :       tree union_type = TREE_TYPE (un->backend_decl);
   10437            9 :       tree val = build_constructor (union_type, NULL);
   10438            9 :       CONSTRUCTOR_APPEND_ELT (v, un->backend_decl, val);
   10439            9 :       ctor = gfc_constructor_next (ctor);
   10440              :     }
   10441              : 
   10442              :   /* Add the map initializer on top.  */
   10443           21 :   if (ctor != NULL && ctor->expr != NULL)
   10444              :     {
   10445           12 :       gcc_assert (ctor->expr->expr_type == EXPR_STRUCTURE);
   10446           12 :       tree val = gfc_conv_initializer (ctor->expr, &un->ts,
   10447           12 :                                        TREE_TYPE (un->backend_decl),
   10448           12 :                                        un->attr.dimension, un->attr.pointer,
   10449           12 :                                        un->attr.proc_pointer);
   10450           12 :       CONSTRUCTOR_APPEND_ELT (v, un->backend_decl, val);
   10451              :     }
   10452              : }
   10453              : 
   10454              : /* Build an expression for a constructor. If init is nonzero then
   10455              :    this is part of a static variable initializer.  */
   10456              : 
   10457              : void
   10458        38687 : gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
   10459              : {
   10460        38687 :   gfc_constructor *c;
   10461        38687 :   gfc_component *cm;
   10462        38687 :   tree val;
   10463        38687 :   tree type;
   10464        38687 :   tree tmp;
   10465        38687 :   vec<constructor_elt, va_gc> *v = NULL;
   10466              : 
   10467        38687 :   gcc_assert (se->ss == NULL);
   10468        38687 :   gcc_assert (expr->expr_type == EXPR_STRUCTURE);
   10469        38687 :   type = gfc_typenode_for_spec (&expr->ts);
   10470              : 
   10471        38687 :   if (!init)
   10472              :     {
   10473        15857 :       if (IS_PDT (expr) && expr->must_finalize)
   10474          276 :         final_block = &se->finalblock;
   10475              : 
   10476              :       /* Create a temporary variable and fill it in.  */
   10477        15857 :       se->expr = gfc_create_var (type, expr->ts.u.derived->name);
   10478              :       /* The symtree in expr is NULL, if the code to generate is for
   10479              :          initializing the static members only.  */
   10480        31714 :       tmp = gfc_trans_structure_assign (se->expr, expr, expr->symtree != NULL,
   10481        15857 :                                         se->want_coarray);
   10482        15857 :       gfc_add_expr_to_block (&se->pre, tmp);
   10483        15857 :       final_block = NULL;
   10484        15857 :       return;
   10485              :     }
   10486              : 
   10487        22830 :   cm = expr->ts.u.derived->components;
   10488              : 
   10489        22830 :   for (c = gfc_constructor_first (expr->value.constructor);
   10490       120463 :        c && cm; c = gfc_constructor_next (c), cm = cm->next)
   10491              :     {
   10492              :       /* Skip absent members in default initializers and allocatable
   10493              :          components.  Although the latter have a default initializer
   10494              :          of EXPR_NULL,... by default, the static nullify is not needed
   10495              :          since this is done every time we come into scope.  */
   10496        97633 :       if (!c->expr || (cm->attr.allocatable && cm->attr.flavor != FL_PROCEDURE))
   10497         8394 :         continue;
   10498              : 
   10499        89239 :       if (cm->initializer && cm->initializer->expr_type != EXPR_NULL
   10500        51654 :           && strcmp (cm->name, "_extends") == 0
   10501         1294 :           && cm->initializer->symtree)
   10502              :         {
   10503         1294 :           tree vtab;
   10504         1294 :           gfc_symbol *vtabs;
   10505         1294 :           vtabs = cm->initializer->symtree->n.sym;
   10506         1294 :           vtab = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtabs));
   10507         1294 :           vtab = unshare_expr_without_location (vtab);
   10508         1294 :           CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, vtab);
   10509         1294 :         }
   10510        87945 :       else if (cm->ts.u.derived && strcmp (cm->name, "_size") == 0)
   10511              :         {
   10512         9766 :           val = TYPE_SIZE_UNIT (gfc_get_derived_type (cm->ts.u.derived));
   10513         9766 :           CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl,
   10514              :                                   fold_convert (TREE_TYPE (cm->backend_decl),
   10515              :                                                 val));
   10516         9766 :         }
   10517        78179 :       else if (cm->ts.type == BT_INTEGER && strcmp (cm->name, "_len") == 0)
   10518          403 :         CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl,
   10519              :                                 fold_convert (TREE_TYPE (cm->backend_decl),
   10520          403 :                                               integer_zero_node));
   10521        77776 :       else if (cm->ts.type == BT_UNION)
   10522           21 :         gfc_conv_union_initializer (v, cm, c->expr);
   10523              :       else
   10524              :         {
   10525        77755 :           val = gfc_conv_initializer (c->expr, &cm->ts,
   10526        77755 :                                       TREE_TYPE (cm->backend_decl),
   10527              :                                       cm->attr.dimension, cm->attr.pointer,
   10528        77755 :                                       cm->attr.proc_pointer);
   10529        77755 :           val = unshare_expr_without_location (val);
   10530              : 
   10531              :           /* Append it to the constructor list.  */
   10532       175388 :           CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val);
   10533              :         }
   10534              :     }
   10535              : 
   10536        22830 :   se->expr = build_constructor (type, v);
   10537        22830 :   if (init)
   10538        22830 :     TREE_CONSTANT (se->expr) = 1;
   10539              : }
   10540              : 
   10541              : 
   10542              : /* Translate a substring expression.  */
   10543              : 
   10544              : static void
   10545          258 : gfc_conv_substring_expr (gfc_se * se, gfc_expr * expr)
   10546              : {
   10547          258 :   gfc_ref *ref;
   10548              : 
   10549          258 :   ref = expr->ref;
   10550              : 
   10551          258 :   gcc_assert (ref == NULL || ref->type == REF_SUBSTRING);
   10552              : 
   10553          516 :   se->expr = gfc_build_wide_string_const (expr->ts.kind,
   10554          258 :                                           expr->value.character.length,
   10555          258 :                                           expr->value.character.string);
   10556              : 
   10557          258 :   se->string_length = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (se->expr)));
   10558          258 :   TYPE_STRING_FLAG (TREE_TYPE (se->expr)) = 1;
   10559              : 
   10560          258 :   if (ref)
   10561          258 :     gfc_conv_substring (se, ref, expr->ts.kind, NULL, &expr->where);
   10562          258 : }
   10563              : 
   10564              : 
   10565              : /* Entry point for expression translation.  Evaluates a scalar quantity.
   10566              :    EXPR is the expression to be translated, and SE is the state structure if
   10567              :    called from within the scalarized.  */
   10568              : 
   10569              : void
   10570      3609928 : gfc_conv_expr (gfc_se * se, gfc_expr * expr)
   10571              : {
   10572      3609928 :   gfc_ss *ss;
   10573              : 
   10574      3609928 :   ss = se->ss;
   10575      3609928 :   if (ss && ss->info->expr == expr
   10576       234566 :       && (ss->info->type == GFC_SS_SCALAR
   10577              :           || ss->info->type == GFC_SS_REFERENCE))
   10578              :     {
   10579        39888 :       gfc_ss_info *ss_info;
   10580              : 
   10581        39888 :       ss_info = ss->info;
   10582              :       /* Substitute a scalar expression evaluated outside the scalarization
   10583              :          loop.  */
   10584        39888 :       se->expr = ss_info->data.scalar.value;
   10585        39888 :       if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
   10586          832 :         se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
   10587              : 
   10588        39888 :       se->string_length = ss_info->string_length;
   10589        39888 :       gfc_advance_se_ss_chain (se);
   10590        39888 :       return;
   10591              :     }
   10592              : 
   10593              :   /* We need to convert the expressions for the iso_c_binding derived types.
   10594              :      C_NULL_PTR and C_NULL_FUNPTR will be made EXPR_NULL, which evaluates to
   10595              :      null_pointer_node.  C_PTR and C_FUNPTR are converted to match the
   10596              :      typespec for the C_PTR and C_FUNPTR symbols, which has already been
   10597              :      updated to be an integer with a kind equal to the size of a (void *).  */
   10598      3570040 :   if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->ts.f90_type == BT_VOID
   10599        15839 :       && expr->ts.u.derived->attr.is_bind_c)
   10600              :     {
   10601        15000 :       if (expr->expr_type == EXPR_VARIABLE
   10602        10701 :           && (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR
   10603        10701 :               || expr->symtree->n.sym->intmod_sym_id
   10604              :                  == ISOCBINDING_NULL_FUNPTR))
   10605              :         {
   10606              :           /* Set expr_type to EXPR_NULL, which will result in
   10607              :              null_pointer_node being used below.  */
   10608            0 :           expr->expr_type = EXPR_NULL;
   10609              :         }
   10610              :       else
   10611              :         {
   10612              :           /* Update the type/kind of the expression to be what the new
   10613              :              type/kind are for the updated symbols of C_PTR/C_FUNPTR.  */
   10614        15000 :           expr->ts.type = BT_INTEGER;
   10615        15000 :           expr->ts.f90_type = BT_VOID;
   10616        15000 :           expr->ts.kind = gfc_index_integer_kind;
   10617              :         }
   10618              :     }
   10619              : 
   10620      3570040 :   gfc_fix_class_refs (expr);
   10621              : 
   10622      3570040 :   switch (expr->expr_type)
   10623              :     {
   10624       502478 :     case EXPR_OP:
   10625       502478 :       gfc_conv_expr_op (se, expr);
   10626       502478 :       break;
   10627              : 
   10628          139 :     case EXPR_CONDITIONAL:
   10629          139 :       gfc_conv_conditional_expr (se, expr);
   10630          139 :       break;
   10631              : 
   10632       301353 :     case EXPR_FUNCTION:
   10633       301353 :       gfc_conv_function_expr (se, expr);
   10634       301353 :       break;
   10635              : 
   10636      1125624 :     case EXPR_CONSTANT:
   10637      1125624 :       gfc_conv_constant (se, expr);
   10638      1125624 :       break;
   10639              : 
   10640      1584912 :     case EXPR_VARIABLE:
   10641      1584912 :       gfc_conv_variable (se, expr);
   10642      1584912 :       break;
   10643              : 
   10644         4181 :     case EXPR_NULL:
   10645         4181 :       se->expr = null_pointer_node;
   10646         4181 :       break;
   10647              : 
   10648          258 :     case EXPR_SUBSTRING:
   10649          258 :       gfc_conv_substring_expr (se, expr);
   10650          258 :       break;
   10651              : 
   10652        15857 :     case EXPR_STRUCTURE:
   10653        15857 :       gfc_conv_structure (se, expr, 0);
   10654              :       /* F2008 4.5.6.3 para 5: If an executable construct references a
   10655              :          structure constructor or array constructor, the entity created by
   10656              :          the constructor is finalized after execution of the innermost
   10657              :          executable construct containing the reference. This, in fact,
   10658              :          was later deleted by the Combined Techical Corrigenda 1 TO 4 for
   10659              :          fortran 2008 (f08/0011).  */
   10660        15857 :       if ((gfc_option.allow_std & (GFC_STD_F2008 | GFC_STD_F2003))
   10661        15857 :           && !(gfc_option.allow_std & GFC_STD_GNU)
   10662          139 :           && expr->must_finalize
   10663        15869 :           && gfc_may_be_finalized (expr->ts))
   10664              :         {
   10665           12 :           locus loc;
   10666           12 :           gfc_locus_from_location (&loc, input_location);
   10667           12 :           gfc_warning (0, "The structure constructor at %L has been"
   10668              :                          " finalized. This feature was removed by f08/0011."
   10669              :                          " Use -std=f2018 or -std=gnu to eliminate the"
   10670              :                          " finalization.", &loc);
   10671           12 :           symbol_attribute attr;
   10672           12 :           attr.allocatable = attr.pointer = 0;
   10673           12 :           gfc_finalize_tree_expr (se, expr->ts.u.derived, attr, 0);
   10674           12 :           gfc_add_block_to_block (&se->post, &se->finalblock);
   10675              :         }
   10676              :       break;
   10677              : 
   10678        35238 :     case EXPR_ARRAY:
   10679        35238 :       gfc_conv_array_constructor_expr (se, expr);
   10680        35238 :       gfc_add_block_to_block (&se->post, &se->finalblock);
   10681        35238 :       break;
   10682              : 
   10683            0 :     default:
   10684            0 :       gcc_unreachable ();
   10685      3609928 :       break;
   10686              :     }
   10687              : }
   10688              : 
   10689              : /* Like gfc_conv_expr_val, but the value is also suitable for use in the lhs
   10690              :    of an assignment.  */
   10691              : void
   10692       366907 : gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr)
   10693              : {
   10694       366907 :   gfc_conv_expr (se, expr);
   10695              :   /* All numeric lvalues should have empty post chains.  If not we need to
   10696              :      figure out a way of rewriting an lvalue so that it has no post chain.  */
   10697       366907 :   gcc_assert (expr->ts.type == BT_CHARACTER || !se->post.head);
   10698       366907 : }
   10699              : 
   10700              : /* Like gfc_conv_expr, but the POST block is guaranteed to be empty for
   10701              :    numeric expressions.  Used for scalar values where inserting cleanup code
   10702              :    is inconvenient.  */
   10703              : void
   10704      1022824 : gfc_conv_expr_val (gfc_se * se, gfc_expr * expr)
   10705              : {
   10706      1022824 :   tree val;
   10707              : 
   10708      1022824 :   gcc_assert (expr->ts.type != BT_CHARACTER);
   10709      1022824 :   gfc_conv_expr (se, expr);
   10710      1022824 :   if (se->post.head)
   10711              :     {
   10712         2462 :       val = gfc_create_var (TREE_TYPE (se->expr), NULL);
   10713         2462 :       gfc_add_modify (&se->pre, val, se->expr);
   10714         2462 :       se->expr = val;
   10715         2462 :       gfc_add_block_to_block (&se->pre, &se->post);
   10716              :     }
   10717      1022824 : }
   10718              : 
   10719              : /* Helper to translate an expression and convert it to a particular type.  */
   10720              : void
   10721       287727 : gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type)
   10722              : {
   10723       287727 :   gfc_conv_expr_val (se, expr);
   10724       287727 :   se->expr = convert (type, se->expr);
   10725       287727 : }
   10726              : 
   10727              : 
   10728              : /* Converts an expression so that it can be passed by reference.  Scalar
   10729              :    values only.  */
   10730              : 
   10731              : void
   10732       225198 : gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
   10733              : {
   10734       225198 :   gfc_ss *ss;
   10735       225198 :   tree var;
   10736              : 
   10737       225198 :   ss = se->ss;
   10738       225198 :   if (ss && ss->info->expr == expr
   10739         7578 :       && ss->info->type == GFC_SS_REFERENCE)
   10740              :     {
   10741              :       /* Returns a reference to the scalar evaluated outside the loop
   10742              :          for this case.  */
   10743          907 :       gfc_conv_expr (se, expr);
   10744              : 
   10745          907 :       if (expr->ts.type == BT_CHARACTER
   10746          114 :           && expr->expr_type != EXPR_FUNCTION)
   10747          102 :         gfc_conv_string_parameter (se);
   10748              :      else
   10749          805 :         se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
   10750              : 
   10751          907 :       return;
   10752              :     }
   10753              : 
   10754       224291 :   if (expr->ts.type == BT_CHARACTER)
   10755              :     {
   10756        49414 :       gfc_conv_expr (se, expr);
   10757        49414 :       gfc_conv_string_parameter (se);
   10758        49414 :       return;
   10759              :     }
   10760              : 
   10761       174877 :   if (expr->expr_type == EXPR_VARIABLE)
   10762              :     {
   10763        69173 :       se->want_pointer = 1;
   10764        69173 :       gfc_conv_expr (se, expr);
   10765        69173 :       if (se->post.head)
   10766              :         {
   10767            0 :           var = gfc_create_var (TREE_TYPE (se->expr), NULL);
   10768            0 :           gfc_add_modify (&se->pre, var, se->expr);
   10769            0 :           gfc_add_block_to_block (&se->pre, &se->post);
   10770            0 :           se->expr = var;
   10771              :         }
   10772        69173 :       return;
   10773              :     }
   10774              : 
   10775       105704 :   if (expr->expr_type == EXPR_CONDITIONAL)
   10776              :     {
   10777           18 :       se->want_pointer = 1;
   10778           18 :       gfc_conv_expr (se, expr);
   10779           18 :       return;
   10780              :     }
   10781              : 
   10782       105686 :   if (expr->expr_type == EXPR_FUNCTION
   10783        13447 :       && ((expr->value.function.esym
   10784         2089 :            && expr->value.function.esym->result
   10785         2088 :            && expr->value.function.esym->result->attr.pointer
   10786           83 :            && !expr->value.function.esym->result->attr.dimension)
   10787        13370 :           || (!expr->value.function.esym && !expr->ref
   10788        11252 :               && expr->symtree->n.sym->attr.pointer
   10789            0 :               && !expr->symtree->n.sym->attr.dimension)))
   10790              :     {
   10791           77 :       se->want_pointer = 1;
   10792           77 :       gfc_conv_expr (se, expr);
   10793           77 :       var = gfc_create_var (TREE_TYPE (se->expr), NULL);
   10794           77 :       gfc_add_modify (&se->pre, var, se->expr);
   10795           77 :       se->expr = var;
   10796           77 :       return;
   10797              :     }
   10798              : 
   10799       105609 :   gfc_conv_expr (se, expr);
   10800              : 
   10801              :   /* Create a temporary var to hold the value.  */
   10802       105609 :   if (TREE_CONSTANT (se->expr))
   10803              :     {
   10804              :       tree tmp = se->expr;
   10805        83751 :       STRIP_TYPE_NOPS (tmp);
   10806        83751 :       var = build_decl (input_location,
   10807        83751 :                         CONST_DECL, NULL, TREE_TYPE (tmp));
   10808        83751 :       DECL_INITIAL (var) = tmp;
   10809        83751 :       TREE_STATIC (var) = 1;
   10810        83751 :       pushdecl (var);
   10811              :     }
   10812              :   else
   10813              :     {
   10814        21858 :       var = gfc_create_var (TREE_TYPE (se->expr), NULL);
   10815        21858 :       gfc_add_modify (&se->pre, var, se->expr);
   10816              :     }
   10817              : 
   10818       105609 :   if (!expr->must_finalize)
   10819       105513 :     gfc_add_block_to_block (&se->pre, &se->post);
   10820              : 
   10821              :   /* Take the address of that value.  */
   10822       105609 :   se->expr = gfc_build_addr_expr (NULL_TREE, var);
   10823              : }
   10824              : 
   10825              : 
   10826              : /* Get the _len component for an unlimited polymorphic expression.  */
   10827              : 
   10828              : static tree
   10829         1788 : trans_get_upoly_len (stmtblock_t *block, gfc_expr *expr)
   10830              : {
   10831         1788 :   gfc_se se;
   10832         1788 :   gfc_ref *ref = expr->ref;
   10833              : 
   10834         1788 :   gfc_init_se (&se, NULL);
   10835         3690 :   while (ref && ref->next)
   10836              :     ref = ref->next;
   10837         1788 :   gfc_add_len_component (expr);
   10838         1788 :   gfc_conv_expr (&se, expr);
   10839         1788 :   gfc_add_block_to_block (block, &se.pre);
   10840         1788 :   gcc_assert (se.post.head == NULL_TREE);
   10841         1788 :   if (ref)
   10842              :     {
   10843          262 :       gfc_free_ref_list (ref->next);
   10844          262 :       ref->next = NULL;
   10845              :     }
   10846              :   else
   10847              :     {
   10848         1526 :       gfc_free_ref_list (expr->ref);
   10849         1526 :       expr->ref = NULL;
   10850              :     }
   10851         1788 :   return se.expr;
   10852              : }
   10853              : 
   10854              : 
   10855              : /* Assign _vptr and _len components as appropriate.  BLOCK should be a
   10856              :    statement-list outside of the scalarizer-loop.  When code is generated, that
   10857              :    depends on the scalarized expression, it is added to RSE.PRE.
   10858              :    Returns le's _vptr tree and when set the len expressions in to_lenp and
   10859              :    from_lenp to form a le%_vptr%_copy (re, le, [from_lenp, to_lenp])
   10860              :    expression.  */
   10861              : 
   10862              : static tree
   10863         4507 : trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
   10864              :                                  gfc_expr * re, gfc_se *rse,
   10865              :                                  tree * to_lenp, tree * from_lenp,
   10866              :                                  tree * from_vptrp)
   10867              : {
   10868         4507 :   gfc_se se;
   10869         4507 :   gfc_expr * vptr_expr;
   10870         4507 :   tree tmp, to_len = NULL_TREE, from_len = NULL_TREE, lhs_vptr;
   10871         4507 :   bool set_vptr = false, temp_rhs = false;
   10872         4507 :   stmtblock_t *pre = block;
   10873         4507 :   tree class_expr = NULL_TREE;
   10874         4507 :   tree from_vptr = NULL_TREE;
   10875              : 
   10876              :   /* Create a temporary for complicated expressions.  */
   10877         4507 :   if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL
   10878         1256 :       && rse->expr != NULL_TREE)
   10879              :     {
   10880         1256 :       if (!DECL_P (rse->expr))
   10881              :         {
   10882          403 :           if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
   10883           37 :             class_expr = gfc_get_class_from_expr (rse->expr);
   10884              : 
   10885          403 :           if (rse->loop)
   10886          159 :             pre = &rse->loop->pre;
   10887              :           else
   10888          244 :             pre = &rse->pre;
   10889              : 
   10890          403 :           if (class_expr != NULL_TREE && UNLIMITED_POLY (re))
   10891           37 :               tmp = gfc_evaluate_now (TREE_OPERAND (rse->expr, 0), &rse->pre);
   10892              :           else
   10893          366 :               tmp = gfc_evaluate_now (rse->expr, &rse->pre);
   10894              : 
   10895          403 :           rse->expr = tmp;
   10896              :         }
   10897              :       else
   10898          853 :         pre = &rse->pre;
   10899              : 
   10900              :       temp_rhs = true;
   10901              :     }
   10902              : 
   10903              :   /* Get the _vptr for the left-hand side expression.  */
   10904         4507 :   gfc_init_se (&se, NULL);
   10905         4507 :   vptr_expr = gfc_find_and_cut_at_last_class_ref (le);
   10906         4507 :   if (vptr_expr != NULL && gfc_expr_attr (vptr_expr).class_ok)
   10907              :     {
   10908              :       /* Care about _len for unlimited polymorphic entities.  */
   10909         4489 :       if (UNLIMITED_POLY (vptr_expr)
   10910         3469 :           || (vptr_expr->ts.type == BT_DERIVED
   10911         2449 :               && vptr_expr->ts.u.derived->attr.unlimited_polymorphic))
   10912         1504 :         to_len = trans_get_upoly_len (block, vptr_expr);
   10913         4489 :       gfc_add_vptr_component (vptr_expr);
   10914         4489 :       set_vptr = true;
   10915              :     }
   10916              :   else
   10917           18 :     vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&le->ts));
   10918         4507 :   se.want_pointer = 1;
   10919         4507 :   gfc_conv_expr (&se, vptr_expr);
   10920         4507 :   gfc_free_expr (vptr_expr);
   10921         4507 :   gfc_add_block_to_block (block, &se.pre);
   10922         4507 :   gcc_assert (se.post.head == NULL_TREE);
   10923         4507 :   lhs_vptr = se.expr;
   10924         4507 :   STRIP_NOPS (lhs_vptr);
   10925              : 
   10926              :   /* Set the _vptr only when the left-hand side of the assignment is a
   10927              :      class-object.  */
   10928         4507 :   if (set_vptr)
   10929              :     {
   10930              :       /* Get the vptr from the rhs expression only, when it is variable.
   10931              :          Functions are expected to be assigned to a temporary beforehand.  */
   10932         3118 :       vptr_expr = (re->expr_type == EXPR_VARIABLE && re->ts.type == BT_CLASS)
   10933         5270 :           ? gfc_find_and_cut_at_last_class_ref (re)
   10934              :           : NULL;
   10935          781 :       if (vptr_expr != NULL && vptr_expr->ts.type == BT_CLASS)
   10936              :         {
   10937          781 :           if (to_len != NULL_TREE)
   10938              :             {
   10939              :               /* Get the _len information from the rhs.  */
   10940          299 :               if (UNLIMITED_POLY (vptr_expr)
   10941              :                   || (vptr_expr->ts.type == BT_DERIVED
   10942              :                       && vptr_expr->ts.u.derived->attr.unlimited_polymorphic))
   10943          272 :                 from_len = trans_get_upoly_len (block, vptr_expr);
   10944              :             }
   10945          781 :           gfc_add_vptr_component (vptr_expr);
   10946              :         }
   10947              :       else
   10948              :         {
   10949         3708 :           if (re->expr_type == EXPR_VARIABLE
   10950         2337 :               && DECL_P (re->symtree->n.sym->backend_decl)
   10951         2337 :               && DECL_LANG_SPECIFIC (re->symtree->n.sym->backend_decl)
   10952          821 :               && GFC_DECL_SAVED_DESCRIPTOR (re->symtree->n.sym->backend_decl)
   10953         3775 :               && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (
   10954              :                                            re->symtree->n.sym->backend_decl))))
   10955              :             {
   10956           43 :               vptr_expr = NULL;
   10957           43 :               se.expr = gfc_class_vptr_get (GFC_DECL_SAVED_DESCRIPTOR (
   10958              :                                              re->symtree->n.sym->backend_decl));
   10959           43 :               if (to_len && UNLIMITED_POLY (re))
   10960            0 :                 from_len = gfc_class_len_get (GFC_DECL_SAVED_DESCRIPTOR (
   10961              :                                              re->symtree->n.sym->backend_decl));
   10962              :             }
   10963         3665 :           else if (temp_rhs && re->ts.type == BT_CLASS)
   10964              :             {
   10965          214 :               vptr_expr = NULL;
   10966          214 :               if (class_expr)
   10967              :                 tmp = class_expr;
   10968          177 :               else if (!GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr)))
   10969            0 :                 tmp = gfc_get_class_from_expr (rse->expr);
   10970              :               else
   10971              :                 tmp = rse->expr;
   10972              : 
   10973          214 :               se.expr = gfc_class_vptr_get (tmp);
   10974          214 :               from_vptr = se.expr;
   10975          214 :               if (UNLIMITED_POLY (re))
   10976           74 :                 from_len = gfc_class_len_get (tmp);
   10977              : 
   10978              :             }
   10979         3451 :           else if (re->expr_type != EXPR_NULL)
   10980              :             /* Only when rhs is non-NULL use its declared type for vptr
   10981              :                initialisation.  */
   10982         3324 :             vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&re->ts));
   10983              :           else
   10984              :             /* When the rhs is NULL use the vtab of lhs' declared type.  */
   10985          127 :             vptr_expr = gfc_lval_expr_from_sym (gfc_find_vtab (&le->ts));
   10986              :         }
   10987              : 
   10988         4306 :       if (vptr_expr)
   10989              :         {
   10990         4232 :           gfc_init_se (&se, NULL);
   10991         4232 :           se.want_pointer = 1;
   10992         4232 :           gfc_conv_expr (&se, vptr_expr);
   10993         4232 :           gfc_free_expr (vptr_expr);
   10994         4232 :           gfc_add_block_to_block (block, &se.pre);
   10995         4232 :           gcc_assert (se.post.head == NULL_TREE);
   10996         4232 :           from_vptr = se.expr;
   10997              :         }
   10998         4489 :       gfc_add_modify (pre, lhs_vptr, fold_convert (TREE_TYPE (lhs_vptr),
   10999              :                                                 se.expr));
   11000              : 
   11001         4489 :       if (to_len != NULL_TREE)
   11002              :         {
   11003              :           /* The _len component needs to be set.  Figure how to get the
   11004              :              value of the right-hand side.  */
   11005         1504 :           if (from_len == NULL_TREE)
   11006              :             {
   11007         1158 :               if (rse->string_length != NULL_TREE)
   11008              :                 from_len = rse->string_length;
   11009          712 :               else if (re->ts.type == BT_CHARACTER && re->ts.u.cl->length)
   11010              :                 {
   11011            0 :                   gfc_init_se (&se, NULL);
   11012            0 :                   gfc_conv_expr (&se, re->ts.u.cl->length);
   11013            0 :                   gfc_add_block_to_block (block, &se.pre);
   11014            0 :                   gcc_assert (se.post.head == NULL_TREE);
   11015            0 :                   from_len = gfc_evaluate_now (se.expr, block);
   11016              :                 }
   11017              :               else
   11018          712 :                 from_len = build_zero_cst (gfc_charlen_type_node);
   11019              :             }
   11020         1504 :           gfc_add_modify (pre, to_len, fold_convert (TREE_TYPE (to_len),
   11021              :                                                      from_len));
   11022              :         }
   11023              :     }
   11024              : 
   11025              :   /* Return the _len and _vptr trees only, when requested.  */
   11026         4507 :   if (to_lenp)
   11027         3306 :     *to_lenp = to_len;
   11028         4507 :   if (from_lenp)
   11029         3306 :     *from_lenp = from_len;
   11030         4507 :   if (from_vptrp)
   11031         3306 :     *from_vptrp = from_vptr;
   11032         4507 :   return lhs_vptr;
   11033              : }
   11034              : 
   11035              : 
   11036              : /* Assign tokens for pointer components.  */
   11037              : 
   11038              : static void
   11039           12 : trans_caf_token_assign (gfc_se *lse, gfc_se *rse, gfc_expr *expr1,
   11040              :                         gfc_expr *expr2)
   11041              : {
   11042           12 :   symbol_attribute lhs_attr, rhs_attr;
   11043           12 :   tree tmp, lhs_tok, rhs_tok;
   11044              :   /* Flag to indicated component refs on the rhs.  */
   11045           12 :   bool rhs_cr;
   11046              : 
   11047           12 :   lhs_attr = gfc_caf_attr (expr1);
   11048           12 :   if (expr2->expr_type != EXPR_NULL)
   11049              :     {
   11050            8 :       rhs_attr = gfc_caf_attr (expr2, false, &rhs_cr);
   11051            8 :       if (lhs_attr.codimension && rhs_attr.codimension)
   11052              :         {
   11053            4 :           lhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (lse, expr1);
   11054            4 :           lhs_tok = build_fold_indirect_ref (lhs_tok);
   11055              : 
   11056            4 :           if (rhs_cr)
   11057            0 :             rhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (rse, expr2);
   11058              :           else
   11059              :             {
   11060            4 :               tree caf_decl;
   11061            4 :               caf_decl = gfc_get_tree_for_caf_expr (expr2);
   11062            4 :               gfc_get_caf_token_offset (rse, &rhs_tok, NULL, caf_decl,
   11063              :                                         NULL_TREE, NULL);
   11064              :             }
   11065            4 :           tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
   11066              :                             lhs_tok,
   11067            4 :                             fold_convert (TREE_TYPE (lhs_tok), rhs_tok));
   11068            4 :           gfc_prepend_expr_to_block (&lse->post, tmp);
   11069              :         }
   11070              :     }
   11071            4 :   else if (lhs_attr.codimension)
   11072              :     {
   11073            4 :       lhs_tok = gfc_get_ultimate_alloc_ptr_comps_caf_token (lse, expr1);
   11074            4 :       if (!lhs_tok)
   11075              :         {
   11076            2 :           lhs_tok = gfc_get_tree_for_caf_expr (expr1);
   11077            2 :           lhs_tok = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (lhs_tok));
   11078              :         }
   11079              :       else
   11080            2 :         lhs_tok = build_fold_indirect_ref (lhs_tok);
   11081            4 :       tmp = build2_loc (input_location, MODIFY_EXPR, void_type_node,
   11082              :                         lhs_tok, null_pointer_node);
   11083            4 :       gfc_prepend_expr_to_block (&lse->post, tmp);
   11084              :     }
   11085           12 : }
   11086              : 
   11087              : 
   11088              : /* Do everything that is needed for a CLASS function expr2.  */
   11089              : 
   11090              : static tree
   11091           18 : trans_class_pointer_fcn (stmtblock_t *block, gfc_se *lse, gfc_se *rse,
   11092              :                          gfc_expr *expr1, gfc_expr *expr2)
   11093              : {
   11094           18 :   tree expr1_vptr = NULL_TREE;
   11095           18 :   tree tmp;
   11096              : 
   11097           18 :   gfc_conv_function_expr (rse, expr2);
   11098           18 :   rse->expr = gfc_evaluate_now (rse->expr, &rse->pre);
   11099              : 
   11100           18 :   if (expr1->ts.type != BT_CLASS)
   11101           12 :       rse->expr = gfc_class_data_get (rse->expr);
   11102              :   else
   11103              :     {
   11104            6 :       expr1_vptr = trans_class_vptr_len_assignment (block, expr1,
   11105              :                                                     expr2, rse,
   11106              :                                                     NULL, NULL, NULL);
   11107            6 :       gfc_add_block_to_block (block, &rse->pre);
   11108            6 :       tmp = gfc_create_var (TREE_TYPE (rse->expr), "ptrtemp");
   11109            6 :       gfc_add_modify (&lse->pre, tmp, rse->expr);
   11110              : 
   11111           12 :       gfc_add_modify (&lse->pre, expr1_vptr,
   11112            6 :                       fold_convert (TREE_TYPE (expr1_vptr),
   11113              :                       gfc_class_vptr_get (tmp)));
   11114            6 :       rse->expr = gfc_class_data_get (tmp);
   11115              :     }
   11116              : 
   11117           18 :   return expr1_vptr;
   11118              : }
   11119              : 
   11120              : 
   11121              : tree
   11122        10091 : gfc_trans_pointer_assign (gfc_code * code)
   11123              : {
   11124        10091 :   return gfc_trans_pointer_assignment (code->expr1, code->expr2);
   11125              : }
   11126              : 
   11127              : 
   11128              : /* Generate code for a pointer assignment.  */
   11129              : 
   11130              : tree
   11131        10146 : gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
   11132              : {
   11133        10146 :   gfc_se lse;
   11134        10146 :   gfc_se rse;
   11135        10146 :   stmtblock_t block;
   11136        10146 :   tree desc;
   11137        10146 :   tree tmp;
   11138        10146 :   tree expr1_vptr = NULL_TREE;
   11139        10146 :   bool scalar, non_proc_ptr_assign;
   11140        10146 :   gfc_ss *ss;
   11141              : 
   11142        10146 :   gfc_start_block (&block);
   11143              : 
   11144        10146 :   gfc_init_se (&lse, NULL);
   11145              : 
   11146              :   /* Usually testing whether this is not a proc pointer assignment.  */
   11147        10146 :   non_proc_ptr_assign
   11148        10146 :     = !(gfc_expr_attr (expr1).proc_pointer
   11149         1181 :         && ((expr2->expr_type == EXPR_VARIABLE
   11150          949 :              && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE)
   11151          282 :             || expr2->expr_type == EXPR_NULL));
   11152              : 
   11153              :   /* Check whether the expression is a scalar or not; we cannot use
   11154              :      expr1->rank as it can be nonzero for proc pointers.  */
   11155        10146 :   ss = gfc_walk_expr (expr1);
   11156        10146 :   scalar = ss == gfc_ss_terminator;
   11157        10146 :   if (!scalar)
   11158         4360 :     gfc_free_ss_chain (ss);
   11159              : 
   11160        10146 :   if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS
   11161           90 :       && expr2->expr_type != EXPR_FUNCTION && non_proc_ptr_assign)
   11162              :     {
   11163           66 :       gfc_add_data_component (expr2);
   11164              :       /* The following is required as gfc_add_data_component doesn't
   11165              :          update ts.type if there is a trailing REF_ARRAY.  */
   11166           66 :       expr2->ts.type = BT_DERIVED;
   11167              :     }
   11168              : 
   11169        10146 :   if (scalar)
   11170              :     {
   11171              :       /* Scalar pointers.  */
   11172         5786 :       lse.want_pointer = 1;
   11173         5786 :       gfc_conv_expr (&lse, expr1);
   11174         5786 :       gfc_init_se (&rse, NULL);
   11175         5786 :       rse.want_pointer = 1;
   11176         5786 :       if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
   11177            6 :         trans_class_pointer_fcn (&block, &lse, &rse, expr1, expr2);
   11178              :       else
   11179         5780 :         gfc_conv_expr (&rse, expr2);
   11180              : 
   11181         5786 :       if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS)
   11182              :         {
   11183          766 :           trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL,
   11184              :                                            NULL, NULL);
   11185          766 :           lse.expr = gfc_class_data_get (lse.expr);
   11186              :         }
   11187              : 
   11188         5786 :       if (expr1->symtree->n.sym->attr.proc_pointer
   11189          851 :           && expr1->symtree->n.sym->attr.dummy)
   11190           49 :         lse.expr = build_fold_indirect_ref_loc (input_location,
   11191              :                                                 lse.expr);
   11192              : 
   11193         5786 :       if (expr2->symtree && expr2->symtree->n.sym->attr.proc_pointer
   11194           47 :           && expr2->symtree->n.sym->attr.dummy)
   11195           20 :         rse.expr = build_fold_indirect_ref_loc (input_location,
   11196              :                                                 rse.expr);
   11197              : 
   11198         5786 :       gfc_add_block_to_block (&block, &lse.pre);
   11199         5786 :       gfc_add_block_to_block (&block, &rse.pre);
   11200              : 
   11201              :       /* Check character lengths if character expression.  The test is only
   11202              :          really added if -fbounds-check is enabled.  Exclude deferred
   11203              :          character length lefthand sides.  */
   11204          954 :       if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL
   11205          780 :           && !expr1->ts.deferred
   11206          365 :           && !expr1->symtree->n.sym->attr.proc_pointer
   11207         6144 :           && !gfc_is_proc_ptr_comp (expr1))
   11208              :         {
   11209          339 :           gcc_assert (expr2->ts.type == BT_CHARACTER);
   11210          339 :           gcc_assert (lse.string_length && rse.string_length);
   11211          339 :           gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
   11212              :                                        lse.string_length, rse.string_length,
   11213              :                                        &block);
   11214              :         }
   11215              : 
   11216              :       /* The assignment to an deferred character length sets the string
   11217              :          length to that of the rhs.  */
   11218         5786 :       if (expr1->ts.deferred)
   11219              :         {
   11220          530 :           if (expr2->expr_type != EXPR_NULL && lse.string_length != NULL)
   11221          413 :             gfc_add_modify (&block, lse.string_length,
   11222          413 :                             fold_convert (TREE_TYPE (lse.string_length),
   11223              :                                           rse.string_length));
   11224          117 :           else if (lse.string_length != NULL)
   11225          115 :             gfc_add_modify (&block, lse.string_length,
   11226          115 :                             build_zero_cst (TREE_TYPE (lse.string_length)));
   11227              :         }
   11228              : 
   11229         5786 :       gfc_add_modify (&block, lse.expr,
   11230         5786 :                       fold_convert (TREE_TYPE (lse.expr), rse.expr));
   11231              : 
   11232         5786 :       if (flag_coarray == GFC_FCOARRAY_LIB)
   11233              :         {
   11234          336 :           if (expr1->ref)
   11235              :             /* Also set the tokens for pointer components in derived typed
   11236              :                coarrays.  */
   11237           12 :             trans_caf_token_assign (&lse, &rse, expr1, expr2);
   11238          324 :           else if (gfc_caf_attr (expr1).codimension)
   11239              :             {
   11240            0 :               tree lhs_caf_decl, rhs_caf_decl, lhs_tok, rhs_tok;
   11241              : 
   11242            0 :               lhs_caf_decl = gfc_get_tree_for_caf_expr (expr1);
   11243            0 :               rhs_caf_decl = gfc_get_tree_for_caf_expr (expr2);
   11244            0 :               gfc_get_caf_token_offset (&lse, &lhs_tok, nullptr, lhs_caf_decl,
   11245              :                                         NULL_TREE, expr1);
   11246            0 :               gfc_get_caf_token_offset (&rse, &rhs_tok, nullptr, rhs_caf_decl,
   11247              :                                         NULL_TREE, expr2);
   11248            0 :               gfc_add_modify (&block, lhs_tok, rhs_tok);
   11249              :             }
   11250              :         }
   11251              : 
   11252         5786 :       gfc_add_block_to_block (&block, &rse.post);
   11253         5786 :       gfc_add_block_to_block (&block, &lse.post);
   11254              :     }
   11255              :   else
   11256              :     {
   11257         4360 :       gfc_ref* remap;
   11258         4360 :       bool rank_remap;
   11259         4360 :       tree strlen_lhs;
   11260         4360 :       tree strlen_rhs = NULL_TREE;
   11261              : 
   11262              :       /* Array pointer.  Find the last reference on the LHS and if it is an
   11263              :          array section ref, we're dealing with bounds remapping.  In this case,
   11264              :          set it to AR_FULL so that gfc_conv_expr_descriptor does
   11265              :          not see it and process the bounds remapping afterwards explicitly.  */
   11266        14046 :       for (remap = expr1->ref; remap; remap = remap->next)
   11267         5705 :         if (!remap->next && remap->type == REF_ARRAY
   11268         4360 :             && remap->u.ar.type == AR_SECTION)
   11269              :           break;
   11270         4360 :       rank_remap = (remap && remap->u.ar.end[0]);
   11271              : 
   11272          379 :       if (remap && expr2->expr_type == EXPR_NULL)
   11273              :         {
   11274            2 :           gfc_error ("If bounds remapping is specified at %L, "
   11275              :                      "the pointer target shall not be NULL", &expr1->where);
   11276            2 :           return NULL_TREE;
   11277              :         }
   11278              : 
   11279         4358 :       gfc_init_se (&lse, NULL);
   11280         4358 :       if (remap)
   11281          377 :         lse.descriptor_only = 1;
   11282         4358 :       gfc_conv_expr_descriptor (&lse, expr1);
   11283         4358 :       strlen_lhs = lse.string_length;
   11284         4358 :       desc = lse.expr;
   11285              : 
   11286         4358 :       if (expr2->expr_type == EXPR_NULL)
   11287              :         {
   11288              :           /* Just set the data pointer to null.  */
   11289          680 :           gfc_conv_descriptor_data_set (&lse.pre, lse.expr, null_pointer_node);
   11290              :         }
   11291         3678 :       else if (rank_remap)
   11292              :         {
   11293              :           /* If we are rank-remapping, just get the RHS's descriptor and
   11294              :              process this later on.  */
   11295          254 :           gfc_init_se (&rse, NULL);
   11296          254 :           rse.direct_byref = 1;
   11297          254 :           rse.byref_noassign = 1;
   11298              : 
   11299          254 :           if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
   11300           12 :             expr1_vptr = trans_class_pointer_fcn (&block, &lse, &rse,
   11301              :                                                   expr1, expr2);
   11302          242 :           else if (expr2->expr_type == EXPR_FUNCTION)
   11303              :             {
   11304              :               tree bound[GFC_MAX_DIMENSIONS];
   11305              :               int i;
   11306              : 
   11307           26 :               for (i = 0; i < expr2->rank; i++)
   11308           13 :                 bound[i] = NULL_TREE;
   11309           13 :               tmp = gfc_typenode_for_spec (&expr2->ts);
   11310           13 :               tmp = gfc_get_array_type_bounds (tmp, expr2->rank, 0,
   11311              :                                                bound, bound, 0,
   11312              :                                                GFC_ARRAY_POINTER_CONT, false);
   11313           13 :               tmp = gfc_create_var (tmp, "ptrtemp");
   11314           13 :               rse.descriptor_only = 0;
   11315           13 :               rse.expr = tmp;
   11316           13 :               rse.direct_byref = 1;
   11317           13 :               gfc_conv_expr_descriptor (&rse, expr2);
   11318           13 :               strlen_rhs = rse.string_length;
   11319           13 :               rse.expr = tmp;
   11320              :             }
   11321              :           else
   11322              :             {
   11323          229 :               gfc_conv_expr_descriptor (&rse, expr2);
   11324          229 :               strlen_rhs = rse.string_length;
   11325          229 :               if (expr1->ts.type == BT_CLASS)
   11326           60 :                 expr1_vptr = trans_class_vptr_len_assignment (&block, expr1,
   11327              :                                                               expr2, &rse,
   11328              :                                                               NULL, NULL,
   11329              :                                                               NULL);
   11330              :             }
   11331              :         }
   11332         3424 :       else if (expr2->expr_type == EXPR_VARIABLE)
   11333              :         {
   11334              :           /* Assign directly to the LHS's descriptor.  */
   11335         3292 :           lse.descriptor_only = 0;
   11336         3292 :           lse.direct_byref = 1;
   11337         3292 :           gfc_conv_expr_descriptor (&lse, expr2);
   11338         3292 :           strlen_rhs = lse.string_length;
   11339         3292 :           gfc_init_se (&rse, NULL);
   11340              : 
   11341         3292 :           if (expr1->ts.type == BT_CLASS)
   11342              :             {
   11343          356 :               rse.expr = NULL_TREE;
   11344          356 :               rse.string_length = strlen_rhs;
   11345          356 :               trans_class_vptr_len_assignment (&block, expr1, expr2, &rse,
   11346              :                                                NULL, NULL, NULL);
   11347              :             }
   11348              : 
   11349         3292 :           if (remap == NULL)
   11350              :             {
   11351              :               /* If the target is not a whole array, use the target array
   11352              :                  reference for remap.  */
   11353         6757 :               for (remap = expr2->ref; remap; remap = remap->next)
   11354         3738 :                 if (remap->type == REF_ARRAY
   11355         3229 :                     && remap->u.ar.type == AR_FULL
   11356         2536 :                     && remap->next)
   11357              :                   break;
   11358              :             }
   11359              :         }
   11360          132 :       else if (expr2->expr_type == EXPR_FUNCTION && expr2->ts.type == BT_CLASS)
   11361              :         {
   11362           25 :           gfc_init_se (&rse, NULL);
   11363           25 :           rse.want_pointer = 1;
   11364           25 :           gfc_conv_function_expr (&rse, expr2);
   11365           25 :           if (expr1->ts.type != BT_CLASS)
   11366              :             {
   11367           12 :               rse.expr = gfc_class_data_get (rse.expr);
   11368           12 :               gfc_add_modify (&lse.pre, desc, rse.expr);
   11369              :             }
   11370              :           else
   11371              :             {
   11372           13 :               expr1_vptr = trans_class_vptr_len_assignment (&block, expr1,
   11373              :                                                             expr2, &rse, NULL,
   11374              :                                                             NULL, NULL);
   11375           13 :               gfc_add_block_to_block (&block, &rse.pre);
   11376           13 :               tmp = gfc_create_var (TREE_TYPE (rse.expr), "ptrtemp");
   11377           13 :               gfc_add_modify (&lse.pre, tmp, rse.expr);
   11378              : 
   11379           26 :               gfc_add_modify (&lse.pre, expr1_vptr,
   11380           13 :                               fold_convert (TREE_TYPE (expr1_vptr),
   11381              :                                         gfc_class_vptr_get (tmp)));
   11382           13 :               rse.expr = gfc_class_data_get (tmp);
   11383           13 :               gfc_add_modify (&lse.pre, desc, rse.expr);
   11384              :             }
   11385              :         }
   11386              :       else
   11387              :         {
   11388              :           /* Assign to a temporary descriptor and then copy that
   11389              :              temporary to the pointer.  */
   11390          107 :           tmp = gfc_create_var (TREE_TYPE (desc), "ptrtemp");
   11391          107 :           lse.descriptor_only = 0;
   11392          107 :           lse.expr = tmp;
   11393          107 :           lse.direct_byref = 1;
   11394          107 :           gfc_conv_expr_descriptor (&lse, expr2);
   11395          107 :           strlen_rhs = lse.string_length;
   11396          107 :           gfc_add_modify (&lse.pre, desc, tmp);
   11397              :         }
   11398              : 
   11399         4358 :       if (expr1->ts.type == BT_CHARACTER
   11400          596 :           && expr1->ts.deferred)
   11401              :         {
   11402          338 :           gfc_symbol *psym = expr1->symtree->n.sym;
   11403          338 :           tmp = NULL_TREE;
   11404          338 :           if (psym->ts.type == BT_CHARACTER
   11405          337 :               && psym->ts.u.cl->backend_decl)
   11406          337 :             tmp = psym->ts.u.cl->backend_decl;
   11407            1 :           else if (expr1->ts.u.cl->backend_decl
   11408            1 :                    && VAR_P (expr1->ts.u.cl->backend_decl))
   11409            0 :             tmp = expr1->ts.u.cl->backend_decl;
   11410            1 :           else if (TREE_CODE (lse.expr) == COMPONENT_REF)
   11411              :             {
   11412            1 :               gfc_ref *ref = expr1->ref;
   11413            3 :               for (;ref; ref = ref->next)
   11414              :                 {
   11415            2 :                   if (ref->type == REF_COMPONENT
   11416            1 :                       && ref->u.c.component->ts.type == BT_CHARACTER
   11417            3 :                       && gfc_deferred_strlen (ref->u.c.component, &tmp))
   11418            1 :                     tmp = fold_build3_loc (input_location, COMPONENT_REF,
   11419            1 :                                            TREE_TYPE (tmp),
   11420            1 :                                            TREE_OPERAND (lse.expr, 0),
   11421              :                                            tmp, NULL_TREE);
   11422              :                 }
   11423              :             }
   11424              : 
   11425          338 :           gcc_assert (tmp);
   11426              : 
   11427          338 :           if (expr2->expr_type != EXPR_NULL)
   11428          326 :             gfc_add_modify (&block, tmp,
   11429          326 :                             fold_convert (TREE_TYPE (tmp), strlen_rhs));
   11430              :           else
   11431           12 :             gfc_add_modify (&block, tmp, build_zero_cst (TREE_TYPE (tmp)));
   11432              :         }
   11433              : 
   11434         4358 :       gfc_add_block_to_block (&block, &lse.pre);
   11435         4358 :       if (rank_remap)
   11436          254 :         gfc_add_block_to_block (&block, &rse.pre);
   11437              : 
   11438              :       /* If we do bounds remapping, update LHS descriptor accordingly.  */
   11439         4358 :       if (remap)
   11440              :         {
   11441          527 :           int dim;
   11442          527 :           gcc_assert (remap->u.ar.dimen == expr1->rank);
   11443              : 
   11444              :           /* Always set dtype.  */
   11445          527 :           tree dtype = gfc_conv_descriptor_dtype (desc);
   11446          527 :           tmp = gfc_get_dtype (TREE_TYPE (desc));
   11447          527 :           gfc_add_modify (&block, dtype, tmp);
   11448              : 
   11449              :           /* For unlimited polymorphic LHS use elem_len from RHS.  */
   11450          527 :           if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
   11451              :             {
   11452           60 :               tree elem_len;
   11453           60 :               tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
   11454           60 :               elem_len = fold_convert (gfc_array_index_type, tmp);
   11455           60 :               elem_len = gfc_evaluate_now (elem_len, &block);
   11456           60 :               tmp = gfc_conv_descriptor_elem_len (desc);
   11457           60 :               gfc_add_modify (&block, tmp,
   11458           60 :                               fold_convert (TREE_TYPE (tmp), elem_len));
   11459              :             }
   11460              : 
   11461          527 :           if (rank_remap)
   11462              :             {
   11463              :               /* Do rank remapping.  We already have the RHS's descriptor
   11464              :                  converted in rse and now have to build the correct LHS
   11465              :                  descriptor for it.  */
   11466              : 
   11467          254 :               tree data, span;
   11468          254 :               tree offs, stride;
   11469          254 :               tree lbound, ubound;
   11470              : 
   11471              :               /* Copy data pointer.  */
   11472          254 :               data = gfc_conv_descriptor_data_get (rse.expr);
   11473          254 :               gfc_conv_descriptor_data_set (&block, desc, data);
   11474              : 
   11475              :               /* Copy the span.  */
   11476          254 :               if (VAR_P (rse.expr)
   11477          254 :                   && GFC_DECL_PTR_ARRAY_P (rse.expr))
   11478           12 :                 span = gfc_conv_descriptor_span_get (rse.expr);
   11479              :               else
   11480              :                 {
   11481          242 :                   tmp = TREE_TYPE (rse.expr);
   11482          242 :                   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (tmp));
   11483          242 :                   span = fold_convert (gfc_array_index_type, tmp);
   11484              :                 }
   11485          254 :               gfc_conv_descriptor_span_set (&block, desc, span);
   11486              : 
   11487              :               /* Copy offset but adjust it such that it would correspond
   11488              :                  to a lbound of zero.  */
   11489          254 :               if (expr2->rank == -1)
   11490           42 :                 gfc_conv_descriptor_offset_set (&block, desc,
   11491              :                                                 gfc_index_zero_node);
   11492              :               else
   11493              :                 {
   11494          212 :                   offs = gfc_conv_descriptor_offset_get (rse.expr);
   11495          654 :                   for (dim = 0; dim < expr2->rank; ++dim)
   11496              :                     {
   11497          230 :                       stride = gfc_conv_descriptor_stride_get (rse.expr,
   11498              :                                                         gfc_rank_cst[dim]);
   11499          230 :                       lbound = gfc_conv_descriptor_lbound_get (rse.expr,
   11500              :                                                         gfc_rank_cst[dim]);
   11501          230 :                       tmp = fold_build2_loc (input_location, MULT_EXPR,
   11502              :                                              gfc_array_index_type, stride,
   11503              :                                              lbound);
   11504          230 :                       offs = fold_build2_loc (input_location, PLUS_EXPR,
   11505              :                                               gfc_array_index_type, offs, tmp);
   11506              :                     }
   11507          212 :                   gfc_conv_descriptor_offset_set (&block, desc, offs);
   11508              :                 }
   11509              :               /* Set the bounds as declared for the LHS and calculate strides as
   11510              :                  well as another offset update accordingly.  */
   11511          254 :               stride = gfc_conv_descriptor_stride_get (rse.expr,
   11512              :                                                        gfc_rank_cst[0]);
   11513          641 :               for (dim = 0; dim < expr1->rank; ++dim)
   11514              :                 {
   11515          387 :                   gfc_se lower_se;
   11516          387 :                   gfc_se upper_se;
   11517              : 
   11518          387 :                   gcc_assert (remap->u.ar.start[dim] && remap->u.ar.end[dim]);
   11519              : 
   11520          387 :                   if (remap->u.ar.start[dim]->expr_type != EXPR_CONSTANT
   11521              :                       || remap->u.ar.start[dim]->expr_type != EXPR_VARIABLE)
   11522          387 :                     gfc_resolve_expr (remap->u.ar.start[dim]);
   11523          387 :                   if (remap->u.ar.end[dim]->expr_type != EXPR_CONSTANT
   11524              :                       || remap->u.ar.end[dim]->expr_type != EXPR_VARIABLE)
   11525          387 :                     gfc_resolve_expr (remap->u.ar.end[dim]);
   11526              : 
   11527              :                   /* Convert declared bounds.  */
   11528          387 :                   gfc_init_se (&lower_se, NULL);
   11529          387 :                   gfc_init_se (&upper_se, NULL);
   11530          387 :                   gfc_conv_expr (&lower_se, remap->u.ar.start[dim]);
   11531          387 :                   gfc_conv_expr (&upper_se, remap->u.ar.end[dim]);
   11532              : 
   11533          387 :                   gfc_add_block_to_block (&block, &lower_se.pre);
   11534          387 :                   gfc_add_block_to_block (&block, &upper_se.pre);
   11535              : 
   11536          387 :                   lbound = fold_convert (gfc_array_index_type, lower_se.expr);
   11537          387 :                   ubound = fold_convert (gfc_array_index_type, upper_se.expr);
   11538              : 
   11539          387 :                   lbound = gfc_evaluate_now (lbound, &block);
   11540          387 :                   ubound = gfc_evaluate_now (ubound, &block);
   11541              : 
   11542          387 :                   gfc_add_block_to_block (&block, &lower_se.post);
   11543          387 :                   gfc_add_block_to_block (&block, &upper_se.post);
   11544              : 
   11545              :                   /* Set bounds in descriptor.  */
   11546          387 :                   gfc_conv_descriptor_lbound_set (&block, desc,
   11547              :                                                   gfc_rank_cst[dim], lbound);
   11548          387 :                   gfc_conv_descriptor_ubound_set (&block, desc,
   11549              :                                                   gfc_rank_cst[dim], ubound);
   11550              : 
   11551              :                   /* Set stride.  */
   11552          387 :                   stride = gfc_evaluate_now (stride, &block);
   11553          387 :                   gfc_conv_descriptor_stride_set (&block, desc,
   11554              :                                                   gfc_rank_cst[dim], stride);
   11555              : 
   11556              :                   /* Update offset.  */
   11557          387 :                   offs = gfc_conv_descriptor_offset_get (desc);
   11558          387 :                   tmp = fold_build2_loc (input_location, MULT_EXPR,
   11559              :                                          gfc_array_index_type, lbound, stride);
   11560          387 :                   offs = fold_build2_loc (input_location, MINUS_EXPR,
   11561              :                                           gfc_array_index_type, offs, tmp);
   11562          387 :                   offs = gfc_evaluate_now (offs, &block);
   11563          387 :                   gfc_conv_descriptor_offset_set (&block, desc, offs);
   11564              : 
   11565              :                   /* Update stride.  */
   11566          387 :                   tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
   11567          387 :                   stride = fold_build2_loc (input_location, MULT_EXPR,
   11568              :                                             gfc_array_index_type, stride, tmp);
   11569              :                 }
   11570              :             }
   11571              :           else
   11572              :             {
   11573              :               /* Bounds remapping.  Just shift the lower bounds.  */
   11574              : 
   11575          273 :               gcc_assert (expr1->rank == expr2->rank);
   11576              : 
   11577          654 :               for (dim = 0; dim < remap->u.ar.dimen; ++dim)
   11578              :                 {
   11579          381 :                   gfc_se lbound_se;
   11580              : 
   11581          381 :                   gcc_assert (!remap->u.ar.end[dim]);
   11582          381 :                   gfc_init_se (&lbound_se, NULL);
   11583          381 :                   if (remap->u.ar.start[dim])
   11584              :                     {
   11585          225 :                       gfc_conv_expr (&lbound_se, remap->u.ar.start[dim]);
   11586          225 :                       gfc_add_block_to_block (&block, &lbound_se.pre);
   11587              :                     }
   11588              :                   else
   11589              :                     /* This remap arises from a target that is not a whole
   11590              :                        array. The start expressions will be NULL but we need
   11591              :                        the lbounds to be one.  */
   11592          156 :                     lbound_se.expr = gfc_index_one_node;
   11593          381 :                   gfc_conv_shift_descriptor_lbound (&block, desc,
   11594              :                                                     dim, lbound_se.expr);
   11595          381 :                   gfc_add_block_to_block (&block, &lbound_se.post);
   11596              :                 }
   11597              :             }
   11598              :         }
   11599              : 
   11600              :       /* If rank remapping was done, check with -fcheck=bounds that
   11601              :          the target is at least as large as the pointer.  */
   11602         4358 :       if (rank_remap && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
   11603           72 :           && expr2->rank != -1)
   11604              :         {
   11605           54 :           tree lsize, rsize;
   11606           54 :           tree fault;
   11607           54 :           const char* msg;
   11608              : 
   11609           54 :           lsize = gfc_conv_descriptor_size (lse.expr, expr1->rank);
   11610           54 :           rsize = gfc_conv_descriptor_size (rse.expr, expr2->rank);
   11611              : 
   11612           54 :           lsize = gfc_evaluate_now (lsize, &block);
   11613           54 :           rsize = gfc_evaluate_now (rsize, &block);
   11614           54 :           fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
   11615              :                                    rsize, lsize);
   11616              : 
   11617           54 :           msg = _("Target of rank remapping is too small (%ld < %ld)");
   11618           54 :           gfc_trans_runtime_check (true, false, fault, &block, &expr2->where,
   11619              :                                    msg, rsize, lsize);
   11620              :         }
   11621              : 
   11622              :       /* Check string lengths if applicable.  The check is only really added
   11623              :          to the output code if -fbounds-check is enabled.  */
   11624         4358 :       if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL)
   11625              :         {
   11626          530 :           gcc_assert (expr2->ts.type == BT_CHARACTER);
   11627          530 :           gcc_assert (strlen_lhs && strlen_rhs);
   11628          530 :           gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
   11629              :                                        strlen_lhs, strlen_rhs, &block);
   11630              :         }
   11631              : 
   11632         4358 :       gfc_add_block_to_block (&block, &lse.post);
   11633         4358 :       if (rank_remap)
   11634          254 :         gfc_add_block_to_block (&block, &rse.post);
   11635              :     }
   11636              : 
   11637        10144 :   return gfc_finish_block (&block);
   11638              : }
   11639              : 
   11640              : 
   11641              : /* Makes sure se is suitable for passing as a function string parameter.  */
   11642              : /* TODO: Need to check all callers of this function.  It may be abused.  */
   11643              : 
   11644              : void
   11645       241494 : gfc_conv_string_parameter (gfc_se * se)
   11646              : {
   11647       241494 :   tree type;
   11648              : 
   11649       241494 :   if (TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE
   11650       241494 :       && integer_onep (se->string_length))
   11651              :     {
   11652          667 :       se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
   11653          667 :       return;
   11654              :     }
   11655              : 
   11656       240827 :   if (TREE_CODE (se->expr) == STRING_CST)
   11657              :     {
   11658       100164 :       type = TREE_TYPE (TREE_TYPE (se->expr));
   11659       100164 :       se->expr = gfc_build_addr_expr (build_pointer_type (type), se->expr);
   11660       100164 :       return;
   11661              :     }
   11662              : 
   11663       140663 :   if (TREE_CODE (se->expr) == COND_EXPR)
   11664              :     {
   11665          482 :       tree cond = TREE_OPERAND (se->expr, 0);
   11666          482 :       tree lhs = TREE_OPERAND (se->expr, 1);
   11667          482 :       tree rhs = TREE_OPERAND (se->expr, 2);
   11668              : 
   11669          482 :       gfc_se lse, rse;
   11670          482 :       gfc_init_se (&lse, NULL);
   11671          482 :       gfc_init_se (&rse, NULL);
   11672              : 
   11673          482 :       lse.expr = lhs;
   11674          482 :       lse.string_length = se->string_length;
   11675          482 :       gfc_conv_string_parameter (&lse);
   11676              : 
   11677          482 :       rse.expr = rhs;
   11678          482 :       rse.string_length = se->string_length;
   11679          482 :       gfc_conv_string_parameter (&rse);
   11680              : 
   11681          482 :       se->expr
   11682          482 :         = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (lse.expr),
   11683              :                            cond, lse.expr, rse.expr);
   11684              :     }
   11685              : 
   11686       140663 :   if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
   11687        55169 :        || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
   11688       140759 :       && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
   11689              :     {
   11690        85590 :       type = TREE_TYPE (se->expr);
   11691        85590 :       if (TREE_CODE (se->expr) != INDIRECT_REF)
   11692        80540 :         se->expr = gfc_build_addr_expr (build_pointer_type (type), se->expr);
   11693              :       else
   11694              :         {
   11695         5050 :           if (TREE_CODE (type) == ARRAY_TYPE)
   11696         5050 :             type = TREE_TYPE (type);
   11697         5050 :           type = gfc_get_character_type_len_for_eltype (type,
   11698              :                                                         se->string_length);
   11699         5050 :           type = build_pointer_type (type);
   11700         5050 :           se->expr = gfc_build_addr_expr (type, se->expr);
   11701              :         }
   11702              :     }
   11703              : 
   11704       140663 :   gcc_assert (POINTER_TYPE_P (TREE_TYPE (se->expr)));
   11705              : }
   11706              : 
   11707              : 
   11708              : /* Generate code for assignment of scalar variables.  Includes character
   11709              :    strings and derived types with allocatable components.
   11710              :    If you know that the LHS has no allocations, set dealloc to false.
   11711              : 
   11712              :    DEEP_COPY has no effect if the typespec TS is not a derived type with
   11713              :    allocatable components.  Otherwise, if it is set, an explicit copy of each
   11714              :    allocatable component is made.  This is necessary as a simple copy of the
   11715              :    whole object would copy array descriptors as is, so that the lhs's
   11716              :    allocatable components would point to the rhs's after the assignment.
   11717              :    Typically, setting DEEP_COPY is necessary if the rhs is a variable, and not
   11718              :    necessary if the rhs is a non-pointer function, as the allocatable components
   11719              :    are not accessible by other means than the function's result after the
   11720              :    function has returned.  It is even more subtle when temporaries are involved,
   11721              :    as the two following examples show:
   11722              :     1.  When we evaluate an array constructor, a temporary is created.  Thus
   11723              :       there is theoretically no alias possible.  However, no deep copy is
   11724              :       made for this temporary, so that if the constructor is made of one or
   11725              :       more variable with allocatable components, those components still point
   11726              :       to the variable's: DEEP_COPY should be set for the assignment from the
   11727              :       temporary to the lhs in that case.
   11728              :     2.  When assigning a scalar to an array, we evaluate the scalar value out
   11729              :       of the loop, store it into a temporary variable, and assign from that.
   11730              :       In that case, deep copying when assigning to the temporary would be a
   11731              :       waste of resources; however deep copies should happen when assigning from
   11732              :       the temporary to each array element: again DEEP_COPY should be set for
   11733              :       the assignment from the temporary to the lhs.  */
   11734              : 
   11735              : tree
   11736       334428 : gfc_trans_scalar_assign (gfc_se *lse, gfc_se *rse, gfc_typespec ts,
   11737              :                          bool deep_copy, bool dealloc, bool in_coarray,
   11738              :                          bool assoc_assign)
   11739              : {
   11740       334428 :   stmtblock_t block;
   11741       334428 :   tree tmp;
   11742       334428 :   tree cond;
   11743              : 
   11744       334428 :   gfc_init_block (&block);
   11745              : 
   11746       334428 :   if (ts.type == BT_CHARACTER)
   11747              :     {
   11748        33071 :       tree rlen = NULL;
   11749        33071 :       tree llen = NULL;
   11750              : 
   11751        33071 :       if (lse->string_length != NULL_TREE)
   11752              :         {
   11753        33071 :           gfc_conv_string_parameter (lse);
   11754        33071 :           gfc_add_block_to_block (&block, &lse->pre);
   11755        33071 :           llen = lse->string_length;
   11756              :         }
   11757              : 
   11758        33071 :       if (rse->string_length != NULL_TREE)
   11759              :         {
   11760        33071 :           gfc_conv_string_parameter (rse);
   11761        33071 :           gfc_add_block_to_block (&block, &rse->pre);
   11762        33071 :           rlen = rse->string_length;
   11763              :         }
   11764              : 
   11765        33071 :       gfc_trans_string_copy (&block, llen, lse->expr, ts.kind, rlen,
   11766              :                              rse->expr, ts.kind);
   11767              :     }
   11768       282755 :   else if (gfc_bt_struct (ts.type)
   11769       301357 :            && (ts.u.derived->attr.alloc_comp
   11770        12248 :                || (deep_copy && has_parameterized_comps (ts.u.derived))))
   11771              :     {
   11772         6498 :       tree tmp_var = NULL_TREE;
   11773         6498 :       cond = NULL_TREE;
   11774              : 
   11775              :       /* Are the rhs and the lhs the same?  */
   11776         6498 :       if (deep_copy)
   11777              :         {
   11778         3881 :           if (!TREE_CONSTANT (rse->expr) && !VAR_P (rse->expr))
   11779         2795 :             rse->expr = gfc_evaluate_now (rse->expr, &rse->pre);
   11780         3881 :           cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   11781              :                                   gfc_build_addr_expr (NULL_TREE, lse->expr),
   11782              :                                   gfc_build_addr_expr (NULL_TREE, rse->expr));
   11783         3881 :           cond = gfc_evaluate_now (cond, &lse->pre);
   11784              :         }
   11785              : 
   11786              :       /* Deallocate the lhs allocated components as long as it is not
   11787              :          the same as the rhs.  This must be done following the assignment
   11788              :          to prevent deallocating data that could be used in the rhs
   11789              :          expression.  */
   11790         6498 :       if (dealloc)
   11791              :         {
   11792         1834 :           tmp_var = gfc_evaluate_now (lse->expr, &lse->pre);
   11793         1834 :           tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var,
   11794         1834 :                                                   0, gfc_may_be_finalized (ts));
   11795         1834 :           if (deep_copy)
   11796          767 :             tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
   11797              :                             tmp);
   11798         1834 :           gfc_add_expr_to_block (&lse->post, tmp);
   11799              :         }
   11800              : 
   11801         6498 :       gfc_add_block_to_block (&block, &rse->pre);
   11802              : 
   11803              :       /* Skip finalization for self-assignment.  */
   11804         6498 :       if (deep_copy && lse->finalblock.head)
   11805              :         {
   11806           24 :           tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
   11807              :                           gfc_finish_block (&lse->finalblock));
   11808           24 :           gfc_add_expr_to_block (&block, tmp);
   11809              :         }
   11810              :       else
   11811         6474 :         gfc_add_block_to_block (&block, &lse->finalblock);
   11812              : 
   11813         6498 :       gfc_add_block_to_block (&block, &lse->pre);
   11814              : 
   11815         6498 :       gfc_add_modify (&block, lse->expr,
   11816         6498 :                            fold_convert (TREE_TYPE (lse->expr), rse->expr));
   11817              : 
   11818              :       /* Restore pointer address of coarray components.  */
   11819         6498 :       if (ts.u.derived->attr.coarray_comp && deep_copy && tmp_var != NULL_TREE)
   11820              :         {
   11821            5 :           tmp = gfc_reassign_alloc_comp_caf (ts.u.derived, tmp_var, lse->expr);
   11822            5 :           tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
   11823              :                           tmp);
   11824            5 :           gfc_add_expr_to_block (&block, tmp);
   11825              :         }
   11826              : 
   11827              :       /* Do a deep copy if the rhs is a variable, if it is not the
   11828              :          same as the lhs.  */
   11829         6498 :       if (deep_copy)
   11830              :         {
   11831         3881 :           int caf_mode = in_coarray ? (GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
   11832              :                                        | GFC_STRUCTURE_CAF_MODE_IN_COARRAY) : 0;
   11833         3881 :           tmp = gfc_copy_alloc_comp (ts.u.derived, rse->expr, lse->expr, 0,
   11834              :                                      caf_mode);
   11835         3881 :           tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
   11836              :                           tmp);
   11837         3881 :           gfc_add_expr_to_block (&block, tmp);
   11838              :         }
   11839              :     }
   11840       294859 :   else if (gfc_bt_struct (ts.type))
   11841              :     {
   11842        12104 :       gfc_add_block_to_block (&block, &rse->pre);
   11843        12104 :       gfc_add_block_to_block (&block, &lse->finalblock);
   11844        12104 :       gfc_add_block_to_block (&block, &lse->pre);
   11845        12104 :       tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
   11846        12104 :                              TREE_TYPE (lse->expr), rse->expr);
   11847        12104 :       gfc_add_modify (&block, lse->expr, tmp);
   11848              :     }
   11849              :   /* If possible use the rhs vptr copy with trans_scalar_class_assign....  */
   11850       282755 :   else if (ts.type == BT_CLASS)
   11851              :     {
   11852          776 :       gfc_add_block_to_block (&block, &lse->pre);
   11853          776 :       gfc_add_block_to_block (&block, &rse->pre);
   11854          776 :       gfc_add_block_to_block (&block, &lse->finalblock);
   11855              : 
   11856          776 :       if (!trans_scalar_class_assign (&block, lse, rse))
   11857              :         {
   11858              :           /* ...otherwise assignment suffices. Note the use of VIEW_CONVERT_EXPR
   11859              :           for the lhs which ensures that class data rhs cast as a string assigns
   11860              :           correctly.  */
   11861          636 :           tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
   11862          636 :                                  TREE_TYPE (rse->expr), lse->expr);
   11863          636 :           gfc_add_modify (&block, tmp, rse->expr);
   11864              :         }
   11865              :     }
   11866       281979 :   else if (ts.type != BT_CLASS)
   11867              :     {
   11868       281979 :       gfc_add_block_to_block (&block, &lse->pre);
   11869       281979 :       gfc_add_block_to_block (&block, &rse->pre);
   11870              : 
   11871       281979 :       if (in_coarray)
   11872              :         {
   11873          833 :           if (flag_coarray == GFC_FCOARRAY_LIB && assoc_assign)
   11874              :             {
   11875            0 :               gfc_add_modify (&block, gfc_conv_descriptor_token (lse->expr),
   11876            0 :                               TYPE_LANG_SPECIFIC (
   11877              :                                 TREE_TYPE (TREE_TYPE (rse->expr)))
   11878              :                                 ->caf_token);
   11879              :             }
   11880          833 :           if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (lse->expr)))
   11881            0 :             lse->expr = gfc_conv_array_data (lse->expr);
   11882          273 :           if (flag_coarray == GFC_FCOARRAY_SINGLE && assoc_assign
   11883          833 :               && !POINTER_TYPE_P (TREE_TYPE (rse->expr)))
   11884            0 :             rse->expr = gfc_build_addr_expr (NULL_TREE, rse->expr);
   11885              :         }
   11886       281979 :       gfc_add_modify (&block, lse->expr,
   11887       281979 :                       fold_convert (TREE_TYPE (lse->expr), rse->expr));
   11888              :     }
   11889              : 
   11890       334428 :   gfc_add_block_to_block (&block, &lse->post);
   11891       334428 :   gfc_add_block_to_block (&block, &rse->post);
   11892              : 
   11893       334428 :   return gfc_finish_block (&block);
   11894              : }
   11895              : 
   11896              : 
   11897              : /* There are quite a lot of restrictions on the optimisation in using an
   11898              :    array function assign without a temporary.  */
   11899              : 
   11900              : static bool
   11901        14387 : arrayfunc_assign_needs_temporary (gfc_expr * expr1, gfc_expr * expr2)
   11902              : {
   11903        14387 :   gfc_ref * ref;
   11904        14387 :   bool seen_array_ref;
   11905        14387 :   bool c = false;
   11906        14387 :   gfc_symbol *sym = expr1->symtree->n.sym;
   11907              : 
   11908              :   /* Play it safe with class functions assigned to a derived type.  */
   11909        14387 :   if (gfc_is_class_array_function (expr2)
   11910        14387 :       && expr1->ts.type == BT_DERIVED)
   11911              :     return true;
   11912              : 
   11913              :   /* The caller has already checked rank>0 and expr_type == EXPR_FUNCTION.  */
   11914        14363 :   if (expr2->value.function.isym && !gfc_is_intrinsic_libcall (expr2))
   11915              :     return true;
   11916              : 
   11917              :   /* Elemental functions are scalarized so that they don't need a
   11918              :      temporary in gfc_trans_assignment_1, so return a true.  Otherwise,
   11919              :      they would need special treatment in gfc_trans_arrayfunc_assign.  */
   11920         8470 :   if (expr2->value.function.esym != NULL
   11921         1547 :       && expr2->value.function.esym->attr.elemental)
   11922              :     return true;
   11923              : 
   11924              :   /* Need a temporary if rhs is not FULL or a contiguous section.  */
   11925         8123 :   if (expr1->ref && !(gfc_full_array_ref_p (expr1->ref, &c) || c))
   11926              :     return true;
   11927              : 
   11928              :   /* Need a temporary if EXPR1 can't be expressed as a descriptor.  */
   11929         7879 :   if (gfc_ref_needs_temporary_p (expr1->ref))
   11930              :     return true;
   11931              : 
   11932              :   /* Functions returning pointers or allocatables need temporaries.  */
   11933         7867 :   if (gfc_expr_attr (expr2).pointer
   11934         7867 :       || gfc_expr_attr (expr2).allocatable)
   11935          370 :     return true;
   11936              : 
   11937              :   /* Character array functions need temporaries unless the
   11938              :      character lengths are the same.  */
   11939         7497 :   if (expr2->ts.type == BT_CHARACTER && expr2->rank > 0)
   11940              :     {
   11941          562 :       if (UNLIMITED_POLY (expr1))
   11942              :         return true;
   11943              : 
   11944          556 :       if (expr1->ts.u.cl->length == NULL
   11945          507 :             || expr1->ts.u.cl->length->expr_type != EXPR_CONSTANT)
   11946              :         return true;
   11947              : 
   11948          493 :       if (expr2->ts.u.cl->length == NULL
   11949          487 :             || expr2->ts.u.cl->length->expr_type != EXPR_CONSTANT)
   11950              :         return true;
   11951              : 
   11952          475 :       if (mpz_cmp (expr1->ts.u.cl->length->value.integer,
   11953          475 :                      expr2->ts.u.cl->length->value.integer) != 0)
   11954              :         return true;
   11955              :     }
   11956              : 
   11957              :   /* Check that no LHS component references appear during an array
   11958              :      reference. This is needed because we do not have the means to
   11959              :      span any arbitrary stride with an array descriptor. This check
   11960              :      is not needed for the rhs because the function result has to be
   11961              :      a complete type.  */
   11962         7404 :   seen_array_ref = false;
   11963        14808 :   for (ref = expr1->ref; ref; ref = ref->next)
   11964              :     {
   11965         7417 :       if (ref->type == REF_ARRAY)
   11966              :         seen_array_ref= true;
   11967           13 :       else if (ref->type == REF_COMPONENT && seen_array_ref)
   11968              :         return true;
   11969              :     }
   11970              : 
   11971              :   /* Check for a dependency.  */
   11972         7391 :   if (gfc_check_fncall_dependency (expr1, INTENT_OUT,
   11973              :                                    expr2->value.function.esym,
   11974              :                                    expr2->value.function.actual,
   11975              :                                    NOT_ELEMENTAL))
   11976              :     return true;
   11977              : 
   11978              :   /* If we have reached here with an intrinsic function, we do not
   11979              :      need a temporary except in the particular case that reallocation
   11980              :      on assignment is active and the lhs is allocatable and a target,
   11981              :      or a pointer which may be a subref pointer.  FIXME: The last
   11982              :      condition can go away when we use span in the intrinsics
   11983              :      directly.*/
   11984         6954 :   if (expr2->value.function.isym)
   11985         6094 :     return (flag_realloc_lhs && sym->attr.allocatable && sym->attr.target)
   11986        12275 :       || (sym->attr.pointer && sym->attr.subref_array_pointer);
   11987              : 
   11988              :   /* If the LHS is a dummy, we need a temporary if it is not
   11989              :      INTENT(OUT).  */
   11990          785 :   if (sym->attr.dummy && sym->attr.intent != INTENT_OUT)
   11991              :     return true;
   11992              : 
   11993              :   /* If the lhs has been host_associated, is in common, a pointer or is
   11994              :      a target and the function is not using a RESULT variable, aliasing
   11995              :      can occur and a temporary is needed.  */
   11996          779 :   if ((sym->attr.host_assoc
   11997          725 :            || sym->attr.in_common
   11998          719 :            || sym->attr.pointer
   11999          713 :            || sym->attr.cray_pointee
   12000          713 :            || sym->attr.target)
   12001           66 :         && expr2->symtree != NULL
   12002           66 :         && expr2->symtree->n.sym == expr2->symtree->n.sym->result)
   12003              :     return true;
   12004              : 
   12005              :   /* A PURE function can unconditionally be called without a temporary.  */
   12006          737 :   if (expr2->value.function.esym != NULL
   12007          712 :       && expr2->value.function.esym->attr.pure)
   12008              :     return false;
   12009              : 
   12010              :   /* Implicit_pure functions are those which could legally be declared
   12011              :      to be PURE.  */
   12012          709 :   if (expr2->value.function.esym != NULL
   12013          684 :       && expr2->value.function.esym->attr.implicit_pure)
   12014              :     return false;
   12015              : 
   12016          426 :   if (!sym->attr.use_assoc
   12017          426 :         && !sym->attr.in_common
   12018          426 :         && !sym->attr.pointer
   12019          420 :         && !sym->attr.target
   12020          420 :         && !sym->attr.cray_pointee
   12021          420 :         && expr2->value.function.esym)
   12022              :     {
   12023              :       /* A temporary is not needed if the function is not contained and
   12024              :          the variable is local or host associated and not a pointer or
   12025              :          a target.  */
   12026          395 :       if (!expr2->value.function.esym->attr.contained)
   12027              :         return false;
   12028              : 
   12029              :       /* A temporary is not needed if the lhs has never been host
   12030              :          associated and the procedure is contained.  */
   12031          152 :       else if (!sym->attr.host_assoc)
   12032              :         return false;
   12033              : 
   12034              :       /* A temporary is not needed if the variable is local and not
   12035              :          a pointer, a target or a result.  */
   12036            6 :       if (sym->ns->parent
   12037            0 :             && expr2->value.function.esym->ns == sym->ns->parent)
   12038              :         return false;
   12039              :     }
   12040              : 
   12041              :   /* Default to temporary use.  */
   12042              :   return true;
   12043              : }
   12044              : 
   12045              : 
   12046              : /* Provide the loop info so that the lhs descriptor can be built for
   12047              :    reallocatable assignments from extrinsic function calls.  */
   12048              : 
   12049              : static void
   12050          185 : realloc_lhs_loop_for_fcn_call (gfc_se *se, locus *where, gfc_ss **ss,
   12051              :                                gfc_loopinfo *loop)
   12052              : {
   12053              :   /* Signal that the function call should not be made by
   12054              :      gfc_conv_loop_setup.  */
   12055          185 :   se->ss->is_alloc_lhs = 1;
   12056          185 :   gfc_init_loopinfo (loop);
   12057          185 :   gfc_add_ss_to_loop (loop, *ss);
   12058          185 :   gfc_add_ss_to_loop (loop, se->ss);
   12059          185 :   gfc_conv_ss_startstride (loop);
   12060          185 :   gfc_conv_loop_setup (loop, where);
   12061          185 :   gfc_copy_loopinfo_to_se (se, loop);
   12062          185 :   gfc_add_block_to_block (&se->pre, &loop->pre);
   12063          185 :   gfc_add_block_to_block (&se->pre, &loop->post);
   12064          185 :   se->ss->is_alloc_lhs = 0;
   12065          185 : }
   12066              : 
   12067              : 
   12068              : /* For assignment to a reallocatable lhs from intrinsic functions,
   12069              :    replace the se.expr (ie. the result) with a temporary descriptor.
   12070              :    Null the data field so that the library allocates space for the
   12071              :    result. Free the data of the original descriptor after the function,
   12072              :    in case it appears in an argument expression and transfer the
   12073              :    result to the original descriptor.  */
   12074              : 
   12075              : static void
   12076         2120 : fcncall_realloc_result (gfc_se *se, int rank, tree dtype)
   12077              : {
   12078         2120 :   tree desc;
   12079         2120 :   tree res_desc;
   12080         2120 :   tree tmp;
   12081         2120 :   tree offset;
   12082         2120 :   tree zero_cond;
   12083         2120 :   tree not_same_shape;
   12084         2120 :   stmtblock_t shape_block;
   12085         2120 :   int n;
   12086              : 
   12087              :   /* Use the allocation done by the library.  Substitute the lhs
   12088              :      descriptor with a copy, whose data field is nulled.*/
   12089         2120 :   desc = build_fold_indirect_ref_loc (input_location, se->expr);
   12090         2120 :   if (POINTER_TYPE_P (TREE_TYPE (desc)))
   12091            9 :     desc = build_fold_indirect_ref_loc (input_location, desc);
   12092              : 
   12093              :   /* Unallocated, the descriptor does not have a dtype.  */
   12094         2120 :   tmp = gfc_conv_descriptor_dtype (desc);
   12095         2120 :   if (dtype != NULL_TREE)
   12096           13 :     gfc_add_modify (&se->pre, tmp, dtype);
   12097              :   else
   12098         2107 :     gfc_add_modify (&se->pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
   12099              : 
   12100         2120 :   res_desc = gfc_evaluate_now (desc, &se->pre);
   12101         2120 :   gfc_conv_descriptor_data_set (&se->pre, res_desc, null_pointer_node);
   12102         2120 :   se->expr = gfc_build_addr_expr (NULL_TREE, res_desc);
   12103              : 
   12104              :   /* Free the lhs after the function call and copy the result data to
   12105              :      the lhs descriptor.  */
   12106         2120 :   tmp = gfc_conv_descriptor_data_get (desc);
   12107         2120 :   zero_cond = fold_build2_loc (input_location, EQ_EXPR,
   12108              :                                logical_type_node, tmp,
   12109         2120 :                                build_int_cst (TREE_TYPE (tmp), 0));
   12110         2120 :   zero_cond = gfc_evaluate_now (zero_cond, &se->post);
   12111         2120 :   tmp = gfc_call_free (tmp);
   12112         2120 :   gfc_add_expr_to_block (&se->post, tmp);
   12113              : 
   12114         2120 :   tmp = gfc_conv_descriptor_data_get (res_desc);
   12115         2120 :   gfc_conv_descriptor_data_set (&se->post, desc, tmp);
   12116              : 
   12117              :   /* Check that the shapes are the same between lhs and expression.
   12118              :      The evaluation of the shape is done in 'shape_block' to avoid
   12119              :      unitialized warnings from the lhs bounds. */
   12120         2120 :   not_same_shape = boolean_false_node;
   12121         2120 :   gfc_start_block (&shape_block);
   12122         6826 :   for (n = 0 ; n < rank; n++)
   12123              :     {
   12124         4706 :       tree tmp1;
   12125         4706 :       tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
   12126         4706 :       tmp1 = gfc_conv_descriptor_lbound_get (res_desc, gfc_rank_cst[n]);
   12127         4706 :       tmp = fold_build2_loc (input_location, MINUS_EXPR,
   12128              :                              gfc_array_index_type, tmp, tmp1);
   12129         4706 :       tmp1 = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
   12130         4706 :       tmp = fold_build2_loc (input_location, MINUS_EXPR,
   12131              :                              gfc_array_index_type, tmp, tmp1);
   12132         4706 :       tmp1 = gfc_conv_descriptor_ubound_get (res_desc, gfc_rank_cst[n]);
   12133         4706 :       tmp = fold_build2_loc (input_location, PLUS_EXPR,
   12134              :                              gfc_array_index_type, tmp, tmp1);
   12135         4706 :       tmp = fold_build2_loc (input_location, NE_EXPR,
   12136              :                              logical_type_node, tmp,
   12137              :                              gfc_index_zero_node);
   12138         4706 :       tmp = gfc_evaluate_now (tmp, &shape_block);
   12139         4706 :       if (n == 0)
   12140              :         not_same_shape = tmp;
   12141              :       else
   12142         2586 :         not_same_shape = fold_build2_loc (input_location, TRUTH_OR_EXPR,
   12143              :                                           logical_type_node, tmp,
   12144              :                                           not_same_shape);
   12145              :     }
   12146              : 
   12147              :   /* 'zero_cond' being true is equal to lhs not being allocated or the
   12148              :      shapes being different.  */
   12149         2120 :   tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR, logical_type_node,
   12150              :                          zero_cond, not_same_shape);
   12151         2120 :   gfc_add_modify (&shape_block, zero_cond, tmp);
   12152         2120 :   tmp = gfc_finish_block (&shape_block);
   12153         2120 :   tmp = build3_v (COND_EXPR, zero_cond,
   12154              :                   build_empty_stmt (input_location), tmp);
   12155         2120 :   gfc_add_expr_to_block (&se->post, tmp);
   12156              : 
   12157              :   /* Now reset the bounds returned from the function call to bounds based
   12158              :      on the lhs lbounds, except where the lhs is not allocated or the shapes
   12159              :      of 'variable and 'expr' are different. Set the offset accordingly.  */
   12160         2120 :   offset = gfc_index_zero_node;
   12161         6826 :   for (n = 0 ; n < rank; n++)
   12162              :     {
   12163         4706 :       tree lbound;
   12164              : 
   12165         4706 :       lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
   12166         4706 :       lbound = fold_build3_loc (input_location, COND_EXPR,
   12167              :                                 gfc_array_index_type, zero_cond,
   12168              :                                 gfc_index_one_node, lbound);
   12169         4706 :       lbound = gfc_evaluate_now (lbound, &se->post);
   12170              : 
   12171         4706 :       tmp = gfc_conv_descriptor_ubound_get (res_desc, gfc_rank_cst[n]);
   12172         4706 :       tmp = fold_build2_loc (input_location, PLUS_EXPR,
   12173              :                              gfc_array_index_type, tmp, lbound);
   12174         4706 :       gfc_conv_descriptor_lbound_set (&se->post, desc,
   12175              :                                       gfc_rank_cst[n], lbound);
   12176         4706 :       gfc_conv_descriptor_ubound_set (&se->post, desc,
   12177              :                                       gfc_rank_cst[n], tmp);
   12178              : 
   12179              :       /* Set stride and accumulate the offset.  */
   12180         4706 :       tmp = gfc_conv_descriptor_stride_get (res_desc, gfc_rank_cst[n]);
   12181         4706 :       gfc_conv_descriptor_stride_set (&se->post, desc,
   12182              :                                       gfc_rank_cst[n], tmp);
   12183         4706 :       tmp = fold_build2_loc (input_location, MULT_EXPR,
   12184              :                              gfc_array_index_type, lbound, tmp);
   12185         4706 :       offset = fold_build2_loc (input_location, MINUS_EXPR,
   12186              :                                 gfc_array_index_type, offset, tmp);
   12187         4706 :       offset = gfc_evaluate_now (offset, &se->post);
   12188              :     }
   12189              : 
   12190         2120 :   gfc_conv_descriptor_offset_set (&se->post, desc, offset);
   12191         2120 : }
   12192              : 
   12193              : 
   12194              : 
   12195              : /* Try to translate array(:) = func (...), where func is a transformational
   12196              :    array function, without using a temporary.  Returns NULL if this isn't the
   12197              :    case.  */
   12198              : 
   12199              : static tree
   12200        14427 : gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
   12201              : {
   12202        14427 :   gfc_se se;
   12203        14427 :   gfc_ss *ss = NULL;
   12204        14427 :   gfc_component *comp = NULL;
   12205        14427 :   gfc_loopinfo loop;
   12206        14427 :   tree tmp;
   12207        14427 :   tree lhs;
   12208        14427 :   gfc_se final_se;
   12209        14427 :   gfc_symbol *sym = expr1->symtree->n.sym;
   12210        14427 :   bool finalizable =  gfc_may_be_finalized (expr1->ts);
   12211              : 
   12212              :   /* If the symbol is host associated and has not been referenced in its name
   12213              :      space, it might be lacking a backend_decl and vtable.  */
   12214        14427 :   if (sym->backend_decl == NULL_TREE)
   12215              :     return NULL_TREE;
   12216              : 
   12217        14387 :   if (arrayfunc_assign_needs_temporary (expr1, expr2))
   12218              :     return NULL_TREE;
   12219              : 
   12220              :   /* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
   12221              :      functions.  */
   12222         6836 :   comp = gfc_get_proc_ptr_comp (expr2);
   12223              : 
   12224         6836 :   if (!(expr2->value.function.isym
   12225          700 :               || (comp && comp->attr.dimension)
   12226          700 :               || (!comp && gfc_return_by_reference (expr2->value.function.esym)
   12227          700 :                   && expr2->value.function.esym->result->attr.dimension)))
   12228            0 :     return NULL_TREE;
   12229              : 
   12230         6836 :   gfc_init_se (&se, NULL);
   12231         6836 :   gfc_start_block (&se.pre);
   12232         6836 :   se.want_pointer = 1;
   12233              : 
   12234              :   /* First the lhs must be finalized, if necessary. We use a copy of the symbol
   12235              :      backend decl, stash the original away for the finalization so that the
   12236              :      value used is that before the assignment. This is necessary because
   12237              :      evaluation of the rhs expression using direct by reference can change
   12238              :      the value. However, the standard mandates that the finalization must occur
   12239              :      after evaluation of the rhs.  */
   12240         6836 :   gfc_init_se (&final_se, NULL);
   12241              : 
   12242         6836 :   if (finalizable)
   12243              :     {
   12244           45 :       tmp = sym->backend_decl;
   12245           45 :       lhs = sym->backend_decl;
   12246           45 :       if (INDIRECT_REF_P (tmp))
   12247            0 :         tmp = TREE_OPERAND (tmp, 0);
   12248           45 :       sym->backend_decl = gfc_create_var (TREE_TYPE (tmp), "lhs");
   12249           45 :       gfc_add_modify (&se.pre, sym->backend_decl, tmp);
   12250           45 :       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
   12251              :         {
   12252            0 :           tmp = gfc_copy_alloc_comp (expr1->ts.u.derived, tmp, sym->backend_decl,
   12253              :                                      expr1->rank, 0);
   12254            0 :           gfc_add_expr_to_block (&final_se.pre, tmp);
   12255              :         }
   12256              :     }
   12257              : 
   12258           45 :   if (finalizable && gfc_assignment_finalizer_call (&final_se, expr1, false))
   12259              :     {
   12260           45 :       gfc_add_block_to_block (&se.pre, &final_se.pre);
   12261           45 :       gfc_add_block_to_block (&se.post, &final_se.finalblock);
   12262              :     }
   12263              : 
   12264         6836 :   if (finalizable)
   12265           45 :     sym->backend_decl = lhs;
   12266              : 
   12267         6836 :   gfc_conv_array_parameter (&se, expr1, false, NULL, NULL, NULL);
   12268              : 
   12269         6836 :   if (expr1->ts.type == BT_DERIVED
   12270          234 :         && expr1->ts.u.derived->attr.alloc_comp)
   12271              :     {
   12272           80 :       tmp = build_fold_indirect_ref_loc (input_location, se.expr);
   12273           80 :       tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, tmp,
   12274              :                                               expr1->rank);
   12275           80 :       gfc_add_expr_to_block (&se.pre, tmp);
   12276              :     }
   12277              : 
   12278         6836 :   se.direct_byref = 1;
   12279         6836 :   se.ss = gfc_walk_expr (expr2);
   12280         6836 :   gcc_assert (se.ss != gfc_ss_terminator);
   12281              : 
   12282              :   /* Since this is a direct by reference call, references to the lhs can be
   12283              :      used for finalization of the function result just as long as the blocks
   12284              :      from final_se are added at the right time.  */
   12285         6836 :   gfc_init_se (&final_se, NULL);
   12286         6836 :   if (finalizable && expr2->value.function.esym)
   12287              :     {
   12288           32 :       final_se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
   12289           32 :       gfc_finalize_tree_expr (&final_se, expr2->ts.u.derived,
   12290           32 :                                     expr2->value.function.esym->attr,
   12291              :                                     expr2->rank);
   12292              :     }
   12293              : 
   12294              :   /* Reallocate on assignment needs the loopinfo for extrinsic functions.
   12295              :      This is signalled to gfc_conv_procedure_call by setting is_alloc_lhs.
   12296              :      Clearly, this cannot be done for an allocatable function result, since
   12297              :      the shape of the result is unknown and, in any case, the function must
   12298              :      correctly take care of the reallocation internally. For intrinsic
   12299              :      calls, the array data is freed and the library takes care of allocation.
   12300              :      TODO: Add logic of trans-array.cc: gfc_alloc_allocatable_for_assignment
   12301              :      to the library.  */
   12302         6836 :   if (flag_realloc_lhs
   12303         6761 :         && gfc_is_reallocatable_lhs (expr1)
   12304         9141 :         && !gfc_expr_attr (expr1).codimension
   12305         2305 :         && !gfc_is_coindexed (expr1)
   12306         9141 :         && !(expr2->value.function.esym
   12307          185 :             && expr2->value.function.esym->result->attr.allocatable))
   12308              :     {
   12309         2305 :       realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
   12310              : 
   12311         2305 :       if (!expr2->value.function.isym)
   12312              :         {
   12313          185 :           ss = gfc_walk_expr (expr1);
   12314          185 :           gcc_assert (ss != gfc_ss_terminator);
   12315              : 
   12316          185 :           realloc_lhs_loop_for_fcn_call (&se, &expr1->where, &ss, &loop);
   12317          185 :           ss->is_alloc_lhs = 1;
   12318              :         }
   12319              :       else
   12320              :         {
   12321         2120 :           tree dtype = NULL_TREE;
   12322         2120 :           tree type = gfc_typenode_for_spec (&expr2->ts);
   12323         2120 :           if (expr1->ts.type == BT_CLASS)
   12324              :             {
   12325           13 :               tmp = gfc_class_vptr_get (sym->backend_decl);
   12326           13 :               tree tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
   12327           13 :               tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
   12328           13 :               gfc_add_modify (&se.pre, tmp, tmp2);
   12329           13 :               dtype = gfc_get_dtype_rank_type (expr1->rank,type);
   12330              :             }
   12331         2120 :           fcncall_realloc_result (&se, expr1->rank, dtype);
   12332              :         }
   12333              :     }
   12334              : 
   12335         6836 :   gfc_conv_function_expr (&se, expr2);
   12336              : 
   12337              :   /* Fix the result.  */
   12338         6836 :   gfc_add_block_to_block (&se.pre, &se.post);
   12339         6836 :   if (finalizable)
   12340           45 :     gfc_add_block_to_block (&se.pre, &final_se.pre);
   12341              : 
   12342              :   /* Do the finalization, including final calls from function arguments.  */
   12343           45 :   if (finalizable)
   12344              :     {
   12345           45 :       gfc_add_block_to_block (&se.pre, &final_se.post);
   12346           45 :       gfc_add_block_to_block (&se.pre, &se.finalblock);
   12347           45 :       gfc_add_block_to_block (&se.pre, &final_se.finalblock);
   12348              :    }
   12349              : 
   12350         6836 :   if (ss)
   12351          185 :     gfc_cleanup_loop (&loop);
   12352              :   else
   12353         6651 :     gfc_free_ss_chain (se.ss);
   12354              : 
   12355         6836 :   return gfc_finish_block (&se.pre);
   12356              : }
   12357              : 
   12358              : 
   12359              : /* Try to efficiently translate array(:) = 0.  Return NULL if this
   12360              :    can't be done.  */
   12361              : 
   12362              : static tree
   12363         3929 : gfc_trans_zero_assign (gfc_expr * expr)
   12364              : {
   12365         3929 :   tree dest, len, type;
   12366         3929 :   tree tmp;
   12367         3929 :   gfc_symbol *sym;
   12368              : 
   12369         3929 :   sym = expr->symtree->n.sym;
   12370         3929 :   dest = gfc_get_symbol_decl (sym);
   12371              : 
   12372         3929 :   type = TREE_TYPE (dest);
   12373         3929 :   if (POINTER_TYPE_P (type))
   12374          248 :     type = TREE_TYPE (type);
   12375         3929 :   if (GFC_ARRAY_TYPE_P (type))
   12376              :     {
   12377              :       /* Determine the length of the array.  */
   12378         2752 :       len = GFC_TYPE_ARRAY_SIZE (type);
   12379         2752 :       if (!len || TREE_CODE (len) != INTEGER_CST)
   12380              :         return NULL_TREE;
   12381              :     }
   12382         1177 :   else if (GFC_DESCRIPTOR_TYPE_P (type)
   12383         1177 :           && gfc_is_simply_contiguous (expr, false, false))
   12384              :     {
   12385         1077 :       if (POINTER_TYPE_P (TREE_TYPE (dest)))
   12386            4 :         dest = build_fold_indirect_ref_loc (input_location, dest);
   12387         1077 :       len = gfc_conv_descriptor_size (dest, GFC_TYPE_ARRAY_RANK (type));
   12388         1077 :       dest = gfc_conv_descriptor_data_get (dest);
   12389              :     }
   12390              :   else
   12391          100 :     return NULL_TREE;
   12392              : 
   12393              :   /* If we are zeroing a local array avoid taking its address by emitting
   12394              :      a = {} instead.  */
   12395         3650 :   if (!POINTER_TYPE_P (TREE_TYPE (dest)))
   12396         2531 :     return build2_loc (input_location, MODIFY_EXPR, void_type_node,
   12397         2531 :                        dest, build_constructor (TREE_TYPE (dest),
   12398         2531 :                                               NULL));
   12399              : 
   12400              :   /* Multiply len by element size.  */
   12401         1119 :   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
   12402         1119 :   len = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
   12403              :                          len, fold_convert (gfc_array_index_type, tmp));
   12404              : 
   12405              :   /* Convert arguments to the correct types.  */
   12406         1119 :   dest = fold_convert (pvoid_type_node, dest);
   12407         1119 :   len = fold_convert (size_type_node, len);
   12408              : 
   12409              :   /* Construct call to __builtin_memset.  */
   12410         1119 :   tmp = build_call_expr_loc (input_location,
   12411              :                              builtin_decl_explicit (BUILT_IN_MEMSET),
   12412              :                              3, dest, integer_zero_node, len);
   12413         1119 :   return fold_convert (void_type_node, tmp);
   12414              : }
   12415              : 
   12416              : 
   12417              : /* Helper for gfc_trans_array_copy and gfc_trans_array_constructor_copy
   12418              :    that constructs the call to __builtin_memcpy.  */
   12419              : 
   12420              : tree
   12421         7781 : gfc_build_memcpy_call (tree dst, tree src, tree len)
   12422              : {
   12423         7781 :   tree tmp;
   12424              : 
   12425              :   /* Convert arguments to the correct types.  */
   12426         7781 :   if (!POINTER_TYPE_P (TREE_TYPE (dst)))
   12427         7522 :     dst = gfc_build_addr_expr (pvoid_type_node, dst);
   12428              :   else
   12429          259 :     dst = fold_convert (pvoid_type_node, dst);
   12430              : 
   12431         7781 :   if (!POINTER_TYPE_P (TREE_TYPE (src)))
   12432         7421 :     src = gfc_build_addr_expr (pvoid_type_node, src);
   12433              :   else
   12434          360 :     src = fold_convert (pvoid_type_node, src);
   12435              : 
   12436         7781 :   len = fold_convert (size_type_node, len);
   12437              : 
   12438              :   /* Construct call to __builtin_memcpy.  */
   12439         7781 :   tmp = build_call_expr_loc (input_location,
   12440              :                              builtin_decl_explicit (BUILT_IN_MEMCPY),
   12441              :                              3, dst, src, len);
   12442         7781 :   return fold_convert (void_type_node, tmp);
   12443              : }
   12444              : 
   12445              : 
   12446              : /* Try to efficiently translate dst(:) = src(:).  Return NULL if this
   12447              :    can't be done.  EXPR1 is the destination/lhs and EXPR2 is the
   12448              :    source/rhs, both are gfc_full_array_ref_p which have been checked for
   12449              :    dependencies.  */
   12450              : 
   12451              : static tree
   12452         2591 : gfc_trans_array_copy (gfc_expr * expr1, gfc_expr * expr2)
   12453              : {
   12454         2591 :   tree dst, dlen, dtype;
   12455         2591 :   tree src, slen, stype;
   12456         2591 :   tree tmp;
   12457              : 
   12458         2591 :   dst = gfc_get_symbol_decl (expr1->symtree->n.sym);
   12459         2591 :   src = gfc_get_symbol_decl (expr2->symtree->n.sym);
   12460              : 
   12461         2591 :   dtype = TREE_TYPE (dst);
   12462         2591 :   if (POINTER_TYPE_P (dtype))
   12463          253 :     dtype = TREE_TYPE (dtype);
   12464         2591 :   stype = TREE_TYPE (src);
   12465         2591 :   if (POINTER_TYPE_P (stype))
   12466          281 :     stype = TREE_TYPE (stype);
   12467              : 
   12468         2591 :   if (!GFC_ARRAY_TYPE_P (dtype) || !GFC_ARRAY_TYPE_P (stype))
   12469              :     return NULL_TREE;
   12470              : 
   12471              :   /* Determine the lengths of the arrays.  */
   12472         1581 :   dlen = GFC_TYPE_ARRAY_SIZE (dtype);
   12473         1581 :   if (!dlen || TREE_CODE (dlen) != INTEGER_CST)
   12474              :     return NULL_TREE;
   12475         1492 :   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (dtype));
   12476         1492 :   dlen = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
   12477              :                           dlen, fold_convert (gfc_array_index_type, tmp));
   12478              : 
   12479         1492 :   slen = GFC_TYPE_ARRAY_SIZE (stype);
   12480         1492 :   if (!slen || TREE_CODE (slen) != INTEGER_CST)
   12481              :     return NULL_TREE;
   12482         1486 :   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (stype));
   12483         1486 :   slen = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
   12484              :                           slen, fold_convert (gfc_array_index_type, tmp));
   12485              : 
   12486              :   /* Sanity check that they are the same.  This should always be
   12487              :      the case, as we should already have checked for conformance.  */
   12488         1486 :   if (!tree_int_cst_equal (slen, dlen))
   12489              :     return NULL_TREE;
   12490              : 
   12491         1486 :   return gfc_build_memcpy_call (dst, src, dlen);
   12492              : }
   12493              : 
   12494              : 
   12495              : /* Try to efficiently translate array(:) = (/ ... /).  Return NULL if
   12496              :    this can't be done.  EXPR1 is the destination/lhs for which
   12497              :    gfc_full_array_ref_p is true, and EXPR2 is the source/rhs.  */
   12498              : 
   12499              : static tree
   12500         7965 : gfc_trans_array_constructor_copy (gfc_expr * expr1, gfc_expr * expr2)
   12501              : {
   12502         7965 :   unsigned HOST_WIDE_INT nelem;
   12503         7965 :   tree dst, dtype;
   12504         7965 :   tree src, stype;
   12505         7965 :   tree len;
   12506         7965 :   tree tmp;
   12507              : 
   12508         7965 :   nelem = gfc_constant_array_constructor_p (expr2->value.constructor);
   12509         7965 :   if (nelem == 0)
   12510              :     return NULL_TREE;
   12511              : 
   12512         6624 :   dst = gfc_get_symbol_decl (expr1->symtree->n.sym);
   12513         6624 :   dtype = TREE_TYPE (dst);
   12514         6624 :   if (POINTER_TYPE_P (dtype))
   12515          258 :     dtype = TREE_TYPE (dtype);
   12516         6624 :   if (!GFC_ARRAY_TYPE_P (dtype))
   12517              :     return NULL_TREE;
   12518              : 
   12519              :   /* Determine the lengths of the array.  */
   12520         5810 :   len = GFC_TYPE_ARRAY_SIZE (dtype);
   12521         5810 :   if (!len || TREE_CODE (len) != INTEGER_CST)
   12522              :     return NULL_TREE;
   12523              : 
   12524              :   /* Confirm that the constructor is the same size.  */
   12525         5712 :   if (compare_tree_int (len, nelem) != 0)
   12526              :     return NULL_TREE;
   12527              : 
   12528         5712 :   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (dtype));
   12529         5712 :   len = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, len,
   12530              :                          fold_convert (gfc_array_index_type, tmp));
   12531              : 
   12532         5712 :   stype = gfc_typenode_for_spec (&expr2->ts);
   12533         5712 :   src = gfc_build_constant_array_constructor (expr2, stype);
   12534              : 
   12535         5712 :   return gfc_build_memcpy_call (dst, src, len);
   12536              : }
   12537              : 
   12538              : 
   12539              : /* Tells whether the expression is to be treated as a variable reference.  */
   12540              : 
   12541              : bool
   12542       311129 : gfc_expr_is_variable (gfc_expr *expr)
   12543              : {
   12544       311389 :   gfc_expr *arg;
   12545       311389 :   gfc_component *comp;
   12546       311389 :   gfc_symbol *func_ifc;
   12547              : 
   12548       311389 :   if (expr->expr_type == EXPR_VARIABLE)
   12549              :     return true;
   12550              : 
   12551       276722 :   arg = gfc_get_noncopying_intrinsic_argument (expr);
   12552       276722 :   if (arg)
   12553              :     {
   12554          260 :       gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
   12555              :       return gfc_expr_is_variable (arg);
   12556              :     }
   12557              : 
   12558              :   /* A data-pointer-returning function should be considered as a variable
   12559              :      too.  */
   12560       276462 :   if (expr->expr_type == EXPR_FUNCTION
   12561        36717 :       && expr->ref == NULL)
   12562              :     {
   12563        36340 :       if (expr->value.function.isym != NULL)
   12564              :         return false;
   12565              : 
   12566         9449 :       if (expr->value.function.esym != NULL)
   12567              :         {
   12568         9440 :           func_ifc = expr->value.function.esym;
   12569         9440 :           goto found_ifc;
   12570              :         }
   12571            9 :       gcc_assert (expr->symtree);
   12572            9 :       func_ifc = expr->symtree->n.sym;
   12573            9 :       goto found_ifc;
   12574              :     }
   12575              : 
   12576       240122 :   comp = gfc_get_proc_ptr_comp (expr);
   12577       240122 :   if ((expr->expr_type == EXPR_PPC || expr->expr_type == EXPR_FUNCTION)
   12578          377 :       && comp)
   12579              :     {
   12580          275 :       func_ifc = comp->ts.interface;
   12581          275 :       goto found_ifc;
   12582              :     }
   12583              : 
   12584       239847 :   if (expr->expr_type == EXPR_COMPCALL)
   12585              :     {
   12586            0 :       gcc_assert (!expr->value.compcall.tbp->is_generic);
   12587            0 :       func_ifc = expr->value.compcall.tbp->u.specific->n.sym;
   12588            0 :       goto found_ifc;
   12589              :     }
   12590              : 
   12591              :   return false;
   12592              : 
   12593         9724 : found_ifc:
   12594         9724 :   gcc_assert (func_ifc->attr.function
   12595              :               && func_ifc->result != NULL);
   12596         9724 :   return func_ifc->result->attr.pointer;
   12597              : }
   12598              : 
   12599              : 
   12600              : /* Is the lhs OK for automatic reallocation?  */
   12601              : 
   12602              : static bool
   12603       263800 : is_scalar_reallocatable_lhs (gfc_expr *expr)
   12604              : {
   12605       263800 :   gfc_ref * ref;
   12606              : 
   12607              :   /* An allocatable variable with no reference.  */
   12608       263800 :   if (expr->symtree->n.sym->attr.allocatable
   12609         6734 :         && !expr->ref)
   12610              :     return true;
   12611              : 
   12612              :   /* All that can be left are allocatable components.  However, we do
   12613              :      not check for allocatable components here because the expression
   12614              :      could be an allocatable component of a pointer component.  */
   12615       261050 :   if (expr->symtree->n.sym->ts.type != BT_DERIVED
   12616       238853 :         && expr->symtree->n.sym->ts.type != BT_CLASS)
   12617              :     return false;
   12618              : 
   12619              :   /* Find an allocatable component ref last.  */
   12620        39394 :   for (ref = expr->ref; ref; ref = ref->next)
   12621        16260 :     if (ref->type == REF_COMPONENT
   12622        12058 :           && !ref->next
   12623         9324 :           && ref->u.c.component->attr.allocatable)
   12624              :       return true;
   12625              : 
   12626              :   return false;
   12627              : }
   12628              : 
   12629              : 
   12630              : /* Allocate or reallocate scalar lhs, as necessary.  */
   12631              : 
   12632              : static void
   12633         3572 : alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
   12634              :                                          tree string_length,
   12635              :                                          gfc_expr *expr1,
   12636              :                                          gfc_expr *expr2)
   12637              : 
   12638              : {
   12639         3572 :   tree cond;
   12640         3572 :   tree tmp;
   12641         3572 :   tree size;
   12642         3572 :   tree size_in_bytes;
   12643         3572 :   tree jump_label1;
   12644         3572 :   tree jump_label2;
   12645         3572 :   gfc_se lse;
   12646         3572 :   gfc_ref *ref;
   12647              : 
   12648         3572 :   if (!expr1 || expr1->rank)
   12649            0 :     return;
   12650              : 
   12651         3572 :   if (!expr2 || expr2->rank)
   12652              :     return;
   12653              : 
   12654         5002 :   for (ref = expr1->ref; ref; ref = ref->next)
   12655         1430 :     if (ref->type == REF_SUBSTRING)
   12656              :       return;
   12657              : 
   12658         3572 :   realloc_lhs_warning (expr2->ts.type, false, &expr2->where);
   12659              : 
   12660              :   /* Since this is a scalar lhs, we can afford to do this.  That is,
   12661              :      there is no risk of side effects being repeated.  */
   12662         3572 :   gfc_init_se (&lse, NULL);
   12663         3572 :   lse.want_pointer = 1;
   12664         3572 :   gfc_conv_expr (&lse, expr1);
   12665              : 
   12666         3572 :   jump_label1 = gfc_build_label_decl (NULL_TREE);
   12667         3572 :   jump_label2 = gfc_build_label_decl (NULL_TREE);
   12668              : 
   12669              :   /* Do the allocation if the lhs is NULL. Otherwise go to label 1.  */
   12670         3572 :   tmp = build_int_cst (TREE_TYPE (lse.expr), 0);
   12671         3572 :   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
   12672              :                           lse.expr, tmp);
   12673         3572 :   tmp = build3_v (COND_EXPR, cond,
   12674              :                   build1_v (GOTO_EXPR, jump_label1),
   12675              :                   build_empty_stmt (input_location));
   12676         3572 :   gfc_add_expr_to_block (block, tmp);
   12677              : 
   12678         3572 :   if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
   12679              :     {
   12680              :       /* Use the rhs string length and the lhs element size. Note that 'size' is
   12681              :          used below for the string-length comparison, only.  */
   12682         1490 :       size = string_length;
   12683         1490 :       tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr1->ts.kind));
   12684         2980 :       size_in_bytes = fold_build2_loc (input_location, MULT_EXPR,
   12685         1490 :                                        TREE_TYPE (tmp), tmp,
   12686         1490 :                                        fold_convert (TREE_TYPE (tmp), size));
   12687              :     }
   12688              :   else
   12689              :     {
   12690              :       /* Otherwise use the length in bytes of the rhs.  */
   12691         2082 :       size = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
   12692         2082 :       size_in_bytes = size;
   12693              :     }
   12694              : 
   12695         3572 :   size_in_bytes = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
   12696              :                                    size_in_bytes, size_one_node);
   12697              : 
   12698         3572 :   if (gfc_caf_attr (expr1).codimension && flag_coarray == GFC_FCOARRAY_LIB)
   12699              :     {
   12700           32 :       tree caf_decl, token;
   12701           32 :       gfc_se caf_se;
   12702           32 :       symbol_attribute attr;
   12703              : 
   12704           32 :       gfc_clear_attr (&attr);
   12705           32 :       gfc_init_se (&caf_se, NULL);
   12706              : 
   12707           32 :       caf_decl = gfc_get_tree_for_caf_expr (expr1);
   12708           32 :       gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl, NULL_TREE,
   12709              :                                 NULL);
   12710           32 :       gfc_add_block_to_block (block, &caf_se.pre);
   12711           32 :       gfc_allocate_allocatable (block, lse.expr, size_in_bytes,
   12712              :                                 gfc_build_addr_expr (NULL_TREE, token),
   12713              :                                 NULL_TREE, NULL_TREE, NULL_TREE, jump_label1,
   12714              :                                 expr1, 1);
   12715              :     }
   12716         3540 :   else if (expr1->ts.type == BT_DERIVED && expr1->ts.u.derived->attr.alloc_comp)
   12717              :     {
   12718           55 :       tmp = build_call_expr_loc (input_location,
   12719              :                                  builtin_decl_explicit (BUILT_IN_CALLOC),
   12720              :                                  2, build_one_cst (size_type_node),
   12721              :                                  size_in_bytes);
   12722           55 :       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   12723           55 :       gfc_add_modify (block, lse.expr, tmp);
   12724              :     }
   12725              :   else
   12726              :     {
   12727         3485 :       tmp = build_call_expr_loc (input_location,
   12728              :                                  builtin_decl_explicit (BUILT_IN_MALLOC),
   12729              :                                  1, size_in_bytes);
   12730         3485 :       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   12731         3485 :       gfc_add_modify (block, lse.expr, tmp);
   12732              :     }
   12733              : 
   12734         3572 :   if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
   12735              :     {
   12736              :       /* Deferred characters need checking for lhs and rhs string
   12737              :          length.  Other deferred parameter variables will have to
   12738              :          come here too.  */
   12739         1490 :       tmp = build1_v (GOTO_EXPR, jump_label2);
   12740         1490 :       gfc_add_expr_to_block (block, tmp);
   12741              :     }
   12742         3572 :   tmp = build1_v (LABEL_EXPR, jump_label1);
   12743         3572 :   gfc_add_expr_to_block (block, tmp);
   12744              : 
   12745              :   /* For a deferred length character, reallocate if lengths of lhs and
   12746              :      rhs are different.  */
   12747         3572 :   if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
   12748              :     {
   12749         1490 :       cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   12750              :                               lse.string_length,
   12751         1490 :                               fold_convert (TREE_TYPE (lse.string_length),
   12752              :                                             size));
   12753              :       /* Jump past the realloc if the lengths are the same.  */
   12754         1490 :       tmp = build3_v (COND_EXPR, cond,
   12755              :                       build1_v (GOTO_EXPR, jump_label2),
   12756              :                       build_empty_stmt (input_location));
   12757         1490 :       gfc_add_expr_to_block (block, tmp);
   12758         1490 :       tmp = build_call_expr_loc (input_location,
   12759              :                                  builtin_decl_explicit (BUILT_IN_REALLOC),
   12760              :                                  2, fold_convert (pvoid_type_node, lse.expr),
   12761              :                                  size_in_bytes);
   12762         1490 :       tree omp_cond = NULL_TREE;
   12763         1490 :       if (flag_openmp_allocators)
   12764              :         {
   12765            1 :           tree omp_tmp;
   12766            1 :           omp_cond = gfc_omp_call_is_alloc (lse.expr);
   12767            1 :           omp_cond = gfc_evaluate_now (omp_cond, block);
   12768              : 
   12769            1 :           omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_REALLOC);
   12770            1 :           omp_tmp = build_call_expr_loc (input_location, omp_tmp, 4,
   12771              :                                          fold_convert (pvoid_type_node,
   12772              :                                                        lse.expr), size_in_bytes,
   12773              :                                          build_zero_cst (ptr_type_node),
   12774              :                                          build_zero_cst (ptr_type_node));
   12775            1 :           tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
   12776              :                             omp_cond, omp_tmp, tmp);
   12777              :         }
   12778         1490 :       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   12779         1490 :       gfc_add_modify (block, lse.expr, tmp);
   12780         1490 :       if (omp_cond)
   12781            1 :         gfc_add_expr_to_block (block,
   12782              :                                build3_loc (input_location, COND_EXPR,
   12783              :                                void_type_node, omp_cond,
   12784              :                                gfc_omp_call_add_alloc (lse.expr),
   12785              :                                build_empty_stmt (input_location)));
   12786         1490 :       tmp = build1_v (LABEL_EXPR, jump_label2);
   12787         1490 :       gfc_add_expr_to_block (block, tmp);
   12788              : 
   12789              :       /* Update the lhs character length.  */
   12790         1490 :       size = string_length;
   12791         1490 :       gfc_add_modify (block, lse.string_length,
   12792         1490 :                       fold_convert (TREE_TYPE (lse.string_length), size));
   12793              :     }
   12794              : }
   12795              : 
   12796              : /* Check for assignments of the type
   12797              : 
   12798              :    a = a + 4
   12799              : 
   12800              :    to make sure we do not check for reallocation unneccessarily.  */
   12801              : 
   12802              : 
   12803              : /* Strip parentheses from an expression to get the underlying variable.
   12804              :    This is needed for self-assignment detection since (a) creates a
   12805              :    parentheses operator node.  */
   12806              : 
   12807              : static gfc_expr *
   12808         7701 : strip_parentheses (gfc_expr *expr)
   12809              : {
   12810            0 :   while (expr->expr_type == EXPR_OP
   12811       312579 :          && expr->value.op.op == INTRINSIC_PARENTHESES)
   12812          536 :     expr = expr->value.op.op1;
   12813       311408 :   return expr;
   12814              : }
   12815              : 
   12816              : 
   12817              : static bool
   12818         7260 : is_runtime_conformable (gfc_expr *expr1, gfc_expr *expr2)
   12819              : {
   12820         7701 :   gfc_actual_arglist *a;
   12821         7701 :   gfc_expr *e1, *e2;
   12822              : 
   12823              :   /* Strip parentheses to handle cases like a = (a).  */
   12824        15429 :   expr1 = strip_parentheses (expr1);
   12825         7701 :   expr2 = strip_parentheses (expr2);
   12826              : 
   12827         7701 :   switch (expr2->expr_type)
   12828              :     {
   12829         2062 :     case EXPR_VARIABLE:
   12830         2062 :       return gfc_dep_compare_expr (expr1, expr2) == 0;
   12831              : 
   12832         2815 :     case EXPR_FUNCTION:
   12833         2815 :       if (expr2->value.function.esym
   12834          281 :           && expr2->value.function.esym->attr.elemental)
   12835              :         {
   12836           63 :           for (a = expr2->value.function.actual; a != NULL; a = a->next)
   12837              :             {
   12838           62 :               e1 = a->expr;
   12839           62 :               if (e1 && e1->rank > 0 && !is_runtime_conformable (expr1, e1))
   12840              :                 return false;
   12841              :             }
   12842              :           return true;
   12843              :         }
   12844         2765 :       else if (expr2->value.function.isym
   12845         2520 :                && expr2->value.function.isym->elemental)
   12846              :         {
   12847          332 :           for (a = expr2->value.function.actual; a != NULL; a = a->next)
   12848              :             {
   12849          322 :               e1 = a->expr;
   12850          322 :               if (e1 && e1->rank > 0 && !is_runtime_conformable (expr1, e1))
   12851              :                 return false;
   12852              :             }
   12853              :           return true;
   12854              :         }
   12855              : 
   12856              :       break;
   12857              : 
   12858          635 :     case EXPR_OP:
   12859          635 :       switch (expr2->value.op.op)
   12860              :         {
   12861           19 :         case INTRINSIC_NOT:
   12862           19 :         case INTRINSIC_UPLUS:
   12863           19 :         case INTRINSIC_UMINUS:
   12864           19 :         case INTRINSIC_PARENTHESES:
   12865           19 :           return is_runtime_conformable (expr1, expr2->value.op.op1);
   12866              : 
   12867          591 :         case INTRINSIC_PLUS:
   12868          591 :         case INTRINSIC_MINUS:
   12869          591 :         case INTRINSIC_TIMES:
   12870          591 :         case INTRINSIC_DIVIDE:
   12871          591 :         case INTRINSIC_POWER:
   12872          591 :         case INTRINSIC_AND:
   12873          591 :         case INTRINSIC_OR:
   12874          591 :         case INTRINSIC_EQV:
   12875          591 :         case INTRINSIC_NEQV:
   12876          591 :         case INTRINSIC_EQ:
   12877          591 :         case INTRINSIC_NE:
   12878          591 :         case INTRINSIC_GT:
   12879          591 :         case INTRINSIC_GE:
   12880          591 :         case INTRINSIC_LT:
   12881          591 :         case INTRINSIC_LE:
   12882          591 :         case INTRINSIC_EQ_OS:
   12883          591 :         case INTRINSIC_NE_OS:
   12884          591 :         case INTRINSIC_GT_OS:
   12885          591 :         case INTRINSIC_GE_OS:
   12886          591 :         case INTRINSIC_LT_OS:
   12887          591 :         case INTRINSIC_LE_OS:
   12888              : 
   12889          591 :           e1 = expr2->value.op.op1;
   12890          591 :           e2 = expr2->value.op.op2;
   12891              : 
   12892          591 :           if (e1->rank == 0 && e2->rank > 0)
   12893              :             return is_runtime_conformable (expr1, e2);
   12894          539 :           else if (e1->rank > 0 && e2->rank == 0)
   12895              :             return is_runtime_conformable (expr1, e1);
   12896          169 :           else if (e1->rank > 0 && e2->rank > 0)
   12897          169 :             return is_runtime_conformable (expr1, e1)
   12898          169 :               && is_runtime_conformable (expr1, e2);
   12899              :           break;
   12900              : 
   12901              :         default:
   12902              :           break;
   12903              : 
   12904              :         }
   12905              : 
   12906              :       break;
   12907              : 
   12908              :     default:
   12909              :       break;
   12910              :     }
   12911              :   return false;
   12912              : }
   12913              : 
   12914              : 
   12915              : static tree
   12916         3306 : trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
   12917              :                         gfc_se *lse, gfc_se *rse, bool use_vptr_copy,
   12918              :                         bool class_realloc)
   12919              : {
   12920         3306 :   tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr, rhs_vptr;
   12921         3306 :   vec<tree, va_gc> *args = NULL;
   12922         3306 :   bool final_expr;
   12923              : 
   12924         3306 :   final_expr = gfc_assignment_finalizer_call (lse, lhs, false);
   12925         3306 :   if (final_expr)
   12926              :     {
   12927          485 :       if (rse->loop)
   12928          226 :         gfc_prepend_expr_to_block (&rse->loop->pre,
   12929              :                                    gfc_finish_block (&lse->finalblock));
   12930              :       else
   12931          259 :         gfc_add_block_to_block (block, &lse->finalblock);
   12932              :     }
   12933              : 
   12934              :   /* Store the old vptr so that dynamic types can be compared for
   12935              :      reallocation to occur or not.  */
   12936         3306 :   if (class_realloc)
   12937              :     {
   12938          301 :       tmp = lse->expr;
   12939          301 :       if (!GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
   12940           18 :         tmp = gfc_get_class_from_expr (tmp);
   12941              :     }
   12942              : 
   12943         3306 :   vptr = trans_class_vptr_len_assignment (block, lhs, rhs, rse, &to_len,
   12944              :                                           &from_len, &rhs_vptr);
   12945         3306 :   if (rhs_vptr == NULL_TREE)
   12946           61 :     rhs_vptr = vptr;
   12947              : 
   12948              :   /* Generate (re)allocation of the lhs.  */
   12949         3306 :   if (class_realloc)
   12950              :     {
   12951          301 :       stmtblock_t alloc, re_alloc;
   12952          301 :       tree class_han, re, size;
   12953              : 
   12954          301 :       if (tmp && GFC_CLASS_TYPE_P (TREE_TYPE (tmp)))
   12955          283 :         old_vptr = gfc_evaluate_now (gfc_class_vptr_get (tmp), block);
   12956              :       else
   12957           18 :         old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
   12958              : 
   12959          301 :       size = gfc_vptr_size_get (rhs_vptr);
   12960              : 
   12961              :       /* Take into account _len of unlimited polymorphic entities.
   12962              :          TODO: handle class(*) allocatable function results on rhs.  */
   12963          301 :       if (UNLIMITED_POLY (rhs))
   12964              :         {
   12965           18 :           tree len;
   12966           18 :           if (rhs->expr_type == EXPR_VARIABLE)
   12967           12 :             len = trans_get_upoly_len (block, rhs);
   12968              :           else
   12969            6 :             len = gfc_class_len_get (tmp);
   12970           18 :           len = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
   12971              :                                  fold_convert (size_type_node, len),
   12972              :                                  size_one_node);
   12973           18 :           size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size),
   12974           18 :                                   size, fold_convert (TREE_TYPE (size), len));
   12975           18 :         }
   12976          283 :       else if (rhs->ts.type == BT_CHARACTER && rse->string_length)
   12977           27 :         size = fold_build2_loc (input_location, MULT_EXPR,
   12978              :                                 gfc_charlen_type_node, size,
   12979              :                                 rse->string_length);
   12980              : 
   12981              : 
   12982          301 :       tmp = lse->expr;
   12983          301 :       class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
   12984          301 :           ? gfc_class_data_get (tmp) : tmp;
   12985              : 
   12986          301 :       if (!POINTER_TYPE_P (TREE_TYPE (class_han)))
   12987           18 :         class_han = gfc_build_addr_expr (NULL_TREE, class_han);
   12988              : 
   12989              :       /* Allocate block.  */
   12990          301 :       gfc_init_block (&alloc);
   12991          301 :       gfc_allocate_using_malloc (&alloc, class_han, size, NULL_TREE);
   12992              : 
   12993              :       /* Reallocate if dynamic types are different. */
   12994          301 :       gfc_init_block (&re_alloc);
   12995          301 :       if (UNLIMITED_POLY (lhs) && rhs->ts.type == BT_CHARACTER)
   12996              :         {
   12997           27 :           gfc_add_expr_to_block (&re_alloc, gfc_call_free (class_han));
   12998           27 :           gfc_allocate_using_malloc (&re_alloc, class_han, size, NULL_TREE);
   12999              :         }
   13000              :       else
   13001              :         {
   13002          274 :           tmp = fold_convert (pvoid_type_node, class_han);
   13003          274 :           re = build_call_expr_loc (input_location,
   13004              :                                     builtin_decl_explicit (BUILT_IN_REALLOC),
   13005              :                                     2, tmp, size);
   13006          274 :           re = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp),
   13007              :                                 tmp, re);
   13008          274 :           tmp = fold_build2_loc (input_location, NE_EXPR,
   13009              :                                  logical_type_node, rhs_vptr, old_vptr);
   13010          274 :           re = fold_build3_loc (input_location, COND_EXPR, void_type_node,
   13011              :                                 tmp, re, build_empty_stmt (input_location));
   13012          274 :           gfc_add_expr_to_block (&re_alloc, re);
   13013              :         }
   13014          301 :       tree realloc_expr = lhs->ts.type == BT_CLASS ?
   13015          283 :                                           gfc_finish_block (&re_alloc) :
   13016           18 :                                           build_empty_stmt (input_location);
   13017              : 
   13018              :       /* Allocate if _data is NULL, reallocate otherwise.  */
   13019          301 :       tmp = fold_build2_loc (input_location, EQ_EXPR,
   13020              :                              logical_type_node, class_han,
   13021              :                              build_int_cst (prvoid_type_node, 0));
   13022          301 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
   13023              :                              gfc_unlikely (tmp,
   13024              :                                            PRED_FORTRAN_FAIL_ALLOC),
   13025              :                              gfc_finish_block (&alloc),
   13026              :                              realloc_expr);
   13027          301 :       gfc_add_expr_to_block (&lse->pre, tmp);
   13028              :     }
   13029              : 
   13030         3306 :   fcn = gfc_vptr_copy_get (vptr);
   13031              : 
   13032         3306 :   tmp = GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))
   13033         3306 :       ? gfc_class_data_get (rse->expr) : rse->expr;
   13034         3306 :   if (use_vptr_copy)
   13035              :     {
   13036         5560 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp))
   13037          524 :           || INDIRECT_REF_P (tmp)
   13038          403 :           || (rhs->ts.type == BT_DERIVED
   13039            0 :               && rhs->ts.u.derived->attr.unlimited_polymorphic
   13040            0 :               && !rhs->ts.u.derived->attr.pointer
   13041            0 :               && !rhs->ts.u.derived->attr.allocatable)
   13042         3442 :           || (UNLIMITED_POLY (rhs)
   13043          134 :               && !CLASS_DATA (rhs)->attr.pointer
   13044           43 :               && !CLASS_DATA (rhs)->attr.allocatable))
   13045         2636 :         vec_safe_push (args, gfc_build_addr_expr (NULL_TREE, tmp));
   13046              :       else
   13047          403 :         vec_safe_push (args, tmp);
   13048         3039 :       tmp = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
   13049         3039 :           ? gfc_class_data_get (lse->expr) : lse->expr;
   13050         5298 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp))
   13051          780 :           || INDIRECT_REF_P (tmp)
   13052          283 :           || (lhs->ts.type == BT_DERIVED
   13053            0 :               && lhs->ts.u.derived->attr.unlimited_polymorphic
   13054            0 :               && !lhs->ts.u.derived->attr.pointer
   13055            0 :               && !lhs->ts.u.derived->attr.allocatable)
   13056         3322 :           || (UNLIMITED_POLY (lhs)
   13057          119 :               && !CLASS_DATA (lhs)->attr.pointer
   13058          119 :               && !CLASS_DATA (lhs)->attr.allocatable))
   13059         2756 :         vec_safe_push (args, gfc_build_addr_expr (NULL_TREE, tmp));
   13060              :       else
   13061          283 :         vec_safe_push (args, tmp);
   13062              : 
   13063         3039 :       stdcopy = build_call_vec (TREE_TYPE (TREE_TYPE (fcn)), fcn, args);
   13064              : 
   13065         3039 :       if (to_len != NULL_TREE && !integer_zerop (from_len))
   13066              :         {
   13067          406 :           tree extcopy;
   13068          406 :           vec_safe_push (args, from_len);
   13069          406 :           vec_safe_push (args, to_len);
   13070          406 :           extcopy = build_call_vec (TREE_TYPE (TREE_TYPE (fcn)), fcn, args);
   13071              : 
   13072          406 :           tmp = fold_build2_loc (input_location, GT_EXPR,
   13073              :                                  logical_type_node, from_len,
   13074          406 :                                  build_zero_cst (TREE_TYPE (from_len)));
   13075          406 :           return fold_build3_loc (input_location, COND_EXPR,
   13076              :                                   void_type_node, tmp,
   13077          406 :                                   extcopy, stdcopy);
   13078              :         }
   13079              :       else
   13080         2633 :         return stdcopy;
   13081              :     }
   13082              :   else
   13083              :     {
   13084          267 :       tree rhst = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
   13085          267 :           ? gfc_class_data_get (lse->expr) : lse->expr;
   13086          267 :       stmtblock_t tblock;
   13087          267 :       gfc_init_block (&tblock);
   13088          267 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
   13089            0 :         tmp = gfc_build_addr_expr (NULL_TREE, tmp);
   13090          267 :       if (!POINTER_TYPE_P (TREE_TYPE (rhst)))
   13091            0 :         rhst = gfc_build_addr_expr (NULL_TREE, rhst);
   13092              :       /* When coming from a ptr_copy lhs and rhs are swapped.  */
   13093          267 :       gfc_add_modify_loc (input_location, &tblock, rhst,
   13094          267 :                           fold_convert (TREE_TYPE (rhst), tmp));
   13095          267 :       return gfc_finish_block (&tblock);
   13096              :     }
   13097              : }
   13098              : 
   13099              : bool
   13100       305764 : is_assoc_assign (gfc_expr *lhs, gfc_expr *rhs)
   13101              : {
   13102       305764 :   if (lhs->expr_type != EXPR_VARIABLE || rhs->expr_type != EXPR_VARIABLE)
   13103              :     return false;
   13104              : 
   13105        31431 :   return lhs->symtree->n.sym->assoc
   13106        31431 :          && lhs->symtree->n.sym->assoc->target == rhs;
   13107              : }
   13108              : 
   13109              : /* Subroutine of gfc_trans_assignment that actually scalarizes the
   13110              :    assignment.  EXPR1 is the destination/LHS and EXPR2 is the source/RHS.
   13111              :    init_flag indicates initialization expressions and dealloc that no
   13112              :    deallocate prior assignment is needed (if in doubt, set true).
   13113              :    When PTR_COPY is set and expr1 is a class type, then use the _vptr-copy
   13114              :    routine instead of a pointer assignment.  Alias resolution is only done,
   13115              :    when MAY_ALIAS is set (the default).  This flag is used by ALLOCATE()
   13116              :    where it is known, that newly allocated memory on the lhs can never be
   13117              :    an alias of the rhs.  */
   13118              : 
   13119              : static tree
   13120       305764 : gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
   13121              :                         bool dealloc, bool use_vptr_copy, bool may_alias)
   13122              : {
   13123       305764 :   gfc_se lse;
   13124       305764 :   gfc_se rse;
   13125       305764 :   gfc_ss *lss;
   13126       305764 :   gfc_ss *lss_section;
   13127       305764 :   gfc_ss *rss;
   13128       305764 :   gfc_loopinfo loop;
   13129       305764 :   tree tmp;
   13130       305764 :   stmtblock_t block;
   13131       305764 :   stmtblock_t body;
   13132       305764 :   bool final_expr;
   13133       305764 :   bool l_is_temp;
   13134       305764 :   bool scalar_to_array;
   13135       305764 :   tree string_length;
   13136       305764 :   int n;
   13137       305764 :   bool maybe_workshare = false, lhs_refs_comp = false, rhs_refs_comp = false;
   13138       305764 :   symbol_attribute lhs_caf_attr, rhs_caf_attr, lhs_attr, rhs_attr;
   13139       305764 :   bool is_poly_assign;
   13140       305764 :   bool realloc_flag;
   13141       305764 :   bool assoc_assign = false;
   13142       305764 :   bool dummy_class_array_copy;
   13143              : 
   13144              :   /* Assignment of the form lhs = rhs.  */
   13145       305764 :   gfc_start_block (&block);
   13146              : 
   13147       305764 :   gfc_init_se (&lse, NULL);
   13148       305764 :   gfc_init_se (&rse, NULL);
   13149              : 
   13150       305764 :   gfc_fix_class_refs (expr1);
   13151              : 
   13152       611528 :   realloc_flag = flag_realloc_lhs
   13153       299740 :                  && gfc_is_reallocatable_lhs (expr1)
   13154         8065 :                  && expr2->rank
   13155       312376 :                  && !is_runtime_conformable (expr1, expr2);
   13156              : 
   13157              :   /* Walk the lhs.  */
   13158       305764 :   lss = gfc_walk_expr (expr1);
   13159       305764 :   if (realloc_flag)
   13160              :     {
   13161         6259 :       lss->no_bounds_check = 1;
   13162         6259 :       lss->is_alloc_lhs = 1;
   13163              :     }
   13164              :   else
   13165       299505 :     lss->no_bounds_check = expr1->no_bounds_check;
   13166              : 
   13167       305764 :   rss = NULL;
   13168              : 
   13169       305764 :   if (expr2->expr_type != EXPR_VARIABLE
   13170       305764 :       && expr2->expr_type != EXPR_CONSTANT
   13171       305764 :       && (expr2->ts.type == BT_CLASS || gfc_may_be_finalized (expr2->ts)))
   13172              :     {
   13173          851 :       expr2->must_finalize = 1;
   13174              :       /* F2023 7.5.6.3: If an executable construct references a nonpointer
   13175              :          function, the result is finalized after execution of the innermost
   13176              :          executable construct containing the reference.  */
   13177          851 :       if (expr2->expr_type == EXPR_FUNCTION
   13178          851 :           && (gfc_expr_attr (expr2).pointer
   13179          292 :               || (expr2->ts.type == BT_CLASS && CLASS_DATA (expr2)->attr.class_pointer)))
   13180          146 :         expr2->must_finalize = 0;
   13181              :       /* F2008 4.5.6.3 para 5: If an executable construct references a
   13182              :          structure constructor or array constructor, the entity created by
   13183              :          the constructor is finalized after execution of the innermost
   13184              :          executable construct containing the reference.
   13185              :          These finalizations were later deleted by the Combined Techical
   13186              :          Corrigenda 1 TO 4 for fortran 2008 (f08/0011).  */
   13187          705 :       else if (gfc_notification_std (GFC_STD_F2018_DEL)
   13188          705 :           && (expr2->expr_type == EXPR_STRUCTURE
   13189          662 :               || expr2->expr_type == EXPR_ARRAY))
   13190          357 :         expr2->must_finalize = 0;
   13191              :     }
   13192              : 
   13193              : 
   13194              :   /* Checking whether a class assignment is desired is quite complicated and
   13195              :      needed at two locations, so do it once only before the information is
   13196              :      needed.  */
   13197       305764 :   lhs_attr = gfc_expr_attr (expr1);
   13198       305764 :   rhs_attr = gfc_expr_attr (expr2);
   13199       305764 :   dummy_class_array_copy
   13200       611528 :     = (expr2->expr_type == EXPR_VARIABLE
   13201        31431 :        && expr2->rank > 0
   13202         8234 :        && expr2->symtree != NULL
   13203         8234 :        && expr2->symtree->n.sym->attr.dummy
   13204         1429 :        && expr2->ts.type == BT_CLASS
   13205          121 :        && !rhs_attr.pointer
   13206          121 :        && !rhs_attr.allocatable
   13207          108 :        && !CLASS_DATA (expr2)->attr.class_pointer
   13208       305872 :        && !CLASS_DATA (expr2)->attr.allocatable);
   13209              : 
   13210       305764 :   is_poly_assign
   13211       305764 :     = (use_vptr_copy
   13212       289184 :        || ((lhs_attr.pointer || lhs_attr.allocatable) && !lhs_attr.dimension))
   13213        22411 :       && (expr1->ts.type == BT_CLASS || gfc_is_class_array_ref (expr1, NULL)
   13214        20355 :           || gfc_is_class_scalar_expr (expr1)
   13215        19056 :           || gfc_is_class_array_ref (expr2, NULL)
   13216        19056 :           || gfc_is_class_scalar_expr (expr2))
   13217       309137 :       && lhs_attr.flavor != FL_PROCEDURE;
   13218              : 
   13219       305764 :   assoc_assign = is_assoc_assign (expr1, expr2);
   13220              : 
   13221              :   /* Only analyze the expressions for coarray properties, when in coarray-lib
   13222              :      mode.  Avoid false-positive uninitialized diagnostics with initializing
   13223              :      the codimension flag unconditionally.  */
   13224       305764 :   lhs_caf_attr.codimension = false;
   13225       305764 :   rhs_caf_attr.codimension = false;
   13226       305764 :   if (flag_coarray == GFC_FCOARRAY_LIB)
   13227              :     {
   13228         6660 :       lhs_caf_attr = gfc_caf_attr (expr1, false, &lhs_refs_comp);
   13229         6660 :       rhs_caf_attr = gfc_caf_attr (expr2, false, &rhs_refs_comp);
   13230              :     }
   13231              : 
   13232       305764 :   tree reallocation = NULL_TREE;
   13233       305764 :   if (lss != gfc_ss_terminator)
   13234              :     {
   13235              :       /* The assignment needs scalarization.  */
   13236              :       lss_section = lss;
   13237              : 
   13238              :       /* Find a non-scalar SS from the lhs.  */
   13239              :       while (lss_section != gfc_ss_terminator
   13240        39242 :              && lss_section->info->type != GFC_SS_SECTION)
   13241            0 :         lss_section = lss_section->next;
   13242              : 
   13243        39242 :       gcc_assert (lss_section != gfc_ss_terminator);
   13244              : 
   13245              :       /* Initialize the scalarizer.  */
   13246        39242 :       gfc_init_loopinfo (&loop);
   13247              : 
   13248              :       /* Walk the rhs.  */
   13249        39242 :       rss = gfc_walk_expr (expr2);
   13250        39242 :       if (rss == gfc_ss_terminator)
   13251              :         {
   13252              :           /* The rhs is scalar.  Add a ss for the expression.  */
   13253        14742 :           rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
   13254        14742 :           lss->is_alloc_lhs = 0;
   13255              :         }
   13256              : 
   13257              :       /* When doing a class assign, then the handle to the rhs needs to be a
   13258              :          pointer to allow for polymorphism.  */
   13259        39242 :       if (is_poly_assign && expr2->rank == 0 && !UNLIMITED_POLY (expr2))
   13260          491 :         rss->info->type = GFC_SS_REFERENCE;
   13261              : 
   13262        39242 :       rss->no_bounds_check = expr2->no_bounds_check;
   13263              :       /* Associate the SS with the loop.  */
   13264        39242 :       gfc_add_ss_to_loop (&loop, lss);
   13265        39242 :       gfc_add_ss_to_loop (&loop, rss);
   13266              : 
   13267              :       /* Calculate the bounds of the scalarization.  */
   13268        39242 :       gfc_conv_ss_startstride (&loop);
   13269              :       /* Enable loop reversal.  */
   13270       667114 :       for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
   13271       588630 :         loop.reverse[n] = GFC_ENABLE_REVERSE;
   13272              :       /* Resolve any data dependencies in the statement.  */
   13273        39242 :       if (may_alias)
   13274        36978 :         gfc_conv_resolve_dependencies (&loop, lss, rss);
   13275              :       /* Setup the scalarizing loops.  */
   13276        39242 :       gfc_conv_loop_setup (&loop, &expr2->where);
   13277              : 
   13278              :       /* Setup the gfc_se structures.  */
   13279        39242 :       gfc_copy_loopinfo_to_se (&lse, &loop);
   13280        39242 :       gfc_copy_loopinfo_to_se (&rse, &loop);
   13281              : 
   13282        39242 :       rse.ss = rss;
   13283        39242 :       gfc_mark_ss_chain_used (rss, 1);
   13284        39242 :       if (loop.temp_ss == NULL)
   13285              :         {
   13286        38166 :           lse.ss = lss;
   13287        38166 :           gfc_mark_ss_chain_used (lss, 1);
   13288              :         }
   13289              :       else
   13290              :         {
   13291         1076 :           lse.ss = loop.temp_ss;
   13292         1076 :           gfc_mark_ss_chain_used (lss, 3);
   13293         1076 :           gfc_mark_ss_chain_used (loop.temp_ss, 3);
   13294              :         }
   13295              : 
   13296              :       /* Allow the scalarizer to workshare array assignments.  */
   13297        39242 :       if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
   13298              :           == OMPWS_WORKSHARE_FLAG
   13299           85 :           && loop.temp_ss == NULL)
   13300              :         {
   13301           73 :           maybe_workshare = true;
   13302           73 :           ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
   13303              :         }
   13304              : 
   13305              :       /* F2003: Allocate or reallocate lhs of allocatable array.  */
   13306        39242 :       if (realloc_flag)
   13307              :         {
   13308         6259 :           realloc_lhs_warning (expr1->ts.type, true, &expr1->where);
   13309         6259 :           ompws_flags &= ~OMPWS_SCALARIZER_WS;
   13310         6259 :           reallocation = gfc_alloc_allocatable_for_assignment (&loop, expr1,
   13311              :                                                                expr2);
   13312              :         }
   13313              : 
   13314              :       /* Start the scalarized loop body.  */
   13315        39242 :       gfc_start_scalarized_body (&loop, &body);
   13316              :     }
   13317              :   else
   13318       266522 :     gfc_init_block (&body);
   13319              : 
   13320       305764 :   l_is_temp = (lss != gfc_ss_terminator && loop.temp_ss != NULL);
   13321              : 
   13322              :   /* Translate the expression.  */
   13323       611528 :   rse.want_coarray = flag_coarray == GFC_FCOARRAY_LIB
   13324       305764 :                      && (init_flag || assoc_assign) && lhs_caf_attr.codimension;
   13325       305764 :   rse.want_pointer = rse.want_coarray && !init_flag && !lhs_caf_attr.dimension;
   13326       305764 :   gfc_conv_expr (&rse, expr2);
   13327              : 
   13328              :   /* Deal with the case of a scalar class function assigned to a derived type.
   13329              :    */
   13330       305764 :   if (gfc_is_alloc_class_scalar_function (expr2)
   13331       305764 :       && expr1->ts.type == BT_DERIVED)
   13332              :     {
   13333           60 :       rse.expr = gfc_class_data_get (rse.expr);
   13334           60 :       rse.expr = build_fold_indirect_ref_loc (input_location, rse.expr);
   13335              :     }
   13336              : 
   13337              :   /* Stabilize a string length for temporaries.  */
   13338       305764 :   if (expr2->ts.type == BT_CHARACTER && !expr1->ts.deferred
   13339        24354 :       && !(VAR_P (rse.string_length)
   13340              :            || TREE_CODE (rse.string_length) == PARM_DECL
   13341              :            || INDIRECT_REF_P (rse.string_length)))
   13342        23490 :     string_length = gfc_evaluate_now (rse.string_length, &rse.pre);
   13343       282274 :   else if (expr2->ts.type == BT_CHARACTER)
   13344              :     {
   13345         4348 :       if (expr1->ts.deferred
   13346         6741 :           && gfc_expr_attr (expr1).allocatable
   13347         6861 :           && gfc_check_dependency (expr1, expr2, true))
   13348          120 :         rse.string_length =
   13349          120 :           gfc_evaluate_now_function_scope (rse.string_length, &rse.pre);
   13350         4348 :       string_length = rse.string_length;
   13351              :     }
   13352              :   else
   13353              :     string_length = NULL_TREE;
   13354              : 
   13355       305764 :   if (l_is_temp)
   13356              :     {
   13357         1076 :       gfc_conv_tmp_array_ref (&lse);
   13358         1076 :       if (expr2->ts.type == BT_CHARACTER)
   13359          123 :         lse.string_length = string_length;
   13360              :     }
   13361              :   else
   13362              :     {
   13363       304688 :       gfc_conv_expr (&lse, expr1);
   13364              :       /* For some expression (e.g. complex numbers) fold_convert uses a
   13365              :          SAVE_EXPR, which is hazardous on the lhs, because the value is
   13366              :          not updated when assigned to.  */
   13367       304688 :       if (TREE_CODE (lse.expr) == SAVE_EXPR)
   13368            8 :         lse.expr = TREE_OPERAND (lse.expr, 0);
   13369              : 
   13370         6153 :       if (gfc_option.rtcheck & GFC_RTCHECK_MEM && !init_flag
   13371       310841 :           && gfc_expr_attr (expr1).allocatable && expr1->rank && !expr2->rank)
   13372              :         {
   13373           36 :           tree cond;
   13374           36 :           const char* msg;
   13375              : 
   13376           36 :           tmp = INDIRECT_REF_P (lse.expr)
   13377           36 :               ? gfc_build_addr_expr (NULL_TREE, lse.expr) : lse.expr;
   13378           36 :           STRIP_NOPS (tmp);
   13379              : 
   13380              :           /* We should only get array references here.  */
   13381           36 :           gcc_assert (TREE_CODE (tmp) == POINTER_PLUS_EXPR
   13382              :                       || TREE_CODE (tmp) == ARRAY_REF);
   13383              : 
   13384              :           /* 'tmp' is either the pointer to the array(POINTER_PLUS_EXPR)
   13385              :              or the array itself(ARRAY_REF).  */
   13386           36 :           tmp = TREE_OPERAND (tmp, 0);
   13387              : 
   13388              :           /* Provide the address of the array.  */
   13389           36 :           if (TREE_CODE (lse.expr) == ARRAY_REF)
   13390           18 :             tmp = gfc_build_addr_expr (NULL_TREE, tmp);
   13391              : 
   13392           36 :           cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
   13393           36 :                                   tmp, build_int_cst (TREE_TYPE (tmp), 0));
   13394           36 :           msg = _("Assignment of scalar to unallocated array");
   13395           36 :           gfc_trans_runtime_check (true, false, cond, &loop.pre,
   13396              :                                    &expr1->where, msg);
   13397              :         }
   13398              : 
   13399              :       /* Deallocate the lhs parameterized components if required.  */
   13400       304688 :       if (dealloc
   13401       286578 :           && !expr1->symtree->n.sym->attr.associate_var
   13402       284691 :           && expr2->expr_type != EXPR_ARRAY
   13403       278853 :           && (IS_PDT (expr1) || IS_CLASS_PDT (expr1)))
   13404              :         {
   13405          295 :           bool pdt_dep = gfc_check_dependency (expr1, expr2, true);
   13406              : 
   13407          295 :           tmp = lse.expr;
   13408          295 :           if (pdt_dep)
   13409              :             {
   13410              :               /* Create a temporary for deallocation after assignment.  */
   13411          126 :               tmp = gfc_create_var (TREE_TYPE (lse.expr), "pdt_tmp");
   13412          126 :               gfc_add_modify (&lse.pre, tmp, lse.expr);
   13413              :             }
   13414              : 
   13415          295 :           if (expr1->ts.type == BT_DERIVED)
   13416          295 :             tmp = gfc_deallocate_pdt_comp (expr1->ts.u.derived, tmp,
   13417              :                                            expr1->rank);
   13418            0 :           else if (expr1->ts.type == BT_CLASS)
   13419              :             {
   13420            0 :               tmp = gfc_class_data_get (tmp);
   13421            0 :               tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr1)->ts.u.derived,
   13422              :                                              tmp, expr1->rank);
   13423              :             }
   13424              : 
   13425          295 :           if (tmp && pdt_dep)
   13426           68 :             gfc_add_expr_to_block (&rse.post, tmp);
   13427          227 :           else if (tmp)
   13428           43 :             gfc_add_expr_to_block (&lse.pre, tmp);
   13429              :         }
   13430              :     }
   13431              : 
   13432              :   /* Assignments of scalar derived types with allocatable components
   13433              :      to arrays must be done with a deep copy and the rhs temporary
   13434              :      must have its components deallocated afterwards.  */
   13435       611528 :   scalar_to_array = (expr2->ts.type == BT_DERIVED
   13436        18940 :                        && expr2->ts.u.derived->attr.alloc_comp
   13437         6437 :                        && !gfc_expr_is_variable (expr2)
   13438       309293 :                        && expr1->rank && !expr2->rank);
   13439       611528 :   scalar_to_array |= (expr1->ts.type == BT_DERIVED
   13440        19223 :                                     && expr1->rank
   13441         3663 :                                     && expr1->ts.u.derived->attr.alloc_comp
   13442       307083 :                                     && gfc_is_alloc_class_scalar_function (expr2));
   13443       305764 :   if (scalar_to_array && dealloc)
   13444              :     {
   13445           53 :       tmp = gfc_deallocate_alloc_comp_no_caf (expr2->ts.u.derived, rse.expr, 0);
   13446           53 :       gfc_prepend_expr_to_block (&loop.post, tmp);
   13447              :     }
   13448              : 
   13449              :   /* When assigning a character function result to a deferred-length variable,
   13450              :      the function call must happen before the (re)allocation of the lhs -
   13451              :      otherwise the character length of the result is not known.
   13452              :      NOTE 1: This relies on having the exact dependence of the length type
   13453              :      parameter available to the caller; gfortran saves it in the .mod files.
   13454              :      NOTE 2: Vector array references generate an index temporary that must
   13455              :      not go outside the loop. Otherwise, variables should not generate
   13456              :      a pre block.
   13457              :      NOTE 3: The concatenation operation generates a temporary pointer,
   13458              :      whose allocation must go to the innermost loop.
   13459              :      NOTE 4: Elemental functions may generate a temporary, too.  */
   13460       305764 :   if (flag_realloc_lhs
   13461       299740 :       && expr2->ts.type == BT_CHARACTER && expr1->ts.deferred
   13462         2956 :       && !(lss != gfc_ss_terminator
   13463          928 :            && rss != gfc_ss_terminator
   13464          928 :            && ((expr2->expr_type == EXPR_VARIABLE && expr2->rank)
   13465          741 :                || (expr2->expr_type == EXPR_FUNCTION
   13466          160 :                    && expr2->value.function.esym != NULL
   13467           26 :                    && expr2->value.function.esym->attr.elemental)
   13468          728 :                || (expr2->expr_type == EXPR_FUNCTION
   13469          147 :                    && expr2->value.function.isym != NULL
   13470          134 :                    && expr2->value.function.isym->elemental)
   13471          672 :                || (expr2->expr_type == EXPR_OP
   13472           31 :                    && expr2->value.op.op == INTRINSIC_CONCAT))))
   13473         2675 :     gfc_add_block_to_block (&block, &rse.pre);
   13474              : 
   13475              :   /* Nullify the allocatable components corresponding to those of the lhs
   13476              :      derived type, so that the finalization of the function result does not
   13477              :      affect the lhs of the assignment. Prepend is used to ensure that the
   13478              :      nullification occurs before the call to the finalizer. In the case of
   13479              :      a scalar to array assignment, this is done in gfc_trans_scalar_assign
   13480              :      as part of the deep copy.  */
   13481       304973 :   if (!scalar_to_array && expr1->ts.type == BT_DERIVED
   13482       324196 :                        && (gfc_is_class_array_function (expr2)
   13483        18408 :                            || gfc_is_alloc_class_scalar_function (expr2)))
   13484              :     {
   13485           78 :       tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, rse.expr, 0);
   13486           78 :       gfc_prepend_expr_to_block (&rse.post, tmp);
   13487           78 :       if (lss != gfc_ss_terminator && rss == gfc_ss_terminator)
   13488            0 :         gfc_add_block_to_block (&loop.post, &rse.post);
   13489              :     }
   13490              : 
   13491       305764 :   tmp = NULL_TREE;
   13492              : 
   13493       305764 :   if (is_poly_assign)
   13494              :     {
   13495         3306 :       tmp = trans_class_assignment (&body, expr1, expr2, &lse, &rse,
   13496         3306 :                                     use_vptr_copy || (lhs_attr.allocatable
   13497          301 :                                                       && !lhs_attr.dimension),
   13498         3050 :                                     !realloc_flag && flag_realloc_lhs
   13499         3874 :                                     && !lhs_attr.pointer);
   13500         3306 :       if (expr2->expr_type == EXPR_FUNCTION
   13501          231 :           && expr2->ts.type == BT_DERIVED
   13502           30 :           && expr2->ts.u.derived->attr.alloc_comp)
   13503              :         {
   13504           18 :           tree tmp2 = gfc_deallocate_alloc_comp (expr2->ts.u.derived,
   13505              :                                                  rse.expr, expr2->rank);
   13506           18 :           if (lss == gfc_ss_terminator)
   13507           18 :             gfc_add_expr_to_block (&rse.post, tmp2);
   13508              :           else
   13509            0 :             gfc_add_expr_to_block (&loop.post, tmp2);
   13510              :         }
   13511              : 
   13512         3306 :       expr1->must_finalize = 0;
   13513              :     }
   13514       302458 :   else if (!is_poly_assign
   13515       302458 :            && expr1->ts.type == BT_CLASS
   13516          430 :            && expr2->ts.type == BT_CLASS
   13517          249 :            && (expr2->must_finalize || dummy_class_array_copy))
   13518              :     {
   13519              :       /* This case comes about when the scalarizer provides array element
   13520              :          references to class temporaries or nonpointer dummy arrays. Use the
   13521              :          vptr copy function, since this does a deep copy of allocatable
   13522              :          components.  */
   13523          126 :       tmp = gfc_get_vptr_from_expr (rse.expr);
   13524          126 :       if (tmp == NULL_TREE && dummy_class_array_copy)
   13525            6 :         tmp = gfc_get_vptr_from_expr (gfc_get_class_from_gfc_expr (expr2));
   13526          126 :       if (tmp != NULL_TREE)
   13527              :         {
   13528          126 :           tree fcn = gfc_vptr_copy_get (tmp);
   13529          126 :           if (POINTER_TYPE_P (TREE_TYPE (fcn)))
   13530          126 :             fcn = build_fold_indirect_ref_loc (input_location, fcn);
   13531          126 :           tmp = build_call_expr_loc (input_location,
   13532              :                                      fcn, 2,
   13533              :                                      gfc_build_addr_expr (NULL, rse.expr),
   13534              :                                      gfc_build_addr_expr (NULL, lse.expr));
   13535              :         }
   13536              :     }
   13537              : 
   13538              :   /* Comply with F2018 (7.5.6.3). Make sure that any finalization code is added
   13539              :      after evaluation of the rhs and before reallocation.
   13540              :      Skip finalization for self-assignment to avoid use-after-free.
   13541              :      Strip parentheses from both sides to handle cases like a = (a).  */
   13542       305764 :   final_expr = gfc_assignment_finalizer_call (&lse, expr1, init_flag);
   13543       305764 :   if (final_expr
   13544          606 :       && gfc_dep_compare_expr (strip_parentheses (expr1),
   13545              :                                strip_parentheses (expr2)) != 0
   13546       306346 :       && !(strip_parentheses (expr2)->expr_type == EXPR_VARIABLE
   13547          187 :            && strip_parentheses (expr2)->symtree->n.sym->attr.artificial))
   13548              :     {
   13549          582 :       if (lss == gfc_ss_terminator)
   13550              :         {
   13551          165 :           gfc_add_block_to_block (&block, &rse.pre);
   13552          165 :           gfc_add_block_to_block (&block, &lse.finalblock);
   13553              :         }
   13554              :       else
   13555              :         {
   13556          417 :           gfc_add_block_to_block (&body, &rse.pre);
   13557          417 :           gfc_add_block_to_block (&loop.code[expr1->rank - 1],
   13558              :                                   &lse.finalblock);
   13559              :         }
   13560              :     }
   13561              :   else
   13562       305182 :     gfc_add_block_to_block (&body, &rse.pre);
   13563              : 
   13564       305764 :   if (flag_coarray != GFC_FCOARRAY_NONE && expr1->ts.type == BT_CHARACTER
   13565         2994 :       && assoc_assign)
   13566            0 :     tmp = gfc_trans_pointer_assignment (expr1, expr2);
   13567              : 
   13568              :   /* If nothing else works, do it the old fashioned way!  */
   13569       305764 :   if (tmp == NULL_TREE)
   13570              :     {
   13571              :       /* Strip parentheses to detect cases like a = (a) which need deep_copy.  */
   13572       302332 :       gfc_expr *expr2_stripped = strip_parentheses (expr2);
   13573       302332 :       tmp
   13574       302332 :         = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
   13575       302332 :                                    gfc_expr_is_variable (expr2_stripped)
   13576       272660 :                                      || scalar_to_array
   13577       574285 :                                      || expr2->expr_type == EXPR_ARRAY,
   13578       302332 :                                    !(l_is_temp || init_flag) && dealloc,
   13579       302332 :                                    expr1->symtree->n.sym->attr.codimension,
   13580              :                                    assoc_assign);
   13581              :     }
   13582              : 
   13583              :   /* Add the lse pre block to the body  */
   13584       305764 :   gfc_add_block_to_block (&body, &lse.pre);
   13585       305764 :   gfc_add_expr_to_block (&body, tmp);
   13586              : 
   13587              :   /* Add the post blocks to the body.  Scalar finalization must appear before
   13588              :      the post block in case any dellocations are done.  */
   13589       305764 :   if (rse.finalblock.head
   13590       305764 :       && (!l_is_temp || (expr2->expr_type == EXPR_FUNCTION
   13591           14 :                          && gfc_expr_attr (expr2).elemental)))
   13592              :     {
   13593          136 :       gfc_add_block_to_block (&body, &rse.finalblock);
   13594          136 :       gfc_add_block_to_block (&body, &rse.post);
   13595              :     }
   13596              :   else
   13597       305628 :     gfc_add_block_to_block (&body, &rse.post);
   13598              : 
   13599       305764 :   gfc_add_block_to_block (&body, &lse.post);
   13600              : 
   13601       305764 :   if (lss == gfc_ss_terminator)
   13602              :     {
   13603              :       /* F2003: Add the code for reallocation on assignment.  */
   13604       263800 :       if (flag_realloc_lhs && is_scalar_reallocatable_lhs (expr1)
   13605       270112 :           && !is_poly_assign)
   13606         3572 :         alloc_scalar_allocatable_for_assignment (&block, string_length,
   13607              :                                                  expr1, expr2);
   13608              : 
   13609              :       /* Use the scalar assignment as is.  */
   13610       266522 :       gfc_add_block_to_block (&block, &body);
   13611              :     }
   13612              :   else
   13613              :     {
   13614        39242 :       gcc_assert (lse.ss == gfc_ss_terminator
   13615              :                   && rse.ss == gfc_ss_terminator);
   13616              : 
   13617        39242 :       if (l_is_temp)
   13618              :         {
   13619         1076 :           gfc_trans_scalarized_loop_boundary (&loop, &body);
   13620              : 
   13621              :           /* We need to copy the temporary to the actual lhs.  */
   13622         1076 :           gfc_init_se (&lse, NULL);
   13623         1076 :           gfc_init_se (&rse, NULL);
   13624         1076 :           gfc_copy_loopinfo_to_se (&lse, &loop);
   13625         1076 :           gfc_copy_loopinfo_to_se (&rse, &loop);
   13626              : 
   13627         1076 :           rse.ss = loop.temp_ss;
   13628         1076 :           lse.ss = lss;
   13629              : 
   13630         1076 :           gfc_conv_tmp_array_ref (&rse);
   13631         1076 :           gfc_conv_expr (&lse, expr1);
   13632              : 
   13633         1076 :           gcc_assert (lse.ss == gfc_ss_terminator
   13634              :                       && rse.ss == gfc_ss_terminator);
   13635              : 
   13636         1076 :           if (expr2->ts.type == BT_CHARACTER)
   13637          123 :             rse.string_length = string_length;
   13638              : 
   13639         1076 :           tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
   13640              :                                          false, dealloc);
   13641         1076 :           gfc_add_expr_to_block (&body, tmp);
   13642              :         }
   13643              : 
   13644        39242 :       if (reallocation != NULL_TREE)
   13645         6259 :         gfc_add_expr_to_block (&loop.code[loop.dimen - 1], reallocation);
   13646              : 
   13647        39242 :       if (maybe_workshare)
   13648           73 :         ompws_flags &= ~OMPWS_SCALARIZER_BODY;
   13649              : 
   13650              :       /* Generate the copying loops.  */
   13651        39242 :       gfc_trans_scalarizing_loops (&loop, &body);
   13652              : 
   13653              :       /* Wrap the whole thing up.  */
   13654        39242 :       gfc_add_block_to_block (&block, &loop.pre);
   13655        39242 :       gfc_add_block_to_block (&block, &loop.post);
   13656              : 
   13657        39242 :       gfc_cleanup_loop (&loop);
   13658              :     }
   13659              : 
   13660              :   /* Since parameterized components cannot have default initializers,
   13661              :      the default PDT constructor leaves them unallocated. Do the
   13662              :      allocation now.  */
   13663       305764 :   if (init_flag && IS_PDT (expr1)
   13664          329 :       && !expr1->symtree->n.sym->attr.allocatable
   13665          329 :       && !expr1->symtree->n.sym->attr.dummy)
   13666              :     {
   13667           67 :       gfc_symbol *sym = expr1->symtree->n.sym;
   13668           67 :       tmp = gfc_allocate_pdt_comp (sym->ts.u.derived,
   13669              :                                    sym->backend_decl,
   13670           67 :                                    sym->as ? sym->as->rank : 0,
   13671           67 :                                              sym->param_list);
   13672           67 :       gfc_add_expr_to_block (&block, tmp);
   13673              :     }
   13674              : 
   13675       305764 :   return gfc_finish_block (&block);
   13676              : }
   13677              : 
   13678              : 
   13679              : /* Check whether EXPR is a copyable array.  */
   13680              : 
   13681              : static bool
   13682       968718 : copyable_array_p (gfc_expr * expr)
   13683              : {
   13684       968718 :   if (expr->expr_type != EXPR_VARIABLE)
   13685              :     return false;
   13686              : 
   13687              :   /* First check it's an array.  */
   13688       945393 :   if (expr->rank < 1 || !expr->ref || expr->ref->next)
   13689              :     return false;
   13690              : 
   13691       144953 :   if (!gfc_full_array_ref_p (expr->ref, NULL))
   13692              :     return false;
   13693              : 
   13694              :   /* Next check that it's of a simple enough type.  */
   13695       114678 :   switch (expr->ts.type)
   13696              :     {
   13697              :     case BT_INTEGER:
   13698              :     case BT_REAL:
   13699              :     case BT_COMPLEX:
   13700              :     case BT_LOGICAL:
   13701              :       return true;
   13702              : 
   13703              :     case BT_CHARACTER:
   13704              :       return false;
   13705              : 
   13706         6371 :     case_bt_struct:
   13707         6371 :       return (!expr->ts.u.derived->attr.alloc_comp
   13708         6371 :               && !expr->ts.u.derived->attr.pdt_type);
   13709              : 
   13710              :     default:
   13711              :       break;
   13712              :     }
   13713              : 
   13714              :   return false;
   13715              : }
   13716              : 
   13717              : /* Translate an assignment.  */
   13718              : 
   13719              : tree
   13720       323448 : gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
   13721              :                       bool dealloc, bool use_vptr_copy, bool may_alias)
   13722              : {
   13723       323448 :   tree tmp;
   13724              : 
   13725              :   /* Special case a single function returning an array.  */
   13726       323448 :   if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
   13727              :     {
   13728        14427 :       tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
   13729        14427 :       if (tmp)
   13730              :         return tmp;
   13731              :     }
   13732              : 
   13733              :   /* Special case assigning an array to zero.  */
   13734       316612 :   if (copyable_array_p (expr1)
   13735       316612 :       && is_zero_initializer_p (expr2))
   13736              :     {
   13737         3929 :       tmp = gfc_trans_zero_assign (expr1);
   13738         3929 :       if (tmp)
   13739              :         return tmp;
   13740              :     }
   13741              : 
   13742              :   /* Special case copying one array to another.  */
   13743       312962 :   if (copyable_array_p (expr1)
   13744        27668 :       && copyable_array_p (expr2)
   13745         2687 :       && gfc_compare_types (&expr1->ts, &expr2->ts)
   13746       315649 :       && !gfc_check_dependency (expr1, expr2, 0))
   13747              :     {
   13748         2591 :       tmp = gfc_trans_array_copy (expr1, expr2);
   13749         2591 :       if (tmp)
   13750              :         return tmp;
   13751              :     }
   13752              : 
   13753              :   /* Special case initializing an array from a constant array constructor.  */
   13754       311476 :   if (copyable_array_p (expr1)
   13755        26182 :       && expr2->expr_type == EXPR_ARRAY
   13756       319441 :       && gfc_compare_types (&expr1->ts, &expr2->ts))
   13757              :     {
   13758         7965 :       tmp = gfc_trans_array_constructor_copy (expr1, expr2);
   13759         7965 :       if (tmp)
   13760              :         return tmp;
   13761              :     }
   13762              : 
   13763       305764 :   if (UNLIMITED_POLY (expr1) && expr1->rank)
   13764       305764 :     use_vptr_copy = true;
   13765              : 
   13766              :   /* Fallback to the scalarizer to generate explicit loops.  */
   13767       305764 :   return gfc_trans_assignment_1 (expr1, expr2, init_flag, dealloc,
   13768       305764 :                                  use_vptr_copy, may_alias);
   13769              : }
   13770              : 
   13771              : tree
   13772        12774 : gfc_trans_init_assign (gfc_code * code)
   13773              : {
   13774        12774 :   return gfc_trans_assignment (code->expr1, code->expr2, true, false, true);
   13775              : }
   13776              : 
   13777              : tree
   13778       302409 : gfc_trans_assign (gfc_code * code)
   13779              : {
   13780       302409 :   return gfc_trans_assignment (code->expr1, code->expr2, false, true);
   13781              : }
   13782              : 
   13783              : /* Generate a simple loop for internal use of the form
   13784              :    for (var = begin; var <cond> end; var += step)
   13785              :       body;  */
   13786              : void
   13787        12147 : gfc_simple_for_loop (stmtblock_t *block, tree var, tree begin, tree end,
   13788              :                      enum tree_code cond, tree step, tree body)
   13789              : {
   13790        12147 :   tree tmp;
   13791              : 
   13792              :   /* var = begin. */
   13793        12147 :   gfc_add_modify (block, var, begin);
   13794              : 
   13795              :   /* Loop: for (var = begin; var <cond> end; var += step).  */
   13796        12147 :   tree label_loop = gfc_build_label_decl (NULL_TREE);
   13797        12147 :   tree label_cond = gfc_build_label_decl (NULL_TREE);
   13798        12147 :   TREE_USED (label_loop) = 1;
   13799        12147 :   TREE_USED (label_cond) = 1;
   13800              : 
   13801        12147 :   gfc_add_expr_to_block (block, build1_v (GOTO_EXPR, label_cond));
   13802        12147 :   gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_loop));
   13803              : 
   13804              :   /* Loop body.  */
   13805        12147 :   gfc_add_expr_to_block (block, body);
   13806              : 
   13807              :   /* End of loop body.  */
   13808        12147 :   tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var, step);
   13809        12147 :   gfc_add_modify (block, var, tmp);
   13810        12147 :   gfc_add_expr_to_block (block, build1_v (LABEL_EXPR, label_cond));
   13811        12147 :   tmp = fold_build2_loc (input_location, cond, boolean_type_node, var, end);
   13812        12147 :   tmp = build3_v (COND_EXPR, tmp, build1_v (GOTO_EXPR, label_loop),
   13813              :                   build_empty_stmt (input_location));
   13814        12147 :   gfc_add_expr_to_block (block, tmp);
   13815        12147 : }
        

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.