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

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.