LCOV - code coverage report
Current view: top level - gcc/fortran - trans-io.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.1 % 1258 1221
Test Date: 2026-07-11 15:47:05 Functions: 100.0 % 37 37
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* IO Code translation/library interface
       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              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "tree.h"
      26              : #include "gfortran.h"
      27              : #include "trans.h"
      28              : #include "stringpool.h"
      29              : #include "fold-const.h"
      30              : #include "stor-layout.h"
      31              : #include "trans-stmt.h"
      32              : #include "trans-array.h"
      33              : #include "trans-types.h"
      34              : #include "trans-const.h"
      35              : #include "trans-descriptor.h"
      36              : #include "options.h"
      37              : 
      38              : /* Members of the ioparm structure.  */
      39              : 
      40              : enum ioparam_type
      41              : {
      42              :   IOPARM_ptype_common,
      43              :   IOPARM_ptype_open,
      44              :   IOPARM_ptype_close,
      45              :   IOPARM_ptype_filepos,
      46              :   IOPARM_ptype_inquire,
      47              :   IOPARM_ptype_dt,
      48              :   IOPARM_ptype_wait,
      49              :   IOPARM_ptype_num
      50              : };
      51              : 
      52              : enum iofield_type
      53              : {
      54              :   IOPARM_type_int4,
      55              :   IOPARM_type_intio,
      56              :   IOPARM_type_pint4,
      57              :   IOPARM_type_pintio,
      58              :   IOPARM_type_pchar,
      59              :   IOPARM_type_parray,
      60              :   IOPARM_type_pad,
      61              :   IOPARM_type_char1,
      62              :   IOPARM_type_char2,
      63              :   IOPARM_type_common,
      64              :   IOPARM_type_num
      65              : };
      66              : 
      67              : typedef struct GTY(()) gfc_st_parameter_field {
      68              :   const char *name;
      69              :   unsigned int mask;
      70              :   enum ioparam_type param_type;
      71              :   enum iofield_type type;
      72              :   tree field;
      73              :   tree field_len;
      74              : }
      75              : gfc_st_parameter_field;
      76              : 
      77              : typedef struct GTY(()) gfc_st_parameter {
      78              :   const char *name;
      79              :   tree type;
      80              : }
      81              : gfc_st_parameter;
      82              : 
      83              : enum iofield
      84              : {
      85              : #define IOPARM(param_type, name, mask, type) IOPARM_##param_type##_##name,
      86              : #include "ioparm.def"
      87              : #undef IOPARM
      88              :   IOPARM_field_num
      89              : };
      90              : 
      91              : static GTY(()) gfc_st_parameter st_parameter[] =
      92              : {
      93              :   { "common", NULL },
      94              :   { "open", NULL },
      95              :   { "close", NULL },
      96              :   { "filepos", NULL },
      97              :   { "inquire", NULL },
      98              :   { "dt", NULL },
      99              :   { "wait", NULL }
     100              : };
     101              : 
     102              : static GTY(()) gfc_st_parameter_field st_parameter_field[] =
     103              : {
     104              : #define IOPARM(param_type, name, mask, type) \
     105              :   { #name, mask, IOPARM_ptype_##param_type, IOPARM_type_##type, NULL, NULL },
     106              : #include "ioparm.def"
     107              : #undef IOPARM
     108              :   { NULL, 0, (enum ioparam_type) 0, (enum iofield_type) 0, NULL, NULL }
     109              : };
     110              : 
     111              : /* Library I/O subroutines */
     112              : 
     113              : enum iocall
     114              : {
     115              :   IOCALL_READ,
     116              :   IOCALL_READ_DONE,
     117              :   IOCALL_WRITE,
     118              :   IOCALL_WRITE_DONE,
     119              :   IOCALL_X_INTEGER,
     120              :   IOCALL_X_INTEGER_WRITE,
     121              :   IOCALL_X_UNSIGNED,
     122              :   IOCALL_X_UNSIGNED_WRITE,
     123              :   IOCALL_X_LOGICAL,
     124              :   IOCALL_X_LOGICAL_WRITE,
     125              :   IOCALL_X_CHARACTER,
     126              :   IOCALL_X_CHARACTER_WRITE,
     127              :   IOCALL_X_CHARACTER_WIDE,
     128              :   IOCALL_X_CHARACTER_WIDE_WRITE,
     129              :   IOCALL_X_REAL,
     130              :   IOCALL_X_REAL_WRITE,
     131              :   IOCALL_X_COMPLEX,
     132              :   IOCALL_X_COMPLEX_WRITE,
     133              :   IOCALL_X_REAL128,
     134              :   IOCALL_X_REAL128_WRITE,
     135              :   IOCALL_X_COMPLEX128,
     136              :   IOCALL_X_COMPLEX128_WRITE,
     137              :   IOCALL_X_ARRAY,
     138              :   IOCALL_X_ARRAY_WRITE,
     139              :   IOCALL_X_DERIVED,
     140              :   IOCALL_OPEN,
     141              :   IOCALL_CLOSE,
     142              :   IOCALL_INQUIRE,
     143              :   IOCALL_IOLENGTH,
     144              :   IOCALL_IOLENGTH_DONE,
     145              :   IOCALL_REWIND,
     146              :   IOCALL_BACKSPACE,
     147              :   IOCALL_ENDFILE,
     148              :   IOCALL_FLUSH,
     149              :   IOCALL_SET_NML_VAL,
     150              :   IOCALL_SET_NML_DTIO_VAL,
     151              :   IOCALL_SET_NML_VAL_DIM,
     152              :   IOCALL_WAIT,
     153              :   IOCALL_NUM
     154              : };
     155              : 
     156              : static GTY(()) tree iocall[IOCALL_NUM];
     157              : 
     158              : /* Variable for keeping track of what the last data transfer statement
     159              :    was.  Used for deciding which subroutine to call when the data
     160              :    transfer is complete.  */
     161              : static enum { READ, WRITE, IOLENGTH } last_dt;
     162              : 
     163              : /* The data transfer parameter block that should be shared by all
     164              :    data transfer calls belonging to the same read/write/iolength.  */
     165              : static GTY(()) tree dt_parm;
     166              : static stmtblock_t *dt_post_end_block;
     167              : 
     168              : static void
     169       223041 : gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
     170              : {
     171       223041 :   unsigned int type;
     172       223041 :   gfc_st_parameter_field *p;
     173       223041 :   char name[64];
     174       223041 :   size_t len;
     175       223041 :   tree t = make_node (RECORD_TYPE);
     176       223041 :   tree *chain = NULL;
     177              : 
     178       223041 :   len = strlen (st_parameter[ptype].name);
     179       223041 :   gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
     180       223041 :   memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
     181       223041 :   memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
     182              :           len + 1);
     183       223041 :   TYPE_NAME (t) = get_identifier (name);
     184              : 
     185     19850649 :   for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
     186     19627608 :     if (p->param_type == ptype)
     187      2803944 :       switch (p->type)
     188              :         {
     189       860301 :         case IOPARM_type_int4:
     190       860301 :         case IOPARM_type_intio:
     191       860301 :         case IOPARM_type_pint4:
     192       860301 :         case IOPARM_type_pintio:
     193       860301 :         case IOPARM_type_parray:
     194       860301 :         case IOPARM_type_pchar:
     195       860301 :         case IOPARM_type_pad:
     196       860301 :           p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
     197       860301 :                                               types[p->type], &chain);
     198       860301 :           break;
     199       924027 :         case IOPARM_type_char1:
     200       924027 :           p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
     201              :                                               pchar_type_node, &chain);
     202              :           /* FALLTHROUGH */
     203      1752465 :         case IOPARM_type_char2:
     204      1752465 :           len = strlen (p->name);
     205      1752465 :           gcc_assert (len <= sizeof (name) - sizeof ("_len"));
     206      1752465 :           memcpy (name, p->name, len);
     207      1752465 :           memcpy (name + len, "_len", sizeof ("_len"));
     208      1752465 :           p->field_len = gfc_add_field_to_struct (t, get_identifier (name),
     209              :                                                   gfc_charlen_type_node,
     210              :                                                   &chain);
     211      1752465 :           if (p->type == IOPARM_type_char2)
     212       828438 :             p->field = gfc_add_field_to_struct (t, get_identifier (p->name),
     213              :                                                 pchar_type_node, &chain);
     214              :           break;
     215       191178 :         case IOPARM_type_common:
     216       191178 :           p->field
     217       191178 :             = gfc_add_field_to_struct (t,
     218              :                                        get_identifier (p->name),
     219              :                                        st_parameter[IOPARM_ptype_common].type,
     220              :                                        &chain);
     221       191178 :           break;
     222            0 :         case IOPARM_type_num:
     223            0 :           gcc_unreachable ();
     224              :         }
     225              : 
     226              :   /* -Wpadded warnings on these artificially created structures are not
     227              :      helpful; suppress them. */
     228       223041 :   int save_warn_padded = warn_padded;
     229       223041 :   warn_padded = 0;
     230       223041 :   gfc_finish_type (t);
     231       223041 :   warn_padded = save_warn_padded;
     232       223041 :   st_parameter[ptype].type = t;
     233       223041 : }
     234              : 
     235              : 
     236              : /* Build code to test an error condition and call generate_error if needed.
     237              :    Note: This builds calls to generate_error in the runtime library function.
     238              :    The function generate_error is dependent on certain parameters in the
     239              :    st_parameter_common flags to be set. (See libgfortran/runtime/error.cc)
     240              :    Therefore, the code to set these flags must be generated before
     241              :    this function is used.  */
     242              : 
     243              : static void
     244          232 : gfc_trans_io_runtime_check (bool has_iostat, tree cond, tree var,
     245              :                             int error_code, const char * msgid,
     246              :                             stmtblock_t * pblock)
     247              : {
     248          232 :   stmtblock_t block;
     249          232 :   tree body;
     250          232 :   tree tmp;
     251          232 :   tree arg1, arg2, arg3;
     252          232 :   char *message;
     253              : 
     254          232 :   if (integer_zerop (cond))
     255          124 :     return;
     256              : 
     257              :   /* The code to generate the error.  */
     258          108 :   gfc_start_block (&block);
     259              : 
     260          108 :   if (has_iostat)
     261           36 :     gfc_add_expr_to_block (&block, build_predict_expr (PRED_FORTRAN_FAIL_IO,
     262              :                                                        NOT_TAKEN));
     263              :   else
     264           72 :     gfc_add_expr_to_block (&block, build_predict_expr (PRED_NORETURN,
     265              :                                                        NOT_TAKEN));
     266              : 
     267          108 :   arg1 = gfc_build_addr_expr (NULL_TREE, var);
     268              : 
     269          108 :   arg2 = build_int_cst (integer_type_node, error_code),
     270              : 
     271          108 :   message = xasprintf ("%s", _(msgid));
     272          108 :   arg3 = gfc_build_addr_expr (pchar_type_node,
     273              :                               gfc_build_localized_cstring_const (message));
     274          108 :   free (message);
     275              : 
     276          108 :   tmp = build_call_expr_loc (input_location,
     277              :                          gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
     278              : 
     279          108 :   gfc_add_expr_to_block (&block, tmp);
     280              : 
     281          108 :   body = gfc_finish_block (&block);
     282              : 
     283          108 :   if (integer_onep (cond))
     284              :     {
     285           18 :       gfc_add_expr_to_block (pblock, body);
     286              :     }
     287              :   else
     288              :     {
     289           90 :       tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt (input_location));
     290           90 :       gfc_add_expr_to_block (pblock, tmp);
     291              :     }
     292              : }
     293              : 
     294              : 
     295              : /* Create function decls for IO library functions.  */
     296              : 
     297              : void
     298        31863 : gfc_build_io_library_fndecls (void)
     299              : {
     300        31863 :   tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
     301        31863 :   tree gfc_intio_type_node;
     302        31863 :   tree parm_type, dt_parm_type;
     303        31863 :   HOST_WIDE_INT pad_size;
     304        31863 :   unsigned int ptype;
     305              : 
     306        31863 :   types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
     307        63726 :   types[IOPARM_type_intio] = gfc_intio_type_node
     308        31863 :                             = gfc_get_int_type (gfc_intio_kind);
     309        31863 :   types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
     310        31863 :   types[IOPARM_type_pintio]
     311        31863 :                             = build_pointer_type (gfc_intio_type_node);
     312        31863 :   types[IOPARM_type_parray] = pchar_type_node;
     313        31863 :   types[IOPARM_type_pchar] = pchar_type_node;
     314        31863 :   pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
     315        31863 :   pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
     316        31863 :   pad_idx = build_index_type (size_int (pad_size - 1));
     317        31863 :   types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
     318              : 
     319              :   /* pad actually contains pointers and integers so it needs to have an
     320              :      alignment that is at least as large as the needed alignment for those
     321              :      types.  See the st_parameter_dt structure in libgfortran/io/io.h for
     322              :      what really goes into this space.  */
     323        31863 :   SET_TYPE_ALIGN (types[IOPARM_type_pad], MAX (TYPE_ALIGN (pchar_type_node),
     324              :                      TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind))));
     325              : 
     326       254904 :   for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
     327       223041 :     gfc_build_st_parameter ((enum ioparam_type) ptype, types);
     328              : 
     329              :   /* Define the transfer functions.  */
     330              : 
     331        31863 :   dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
     332              : 
     333        31863 :   iocall[IOCALL_X_INTEGER] = gfc_build_library_function_decl_with_spec (
     334              :         get_identifier (PREFIX("transfer_integer")), ". w W . ",
     335              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     336              : 
     337        31863 :   iocall[IOCALL_X_INTEGER_WRITE] = gfc_build_library_function_decl_with_spec (
     338              :         get_identifier (PREFIX("transfer_integer_write")), ". w R . ",
     339              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     340              : 
     341        31863 :   iocall[IOCALL_X_UNSIGNED] = gfc_build_library_function_decl_with_spec (
     342              :         get_identifier (PREFIX("transfer_unsigned")), ". w W . ",
     343              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     344              : 
     345        31863 :   iocall[IOCALL_X_UNSIGNED_WRITE] = gfc_build_library_function_decl_with_spec (
     346              :         get_identifier (PREFIX("transfer_unsigned_write")), ". w R . ",
     347              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     348              : 
     349        31863 :   iocall[IOCALL_X_LOGICAL] = gfc_build_library_function_decl_with_spec (
     350              :         get_identifier (PREFIX("transfer_logical")), ". w W . ",
     351              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     352              : 
     353        31863 :   iocall[IOCALL_X_LOGICAL_WRITE] = gfc_build_library_function_decl_with_spec (
     354              :         get_identifier (PREFIX("transfer_logical_write")), ". w R . ",
     355              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     356              : 
     357        31863 :   iocall[IOCALL_X_CHARACTER] = gfc_build_library_function_decl_with_spec (
     358              :         get_identifier (PREFIX("transfer_character")), ". w W . ",
     359              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_charlen_type_node);
     360              : 
     361        31863 :   iocall[IOCALL_X_CHARACTER_WRITE] = gfc_build_library_function_decl_with_spec (
     362              :         get_identifier (PREFIX("transfer_character_write")), ". w R . ",
     363              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_charlen_type_node);
     364              : 
     365        31863 :   iocall[IOCALL_X_CHARACTER_WIDE] = gfc_build_library_function_decl_with_spec (
     366              :         get_identifier (PREFIX("transfer_character_wide")), ". w W . . ",
     367              :         void_type_node, 4, dt_parm_type, pvoid_type_node,
     368              :         gfc_charlen_type_node, gfc_int4_type_node);
     369              : 
     370        63726 :   iocall[IOCALL_X_CHARACTER_WIDE_WRITE] =
     371        31863 :     gfc_build_library_function_decl_with_spec (
     372              :         get_identifier (PREFIX("transfer_character_wide_write")), ". w R . . ",
     373              :         void_type_node, 4, dt_parm_type, pvoid_type_node,
     374              :         gfc_charlen_type_node, gfc_int4_type_node);
     375              : 
     376        31863 :   iocall[IOCALL_X_REAL] = gfc_build_library_function_decl_with_spec (
     377              :         get_identifier (PREFIX("transfer_real")), ". w W . ",
     378              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     379              : 
     380        31863 :   iocall[IOCALL_X_REAL_WRITE] = gfc_build_library_function_decl_with_spec (
     381              :         get_identifier (PREFIX("transfer_real_write")), ". w R . ",
     382              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     383              : 
     384        31863 :   iocall[IOCALL_X_COMPLEX] = gfc_build_library_function_decl_with_spec (
     385              :         get_identifier (PREFIX("transfer_complex")), ". w W . ",
     386              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     387              : 
     388        31863 :   iocall[IOCALL_X_COMPLEX_WRITE] = gfc_build_library_function_decl_with_spec (
     389              :         get_identifier (PREFIX("transfer_complex_write")), ". w R . ",
     390              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     391              : 
     392              :   /* Version for __float128.  */
     393        31863 :   iocall[IOCALL_X_REAL128] = gfc_build_library_function_decl_with_spec (
     394              :         get_identifier (PREFIX("transfer_real128")), ". w W . ",
     395              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     396              : 
     397        31863 :   iocall[IOCALL_X_REAL128_WRITE] = gfc_build_library_function_decl_with_spec (
     398              :         get_identifier (PREFIX("transfer_real128_write")), ". w R . ",
     399              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     400              : 
     401        31863 :   iocall[IOCALL_X_COMPLEX128] = gfc_build_library_function_decl_with_spec (
     402              :         get_identifier (PREFIX("transfer_complex128")), ". w W . ",
     403              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     404              : 
     405        31863 :   iocall[IOCALL_X_COMPLEX128_WRITE] = gfc_build_library_function_decl_with_spec (
     406              :         get_identifier (PREFIX("transfer_complex128_write")), ". w R . ",
     407              :         void_type_node, 3, dt_parm_type, pvoid_type_node, gfc_int4_type_node);
     408              : 
     409        31863 :   iocall[IOCALL_X_ARRAY] = gfc_build_library_function_decl_with_spec (
     410              :         get_identifier (PREFIX("transfer_array")), ". w w . . ",
     411              :         void_type_node, 4, dt_parm_type, pvoid_type_node,
     412              :         integer_type_node, gfc_charlen_type_node);
     413              : 
     414        31863 :   iocall[IOCALL_X_ARRAY_WRITE] = gfc_build_library_function_decl_with_spec (
     415              :         get_identifier (PREFIX("transfer_array_write")), ". w r . . ",
     416              :         void_type_node, 4, dt_parm_type, pvoid_type_node,
     417              :         integer_type_node, gfc_charlen_type_node);
     418              : 
     419        31863 :   iocall[IOCALL_X_DERIVED] = gfc_build_library_function_decl_with_spec (
     420              :         get_identifier (PREFIX("transfer_derived")), ". w w ",
     421              :         void_type_node, 2, dt_parm_type, pvoid_type_node);
     422              : 
     423              :   /* Library entry points */
     424              : 
     425        31863 :   iocall[IOCALL_READ] = gfc_build_library_function_decl_with_spec (
     426              :         get_identifier (PREFIX("st_read")), ". w ",
     427              :         void_type_node, 1, dt_parm_type);
     428              : 
     429        31863 :   iocall[IOCALL_WRITE] = gfc_build_library_function_decl_with_spec (
     430              :         get_identifier (PREFIX("st_write")), ". w ",
     431              :         void_type_node, 1, dt_parm_type);
     432              : 
     433        31863 :   parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
     434        31863 :   iocall[IOCALL_OPEN] = gfc_build_library_function_decl_with_spec (
     435              :         get_identifier (PREFIX("st_open")), ". w ",
     436              :         void_type_node, 1, parm_type);
     437              : 
     438        31863 :   parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
     439        31863 :   iocall[IOCALL_CLOSE] = gfc_build_library_function_decl_with_spec (
     440              :         get_identifier (PREFIX("st_close")), ". w ",
     441              :         void_type_node, 1, parm_type);
     442              : 
     443        31863 :   parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
     444        31863 :   iocall[IOCALL_INQUIRE] = gfc_build_library_function_decl_with_spec (
     445              :         get_identifier (PREFIX("st_inquire")), ". w ",
     446              :         void_type_node, 1, parm_type);
     447              : 
     448        31863 :   iocall[IOCALL_IOLENGTH] = gfc_build_library_function_decl_with_spec(
     449              :         get_identifier (PREFIX("st_iolength")), ". w ",
     450              :         void_type_node, 1, dt_parm_type);
     451              : 
     452        31863 :   parm_type = build_pointer_type (st_parameter[IOPARM_ptype_wait].type);
     453        31863 :   iocall[IOCALL_WAIT] = gfc_build_library_function_decl_with_spec (
     454              :         get_identifier (PREFIX("st_wait_async")), ". w ",
     455              :         void_type_node, 1, parm_type);
     456              : 
     457        31863 :   parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
     458        31863 :   iocall[IOCALL_REWIND] = gfc_build_library_function_decl_with_spec (
     459              :         get_identifier (PREFIX("st_rewind")), ". w ",
     460              :         void_type_node, 1, parm_type);
     461              : 
     462        31863 :   iocall[IOCALL_BACKSPACE] = gfc_build_library_function_decl_with_spec (
     463              :         get_identifier (PREFIX("st_backspace")), ". w ",
     464              :         void_type_node, 1, parm_type);
     465              : 
     466        31863 :   iocall[IOCALL_ENDFILE] = gfc_build_library_function_decl_with_spec (
     467              :         get_identifier (PREFIX("st_endfile")), ". w ",
     468              :         void_type_node, 1, parm_type);
     469              : 
     470        31863 :   iocall[IOCALL_FLUSH] = gfc_build_library_function_decl_with_spec (
     471              :         get_identifier (PREFIX("st_flush")), ". w ",
     472              :         void_type_node, 1, parm_type);
     473              : 
     474              :   /* Library helpers */
     475              : 
     476        31863 :   iocall[IOCALL_READ_DONE] = gfc_build_library_function_decl_with_spec (
     477              :         get_identifier (PREFIX("st_read_done")), ". w ",
     478              :         void_type_node, 1, dt_parm_type);
     479              : 
     480        31863 :   iocall[IOCALL_WRITE_DONE] = gfc_build_library_function_decl_with_spec (
     481              :         get_identifier (PREFIX("st_write_done")), ". w ",
     482              :         void_type_node, 1, dt_parm_type);
     483              : 
     484        31863 :   iocall[IOCALL_IOLENGTH_DONE] = gfc_build_library_function_decl_with_spec (
     485              :         get_identifier (PREFIX("st_iolength_done")), ". w ",
     486              :         void_type_node, 1, dt_parm_type);
     487              : 
     488        31863 :   iocall[IOCALL_SET_NML_VAL] = gfc_build_library_function_decl_with_spec (
     489              :         get_identifier (PREFIX("st_set_nml_var")), ". w . R . . . ",
     490              :         void_type_node, 6, dt_parm_type, pvoid_type_node, pvoid_type_node,
     491              :         gfc_int4_type_node, gfc_charlen_type_node, get_dtype_type_node());
     492              : 
     493        31863 :   iocall[IOCALL_SET_NML_DTIO_VAL] = gfc_build_library_function_decl_with_spec (
     494              :         get_identifier (PREFIX("st_set_nml_dtio_var")), ". w . R . . . . . ",
     495              :         void_type_node, 8, dt_parm_type, pvoid_type_node, pvoid_type_node,
     496              :         gfc_int4_type_node, gfc_charlen_type_node, get_dtype_type_node(),
     497              :         pvoid_type_node, pvoid_type_node);
     498              : 
     499        31863 :   iocall[IOCALL_SET_NML_VAL_DIM] = gfc_build_library_function_decl_with_spec (
     500              :         get_identifier (PREFIX("st_set_nml_var_dim")), ". w . . . . ",
     501              :         void_type_node, 5, dt_parm_type, gfc_int4_type_node,
     502              :         gfc_array_index_type, gfc_array_index_type, gfc_array_index_type);
     503        31863 : }
     504              : 
     505              : 
     506              : static void
     507       101632 : set_parameter_tree (stmtblock_t *block, tree var, enum iofield type, tree value)
     508              : {
     509       101632 :   tree tmp;
     510       101632 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     511              : 
     512       101632 :   if (p->param_type == IOPARM_ptype_common)
     513        96862 :     var = fold_build3_loc (input_location, COMPONENT_REF,
     514              :                            st_parameter[IOPARM_ptype_common].type,
     515        96862 :                            var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
     516       101632 :   tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
     517              :                          var, p->field, NULL_TREE);
     518       101632 :   gfc_add_modify (block, tmp, value);
     519       101632 : }
     520              : 
     521              : 
     522              : /* Generate code to store an integer constant into the
     523              :    st_parameter_XXX structure.  */
     524              : 
     525              : static unsigned int
     526        98538 : set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
     527              :                      unsigned int val)
     528              : {
     529        98538 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     530              : 
     531        98538 :   set_parameter_tree (block, var, type,
     532        98538 :                       build_int_cst (TREE_TYPE (p->field), val));
     533        98538 :   return p->mask;
     534              : }
     535              : 
     536              : 
     537              : /* Generate code to store a non-string I/O parameter into the
     538              :    st_parameter_XXX structure.  This is a pass by value.  */
     539              : 
     540              : static unsigned int
     541         1477 : set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
     542              :                      gfc_expr *e)
     543              : {
     544         1477 :   gfc_se se;
     545         1477 :   tree tmp;
     546         1477 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     547         1477 :   tree dest_type = TREE_TYPE (p->field);
     548              : 
     549         1477 :   gfc_init_se (&se, NULL);
     550         1477 :   gfc_conv_expr_val (&se, e);
     551              : 
     552         1477 :   se.expr = convert (dest_type, se.expr);
     553         1477 :   gfc_add_block_to_block (block, &se.pre);
     554              : 
     555         1477 :   if (p->param_type == IOPARM_ptype_common)
     556          574 :     var = fold_build3_loc (input_location, COMPONENT_REF,
     557              :                            st_parameter[IOPARM_ptype_common].type,
     558          574 :                            var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
     559              : 
     560         1477 :   tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
     561              :                          p->field, NULL_TREE);
     562         1477 :   gfc_add_modify (block, tmp, se.expr);
     563         1477 :   return p->mask;
     564              : }
     565              : 
     566              : 
     567              : /* Similar to set_parameter_value except generate runtime
     568              :    error checks.  */
     569              : 
     570              : static unsigned int
     571        31136 : set_parameter_value_chk (stmtblock_t *block, bool has_iostat, tree var,
     572              :                      enum iofield type, gfc_expr *e)
     573              : {
     574        31136 :   gfc_se se;
     575        31136 :   tree tmp;
     576        31136 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     577        31136 :   tree dest_type = TREE_TYPE (p->field);
     578              : 
     579        31136 :   gfc_init_se (&se, NULL);
     580        31136 :   gfc_conv_expr_val (&se, e);
     581              : 
     582              :   /* If we're storing a UNIT number, we need to check it first.  */
     583        31136 :   if (type == IOPARM_common_unit && e->ts.kind > 4)
     584              :     {
     585          116 :       tree cond, val;
     586          116 :       int i;
     587              : 
     588              :       /* Don't evaluate the UNIT number multiple times.  */
     589          116 :       se.expr = gfc_evaluate_now (se.expr, &se.pre);
     590              : 
     591              :       /* UNIT numbers should be greater than the min.  */
     592          116 :       i = gfc_validate_kind (BT_INTEGER, 4, false);
     593          116 :       val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
     594          116 :       cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
     595              :                               se.expr,
     596          116 :                               fold_convert (TREE_TYPE (se.expr), val));
     597          116 :       gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT,
     598              :                                   "Unit number in I/O statement too small",
     599              :                                   &se.pre);
     600              : 
     601              :       /* UNIT numbers should be less than the max.  */
     602          116 :       val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
     603          116 :       cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
     604              :                               se.expr,
     605          116 :                               fold_convert (TREE_TYPE (se.expr), val));
     606          116 :       gfc_trans_io_runtime_check (has_iostat, cond, var, LIBERROR_BAD_UNIT,
     607              :                                   "Unit number in I/O statement too large",
     608              :                                   &se.pre);
     609              :     }
     610              : 
     611        31136 :   se.expr = convert (dest_type, se.expr);
     612        31136 :   gfc_add_block_to_block (block, &se.pre);
     613              : 
     614        31136 :   if (p->param_type == IOPARM_ptype_common)
     615        31136 :     var = fold_build3_loc (input_location, COMPONENT_REF,
     616              :                            st_parameter[IOPARM_ptype_common].type,
     617        31136 :                            var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
     618              : 
     619        31136 :   tmp = fold_build3_loc (input_location, COMPONENT_REF, dest_type, var,
     620              :                          p->field, NULL_TREE);
     621        31136 :   gfc_add_modify (block, tmp, se.expr);
     622        31136 :   return p->mask;
     623              : }
     624              : 
     625              : 
     626              : /* Build code to check the unit range if KIND=8 is used.  Similar to
     627              :    set_parameter_value_chk but we do not generate error calls for
     628              :    inquire statements.  */
     629              : 
     630              : static unsigned int
     631          574 : set_parameter_value_inquire (stmtblock_t *block, tree var,
     632              :                              enum iofield type, gfc_expr *e)
     633              : {
     634          574 :   gfc_se se;
     635          574 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     636          574 :   tree dest_type = TREE_TYPE (p->field);
     637              : 
     638          574 :   gfc_init_se (&se, NULL);
     639          574 :   gfc_conv_expr_val (&se, e);
     640              : 
     641              :   /* If we're inquiring on a UNIT number, we need to check to make
     642              :      sure it exists for larger than kind = 4.  */
     643          574 :   if (type == IOPARM_common_unit && e->ts.kind > 4)
     644              :     {
     645           24 :       stmtblock_t newblock;
     646           24 :       tree cond1, cond2, cond3, val, body;
     647           24 :       int i;
     648              : 
     649              :       /* Don't evaluate the UNIT number multiple times.  */
     650           24 :       se.expr = gfc_evaluate_now (se.expr, &se.pre);
     651              : 
     652              :       /* UNIT numbers should be greater than the min.  */
     653           24 :       i = gfc_validate_kind (BT_INTEGER, 4, false);
     654           24 :       val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].pedantic_min_int, 4);
     655           24 :       cond1 = build2_loc (input_location, LT_EXPR, logical_type_node,
     656              :                           se.expr,
     657           24 :                           fold_convert (TREE_TYPE (se.expr), val));
     658              :       /* UNIT numbers should be less than the max.  */
     659           24 :       val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
     660           24 :       cond2 = build2_loc (input_location, GT_EXPR, logical_type_node,
     661              :                           se.expr,
     662           24 :                           fold_convert (TREE_TYPE (se.expr), val));
     663           24 :       cond3 = build2_loc (input_location, TRUTH_OR_EXPR,
     664              :                           logical_type_node, cond1, cond2);
     665              : 
     666           24 :       gfc_start_block (&newblock);
     667              : 
     668              :       /* The unit number GFC_INVALID_UNIT is reserved.  No units can
     669              :          ever have this value.  It is used here to signal to the
     670              :          runtime library that the inquire unit number is outside the
     671              :          allowable range and so cannot exist.  It is needed when
     672              :          -fdefault-integer-8 is used.  */
     673           24 :       set_parameter_const (&newblock, var, IOPARM_common_unit,
     674              :                            GFC_INVALID_UNIT);
     675              : 
     676           24 :       body = gfc_finish_block (&newblock);
     677              : 
     678           24 :       cond3 = gfc_unlikely (cond3, PRED_FORTRAN_FAIL_IO);
     679           24 :       var = build3_v (COND_EXPR, cond3, body, build_empty_stmt (input_location));
     680           24 :       gfc_add_expr_to_block (&se.pre, var);
     681              :     }
     682              : 
     683          574 :   se.expr = convert (dest_type, se.expr);
     684          574 :   gfc_add_block_to_block (block, &se.pre);
     685              : 
     686          574 :   return p->mask;
     687              : }
     688              : 
     689              : 
     690              : /* Generate code to store a non-string I/O parameter into the
     691              :    st_parameter_XXX structure.  This is pass by reference.  */
     692              : 
     693              : static unsigned int
     694         3094 : set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
     695              :                    tree var, enum iofield type, gfc_expr *e)
     696              : {
     697         3094 :   gfc_se se;
     698         3094 :   tree tmp, addr;
     699         3094 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     700              : 
     701         3094 :   gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
     702         3094 :   gfc_init_se (&se, NULL);
     703         3094 :   gfc_conv_expr_lhs (&se, e);
     704              : 
     705         3094 :   gfc_add_block_to_block (block, &se.pre);
     706              : 
     707         6188 :   if (TYPE_MODE (TREE_TYPE (se.expr))
     708         3094 :       == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
     709              :     {
     710         2673 :       addr = convert (TREE_TYPE (p->field), gfc_build_addr_expr (NULL_TREE, se.expr));
     711              : 
     712              :       /* If this is for the iostat variable initialize the
     713              :          user variable to LIBERROR_OK which is zero.  */
     714         2673 :       if (type == IOPARM_common_iostat)
     715         2030 :         gfc_add_modify (block, se.expr,
     716         2030 :                              build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
     717              :     }
     718              :   else
     719              :     {
     720              :       /* The type used by the library has different size
     721              :         from the type of the variable supplied by the user.
     722              :         Need to use a temporary.  */
     723          421 :       tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
     724              :                                     st_parameter_field[type].name);
     725              : 
     726              :       /* If this is for the iostat variable, initialize the
     727              :          user variable to LIBERROR_OK which is zero.  */
     728          421 :       if (type == IOPARM_common_iostat)
     729           26 :         gfc_add_modify (block, tmpvar,
     730           26 :                              build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
     731              : 
     732          421 :       addr = gfc_build_addr_expr (NULL_TREE, tmpvar);
     733              :         /* After the I/O operation, we set the variable from the temporary.  */
     734          421 :       tmp = convert (TREE_TYPE (se.expr), tmpvar);
     735          421 :       gfc_add_modify (postblock, se.expr, tmp);
     736              :      }
     737              : 
     738         3094 :   set_parameter_tree (block, var, type, addr);
     739         3094 :   return p->mask;
     740              : }
     741              : 
     742              : /* Given an array expr, find its address and length to get a string. If the
     743              :    array is full, the string's address is the address of array's first element
     744              :    and the length is the size of the whole array.  If it is an element, the
     745              :    string's address is the element's address and the length is the rest size of
     746              :    the array.  */
     747              : 
     748              : static void
     749          125 : gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
     750              : {
     751              : 
     752          125 :   if (e->rank == 0)
     753              :     {
     754           25 :       tree type, array, tmp;
     755           25 :       gfc_symbol *sym;
     756           25 :       int rank;
     757              : 
     758              :       /* If it is an element, we need its address and size of the rest.  */
     759           25 :       gcc_assert (e->expr_type == EXPR_VARIABLE);
     760           25 :       gcc_assert (e->ref->u.ar.type == AR_ELEMENT);
     761           25 :       sym = e->symtree->n.sym;
     762           25 :       rank = sym->as->rank - 1;
     763           25 :       gfc_conv_expr (se, e);
     764              : 
     765           25 :       array = sym->backend_decl;
     766           25 :       type = TREE_TYPE (array);
     767              : 
     768           25 :       tree elts_count;
     769           25 :       if (GFC_ARRAY_TYPE_P (type))
     770           19 :         elts_count = GFC_TYPE_ARRAY_SIZE (type);
     771              :       else
     772              :         {
     773            6 :           gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     774            6 :           tree stride = gfc_conv_array_stride (array, rank);
     775            6 :           tmp = fold_build2_loc (input_location, MINUS_EXPR,
     776              :                                  gfc_array_index_type,
     777              :                                  gfc_conv_array_ubound (array, rank),
     778              :                                  gfc_conv_array_lbound (array, rank));
     779            6 :           tmp = fold_build2_loc (input_location, PLUS_EXPR,
     780              :                                  gfc_array_index_type, tmp,
     781              :                                  gfc_index_one_node);
     782            6 :           elts_count = fold_build2_loc (input_location, MULT_EXPR,
     783              :                                         gfc_array_index_type, tmp, stride);
     784              :         }
     785           25 :       gcc_assert (elts_count);
     786              : 
     787           25 :       tree elt_size = TYPE_SIZE_UNIT (gfc_get_element_type (type));
     788           25 :       elt_size = fold_convert (gfc_array_index_type, elt_size);
     789              : 
     790           25 :       tree size;
     791           25 :       if (TREE_CODE (se->expr) == ARRAY_REF)
     792              :         {
     793           25 :           tree index = TREE_OPERAND (se->expr, 1);
     794           25 :           index = fold_convert (gfc_array_index_type, index);
     795              : 
     796           25 :           elts_count = fold_build2_loc (input_location, MINUS_EXPR,
     797              :                                         gfc_array_index_type,
     798              :                                         elts_count, index);
     799              : 
     800           25 :           size = fold_build2_loc (input_location, MULT_EXPR,
     801              :                                   gfc_array_index_type, elts_count, elt_size);
     802              :         }
     803              :       else
     804              :         {
     805            0 :           gcc_assert (INDIRECT_REF_P (se->expr));
     806            0 :           tree ptr = TREE_OPERAND (se->expr, 0);
     807              : 
     808            0 :           gcc_assert (TREE_CODE (ptr) == POINTER_PLUS_EXPR);
     809            0 :           tree offset = fold_convert_loc (input_location, gfc_array_index_type,
     810            0 :                                           TREE_OPERAND (ptr, 1));
     811              : 
     812            0 :           size = fold_build2_loc (input_location, MULT_EXPR,
     813              :                                   gfc_array_index_type, elts_count, elt_size);
     814            0 :           size = fold_build2_loc (input_location, MINUS_EXPR,
     815              :                                   gfc_array_index_type, size, offset);
     816              :         }
     817           25 :       gcc_assert (size);
     818              : 
     819           25 :       se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
     820           25 :       se->string_length = fold_convert (gfc_charlen_type_node, size);
     821           25 :       return;
     822              :     }
     823              : 
     824          100 :   tree size;
     825          100 :   gfc_conv_array_parameter (se, e, true, NULL, NULL, &size);
     826          100 :   se->string_length = fold_convert (gfc_charlen_type_node, size);
     827              : }
     828              : 
     829              : 
     830              : /* Generate code to store a string and its length into the
     831              :    st_parameter_XXX structure.  */
     832              : 
     833              : static unsigned int
     834        25607 : set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
     835              :             enum iofield type, gfc_expr * e)
     836              : {
     837        25607 :   gfc_se se;
     838        25607 :   tree tmp;
     839        25607 :   tree io;
     840        25607 :   tree len;
     841        25607 :   gfc_st_parameter_field *p = &st_parameter_field[type];
     842              : 
     843        25607 :   gfc_init_se (&se, NULL);
     844              : 
     845        25607 :   if (p->param_type == IOPARM_ptype_common)
     846          533 :     var = fold_build3_loc (input_location, COMPONENT_REF,
     847              :                            st_parameter[IOPARM_ptype_common].type,
     848          533 :                            var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
     849        25607 :   io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
     850              :                     var, p->field, NULL_TREE);
     851        25607 :   len = fold_build3_loc (input_location, COMPONENT_REF,
     852        25607 :                          TREE_TYPE (p->field_len),
     853              :                          var, p->field_len, NULL_TREE);
     854              : 
     855              :   /* Integer variable assigned a format label.  */
     856        25607 :   if (e->ts.type == BT_INTEGER
     857           37 :       && e->rank == 0
     858           19 :       && e->symtree->n.sym->attr.assign == 1)
     859              :     {
     860            1 :       char * msg;
     861            1 :       tree cond;
     862              : 
     863            1 :       gfc_conv_label_variable (&se, e);
     864            1 :       tmp = GFC_DECL_STRING_LEN (se.expr);
     865            1 :       cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
     866            1 :                               tmp, build_int_cst (TREE_TYPE (tmp), 0));
     867              : 
     868            2 :       msg = xasprintf ("Label assigned to variable '%s' (%%ld) is not a format "
     869            1 :                        "label", e->symtree->name);
     870            1 :       gfc_trans_runtime_check (true, false, cond, &se.pre, &e->where, msg,
     871              :                                fold_convert (long_integer_type_node, tmp));
     872            1 :       free (msg);
     873              : 
     874            1 :       gfc_add_modify (&se.pre, io,
     875            1 :                  fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
     876            1 :       gfc_add_modify (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
     877            1 :     }
     878              :   else
     879              :     {
     880              :       /* General character.  */
     881        25606 :       if (e->ts.type == BT_CHARACTER && e->rank == 0)
     882        25481 :         gfc_conv_expr (&se, e);
     883              :       /* Array assigned Hollerith constant or character array.  */
     884          125 :       else if (e->rank > 0 || (e->symtree && e->symtree->n.sym->as->rank > 0))
     885          125 :         gfc_convert_array_to_string (&se, e);
     886              :       else
     887            0 :         gcc_unreachable ();
     888              : 
     889        25606 :       gfc_conv_string_parameter (&se);
     890        25606 :       gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
     891        25606 :       gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len),
     892              :                                                   se.string_length));
     893              :     }
     894              : 
     895        25607 :   gfc_add_block_to_block (block, &se.pre);
     896        25607 :   gfc_add_block_to_block (postblock, &se.post);
     897        25607 :   return p->mask;
     898              : }
     899              : 
     900              : 
     901              : /* Generate code to store the character (array) and the character length
     902              :    for an internal unit.  */
     903              : 
     904              : static unsigned int
     905         9981 : set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
     906              :                    tree var, gfc_expr * e)
     907              : {
     908         9981 :   gfc_se se;
     909         9981 :   tree io;
     910         9981 :   tree len;
     911         9981 :   tree desc;
     912         9981 :   tree tmp;
     913         9981 :   gfc_st_parameter_field *p;
     914         9981 :   unsigned int mask;
     915              : 
     916         9981 :   gfc_init_se (&se, NULL);
     917              : 
     918         9981 :   p = &st_parameter_field[IOPARM_dt_internal_unit];
     919         9981 :   mask = p->mask;
     920         9981 :   io = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
     921              :                         var, p->field, NULL_TREE);
     922         9981 :   len = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field_len),
     923              :                          var, p->field_len,  NULL_TREE);
     924         9981 :   p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
     925         9981 :   desc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
     926              :                           var, p->field, NULL_TREE);
     927              : 
     928         9981 :   gcc_assert (e->ts.type == BT_CHARACTER);
     929              : 
     930              :   /* Character scalars.  */
     931         9981 :   if (e->rank == 0)
     932              :     {
     933         9445 :       gfc_conv_expr (&se, e);
     934         9445 :       gfc_conv_string_parameter (&se);
     935         9445 :       tmp = se.expr;
     936         9445 :       se.expr = build_int_cst (pchar_type_node, 0);
     937              :     }
     938              : 
     939              :   /* Character array.  */
     940          536 :   else if (e->rank > 0)
     941              :     {
     942          536 :       if (is_subref_array (e))
     943              :         {
     944              :           /* Use a temporary for components of arrays of derived types
     945              :              or substring array references.  */
     946           48 :           gfc_conv_subref_array_arg (&se, e, 0,
     947           48 :                 last_dt == READ ? INTENT_IN : INTENT_OUT, false);
     948           48 :           tmp = build_fold_indirect_ref_loc (input_location,
     949              :                                          se.expr);
     950           48 :           se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
     951           48 :           tmp = gfc_conv_descriptor_data_get (tmp);
     952              :         }
     953              :       else
     954              :         {
     955              :           /* Return the data pointer and rank from the descriptor.  */
     956          488 :           gfc_conv_expr_descriptor (&se, e);
     957          488 :           tmp = gfc_conv_descriptor_data_get (se.expr);
     958          488 :           se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
     959              :         }
     960              :     }
     961              :   else
     962            0 :     gcc_unreachable ();
     963              : 
     964              :   /* The cast is needed for character substrings and the descriptor
     965              :      data.  */
     966         9981 :   gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
     967         9981 :   gfc_add_modify (&se.pre, len,
     968         9981 :                        fold_convert (TREE_TYPE (len), se.string_length));
     969         9981 :   gfc_add_modify (&se.pre, desc, se.expr);
     970              : 
     971         9981 :   gfc_add_block_to_block (block, &se.pre);
     972         9981 :   gfc_add_block_to_block (post_block, &se.post);
     973         9981 :   return mask;
     974              : }
     975              : 
     976              : /* Add a case to a IO-result switch.  */
     977              : 
     978              : static void
     979         2547 : add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
     980              : {
     981         2547 :   tree tmp, value;
     982              : 
     983         2547 :   if (label == NULL)
     984              :     return;                     /* No label, no case */
     985              : 
     986          947 :   value = build_int_cst (integer_type_node, label_value);
     987              : 
     988              :   /* Make a backend label for this case.  */
     989          947 :   tmp = gfc_build_label_decl (NULL_TREE);
     990              : 
     991              :   /* And the case itself.  */
     992          947 :   tmp = build_case_label (value, NULL_TREE, tmp);
     993          947 :   gfc_add_expr_to_block (body, tmp);
     994              : 
     995              :   /* Jump to the label.  */
     996          947 :   tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
     997          947 :   gfc_add_expr_to_block (body, tmp);
     998              : }
     999              : 
    1000              : 
    1001              : /* Generate a switch statement that branches to the correct I/O
    1002              :    result label.  The last statement of an I/O call stores the
    1003              :    result into a variable because there is often cleanup that
    1004              :    must be done before the switch, so a temporary would have to
    1005              :    be created anyway.  */
    1006              : 
    1007              : static void
    1008        42080 : io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
    1009              :            gfc_st_label * end_label, gfc_st_label * eor_label)
    1010              : {
    1011        42080 :   stmtblock_t body;
    1012        42080 :   tree tmp, rc;
    1013        42080 :   gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
    1014              : 
    1015              :   /* If no labels are specified, ignore the result instead
    1016              :      of building an empty switch.  */
    1017        42080 :   if (err_label == NULL
    1018        42080 :       && end_label == NULL
    1019        41255 :       && eor_label == NULL)
    1020        41231 :     return;
    1021              : 
    1022              :   /* Build a switch statement.  */
    1023          849 :   gfc_start_block (&body);
    1024              : 
    1025              :   /* The label values here must be the same as the values
    1026              :      in the library_return enum in the runtime library */
    1027          849 :   add_case (1, err_label, &body);
    1028          849 :   add_case (2, end_label, &body);
    1029          849 :   add_case (3, eor_label, &body);
    1030              : 
    1031          849 :   tmp = gfc_finish_block (&body);
    1032              : 
    1033          849 :   var = fold_build3_loc (input_location, COMPONENT_REF,
    1034              :                          st_parameter[IOPARM_ptype_common].type,
    1035          849 :                          var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
    1036          849 :   rc = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (p->field),
    1037              :                         var, p->field, NULL_TREE);
    1038          849 :   rc = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (rc),
    1039          849 :                         rc, build_int_cst (TREE_TYPE (rc),
    1040              :                                            IOPARM_common_libreturn_mask));
    1041              : 
    1042          849 :   tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, rc, tmp);
    1043              : 
    1044          849 :   gfc_add_expr_to_block (block, tmp);
    1045              : }
    1046              : 
    1047              : 
    1048              : /* Store the current file and line number to variables so that if a
    1049              :    library call goes awry, we can tell the user where the problem is.  */
    1050              : 
    1051              : static void
    1052        42164 : set_error_locus (stmtblock_t * block, tree var, locus * where)
    1053              : {
    1054        42164 :   tree str, locus_file;
    1055        42164 :   gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
    1056              : 
    1057        42164 :   locus_file = fold_build3_loc (input_location, COMPONENT_REF,
    1058              :                                 st_parameter[IOPARM_ptype_common].type,
    1059        42164 :                                 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
    1060        42164 :   locus_file = fold_build3_loc (input_location, COMPONENT_REF,
    1061        42164 :                                 TREE_TYPE (p->field), locus_file,
    1062              :                                 p->field, NULL_TREE);
    1063        42164 :   location_t loc = gfc_get_location (where);
    1064        42164 :   str = gfc_build_cstring_const (LOCATION_FILE (loc));
    1065        42164 :   str = gfc_build_addr_expr (pchar_type_node, str);
    1066        42164 :   gfc_add_modify (block, locus_file, str);
    1067              : 
    1068        42164 :   set_parameter_const (block, var, IOPARM_common_line, LOCATION_LINE (loc));
    1069        42164 : }
    1070              : 
    1071              : 
    1072              : /* Translate an OPEN statement.  */
    1073              : 
    1074              : tree
    1075         3612 : gfc_trans_open (gfc_code * code)
    1076              : {
    1077         3612 :   stmtblock_t block, post_block;
    1078         3612 :   gfc_open *p;
    1079         3612 :   tree tmp, var;
    1080         3612 :   unsigned int mask = 0;
    1081              : 
    1082         3612 :   gfc_start_block (&block);
    1083         3612 :   gfc_init_block (&post_block);
    1084              : 
    1085         3612 :   var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
    1086              : 
    1087         3612 :   set_error_locus (&block, var, &code->loc);
    1088         3612 :   p = code->ext.open;
    1089              : 
    1090         3612 :   if (p->iomsg)
    1091           42 :     mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1092              :                         p->iomsg);
    1093              : 
    1094         3612 :   if (p->iostat)
    1095          130 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
    1096              :                                p->iostat);
    1097              : 
    1098         3612 :   if (p->err)
    1099           75 :     mask |= IOPARM_common_err;
    1100              : 
    1101         3612 :   if (p->file)
    1102         1490 :     mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
    1103              : 
    1104         3612 :   if (p->status)
    1105         2148 :     mask |= set_string (&block, &post_block, var, IOPARM_open_status,
    1106              :                         p->status);
    1107              : 
    1108         3612 :   if (p->access)
    1109          763 :     mask |= set_string (&block, &post_block, var, IOPARM_open_access,
    1110              :                         p->access);
    1111              : 
    1112         3612 :   if (p->form)
    1113         1103 :     mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
    1114              : 
    1115         3612 :   if (p->recl)
    1116          242 :     mask |= set_parameter_value (&block, var, IOPARM_open_recl_in,
    1117              :                                  p->recl);
    1118              : 
    1119         3612 :   if (p->blank)
    1120           12 :     mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
    1121              :                         p->blank);
    1122              : 
    1123         3612 :   if (p->position)
    1124          108 :     mask |= set_string (&block, &post_block, var, IOPARM_open_position,
    1125              :                         p->position);
    1126              : 
    1127         3612 :   if (p->action)
    1128          231 :     mask |= set_string (&block, &post_block, var, IOPARM_open_action,
    1129              :                         p->action);
    1130              : 
    1131         3612 :   if (p->delim)
    1132          120 :     mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
    1133              :                         p->delim);
    1134              : 
    1135         3612 :   if (p->pad)
    1136           30 :     mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
    1137              : 
    1138         3612 :   if (p->decimal)
    1139           36 :     mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
    1140              :                         p->decimal);
    1141              : 
    1142         3612 :   if (p->encoding)
    1143           60 :     mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
    1144              :                         p->encoding);
    1145              : 
    1146         3612 :   if (p->round)
    1147            0 :     mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
    1148              : 
    1149         3612 :   if (p->sign)
    1150           18 :     mask |= set_string (&block, &post_block, var, IOPARM_open_sign, p->sign);
    1151              : 
    1152         3612 :   if (p->asynchronous)
    1153          100 :     mask |= set_string (&block, &post_block, var, IOPARM_open_asynchronous,
    1154              :                         p->asynchronous);
    1155              : 
    1156         3612 :   if (p->convert)
    1157           72 :     mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
    1158              :                         p->convert);
    1159              : 
    1160         3612 :   if (p->newunit)
    1161          183 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
    1162              :                                p->newunit);
    1163              : 
    1164         3612 :   if (p->cc)
    1165           24 :     mask |= set_string (&block, &post_block, var, IOPARM_open_cc, p->cc);
    1166              : 
    1167         3612 :   if (p->share)
    1168           24 :     mask |= set_string (&block, &post_block, var, IOPARM_open_share, p->share);
    1169              : 
    1170         3612 :   mask |= set_parameter_const (&block, var, IOPARM_open_readonly, p->readonly);
    1171              : 
    1172         3612 :   set_parameter_const (&block, var, IOPARM_common_flags, mask);
    1173              : 
    1174         3612 :   if (p->unit)
    1175         3429 :     set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
    1176              :   else
    1177          183 :     set_parameter_const (&block, var, IOPARM_common_unit, 0);
    1178              : 
    1179         3612 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    1180         3612 :   tmp = build_call_expr_loc (input_location,
    1181              :                          iocall[IOCALL_OPEN], 1, tmp);
    1182         3612 :   gfc_add_expr_to_block (&block, tmp);
    1183              : 
    1184         3612 :   gfc_add_block_to_block (&block, &post_block);
    1185              : 
    1186         3612 :   io_result (&block, var, p->err, NULL, NULL);
    1187              : 
    1188         3612 :   return gfc_finish_block (&block);
    1189              : }
    1190              : 
    1191              : 
    1192              : /* Translate a CLOSE statement.  */
    1193              : 
    1194              : tree
    1195         3092 : gfc_trans_close (gfc_code * code)
    1196              : {
    1197         3092 :   stmtblock_t block, post_block;
    1198         3092 :   gfc_close *p;
    1199         3092 :   tree tmp, var;
    1200         3092 :   unsigned int mask = 0;
    1201              : 
    1202         3092 :   gfc_start_block (&block);
    1203         3092 :   gfc_init_block (&post_block);
    1204              : 
    1205         3092 :   var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
    1206              : 
    1207         3092 :   set_error_locus (&block, var, &code->loc);
    1208         3092 :   p = code->ext.close;
    1209              : 
    1210         3092 :   if (p->iomsg)
    1211           12 :     mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1212              :                         p->iomsg);
    1213              : 
    1214         3092 :   if (p->iostat)
    1215           19 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
    1216              :                                p->iostat);
    1217              : 
    1218         3092 :   if (p->err)
    1219            7 :     mask |= IOPARM_common_err;
    1220              : 
    1221         3092 :   if (p->status)
    1222         1383 :     mask |= set_string (&block, &post_block, var, IOPARM_close_status,
    1223              :                         p->status);
    1224              : 
    1225         3092 :   set_parameter_const (&block, var, IOPARM_common_flags, mask);
    1226              : 
    1227         3092 :   if (p->unit)
    1228         3092 :     set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
    1229              :   else
    1230            0 :     set_parameter_const (&block, var, IOPARM_common_unit, 0);
    1231              : 
    1232         3092 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    1233         3092 :   tmp = build_call_expr_loc (input_location,
    1234              :                          iocall[IOCALL_CLOSE], 1, tmp);
    1235         3092 :   gfc_add_expr_to_block (&block, tmp);
    1236              : 
    1237         3092 :   gfc_add_block_to_block (&block, &post_block);
    1238              : 
    1239         3092 :   io_result (&block, var, p->err, NULL, NULL);
    1240              : 
    1241         3092 :   return gfc_finish_block (&block);
    1242              : }
    1243              : 
    1244              : 
    1245              : /* Common subroutine for building a file positioning statement.  */
    1246              : 
    1247              : static tree
    1248         2781 : build_filepos (tree function, gfc_code * code)
    1249              : {
    1250         2781 :   stmtblock_t block, post_block;
    1251         2781 :   gfc_filepos *p;
    1252         2781 :   tree tmp, var;
    1253         2781 :   unsigned int mask = 0;
    1254              : 
    1255         2781 :   p = code->ext.filepos;
    1256              : 
    1257         2781 :   gfc_start_block (&block);
    1258         2781 :   gfc_init_block (&post_block);
    1259              : 
    1260         2781 :   var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
    1261              :                         "filepos_parm");
    1262              : 
    1263         2781 :   set_error_locus (&block, var, &code->loc);
    1264              : 
    1265         2781 :   if (p->iomsg)
    1266           30 :     mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1267              :                         p->iomsg);
    1268              : 
    1269         2781 :   if (p->iostat)
    1270           63 :     mask |= set_parameter_ref (&block, &post_block, var,
    1271              :                                IOPARM_common_iostat, p->iostat);
    1272              : 
    1273         2781 :   if (p->err)
    1274           16 :     mask |= IOPARM_common_err;
    1275              : 
    1276         2781 :   set_parameter_const (&block, var, IOPARM_common_flags, mask);
    1277              : 
    1278         2781 :   if (p->unit)
    1279         2781 :     set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit,
    1280              :                              p->unit);
    1281              :   else
    1282            0 :     set_parameter_const (&block, var, IOPARM_common_unit, 0);
    1283              : 
    1284         2781 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    1285         2781 :   tmp = build_call_expr_loc (input_location,
    1286              :                          function, 1, tmp);
    1287         2781 :   gfc_add_expr_to_block (&block, tmp);
    1288              : 
    1289         2781 :   gfc_add_block_to_block (&block, &post_block);
    1290              : 
    1291         2781 :   io_result (&block, var, p->err, NULL, NULL);
    1292              : 
    1293         2781 :   return gfc_finish_block (&block);
    1294              : }
    1295              : 
    1296              : 
    1297              : /* Translate a BACKSPACE statement.  */
    1298              : 
    1299              : tree
    1300          389 : gfc_trans_backspace (gfc_code * code)
    1301              : {
    1302          389 :   return build_filepos (iocall[IOCALL_BACKSPACE], code);
    1303              : }
    1304              : 
    1305              : 
    1306              : /* Translate an ENDFILE statement.  */
    1307              : 
    1308              : tree
    1309           56 : gfc_trans_endfile (gfc_code * code)
    1310              : {
    1311           56 :   return build_filepos (iocall[IOCALL_ENDFILE], code);
    1312              : }
    1313              : 
    1314              : 
    1315              : /* Translate a REWIND statement.  */
    1316              : 
    1317              : tree
    1318         2258 : gfc_trans_rewind (gfc_code * code)
    1319              : {
    1320         2258 :   return build_filepos (iocall[IOCALL_REWIND], code);
    1321              : }
    1322              : 
    1323              : 
    1324              : /* Translate a FLUSH statement.  */
    1325              : 
    1326              : tree
    1327           78 : gfc_trans_flush (gfc_code * code)
    1328              : {
    1329           78 :   return build_filepos (iocall[IOCALL_FLUSH], code);
    1330              : }
    1331              : 
    1332              : 
    1333              : /* Translate the non-IOLENGTH form of an INQUIRE statement.  */
    1334              : 
    1335              : tree
    1336          780 : gfc_trans_inquire (gfc_code * code)
    1337              : {
    1338          780 :   stmtblock_t block, post_block;
    1339          780 :   gfc_inquire *p;
    1340          780 :   tree tmp, var;
    1341          780 :   unsigned int mask = 0, mask2 = 0;
    1342              : 
    1343          780 :   gfc_start_block (&block);
    1344          780 :   gfc_init_block (&post_block);
    1345              : 
    1346          780 :   var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
    1347              :                         "inquire_parm");
    1348              : 
    1349          780 :   set_error_locus (&block, var, &code->loc);
    1350          780 :   p = code->ext.inquire;
    1351              : 
    1352          780 :   if (p->iomsg)
    1353           13 :     mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1354              :                         p->iomsg);
    1355              : 
    1356          780 :   if (p->iostat)
    1357           46 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
    1358              :                                p->iostat);
    1359              : 
    1360          780 :   if (p->err)
    1361            7 :     mask |= IOPARM_common_err;
    1362              : 
    1363              :   /* Sanity check.  */
    1364          780 :   if (p->unit && p->file)
    1365            0 :     gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
    1366              : 
    1367          780 :   if (p->file)
    1368          206 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
    1369              :                         p->file);
    1370              : 
    1371          780 :   if (p->exist)
    1372          138 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
    1373              :                                  p->exist);
    1374              : 
    1375          780 :   if (p->opened)
    1376          147 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
    1377              :                                p->opened);
    1378              : 
    1379          780 :   if (p->number)
    1380           84 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
    1381              :                                p->number);
    1382              : 
    1383          780 :   if (p->named)
    1384           21 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
    1385              :                                p->named);
    1386              : 
    1387          780 :   if (p->name)
    1388           26 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
    1389              :                         p->name);
    1390              : 
    1391          780 :   if (p->access)
    1392          149 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
    1393              :                         p->access);
    1394              : 
    1395          780 :   if (p->sequential)
    1396           38 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
    1397              :                         p->sequential);
    1398              : 
    1399          780 :   if (p->direct)
    1400          110 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
    1401              :                         p->direct);
    1402              : 
    1403          780 :   if (p->form)
    1404           14 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
    1405              :                         p->form);
    1406              : 
    1407          780 :   if (p->formatted)
    1408           44 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
    1409              :                         p->formatted);
    1410              : 
    1411          780 :   if (p->unformatted)
    1412           38 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
    1413              :                         p->unformatted);
    1414              : 
    1415          780 :   if (p->recl)
    1416           57 :     mask |= set_parameter_ref (&block, &post_block, var,
    1417              :                                IOPARM_inquire_recl_out, p->recl);
    1418              : 
    1419          780 :   if (p->nextrec)
    1420           60 :     mask |= set_parameter_ref (&block, &post_block, var,
    1421              :                                IOPARM_inquire_nextrec, p->nextrec);
    1422              : 
    1423          780 :   if (p->blank)
    1424           23 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
    1425              :                         p->blank);
    1426              : 
    1427          780 :   if (p->delim)
    1428           38 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
    1429              :                         p->delim);
    1430              : 
    1431          780 :   if (p->position)
    1432           56 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
    1433              :                         p->position);
    1434              : 
    1435          780 :   if (p->action)
    1436           20 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
    1437              :                         p->action);
    1438              : 
    1439          780 :   if (p->read)
    1440           32 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
    1441              :                         p->read);
    1442              : 
    1443          780 :   if (p->write)
    1444           32 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
    1445              :                         p->write);
    1446              : 
    1447          780 :   if (p->readwrite)
    1448           32 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
    1449              :                         p->readwrite);
    1450              : 
    1451          780 :   if (p->pad)
    1452           38 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
    1453              :                         p->pad);
    1454              : 
    1455          780 :   if (p->convert)
    1456           12 :     mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
    1457              :                         p->convert);
    1458              : 
    1459          780 :   if (p->strm_pos)
    1460          108 :     mask |= set_parameter_ref (&block, &post_block, var,
    1461              :                                IOPARM_inquire_strm_pos_out, p->strm_pos);
    1462              : 
    1463              :   /* The second series of flags.  */
    1464          780 :   if (p->asynchronous)
    1465           26 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_asynchronous,
    1466              :                          p->asynchronous);
    1467              : 
    1468          780 :   if (p->decimal)
    1469           18 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
    1470              :                          p->decimal);
    1471              : 
    1472          780 :   if (p->encoding)
    1473           18 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
    1474              :                          p->encoding);
    1475              : 
    1476          780 :   if (p->round)
    1477           18 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
    1478              :                          p->round);
    1479              : 
    1480          780 :   if (p->sign)
    1481           18 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
    1482              :                          p->sign);
    1483              : 
    1484          780 :   if (p->pending)
    1485           17 :     mask2 |= set_parameter_ref (&block, &post_block, var,
    1486              :                                 IOPARM_inquire_pending, p->pending);
    1487              : 
    1488          780 :   if (p->size)
    1489           42 :     mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
    1490              :                                 p->size);
    1491              : 
    1492          780 :   if (p->id)
    1493           10 :     mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
    1494              :                                 p->id);
    1495          780 :   if (p->iqstream)
    1496           42 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_iqstream,
    1497              :                          p->iqstream);
    1498              : 
    1499          780 :   if (p->share)
    1500            6 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_share,
    1501              :                          p->share);
    1502              : 
    1503          780 :   if (p->cc)
    1504            6 :     mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_cc, p->cc);
    1505              : 
    1506          780 :   if (mask2)
    1507          120 :     mask |= set_parameter_const (&block, var, IOPARM_inquire_flags2, mask2);
    1508              : 
    1509          780 :   set_parameter_const (&block, var, IOPARM_common_flags, mask);
    1510              : 
    1511          780 :   if (p->unit)
    1512              :     {
    1513          574 :       set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
    1514          574 :       set_parameter_value_inquire (&block, var, IOPARM_common_unit, p->unit);
    1515              :     }
    1516              :   else
    1517          206 :     set_parameter_const (&block, var, IOPARM_common_unit, 0);
    1518              : 
    1519          780 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    1520          780 :   tmp = build_call_expr_loc (input_location,
    1521              :                          iocall[IOCALL_INQUIRE], 1, tmp);
    1522          780 :   gfc_add_expr_to_block (&block, tmp);
    1523              : 
    1524          780 :   gfc_add_block_to_block (&block, &post_block);
    1525              : 
    1526          780 :   io_result (&block, var, p->err, NULL, NULL);
    1527              : 
    1528          780 :   return gfc_finish_block (&block);
    1529              : }
    1530              : 
    1531              : 
    1532              : tree
    1533           74 : gfc_trans_wait (gfc_code * code)
    1534              : {
    1535           74 :   stmtblock_t block, post_block;
    1536           74 :   gfc_wait *p;
    1537           74 :   tree tmp, var;
    1538           74 :   unsigned int mask = 0;
    1539              : 
    1540           74 :   gfc_start_block (&block);
    1541           74 :   gfc_init_block (&post_block);
    1542              : 
    1543           74 :   var = gfc_create_var (st_parameter[IOPARM_ptype_wait].type,
    1544              :                         "wait_parm");
    1545              : 
    1546           74 :   set_error_locus (&block, var, &code->loc);
    1547           74 :   p = code->ext.wait;
    1548              : 
    1549              :   /* Set parameters here.  */
    1550           74 :   if (p->iomsg)
    1551           14 :     mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1552              :                         p->iomsg);
    1553              : 
    1554           74 :   if (p->iostat)
    1555           20 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
    1556              :                                p->iostat);
    1557              : 
    1558           74 :   if (p->err)
    1559            7 :     mask |= IOPARM_common_err;
    1560              : 
    1561           74 :   if (p->id)
    1562           13 :     mask |= set_parameter_ref (&block, &post_block, var, IOPARM_wait_id, p->id);
    1563              : 
    1564           74 :   set_parameter_const (&block, var, IOPARM_common_flags, mask);
    1565              : 
    1566           74 :   if (p->unit)
    1567           74 :     set_parameter_value_chk (&block, p->iostat, var, IOPARM_common_unit, p->unit);
    1568              : 
    1569           74 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    1570           74 :   tmp = build_call_expr_loc (input_location,
    1571              :                          iocall[IOCALL_WAIT], 1, tmp);
    1572           74 :   gfc_add_expr_to_block (&block, tmp);
    1573              : 
    1574           74 :   gfc_add_block_to_block (&block, &post_block);
    1575              : 
    1576           74 :   io_result (&block, var, p->err, NULL, NULL);
    1577              : 
    1578           74 :   return gfc_finish_block (&block);
    1579              : 
    1580              : }
    1581              : 
    1582              : 
    1583              : /* nml_full_name builds up the fully qualified name of a
    1584              :    derived type component. '+' is used to denote a type extension.  */
    1585              : 
    1586              : static char*
    1587         1844 : nml_full_name (const char* var_name, const char* cmp_name, bool parent)
    1588              : {
    1589         1844 :   int full_name_length;
    1590         1844 :   char * full_name;
    1591              : 
    1592         1844 :   full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
    1593         1844 :   full_name = XCNEWVEC (char, full_name_length + 1);
    1594         1844 :   strcpy (full_name, var_name);
    1595         1844 :   full_name = strcat (full_name, parent ? "+" : "%");
    1596         1844 :   full_name = strcat (full_name, cmp_name);
    1597         1844 :   return full_name;
    1598              : }
    1599              : 
    1600              : 
    1601              : /* nml_get_addr_expr builds an address expression from the
    1602              :    gfc_symbol or gfc_component backend_decl's. An offset is
    1603              :    provided so that the address of an element of an array of
    1604              :    derived types is returned. This is used in the runtime to
    1605              :    determine that span of the derived type.  */
    1606              : 
    1607              : static tree
    1608         4849 : nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
    1609              :                    tree base_addr)
    1610              : {
    1611         4849 :   tree decl = NULL_TREE;
    1612         4849 :   tree tmp;
    1613              : 
    1614         4849 :   if (sym)
    1615              :     {
    1616         3005 :       sym->attr.referenced = 1;
    1617         3005 :       decl = gfc_get_symbol_decl (sym);
    1618              : 
    1619              :       /* If this is the enclosing function declaration, use
    1620              :          the fake result instead.  */
    1621         3005 :       if (decl == current_function_decl)
    1622           12 :         decl = gfc_get_fake_result_decl (sym, 0);
    1623         2993 :       else if (decl == DECL_CONTEXT (current_function_decl))
    1624            0 :         decl =  gfc_get_fake_result_decl (sym, 1);
    1625              :     }
    1626              :   else
    1627         1844 :     decl = c->backend_decl;
    1628              : 
    1629         4849 :   gcc_assert (decl && (TREE_CODE (decl) == FIELD_DECL
    1630              :                        || VAR_P (decl)
    1631              :                        || TREE_CODE (decl) == PARM_DECL
    1632              :                        || TREE_CODE (decl) == COMPONENT_REF));
    1633              : 
    1634         4849 :   tmp = decl;
    1635              : 
    1636              :   /* Build indirect reference, if dummy argument.  */
    1637              : 
    1638         4849 :   if (POINTER_TYPE_P (TREE_TYPE(tmp)))
    1639          831 :     tmp = build_fold_indirect_ref_loc (input_location, tmp);
    1640              : 
    1641              :   /* Treat the component of a derived type, using base_addr for
    1642              :      the derived type.  */
    1643              : 
    1644         4849 :   if (TREE_CODE (decl) == FIELD_DECL)
    1645         1844 :     tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
    1646              :                            base_addr, tmp, NULL_TREE);
    1647              : 
    1648         4849 :   if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
    1649         4849 :       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (gfc_class_data_get (tmp))))
    1650           12 :     tmp = gfc_class_data_get (tmp);
    1651              : 
    1652         4849 :   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
    1653          300 :     tmp = gfc_conv_array_data (tmp);
    1654              :   else
    1655              :     {
    1656         4549 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
    1657         4357 :         tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    1658              : 
    1659         4549 :       if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
    1660            0 :          tmp = gfc_build_array_ref (tmp, gfc_index_zero_node, NULL);
    1661              : 
    1662         4549 :       if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
    1663            0 :         tmp = build_fold_indirect_ref_loc (input_location,
    1664              :                                    tmp);
    1665              :     }
    1666              : 
    1667         4849 :   gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
    1668              : 
    1669         4849 :   return tmp;
    1670              : }
    1671              : 
    1672              : 
    1673              : /* For an object VAR_NAME whose base address is BASE_ADDR, generate a
    1674              :    call to iocall[IOCALL_SET_NML_VAL].  For derived type variable, recursively
    1675              :    generate calls to iocall[IOCALL_SET_NML_VAL] for each component.  */
    1676              : 
    1677              : #define IARG(i) build_int_cst (gfc_array_index_type, i)
    1678              : 
    1679              : static void
    1680         4849 : transfer_namelist_element (stmtblock_t * block, const char * var_name,
    1681              :                            gfc_symbol * sym, gfc_component * c,
    1682              :                            tree base_addr)
    1683              : {
    1684         4849 :   gfc_typespec * ts = NULL;
    1685         4849 :   gfc_array_spec * as = NULL;
    1686         4849 :   tree addr_expr = NULL;
    1687         4849 :   tree dt = NULL;
    1688         4849 :   tree string;
    1689         4849 :   tree tmp;
    1690         4849 :   tree dtype;
    1691         4849 :   tree dt_parm_addr;
    1692         4849 :   tree decl = NULL_TREE;
    1693         4849 :   tree gfc_int4_type_node = gfc_get_int_type (4);
    1694         4849 :   tree dtio_proc = null_pointer_node;
    1695         4849 :   tree vtable = null_pointer_node;
    1696         4849 :   int n_dim;
    1697         4849 :   int rank = 0;
    1698              : 
    1699         4849 :   gcc_assert (sym || c);
    1700              : 
    1701              :   /* Build the namelist object name.  */
    1702         4849 :   if (sym && sym->attr.use_rename && sym->ns->use_stmts->rename
    1703           73 :       && strlen(sym->ns->use_stmts->rename->local_name) > 0
    1704           36 :       && strcmp(sym->ns->use_stmts->rename->use_name, var_name) == 0)
    1705           18 :     string = gfc_build_cstring_const (sym->ns->use_stmts->rename->local_name);
    1706              :   else
    1707         4831 :     string = gfc_build_cstring_const (var_name);
    1708         4849 :   string = gfc_build_addr_expr (pchar_type_node, string);
    1709              : 
    1710              :   /* Build ts, as and data address using symbol or component.  */
    1711              : 
    1712         4849 :   ts = sym ? &sym->ts : &c->ts;
    1713              : 
    1714         4849 :   if (ts->type != BT_CLASS)
    1715         4831 :     as = sym ? sym->as : c->as;
    1716              :   else
    1717           18 :     as = sym ? CLASS_DATA (sym)->as : CLASS_DATA (c)->as;
    1718              : 
    1719         4849 :   addr_expr = nml_get_addr_expr (sym, c, base_addr);
    1720              : 
    1721         4849 :   if (as)
    1722         1951 :     rank = as->rank;
    1723              : 
    1724         1951 :   if (rank)
    1725              :     {
    1726         1951 :       decl = sym ? sym->backend_decl : c->backend_decl;
    1727         1951 :       if (sym && sym->attr.dummy)
    1728          325 :         decl = build_fold_indirect_ref_loc (input_location, decl);
    1729              : 
    1730         1951 :       if (ts->type == BT_CLASS)
    1731           12 :         decl = gfc_class_data_get (decl);
    1732         1951 :       dt =  TREE_TYPE (decl);
    1733         1951 :       dtype = gfc_get_dtype (dt);
    1734              :     }
    1735              :   else
    1736              :     {
    1737         2898 :       dt =  gfc_typenode_for_spec (ts);
    1738         2898 :       dtype = gfc_get_dtype_rank_type (0, dt);
    1739              :     }
    1740              : 
    1741              :   /* Build up the arguments for the transfer call.
    1742              :      The call for the scalar part transfers:
    1743              :      (address, name, type, kind or string_length, dtype)  */
    1744              : 
    1745         4849 :   dt_parm_addr = gfc_build_addr_expr (NULL_TREE, dt_parm);
    1746              : 
    1747              :   /* Check if the derived type has a specific DTIO for the mode.
    1748              :      Note that although namelist io is forbidden to have a format
    1749              :      list, the specific subroutine is of the formatted kind.  */
    1750         4849 :   if (ts->type == BT_DERIVED || ts->type == BT_CLASS)
    1751              :     {
    1752          956 :       gfc_symbol *derived;
    1753          956 :       if (ts->type==BT_CLASS)
    1754           18 :         derived = ts->u.derived->components->ts.u.derived;
    1755              :       else
    1756          938 :         derived = ts->u.derived;
    1757              : 
    1758          956 :       gfc_symtree *tb_io_st = gfc_find_typebound_dtio_proc (derived,
    1759              :                                                         last_dt == WRITE, true);
    1760              : 
    1761          956 :       if (ts->type == BT_CLASS && tb_io_st)
    1762              :         {
    1763              :           // polymorphic DTIO call  (based on the dynamic type)
    1764           18 :           gfc_se se;
    1765           18 :           gfc_symtree *st = gfc_find_symtree (sym->ns->sym_root, sym->name);
    1766              :           // build vtable expr
    1767           18 :           gfc_expr *expr = gfc_get_variable_expr (st);
    1768           18 :           gfc_add_vptr_component (expr);
    1769           18 :           gfc_init_se (&se, NULL);
    1770           18 :           se.want_pointer = 1;
    1771           18 :           gfc_conv_expr (&se, expr);
    1772           18 :           vtable = se.expr;
    1773              :           // build dtio expr
    1774           18 :           gfc_add_component_ref (expr,
    1775           18 :                                 tb_io_st->n.tb->u.generic->specific_st->name);
    1776           18 :           gfc_init_se (&se, NULL);
    1777           18 :           se.want_pointer = 1;
    1778           18 :           gfc_conv_expr (&se, expr);
    1779           18 :           gfc_free_expr (expr);
    1780           18 :           dtio_proc = se.expr;
    1781           18 :         }
    1782              :       else
    1783              :         {
    1784              :           // non-polymorphic DTIO call (based on the declared type)
    1785          938 :           gfc_symbol *dtio_sub = gfc_find_specific_dtio_proc (derived,
    1786              :                                                         last_dt == WRITE, true);
    1787          938 :           if (dtio_sub != NULL)
    1788              :             {
    1789           78 :               dtio_proc = gfc_get_symbol_decl (dtio_sub);
    1790           78 :               dtio_proc = gfc_build_addr_expr (NULL, dtio_proc);
    1791           78 :               gfc_symbol *vtab = gfc_find_derived_vtab (derived);
    1792           78 :               vtable = vtab->backend_decl;
    1793           78 :               if (vtable == NULL_TREE)
    1794            0 :                 vtable = gfc_get_symbol_decl (vtab);
    1795           78 :               vtable = gfc_build_addr_expr (pvoid_type_node, vtable);
    1796              :             }
    1797              :         }
    1798              :     }
    1799              : 
    1800         4849 :   if (ts->type == BT_CHARACTER)
    1801         1590 :     tmp = ts->u.cl->backend_decl;
    1802              :   else
    1803         3259 :     tmp = build_int_cst (gfc_charlen_type_node, 0);
    1804              : 
    1805         4849 :   int abi_kind = gfc_type_abi_kind (ts);
    1806         4849 :   if (dtio_proc == null_pointer_node)
    1807         4753 :     tmp = build_call_expr_loc (input_location, iocall[IOCALL_SET_NML_VAL], 6,
    1808              :                                dt_parm_addr, addr_expr, string,
    1809         4753 :                                build_int_cst (gfc_int4_type_node, abi_kind),
    1810              :                                tmp, dtype);
    1811              :   else
    1812           96 :     tmp = build_call_expr_loc (input_location, iocall[IOCALL_SET_NML_DTIO_VAL],
    1813              :                                8, dt_parm_addr, addr_expr, string,
    1814           96 :                                build_int_cst (gfc_int4_type_node, abi_kind),
    1815              :                                tmp, dtype, dtio_proc, vtable);
    1816         4849 :   gfc_add_expr_to_block (block, tmp);
    1817              : 
    1818              :   /* If the object is an array, transfer rank times:
    1819              :      (null pointer, name, stride, lbound, ubound)  */
    1820              : 
    1821        11709 :   for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
    1822              :     {
    1823         2011 :       tmp = build_call_expr_loc (input_location,
    1824              :                              iocall[IOCALL_SET_NML_VAL_DIM], 5,
    1825              :                              dt_parm_addr,
    1826         2011 :                              build_int_cst (gfc_int4_type_node, n_dim),
    1827              :                              gfc_conv_array_stride (decl, n_dim),
    1828              :                              gfc_conv_array_lbound (decl, n_dim),
    1829              :                              gfc_conv_array_ubound (decl, n_dim));
    1830         2011 :       gfc_add_expr_to_block (block, tmp);
    1831              :     }
    1832              : 
    1833         4849 :   if (gfc_bt_struct (ts->type) && ts->u.derived->components
    1834          938 :       && dtio_proc == null_pointer_node)
    1835              :     {
    1836          860 :       gfc_component *cmp;
    1837              : 
    1838              :       /* Provide the RECORD_TYPE to build component references.  */
    1839              : 
    1840          860 :       tree expr = build_fold_indirect_ref_loc (input_location,
    1841              :                                            addr_expr);
    1842              : 
    1843         2704 :       for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
    1844              :         {
    1845         3688 :           char *full_name = nml_full_name (var_name, cmp->name,
    1846         1844 :                                            ts->u.derived->attr.extension);
    1847         1844 :           transfer_namelist_element (block,
    1848              :                                      full_name,
    1849              :                                      NULL, cmp, expr);
    1850         1844 :           free (full_name);
    1851              :         }
    1852              :     }
    1853         4849 : }
    1854              : 
    1855              : #undef IARG
    1856              : 
    1857              : /* Create a data transfer statement.  Not all of the fields are valid
    1858              :    for both reading and writing, but improper use has been filtered
    1859              :    out by now.  */
    1860              : 
    1861              : static tree
    1862        31825 : build_dt (tree function, gfc_code * code)
    1863              : {
    1864        31825 :   stmtblock_t block, post_block, post_end_block, post_iu_block;
    1865        31825 :   gfc_dt *dt;
    1866        31825 :   tree tmp, var;
    1867        31825 :   gfc_expr *nmlname;
    1868        31825 :   gfc_namelist *nml;
    1869        31825 :   unsigned int mask = 0;
    1870              : 
    1871        31825 :   gfc_start_block (&block);
    1872        31825 :   gfc_init_block (&post_block);
    1873        31825 :   gfc_init_block (&post_end_block);
    1874        31825 :   gfc_init_block (&post_iu_block);
    1875              : 
    1876        31825 :   var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
    1877              : 
    1878        31825 :   set_error_locus (&block, var, &code->loc);
    1879              : 
    1880        31825 :   if (last_dt == IOLENGTH)
    1881              :     {
    1882           84 :       gfc_inquire *inq;
    1883              : 
    1884           84 :       inq = code->ext.inquire;
    1885              : 
    1886              :       /* First check that preconditions are met.  */
    1887           84 :       gcc_assert (inq != NULL);
    1888           84 :       gcc_assert (inq->iolength != NULL);
    1889              : 
    1890              :       /* Connect to the iolength variable.  */
    1891           84 :       mask |= set_parameter_ref (&block, &post_end_block, var,
    1892              :                                  IOPARM_dt_iolength, inq->iolength);
    1893           84 :       dt = NULL;
    1894              :     }
    1895              :   else
    1896              :     {
    1897        31741 :       dt = code->ext.dt;
    1898        31741 :       gcc_assert (dt != NULL);
    1899              :     }
    1900              : 
    1901        31825 :   if (dt && dt->io_unit)
    1902              :     {
    1903        31741 :       if (dt->io_unit->ts.type == BT_CHARACTER)
    1904              :         {
    1905         9981 :           mask |= set_internal_unit (&block, &post_iu_block,
    1906              :                                      var, dt->io_unit);
    1907         9981 :           set_parameter_const (&block, var, IOPARM_common_unit,
    1908         9981 :                                dt->io_unit->ts.kind == 1 ?
    1909              :                                 GFC_INTERNAL_UNIT : GFC_INTERNAL_UNIT4);
    1910              :         }
    1911              :     }
    1912              :   else
    1913           84 :     set_parameter_const (&block, var, IOPARM_common_unit, 0);
    1914              : 
    1915        10065 :   if (dt)
    1916              :     {
    1917        31741 :       if (dt->iomsg)
    1918          422 :         mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
    1919              :                             dt->iomsg);
    1920              : 
    1921        31741 :       if (dt->iostat)
    1922         1778 :         mask |= set_parameter_ref (&block, &post_end_block, var,
    1923              :                                    IOPARM_common_iostat, dt->iostat);
    1924              : 
    1925        31741 :       if (dt->err)
    1926          249 :         mask |= IOPARM_common_err;
    1927              : 
    1928        31741 :       if (dt->eor)
    1929           30 :         mask |= IOPARM_common_eor;
    1930              : 
    1931        31741 :       if (dt->end)
    1932          556 :         mask |= IOPARM_common_end;
    1933              : 
    1934        31741 :       if (dt->id)
    1935           19 :         mask |= set_parameter_ref (&block, &post_end_block, var,
    1936              :                                    IOPARM_dt_id, dt->id);
    1937              : 
    1938        31741 :       if (dt->pos)
    1939          168 :         mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos);
    1940              : 
    1941        31741 :       if (dt->asynchronous)
    1942          194 :         mask |= set_string (&block, &post_block, var,
    1943              :                             IOPARM_dt_asynchronous, dt->asynchronous);
    1944              : 
    1945        31741 :       if (dt->blank)
    1946           13 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
    1947              :                             dt->blank);
    1948              : 
    1949        31741 :       if (dt->decimal)
    1950          141 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_decimal,
    1951              :                             dt->decimal);
    1952              : 
    1953        31741 :       if (dt->delim)
    1954            2 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_delim,
    1955              :                             dt->delim);
    1956              : 
    1957        31741 :       if (dt->pad)
    1958           79 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_pad,
    1959              :                             dt->pad);
    1960              : 
    1961        31741 :       if (dt->round)
    1962          313 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_round,
    1963              :                             dt->round);
    1964              : 
    1965        31741 :       if (dt->sign)
    1966           13 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_sign,
    1967              :                             dt->sign);
    1968              : 
    1969        31741 :       if (dt->rec)
    1970          493 :         mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
    1971              : 
    1972        31741 :       if (dt->advance)
    1973          359 :         mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
    1974              :                             dt->advance);
    1975              : 
    1976        31741 :       if (dt->format_expr)
    1977        12212 :         mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
    1978              :                             dt->format_expr);
    1979              : 
    1980        31741 :       if (dt->format_label)
    1981              :         {
    1982        15979 :           if (dt->format_label == &format_asterisk)
    1983        14199 :             mask |= IOPARM_dt_list_format;
    1984              :           else
    1985         1780 :             mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
    1986         1780 :                                 dt->format_label->format);
    1987              :         }
    1988              : 
    1989        31741 :       if (dt->size)
    1990           55 :         mask |= set_parameter_ref (&block, &post_end_block, var,
    1991              :                                    IOPARM_dt_size, dt->size);
    1992              : 
    1993        31741 :       if (dt->udtio)
    1994          364 :         mask |= IOPARM_dt_dtio;
    1995              : 
    1996        31741 :       if (dt->dec_ext)
    1997          480 :         mask |= IOPARM_dt_dec_ext;
    1998              : 
    1999        31741 :       if (dt->namelist)
    2000              :         {
    2001         1186 :           if (dt->format_expr || dt->format_label)
    2002            0 :             gfc_internal_error ("build_dt: format with namelist");
    2003              : 
    2004         2372 :           nmlname = gfc_get_character_expr (gfc_default_character_kind, NULL,
    2005              :                                             dt->namelist->name,
    2006         1186 :                                             strlen (dt->namelist->name));
    2007              : 
    2008         1186 :           mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
    2009              :                               nmlname);
    2010              : 
    2011         1186 :           gfc_free_expr (nmlname);
    2012              : 
    2013         1186 :           if (last_dt == READ)
    2014          866 :             mask |= IOPARM_dt_namelist_read_mode;
    2015              : 
    2016         1186 :           set_parameter_const (&block, var, IOPARM_common_flags, mask);
    2017              : 
    2018         1186 :           dt_parm = var;
    2019              : 
    2020         4191 :           for (nml = dt->namelist->namelist; nml; nml = nml->next)
    2021         3005 :             transfer_namelist_element (&block, nml->sym->name, nml->sym,
    2022              :                                        NULL, NULL_TREE);
    2023              :         }
    2024              :       else
    2025        30555 :         set_parameter_const (&block, var, IOPARM_common_flags, mask);
    2026              : 
    2027        31741 :       if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
    2028        21760 :         set_parameter_value_chk (&block, dt->iostat, var,
    2029              :                                  IOPARM_common_unit, dt->io_unit);
    2030              :     }
    2031              :   else
    2032           84 :     set_parameter_const (&block, var, IOPARM_common_flags, mask);
    2033              : 
    2034        31825 :   tmp = gfc_build_addr_expr (NULL_TREE, var);
    2035        31825 :   tmp = build_call_expr_loc (UNKNOWN_LOCATION,
    2036              :                          function, 1, tmp);
    2037        31825 :   gfc_add_expr_to_block (&block, tmp);
    2038              : 
    2039        31825 :   gfc_add_block_to_block (&block, &post_block);
    2040              : 
    2041        31825 :   dt_parm = var;
    2042        31825 :   dt_post_end_block = &post_end_block;
    2043              : 
    2044              :   /* Set implied do loop exit condition.  */
    2045        31825 :   if (last_dt == READ || last_dt == WRITE)
    2046              :     {
    2047        31741 :       gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
    2048              : 
    2049        31741 :       tmp = fold_build3_loc (input_location, COMPONENT_REF,
    2050              :                              st_parameter[IOPARM_ptype_common].type,
    2051        31741 :                              dt_parm, TYPE_FIELDS (TREE_TYPE (dt_parm)),
    2052              :                              NULL_TREE);
    2053        31741 :       tmp = fold_build3_loc (input_location, COMPONENT_REF,
    2054        31741 :                              TREE_TYPE (p->field), tmp, p->field, NULL_TREE);
    2055        31741 :       tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (tmp),
    2056        31741 :                              tmp, build_int_cst (TREE_TYPE (tmp),
    2057              :                              IOPARM_common_libreturn_mask));
    2058              :     }
    2059              :   else /* IOLENGTH */
    2060              :     tmp = NULL_TREE;
    2061              : 
    2062        31825 :   gfc_add_expr_to_block (&block, gfc_trans_code_cond (code->block->next, tmp));
    2063              : 
    2064        31825 :   gfc_add_block_to_block (&block, &post_iu_block);
    2065              : 
    2066        31825 :   dt_parm = NULL;
    2067        31825 :   dt_post_end_block = NULL;
    2068              : 
    2069        31825 :   return gfc_finish_block (&block);
    2070              : }
    2071              : 
    2072              : 
    2073              : /* Translate the IOLENGTH form of an INQUIRE statement.  We treat
    2074              :    this as a third sort of data transfer statement, except that
    2075              :    lengths are summed instead of actually transferring any data.  */
    2076              : 
    2077              : tree
    2078           84 : gfc_trans_iolength (gfc_code * code)
    2079              : {
    2080           84 :   last_dt = IOLENGTH;
    2081           84 :   return build_dt (iocall[IOCALL_IOLENGTH], code);
    2082              : }
    2083              : 
    2084              : 
    2085              : /* Translate a READ statement.  */
    2086              : 
    2087              : tree
    2088         6306 : gfc_trans_read (gfc_code * code)
    2089              : {
    2090         6306 :   last_dt = READ;
    2091         6306 :   return build_dt (iocall[IOCALL_READ], code);
    2092              : }
    2093              : 
    2094              : 
    2095              : /* Translate a WRITE statement */
    2096              : 
    2097              : tree
    2098        25435 : gfc_trans_write (gfc_code * code)
    2099              : {
    2100        25435 :   last_dt = WRITE;
    2101        25435 :   return build_dt (iocall[IOCALL_WRITE], code);
    2102              : }
    2103              : 
    2104              : 
    2105              : /* Finish a data transfer statement.  */
    2106              : 
    2107              : tree
    2108        31825 : gfc_trans_dt_end (gfc_code * code)
    2109              : {
    2110        31825 :   tree function, tmp;
    2111        31825 :   stmtblock_t block;
    2112              : 
    2113        31825 :   gfc_init_block (&block);
    2114              : 
    2115        31825 :   switch (last_dt)
    2116              :     {
    2117         6306 :     case READ:
    2118         6306 :       function = iocall[IOCALL_READ_DONE];
    2119         6306 :       break;
    2120              : 
    2121        25435 :     case WRITE:
    2122        25435 :       function = iocall[IOCALL_WRITE_DONE];
    2123        25435 :       break;
    2124              : 
    2125           84 :     case IOLENGTH:
    2126           84 :       function = iocall[IOCALL_IOLENGTH_DONE];
    2127           84 :       break;
    2128              : 
    2129            0 :     default:
    2130            0 :       gcc_unreachable ();
    2131              :     }
    2132              : 
    2133        31825 :   tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
    2134        31825 :   tmp = build_call_expr_loc (input_location,
    2135              :                          function, 1, tmp);
    2136        31825 :   gfc_add_expr_to_block (&block, tmp);
    2137        31825 :   gfc_add_block_to_block (&block, dt_post_end_block);
    2138        31825 :   gfc_init_block (dt_post_end_block);
    2139              : 
    2140        31825 :   if (last_dt != IOLENGTH)
    2141              :     {
    2142        31741 :       gcc_assert (code->ext.dt != NULL);
    2143        31741 :       io_result (&block, dt_parm, code->ext.dt->err,
    2144              :                  code->ext.dt->end, code->ext.dt->eor);
    2145              :     }
    2146              : 
    2147        31825 :   return gfc_finish_block (&block);
    2148              : }
    2149              : 
    2150              : static void
    2151              : transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
    2152              :                gfc_code * code, tree vptr);
    2153              : 
    2154              : /* Given an array field in a derived type variable, generate the code
    2155              :    for the loop that iterates over array elements, and the code that
    2156              :    accesses those array elements.  Use transfer_expr to generate code
    2157              :    for transferring that element.  Because elements may also be
    2158              :    derived types, transfer_expr and transfer_array_component are mutually
    2159              :    recursive.  */
    2160              : 
    2161              : static tree
    2162           81 : transfer_array_component (tree expr, gfc_component * cm, locus * where)
    2163              : {
    2164           81 :   tree tmp;
    2165           81 :   stmtblock_t body;
    2166           81 :   stmtblock_t block;
    2167           81 :   gfc_loopinfo loop;
    2168           81 :   int n;
    2169           81 :   gfc_ss *ss;
    2170           81 :   gfc_se se;
    2171           81 :   gfc_array_info *ss_array;
    2172              : 
    2173           81 :   gfc_start_block (&block);
    2174           81 :   gfc_init_se (&se, NULL);
    2175              : 
    2176              :   /* Create and initialize Scalarization Status.  Unlike in
    2177              :      gfc_trans_transfer, we can't simply use gfc_walk_expr to take
    2178              :      care of this task, because we don't have a gfc_expr at hand.
    2179              :      Build one manually, as in gfc_trans_subarray_assign.  */
    2180              : 
    2181           81 :   ss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
    2182              :                          GFC_SS_COMPONENT);
    2183           81 :   ss_array = &ss->info->data.array;
    2184              : 
    2185           81 :   if (cm->attr.pdt_array)
    2186           12 :     ss_array->shape = NULL;
    2187              :   else
    2188           69 :     ss_array->shape = gfc_get_shape (cm->as->rank);
    2189              : 
    2190           81 :   ss_array->descriptor = expr;
    2191           81 :   ss_array->data = gfc_conv_array_data (expr);
    2192           81 :   ss_array->offset = gfc_conv_array_offset (expr);
    2193          162 :   for (n = 0; n < cm->as->rank; n++)
    2194              :     {
    2195           81 :       ss_array->start[n] = gfc_conv_array_lbound (expr, n);
    2196           81 :       ss_array->stride[n] = gfc_index_one_node;
    2197              : 
    2198           81 :       if (cm->attr.pdt_array)
    2199           12 :         ss_array->end[n] = gfc_conv_array_ubound (expr, n);
    2200              :       else
    2201              :         {
    2202           69 :           mpz_init (ss_array->shape[n]);
    2203           69 :           mpz_sub (ss_array->shape[n], cm->as->upper[n]->value.integer,
    2204           69 :                    cm->as->lower[n]->value.integer);
    2205           69 :           mpz_add_ui (ss_array->shape[n], ss_array->shape[n], 1);
    2206              :         }
    2207              :     }
    2208              : 
    2209              :   /* Once we got ss, we use scalarizer to create the loop.  */
    2210              : 
    2211           81 :   gfc_init_loopinfo (&loop);
    2212           81 :   gfc_add_ss_to_loop (&loop, ss);
    2213           81 :   gfc_conv_ss_startstride (&loop);
    2214           81 :   gfc_conv_loop_setup (&loop, where);
    2215           81 :   gfc_mark_ss_chain_used (ss, 1);
    2216           81 :   gfc_start_scalarized_body (&loop, &body);
    2217              : 
    2218           81 :   gfc_copy_loopinfo_to_se (&se, &loop);
    2219           81 :   se.ss = ss;
    2220              : 
    2221              :   /* gfc_conv_tmp_array_ref assumes that se.expr contains the array.  */
    2222           81 :   se.expr = expr;
    2223           81 :   gfc_conv_tmp_array_ref (&se);
    2224              : 
    2225              :   /* Now se.expr contains an element of the array.  Take the address and pass
    2226              :      it to the IO routines.  */
    2227           81 :   tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
    2228           81 :   transfer_expr (&se, &cm->ts, tmp, NULL, NULL_TREE);
    2229              : 
    2230              :   /* We are done now with the loop body.  Wrap up the scalarizer and
    2231              :      return.  */
    2232              : 
    2233           81 :   gfc_add_block_to_block (&body, &se.pre);
    2234           81 :   gfc_add_block_to_block (&body, &se.post);
    2235              : 
    2236           81 :   gfc_trans_scalarizing_loops (&loop, &body);
    2237              : 
    2238           81 :   gfc_add_block_to_block (&block, &loop.pre);
    2239           81 :   gfc_add_block_to_block (&block, &loop.post);
    2240              : 
    2241           81 :   if (!cm->attr.pdt_array)
    2242              :     {
    2243           69 :       gcc_assert (ss_array->shape != NULL);
    2244           69 :       gfc_free_shape (&ss_array->shape, cm->as->rank);
    2245              :     }
    2246           81 :   gfc_cleanup_loop (&loop);
    2247              : 
    2248           81 :   return gfc_finish_block (&block);
    2249              : }
    2250              : 
    2251              : 
    2252              : /* Helper function for transfer_expr that looks for the DTIO procedure
    2253              :    either as a typebound binding or in a generic interface. If present,
    2254              :    the address expression of the procedure is returned. It is assumed
    2255              :    that the procedure interface has been checked during resolution.  */
    2256              : 
    2257              : static tree
    2258          492 : get_dtio_proc (gfc_typespec * ts, gfc_code * code, gfc_symbol **dtio_sub)
    2259              : {
    2260          492 :   gfc_symbol *derived;
    2261          492 :   bool formatted = false;
    2262          492 :   gfc_dt *dt = code->ext.dt;
    2263              : 
    2264              :   /* Determine when to use the formatted DTIO procedure.  */
    2265          492 :   if (dt && (dt->format_expr || dt->format_label))
    2266          492 :     formatted = true;
    2267              : 
    2268          492 :   if (ts->type == BT_CLASS)
    2269           48 :     derived = ts->u.derived->components->ts.u.derived;
    2270              :   else
    2271          444 :     derived = ts->u.derived;
    2272              : 
    2273          492 :   gfc_symtree *tb_io_st = gfc_find_typebound_dtio_proc (derived,
    2274              :                                                   last_dt == WRITE, formatted);
    2275          492 :   if (ts->type == BT_CLASS && tb_io_st)
    2276              :     {
    2277              :       // polymorphic DTIO call  (based on the dynamic type)
    2278           42 :       gfc_se se;
    2279           42 :       gfc_expr *expr = gfc_find_and_cut_at_last_class_ref (code->expr1);
    2280           42 :       gfc_add_vptr_component (expr);
    2281           42 :       gfc_add_component_ref (expr,
    2282           42 :                              tb_io_st->n.tb->u.generic->specific_st->name);
    2283           42 :       *dtio_sub = tb_io_st->n.tb->u.generic->specific->u.specific->n.sym;
    2284           42 :       gfc_init_se (&se, NULL);
    2285           42 :       se.want_pointer = 1;
    2286           42 :       gfc_conv_expr (&se, expr);
    2287           42 :       gfc_free_expr (expr);
    2288           42 :       return se.expr;
    2289              :     }
    2290              :   else
    2291              :     {
    2292              :       // non-polymorphic DTIO call (based on the declared type)
    2293          450 :       *dtio_sub = gfc_find_specific_dtio_proc (derived, last_dt == WRITE,
    2294              :                                               formatted);
    2295              : 
    2296          450 :       if (*dtio_sub)
    2297          450 :         return gfc_build_addr_expr (NULL, gfc_get_symbol_decl (*dtio_sub));
    2298              :     }
    2299              : 
    2300              :   return NULL_TREE;
    2301              : }
    2302              : 
    2303              : /* Generate the call for a scalar transfer node.  */
    2304              : 
    2305              : static void
    2306        43006 : transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr,
    2307              :                gfc_code * code, tree vptr)
    2308              : {
    2309        43006 :   tree tmp, function, arg2, arg3, field, expr;
    2310        43006 :   gfc_component *c;
    2311        43006 :   int kind;
    2312              : 
    2313              :   /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
    2314              :      the user says something like: print *, 'c_null_ptr: ', c_null_ptr
    2315              :      We need to translate the expression to a constant if it's either
    2316              :      C_NULL_PTR or C_NULL_FUNPTR.  We could also get a user variable of
    2317              :      type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
    2318              :      BT_DERIVED (could have been changed by gfc_conv_expr).  */
    2319        43006 :   if ((ts->type == BT_DERIVED || ts->type == BT_INTEGER)
    2320        14216 :       && ts->u.derived != NULL
    2321          695 :       && (ts->is_iso_c == 1 || ts->u.derived->ts.is_iso_c == 1))
    2322              :     {
    2323            0 :       ts->type = BT_INTEGER;
    2324            0 :       ts->kind = gfc_index_integer_kind;
    2325              :     }
    2326              : 
    2327              :   /* gfortran reaches here for "print *, c_loc(xxx)".  */
    2328        43006 :   if (ts->type == BT_VOID
    2329            0 :       && code->expr1 && code->expr1->ts.type == BT_VOID
    2330            0 :       && code->expr1->symtree
    2331            0 :       && strcmp (code->expr1->symtree->name, "c_loc") == 0)
    2332              :     {
    2333            0 :       ts->type = BT_INTEGER;
    2334            0 :       ts->kind = gfc_index_integer_kind;
    2335              :     }
    2336              : 
    2337        43006 :   kind = gfc_type_abi_kind (ts);
    2338        43006 :   function = NULL;
    2339        43006 :   arg2 = NULL;
    2340        43006 :   arg3 = NULL;
    2341              : 
    2342        43006 :   switch (ts->type)
    2343              :     {
    2344        13521 :     case BT_INTEGER:
    2345        13521 :       arg2 = build_int_cst (integer_type_node, kind);
    2346        13521 :       if (last_dt == READ)
    2347         2418 :         function = iocall[IOCALL_X_INTEGER];
    2348              :       else
    2349        11103 :         function = iocall[IOCALL_X_INTEGER_WRITE];
    2350              : 
    2351              :       break;
    2352              : 
    2353          187 :     case BT_UNSIGNED:
    2354          187 :       arg2 = build_int_cst (unsigned_type_node, kind);
    2355          187 :       if (last_dt == READ)
    2356           72 :         function = iocall[IOCALL_X_UNSIGNED];
    2357              :       else
    2358          115 :         function = iocall[IOCALL_X_UNSIGNED_WRITE];
    2359              : 
    2360              :       break;
    2361              : 
    2362         8557 :     case BT_REAL:
    2363         8557 :       arg2 = build_int_cst (integer_type_node, kind);
    2364         8557 :       if (last_dt == READ)
    2365              :         {
    2366         1617 :           if ((gfc_real16_is_float128 && kind == 16) || kind == 17)
    2367           84 :             function = iocall[IOCALL_X_REAL128];
    2368              :           else
    2369         1533 :             function = iocall[IOCALL_X_REAL];
    2370              :         }
    2371              :       else
    2372              :         {
    2373         6940 :           if ((gfc_real16_is_float128 && kind == 16) || kind == 17)
    2374          522 :             function = iocall[IOCALL_X_REAL128_WRITE];
    2375              :           else
    2376         6418 :             function = iocall[IOCALL_X_REAL_WRITE];
    2377              :         }
    2378              : 
    2379              :       break;
    2380              : 
    2381          791 :     case BT_COMPLEX:
    2382          791 :       arg2 = build_int_cst (integer_type_node, kind);
    2383          791 :       if (last_dt == READ)
    2384              :         {
    2385          355 :           if ((gfc_real16_is_float128 && kind == 16) || kind == 17)
    2386            0 :             function = iocall[IOCALL_X_COMPLEX128];
    2387              :           else
    2388          355 :             function = iocall[IOCALL_X_COMPLEX];
    2389              :         }
    2390              :       else
    2391              :         {
    2392          436 :           if ((gfc_real16_is_float128 && kind == 16) || kind == 17)
    2393            3 :             function = iocall[IOCALL_X_COMPLEX128_WRITE];
    2394              :           else
    2395          433 :             function = iocall[IOCALL_X_COMPLEX_WRITE];
    2396              :         }
    2397              : 
    2398              :       break;
    2399              : 
    2400         1073 :     case BT_LOGICAL:
    2401         1073 :       arg2 = build_int_cst (integer_type_node, kind);
    2402         1073 :       if (last_dt == READ)
    2403          120 :         function = iocall[IOCALL_X_LOGICAL];
    2404              :       else
    2405          953 :         function = iocall[IOCALL_X_LOGICAL_WRITE];
    2406              : 
    2407              :       break;
    2408              : 
    2409        18116 :     case BT_CHARACTER:
    2410        18116 :       if (kind == 4)
    2411              :         {
    2412          587 :           if (se->string_length)
    2413              :             arg2 = se->string_length;
    2414              :           else
    2415              :             {
    2416            0 :               tmp = build_fold_indirect_ref_loc (input_location,
    2417              :                                              addr_expr);
    2418            0 :               gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
    2419            0 :               arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
    2420            0 :               arg2 = fold_convert (gfc_charlen_type_node, arg2);
    2421              :             }
    2422          587 :           arg3 = build_int_cst (integer_type_node, kind);
    2423          587 :           if (last_dt == READ)
    2424          132 :             function = iocall[IOCALL_X_CHARACTER_WIDE];
    2425              :           else
    2426          455 :             function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
    2427              : 
    2428          587 :           tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
    2429          587 :           tmp = build_call_expr_loc (input_location,
    2430              :                                  function, 4, tmp, addr_expr, arg2, arg3);
    2431          587 :           gfc_add_expr_to_block (&se->pre, tmp);
    2432          587 :           gfc_add_block_to_block (&se->pre, &se->post);
    2433          587 :           return;
    2434              :         }
    2435              :       /* Fall through.  */
    2436        17541 :     case BT_HOLLERITH:
    2437        17541 :       if (se->string_length)
    2438              :         arg2 = se->string_length;
    2439              :       else
    2440              :         {
    2441          120 :           tmp = build_fold_indirect_ref_loc (input_location,
    2442              :                                          addr_expr);
    2443          120 :           gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
    2444          120 :           arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
    2445              :         }
    2446        17541 :       if (last_dt == READ)
    2447         1638 :         function = iocall[IOCALL_X_CHARACTER];
    2448              :       else
    2449        15903 :         function = iocall[IOCALL_X_CHARACTER_WRITE];
    2450              : 
    2451              :       break;
    2452              : 
    2453          749 :     case_bt_struct:
    2454          749 :     case BT_CLASS:
    2455          749 :       if (gfc_bt_struct (ts->type) || ts->type == BT_CLASS)
    2456              :         {
    2457          749 :           gfc_symbol *derived;
    2458          749 :           gfc_symbol *dtio_sub = NULL;
    2459              :           /* Test for a specific DTIO subroutine.  */
    2460          749 :           if (ts->type == BT_DERIVED)
    2461          695 :             derived = ts->u.derived;
    2462              :           else
    2463           54 :             derived = ts->u.derived->components->ts.u.derived;
    2464              : 
    2465          749 :           if (derived->attr.has_dtio_procs)
    2466          492 :             arg2 = get_dtio_proc (ts, code, &dtio_sub);
    2467              : 
    2468          749 :           if ((dtio_sub != NULL) && (last_dt != IOLENGTH))
    2469              :             {
    2470          480 :               tree decl;
    2471          480 :               decl = build_fold_indirect_ref_loc (input_location,
    2472              :                                                   se->expr);
    2473              :               /* Remember that the first dummy of the DTIO subroutines
    2474              :                  is CLASS(derived) for extensible derived types, so the
    2475              :                  conversion must be done here for derived type and for
    2476              :                  scalarized CLASS array element io-list objects.  */
    2477          480 :               if ((ts->type == BT_DERIVED
    2478          432 :                    && !(ts->u.derived->attr.sequence
    2479          419 :                         || ts->u.derived->attr.is_bind_c))
    2480          505 :                   || (ts->type == BT_CLASS
    2481           48 :                       && !GFC_CLASS_TYPE_P (TREE_TYPE (decl))))
    2482          443 :                 gfc_conv_derived_to_class (se, code->expr1,
    2483          443 :                                            dtio_sub->formal->sym, vptr, false,
    2484              :                                            false, "transfer");
    2485          480 :               addr_expr = se->expr;
    2486          480 :               function = iocall[IOCALL_X_DERIVED];
    2487          480 :               break;
    2488              :             }
    2489          269 :           else if (gfc_bt_struct (ts->type))
    2490              :             {
    2491              :               /* Recurse into the elements of the derived type.  */
    2492          269 :               expr = gfc_evaluate_now (addr_expr, &se->pre);
    2493          269 :               expr = build_fold_indirect_ref_loc (input_location, expr);
    2494              : 
    2495              :               /* Make sure that the derived type has been built.  An external
    2496              :                  function, if only referenced in an io statement, requires this
    2497              :                  check (see PR58771).  */
    2498          269 :               if (ts->u.derived->backend_decl == NULL_TREE)
    2499            6 :                 (void) gfc_typenode_for_spec (ts);
    2500              : 
    2501          805 :               for (c = ts->u.derived->components; c; c = c->next)
    2502              :                 {
    2503              :                   /* Ignore hidden string lengths.  */
    2504          536 :                   if (c->name[0] == '_'
    2505          524 :                       || c->attr.pdt_kind || c->attr.pdt_len)
    2506           48 :                     continue;
    2507              : 
    2508          488 :                   field = c->backend_decl;
    2509          488 :                   gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
    2510              : 
    2511          488 :                   tmp = fold_build3_loc (UNKNOWN_LOCATION,
    2512          488 :                                          COMPONENT_REF, TREE_TYPE (field),
    2513              :                                          expr, field, NULL_TREE);
    2514              : 
    2515          488 :                   if (c->attr.dimension)
    2516              :                     {
    2517           81 :                       tmp = transfer_array_component (tmp, c,
    2518              :                                                       code ? &code->loc
    2519              :                                                       : NULL);
    2520           81 :                       gfc_add_expr_to_block (&se->pre, tmp);
    2521              :                     }
    2522              :                   else
    2523              :                     {
    2524          407 :                       tree strlen = NULL_TREE;
    2525              : 
    2526          407 :                       if (!c->attr.pointer && !c->attr.pdt_string)
    2527          395 :                         tmp = gfc_build_addr_expr (NULL_TREE, tmp);
    2528              : 
    2529              :                       /* Use the hidden string length for pdt strings.  */
    2530          407 :                       if (c->attr.pdt_string
    2531           12 :                           && gfc_deferred_strlen (c, &strlen)
    2532          419 :                           && strlen != NULL_TREE)
    2533              :                         {
    2534           12 :                           strlen = fold_build3_loc (UNKNOWN_LOCATION,
    2535              :                                                     COMPONENT_REF,
    2536           12 :                                                     TREE_TYPE (strlen),
    2537              :                                                     expr, strlen, NULL_TREE);
    2538           12 :                           se->string_length = strlen;
    2539              :                         }
    2540              : 
    2541          407 :                       transfer_expr (se, &c->ts, tmp, code, NULL_TREE);
    2542              : 
    2543              :                       /* Reset so that the pdt string length does not propagate
    2544              :                          through to other strings.  */
    2545          407 :                       if (c->attr.pdt_string && strlen)
    2546           12 :                         se->string_length = NULL_TREE;
    2547              :                    }
    2548              :                 }
    2549          269 :               return;
    2550              :             }
    2551              :           /* If a CLASS object gets through to here, fall through and ICE.  */
    2552              :         }
    2553            0 :       gcc_fallthrough ();
    2554            0 :     default:
    2555            0 :       gfc_internal_error ("Bad IO basetype (%d)", ts->type);
    2556              :     }
    2557              : 
    2558        42150 :   tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
    2559        42150 :   tmp = build_call_expr_loc (input_location,
    2560              :                          function, 3, tmp, addr_expr, arg2);
    2561        42150 :   gfc_add_expr_to_block (&se->pre, tmp);
    2562        42150 :   gfc_add_block_to_block (&se->pre, &se->post);
    2563              : 
    2564              : }
    2565              : 
    2566              : 
    2567              : /* Generate a call to pass an array descriptor to the IO library. The
    2568              :    array should be of one of the intrinsic types.  */
    2569              : 
    2570              : static void
    2571         3206 : transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
    2572              : {
    2573         3206 :   tree tmp, charlen_arg, kind_arg, io_call;
    2574              : 
    2575         3206 :   if (ts->type == BT_CHARACTER)
    2576          539 :     charlen_arg = se->string_length;
    2577              :   else
    2578         2667 :     charlen_arg = build_int_cst (gfc_charlen_type_node, 0);
    2579              : 
    2580         3206 :   kind_arg = build_int_cst (integer_type_node, gfc_type_abi_kind (ts));
    2581              : 
    2582         3206 :   tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
    2583         3206 :   if (last_dt == READ)
    2584          898 :     io_call = iocall[IOCALL_X_ARRAY];
    2585              :   else
    2586         2308 :     io_call = iocall[IOCALL_X_ARRAY_WRITE];
    2587              : 
    2588         3206 :   tmp = build_call_expr_loc (UNKNOWN_LOCATION,
    2589              :                          io_call, 4,
    2590              :                          tmp, addr_expr, kind_arg, charlen_arg);
    2591         3206 :   gfc_add_expr_to_block (&se->pre, tmp);
    2592         3206 :   gfc_add_block_to_block (&se->pre, &se->post);
    2593         3206 : }
    2594              : 
    2595              : 
    2596              : /* gfc_trans_transfer()-- Translate a TRANSFER code node */
    2597              : 
    2598              : tree
    2599        45724 : gfc_trans_transfer (gfc_code * code)
    2600              : {
    2601        45724 :   stmtblock_t block, body;
    2602        45724 :   gfc_loopinfo loop;
    2603        45724 :   gfc_expr *expr;
    2604        45724 :   gfc_ref *ref;
    2605        45724 :   gfc_ss *ss;
    2606        45724 :   gfc_se se;
    2607        45724 :   tree tmp;
    2608        45724 :   tree vptr;
    2609        45724 :   int n;
    2610              : 
    2611        45724 :   gfc_start_block (&block);
    2612        45724 :   gfc_init_block (&body);
    2613              : 
    2614        45724 :   expr = code->expr1;
    2615        45724 :   ref = NULL;
    2616        45724 :   gfc_init_se (&se, NULL);
    2617              : 
    2618        45724 :   if (expr->rank == 0)
    2619              :     {
    2620              :       /* Transfer a scalar value.  */
    2621        39214 :       if (expr->ts.type == BT_CLASS)
    2622              :         {
    2623           24 :           se.want_pointer = 1;
    2624           24 :           gfc_conv_expr (&se, expr);
    2625           24 :           vptr = gfc_get_vptr_from_expr (se.expr);
    2626              :         }
    2627              :       else
    2628              :         {
    2629        39190 :           vptr = NULL_TREE;
    2630        39190 :           gfc_conv_expr_reference (&se, expr);
    2631              :         }
    2632        39214 :       transfer_expr (&se, &expr->ts, se.expr, code, vptr);
    2633              :     }
    2634              :   else
    2635              :     {
    2636              :       /* Transfer an array. If it is an array of an intrinsic
    2637              :          type, pass the descriptor to the library.  Otherwise
    2638              :          scalarize the transfer.  */
    2639         6510 :       if (expr->ref && !gfc_is_proc_ptr_comp (expr))
    2640              :         {
    2641         4392 :           for (ref = expr->ref; ref && ref->type != REF_ARRAY;
    2642          171 :             ref = ref->next);
    2643         4221 :           gcc_assert (ref && ref->type == REF_ARRAY);
    2644              :         }
    2645              : 
    2646              :       /* These expressions don't always have the dtype element length set
    2647              :          correctly, rendering them useless for array transfer.  */
    2648         6510 :       if (expr->ts.type != BT_CLASS
    2649         6486 :          && expr->expr_type == EXPR_VARIABLE
    2650        10707 :          && ((expr->symtree->n.sym->ts.type == BT_DERIVED && expr->ts.deferred)
    2651         4185 :              || (expr->symtree->n.sym->assoc
    2652          431 :                  && expr->symtree->n.sym->assoc->variable)
    2653         3799 :              || gfc_expr_attr (expr).pointer
    2654         3770 :              || (expr->symtree->n.sym->attr.pointer
    2655          362 :                  && gfc_expr_attr (expr).target)))
    2656          789 :         goto scalarize;
    2657              : 
    2658              :       /* With array-bounds checking enabled, force scalarization in some
    2659              :          situations, e.g., when an array index depends on a function
    2660              :          evaluation or an expression and possibly has side-effects.  */
    2661         5721 :       if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
    2662          623 :           && ref
    2663          329 :           && ref->u.ar.type == AR_SECTION)
    2664              :         {
    2665          477 :           for (n = 0; n < ref->u.ar.dimen; n++)
    2666          290 :             if (ref->u.ar.dimen_type[n] == DIMEN_ELEMENT
    2667           80 :                 && ref->u.ar.start[n])
    2668              :               {
    2669           80 :                 switch (ref->u.ar.start[n]->expr_type)
    2670              :                   {
    2671           18 :                   case EXPR_FUNCTION:
    2672           18 :                   case EXPR_OP:
    2673           18 :                     goto scalarize;
    2674              :                   default:
    2675              :                     break;
    2676              :                   }
    2677              :               }
    2678              :         }
    2679              : 
    2680         5703 :       if (!(gfc_bt_struct (expr->ts.type)
    2681              :               || expr->ts.type == BT_CLASS)
    2682         5605 :             && ref && ref->next == NULL
    2683         3206 :             && !is_subref_array (expr))
    2684              :         {
    2685         3206 :           bool seen_vector = false;
    2686              : 
    2687         3206 :           if (ref && ref->u.ar.type == AR_SECTION)
    2688              :             {
    2689         2130 :               for (n = 0; n < ref->u.ar.dimen; n++)
    2690         1223 :                 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
    2691              :                   {
    2692              :                     seen_vector = true;
    2693              :                     break;
    2694              :                   }
    2695              :             }
    2696              : 
    2697          917 :           if (seen_vector && last_dt == READ)
    2698              :             {
    2699              :               /* Create a temp, read to that and copy it back.  */
    2700            6 :               gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT, false);
    2701            6 :               tmp =  se.expr;
    2702              :             }
    2703              :           else
    2704              :             {
    2705              :               /* Get the descriptor.  */
    2706         3200 :               gfc_conv_expr_descriptor (&se, expr);
    2707         3200 :               tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
    2708              :             }
    2709              : 
    2710         3206 :           transfer_array_desc (&se, &expr->ts, tmp);
    2711         3206 :           goto finish_block_label;
    2712              :         }
    2713              : 
    2714         3304 : scalarize:
    2715              :       /* Initialize the scalarizer.  */
    2716         3304 :       ss = gfc_walk_expr (expr);
    2717         3304 :       gfc_init_loopinfo (&loop);
    2718         3304 :       gfc_add_ss_to_loop (&loop, ss);
    2719              : 
    2720              :       /* Initialize the loop.  */
    2721         3304 :       gfc_conv_ss_startstride (&loop);
    2722         3304 :       gfc_conv_loop_setup (&loop, &code->expr1->where);
    2723              : 
    2724              :       /* The main loop body.  */
    2725         3304 :       gfc_mark_ss_chain_used (ss, 1);
    2726         3304 :       gfc_start_scalarized_body (&loop, &body);
    2727              : 
    2728         3304 :       gfc_copy_loopinfo_to_se (&se, &loop);
    2729         3304 :       se.ss = ss;
    2730              : 
    2731         3304 :       gfc_conv_expr_reference (&se, expr);
    2732              : 
    2733         3304 :       if (expr->ts.type == BT_CLASS)
    2734           24 :         vptr = gfc_get_vptr_from_expr (ss->info->data.array.descriptor);
    2735              :       else
    2736              :         vptr = NULL_TREE;
    2737         3304 :       transfer_expr (&se, &expr->ts, se.expr, code, vptr);
    2738              :     }
    2739              : 
    2740        45724 :  finish_block_label:
    2741              : 
    2742        45724 :   gfc_add_block_to_block (&body, &se.pre);
    2743        45724 :   gfc_add_block_to_block (&body, &se.post);
    2744        45724 :   gfc_add_block_to_block (&body, &se.finalblock);
    2745              : 
    2746        45724 :   if (se.ss == NULL)
    2747        42420 :     tmp = gfc_finish_block (&body);
    2748              :   else
    2749              :     {
    2750         3304 :       gcc_assert (expr->rank != 0);
    2751         3304 :       gcc_assert (se.ss == gfc_ss_terminator);
    2752         3304 :       gfc_trans_scalarizing_loops (&loop, &body);
    2753              : 
    2754         3304 :       gfc_add_block_to_block (&loop.pre, &loop.post);
    2755         3304 :       tmp = gfc_finish_block (&loop.pre);
    2756         3304 :       gfc_cleanup_loop (&loop);
    2757              :     }
    2758              : 
    2759        45724 :   gfc_add_expr_to_block (&block, tmp);
    2760              : 
    2761        45724 :   return gfc_finish_block (&block);
    2762              : }
    2763              : 
    2764              : #include "gt-fortran-trans-io.h"
        

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.