LCOV - code coverage report
Current view: top level - gcc/fortran - trans.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.3 % 1391 1326
Test Date: 2026-10-03 16:17:38 Functions: 98.2 % 56 55
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Code translation -- generate GCC trees from gfc_code.
       2              :    Copyright (C) 2002-2026 Free Software Foundation, Inc.
       3              :    Contributed by Paul Brook
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "options.h"
      25              : #include "tree.h"
      26              : #include "gfortran.h"
      27              : #include "gimple-expr.h"      /* For create_tmp_var_raw.  */
      28              : #include "trans.h"
      29              : #include "stringpool.h"
      30              : #include "fold-const.h"
      31              : #include "tree-iterator.h"
      32              : #include "trans-stmt.h"
      33              : #include "trans-array.h"
      34              : #include "trans-types.h"
      35              : #include "trans-const.h"
      36              : #include "trans-descriptor.h"
      37              : 
      38              : /* Naming convention for backend interface code:
      39              : 
      40              :    gfc_trans_*  translate gfc_code into STMT trees.
      41              : 
      42              :    gfc_conv_*   expression conversion
      43              : 
      44              :    gfc_get_*    get a backend tree representation of a decl or type  */
      45              : 
      46              : const char gfc_msg_fault[] = N_("Array reference out of bounds");
      47              : 
      48              : /* Nonzero if we're translating a defined assignment call. */
      49              : int is_assign_call = 0;
      50              : 
      51              : /* Advance along TREE_CHAIN n times.  */
      52              : 
      53              : tree
      54      6249047 : gfc_advance_chain (tree t, int n)
      55              : {
      56     18059076 :   for (; n > 0; n--)
      57              :     {
      58     11810029 :       gcc_assert (t != NULL_TREE);
      59     11810029 :       t = DECL_CHAIN (t);
      60              :     }
      61      6249047 :   return t;
      62              : }
      63              : 
      64              : void
      65       102446 : gfc_locus_from_location (locus *where, location_t loc)
      66              : {
      67       102446 :   where->nextc = (gfc_char_t *) -1;
      68       102446 :   where->u.location = loc;
      69       102446 : }
      70              : 
      71              : 
      72              : static int num_var;
      73              : 
      74              : #define MAX_PREFIX_LEN 20
      75              : 
      76              : static tree
      77            0 : create_var_debug_raw (tree type, const char *prefix)
      78              : {
      79              :   /* Space for prefix + "_" + 10-digit-number + \0.  */
      80            0 :   char name_buf[MAX_PREFIX_LEN + 1 + 10 + 1];
      81            0 :   tree t;
      82            0 :   int i;
      83              : 
      84            0 :   if (prefix == NULL)
      85              :     prefix = "gfc";
      86              :   else
      87            0 :     gcc_assert (strlen (prefix) <= MAX_PREFIX_LEN);
      88              : 
      89            0 :   for (i = 0; prefix[i] != 0; i++)
      90            0 :     name_buf[i] = gfc_wide_toupper (prefix[i]);
      91              : 
      92            0 :   snprintf (name_buf + i, sizeof (name_buf) - i, "_%d", num_var++);
      93              : 
      94            0 :   t = build_decl (input_location, VAR_DECL, get_identifier (name_buf), type);
      95              : 
      96              :   /* Not setting this causes some regressions.  */
      97            0 :   DECL_ARTIFICIAL (t) = 1;
      98              : 
      99              :   /* We want debug info for it.  */
     100            0 :   DECL_IGNORED_P (t) = 0;
     101              :   /* It should not be nameless.  */
     102            0 :   DECL_NAMELESS (t) = 0;
     103              : 
     104              :   /* Make the variable writable.  */
     105            0 :   TREE_READONLY (t) = 0;
     106              : 
     107            0 :   DECL_EXTERNAL (t) = 0;
     108            0 :   TREE_STATIC (t) = 0;
     109            0 :   TREE_USED (t) = 1;
     110              : 
     111            0 :   return t;
     112              : }
     113              : 
     114              : /* Creates a variable declaration with a given TYPE.  */
     115              : 
     116              : tree
     117      1694775 : gfc_create_var_np (tree type, const char *prefix)
     118              : {
     119      1694775 :   tree t;
     120              : 
     121      1694775 :   if (flag_debug_aux_vars)
     122            0 :     return create_var_debug_raw (type, prefix);
     123              : 
     124      1694775 :   t = create_tmp_var_raw (type, prefix);
     125              : 
     126              :   /* No warnings for anonymous variables.  */
     127      1694775 :   if (prefix == NULL)
     128      1038880 :     suppress_warning (t);
     129              : 
     130              :   return t;
     131              : }
     132              : 
     133              : 
     134              : /* Like above, but also adds it to the current scope.  */
     135              : 
     136              : tree
     137      1563561 : gfc_create_var (tree type, const char *prefix)
     138              : {
     139      1563561 :   tree tmp;
     140              : 
     141      1563561 :   tmp = gfc_create_var_np (type, prefix);
     142              : 
     143      1563561 :   pushdecl (tmp);
     144              : 
     145      1563561 :   return tmp;
     146              : }
     147              : 
     148              : 
     149              : /* If the expression is not constant, evaluate it now.  We assign the
     150              :    result of the expression to an artificially created variable VAR, and
     151              :    return a pointer to the VAR_DECL node for this variable.  */
     152              : 
     153              : tree
     154      2229714 : gfc_evaluate_now_loc (location_t loc, tree expr, stmtblock_t * pblock)
     155              : {
     156      2229714 :   tree var;
     157              : 
     158      2229714 :   if (CONSTANT_CLASS_P (expr))
     159              :     return expr;
     160              : 
     161       887472 :   var = gfc_create_var (TREE_TYPE (expr), NULL);
     162       887472 :   gfc_add_modify_loc (loc, pblock, var, expr);
     163              : 
     164       887472 :   return var;
     165              : }
     166              : 
     167              : 
     168              : tree
     169      2192051 : gfc_evaluate_now (tree expr, stmtblock_t * pblock)
     170              : {
     171      2192051 :   return gfc_evaluate_now_loc (input_location, expr, pblock);
     172              : }
     173              : 
     174              : 
     175              : /* Returns a fresh pointer variable pointing to the same data as EXPR, adding
     176              :    in BLOCK the initialization code that makes it point to EXPR.  */
     177              : 
     178              : tree
     179          704 : gfc_evaluate_data_ref_now (tree expr, stmtblock_t *block)
     180              : {
     181          704 :   tree t = expr;
     182              : 
     183          704 :   STRIP_NOPS (t);
     184              : 
     185              :   /* If EXPR can be used as lhs of an assignment, we have to take the address
     186              :      of EXPR.  Otherwise, reassigning the pointer would retarget it to some
     187              :      other data without EXPR being retargetted as well.  */
     188          704 :   bool lvalue_p = DECL_P (t) || REFERENCE_CLASS_P (t) || INDIRECT_REF_P (t);
     189              : 
     190          149 :   tree value;
     191          149 :   if (lvalue_p)
     192              :     {
     193          555 :       value = gfc_build_addr_expr (NULL_TREE, expr);
     194          555 :       value = gfc_evaluate_now (value, block);
     195          555 :       return build_fold_indirect_ref_loc (input_location, value);
     196              :     }
     197              :   else
     198          149 :     return gfc_evaluate_now (expr, block);
     199              : }
     200              : 
     201              : 
     202              : /* Like gfc_evaluate_now, but add the created variable to the
     203              :    function scope.  */
     204              : 
     205              : tree
     206          120 : gfc_evaluate_now_function_scope (tree expr, stmtblock_t * pblock)
     207              : {
     208          120 :   tree var;
     209          120 :   var = gfc_create_var_np (TREE_TYPE (expr), NULL);
     210          120 :   gfc_add_decl_to_function (var);
     211          120 :   gfc_add_modify (pblock, var, expr);
     212              : 
     213          120 :   return var;
     214              : }
     215              : 
     216              : /* Build a MODIFY_EXPR node and add it to a given statement block PBLOCK.
     217              :    A MODIFY_EXPR is an assignment:
     218              :    LHS <- RHS.  */
     219              : 
     220              : void
     221      3857144 : gfc_add_modify_loc (location_t loc, stmtblock_t * pblock, tree lhs, tree rhs)
     222              : {
     223      3857144 :   tree tmp;
     224              : 
     225      3857144 :   tree t1, t2;
     226      3857144 :   t1 = TREE_TYPE (rhs);
     227      3857144 :   t2 = TREE_TYPE (lhs);
     228              :   /* Make sure that the types of the rhs and the lhs are compatible
     229              :      for scalar assignments.  We should probably have something
     230              :      similar for aggregates, but right now removing that check just
     231              :      breaks everything.  */
     232      3857144 :   gcc_checking_assert (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
     233              :                        || AGGREGATE_TYPE_P (TREE_TYPE (lhs)));
     234              : 
     235      3857144 :   tmp = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, lhs,
     236              :                          rhs);
     237      3857144 :   gfc_add_expr_to_block (pblock, tmp);
     238      3857144 : }
     239              : 
     240              : 
     241              : void
     242      2761587 : gfc_add_modify (stmtblock_t * pblock, tree lhs, tree rhs)
     243              : {
     244      2761587 :   gfc_add_modify_loc (input_location, pblock, lhs, rhs);
     245      2761587 : }
     246              : 
     247              : tree
     248         1270 : gfc_trans_force_lval (stmtblock_t *pblock, tree e)
     249              : {
     250         1270 :   if (VAR_P (e))
     251              :     return e;
     252              : 
     253         1087 :   tree v = gfc_create_var (TREE_TYPE (e), NULL);
     254         1087 :   gfc_add_modify (pblock, v, e);
     255         1087 :   return v;
     256              : }
     257              : 
     258              : /* Create a new scope/binding level and initialize a block.  Care must be
     259              :    taken when translating expressions as any temporaries will be placed in
     260              :    the innermost scope.  */
     261              : 
     262              : void
     263      2323819 : gfc_start_block (stmtblock_t * block)
     264              : {
     265              :   /* Start a new binding level.  */
     266      2323819 :   pushlevel ();
     267      2323819 :   block->has_scope = 1;
     268              : 
     269              :   /* The block is empty.  */
     270      2323819 :   block->head = NULL_TREE;
     271      2323819 : }
     272              : 
     273              : 
     274              : /* Initialize a block without creating a new scope.  */
     275              : 
     276              : void
     277     17886690 : gfc_init_block (stmtblock_t * block)
     278              : {
     279     17886690 :   block->head = NULL_TREE;
     280     17886690 :   block->has_scope = 0;
     281     17886690 : }
     282              : 
     283              : 
     284              : /* Sometimes we create a scope but it turns out that we don't actually
     285              :    need it.  This function merges the scope of BLOCK with its parent.
     286              :    Only variable decls will be merged, you still need to add the code.  */
     287              : 
     288              : void
     289           85 : gfc_merge_block_scope (stmtblock_t * block)
     290              : {
     291           85 :   tree decl;
     292           85 :   tree next;
     293              : 
     294           85 :   gcc_assert (block->has_scope);
     295           85 :   block->has_scope = 0;
     296              : 
     297              :   /* Remember the decls in this scope.  */
     298           85 :   decl = getdecls ();
     299           85 :   poplevel (0, 0);
     300              : 
     301              :   /* Add them to the parent scope.  */
     302          283 :   while (decl != NULL_TREE)
     303              :     {
     304          113 :       next = DECL_CHAIN (decl);
     305          113 :       DECL_CHAIN (decl) = NULL_TREE;
     306              : 
     307          113 :       pushdecl (decl);
     308          113 :       decl = next;
     309              :     }
     310           85 : }
     311              : 
     312              : 
     313              : /* Finish a scope containing a block of statements.  */
     314              : 
     315              : tree
     316      4117725 : gfc_finish_block (stmtblock_t * stmtblock)
     317              : {
     318      4117725 :   tree decl;
     319      4117725 :   tree expr;
     320      4117725 :   tree block;
     321              : 
     322      4117725 :   expr = stmtblock->head;
     323      4117725 :   if (!expr)
     324       517672 :     expr = build_empty_stmt (input_location);
     325              : 
     326      4117725 :   stmtblock->head = NULL_TREE;
     327              : 
     328      4117725 :   if (stmtblock->has_scope)
     329              :     {
     330      2323727 :       decl = getdecls ();
     331              : 
     332      2323727 :       if (decl)
     333              :         {
     334       587997 :           block = poplevel (1, 0);
     335       587997 :           expr = build3_v (BIND_EXPR, decl, expr, block);
     336              :         }
     337              :       else
     338      1735730 :         poplevel (0, 0);
     339              :     }
     340              : 
     341      4117725 :   return expr;
     342              : }
     343              : 
     344              : 
     345              : /* Build an ADDR_EXPR and cast the result to TYPE.  If TYPE is NULL, the
     346              :    natural type is used.  */
     347              : 
     348              : tree
     349      1620012 : gfc_build_addr_expr (tree type, tree t)
     350              : {
     351      1620012 :   tree base_type = TREE_TYPE (t);
     352      1620012 :   tree natural_type;
     353              : 
     354       697848 :   if (type && POINTER_TYPE_P (type)
     355       697848 :       && TREE_CODE (base_type) == ARRAY_TYPE
     356      2245057 :       && TYPE_MAIN_VARIANT (TREE_TYPE (type))
     357       625045 :          == TYPE_MAIN_VARIANT (TREE_TYPE (base_type)))
     358              :     {
     359       422052 :       tree min_val = size_zero_node;
     360       422052 :       tree type_domain = TYPE_DOMAIN (base_type);
     361       422052 :       if (type_domain && TYPE_MIN_VALUE (type_domain))
     362       422052 :         min_val = TYPE_MIN_VALUE (type_domain);
     363       422052 :       t = fold (build4_loc (input_location, ARRAY_REF, TREE_TYPE (type),
     364              :                             t, min_val, NULL_TREE, NULL_TREE));
     365       422052 :       natural_type = type;
     366              :     }
     367              :   else
     368      1197960 :     natural_type = build_pointer_type (base_type);
     369              : 
     370      1620012 :   if (INDIRECT_REF_P (t))
     371              :     {
     372       170054 :       if (!type)
     373        76905 :         type = natural_type;
     374       170054 :       t = TREE_OPERAND (t, 0);
     375       170054 :       natural_type = TREE_TYPE (t);
     376              :     }
     377              :   else
     378              :     {
     379      1449958 :       tree base = get_base_address (t);
     380      1449958 :       if (base && DECL_P (base))
     381      1008505 :         TREE_ADDRESSABLE (base) = 1;
     382      1449958 :       t = fold_build1_loc (input_location, ADDR_EXPR, natural_type, t);
     383              :     }
     384              : 
     385      1620012 :   if (type && natural_type != type)
     386       211110 :     t = convert (type, t);
     387              : 
     388      1620012 :   return t;
     389              : }
     390              : 
     391              : 
     392              : /* Return the descriptor that carries the span of DECL, which is marked as a
     393              :    pointer array.  Such a decl usually is a descriptor.  The local decl of a
     394              :    descriptorless dummy array is not, so its span comes from the descriptor it
     395              :    was built from, which is the saved one.  */
     396              : 
     397              : tree
     398         9587 : gfc_get_span_descriptor (tree decl)
     399              : {
     400         9587 :   if (DECL_P (decl)
     401         9288 :       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
     402           90 :       && DECL_LANG_SPECIFIC (decl)
     403         9677 :       && GFC_DECL_SAVED_DESCRIPTOR (decl))
     404           90 :     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     405              : 
     406         9587 :   if (POINTER_TYPE_P (TREE_TYPE (decl)))
     407         2379 :     decl = build_fold_indirect_ref_loc (input_location, decl);
     408              : 
     409         9587 :   return decl;
     410              : }
     411              : 
     412              : 
     413              : static tree
     414        22542 : get_array_span (tree type, tree decl)
     415              : {
     416        22542 :   tree span;
     417              : 
     418              :   /* Component references are guaranteed to have a reliable value for
     419              :      'span'. Likewise indirect references since they emerge from the
     420              :      conversion of a CFI descriptor or the hidden dummy descriptor.  */
     421        22542 :   if (TREE_CODE (decl) == COMPONENT_REF
     422        22542 :       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
     423         4147 :     return gfc_conv_descriptor_span_get (decl);
     424        18395 :   else if (INDIRECT_REF_P (decl)
     425        18395 :            && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
     426         2435 :     return gfc_conv_descriptor_span_get (decl);
     427              : 
     428              :   /* Return the span for deferred character length array references.  */
     429        15960 :   if (type
     430        15960 :       && (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
     431        26655 :       && TYPE_STRING_FLAG (type))
     432              :     {
     433         7739 :       if (DECL_P (decl) && GFC_DECL_PTR_ARRAY_P (decl))
     434         1257 :         decl = gfc_get_span_descriptor (decl);
     435         6482 :       else if (TREE_CODE (decl) == PARM_DECL)
     436          134 :         decl = build_fold_indirect_ref_loc (input_location, decl);
     437         7739 :       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
     438         6029 :         span = gfc_conv_descriptor_span_get (decl);
     439              :       else
     440         1710 :         span = gfc_get_character_len_in_bytes (type);
     441        15478 :       span = (span && !integer_zerop (span))
     442        15478 :         ? (fold_convert (gfc_array_index_type, span)) : (NULL_TREE);
     443              :     }
     444              :   /* Likewise for class array or pointer array references.  */
     445         8221 :   else if (TREE_CODE (decl) == FIELD_DECL
     446              :            || VAR_OR_FUNCTION_DECL_P (decl)
     447              :            || TREE_CODE (decl) == PARM_DECL)
     448              :     {
     449         8221 :       if (GFC_DECL_CLASS (decl))
     450              :         {
     451              :           /* When a temporary is in place for the class array, then the
     452              :              original class' declaration is stored in the saved
     453              :              descriptor.  */
     454            0 :           if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
     455            0 :             decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
     456              :           else
     457              :             {
     458              :               /* Allow for dummy arguments and other good things.  */
     459            0 :               if (POINTER_TYPE_P (TREE_TYPE (decl)))
     460            0 :                 decl = build_fold_indirect_ref_loc (input_location, decl);
     461              : 
     462              :               /* Check if '_data' is an array descriptor.  If it is not,
     463              :                  the array must be one of the components of the class
     464              :                  object, so return a null span.  */
     465            0 :               if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (
     466              :                                           gfc_class_data_get (decl))))
     467              :                 return NULL_TREE;
     468              :             }
     469            0 :           span = gfc_class_vtab_size_get (decl);
     470              :           /* For unlimited polymorphic entities then _len component needs
     471              :              to be multiplied with the size.  */
     472            0 :           span = gfc_resize_class_size_with_len (NULL, decl, span);
     473              :         }
     474         8221 :       else if (tree cached = GFC_DECL_GET_SPAN (decl))
     475              :         /* A span addressed dummy loaded its span on entry.  */
     476              :         span = cached;
     477         8065 :       else if (GFC_DECL_PTR_ARRAY_P (decl))
     478         7698 :         span = gfc_conv_descriptor_span_get (gfc_get_span_descriptor (decl));
     479              :       else
     480              :         span = NULL_TREE;
     481              :     }
     482              :   else
     483              :     span = NULL_TREE;
     484              : 
     485              :   return span;
     486              : }
     487              : 
     488              : 
     489              : tree
     490        29696 : gfc_build_spanned_array_ref (tree base, tree offset, tree span)
     491              : {
     492        29696 :   tree type;
     493        29696 :   tree tmp;
     494        29696 :   type = TREE_TYPE (TREE_TYPE (base));
     495        29696 :   offset = fold_build2_loc (input_location, MULT_EXPR,
     496              :                             gfc_array_index_type,
     497              :                             offset, span);
     498        29696 :   tmp = gfc_build_addr_expr (pvoid_type_node, base);
     499        29696 :   tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
     500        29696 :   tmp = fold_convert (build_pointer_type (type), tmp);
     501        29696 :   tmp = build_fold_indirect_ref_loc (input_location, tmp);
     502        29696 :   return tmp;
     503              : }
     504              : 
     505              : 
     506              : /* Build an ARRAY_REF with its natural type.
     507              :    NON_NEGATIVE_OFFSET indicates if it’s true that OFFSET can’t be negative,
     508              :    and thus that an ARRAY_REF can safely be generated.  If it’s false, we
     509              :    have to play it safe and use pointer arithmetic.  */
     510              : 
     511              : tree
     512      1510129 : gfc_build_array_ref (tree base, tree offset, tree decl,
     513              :                      bool non_negative_offset, tree vptr)
     514              : {
     515      1510129 :   tree type = TREE_TYPE (base);
     516      1510129 :   tree span = NULL_TREE;
     517              : 
     518      1510129 :   if (GFC_ARRAY_TYPE_P (type) && GFC_TYPE_ARRAY_RANK (type) == 0)
     519              :     {
     520          203 :       gcc_assert (GFC_TYPE_ARRAY_CORANK (type) > 0);
     521              : 
     522          203 :       return fold_convert (TYPE_MAIN_VARIANT (type), base);
     523              :     }
     524              : 
     525              :   /* Scalar coarray, there is nothing to do.  */
     526      1509926 :   if (TREE_CODE (type) != ARRAY_TYPE)
     527              :     {
     528           19 :       gcc_assert (decl == NULL_TREE);
     529           19 :       gcc_assert (integer_zerop (offset));
     530              :       return base;
     531              :     }
     532              : 
     533      1509907 :   type = TREE_TYPE (type);
     534              : 
     535      1509907 :   if (DECL_P (base))
     536       209667 :     TREE_ADDRESSABLE (base) = 1;
     537              : 
     538              :   /* Strip NON_LVALUE_EXPR nodes.  */
     539      1531000 :   STRIP_TYPE_NOPS (offset);
     540              : 
     541              :   /* If decl or vptr are non-null, pointer arithmetic for the array reference
     542              :      is likely. Generate the 'span' for the array reference.  */
     543      1509907 :   if (vptr)
     544              :     {
     545         3624 :       span = gfc_vptr_size_get (vptr);
     546              : 
     547              :       /* Check if this is an unlimited polymorphic object carrying a character
     548              :          payload. In this case, the 'len' field is non-zero.  */
     549         3624 :       if (decl && GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
     550         3469 :         span = gfc_resize_class_size_with_len (NULL, decl, span);
     551              :     }
     552      1506283 :   else if (decl)
     553        22542 :     span = get_array_span (type, decl);
     554              : 
     555              :   /* If a non-null span has been generated reference the element with
     556              :      pointer arithmetic.  */
     557        26166 :   if (span != NULL_TREE)
     558        25799 :     return gfc_build_spanned_array_ref (base, offset, span);
     559              :   /* Else use a straightforward array reference if possible.  */
     560      1484108 :   else if (non_negative_offset)
     561      1436868 :     return build4_loc (input_location, ARRAY_REF, type, base, offset,
     562      1436868 :                        NULL_TREE, NULL_TREE);
     563              :   /* Otherwise use pointer arithmetic.  */
     564              :   else
     565              :     {
     566        47240 :       gcc_assert (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE);
     567        47240 :       tree min = NULL_TREE;
     568        47240 :       if (TYPE_DOMAIN (TREE_TYPE (base))
     569        47240 :           && !integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (base)))))
     570          314 :         min = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (base)));
     571              : 
     572          314 :       tree zero_based_index
     573          314 :            = min ? fold_build2_loc (input_location, MINUS_EXPR,
     574              :                                     gfc_array_index_type,
     575              :                                     fold_convert (gfc_array_index_type, offset),
     576              :                                     fold_convert (gfc_array_index_type, min))
     577        46926 :                  : fold_convert (gfc_array_index_type, offset);
     578              : 
     579        47240 :       tree elt_size = fold_convert (gfc_array_index_type,
     580              :                                     TYPE_SIZE_UNIT (type));
     581              : 
     582        47240 :       tree offset_bytes = fold_build2_loc (input_location, MULT_EXPR,
     583              :                                            gfc_array_index_type,
     584              :                                            zero_based_index, elt_size);
     585              : 
     586        47240 :       tree base_addr = gfc_build_addr_expr (pvoid_type_node, base);
     587              : 
     588        47240 :       tree ptr = fold_build_pointer_plus_loc (input_location, base_addr,
     589              :                                               offset_bytes);
     590        47240 :       return build1_loc (input_location, INDIRECT_REF, type,
     591        47240 :                          fold_convert (build_pointer_type (type), ptr));
     592              :     }
     593              : }
     594              : 
     595              : 
     596              : /* Generate a call to print a runtime error possibly including multiple
     597              :    arguments and a locus.  */
     598              : 
     599              : static tree
     600        83785 : trans_runtime_error_vararg (tree errorfunc, locus* where, const char* msgid,
     601              :                             va_list ap)
     602              : {
     603        83785 :   stmtblock_t block;
     604        83785 :   tree tmp;
     605        83785 :   tree arg, arg2;
     606        83785 :   tree *argarray;
     607        83785 :   tree fntype;
     608        83785 :   char *message;
     609        83785 :   const char *p;
     610        83785 :   int nargs, i;
     611        83785 :   location_t loc;
     612              : 
     613              :   /* Compute the number of extra arguments from the format string.  */
     614      4435956 :   for (p = msgid, nargs = 0; *p; p++)
     615      4352171 :     if (*p == '%')
     616              :       {
     617       122293 :         p++;
     618       122293 :         if (*p != '%')
     619       121360 :           nargs++;
     620              :       }
     621              : 
     622              :   /* The code to generate the error.  */
     623        83785 :   gfc_start_block (&block);
     624              : 
     625        83785 :   if (where)
     626              :     {
     627        64264 :       location_t loc = gfc_get_location (where);
     628        64264 :       message = xasprintf ("At line %d of file %s",  LOCATION_LINE (loc),
     629       128528 :                            LOCATION_FILE (loc));
     630              :     }
     631              :   else
     632        19521 :     message = xasprintf ("In file '%s', around line %d",
     633        39042 :                          gfc_source_file, LOCATION_LINE (input_location));
     634              : 
     635        83785 :   arg = gfc_build_addr_expr (pchar_type_node,
     636              :                              gfc_build_localized_cstring_const (message));
     637        83785 :   free (message);
     638              : 
     639        83785 :   message = xasprintf ("%s", _(msgid));
     640        83785 :   arg2 = gfc_build_addr_expr (pchar_type_node,
     641              :                               gfc_build_localized_cstring_const (message));
     642        83785 :   free (message);
     643              : 
     644              :   /* Build the argument array.  */
     645        83785 :   argarray = XALLOCAVEC (tree, nargs + 2);
     646        83785 :   argarray[0] = arg;
     647        83785 :   argarray[1] = arg2;
     648       205145 :   for (i = 0; i < nargs; i++)
     649       121360 :     argarray[2 + i] = va_arg (ap, tree);
     650              : 
     651              :   /* Build the function call to runtime_(warning,error)_at; because of the
     652              :      variable number of arguments, we can't use build_call_expr_loc dinput_location,
     653              :      irectly.  */
     654        83785 :   fntype = TREE_TYPE (errorfunc);
     655              : 
     656        83785 :   loc = where ? gfc_get_location (where) : input_location;
     657        83785 :   tmp = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
     658              :                                    fold_build1_loc (loc, ADDR_EXPR,
     659              :                                              build_pointer_type (fntype),
     660              :                                              errorfunc),
     661              :                                    nargs + 2, argarray);
     662        83785 :   gfc_add_expr_to_block (&block, tmp);
     663              : 
     664        83785 :   return gfc_finish_block (&block);
     665              : }
     666              : 
     667              : 
     668              : tree
     669        25293 : gfc_trans_runtime_error (bool error, locus* where, const char* msgid, ...)
     670              : {
     671        25293 :   va_list ap;
     672        25293 :   tree result;
     673              : 
     674        25293 :   va_start (ap, msgid);
     675        25293 :   result = trans_runtime_error_vararg (error
     676              :                                        ? gfor_fndecl_runtime_error_at
     677              :                                        : gfor_fndecl_runtime_warning_at,
     678              :                                        where, msgid, ap);
     679        25293 :   va_end (ap);
     680        25293 :   return result;
     681              : }
     682              : 
     683              : 
     684              : /* Generate a runtime error if COND is true.  */
     685              : 
     686              : void
     687       166801 : gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
     688              :                          locus * where, const char * msgid, ...)
     689              : {
     690       166801 :   va_list ap;
     691       166801 :   stmtblock_t block;
     692       166801 :   tree body;
     693       166801 :   tree tmp;
     694       166801 :   tree tmpvar = NULL;
     695              : 
     696       166801 :   if (integer_zerop (cond))
     697       127770 :     return;
     698              : 
     699        39031 :   if (once)
     700              :     {
     701          954 :        tmpvar = gfc_create_var (boolean_type_node, "print_warning");
     702          954 :        TREE_STATIC (tmpvar) = 1;
     703          954 :        DECL_INITIAL (tmpvar) = boolean_true_node;
     704          954 :        gfc_add_expr_to_block (pblock, tmpvar);
     705              :     }
     706              : 
     707        39031 :   gfc_start_block (&block);
     708              : 
     709              :   /* For error, runtime_error_at already implies PRED_NORETURN.  */
     710        39031 :   if (!error && once)
     711          954 :     gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_WARN_ONCE,
     712              :                                                        NOT_TAKEN));
     713              : 
     714              :   /* The code to generate the error.  */
     715        39031 :   va_start (ap, msgid);
     716        39031 :   gfc_add_expr_to_block (&block,
     717              :                          trans_runtime_error_vararg
     718              :                          (error ? gfor_fndecl_runtime_error_at
     719              :                           : gfor_fndecl_runtime_warning_at,
     720              :                           where, msgid, ap));
     721        39031 :   va_end (ap);
     722              : 
     723        39031 :   if (once)
     724          954 :     gfc_add_modify (&block, tmpvar, boolean_false_node);
     725              : 
     726        39031 :   body = gfc_finish_block (&block);
     727              : 
     728        39031 :   if (integer_onep (cond))
     729              :     {
     730          892 :       gfc_add_expr_to_block (pblock, body);
     731              :     }
     732              :   else
     733              :     {
     734        38139 :       location_t loc = where ? gfc_get_location (where) : input_location;
     735        38139 :       if (once)
     736           86 :         cond = fold_build2_loc (loc, TRUTH_AND_EXPR, boolean_type_node, tmpvar,
     737              :                                 fold_convert (boolean_type_node, cond));
     738              : 
     739        38139 :       tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, body,
     740              :                              build_empty_stmt (loc));
     741        38139 :       gfc_add_expr_to_block (pblock, tmp);
     742              :     }
     743              : }
     744              : 
     745              : 
     746              : static tree
     747        19461 : trans_os_error_at (locus* where, const char* msgid, ...)
     748              : {
     749        19461 :   va_list ap;
     750        19461 :   tree result;
     751              : 
     752        19461 :   va_start (ap, msgid);
     753        19461 :   result = trans_runtime_error_vararg (gfor_fndecl_os_error_at,
     754              :                                        where, msgid, ap);
     755        19461 :   va_end (ap);
     756        19461 :   return result;
     757              : }
     758              : 
     759              : 
     760              : 
     761              : /* Call malloc to allocate size bytes of memory, with special conditions:
     762              :       + if size == 0, return a malloced area of size 1,
     763              :       + if malloc returns NULL, issue a runtime error.  */
     764              : tree
     765        25191 : gfc_call_malloc (stmtblock_t * block, tree type, tree size)
     766              : {
     767        25191 :   tree tmp, malloc_result, null_result, res, malloc_tree;
     768        25191 :   stmtblock_t block2;
     769              : 
     770              :   /* Create a variable to hold the result.  */
     771        25191 :   res = gfc_create_var (prvoid_type_node, NULL);
     772              : 
     773              :   /* Call malloc.  */
     774        25191 :   gfc_start_block (&block2);
     775              : 
     776        25191 :   if (size == NULL_TREE)
     777            1 :     size = build_int_cst (size_type_node, 1);
     778              : 
     779        25191 :   size = fold_convert (size_type_node, size);
     780        25191 :   size = fold_build2_loc (input_location, MAX_EXPR, size_type_node, size,
     781              :                           build_int_cst (size_type_node, 1));
     782              : 
     783        25191 :   malloc_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
     784        25191 :   gfc_add_modify (&block2, res,
     785              :                   fold_convert (prvoid_type_node,
     786              :                                 build_call_expr_loc (input_location,
     787              :                                                      malloc_tree, 1, size)));
     788              : 
     789              :   /* Optionally check whether malloc was successful.  */
     790        25191 :   if (gfc_option.rtcheck & GFC_RTCHECK_MEM)
     791              :     {
     792          107 :       null_result = fold_build2_loc (input_location, EQ_EXPR,
     793              :                                      logical_type_node, res,
     794              :                                      build_int_cst (pvoid_type_node, 0));
     795          107 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
     796              :                              null_result,
     797              :                              trans_os_error_at (NULL,
     798              :                                                 "Error allocating %lu bytes",
     799              :                                                 fold_convert
     800              :                                                 (long_unsigned_type_node,
     801              :                                                  size)),
     802              :                              build_empty_stmt (input_location));
     803          107 :       gfc_add_expr_to_block (&block2, tmp);
     804              :     }
     805              : 
     806        25191 :   malloc_result = gfc_finish_block (&block2);
     807        25191 :   gfc_add_expr_to_block (block, malloc_result);
     808              : 
     809        25191 :   if (type != NULL)
     810        19652 :     res = fold_convert (type, res);
     811        25191 :   return res;
     812              : }
     813              : 
     814              : 
     815              : /* Allocate memory, using an optional status argument.
     816              : 
     817              :    This function follows the following pseudo-code:
     818              : 
     819              :     void *
     820              :     allocate (size_t size, integer_type stat)
     821              :     {
     822              :       void *newmem;
     823              : 
     824              :       if (stat requested)
     825              :         stat = 0;
     826              : 
     827              :       // if cond == NULL_NULL:
     828              :       newmem = malloc (MAX (size, 1));
     829              :       // otherwise:
     830              :       newmem = <cond> ? <alt_alloc> : malloc (MAX (size, 1))
     831              :       if (newmem == NULL)
     832              :       {
     833              :         if (stat)
     834              :           *stat = LIBERROR_NO_MEMORY;
     835              :         else
     836              :           runtime_error ("Allocation would exceed memory limit");
     837              :       }
     838              :       return newmem;
     839              :     }  */
     840              : void
     841        18400 : gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
     842              :                            tree size, tree status, tree cond, tree alt_alloc,
     843              :                            tree extra_success_expr)
     844              : {
     845        18400 :   tree tmp, error_cond;
     846        18400 :   stmtblock_t on_error;
     847        18400 :   tree status_type = status ? TREE_TYPE (status) : NULL_TREE;
     848        18400 :   bool cond_is_true = cond == boolean_true_node;
     849              : 
     850              :   /* If successful and stat= is given, set status to 0.  */
     851        18113 :   if (status != NULL_TREE)
     852          287 :       gfc_add_expr_to_block (block,
     853              :              fold_build2_loc (input_location, MODIFY_EXPR, status_type,
     854              :                               status, build_int_cst (status_type, 0)));
     855              : 
     856              :   /* The allocation itself.  */
     857        18400 :   size = fold_convert (size_type_node, size);
     858        18400 :   tmp = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
     859              :                          size, build_int_cst (size_type_node, 1));
     860              : 
     861        18400 :   if (!cond_is_true)
     862        18339 :     tmp = build_call_expr_loc (input_location,
     863              :                                builtin_decl_explicit (BUILT_IN_MALLOC), 1, tmp);
     864              :   else
     865              :     tmp = alt_alloc;
     866              : 
     867        18400 :   if (!cond_is_true && cond)
     868            0 :     tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
     869              :                       alt_alloc, tmp);
     870              : 
     871        18400 :   gfc_add_modify (block, pointer, fold_convert (TREE_TYPE (pointer), tmp));
     872              : 
     873              :   /* What to do in case of error.  */
     874        18400 :   gfc_start_block (&on_error);
     875        18400 :   if (status != NULL_TREE)
     876              :     {
     877          287 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type, status,
     878              :                              build_int_cst (status_type, LIBERROR_NO_MEMORY));
     879          287 :       gfc_add_expr_to_block (&on_error, tmp);
     880              :     }
     881              :   else
     882              :     {
     883              :       /* Here, os_error_at already implies PRED_NORETURN.  */
     884        18113 :       tree lusize = fold_convert (long_unsigned_type_node, size);
     885        18113 :       tmp = trans_os_error_at (NULL, "Error allocating %lu bytes", lusize);
     886        18113 :       gfc_add_expr_to_block (&on_error, tmp);
     887              :     }
     888              : 
     889        18400 :   error_cond = fold_build2_loc (input_location, EQ_EXPR,
     890              :                                 logical_type_node, pointer,
     891              :                                 build_int_cst (prvoid_type_node, 0));
     892        36739 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
     893              :                          gfc_unlikely (error_cond, PRED_FORTRAN_FAIL_ALLOC),
     894              :                          gfc_finish_block (&on_error),
     895              :                          extra_success_expr
     896              :                          ? extra_success_expr
     897        18339 :                          : build_empty_stmt (input_location));
     898              : 
     899        18400 :   gfc_add_expr_to_block (block, tmp);
     900        18400 : }
     901              : 
     902              : 
     903              : /* Allocate memory, using an optional status argument.
     904              : 
     905              :    This function follows the following pseudo-code:
     906              : 
     907              :     void *
     908              :     allocate (size_t size, void** token, int *stat, char* errmsg, int errlen)
     909              :     {
     910              :       void *newmem;
     911              : 
     912              :       newmem = _caf_register (size, regtype, token, &stat, errmsg, errlen);
     913              :       return newmem;
     914              :     }  */
     915              : void
     916          793 : gfc_allocate_using_caf_lib (stmtblock_t * block, tree pointer, tree size,
     917              :                             tree token, tree status, tree errmsg, tree errlen,
     918              :                             gfc_coarray_regtype alloc_type)
     919              : {
     920          793 :   tree tmp, pstat;
     921              : 
     922          793 :   gcc_assert (token != NULL_TREE);
     923              : 
     924              :   /* The allocation itself.  */
     925          793 :   if (status == NULL_TREE)
     926          775 :     pstat  = null_pointer_node;
     927              :   else
     928           18 :     pstat  = gfc_build_addr_expr (NULL_TREE, status);
     929              : 
     930          793 :   if (errmsg == NULL_TREE)
     931              :     {
     932          775 :       gcc_assert(errlen == NULL_TREE);
     933          775 :       errmsg = null_pointer_node;
     934          775 :       errlen = integer_zero_node;
     935              :     }
     936              : 
     937          793 :   size = fold_convert (size_type_node, size);
     938          793 :   tmp = build_call_expr_loc (input_location,
     939              :              gfor_fndecl_caf_register, 7,
     940              :              fold_build2_loc (input_location,
     941              :                               MAX_EXPR, size_type_node, size, size_one_node),
     942          793 :              build_int_cst (integer_type_node, alloc_type),
     943              :              token, gfc_build_addr_expr (pvoid_type_node, pointer),
     944              :              pstat, errmsg, errlen);
     945              : 
     946          793 :   gfc_add_expr_to_block (block, tmp);
     947              : 
     948              :   /* It guarantees memory consistency within the same segment */
     949          793 :   tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
     950          793 :   tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
     951              :                     gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
     952              :                     tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
     953          793 :   ASM_VOLATILE_P (tmp) = 1;
     954          793 :   gfc_add_expr_to_block (block, tmp);
     955          793 : }
     956              : 
     957              : 
     958              : /* Generate code for an ALLOCATE statement when the argument is an
     959              :    allocatable variable.  If the variable is currently allocated, it is an
     960              :    error to allocate it again.
     961              : 
     962              :    This function follows the following pseudo-code:
     963              : 
     964              :     void *
     965              :     allocate_allocatable (void *mem, size_t size, integer_type stat)
     966              :     {
     967              :       if (mem == NULL)
     968              :         return allocate (size, stat);
     969              :       else
     970              :       {
     971              :         if (stat)
     972              :           stat = LIBERROR_ALLOCATION;
     973              :         else
     974              :           runtime_error ("Attempting to allocate already allocated variable");
     975              :       }
     976              :     }
     977              : 
     978              :     expr must be set to the original expression being allocated for its locus
     979              :     and variable name in case a runtime error has to be printed.  */
     980              : void
     981        13889 : gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size,
     982              :                           tree token, tree status, tree errmsg, tree errlen,
     983              :                           tree label_finish, gfc_expr* expr, int corank,
     984              :                           tree cond, tree alt_alloc, tree extra_success_expr)
     985              : {
     986        13889 :   stmtblock_t alloc_block;
     987        13889 :   tree tmp, null_mem, alloc, error;
     988        13889 :   tree type = TREE_TYPE (mem);
     989        13889 :   symbol_attribute caf_attr;
     990        13889 :   bool need_assign = false, refs_comp = false;
     991        13889 :   gfc_coarray_regtype caf_alloc_type = GFC_CAF_COARRAY_ALLOC;
     992              : 
     993        13889 :   size = fold_convert (size_type_node, size);
     994        13889 :   null_mem = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
     995              :                                             logical_type_node, mem,
     996              :                                             build_int_cst (type, 0)),
     997              :                            PRED_FORTRAN_REALLOC);
     998              : 
     999              :   /* If mem is NULL, we call gfc_allocate_using_malloc or
    1000              :      gfc_allocate_using_lib.  */
    1001        13889 :   gfc_start_block (&alloc_block);
    1002              : 
    1003        13889 :   if (flag_coarray == GFC_FCOARRAY_LIB)
    1004          524 :     caf_attr = gfc_caf_attr (expr, true, &refs_comp);
    1005              : 
    1006        13889 :   if (flag_coarray == GFC_FCOARRAY_LIB
    1007          524 :       && (corank > 0 || caf_attr.codimension))
    1008              :     {
    1009          465 :       tree cond2, sub_caf_tree;
    1010          465 :       gfc_se se;
    1011          465 :       bool compute_special_caf_types_size = false;
    1012              : 
    1013          465 :       if (expr->ts.type == BT_DERIVED
    1014          106 :           && expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
    1015           10 :           && expr->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
    1016              :         {
    1017              :           compute_special_caf_types_size = true;
    1018              :           caf_alloc_type = GFC_CAF_LOCK_ALLOC;
    1019              :         }
    1020          459 :       else if (expr->ts.type == BT_DERIVED
    1021          100 :                && expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
    1022            4 :                && expr->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
    1023              :         {
    1024              :           compute_special_caf_types_size = true;
    1025              :           caf_alloc_type = GFC_CAF_EVENT_ALLOC;
    1026              :         }
    1027          455 :       else if (!caf_attr.coarray_comp && refs_comp)
    1028              :         /* Only allocatable components in a derived type coarray can be
    1029              :            allocate only.  */
    1030          465 :         caf_alloc_type = GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY;
    1031              : 
    1032          465 :       gfc_init_se (&se, NULL);
    1033          465 :       sub_caf_tree = gfc_get_ultimate_alloc_ptr_comps_caf_token (&se, expr);
    1034          465 :       if (sub_caf_tree == NULL_TREE)
    1035          253 :         sub_caf_tree = token;
    1036              : 
    1037              :       /* When mem is an array ref, then strip the .data-ref.  */
    1038          465 :       if (TREE_CODE (mem) == COMPONENT_REF
    1039          465 :           && !(GFC_ARRAY_TYPE_P (TREE_TYPE (mem))))
    1040          465 :         tmp = TREE_OPERAND (mem, 0);
    1041              :       else
    1042              :         tmp = mem;
    1043              : 
    1044          465 :       if (!(GFC_ARRAY_TYPE_P (TREE_TYPE (tmp))
    1045           48 :             && TYPE_LANG_SPECIFIC (TREE_TYPE (tmp))->corank == 0)
    1046          513 :           && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    1047              :         {
    1048          100 :           symbol_attribute attr;
    1049              : 
    1050          100 :           gfc_clear_attr (&attr);
    1051          100 :           tmp = gfc_conv_scalar_to_descriptor (&se, mem, attr);
    1052          100 :           need_assign = true;
    1053              :         }
    1054          465 :       gfc_add_block_to_block (&alloc_block, &se.pre);
    1055              : 
    1056              :       /* In the front end, we represent the lock variable as pointer. However,
    1057              :          the FE only passes the pointer around and leaves the actual
    1058              :          representation to the library. Hence, we have to convert back to the
    1059              :          number of elements.  */
    1060          465 :       if (compute_special_caf_types_size)
    1061           10 :         size = fold_build2_loc (input_location, TRUNC_DIV_EXPR, size_type_node,
    1062           10 :                                 size, TYPE_SIZE_UNIT (ptr_type_node));
    1063              : 
    1064          465 :       gfc_allocate_using_caf_lib (&alloc_block, tmp, size, sub_caf_tree,
    1065              :                                   status, errmsg, errlen, caf_alloc_type);
    1066          465 :       if (need_assign)
    1067          100 :         gfc_add_modify (&alloc_block, mem, fold_convert (TREE_TYPE (mem),
    1068              :                                            gfc_conv_descriptor_data_get (tmp)));
    1069          465 :       if (status != NULL_TREE)
    1070              :         {
    1071           18 :           TREE_USED (label_finish) = 1;
    1072           18 :           tmp = build1_v (GOTO_EXPR, label_finish);
    1073           18 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1074           18 :                                    status, build_zero_cst (TREE_TYPE (status)));
    1075           18 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1076              :                                  gfc_unlikely (cond2, PRED_FORTRAN_FAIL_ALLOC),
    1077              :                                  tmp, build_empty_stmt (input_location));
    1078           18 :           gfc_add_expr_to_block (&alloc_block, tmp);
    1079              :         }
    1080          465 :     }
    1081              :   else
    1082        13424 :     gfc_allocate_using_malloc (&alloc_block, mem, size, status,
    1083              :                                cond, alt_alloc, extra_success_expr);
    1084              : 
    1085        13889 :   alloc = gfc_finish_block (&alloc_block);
    1086              : 
    1087              :   /* If mem is not NULL, we issue a runtime error or set the
    1088              :      status variable.  */
    1089        13889 :   if (expr)
    1090              :     {
    1091        13889 :       tree varname;
    1092              : 
    1093        13889 :       gcc_assert (expr->expr_type == EXPR_VARIABLE && expr->symtree);
    1094        13889 :       varname = gfc_build_cstring_const (expr->symtree->name);
    1095        13889 :       varname = gfc_build_addr_expr (pchar_type_node, varname);
    1096              : 
    1097        13889 :       error = gfc_trans_runtime_error (true, &expr->where,
    1098              :                                        "Attempting to allocate already"
    1099              :                                        " allocated variable '%s'",
    1100              :                                        varname);
    1101              :     }
    1102              :   else
    1103            0 :     error = gfc_trans_runtime_error (true, NULL,
    1104              :                                      "Attempting to allocate already allocated"
    1105              :                                      " variable");
    1106              : 
    1107        13889 :   if (status != NULL_TREE)
    1108              :     {
    1109          283 :       tree status_type = TREE_TYPE (status);
    1110              : 
    1111          283 :       error = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
    1112              :               status, build_int_cst (status_type, LIBERROR_ALLOCATION));
    1113              :     }
    1114              : 
    1115        13889 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, null_mem,
    1116              :                          error, alloc);
    1117        13889 :   gfc_add_expr_to_block (block, tmp);
    1118        13889 : }
    1119              : 
    1120              : 
    1121              : /* Free a given variable.  */
    1122              : 
    1123              : tree
    1124        24444 : gfc_call_free (tree var)
    1125              : {
    1126        24444 :   return build_call_expr_loc (input_location,
    1127              :                               builtin_decl_explicit (BUILT_IN_FREE),
    1128        24444 :                               1, fold_convert (pvoid_type_node, var));
    1129              : }
    1130              : 
    1131              : 
    1132              : /* Generate the data reference to the finalization procedure pointer associated
    1133              :    with the expression passed as argument in EXPR.  */
    1134              : 
    1135              : static void
    1136         5301 : get_final_proc_ref (gfc_se *se, gfc_expr *expr, tree class_container)
    1137              : {
    1138         5301 :   gfc_expr *final_wrapper = NULL;
    1139              : 
    1140         5301 :   gcc_assert (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS);
    1141              : 
    1142         5301 :   bool using_class_container = false;
    1143         5301 :   if (expr->ts.type == BT_DERIVED)
    1144          895 :     gfc_is_finalizable (expr->ts.u.derived, &final_wrapper);
    1145         4406 :   else if (class_container)
    1146              :     {
    1147          284 :       using_class_container = true;
    1148          284 :       se->expr = gfc_class_vtab_final_get (class_container);
    1149              :     }
    1150              :   else
    1151              :     {
    1152         4122 :       final_wrapper = gfc_copy_expr (expr);
    1153         4122 :       gfc_add_vptr_component (final_wrapper);
    1154         4122 :       gfc_add_final_component (final_wrapper);
    1155              :     }
    1156              : 
    1157         5301 :   if (!using_class_container)
    1158              :     {
    1159         5017 :       gcc_assert (final_wrapper->expr_type == EXPR_VARIABLE);
    1160              : 
    1161         5017 :       gfc_conv_expr (se, final_wrapper);
    1162              :     }
    1163              : 
    1164         5301 :   if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
    1165         1166 :     se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
    1166              : 
    1167         5301 :   if (expr->ts.type != BT_DERIVED && !using_class_container)
    1168         4122 :     gfc_free_expr (final_wrapper);
    1169         5301 : }
    1170              : 
    1171              : 
    1172              : /* Generate the code to obtain the value of the element size of the expression
    1173              :    passed as argument in EXPR.  */
    1174              : 
    1175              : static void
    1176         5301 : get_elem_size (gfc_se *se, gfc_expr *expr, tree class_container)
    1177              : {
    1178         5301 :   gcc_assert (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS);
    1179              : 
    1180         5301 :   if (expr->ts.type == BT_DERIVED)
    1181              :     {
    1182          895 :       se->expr = gfc_typenode_for_spec (&expr->ts);
    1183          895 :       se->expr = TYPE_SIZE_UNIT (se->expr);
    1184          895 :       se->expr = fold_convert (gfc_array_index_type, se->expr);
    1185              :     }
    1186         4406 :   else if (class_container)
    1187          284 :     se->expr = gfc_class_vtab_size_get (class_container);
    1188              :   else
    1189              :     {
    1190         4122 :       gfc_expr *class_size = gfc_copy_expr (expr);
    1191         4122 :       gfc_add_vptr_component (class_size);
    1192         4122 :       gfc_add_size_component (class_size);
    1193              : 
    1194         4122 :       gfc_conv_expr (se, class_size);
    1195         4122 :       gcc_assert (se->post.head == NULL_TREE);
    1196         4122 :       gfc_free_expr (class_size);
    1197              :     }
    1198         5301 : }
    1199              : 
    1200              : 
    1201              : /* Generate the data reference (array) descriptor corresponding to the
    1202              :    expression passed as argument in VAR.  */
    1203              : 
    1204              : static void
    1205         5301 : get_var_descr (gfc_se *se, gfc_expr *var, tree class_container)
    1206              : {
    1207         5301 :   gfc_se tmp_se;
    1208              : 
    1209         5301 :   gcc_assert (var);
    1210              : 
    1211         5301 :   gfc_init_se (&tmp_se, NULL);
    1212              : 
    1213         5301 :   if (var->ts.type == BT_DERIVED)
    1214              :     {
    1215          895 :       tmp_se.want_pointer = 1;
    1216          895 :       if (var->rank)
    1217              :         {
    1218          266 :           tmp_se.descriptor_only = 1;
    1219          266 :           gfc_conv_expr_descriptor (&tmp_se, var);
    1220              :         }
    1221              :       else
    1222          629 :         gfc_conv_expr (&tmp_se, var);
    1223              :     }
    1224         4406 :   else if (class_container)
    1225          284 :     tmp_se.expr = gfc_class_data_get (class_container);
    1226              :   else
    1227              :     {
    1228         4122 :       gfc_expr *array_expr;
    1229              : 
    1230         4122 :       array_expr = gfc_copy_expr (var);
    1231              : 
    1232         4122 :       tmp_se.want_pointer = 1;
    1233         4122 :       if (array_expr->rank)
    1234              :         {
    1235         2176 :           gfc_add_class_array_ref (array_expr);
    1236         2176 :           tmp_se.descriptor_only = 1;
    1237         2176 :           gfc_conv_expr_descriptor (&tmp_se, array_expr);
    1238              :         }
    1239              :       else
    1240              :         {
    1241         1946 :           gfc_add_data_component (array_expr);
    1242         1946 :           gfc_conv_expr (&tmp_se, array_expr);
    1243         1946 :           gcc_assert (tmp_se.post.head == NULL_TREE);
    1244              :         }
    1245         4122 :       gfc_free_expr (array_expr);
    1246              :     }
    1247              : 
    1248         5301 :   if (var->rank == 0)
    1249              :     {
    1250         2737 :       if (var->ts.type == BT_DERIVED
    1251         2737 :           || !gfc_is_coarray (var))
    1252              :         {
    1253              :           /* No copy back needed, hence set attr's allocatable/pointer
    1254              :              to zero.  */
    1255         2695 :           symbol_attribute attr;
    1256         2695 :           gfc_clear_attr (&attr);
    1257         2695 :           tmp_se.expr = gfc_conv_scalar_to_descriptor (&tmp_se, tmp_se.expr,
    1258              :                                                        attr);
    1259              :         }
    1260         2737 :       gcc_assert (tmp_se.post.head == NULL_TREE);
    1261              :     }
    1262              : 
    1263         5301 :   if (!POINTER_TYPE_P (TREE_TYPE (tmp_se.expr)))
    1264         2817 :     tmp_se.expr = gfc_build_addr_expr (NULL, tmp_se.expr);
    1265              : 
    1266         5301 :   gfc_add_block_to_block (&se->pre, &tmp_se.pre);
    1267         5301 :   gfc_add_block_to_block (&se->post, &tmp_se.post);
    1268         5301 :   se->expr = tmp_se.expr;
    1269         5301 : }
    1270              : 
    1271              : 
    1272              : static void
    1273         1198 : get_vptr (gfc_se *se, gfc_expr *expr, tree class_container)
    1274              : {
    1275         1198 :   if (class_container)
    1276           54 :     se->expr = gfc_class_vptr_get (class_container);
    1277              :   else
    1278              :     {
    1279         1144 :       gfc_expr *vptr_expr = gfc_copy_expr (expr);
    1280         1144 :       gfc_add_vptr_component (vptr_expr);
    1281              : 
    1282         1144 :       gfc_se tmp_se;
    1283         1144 :       gfc_init_se (&tmp_se, NULL);
    1284         1144 :       tmp_se.want_pointer = 1;
    1285         1144 :       gfc_conv_expr (&tmp_se, vptr_expr);
    1286         1144 :       gfc_free_expr (vptr_expr);
    1287              : 
    1288         1144 :       gfc_add_block_to_block (&se->pre, &tmp_se.pre);
    1289         1144 :       gfc_add_block_to_block (&se->post, &tmp_se.post);
    1290         1144 :       se->expr = tmp_se.expr;
    1291              :     }
    1292         1198 : }
    1293              : 
    1294              : 
    1295              : bool
    1296         4182 : gfc_add_comp_finalizer_call (stmtblock_t *block, tree decl, gfc_component *comp,
    1297              :                              bool fini_coarray)
    1298              : {
    1299         4182 :   gfc_se se;
    1300         4182 :   stmtblock_t block2;
    1301         4182 :   tree final_fndecl, size, array, tmp, cond;
    1302         4182 :   symbol_attribute attr;
    1303         4182 :   gfc_expr *final_expr = NULL;
    1304              : 
    1305         4182 :   if (comp->ts.type != BT_DERIVED && comp->ts.type != BT_CLASS)
    1306              :     return false;
    1307              : 
    1308         4182 :   gfc_init_block (&block2);
    1309              : 
    1310         4182 :   if (comp->ts.type == BT_DERIVED)
    1311              :     {
    1312         3203 :       if (comp->attr.pointer)
    1313              :         return false;
    1314              : 
    1315         3203 :       gfc_is_finalizable (comp->ts.u.derived, &final_expr);
    1316         3203 :       if (!final_expr)
    1317              :         return false;
    1318              : 
    1319           81 :       gfc_init_se (&se, NULL);
    1320           81 :       gfc_conv_expr (&se, final_expr);
    1321           81 :       final_fndecl = se.expr;
    1322           81 :       size = gfc_typenode_for_spec (&comp->ts);
    1323           81 :       size = TYPE_SIZE_UNIT (size);
    1324           81 :       size = fold_convert (gfc_array_index_type, size);
    1325              : 
    1326           81 :       array = decl;
    1327              :     }
    1328              :   else /* comp->ts.type == BT_CLASS.  */
    1329              :     {
    1330          979 :       if (CLASS_DATA (comp)->attr.class_pointer)
    1331              :         return false;
    1332              : 
    1333          979 :       gfc_is_finalizable (CLASS_DATA (comp)->ts.u.derived, &final_expr);
    1334          979 :       final_fndecl = gfc_class_vtab_final_get (decl);
    1335          979 :       size = gfc_class_vtab_size_get (decl);
    1336          979 :       array = gfc_class_data_get (decl);
    1337              :     }
    1338              : 
    1339         1060 :   if (comp->attr.allocatable
    1340          979 :       || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)->attr.allocatable))
    1341              :     {
    1342         1060 :       tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array))
    1343         1060 :             ?  gfc_conv_descriptor_data_get (array) : array;
    1344         1060 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1345         1060 :                             tmp, fold_convert (TREE_TYPE (tmp),
    1346              :                                                  null_pointer_node));
    1347              :     }
    1348              :   else
    1349            0 :     cond = logical_true_node;
    1350              : 
    1351         1060 :   if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array)))
    1352              :     {
    1353          621 :       gfc_clear_attr (&attr);
    1354          621 :       gfc_init_se (&se, NULL);
    1355          621 :       array = gfc_conv_scalar_to_descriptor (&se, array, attr);
    1356          621 :       gfc_add_block_to_block (&block2, &se.pre);
    1357          621 :       gcc_assert (se.post.head == NULL_TREE);
    1358              :     }
    1359              : 
    1360         1060 :   if (!POINTER_TYPE_P (TREE_TYPE (array)))
    1361         1060 :     array = gfc_build_addr_expr (NULL, array);
    1362              : 
    1363         1060 :   if (!final_expr)
    1364              :     {
    1365          977 :       tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1366              :                              final_fndecl,
    1367          977 :                              fold_convert (TREE_TYPE (final_fndecl),
    1368              :                                            null_pointer_node));
    1369          977 :       cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    1370              :                               logical_type_node, cond, tmp);
    1371              :     }
    1372              : 
    1373         1060 :   if (POINTER_TYPE_P (TREE_TYPE (final_fndecl)))
    1374         1060 :     final_fndecl = build_fold_indirect_ref_loc (input_location, final_fndecl);
    1375              : 
    1376         1060 :   tmp = build_call_expr_loc (input_location,
    1377              :                              final_fndecl, 3, array,
    1378              :                              size, fini_coarray ? boolean_true_node
    1379              :                                                 : boolean_false_node);
    1380         1060 :   gfc_add_expr_to_block (&block2, tmp);
    1381         1060 :   tmp = gfc_finish_block (&block2);
    1382              : 
    1383         1060 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
    1384              :                          build_empty_stmt (input_location));
    1385         1060 :   gfc_add_expr_to_block (block, tmp);
    1386              : 
    1387         1060 :   return true;
    1388              : }
    1389              : 
    1390              : 
    1391              : /* Add a call to the finalizer, using the passed *expr. Returns
    1392              :    true when a finalizer call has been inserted.  */
    1393              : 
    1394              : bool
    1395        30847 : gfc_add_finalizer_call (stmtblock_t *block, gfc_expr *expr2,
    1396              :                         tree class_container)
    1397              : {
    1398        30847 :   tree tmp;
    1399        30847 :   gfc_ref *ref;
    1400        30847 :   gfc_expr *expr;
    1401              : 
    1402        30847 :   if (!expr2 || (expr2->ts.type != BT_DERIVED && expr2->ts.type != BT_CLASS))
    1403              :     return false;
    1404              : 
    1405              :   /* Finalization of these temporaries is made by explicit calls in
    1406              :      resolve.cc(generate_component_assignments).  */
    1407         7573 :   if (expr2->expr_type == EXPR_VARIABLE
    1408         7573 :       && expr2->symtree->n.sym->name[0] == '_'
    1409           91 :       && expr2->ts.type == BT_DERIVED
    1410           37 :       && expr2->ts.u.derived->attr.defined_assign_comp)
    1411              :     return false;
    1412              : 
    1413         7542 :   if (expr2->ts.type == BT_DERIVED
    1414         7542 :       && !gfc_is_finalizable (expr2->ts.u.derived, NULL))
    1415              :     return false;
    1416              : 
    1417              :   /* If we have a class array, we need go back to the class
    1418              :      container.  */
    1419         5301 :   expr = gfc_copy_expr (expr2);
    1420              : 
    1421         5301 :   if (expr->ref && expr->ref->next && !expr->ref->next->next
    1422         1169 :       && expr->ref->next->type == REF_ARRAY
    1423         1084 :       && expr->ref->type == REF_COMPONENT
    1424         1084 :       && strcmp (expr->ref->u.c.component->name, "_data") == 0)
    1425              :     {
    1426         1041 :       gfc_free_ref_list (expr->ref);
    1427         1041 :       expr->ref = NULL;
    1428              :     }
    1429              :   else
    1430         6548 :     for (ref = expr->ref; ref; ref = ref->next)
    1431         2288 :       if (ref->next && ref->next->next && !ref->next->next->next
    1432          368 :          && ref->next->next->type == REF_ARRAY
    1433          349 :          && ref->next->type == REF_COMPONENT
    1434          349 :          && strcmp (ref->next->u.c.component->name, "_data") == 0)
    1435              :        {
    1436          349 :          gfc_free_ref_list (ref->next);
    1437          349 :          ref->next = NULL;
    1438              :        }
    1439              : 
    1440         5301 :   if (expr->ts.type == BT_CLASS && (!expr2->rank || !expr2->corank)
    1441         4359 :       && !expr2->ref && CLASS_DATA (expr2->symtree->n.sym)->as)
    1442              :     {
    1443            3 :       expr->rank = CLASS_DATA (expr2->symtree->n.sym)->as->rank;
    1444            3 :       expr->corank = CLASS_DATA (expr2->symtree->n.sym)->as->corank;
    1445              :     }
    1446              : 
    1447         5301 :   stmtblock_t tmp_block;
    1448         5301 :   gfc_start_block (&tmp_block);
    1449              : 
    1450         5301 :   gfc_se final_se;
    1451         5301 :   gfc_init_se (&final_se, NULL);
    1452         5301 :   get_final_proc_ref (&final_se, expr, class_container);
    1453         5301 :   gfc_add_block_to_block (block, &final_se.pre);
    1454              : 
    1455         5301 :   gfc_se size_se;
    1456         5301 :   gfc_init_se (&size_se, NULL);
    1457         5301 :   get_elem_size (&size_se, expr, class_container);
    1458         5301 :   gfc_add_block_to_block (&tmp_block, &size_se.pre);
    1459              : 
    1460         5301 :   gfc_se desc_se;
    1461         5301 :   gfc_init_se (&desc_se, NULL);
    1462         5301 :   get_var_descr (&desc_se, expr, class_container);
    1463         5301 :   gfc_add_block_to_block (&tmp_block, &desc_se.pre);
    1464              : 
    1465         5301 :   tmp = build_call_expr_loc (input_location, final_se.expr, 3,
    1466              :                              desc_se.expr, size_se.expr,
    1467              :                              boolean_false_node);
    1468              : 
    1469         5301 :   gfc_add_expr_to_block (&tmp_block, tmp);
    1470              : 
    1471         5301 :   gfc_add_block_to_block (&tmp_block, &desc_se.post);
    1472         5301 :   gfc_add_block_to_block (&tmp_block, &size_se.post);
    1473              : 
    1474         5301 :   tmp = gfc_finish_block (&tmp_block);
    1475              : 
    1476         5301 :   if (expr->ts.type == BT_CLASS
    1477         5301 :       && !gfc_is_finalizable (expr->ts.u.derived, NULL))
    1478              :     {
    1479         4406 :       tree cond;
    1480              : 
    1481         4406 :       tree ptr = gfc_build_addr_expr (NULL_TREE, final_se.expr);
    1482              : 
    1483         4406 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1484         4406 :                               ptr, build_int_cst (TREE_TYPE (ptr), 0));
    1485              : 
    1486              :       /* For CLASS(*) not only sym->_vtab->_final can be NULL
    1487              :          but already sym->_vtab itself.  */
    1488         4406 :       if (UNLIMITED_POLY (expr))
    1489              :         {
    1490         1198 :           tree cond2;
    1491         1198 :           gfc_se vptr_se;
    1492              : 
    1493         1198 :           gfc_init_se (&vptr_se, NULL);
    1494         1198 :           get_vptr (&vptr_se, expr, class_container);
    1495              : 
    1496         1198 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1497              :                                    vptr_se.expr,
    1498         1198 :                                    build_int_cst (TREE_TYPE (vptr_se.expr), 0));
    1499         1198 :           cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
    1500              :                                   logical_type_node, cond2, cond);
    1501              :         }
    1502              : 
    1503         4406 :       tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1504              :                              cond, tmp, build_empty_stmt (input_location));
    1505              :     }
    1506              : 
    1507         5301 :   gfc_add_expr_to_block (block, tmp);
    1508         5301 :   gfc_add_block_to_block (block, &final_se.post);
    1509         5301 :   gfc_free_expr (expr);
    1510              : 
    1511         5301 :   return true;
    1512              : }
    1513              : 
    1514              : 
    1515              :   /* F2018 (7.5.6.3): "When an intrinsic assignment statement is executed
    1516              :      (10.2.1.3), if the variable is not an unallocated allocatable variable,
    1517              :      it is finalized after evaluation of expr and before the definition of
    1518              :      the variable. If the variable is an allocated allocatable variable, or
    1519              :      has an allocated allocatable subobject, that would be deallocated by
    1520              :      intrinsic assignment, the finalization occurs before the deallocation */
    1521              : 
    1522              : bool
    1523       316998 : gfc_assignment_finalizer_call (gfc_se *lse, gfc_expr *expr1, bool init_flag)
    1524              : {
    1525       316998 :   symbol_attribute lhs_attr;
    1526       316998 :   tree final_expr;
    1527       316998 :   tree ptr;
    1528       316998 :   tree cond;
    1529       316998 :   gfc_se se;
    1530       316998 :   gfc_symbol *sym = expr1->symtree->n.sym;
    1531       316998 :   gfc_ref *ref = expr1->ref;
    1532       316998 :   stmtblock_t final_block;
    1533       316998 :   gfc_init_block (&final_block);
    1534       316998 :   gfc_expr *finalize_expr;
    1535       316998 :   bool class_array_ref;
    1536              : 
    1537              :   /* We have to exclude vtable procedures (_copy and _final especially), uses
    1538              :      of gfc_trans_assignment_1 in initialization and allocation before trying
    1539              :      to build a final call.  */
    1540       316998 :   if (!expr1->must_finalize
    1541         1342 :       || sym->attr.artificial
    1542         1342 :       || sym->ns->proc_name->attr.artificial
    1543         1342 :       || init_flag)
    1544              :     return false;
    1545              : 
    1546          906 :   class_array_ref = ref && ref->type == REF_COMPONENT
    1547          757 :                     && !strcmp (ref->u.c.component->name, "_data")
    1548          587 :                     && ref->next && ref->next->type == REF_ARRAY
    1549         1929 :                     && !ref->next->next;
    1550              : 
    1551         1342 :   if (class_array_ref)
    1552              :     {
    1553          575 :       finalize_expr = gfc_lval_expr_from_sym (sym);
    1554          575 :       finalize_expr->must_finalize = 1;
    1555          575 :       ref = NULL;
    1556              :     }
    1557              :   else
    1558          767 :     finalize_expr = gfc_copy_expr (expr1);
    1559              : 
    1560              :   /* F2018 7.5.6.2: Only finalizable entities are finalized.  */
    1561          323 :   if (!(expr1->ts.type == BT_DERIVED
    1562          323 :         && gfc_is_finalizable (expr1->ts.u.derived, NULL))
    1563         1342 :       && expr1->ts.type != BT_CLASS)
    1564              :       return false;
    1565              : 
    1566         1330 :   if (!gfc_may_be_finalized (sym->ts))
    1567              :     return false;
    1568              : 
    1569         1244 :   gfc_init_block (&final_block);
    1570         1244 :   bool finalizable = gfc_add_finalizer_call (&final_block, finalize_expr);
    1571         1244 :   gfc_free_expr (finalize_expr);
    1572              : 
    1573         1244 :   if (!finalizable)
    1574              :     return false;
    1575              : 
    1576         1244 :   lhs_attr = gfc_expr_attr (expr1);
    1577              : 
    1578              :   /* Check allocatable/pointer is allocated/associated.  */
    1579         1244 :   if (lhs_attr.allocatable || lhs_attr.pointer)
    1580              :     {
    1581         1029 :       if (expr1->ts.type == BT_CLASS)
    1582              :         {
    1583          927 :           ptr = gfc_get_class_from_gfc_expr (expr1);
    1584          927 :           gcc_assert (ptr != NULL_TREE);
    1585          927 :           ptr = gfc_class_data_get (ptr);
    1586          927 :           if (lhs_attr.dimension)
    1587          656 :             ptr = gfc_conv_descriptor_data_get (ptr);
    1588              :         }
    1589              :       else
    1590              :         {
    1591          102 :           gfc_init_se (&se, NULL);
    1592          102 :           if (expr1->rank)
    1593              :             {
    1594              :               /* Avoid calling trans-array.cc(set_factored_descriptor_value) by
    1595              :                  not using gfc_conv_expr_descriptor.  */
    1596           54 :               se.descriptor_only = 1;
    1597           54 :               gfc_conv_expr (&se, expr1);
    1598           54 :               ptr = gfc_conv_descriptor_data_get (se.expr);
    1599              :             }
    1600              :           else
    1601              :             {
    1602           48 :               gfc_conv_expr (&se, expr1);
    1603           48 :               ptr = gfc_build_addr_expr (NULL_TREE, se.expr);
    1604              :             }
    1605              :         }
    1606              : 
    1607         1029 :       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1608         1029 :                               ptr, build_zero_cst (TREE_TYPE (ptr)));
    1609         1029 :       final_expr = build3_loc (input_location, COND_EXPR, void_type_node,
    1610              :                                cond, gfc_finish_block (&final_block),
    1611              :                                build_empty_stmt (input_location));
    1612              :     }
    1613              :   else
    1614          215 :     final_expr = gfc_finish_block (&final_block);
    1615              : 
    1616              :   /* Check optional present.  */
    1617         1244 :   if (sym->attr.optional)
    1618              :     {
    1619            0 :       cond = gfc_conv_expr_present (sym);
    1620            0 :       final_expr = build3_loc (input_location, COND_EXPR, void_type_node,
    1621              :                                cond, final_expr,
    1622              :                                build_empty_stmt (input_location));
    1623              :     }
    1624              : 
    1625         1244 :   gfc_add_expr_to_block (&lse->finalblock, final_expr);
    1626              : 
    1627         1244 :   return true;
    1628              : }
    1629              : 
    1630              : 
    1631              : /* Finalize a TREE expression using the finalizer wrapper. The result is
    1632              :    fixed in order to prevent repeated calls.  */
    1633              : 
    1634              : void
    1635          662 : gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
    1636              :                         const symbol_attribute &attr, int rank)
    1637              : {
    1638          662 :   tree vptr, final_fndecl, desc, tmp, size, is_final;
    1639          662 :   tree data_ptr, data_null, cond;
    1640          662 :   gfc_symbol *vtab;
    1641          662 :   gfc_se post_se;
    1642          662 :   bool is_class = GFC_CLASS_TYPE_P (TREE_TYPE (se->expr));
    1643              : 
    1644          662 :   if (attr.pointer)
    1645           52 :     return;
    1646              : 
    1647              :   /* Derived type function results with components that have defined
    1648              :      assignments are handled in resolve.cc(generate_component_assignments),
    1649              :      unless the assignment was replaced by a subroutine call to the
    1650              :      subroutine associated with the assignment operator. */
    1651          659 :   if ( ! is_assign_call
    1652          573 :        && derived && (derived->attr.is_c_interop
    1653          188 :        || derived->attr.is_iso_c
    1654          188 :        || derived->attr.is_bind_c
    1655          188 :        || (derived->attr.extension && derived->f2k_derived
    1656           24 :            && derived->f2k_derived->tb_op[INTRINSIC_ASSIGN])
    1657          188 :        || (!derived->attr.extension
    1658          164 :            && derived->attr.defined_assign_comp)))
    1659              :     return;
    1660              : 
    1661          653 :   if (is_class)
    1662              :     {
    1663          384 :       if (!VAR_P (se->expr))
    1664              :         {
    1665            0 :           desc = gfc_evaluate_now (se->expr, &se->pre);
    1666            0 :           se->expr = desc;
    1667              :         }
    1668          384 :       desc = gfc_class_data_get (se->expr);
    1669          384 :       vptr = gfc_class_vptr_get (se->expr);
    1670              :     }
    1671          269 :   else if (derived && gfc_is_finalizable (derived, NULL))
    1672              :     {
    1673          230 :       tree type = TREE_TYPE (se->expr);
    1674          230 :       if (type && TYPE_SIZE_UNIT (type)
    1675          230 :           && integer_zerop (TYPE_SIZE_UNIT (type))
    1676          235 :           && (!rank || attr.elemental))
    1677              :         {
    1678              :           /* Any attempt to assign zero length entities, causes the gimplifier
    1679              :              all manner of problems. Instead, a variable is created to act as
    1680              :              the argument for the final call.  */
    1681            5 :           desc = gfc_create_var (type, "zero");
    1682              :         }
    1683          225 :       else if (se->direct_byref)
    1684              :         {
    1685            0 :           desc = gfc_evaluate_now (se->expr, &se->finalblock);
    1686            0 :           if (derived->attr.alloc_comp)
    1687              :             {
    1688              :               /* Need to copy allocated components and not finalize.  */
    1689            0 :               tmp = gfc_copy_alloc_comp_no_fini (derived, se->expr, desc, rank, 0);
    1690            0 :               gfc_add_expr_to_block (&se->finalblock, tmp);
    1691              :             }
    1692              :         }
    1693              :       else
    1694              :         {
    1695          225 :           desc = gfc_evaluate_now (se->expr, &se->pre);
    1696          225 :           se->expr = gfc_evaluate_now (desc, &se->pre);
    1697          225 :           if (derived->attr.alloc_comp)
    1698              :             {
    1699              :               /* Need to copy allocated components and not finalize.  */
    1700           38 :               tmp = gfc_copy_alloc_comp_no_fini (derived, se->expr, desc, rank, 0);
    1701           38 :               gfc_add_expr_to_block (&se->pre, tmp);
    1702              :             }
    1703              :         }
    1704              : 
    1705          230 :       vtab = gfc_find_derived_vtab (derived);
    1706          230 :       if (vtab->backend_decl == NULL_TREE)
    1707            6 :         vptr = gfc_get_symbol_decl (vtab);
    1708              :       else
    1709              :         vptr = vtab->backend_decl;
    1710          230 :       vptr = gfc_build_addr_expr (NULL, vptr);
    1711              :     }
    1712              :   else
    1713              :     return;
    1714              : 
    1715          614 :   size = gfc_vptr_size_get (vptr);
    1716          614 :   final_fndecl = gfc_vptr_final_get (vptr);
    1717          614 :   is_final = fold_build2_loc (input_location, NE_EXPR,
    1718              :                               logical_type_node,
    1719              :                               final_fndecl,
    1720          614 :                               fold_convert (TREE_TYPE (final_fndecl),
    1721              :                                             null_pointer_node));
    1722              : 
    1723          614 :   final_fndecl = build_fold_indirect_ref_loc (input_location,
    1724              :                                               final_fndecl);
    1725          614 :   if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
    1726              :     {
    1727          356 :       if (is_class || attr.elemental)
    1728          202 :         desc = gfc_conv_scalar_to_descriptor (se, desc, attr);
    1729              :       else
    1730              :         {
    1731          154 :           gfc_init_se (&post_se, NULL);
    1732          154 :           desc = gfc_conv_scalar_to_descriptor (&post_se, desc, attr);
    1733          154 :           gfc_add_expr_to_block (&se->pre, gfc_finish_block (&post_se.pre));
    1734              :         }
    1735              :     }
    1736              : 
    1737          614 :   if (derived && !derived->components)
    1738              :     {
    1739              :       /* All the conditions below break down for zero length derived types.  */
    1740            4 :       tmp = build_call_expr_loc (input_location, final_fndecl, 3,
    1741              :                                  gfc_build_addr_expr (NULL, desc),
    1742              :                                  size, boolean_false_node);
    1743            4 :       gfc_add_expr_to_block (&se->finalblock, tmp);
    1744            4 :       return;
    1745              :     }
    1746              : 
    1747          610 :   if (!VAR_P (desc))
    1748              :     {
    1749          222 :       tmp = gfc_create_var (TREE_TYPE (desc), "res");
    1750          222 :       if (se->direct_byref)
    1751            0 :         gfc_add_modify (&se->finalblock, tmp, desc);
    1752              :       else
    1753          222 :         gfc_add_modify (&se->pre, tmp, desc);
    1754              :       desc = tmp;
    1755              :     }
    1756              : 
    1757          610 :   data_ptr = gfc_conv_descriptor_data_get (desc);
    1758          610 :   data_null = fold_convert (TREE_TYPE (data_ptr), null_pointer_node);
    1759          610 :   cond = fold_build2_loc (input_location, NE_EXPR,
    1760              :                           logical_type_node, data_ptr, data_null);
    1761          610 :   is_final = fold_build2_loc (input_location, TRUTH_AND_EXPR,
    1762              :                               logical_type_node, is_final, cond);
    1763          610 :   tmp = build_call_expr_loc (input_location, final_fndecl, 3,
    1764              :                              gfc_build_addr_expr (NULL, desc),
    1765              :                              size, boolean_false_node);
    1766          610 :   tmp = fold_build3_loc (input_location, COND_EXPR,
    1767              :                          void_type_node, is_final, tmp,
    1768              :                          build_empty_stmt (input_location));
    1769              : 
    1770          610 :   if (is_class && se->ss && se->ss->loop)
    1771              :     {
    1772          140 :       gfc_add_expr_to_block (&se->loop->post, tmp);
    1773          140 :       tmp = fold_build3_loc (input_location, COND_EXPR,
    1774              :                              void_type_node, cond,
    1775              :                              gfc_call_free (data_ptr),
    1776              :                              build_empty_stmt (input_location));
    1777          140 :       gfc_add_expr_to_block (&se->loop->post, tmp);
    1778          140 :       gfc_conv_descriptor_data_set (&se->loop->post, desc, data_null);
    1779              :     }
    1780              :   else
    1781              :     {
    1782          470 :       gfc_add_expr_to_block (&se->finalblock, tmp);
    1783              : 
    1784              :       /* Let the scalarizer take care of freeing of temporary arrays.  */
    1785          470 :       if (attr.allocatable && !(se->loop && se->loop->temp_dim))
    1786              :         {
    1787          244 :           tmp = fold_build3_loc (input_location, COND_EXPR,
    1788              :                                  void_type_node, cond,
    1789              :                                  gfc_call_free (data_ptr),
    1790              :                                  build_empty_stmt (input_location));
    1791          244 :           gfc_add_expr_to_block (&se->finalblock, tmp);
    1792          244 :           gfc_conv_descriptor_data_set (&se->finalblock, desc, data_null);
    1793              :         }
    1794              :     }
    1795              : }
    1796              : 
    1797              : 
    1798              : /* User-deallocate; we emit the code directly from the front-end, and the
    1799              :    logic is the same as the previous library function:
    1800              : 
    1801              :     void
    1802              :     deallocate (void *pointer, GFC_INTEGER_4 * stat)
    1803              :     {
    1804              :       if (!pointer)
    1805              :         {
    1806              :           if (stat)
    1807              :             *stat = 1;
    1808              :           else
    1809              :             runtime_error ("Attempt to DEALLOCATE unallocated memory.");
    1810              :         }
    1811              :       else
    1812              :         {
    1813              :           free (pointer);
    1814              :           if (stat)
    1815              :             *stat = 0;
    1816              :         }
    1817              :     }
    1818              : 
    1819              :    In this front-end version, status doesn't have to be GFC_INTEGER_4.
    1820              :    Moreover, if CAN_FAIL is true, then we will not emit a runtime error,
    1821              :    even when no status variable is passed to us (this is used for
    1822              :    unconditional deallocation generated by the front-end at end of
    1823              :    each procedure).
    1824              : 
    1825              :    If a runtime-message is possible, `expr' must point to the original
    1826              :    expression being deallocated for its locus and variable name.
    1827              : 
    1828              :    For coarrays, "pointer" must be the array descriptor and not its
    1829              :    "data" component.
    1830              : 
    1831              :    COARRAY_DEALLOC_MODE gives the mode unregister coarrays.  Available modes are
    1832              :    the ones of GFC_CAF_DEREGTYPE, -1 when the mode for deregistration is to be
    1833              :    analyzed and set by this routine, and -2 to indicate that a non-coarray is to
    1834              :    be deallocated.  */
    1835              : tree
    1836        23442 : gfc_deallocate_with_status (tree pointer, tree status, tree errmsg, tree errlen,
    1837              :                             tree label_finish, bool can_fail, gfc_expr *expr,
    1838              :                             int coarray_dealloc_mode, tree class_container,
    1839              :                             tree add_when_allocated, tree caf_token,
    1840              :                             bool unalloc_ok)
    1841              : {
    1842        23442 :   stmtblock_t null, non_null;
    1843        23442 :   tree cond, tmp, error;
    1844        23442 :   tree status_type = NULL_TREE;
    1845        23442 :   tree token = NULL_TREE;
    1846        23442 :   tree descr = NULL_TREE;
    1847        23442 :   gfc_coarray_deregtype caf_dereg_type = GFC_CAF_COARRAY_DEREGISTER;
    1848              : 
    1849        23442 :   if (coarray_dealloc_mode >= GFC_CAF_COARRAY_ANALYZE)
    1850              :     {
    1851          475 :       if (flag_coarray == GFC_FCOARRAY_LIB)
    1852              :         {
    1853          313 :           if (caf_token)
    1854              :             {
    1855           63 :               token = caf_token;
    1856           63 :               if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
    1857           44 :                 pointer = gfc_conv_descriptor_data_get (pointer);
    1858              :             }
    1859              :           else
    1860              :             {
    1861          250 :               tree caf_type, caf_decl = pointer;
    1862          250 :               pointer = gfc_conv_descriptor_data_get (caf_decl);
    1863          250 :               caf_type = TREE_TYPE (caf_decl);
    1864          250 :               STRIP_NOPS (pointer);
    1865          250 :               if (GFC_DESCRIPTOR_TYPE_P (caf_type))
    1866          250 :                 token = gfc_conv_descriptor_token (caf_decl);
    1867            0 :               else if (DECL_LANG_SPECIFIC (caf_decl)
    1868            0 :                        && GFC_DECL_TOKEN (caf_decl) != NULL_TREE)
    1869            0 :                 token = GFC_DECL_TOKEN (caf_decl);
    1870              :               else
    1871              :                 {
    1872            0 :                   gcc_assert (GFC_ARRAY_TYPE_P (caf_type)
    1873              :                               && GFC_TYPE_ARRAY_CAF_TOKEN (caf_type)
    1874              :                                  != NULL_TREE);
    1875            0 :                   token = GFC_TYPE_ARRAY_CAF_TOKEN (caf_type);
    1876              :                 }
    1877              :             }
    1878              : 
    1879          313 :           if (coarray_dealloc_mode == GFC_CAF_COARRAY_ANALYZE)
    1880              :             {
    1881            4 :               bool comp_ref;
    1882            4 :               if (expr && !gfc_caf_attr (expr, false, &comp_ref).coarray_comp
    1883            4 :                   && comp_ref)
    1884            0 :                 caf_dereg_type = GFC_CAF_COARRAY_DEALLOCATE_ONLY;
    1885              :               // else do a deregister as set by default.
    1886              :             }
    1887              :           else
    1888              :             caf_dereg_type = (enum gfc_coarray_deregtype) coarray_dealloc_mode;
    1889              :         }
    1890          162 :       else if (flag_coarray == GFC_FCOARRAY_SINGLE
    1891          162 :                && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
    1892          162 :         pointer = gfc_conv_descriptor_data_get (pointer);
    1893              :     }
    1894        22967 :   else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
    1895              :     {
    1896        18549 :       descr = pointer;
    1897        18549 :       pointer = gfc_conv_descriptor_data_get (pointer);
    1898              :     }
    1899              : 
    1900        23442 :   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pointer,
    1901        23442 :                           build_int_cst (TREE_TYPE (pointer), 0));
    1902              : 
    1903              :   /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
    1904              :      we emit a runtime error.  */
    1905        23442 :   gfc_start_block (&null);
    1906        23442 :   if (!can_fail)
    1907              :     {
    1908         7890 :       tree varname;
    1909              : 
    1910         7890 :       gcc_assert (expr && expr->expr_type == EXPR_VARIABLE && expr->symtree);
    1911              : 
    1912         7890 :       varname = gfc_build_cstring_const (expr->symtree->name);
    1913         7890 :       varname = gfc_build_addr_expr (pchar_type_node, varname);
    1914              : 
    1915         7890 :       error = gfc_trans_runtime_error (true, &expr->where,
    1916              :                                        "Attempt to DEALLOCATE unallocated '%s'",
    1917              :                                        varname);
    1918              :     }
    1919              :   else
    1920        15552 :     error = build_empty_stmt (input_location);
    1921              : 
    1922        23442 :   if (status != NULL_TREE && !integer_zerop (status))
    1923              :     {
    1924         2012 :       tree cond2;
    1925              : 
    1926         2012 :       status_type = TREE_TYPE (TREE_TYPE (status));
    1927         2012 :       cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1928         2012 :                                status, build_int_cst (TREE_TYPE (status), 0));
    1929         2012 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
    1930              :                              fold_build1_loc (input_location, INDIRECT_REF,
    1931              :                                               status_type, status),
    1932         4024 :                              build_int_cst (status_type, unalloc_ok ? 0 : 1));
    1933         2012 :       error = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1934              :                                cond2, tmp, error);
    1935              :     }
    1936              : 
    1937        23442 :   gfc_add_expr_to_block (&null, error);
    1938              : 
    1939              :   /* When POINTER is not NULL, we free it.  */
    1940        23442 :   gfc_start_block (&non_null);
    1941        23442 :   if (add_when_allocated)
    1942         5610 :     gfc_add_expr_to_block (&non_null, add_when_allocated);
    1943        23442 :   gfc_add_finalizer_call (&non_null, expr, class_container);
    1944        23442 :   if (coarray_dealloc_mode == GFC_CAF_COARRAY_NOCOARRAY
    1945          475 :       || flag_coarray != GFC_FCOARRAY_LIB)
    1946              :     {
    1947        23129 :       tmp = build_call_expr_loc (input_location,
    1948              :                                  builtin_decl_explicit (BUILT_IN_FREE), 1,
    1949              :                                  fold_convert (pvoid_type_node, pointer));
    1950        23129 :       if (flag_openmp_allocators && coarray_dealloc_mode < GFC_CAF_COARRAY_ANALYZE)
    1951              :         {
    1952           61 :           tree cond, omp_tmp;
    1953           61 :           if (descr)
    1954           46 :             cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
    1955              :                                     gfc_conv_descriptor_version_get (descr),
    1956              :                                     integer_one_node);
    1957              :           else
    1958           15 :             cond = gfc_omp_call_is_alloc (pointer);
    1959           61 :           omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
    1960           61 :           omp_tmp = build_call_expr_loc (input_location, omp_tmp, 2, pointer,
    1961              :                                          build_zero_cst (ptr_type_node));
    1962           61 :           tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
    1963              :                             omp_tmp, tmp);
    1964              :         }
    1965        23129 :       gfc_add_expr_to_block (&non_null, tmp);
    1966        23129 :       gfc_add_modify (&non_null, pointer, build_int_cst (TREE_TYPE (pointer),
    1967              :                                                          0));
    1968        23129 :       if (flag_openmp_allocators && descr)
    1969           46 :         gfc_conv_descriptor_version_set (&non_null, descr, integer_zero_node);
    1970              : 
    1971        23129 :       if (status != NULL_TREE && !integer_zerop (status))
    1972              :         {
    1973              :           /* We set STATUS to zero if it is present.  */
    1974         1992 :           tree status_type = TREE_TYPE (TREE_TYPE (status));
    1975         1992 :           tree cond2;
    1976              : 
    1977         1992 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    1978              :                                    status,
    1979         1992 :                                    build_int_cst (TREE_TYPE (status), 0));
    1980         1992 :           tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
    1981              :                                  fold_build1_loc (input_location, INDIRECT_REF,
    1982              :                                                   status_type, status),
    1983              :                                  build_int_cst (status_type, 0));
    1984         1992 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    1985              :                                  gfc_unlikely (cond2, PRED_FORTRAN_FAIL_ALLOC),
    1986              :                                  tmp, build_empty_stmt (input_location));
    1987         1992 :           gfc_add_expr_to_block (&non_null, tmp);
    1988              :         }
    1989              :     }
    1990              :   else
    1991              :     {
    1992          313 :       tree cond2, pstat = null_pointer_node;
    1993              : 
    1994          313 :       if (errmsg == NULL_TREE)
    1995              :         {
    1996          301 :           gcc_assert (errlen == NULL_TREE);
    1997          301 :           errmsg = null_pointer_node;
    1998          301 :           errlen = integer_zero_node;
    1999              :         }
    2000              :       else
    2001              :         {
    2002           12 :           gcc_assert (errlen != NULL_TREE);
    2003           12 :           if (!POINTER_TYPE_P (TREE_TYPE (errmsg)))
    2004            0 :             errmsg = gfc_build_addr_expr (NULL_TREE, errmsg);
    2005              :         }
    2006              : 
    2007          313 :       if (status != NULL_TREE && !integer_zerop (status))
    2008              :         {
    2009           20 :           gcc_assert (status_type == integer_type_node);
    2010              :           pstat = status;
    2011              :         }
    2012              : 
    2013          313 :       token = gfc_build_addr_expr  (NULL_TREE, token);
    2014          313 :       gcc_assert (caf_dereg_type > GFC_CAF_COARRAY_ANALYZE);
    2015          313 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_deregister, 5,
    2016              :                                  token,
    2017              :                                  build_int_cst (integer_type_node,
    2018          313 :                                                 caf_dereg_type),
    2019              :                                  pstat, errmsg, errlen);
    2020          313 :       gfc_add_expr_to_block (&non_null, tmp);
    2021              : 
    2022              :       /* It guarantees memory consistency within the same segment */
    2023          313 :       tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
    2024          313 :       tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    2025              :                         gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    2026              :                         tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    2027          313 :       ASM_VOLATILE_P (tmp) = 1;
    2028          313 :       gfc_add_expr_to_block (&non_null, tmp);
    2029              : 
    2030          313 :       if (status != NULL_TREE && !integer_zerop (status))
    2031              :         {
    2032           20 :           tree stat = build_fold_indirect_ref_loc (input_location, status);
    2033           20 :           tree nullify = fold_build2_loc (input_location, MODIFY_EXPR,
    2034              :                                           void_type_node, pointer,
    2035           20 :                                           build_int_cst (TREE_TYPE (pointer),
    2036              :                                                          0));
    2037              : 
    2038           20 :           TREE_USED (label_finish) = 1;
    2039           20 :           tmp = build1_v (GOTO_EXPR, label_finish);
    2040           20 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    2041           20 :                                    stat, build_zero_cst (TREE_TYPE (stat)));
    2042           20 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    2043              :                                  gfc_unlikely (cond2, PRED_FORTRAN_REALLOC),
    2044              :                                  tmp, nullify);
    2045           20 :           gfc_add_expr_to_block (&non_null, tmp);
    2046              :         }
    2047              :       else
    2048          293 :         gfc_add_modify (&non_null, pointer, build_int_cst (TREE_TYPE (pointer),
    2049              :                                                            0));
    2050              :     }
    2051              : 
    2052        23442 :   return fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    2053              :                           gfc_finish_block (&null),
    2054        23442 :                           gfc_finish_block (&non_null));
    2055              : }
    2056              : 
    2057              : 
    2058              : /* Generate code for deallocation of allocatable scalars (variables or
    2059              :    components). Before the object itself is freed, any allocatable
    2060              :    subcomponents are being deallocated.  */
    2061              : 
    2062              : tree
    2063         5417 : gfc_deallocate_scalar_with_status (tree pointer, tree status, tree label_finish,
    2064              :                                    bool can_fail, gfc_expr *expr,
    2065              :                                    gfc_typespec ts, tree class_container,
    2066              :                                    bool coarray, bool unalloc_ok, tree errmsg,
    2067              :                                    tree errmsg_len)
    2068              : {
    2069         5417 :   stmtblock_t null, non_null;
    2070         5417 :   tree cond, tmp, error;
    2071         5417 :   bool finalizable, comp_ref;
    2072         5417 :   gfc_coarray_deregtype caf_dereg_type = GFC_CAF_COARRAY_DEREGISTER;
    2073              : 
    2074         5417 :   if (coarray && expr && !gfc_caf_attr (expr, false, &comp_ref).coarray_comp
    2075         5460 :       && comp_ref)
    2076           43 :     caf_dereg_type = GFC_CAF_COARRAY_DEALLOCATE_ONLY;
    2077              : 
    2078         5417 :   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pointer,
    2079         5417 :                           build_int_cst (TREE_TYPE (pointer), 0));
    2080              : 
    2081              :   /* When POINTER is NULL, we set STATUS to 1 if it's present, otherwise
    2082              :      we emit a runtime error.  */
    2083         5417 :   gfc_start_block (&null);
    2084         5417 :   if (!can_fail)
    2085              :     {
    2086         3484 :       tree varname;
    2087              : 
    2088         3484 :       gcc_assert (expr && expr->expr_type == EXPR_VARIABLE && expr->symtree);
    2089              : 
    2090         3484 :       varname = gfc_build_cstring_const (expr->symtree->name);
    2091         3484 :       varname = gfc_build_addr_expr (pchar_type_node, varname);
    2092              : 
    2093         3484 :       error = gfc_trans_runtime_error (true, &expr->where,
    2094              :                                        "Attempt to DEALLOCATE unallocated '%s'",
    2095              :                                        varname);
    2096              :     }
    2097              :   else
    2098         1933 :     error = build_empty_stmt (input_location);
    2099              : 
    2100         5417 :   if (status != NULL_TREE && !integer_zerop (status))
    2101              :     {
    2102          820 :       tree status_type = TREE_TYPE (TREE_TYPE (status));
    2103          820 :       tree cond2;
    2104              : 
    2105          820 :       cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    2106          820 :                                status, build_int_cst (TREE_TYPE (status), 0));
    2107          820 :       tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
    2108              :                              fold_build1_loc (input_location, INDIRECT_REF,
    2109              :                                               status_type, status),
    2110         1640 :                              build_int_cst (status_type, unalloc_ok ? 0 : 1));
    2111          820 :       error = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    2112              :                                cond2, tmp, error);
    2113              :     }
    2114         5417 :   gfc_add_expr_to_block (&null, error);
    2115              : 
    2116              :   /* When POINTER is not NULL, we free it.  */
    2117         5417 :   gfc_start_block (&non_null);
    2118              : 
    2119              :   /* Free allocatable components.  */
    2120         5417 :   finalizable = gfc_add_finalizer_call (&non_null, expr, class_container);
    2121         5417 :   if (!finalizable && ts.type == BT_DERIVED && ts.u.derived->attr.alloc_comp)
    2122              :     {
    2123            0 :       int caf_mode = coarray
    2124          566 :           ? ((caf_dereg_type == GFC_CAF_COARRAY_DEALLOCATE_ONLY
    2125              :               ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0)
    2126              :              | GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
    2127            4 :              | GFC_STRUCTURE_CAF_MODE_IN_COARRAY)
    2128              :           : 0;
    2129            4 :       if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
    2130            0 :         tmp = gfc_conv_descriptor_data_get (pointer);
    2131              :       else
    2132          566 :         tmp = build_fold_indirect_ref_loc (input_location, pointer);
    2133          566 :       tmp = gfc_deallocate_alloc_comp (ts.u.derived, tmp, 0, caf_mode);
    2134          566 :       gfc_add_expr_to_block (&non_null, tmp);
    2135              :     }
    2136              : 
    2137         5417 :   if (!coarray || flag_coarray == GFC_FCOARRAY_SINGLE)
    2138              :     {
    2139         5377 :       tmp = build_call_expr_loc (input_location,
    2140              :                                  builtin_decl_explicit (BUILT_IN_FREE), 1,
    2141              :                                  fold_convert (pvoid_type_node, pointer));
    2142         5377 :       if (flag_openmp_allocators)
    2143              :         {
    2144           31 :           tree cond, omp_tmp;
    2145           31 :           cond = gfc_omp_call_is_alloc (pointer);
    2146           31 :           omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
    2147           31 :           omp_tmp = build_call_expr_loc (input_location, omp_tmp, 2, pointer,
    2148              :                                          build_zero_cst (ptr_type_node));
    2149           31 :           tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
    2150              :                             omp_tmp, tmp);
    2151              :         }
    2152         5377 :       gfc_add_expr_to_block (&non_null, tmp);
    2153              : 
    2154         5377 :       if (status != NULL_TREE && !integer_zerop (status))
    2155              :         {
    2156              :           /* We set STATUS to zero if it is present.  */
    2157          820 :           tree status_type = TREE_TYPE (TREE_TYPE (status));
    2158          820 :           tree cond2;
    2159              : 
    2160          820 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    2161              :                                    status,
    2162          820 :                                    build_int_cst (TREE_TYPE (status), 0));
    2163          820 :           tmp = fold_build2_loc (input_location, MODIFY_EXPR, status_type,
    2164              :                                  fold_build1_loc (input_location, INDIRECT_REF,
    2165              :                                                   status_type, status),
    2166              :                                  build_int_cst (status_type, 0));
    2167          820 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    2168              :                                  cond2, tmp, build_empty_stmt (input_location));
    2169          820 :           gfc_add_expr_to_block (&non_null, tmp);
    2170              :         }
    2171              :     }
    2172              :   else
    2173              :     {
    2174           40 :       tree token;
    2175           40 :       tree pstat = null_pointer_node, perrmsg = null_pointer_node,
    2176           40 :            perrlen = size_zero_node;
    2177           40 :       gfc_se se;
    2178              : 
    2179           40 :       gfc_init_se (&se, NULL);
    2180           40 :       token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&se, expr);
    2181           40 :       gcc_assert (token != NULL_TREE);
    2182              : 
    2183           40 :       if (status != NULL_TREE && !integer_zerop (status))
    2184              :         {
    2185            0 :           gcc_assert (TREE_TYPE (TREE_TYPE (status)) == integer_type_node);
    2186              :           pstat = status;
    2187              :         }
    2188              : 
    2189           40 :       if (errmsg != NULL_TREE)
    2190              :         {
    2191            0 :           perrmsg = errmsg;
    2192            0 :           perrlen = errmsg_len;
    2193              :         }
    2194              : 
    2195           40 :       tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_deregister, 5,
    2196              :                                  token,
    2197              :                                  build_int_cst (integer_type_node,
    2198           40 :                                                 caf_dereg_type),
    2199              :                                  pstat, perrmsg, perrlen);
    2200           40 :       gfc_add_expr_to_block (&non_null, tmp);
    2201              : 
    2202              :       /* It guarantees memory consistency within the same segment.  */
    2203           40 :       tmp = gfc_build_string_const (strlen ("memory")+1, "memory");
    2204           40 :       tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
    2205              :                         gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
    2206              :                         tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
    2207           40 :       ASM_VOLATILE_P (tmp) = 1;
    2208           40 :       gfc_add_expr_to_block (&non_null, tmp);
    2209              : 
    2210           40 :       if (status != NULL_TREE)
    2211              :         {
    2212            0 :           tree stat = build_fold_indirect_ref_loc (input_location, status);
    2213            0 :           tree cond2;
    2214              : 
    2215            0 :           TREE_USED (label_finish) = 1;
    2216            0 :           tmp = build1_v (GOTO_EXPR, label_finish);
    2217            0 :           cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
    2218            0 :                                    stat, build_zero_cst (TREE_TYPE (stat)));
    2219            0 :           tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    2220              :                                  gfc_unlikely (cond2, PRED_FORTRAN_REALLOC),
    2221              :                                  tmp, build_empty_stmt (input_location));
    2222            0 :           gfc_add_expr_to_block (&non_null, tmp);
    2223              :         }
    2224              :     }
    2225              : 
    2226         5417 :   return fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
    2227              :                           gfc_finish_block (&null),
    2228         5417 :                           gfc_finish_block (&non_null));
    2229              : }
    2230              : 
    2231              : /* Reallocate MEM so it has SIZE bytes of data.  This behaves like the
    2232              :    following pseudo-code:
    2233              : 
    2234              : void *
    2235              : internal_realloc (void *mem, size_t size)
    2236              : {
    2237              :   res = realloc (mem, size);
    2238              :   if (!res && size != 0)
    2239              :     _gfortran_os_error ("Allocation would exceed memory limit");
    2240              : 
    2241              :   return res;
    2242              : }  */
    2243              : tree
    2244         1241 : gfc_call_realloc (stmtblock_t * block, tree mem, tree size)
    2245              : {
    2246         1241 :   tree res, nonzero, null_result, tmp;
    2247         1241 :   tree type = TREE_TYPE (mem);
    2248              : 
    2249              :   /* Only evaluate the size once.  */
    2250         1241 :   size = save_expr (fold_convert (size_type_node, size));
    2251              : 
    2252              :   /* Create a variable to hold the result.  */
    2253         1241 :   res = gfc_create_var (type, NULL);
    2254              : 
    2255              :   /* Call realloc and check the result.  */
    2256         1241 :   tmp = build_call_expr_loc (input_location,
    2257              :                          builtin_decl_explicit (BUILT_IN_REALLOC), 2,
    2258              :                          fold_convert (pvoid_type_node, mem), size);
    2259         1241 :   gfc_add_modify (block, res, fold_convert (type, tmp));
    2260         1241 :   null_result = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
    2261              :                                  res, build_int_cst (pvoid_type_node, 0));
    2262         1241 :   nonzero = fold_build2_loc (input_location, NE_EXPR, logical_type_node, size,
    2263              :                              build_int_cst (size_type_node, 0));
    2264         1241 :   null_result = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node,
    2265              :                                  null_result, nonzero);
    2266         1241 :   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
    2267              :                          null_result,
    2268              :                          trans_os_error_at (NULL,
    2269              :                                             "Error reallocating to %lu bytes",
    2270              :                                             fold_convert
    2271              :                                             (long_unsigned_type_node, size)),
    2272              :                          build_empty_stmt (input_location));
    2273         1241 :   gfc_add_expr_to_block (block, tmp);
    2274              : 
    2275         1241 :   return res;
    2276              : }
    2277              : 
    2278              : 
    2279              : /* Add an expression to another one, either at the front or the back.  */
    2280              : 
    2281              : static void
    2282     19974770 : add_expr_to_chain (tree* chain, tree expr, bool front)
    2283              : {
    2284     19974770 :   if (expr == NULL_TREE || IS_EMPTY_STMT (expr))
    2285              :     return;
    2286              : 
    2287     10235082 :   if (*chain)
    2288              :     {
    2289      5487458 :       if (TREE_CODE (*chain) != STATEMENT_LIST)
    2290              :         {
    2291      1569310 :           tree tmp;
    2292              : 
    2293      1569310 :           tmp = *chain;
    2294      1569310 :           *chain = NULL_TREE;
    2295      1569310 :           append_to_statement_list (tmp, chain);
    2296              :         }
    2297              : 
    2298      5487458 :       if (front)
    2299              :         {
    2300        29167 :           tree_stmt_iterator i;
    2301              : 
    2302        29167 :           i = tsi_start (*chain);
    2303        29167 :           tsi_link_before (&i, expr, TSI_CONTINUE_LINKING);
    2304              :         }
    2305              :       else
    2306      5458291 :         append_to_statement_list (expr, chain);
    2307              :     }
    2308              :   else
    2309      4747624 :     *chain = expr;
    2310              : }
    2311              : 
    2312              : 
    2313              : /* Add a statement at the end of a block.  */
    2314              : 
    2315              : void
    2316     19107728 : gfc_add_expr_to_block (stmtblock_t * block, tree expr)
    2317              : {
    2318     19107728 :   gcc_assert (block);
    2319     19107728 :   add_expr_to_chain (&block->head, expr, false);
    2320     19107728 : }
    2321              : 
    2322              : 
    2323              : /* Add a statement at the beginning of a block.  */
    2324              : 
    2325              : void
    2326        11877 : gfc_prepend_expr_to_block (stmtblock_t * block, tree expr)
    2327              : {
    2328        11877 :   gcc_assert (block);
    2329        11877 :   add_expr_to_chain (&block->head, expr, true);
    2330        11877 : }
    2331              : 
    2332              : 
    2333              : /* Add a block the end of a block.  */
    2334              : 
    2335              : void
    2336      9629608 : gfc_add_block_to_block (stmtblock_t * block, stmtblock_t * append)
    2337              : {
    2338      9629608 :   gcc_assert (append);
    2339      9629608 :   gcc_assert (!append->has_scope);
    2340              : 
    2341      9629608 :   gfc_add_expr_to_block (block, append->head);
    2342      9629608 :   append->head = NULL_TREE;
    2343      9629608 : }
    2344              : 
    2345              : 
    2346              : /* Translate an executable statement. The tree cond is used by gfc_trans_do.
    2347              :    This static function is wrapped by gfc_trans_code_cond and
    2348              :    gfc_trans_code.  */
    2349              : 
    2350              : static tree
    2351       446388 : trans_code (gfc_code * code, tree cond)
    2352              : {
    2353       446388 :   stmtblock_t block;
    2354       446388 :   tree res;
    2355              : 
    2356       446388 :   if (!code)
    2357         2094 :     return build_empty_stmt (input_location);
    2358              : 
    2359       444294 :   gfc_start_block (&block);
    2360              : 
    2361              :   /* Translate statements one by one into GENERIC trees until we reach
    2362              :      the end of this gfc_code branch.  */
    2363      2073746 :   for (; code; code = code->next)
    2364              :     {
    2365      1185158 :       if (code->here != 0)
    2366              :         {
    2367         3574 :           res = gfc_trans_label_here (code);
    2368         3574 :           gfc_add_expr_to_block (&block, res);
    2369              :         }
    2370              : 
    2371      1185158 :       input_location = gfc_get_location (&code->loc);
    2372              : 
    2373      1185158 :       switch (code->op)
    2374              :         {
    2375              :         case EXEC_NOP:
    2376              :         case EXEC_END_BLOCK:
    2377              :         case EXEC_END_NESTED_BLOCK:
    2378              :         case EXEC_END_PROCEDURE:
    2379              :           res = NULL_TREE;
    2380              :           break;
    2381              : 
    2382       309287 :         case EXEC_ASSIGN:
    2383       309287 :           res = gfc_trans_assign (code);
    2384       309287 :           break;
    2385              : 
    2386          116 :         case EXEC_LABEL_ASSIGN:
    2387          116 :           res = gfc_trans_label_assign (code);
    2388          116 :           break;
    2389              : 
    2390        10307 :         case EXEC_POINTER_ASSIGN:
    2391        10307 :           res = gfc_trans_pointer_assign (code);
    2392        10307 :           break;
    2393              : 
    2394        11827 :         case EXEC_INIT_ASSIGN:
    2395        11827 :           if (code->expr1->ts.type == BT_CLASS)
    2396          430 :             res = gfc_trans_class_init_assign (code);
    2397              :           else
    2398        11397 :             res = gfc_trans_init_assign (code);
    2399              :           break;
    2400              : 
    2401              :         case EXEC_CONTINUE:
    2402              :           res = NULL_TREE;
    2403              :           break;
    2404              : 
    2405           37 :         case EXEC_CRITICAL:
    2406           37 :           res = gfc_trans_critical (code);
    2407           37 :           break;
    2408              : 
    2409          123 :         case EXEC_CYCLE:
    2410          123 :           res = gfc_trans_cycle (code);
    2411          123 :           break;
    2412              : 
    2413          708 :         case EXEC_EXIT:
    2414          708 :           res = gfc_trans_exit (code);
    2415          708 :           break;
    2416              : 
    2417         1242 :         case EXEC_GOTO:
    2418         1242 :           res = gfc_trans_goto (code);
    2419         1242 :           break;
    2420              : 
    2421         1412 :         case EXEC_ENTRY:
    2422         1412 :           res = gfc_trans_entry (code);
    2423         1412 :           break;
    2424              : 
    2425           30 :         case EXEC_PAUSE:
    2426           30 :           res = gfc_trans_pause (code);
    2427           30 :           break;
    2428              : 
    2429       220925 :         case EXEC_STOP:
    2430       220925 :         case EXEC_ERROR_STOP:
    2431       220925 :           res = gfc_trans_stop (code, code->op == EXEC_ERROR_STOP);
    2432       220925 :           break;
    2433              : 
    2434        84365 :         case EXEC_CALL:
    2435              :           /* For MVBITS we've got the special exception that we need a
    2436              :              dependency check, too.  */
    2437        84365 :           {
    2438        84365 :             bool is_mvbits = false;
    2439              : 
    2440        84365 :             if (code->resolved_isym)
    2441              :               {
    2442         7010 :                 res = gfc_conv_intrinsic_subroutine (code);
    2443         7010 :                 if (res != NULL_TREE)
    2444              :                   break;
    2445              :               }
    2446              : 
    2447        79208 :             if (code->resolved_isym
    2448         1853 :                 && code->resolved_isym->id == GFC_ISYM_MVBITS)
    2449        79208 :               is_mvbits = true;
    2450              : 
    2451        79208 :             res = gfc_trans_call (code, is_mvbits, NULL_TREE,
    2452              :                                   NULL_TREE, false);
    2453              :           }
    2454        79208 :           break;
    2455              : 
    2456          115 :         case EXEC_CALL_PPC:
    2457          115 :           res = gfc_trans_call (code, false, NULL_TREE,
    2458              :                                 NULL_TREE, false);
    2459          115 :           break;
    2460              : 
    2461          863 :         case EXEC_ASSIGN_CALL:
    2462              :           /* Record that an assignment call is being processed, to
    2463              :              ensure finalization occurs in gfc_finalize_tree_expr */
    2464          863 :           is_assign_call = 1;
    2465          863 :           res = gfc_trans_call (code, true, NULL_TREE,
    2466              :                                 NULL_TREE, false);
    2467          863 :           is_assign_call = 0;
    2468          863 :           break;
    2469              : 
    2470         3205 :         case EXEC_RETURN:
    2471         3205 :           res = gfc_trans_return (code);
    2472         3205 :           break;
    2473              : 
    2474       242926 :         case EXEC_IF:
    2475       242926 :           res = gfc_trans_if (code);
    2476       242926 :           break;
    2477              : 
    2478           64 :         case EXEC_ARITHMETIC_IF:
    2479           64 :           res = gfc_trans_arithmetic_if (code);
    2480           64 :           break;
    2481              : 
    2482        14503 :         case EXEC_BLOCK:
    2483        14503 :           res = gfc_trans_block_construct (code);
    2484        14503 :           break;
    2485              : 
    2486        28686 :         case EXEC_DO:
    2487        28686 :           res = gfc_trans_do (code, cond);
    2488        28686 :           break;
    2489              : 
    2490          214 :         case EXEC_DO_CONCURRENT:
    2491          214 :           res = gfc_trans_do_concurrent (code);
    2492          214 :           break;
    2493              : 
    2494          508 :         case EXEC_DO_WHILE:
    2495          508 :           res = gfc_trans_do_while (code);
    2496          508 :           break;
    2497              : 
    2498         1108 :         case EXEC_SELECT:
    2499         1108 :           res = gfc_trans_select (code);
    2500         1108 :           break;
    2501              : 
    2502         3052 :         case EXEC_SELECT_TYPE:
    2503         3052 :           res = gfc_trans_select_type (code);
    2504         3052 :           break;
    2505              : 
    2506         1031 :         case EXEC_SELECT_RANK:
    2507         1031 :           res = gfc_trans_select_rank (code);
    2508         1031 :           break;
    2509              : 
    2510           78 :         case EXEC_FLUSH:
    2511           78 :           res = gfc_trans_flush (code);
    2512           78 :           break;
    2513              : 
    2514         1363 :         case EXEC_SYNC_ALL:
    2515         1363 :         case EXEC_SYNC_IMAGES:
    2516         1363 :         case EXEC_SYNC_MEMORY:
    2517         1363 :           res = gfc_trans_sync (code, code->op);
    2518         1363 :           break;
    2519              : 
    2520          126 :         case EXEC_LOCK:
    2521          126 :         case EXEC_UNLOCK:
    2522          126 :           res = gfc_trans_lock_unlock (code, code->op);
    2523          126 :           break;
    2524              : 
    2525           58 :         case EXEC_EVENT_POST:
    2526           58 :         case EXEC_EVENT_WAIT:
    2527           58 :           res = gfc_trans_event_post_wait (code, code->op);
    2528           58 :           break;
    2529              : 
    2530           16 :         case EXEC_FAIL_IMAGE:
    2531           16 :           res = gfc_trans_fail_image (code);
    2532           16 :           break;
    2533              : 
    2534         1866 :         case EXEC_FORALL:
    2535         1866 :           res = gfc_trans_forall (code);
    2536         1866 :           break;
    2537              : 
    2538          148 :         case EXEC_FORM_TEAM:
    2539          148 :           res = gfc_trans_form_team (code);
    2540          148 :           break;
    2541              : 
    2542           88 :         case EXEC_CHANGE_TEAM:
    2543           88 :           res = gfc_trans_change_team (code);
    2544           88 :           break;
    2545              : 
    2546           63 :         case EXEC_END_TEAM:
    2547           63 :           res = gfc_trans_end_team (code);
    2548           63 :           break;
    2549              : 
    2550           34 :         case EXEC_SYNC_TEAM:
    2551           34 :           res = gfc_trans_sync_team (code);
    2552           34 :           break;
    2553              : 
    2554          330 :         case EXEC_WHERE:
    2555          330 :           res = gfc_trans_where (code);
    2556          330 :           break;
    2557              : 
    2558        14624 :         case EXEC_ALLOCATE:
    2559        14624 :           res = gfc_trans_allocate (code, NULL);
    2560        14624 :           break;
    2561              : 
    2562         9147 :         case EXEC_DEALLOCATE:
    2563         9147 :           res = gfc_trans_deallocate (code);
    2564         9147 :           break;
    2565              : 
    2566         3618 :         case EXEC_OPEN:
    2567         3618 :           res = gfc_trans_open (code);
    2568         3618 :           break;
    2569              : 
    2570         3098 :         case EXEC_CLOSE:
    2571         3098 :           res = gfc_trans_close (code);
    2572         3098 :           break;
    2573              : 
    2574         6411 :         case EXEC_READ:
    2575         6411 :           res = gfc_trans_read (code);
    2576         6411 :           break;
    2577              : 
    2578        25525 :         case EXEC_WRITE:
    2579        25525 :           res = gfc_trans_write (code);
    2580        25525 :           break;
    2581              : 
    2582           84 :         case EXEC_IOLENGTH:
    2583           84 :           res = gfc_trans_iolength (code);
    2584           84 :           break;
    2585              : 
    2586          389 :         case EXEC_BACKSPACE:
    2587          389 :           res = gfc_trans_backspace (code);
    2588          389 :           break;
    2589              : 
    2590           56 :         case EXEC_ENDFILE:
    2591           56 :           res = gfc_trans_endfile (code);
    2592           56 :           break;
    2593              : 
    2594          780 :         case EXEC_INQUIRE:
    2595          780 :           res = gfc_trans_inquire (code);
    2596          780 :           break;
    2597              : 
    2598           74 :         case EXEC_WAIT:
    2599           74 :           res = gfc_trans_wait (code);
    2600           74 :           break;
    2601              : 
    2602         2264 :         case EXEC_REWIND:
    2603         2264 :           res = gfc_trans_rewind (code);
    2604         2264 :           break;
    2605              : 
    2606        45913 :         case EXEC_TRANSFER:
    2607        45913 :           res = gfc_trans_transfer (code);
    2608        45913 :           break;
    2609              : 
    2610        32020 :         case EXEC_DT_END:
    2611        32020 :           res = gfc_trans_dt_end (code);
    2612        32020 :           break;
    2613              : 
    2614        19464 :         case EXEC_OMP_ALLOCATE:
    2615        19464 :         case EXEC_OMP_ALLOCATORS:
    2616        19464 :         case EXEC_OMP_ASSUME:
    2617        19464 :         case EXEC_OMP_ATOMIC:
    2618        19464 :         case EXEC_OMP_BARRIER:
    2619        19464 :         case EXEC_OMP_CANCEL:
    2620        19464 :         case EXEC_OMP_CANCELLATION_POINT:
    2621        19464 :         case EXEC_OMP_CRITICAL:
    2622        19464 :         case EXEC_OMP_DEPOBJ:
    2623        19464 :         case EXEC_OMP_DISPATCH:
    2624        19464 :         case EXEC_OMP_DISTRIBUTE:
    2625        19464 :         case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
    2626        19464 :         case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
    2627        19464 :         case EXEC_OMP_DISTRIBUTE_SIMD:
    2628        19464 :         case EXEC_OMP_DO:
    2629        19464 :         case EXEC_OMP_DO_SIMD:
    2630        19464 :         case EXEC_OMP_ERROR:
    2631        19464 :         case EXEC_OMP_FLUSH:
    2632        19464 :         case EXEC_OMP_INTEROP:
    2633        19464 :         case EXEC_OMP_LOOP:
    2634        19464 :         case EXEC_OMP_MASKED:
    2635        19464 :         case EXEC_OMP_MASKED_TASKLOOP:
    2636        19464 :         case EXEC_OMP_MASKED_TASKLOOP_SIMD:
    2637        19464 :         case EXEC_OMP_MASTER:
    2638        19464 :         case EXEC_OMP_MASTER_TASKLOOP:
    2639        19464 :         case EXEC_OMP_MASTER_TASKLOOP_SIMD:
    2640        19464 :         case EXEC_OMP_METADIRECTIVE:
    2641        19464 :         case EXEC_OMP_ORDERED:
    2642        19464 :         case EXEC_OMP_PARALLEL:
    2643        19464 :         case EXEC_OMP_PARALLEL_DO:
    2644        19464 :         case EXEC_OMP_PARALLEL_DO_SIMD:
    2645        19464 :         case EXEC_OMP_PARALLEL_LOOP:
    2646        19464 :         case EXEC_OMP_PARALLEL_MASKED:
    2647        19464 :         case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
    2648        19464 :         case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
    2649        19464 :         case EXEC_OMP_PARALLEL_MASTER:
    2650        19464 :         case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
    2651        19464 :         case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
    2652        19464 :         case EXEC_OMP_PARALLEL_SECTIONS:
    2653        19464 :         case EXEC_OMP_PARALLEL_WORKSHARE:
    2654        19464 :         case EXEC_OMP_SCOPE:
    2655        19464 :         case EXEC_OMP_SECTIONS:
    2656        19464 :         case EXEC_OMP_SIMD:
    2657        19464 :         case EXEC_OMP_SINGLE:
    2658        19464 :         case EXEC_OMP_TARGET:
    2659        19464 :         case EXEC_OMP_TARGET_DATA:
    2660        19464 :         case EXEC_OMP_TARGET_ENTER_DATA:
    2661        19464 :         case EXEC_OMP_TARGET_EXIT_DATA:
    2662        19464 :         case EXEC_OMP_TARGET_PARALLEL:
    2663        19464 :         case EXEC_OMP_TARGET_PARALLEL_DO:
    2664        19464 :         case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
    2665        19464 :         case EXEC_OMP_TARGET_PARALLEL_LOOP:
    2666        19464 :         case EXEC_OMP_TARGET_SIMD:
    2667        19464 :         case EXEC_OMP_TARGET_TEAMS:
    2668        19464 :         case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
    2669        19464 :         case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
    2670        19464 :         case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    2671        19464 :         case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
    2672        19464 :         case EXEC_OMP_TARGET_TEAMS_LOOP:
    2673        19464 :         case EXEC_OMP_TARGET_UPDATE:
    2674        19464 :         case EXEC_OMP_TASK:
    2675        19464 :         case EXEC_OMP_TASKGROUP:
    2676        19464 :         case EXEC_OMP_TASKLOOP:
    2677        19464 :         case EXEC_OMP_TASKLOOP_SIMD:
    2678        19464 :         case EXEC_OMP_TASKWAIT:
    2679        19464 :         case EXEC_OMP_TASKYIELD:
    2680        19464 :         case EXEC_OMP_TEAMS:
    2681        19464 :         case EXEC_OMP_TEAMS_DISTRIBUTE:
    2682        19464 :         case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
    2683        19464 :         case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
    2684        19464 :         case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
    2685        19464 :         case EXEC_OMP_TEAMS_LOOP:
    2686        19464 :         case EXEC_OMP_TILE:
    2687        19464 :         case EXEC_OMP_UNROLL:
    2688        19464 :         case EXEC_OMP_WORKSHARE:
    2689        19464 :           res = gfc_trans_omp_directive (code);
    2690        19464 :           break;
    2691              : 
    2692        12412 :         case EXEC_OACC_CACHE:
    2693        12412 :         case EXEC_OACC_WAIT:
    2694        12412 :         case EXEC_OACC_UPDATE:
    2695        12412 :         case EXEC_OACC_LOOP:
    2696        12412 :         case EXEC_OACC_HOST_DATA:
    2697        12412 :         case EXEC_OACC_DATA:
    2698        12412 :         case EXEC_OACC_KERNELS:
    2699        12412 :         case EXEC_OACC_KERNELS_LOOP:
    2700        12412 :         case EXEC_OACC_PARALLEL:
    2701        12412 :         case EXEC_OACC_PARALLEL_LOOP:
    2702        12412 :         case EXEC_OACC_SERIAL:
    2703        12412 :         case EXEC_OACC_SERIAL_LOOP:
    2704        12412 :         case EXEC_OACC_ENTER_DATA:
    2705        12412 :         case EXEC_OACC_EXIT_DATA:
    2706        12412 :         case EXEC_OACC_ATOMIC:
    2707        12412 :         case EXEC_OACC_DECLARE:
    2708        12412 :         case EXEC_OACC_INIT:
    2709        12412 :         case EXEC_OACC_SHUTDOWN:
    2710        12412 :         case EXEC_OACC_SET:
    2711        12412 :           res = gfc_trans_oacc_directive (code);
    2712        12412 :           break;
    2713              : 
    2714            0 :         default:
    2715            0 :           gfc_internal_error ("gfc_trans_code(): Bad statement code");
    2716              :         }
    2717              : 
    2718      1185158 :       input_location = gfc_get_location (&code->loc);
    2719              : 
    2720      1185158 :       if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
    2721              :         {
    2722              :           /* Don't try to set location for trees that don't have one,
    2723              :              e.g. STATEMENT_LIST or error_mark_node.  */
    2724      1116004 :           if (EXPR_P (res))
    2725       830203 :             SET_EXPR_LOCATION (res, input_location);
    2726              : 
    2727              :           /* Add the new statement to the block.  */
    2728      1116004 :           gfc_add_expr_to_block (&block, res);
    2729              :         }
    2730              :     }
    2731              : 
    2732              :   /* Return the finished block.  */
    2733       444294 :   return gfc_finish_block (&block);
    2734              : }
    2735              : 
    2736              : 
    2737              : /* Translate an executable statement with condition, cond.  The condition is
    2738              :    used by gfc_trans_do to test for IO result conditions inside implied
    2739              :    DO loops of READ and WRITE statements.  See build_dt in trans-io.cc.  */
    2740              : 
    2741              : tree
    2742        60706 : gfc_trans_code_cond (gfc_code * code, tree cond)
    2743              : {
    2744        60706 :   return trans_code (code, cond);
    2745              : }
    2746              : 
    2747              : /* Translate an executable statement without condition.  */
    2748              : 
    2749              : tree
    2750       385682 : gfc_trans_code (gfc_code * code)
    2751              : {
    2752       385682 :   return trans_code (code, NULL_TREE);
    2753              : }
    2754              : 
    2755              : 
    2756              : /* This function is called after a complete program unit has been parsed
    2757              :    and resolved.  */
    2758              : 
    2759              : void
    2760        37130 : gfc_generate_code (gfc_namespace * ns)
    2761              : {
    2762        37130 :   ompws_flags = 0;
    2763        37130 :   if (ns->is_block_data)
    2764              :     {
    2765           72 :       gfc_generate_block_data (ns);
    2766           72 :       return;
    2767              :     }
    2768              : 
    2769        37058 :   gfc_generate_function_code (ns);
    2770              : }
    2771              : 
    2772              : 
    2773              : /* This function is called after a complete module has been parsed
    2774              :    and resolved.  */
    2775              : 
    2776              : void
    2777         9504 : gfc_generate_module_code (gfc_namespace * ns)
    2778              : {
    2779         9504 :   gfc_namespace *n;
    2780         9504 :   struct module_htab_entry *entry;
    2781              : 
    2782         9504 :   gcc_assert (ns->proc_name->backend_decl == NULL);
    2783        19008 :   ns->proc_name->backend_decl
    2784         9504 :     = build_decl (gfc_get_location (&ns->proc_name->declared_at),
    2785              :                   NAMESPACE_DECL, get_identifier (ns->proc_name->name),
    2786              :                   void_type_node);
    2787         9504 :   entry = gfc_find_module (ns->proc_name->name);
    2788         9504 :   if (entry->namespace_decl)
    2789              :     /* Buggy sourcecode, using a module before defining it?  */
    2790            0 :     entry->decls->empty ();
    2791         9504 :   entry->namespace_decl = ns->proc_name->backend_decl;
    2792              : 
    2793         9504 :   gfc_generate_module_vars (ns);
    2794              : 
    2795              :   /* We need to generate all module function prototypes first, to allow
    2796              :      sibling calls.  */
    2797        36437 :   for (n = ns->contained; n; n = n->sibling)
    2798              :     {
    2799        26933 :       gfc_entry_list *el;
    2800              : 
    2801        26933 :       if (!n->proc_name)
    2802            0 :         continue;
    2803              : 
    2804        26933 :       gfc_create_function_decl (n, false);
    2805        26933 :       DECL_CONTEXT (n->proc_name->backend_decl) = ns->proc_name->backend_decl;
    2806        26933 :       gfc_module_add_decl (entry, n->proc_name->backend_decl);
    2807        26933 :       for (el = ns->entries; el; el = el->next)
    2808              :         {
    2809            0 :           DECL_CONTEXT (el->sym->backend_decl) = ns->proc_name->backend_decl;
    2810            0 :           gfc_module_add_decl (entry, el->sym->backend_decl);
    2811              :         }
    2812              :     }
    2813              : 
    2814        36437 :   for (n = ns->contained; n; n = n->sibling)
    2815              :     {
    2816        26933 :       if (!n->proc_name)
    2817            0 :         continue;
    2818              : 
    2819        26933 :       gfc_generate_function_code (n);
    2820              :     }
    2821         9504 : }
    2822              : 
    2823              : 
    2824              : /* Initialize an init/cleanup block with existing code.  */
    2825              : 
    2826              : void
    2827       102357 : gfc_start_wrapped_block (gfc_wrapped_block* block, tree code)
    2828              : {
    2829       102357 :   gcc_assert (block);
    2830              : 
    2831       102357 :   block->init = NULL_TREE;
    2832       102357 :   block->code = code;
    2833       102357 :   block->cleanup = NULL_TREE;
    2834       102357 : }
    2835              : 
    2836              : 
    2837              : /* Add a new pair of initializers/clean-up code.  */
    2838              : 
    2839              : void
    2840       376404 : gfc_add_init_cleanup (gfc_wrapped_block* block, tree init, tree cleanup,
    2841              :                       bool back)
    2842              : {
    2843       376404 :   gcc_assert (block);
    2844              : 
    2845              :   /* The new pair of init/cleanup should be "wrapped around" the existing
    2846              :      block of code, thus the initialization is added to the front and the
    2847              :      cleanup to the back.  */
    2848       376404 :   add_expr_to_chain (&block->init, init, !back);
    2849       376404 :   add_expr_to_chain (&block->cleanup, cleanup, false);
    2850       376404 : }
    2851              : 
    2852              : 
    2853              : /* Finish up a wrapped block by building a corresponding try-finally expr.  */
    2854              : 
    2855              : tree
    2856       102357 : gfc_finish_wrapped_block (gfc_wrapped_block* block)
    2857              : {
    2858       102357 :   tree result;
    2859              : 
    2860       102357 :   gcc_assert (block);
    2861              : 
    2862              :   /* Build the final expression.  For this, just add init and body together,
    2863              :      and put clean-up with that into a TRY_FINALLY_EXPR.  */
    2864       102357 :   result = block->init;
    2865       102357 :   add_expr_to_chain (&result, block->code, false);
    2866       102357 :   if (block->cleanup)
    2867        11030 :     result = build2_loc (input_location, TRY_FINALLY_EXPR, void_type_node,
    2868              :                          result, block->cleanup);
    2869              : 
    2870              :   /* Clear the block.  */
    2871       102357 :   block->init = NULL_TREE;
    2872       102357 :   block->code = NULL_TREE;
    2873       102357 :   block->cleanup = NULL_TREE;
    2874              : 
    2875       102357 :   return result;
    2876              : }
    2877              : 
    2878              : 
    2879              : /* Helper function for marking a boolean expression tree as unlikely.  */
    2880              : 
    2881              : tree
    2882       128141 : gfc_unlikely (tree cond, enum br_predictor predictor)
    2883              : {
    2884       128141 :   tree tmp;
    2885              : 
    2886       128141 :   if (optimize)
    2887              :     {
    2888       109960 :       cond = fold_convert (long_integer_type_node, cond);
    2889       109960 :       tmp = build_zero_cst (long_integer_type_node);
    2890       109960 :       cond = build_call_expr_loc (input_location,
    2891              :                                   builtin_decl_explicit (BUILT_IN_EXPECT),
    2892              :                                   3, cond, tmp,
    2893              :                                   build_int_cst (integer_type_node,
    2894       109960 :                                                  predictor));
    2895              :     }
    2896       128141 :   return cond;
    2897              : }
    2898              : 
    2899              : 
    2900              : /* Helper function for marking a boolean expression tree as likely.  */
    2901              : 
    2902              : tree
    2903         2954 : gfc_likely (tree cond, enum br_predictor predictor)
    2904              : {
    2905         2954 :   tree tmp;
    2906              : 
    2907         2954 :   if (optimize)
    2908              :     {
    2909         2621 :       cond = fold_convert (long_integer_type_node, cond);
    2910         2621 :       tmp = build_one_cst (long_integer_type_node);
    2911         2621 :       cond = build_call_expr_loc (input_location,
    2912              :                                   builtin_decl_explicit (BUILT_IN_EXPECT),
    2913              :                                   3, cond, tmp,
    2914              :                                   build_int_cst (integer_type_node,
    2915         2621 :                                                  predictor));
    2916              :     }
    2917         2954 :   return cond;
    2918              : }
    2919              : 
    2920              : 
    2921              : /* Get the string length for a deferred character length component.  */
    2922              : 
    2923              : bool
    2924       216934 : gfc_deferred_strlen (gfc_component *c, tree *decl)
    2925              : {
    2926       216934 :   char name[GFC_MAX_SYMBOL_LEN+9];
    2927       216934 :   gfc_component *strlen;
    2928       216934 :   if (!(c->ts.type == BT_CHARACTER
    2929        12663 :         && (c->ts.deferred || c->attr.pdt_string)))
    2930              :     return false;
    2931         4989 :   sprintf (name, "_%s_length", c->name);
    2932        15267 :   for (strlen = c; strlen; strlen = strlen->next)
    2933        15256 :     if (strcmp (strlen->name, name) == 0)
    2934              :       break;
    2935         4989 :   *decl = strlen ? strlen->backend_decl : NULL_TREE;
    2936         4989 :   return strlen != NULL;
    2937              : }
        

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.