]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-io.c
re PR driver/40144 (ice in common_handle_option)
[thirdparty/gcc.git] / gcc / fortran / trans-io.c
CommitLineData
6de9cd9a 1/* IO Code translation/library interface
32e8bb8e 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
7d1f1e61 3 Free Software Foundation, Inc.
6de9cd9a
DN
4 Contributed by Paul Brook
5
9fc4d79b 6This file is part of GCC.
6de9cd9a 7
9fc4d79b
TS
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
d234d788 10Software Foundation; either version 3, or (at your option) any later
9fc4d79b 11version.
6de9cd9a 12
9fc4d79b
TS
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
6de9cd9a
DN
17
18You should have received a copy of the GNU General Public License
d234d788
NC
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
21
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tree.h"
726a989a 27#include "gimple.h"
6de9cd9a
DN
28#include "ggc.h"
29#include "toplev.h"
30#include "real.h"
6de9cd9a
DN
31#include "gfortran.h"
32#include "trans.h"
33#include "trans-stmt.h"
34#include "trans-array.h"
35#include "trans-types.h"
36#include "trans-const.h"
37
6de9cd9a
DN
38/* Members of the ioparm structure. */
39
5e805e44
JJ
40enum 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,
6f0f0b2e 48 IOPARM_ptype_wait,
5e805e44
JJ
49 IOPARM_ptype_num
50};
51
52enum iofield_type
53{
54 IOPARM_type_int4,
014ec6ee 55 IOPARM_type_intio,
5e805e44 56 IOPARM_type_pint4,
014ec6ee 57 IOPARM_type_pintio,
5e805e44
JJ
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
d1b38208 67typedef struct GTY(()) gfc_st_parameter_field {
5e805e44
JJ
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}
75gfc_st_parameter_field;
6de9cd9a 76
d1b38208 77typedef struct GTY(()) gfc_st_parameter {
5e805e44
JJ
78 const char *name;
79 tree type;
80}
81gfc_st_parameter;
82
83enum 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
91static GTY(()) gfc_st_parameter st_parameter[] =
92{
93 { "common", NULL },
94 { "open", NULL },
95 { "close", NULL },
96 { "filepos", NULL },
97 { "inquire", NULL },
6f0f0b2e
JD
98 { "dt", NULL },
99 { "wait", NULL }
5e805e44
JJ
100};
101
102static 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
81f40b79 108 { NULL, 0, (enum ioparam_type) 0, (enum iofield_type) 0, NULL, NULL }
5e805e44 109};
6de9cd9a
DN
110
111/* Library I/O subroutines */
112
5e805e44
JJ
113enum iocall
114{
115 IOCALL_READ,
116 IOCALL_READ_DONE,
117 IOCALL_WRITE,
118 IOCALL_WRITE_DONE,
119 IOCALL_X_INTEGER,
120 IOCALL_X_LOGICAL,
121 IOCALL_X_CHARACTER,
8a221914 122 IOCALL_X_CHARACTER_WIDE,
5e805e44
JJ
123 IOCALL_X_REAL,
124 IOCALL_X_COMPLEX,
125 IOCALL_X_ARRAY,
126 IOCALL_OPEN,
127 IOCALL_CLOSE,
128 IOCALL_INQUIRE,
129 IOCALL_IOLENGTH,
130 IOCALL_IOLENGTH_DONE,
131 IOCALL_REWIND,
132 IOCALL_BACKSPACE,
133 IOCALL_ENDFILE,
134 IOCALL_FLUSH,
135 IOCALL_SET_NML_VAL,
136 IOCALL_SET_NML_VAL_DIM,
6f0f0b2e 137 IOCALL_WAIT,
5e805e44
JJ
138 IOCALL_NUM
139};
140
141static GTY(()) tree iocall[IOCALL_NUM];
6de9cd9a
DN
142
143/* Variable for keeping track of what the last data transfer statement
144 was. Used for deciding which subroutine to call when the data
f7b529fa 145 transfer is complete. */
8750f9cd 146static enum { READ, WRITE, IOLENGTH } last_dt;
6de9cd9a 147
5e805e44
JJ
148/* The data transfer parameter block that should be shared by all
149 data transfer calls belonging to the same read/write/iolength. */
150static GTY(()) tree dt_parm;
151static stmtblock_t *dt_post_end_block;
6de9cd9a 152
5e805e44
JJ
153static void
154gfc_build_st_parameter (enum ioparam_type ptype, tree *types)
155{
32e8bb8e 156 unsigned int type;
5e805e44
JJ
157 gfc_st_parameter_field *p;
158 char name[64];
159 size_t len;
160 tree t = make_node (RECORD_TYPE);
161
162 len = strlen (st_parameter[ptype].name);
163 gcc_assert (len <= sizeof (name) - sizeof ("__st_parameter_"));
164 memcpy (name, "__st_parameter_", sizeof ("__st_parameter_"));
165 memcpy (name + sizeof ("__st_parameter_") - 1, st_parameter[ptype].name,
ff7417d4 166 len + 1);
5e805e44
JJ
167 TYPE_NAME (t) = get_identifier (name);
168
169 for (type = 0, p = st_parameter_field; type < IOPARM_field_num; type++, p++)
170 if (p->param_type == ptype)
171 switch (p->type)
172 {
173 case IOPARM_type_int4:
014ec6ee 174 case IOPARM_type_intio:
5e805e44 175 case IOPARM_type_pint4:
014ec6ee 176 case IOPARM_type_pintio:
5e805e44
JJ
177 case IOPARM_type_parray:
178 case IOPARM_type_pchar:
179 case IOPARM_type_pad:
180 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
181 get_identifier (p->name),
182 types[p->type]);
183 break;
184 case IOPARM_type_char1:
185 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
186 get_identifier (p->name),
187 pchar_type_node);
188 /* FALLTHROUGH */
189 case IOPARM_type_char2:
190 len = strlen (p->name);
191 gcc_assert (len <= sizeof (name) - sizeof ("_len"));
192 memcpy (name, p->name, len);
193 memcpy (name + len, "_len", sizeof ("_len"));
194 p->field_len = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
195 get_identifier (name),
196 gfc_charlen_type_node);
197 if (p->type == IOPARM_type_char2)
198 p->field = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
199 get_identifier (p->name),
200 pchar_type_node);
201 break;
202 case IOPARM_type_common:
203 p->field
204 = gfc_add_field_to_struct (&TYPE_FIELDS (t), t,
205 get_identifier (p->name),
206 st_parameter[IOPARM_ptype_common].type);
207 break;
208 case IOPARM_type_num:
209 gcc_unreachable ();
210 }
6de9cd9a 211
5e805e44
JJ
212 gfc_finish_type (t);
213 st_parameter[ptype].type = t;
214}
6de9cd9a 215
f96d606f
JD
216
217/* Build code to test an error condition and call generate_error if needed.
218 Note: This builds calls to generate_error in the runtime library function.
219 The function generate_error is dependent on certain parameters in the
220 st_parameter_common flags to be set. (See libgfortran/runtime/error.c)
221 Therefore, the code to set these flags must be generated before
222 this function is used. */
223
224void
225gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
226 const char * msgid, stmtblock_t * pblock)
227{
228 stmtblock_t block;
229 tree body;
230 tree tmp;
231 tree arg1, arg2, arg3;
232 char *message;
233
234 if (integer_zerop (cond))
235 return;
236
237 /* The code to generate the error. */
238 gfc_start_block (&block);
239
628c189e 240 arg1 = gfc_build_addr_expr (NULL_TREE, var);
f96d606f
JD
241
242 arg2 = build_int_cst (integer_type_node, error_code),
243
244 asprintf (&message, "%s", _(msgid));
ee37d2f5
FXC
245 arg3 = gfc_build_addr_expr (pchar_type_node,
246 gfc_build_localized_cstring_const (message));
f96d606f
JD
247 gfc_free(message);
248
249 tmp = build_call_expr (gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
250
251 gfc_add_expr_to_block (&block, tmp);
252
253 body = gfc_finish_block (&block);
254
255 if (integer_onep (cond))
256 {
257 gfc_add_expr_to_block (pblock, body);
258 }
259 else
260 {
261 /* Tell the compiler that this isn't likely. */
262 cond = fold_convert (long_integer_type_node, cond);
263 tmp = build_int_cst (long_integer_type_node, 0);
264 cond = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
265 cond = fold_convert (boolean_type_node, cond);
266
267 tmp = build3_v (COND_EXPR, cond, body, build_empty_stmt ());
268 gfc_add_expr_to_block (pblock, tmp);
269 }
270}
271
272
6de9cd9a
DN
273/* Create function decls for IO library functions. */
274
275void
276gfc_build_io_library_fndecls (void)
277{
5e805e44 278 tree types[IOPARM_type_num], pad_idx, gfc_int4_type_node;
014ec6ee 279 tree gfc_intio_type_node;
5e805e44 280 tree parm_type, dt_parm_type;
5e805e44
JJ
281 HOST_WIDE_INT pad_size;
282 enum ioparam_type ptype;
283
284 types[IOPARM_type_int4] = gfc_int4_type_node = gfc_get_int_type (4);
014ec6ee
JD
285 types[IOPARM_type_intio] = gfc_intio_type_node
286 = gfc_get_int_type (gfc_intio_kind);
5e805e44 287 types[IOPARM_type_pint4] = build_pointer_type (gfc_int4_type_node);
014ec6ee
JD
288 types[IOPARM_type_pintio]
289 = build_pointer_type (gfc_intio_type_node);
5e805e44
JJ
290 types[IOPARM_type_parray] = pchar_type_node;
291 types[IOPARM_type_pchar] = pchar_type_node;
e1456843 292 pad_size = 16 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (pchar_type_node));
5e805e44 293 pad_size += 32 * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (integer_type_node));
e1456843 294 pad_idx = build_index_type (build_int_cst (NULL_TREE, pad_size - 1));
5e805e44 295 types[IOPARM_type_pad] = build_array_type (char_type_node, pad_idx);
7ae99337
SE
296
297 /* pad actually contains pointers and integers so it needs to have an
298 alignment that is at least as large as the needed alignment for those
299 types. See the st_parameter_dt structure in libgfortran/io/io.h for
300 what really goes into this space. */
301 TYPE_ALIGN (types[IOPARM_type_pad]) = MAX (TYPE_ALIGN (pchar_type_node),
e1456843 302 TYPE_ALIGN (gfc_get_int_type (gfc_intio_kind)));
7ae99337 303
5e805e44
JJ
304 for (ptype = IOPARM_ptype_common; ptype < IOPARM_ptype_num; ptype++)
305 gfc_build_st_parameter (ptype, types);
6de9cd9a
DN
306
307 /* Define the transfer functions. */
308
5e805e44
JJ
309 dt_parm_type = build_pointer_type (st_parameter[IOPARM_ptype_dt].type);
310
311 iocall[IOCALL_X_INTEGER] =
6de9cd9a
DN
312 gfc_build_library_function_decl (get_identifier
313 (PREFIX("transfer_integer")),
5e805e44
JJ
314 void_type_node, 3, dt_parm_type,
315 pvoid_type_node, gfc_int4_type_node);
6de9cd9a 316
5e805e44 317 iocall[IOCALL_X_LOGICAL] =
6de9cd9a
DN
318 gfc_build_library_function_decl (get_identifier
319 (PREFIX("transfer_logical")),
5e805e44
JJ
320 void_type_node, 3, dt_parm_type,
321 pvoid_type_node, gfc_int4_type_node);
6de9cd9a 322
5e805e44 323 iocall[IOCALL_X_CHARACTER] =
6de9cd9a
DN
324 gfc_build_library_function_decl (get_identifier
325 (PREFIX("transfer_character")),
5e805e44
JJ
326 void_type_node, 3, dt_parm_type,
327 pvoid_type_node, gfc_int4_type_node);
6de9cd9a 328
8a221914
JD
329 iocall[IOCALL_X_CHARACTER_WIDE] =
330 gfc_build_library_function_decl (get_identifier
331 (PREFIX("transfer_character_wide")),
332 void_type_node, 4, dt_parm_type,
333 pvoid_type_node, gfc_charlen_type_node,
334 gfc_int4_type_node);
335
5e805e44 336 iocall[IOCALL_X_REAL] =
6de9cd9a 337 gfc_build_library_function_decl (get_identifier (PREFIX("transfer_real")),
5e805e44 338 void_type_node, 3, dt_parm_type,
6de9cd9a
DN
339 pvoid_type_node, gfc_int4_type_node);
340
5e805e44 341 iocall[IOCALL_X_COMPLEX] =
6de9cd9a
DN
342 gfc_build_library_function_decl (get_identifier
343 (PREFIX("transfer_complex")),
5e805e44
JJ
344 void_type_node, 3, dt_parm_type,
345 pvoid_type_node, gfc_int4_type_node);
6de9cd9a 346
5e805e44 347 iocall[IOCALL_X_ARRAY] =
18623fae
JB
348 gfc_build_library_function_decl (get_identifier
349 (PREFIX("transfer_array")),
5e805e44 350 void_type_node, 4, dt_parm_type,
dd52ecb0 351 pvoid_type_node, integer_type_node,
18623fae
JB
352 gfc_charlen_type_node);
353
6de9cd9a
DN
354 /* Library entry points */
355
5e805e44 356 iocall[IOCALL_READ] =
6de9cd9a 357 gfc_build_library_function_decl (get_identifier (PREFIX("st_read")),
5e805e44 358 void_type_node, 1, dt_parm_type);
6de9cd9a 359
5e805e44 360 iocall[IOCALL_WRITE] =
6de9cd9a 361 gfc_build_library_function_decl (get_identifier (PREFIX("st_write")),
5e805e44
JJ
362 void_type_node, 1, dt_parm_type);
363
364 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_open].type);
365 iocall[IOCALL_OPEN] =
6de9cd9a 366 gfc_build_library_function_decl (get_identifier (PREFIX("st_open")),
5e805e44 367 void_type_node, 1, parm_type);
6de9cd9a 368
5e805e44
JJ
369
370 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_close].type);
371 iocall[IOCALL_CLOSE] =
6de9cd9a 372 gfc_build_library_function_decl (get_identifier (PREFIX("st_close")),
5e805e44 373 void_type_node, 1, parm_type);
6de9cd9a 374
5e805e44
JJ
375 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_inquire].type);
376 iocall[IOCALL_INQUIRE] =
6de9cd9a 377 gfc_build_library_function_decl (get_identifier (PREFIX("st_inquire")),
5e805e44 378 gfc_int4_type_node, 1, parm_type);
6de9cd9a 379
5e805e44 380 iocall[IOCALL_IOLENGTH] =
8750f9cd 381 gfc_build_library_function_decl(get_identifier (PREFIX("st_iolength")),
5e805e44 382 void_type_node, 1, dt_parm_type);
8750f9cd 383
6f0f0b2e
JD
384 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_wait].type);
385 iocall[IOCALL_WAIT] =
386 gfc_build_library_function_decl (get_identifier (PREFIX("st_wait")),
387 gfc_int4_type_node, 1, parm_type);
388
5e805e44
JJ
389 parm_type = build_pointer_type (st_parameter[IOPARM_ptype_filepos].type);
390 iocall[IOCALL_REWIND] =
6de9cd9a 391 gfc_build_library_function_decl (get_identifier (PREFIX("st_rewind")),
5e805e44 392 gfc_int4_type_node, 1, parm_type);
6de9cd9a 393
5e805e44 394 iocall[IOCALL_BACKSPACE] =
6de9cd9a 395 gfc_build_library_function_decl (get_identifier (PREFIX("st_backspace")),
5e805e44 396 gfc_int4_type_node, 1, parm_type);
6de9cd9a 397
5e805e44 398 iocall[IOCALL_ENDFILE] =
6de9cd9a 399 gfc_build_library_function_decl (get_identifier (PREFIX("st_endfile")),
5e805e44 400 gfc_int4_type_node, 1, parm_type);
6403ec5f 401
5e805e44 402 iocall[IOCALL_FLUSH] =
6403ec5f 403 gfc_build_library_function_decl (get_identifier (PREFIX("st_flush")),
5e805e44 404 gfc_int4_type_node, 1, parm_type);
6403ec5f 405
6de9cd9a
DN
406 /* Library helpers */
407
5e805e44 408 iocall[IOCALL_READ_DONE] =
6de9cd9a 409 gfc_build_library_function_decl (get_identifier (PREFIX("st_read_done")),
5e805e44 410 gfc_int4_type_node, 1, dt_parm_type);
6de9cd9a 411
5e805e44 412 iocall[IOCALL_WRITE_DONE] =
6de9cd9a 413 gfc_build_library_function_decl (get_identifier (PREFIX("st_write_done")),
5e805e44 414 gfc_int4_type_node, 1, dt_parm_type);
8750f9cd 415
5e805e44 416 iocall[IOCALL_IOLENGTH_DONE] =
8750f9cd 417 gfc_build_library_function_decl (get_identifier (PREFIX("st_iolength_done")),
5e805e44 418 gfc_int4_type_node, 1, dt_parm_type);
8750f9cd 419
6de9cd9a 420
5e805e44 421 iocall[IOCALL_SET_NML_VAL] =
29dc5138 422 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var")),
5e805e44
JJ
423 void_type_node, 6, dt_parm_type,
424 pvoid_type_node, pvoid_type_node,
425 gfc_int4_type_node, gfc_charlen_type_node,
29dc5138 426 gfc_int4_type_node);
6de9cd9a 427
5e805e44 428 iocall[IOCALL_SET_NML_VAL_DIM] =
29dc5138 429 gfc_build_library_function_decl (get_identifier (PREFIX("st_set_nml_var_dim")),
5e805e44 430 void_type_node, 5, dt_parm_type,
6520ecac
JB
431 gfc_int4_type_node, gfc_array_index_type,
432 gfc_array_index_type, gfc_array_index_type);
6de9cd9a
DN
433}
434
435
5e805e44
JJ
436/* Generate code to store an integer constant into the
437 st_parameter_XXX structure. */
438
439static unsigned int
440set_parameter_const (stmtblock_t *block, tree var, enum iofield type,
441 unsigned int val)
442{
443 tree tmp;
444 gfc_st_parameter_field *p = &st_parameter_field[type];
445
446 if (p->param_type == IOPARM_ptype_common)
44855d8c
TS
447 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
448 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
449 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field), var, p->field,
450 NULL_TREE);
726a989a 451 gfc_add_modify (block, tmp, build_int_cst (TREE_TYPE (p->field), val));
5e805e44
JJ
452 return p->mask;
453}
454
455
49de9e73 456/* Generate code to store a non-string I/O parameter into the
5e805e44 457 st_parameter_XXX structure. This is a pass by value. */
6de9cd9a 458
5e805e44
JJ
459static unsigned int
460set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
461 gfc_expr *e)
6de9cd9a
DN
462{
463 gfc_se se;
464 tree tmp;
5e805e44 465 gfc_st_parameter_field *p = &st_parameter_field[type];
f96d606f 466 tree dest_type = TREE_TYPE (p->field);
6de9cd9a
DN
467
468 gfc_init_se (&se, NULL);
f96d606f
JD
469 gfc_conv_expr_val (&se, e);
470
471 /* If we're storing a UNIT number, we need to check it first. */
472 if (type == IOPARM_common_unit && e->ts.kind != 4)
473 {
474 tree cond, max;
f96d606f
JD
475 int i;
476
f96d606f
JD
477 /* Don't evaluate the UNIT number multiple times. */
478 se.expr = gfc_evaluate_now (se.expr, &se.pre);
479
480 /* UNIT numbers should be nonnegative. */
481 cond = fold_build2 (LT_EXPR, boolean_type_node, se.expr,
482 build_int_cst (TREE_TYPE (se.expr),0));
d74b97cc 483 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
f96d606f
JD
484 "Negative unit number in I/O statement",
485 &se.pre);
486
487 /* UNIT numbers should be less than the max. */
488 i = gfc_validate_kind (BT_INTEGER, 4, false);
489 max = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
490 cond = fold_build2 (GT_EXPR, boolean_type_node, se.expr,
491 fold_convert (TREE_TYPE (se.expr), max));
d74b97cc 492 gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
f96d606f
JD
493 "Unit number in I/O statement too large",
494 &se.pre);
495
496 }
497
498 se.expr = convert (dest_type, se.expr);
6de9cd9a
DN
499 gfc_add_block_to_block (block, &se.pre);
500
5e805e44 501 if (p->param_type == IOPARM_ptype_common)
44855d8c
TS
502 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
503 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
f96d606f 504
44855d8c 505 tmp = fold_build3 (COMPONENT_REF, dest_type, var, p->field, NULL_TREE);
726a989a 506 gfc_add_modify (block, tmp, se.expr);
5e805e44 507 return p->mask;
6de9cd9a
DN
508}
509
510
49de9e73 511/* Generate code to store a non-string I/O parameter into the
5e805e44 512 st_parameter_XXX structure. This is pass by reference. */
6de9cd9a 513
5e805e44
JJ
514static unsigned int
515set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
516 tree var, enum iofield type, gfc_expr *e)
6de9cd9a
DN
517{
518 gfc_se se;
5e805e44
JJ
519 tree tmp, addr;
520 gfc_st_parameter_field *p = &st_parameter_field[type];
6de9cd9a 521
5e805e44 522 gcc_assert (e->ts.type == BT_INTEGER || e->ts.type == BT_LOGICAL);
6de9cd9a 523 gfc_init_se (&se, NULL);
5e805e44 524 gfc_conv_expr_lhs (&se, e);
6de9cd9a 525
6de9cd9a
DN
526 gfc_add_block_to_block (block, &se.pre);
527
5e805e44
JJ
528 if (TYPE_MODE (TREE_TYPE (se.expr))
529 == TYPE_MODE (TREE_TYPE (TREE_TYPE (p->field))))
f96d606f 530 {
628c189e 531 addr = convert (TREE_TYPE (p->field), gfc_build_addr_expr (NULL_TREE, se.expr));
f96d606f
JD
532
533 /* If this is for the iostat variable initialize the
d74b97cc 534 user variable to LIBERROR_OK which is zero. */
f96d606f 535 if (type == IOPARM_common_iostat)
726a989a 536 gfc_add_modify (block, se.expr,
d74b97cc 537 build_int_cst (TREE_TYPE (se.expr), LIBERROR_OK));
f96d606f 538 }
5e805e44
JJ
539 else
540 {
541 /* The type used by the library has different size
f96d606f
JD
542 from the type of the variable supplied by the user.
543 Need to use a temporary. */
544 tree tmpvar = gfc_create_var (TREE_TYPE (TREE_TYPE (p->field)),
545 st_parameter_field[type].name);
546
547 /* If this is for the iostat variable, initialize the
d74b97cc 548 user variable to LIBERROR_OK which is zero. */
f96d606f 549 if (type == IOPARM_common_iostat)
726a989a 550 gfc_add_modify (block, tmpvar,
d74b97cc 551 build_int_cst (TREE_TYPE (tmpvar), LIBERROR_OK));
f96d606f 552
628c189e 553 addr = gfc_build_addr_expr (NULL_TREE, tmpvar);
f96d606f 554 /* After the I/O operation, we set the variable from the temporary. */
5e805e44 555 tmp = convert (TREE_TYPE (se.expr), tmpvar);
726a989a 556 gfc_add_modify (postblock, se.expr, tmp);
f96d606f 557 }
5e805e44
JJ
558
559 if (p->param_type == IOPARM_ptype_common)
44855d8c
TS
560 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
561 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
562 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
563 var, p->field, NULL_TREE);
726a989a 564 gfc_add_modify (block, tmp, addr);
5e805e44 565 return p->mask;
6de9cd9a
DN
566}
567
d3642f89
FW
568/* Given an array expr, find its address and length to get a string. If the
569 array is full, the string's address is the address of array's first element
7e279142 570 and the length is the size of the whole array. If it is an element, the
d3642f89 571 string's address is the element's address and the length is the rest size of
7e279142 572 the array. */
d3642f89
FW
573
574static void
575gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
576{
d3642f89 577 tree size;
d3642f89 578
7e279142 579 if (e->rank == 0)
d3642f89 580 {
7e279142
JJ
581 tree type, array, tmp;
582 gfc_symbol *sym;
583 int rank;
584
585 /* If it is an element, we need its address and size of the rest. */
586 gcc_assert (e->expr_type == EXPR_VARIABLE);
587 gcc_assert (e->ref->u.ar.type == AR_ELEMENT);
588 sym = e->symtree->n.sym;
589 rank = sym->as->rank - 1;
d3642f89 590 gfc_conv_expr (se, e);
d3642f89 591
7e279142
JJ
592 array = sym->backend_decl;
593 type = TREE_TYPE (array);
d3642f89 594
7e279142
JJ
595 if (GFC_ARRAY_TYPE_P (type))
596 size = GFC_TYPE_ARRAY_SIZE (type);
597 else
598 {
599 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
600 size = gfc_conv_array_stride (array, rank);
601 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
602 gfc_conv_array_ubound (array, rank),
603 gfc_conv_array_lbound (array, rank));
604 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp,
605 gfc_index_one_node);
606 size = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, size);
607 }
608 gcc_assert (size);
d3642f89 609
d3642f89 610 size = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
7e279142 611 TREE_OPERAND (se->expr, 1));
628c189e 612 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7e279142
JJ
613 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
614 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
615 fold_convert (gfc_array_index_type, tmp));
616 se->string_length = fold_convert (gfc_charlen_type_node, size);
617 return;
d3642f89
FW
618 }
619
7e279142 620 gfc_conv_array_parameter (se, e, gfc_walk_expr (e), 1, NULL, NULL, &size);
d3642f89
FW
621 se->string_length = fold_convert (gfc_charlen_type_node, size);
622}
6de9cd9a 623
109b0ac2 624
6de9cd9a 625/* Generate code to store a string and its length into the
5e805e44 626 st_parameter_XXX structure. */
6de9cd9a 627
5e805e44 628static unsigned int
6de9cd9a 629set_string (stmtblock_t * block, stmtblock_t * postblock, tree var,
5e805e44 630 enum iofield type, gfc_expr * e)
6de9cd9a
DN
631{
632 gfc_se se;
633 tree tmp;
6de9cd9a
DN
634 tree io;
635 tree len;
5e805e44 636 gfc_st_parameter_field *p = &st_parameter_field[type];
6de9cd9a
DN
637
638 gfc_init_se (&se, NULL);
6de9cd9a 639
5e805e44 640 if (p->param_type == IOPARM_ptype_common)
44855d8c
TS
641 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
642 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
643 io = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
644 var, p->field, NULL_TREE);
645 len = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field_len),
646 var, p->field_len, NULL_TREE);
6de9cd9a 647
7ab92584 648 /* Integer variable assigned a format label. */
7e279142
JJ
649 if (e->ts.type == BT_INTEGER
650 && e->rank == 0
651 && e->symtree->n.sym->attr.assign == 1)
6de9cd9a 652 {
dd18a33b 653 char * msg;
c8fe94c7 654 tree cond;
dd18a33b 655
ce2df7c6 656 gfc_conv_label_variable (&se, e);
6de9cd9a 657 tmp = GFC_DECL_STRING_LEN (se.expr);
c8fe94c7
FXC
658 cond = fold_build2 (LT_EXPR, boolean_type_node,
659 tmp, build_int_cst (TREE_TYPE (tmp), 0));
dd18a33b 660
c8fe94c7
FXC
661 asprintf(&msg, "Label assigned to variable '%s' (%%ld) is not a format "
662 "label", e->symtree->name);
0d52899f 663 gfc_trans_runtime_check (true, false, cond, &se.pre, &e->where, msg,
c8fe94c7 664 fold_convert (long_integer_type_node, tmp));
dd18a33b
FXC
665 gfc_free (msg);
666
726a989a 667 gfc_add_modify (&se.pre, io,
b078dfbf 668 fold_convert (TREE_TYPE (io), GFC_DECL_ASSIGN_ADDR (se.expr)));
726a989a 669 gfc_add_modify (&se.pre, len, GFC_DECL_STRING_LEN (se.expr));
6de9cd9a
DN
670 }
671 else
672 {
d3642f89
FW
673 /* General character. */
674 if (e->ts.type == BT_CHARACTER && e->rank == 0)
675 gfc_conv_expr (&se, e);
676 /* Array assigned Hollerith constant or character array. */
7e279142 677 else if (e->rank > 0 || (e->symtree && e->symtree->n.sym->as->rank > 0))
d3642f89
FW
678 gfc_convert_array_to_string (&se, e);
679 else
680 gcc_unreachable ();
681
6de9cd9a 682 gfc_conv_string_parameter (&se);
726a989a
RB
683 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), se.expr));
684 gfc_add_modify (&se.pre, len, se.string_length);
6de9cd9a
DN
685 }
686
687 gfc_add_block_to_block (block, &se.pre);
688 gfc_add_block_to_block (postblock, &se.post);
5e805e44 689 return p->mask;
6de9cd9a
DN
690}
691
692
109b0ac2
PT
693/* Generate code to store the character (array) and the character length
694 for an internal unit. */
695
5e805e44 696static unsigned int
d4feb3d3
PT
697set_internal_unit (stmtblock_t * block, stmtblock_t * post_block,
698 tree var, gfc_expr * e)
109b0ac2
PT
699{
700 gfc_se se;
701 tree io;
702 tree len;
703 tree desc;
704 tree tmp;
5e805e44
JJ
705 gfc_st_parameter_field *p;
706 unsigned int mask;
109b0ac2
PT
707
708 gfc_init_se (&se, NULL);
709
5e805e44
JJ
710 p = &st_parameter_field[IOPARM_dt_internal_unit];
711 mask = p->mask;
44855d8c
TS
712 io = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
713 var, p->field, NULL_TREE);
714 len = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field_len),
715 var, p->field_len, NULL_TREE);
5e805e44 716 p = &st_parameter_field[IOPARM_dt_internal_unit_desc];
44855d8c
TS
717 desc = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
718 var, p->field, NULL_TREE);
109b0ac2
PT
719
720 gcc_assert (e->ts.type == BT_CHARACTER);
721
722 /* Character scalars. */
723 if (e->rank == 0)
724 {
725 gfc_conv_expr (&se, e);
726 gfc_conv_string_parameter (&se);
727 tmp = se.expr;
c3238e32 728 se.expr = build_int_cst (pchar_type_node, 0);
109b0ac2
PT
729 }
730
731 /* Character array. */
64db4d29 732 else if (e->rank > 0)
109b0ac2
PT
733 {
734 se.ss = gfc_walk_expr (e);
735
1d6b7f39 736 if (is_subref_array (e))
d4feb3d3
PT
737 {
738 /* Use a temporary for components of arrays of derived types
739 or substring array references. */
1d6b7f39 740 gfc_conv_subref_array_arg (&se, e, 0,
d4feb3d3
PT
741 last_dt == READ ? INTENT_IN : INTENT_OUT);
742 tmp = build_fold_indirect_ref (se.expr);
743 se.expr = gfc_build_addr_expr (pchar_type_node, tmp);
744 tmp = gfc_conv_descriptor_data_get (tmp);
745 }
746 else
747 {
748 /* Return the data pointer and rank from the descriptor. */
749 gfc_conv_expr_descriptor (&se, e, se.ss);
750 tmp = gfc_conv_descriptor_data_get (se.expr);
751 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
752 }
109b0ac2
PT
753 }
754 else
755 gcc_unreachable ();
756
757 /* The cast is needed for character substrings and the descriptor
758 data. */
726a989a
RB
759 gfc_add_modify (&se.pre, io, fold_convert (TREE_TYPE (io), tmp));
760 gfc_add_modify (&se.pre, len,
d4feb3d3 761 fold_convert (TREE_TYPE (len), se.string_length));
726a989a 762 gfc_add_modify (&se.pre, desc, se.expr);
109b0ac2
PT
763
764 gfc_add_block_to_block (block, &se.pre);
d4feb3d3 765 gfc_add_block_to_block (post_block, &se.post);
5e805e44 766 return mask;
109b0ac2
PT
767}
768
6de9cd9a
DN
769/* Add a case to a IO-result switch. */
770
771static void
772add_case (int label_value, gfc_st_label * label, stmtblock_t * body)
773{
774 tree tmp, value;
775
776 if (label == NULL)
777 return; /* No label, no case */
778
7d60be94 779 value = build_int_cst (NULL_TREE, label_value);
6de9cd9a
DN
780
781 /* Make a backend label for this case. */
c006df4e 782 tmp = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
783
784 /* And the case itself. */
923ab88c 785 tmp = build3_v (CASE_LABEL_EXPR, value, NULL_TREE, tmp);
6de9cd9a
DN
786 gfc_add_expr_to_block (body, tmp);
787
788 /* Jump to the label. */
789 tmp = build1_v (GOTO_EXPR, gfc_get_label_decl (label));
790 gfc_add_expr_to_block (body, tmp);
791}
792
793
794/* Generate a switch statement that branches to the correct I/O
795 result label. The last statement of an I/O call stores the
796 result into a variable because there is often cleanup that
797 must be done before the switch, so a temporary would have to
798 be created anyway. */
799
800static void
5e805e44 801io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
6de9cd9a
DN
802 gfc_st_label * end_label, gfc_st_label * eor_label)
803{
804 stmtblock_t body;
805 tree tmp, rc;
5e805e44 806 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_flags];
6de9cd9a
DN
807
808 /* If no labels are specified, ignore the result instead
809 of building an empty switch. */
810 if (err_label == NULL
811 && end_label == NULL
812 && eor_label == NULL)
813 return;
814
815 /* Build a switch statement. */
816 gfc_start_block (&body);
817
818 /* The label values here must be the same as the values
819 in the library_return enum in the runtime library */
820 add_case (1, err_label, &body);
821 add_case (2, end_label, &body);
822 add_case (3, eor_label, &body);
823
824 tmp = gfc_finish_block (&body);
825
44855d8c
TS
826 var = fold_build3 (COMPONENT_REF, st_parameter[IOPARM_ptype_common].type,
827 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
828 rc = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
829 var, p->field, NULL_TREE);
830 rc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (rc),
831 rc, build_int_cst (TREE_TYPE (rc),
832 IOPARM_common_libreturn_mask));
6de9cd9a 833
923ab88c 834 tmp = build3_v (SWITCH_EXPR, rc, tmp, NULL_TREE);
6de9cd9a
DN
835
836 gfc_add_expr_to_block (block, tmp);
837}
838
839
840/* Store the current file and line number to variables so that if a
841 library call goes awry, we can tell the user where the problem is. */
842
843static void
5e805e44 844set_error_locus (stmtblock_t * block, tree var, locus * where)
6de9cd9a
DN
845{
846 gfc_file *f;
5e805e44 847 tree str, locus_file;
6de9cd9a 848 int line;
5e805e44 849 gfc_st_parameter_field *p = &st_parameter_field[IOPARM_common_filename];
6de9cd9a 850
44855d8c
TS
851 locus_file = fold_build3 (COMPONENT_REF,
852 st_parameter[IOPARM_ptype_common].type,
853 var, TYPE_FIELDS (TREE_TYPE (var)), NULL_TREE);
854 locus_file = fold_build3 (COMPONENT_REF, TREE_TYPE (p->field),
855 locus_file, p->field, NULL_TREE);
d4fa05b9 856 f = where->lb->file;
5e805e44 857 str = gfc_build_cstring_const (f->filename);
6de9cd9a 858
5e805e44 859 str = gfc_build_addr_expr (pchar_type_node, str);
726a989a 860 gfc_add_modify (block, locus_file, str);
6de9cd9a 861
c8cc8542 862 line = LOCATION_LINE (where->lb->location);
5e805e44 863 set_parameter_const (block, var, IOPARM_common_line, line);
6de9cd9a
DN
864}
865
866
867/* Translate an OPEN statement. */
868
869tree
870gfc_trans_open (gfc_code * code)
871{
872 stmtblock_t block, post_block;
873 gfc_open *p;
5e805e44
JJ
874 tree tmp, var;
875 unsigned int mask = 0;
6de9cd9a 876
5e805e44 877 gfc_start_block (&block);
6de9cd9a
DN
878 gfc_init_block (&post_block);
879
5e805e44
JJ
880 var = gfc_create_var (st_parameter[IOPARM_ptype_open].type, "open_parm");
881
882 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
883 p = code->ext.open;
884
f96d606f
JD
885 if (p->iomsg)
886 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
887 p->iomsg);
888
889 if (p->iostat)
890 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
891 p->iostat);
892
893 if (p->err)
894 mask |= IOPARM_common_err;
6de9cd9a
DN
895
896 if (p->file)
5e805e44 897 mask |= set_string (&block, &post_block, var, IOPARM_open_file, p->file);
6de9cd9a
DN
898
899 if (p->status)
5e805e44
JJ
900 mask |= set_string (&block, &post_block, var, IOPARM_open_status,
901 p->status);
6de9cd9a
DN
902
903 if (p->access)
5e805e44
JJ
904 mask |= set_string (&block, &post_block, var, IOPARM_open_access,
905 p->access);
6de9cd9a
DN
906
907 if (p->form)
5e805e44 908 mask |= set_string (&block, &post_block, var, IOPARM_open_form, p->form);
6de9cd9a
DN
909
910 if (p->recl)
5e805e44 911 mask |= set_parameter_value (&block, var, IOPARM_open_recl_in, p->recl);
6de9cd9a
DN
912
913 if (p->blank)
5e805e44
JJ
914 mask |= set_string (&block, &post_block, var, IOPARM_open_blank,
915 p->blank);
6de9cd9a
DN
916
917 if (p->position)
5e805e44
JJ
918 mask |= set_string (&block, &post_block, var, IOPARM_open_position,
919 p->position);
6de9cd9a
DN
920
921 if (p->action)
5e805e44
JJ
922 mask |= set_string (&block, &post_block, var, IOPARM_open_action,
923 p->action);
6de9cd9a
DN
924
925 if (p->delim)
5e805e44
JJ
926 mask |= set_string (&block, &post_block, var, IOPARM_open_delim,
927 p->delim);
6de9cd9a
DN
928
929 if (p->pad)
5e805e44 930 mask |= set_string (&block, &post_block, var, IOPARM_open_pad, p->pad);
6de9cd9a 931
6f0f0b2e
JD
932 if (p->decimal)
933 mask |= set_string (&block, &post_block, var, IOPARM_open_decimal,
934 p->decimal);
935
936 if (p->encoding)
937 mask |= set_string (&block, &post_block, var, IOPARM_open_encoding,
938 p->encoding);
939
940 if (p->round)
941 mask |= set_string (&block, &post_block, var, IOPARM_open_round, p->round);
942
943 if (p->sign)
944 mask |= set_string (&block, &post_block, var, IOPARM_open_sign, p->sign);
945
946 if (p->asynchronous)
947 mask |= set_string (&block, &post_block, var, IOPARM_open_asynchronous,
948 p->asynchronous);
949
181c9f4a
TK
950 if (p->convert)
951 mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
952 p->convert);
953
5e805e44
JJ
954 set_parameter_const (&block, var, IOPARM_common_flags, mask);
955
f96d606f
JD
956 if (p->unit)
957 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
958 else
959 set_parameter_const (&block, var, IOPARM_common_unit, 0);
960
628c189e 961 tmp = gfc_build_addr_expr (NULL_TREE, var);
5039610b 962 tmp = build_call_expr (iocall[IOCALL_OPEN], 1, tmp);
6de9cd9a
DN
963 gfc_add_expr_to_block (&block, tmp);
964
965 gfc_add_block_to_block (&block, &post_block);
966
5e805e44 967 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
968
969 return gfc_finish_block (&block);
970}
971
972
973/* Translate a CLOSE statement. */
974
975tree
976gfc_trans_close (gfc_code * code)
977{
978 stmtblock_t block, post_block;
979 gfc_close *p;
5e805e44
JJ
980 tree tmp, var;
981 unsigned int mask = 0;
6de9cd9a 982
5e805e44 983 gfc_start_block (&block);
6de9cd9a
DN
984 gfc_init_block (&post_block);
985
5e805e44
JJ
986 var = gfc_create_var (st_parameter[IOPARM_ptype_close].type, "close_parm");
987
988 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
989 p = code->ext.close;
990
7aba8abe 991 if (p->iomsg)
5e805e44
JJ
992 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
993 p->iomsg);
7aba8abe 994
6de9cd9a 995 if (p->iostat)
5e805e44
JJ
996 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
997 p->iostat);
6de9cd9a
DN
998
999 if (p->err)
5e805e44
JJ
1000 mask |= IOPARM_common_err;
1001
f96d606f
JD
1002 if (p->status)
1003 mask |= set_string (&block, &post_block, var, IOPARM_close_status,
1004 p->status);
1005
5e805e44 1006 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1007
f96d606f
JD
1008 if (p->unit)
1009 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1010 else
1011 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1012
628c189e 1013 tmp = gfc_build_addr_expr (NULL_TREE, var);
5039610b 1014 tmp = build_call_expr (iocall[IOCALL_CLOSE], 1, tmp);
6de9cd9a
DN
1015 gfc_add_expr_to_block (&block, tmp);
1016
1017 gfc_add_block_to_block (&block, &post_block);
1018
5e805e44 1019 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1020
1021 return gfc_finish_block (&block);
1022}
1023
1024
1025/* Common subroutine for building a file positioning statement. */
1026
1027static tree
1028build_filepos (tree function, gfc_code * code)
1029{
7aba8abe 1030 stmtblock_t block, post_block;
6de9cd9a 1031 gfc_filepos *p;
5e805e44
JJ
1032 tree tmp, var;
1033 unsigned int mask = 0;
6de9cd9a
DN
1034
1035 p = code->ext.filepos;
1036
5e805e44 1037 gfc_start_block (&block);
7aba8abe 1038 gfc_init_block (&post_block);
6de9cd9a 1039
5e805e44
JJ
1040 var = gfc_create_var (st_parameter[IOPARM_ptype_filepos].type,
1041 "filepos_parm");
1042
1043 set_error_locus (&block, var, &code->loc);
6de9cd9a 1044
7aba8abe 1045 if (p->iomsg)
5e805e44
JJ
1046 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1047 p->iomsg);
7aba8abe 1048
6de9cd9a 1049 if (p->iostat)
5e805e44
JJ
1050 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1051 p->iostat);
6de9cd9a
DN
1052
1053 if (p->err)
5e805e44
JJ
1054 mask |= IOPARM_common_err;
1055
1056 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1057
f96d606f
JD
1058 if (p->unit)
1059 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1060 else
1061 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1062
628c189e 1063 tmp = gfc_build_addr_expr (NULL_TREE, var);
5039610b 1064 tmp = build_call_expr (function, 1, tmp);
6de9cd9a
DN
1065 gfc_add_expr_to_block (&block, tmp);
1066
7aba8abe
TK
1067 gfc_add_block_to_block (&block, &post_block);
1068
5e805e44 1069 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1070
1071 return gfc_finish_block (&block);
1072}
1073
1074
1075/* Translate a BACKSPACE statement. */
1076
1077tree
1078gfc_trans_backspace (gfc_code * code)
1079{
5e805e44 1080 return build_filepos (iocall[IOCALL_BACKSPACE], code);
6de9cd9a
DN
1081}
1082
1083
1084/* Translate an ENDFILE statement. */
1085
1086tree
1087gfc_trans_endfile (gfc_code * code)
1088{
5e805e44 1089 return build_filepos (iocall[IOCALL_ENDFILE], code);
6de9cd9a
DN
1090}
1091
1092
1093/* Translate a REWIND statement. */
1094
1095tree
1096gfc_trans_rewind (gfc_code * code)
1097{
5e805e44 1098 return build_filepos (iocall[IOCALL_REWIND], code);
6de9cd9a
DN
1099}
1100
1101
6403ec5f
JB
1102/* Translate a FLUSH statement. */
1103
1104tree
1105gfc_trans_flush (gfc_code * code)
1106{
5e805e44 1107 return build_filepos (iocall[IOCALL_FLUSH], code);
6403ec5f
JB
1108}
1109
1110
c16dd6a8
JD
1111/* Create a dummy iostat variable to catch any error due to bad unit. */
1112
1113static gfc_expr *
1114create_dummy_iostat (void)
1115{
1116 gfc_symtree *st;
1117 gfc_expr *e;
1118
1119 gfc_get_ha_sym_tree ("@iostat", &st);
1120 st->n.sym->ts.type = BT_INTEGER;
1121 st->n.sym->ts.kind = gfc_default_integer_kind;
1122 gfc_set_sym_referenced (st->n.sym);
bc9d9552 1123 gfc_commit_symbol (st->n.sym);
c16dd6a8
JD
1124 st->n.sym->backend_decl
1125 = gfc_create_var (gfc_get_int_type (st->n.sym->ts.kind),
1126 st->n.sym->name);
1127
1128 e = gfc_get_expr ();
1129 e->expr_type = EXPR_VARIABLE;
1130 e->symtree = st;
1131 e->ts.type = BT_INTEGER;
1132 e->ts.kind = st->n.sym->ts.kind;
1133
1134 return e;
1135}
1136
1137
6de9cd9a
DN
1138/* Translate the non-IOLENGTH form of an INQUIRE statement. */
1139
1140tree
1141gfc_trans_inquire (gfc_code * code)
1142{
1143 stmtblock_t block, post_block;
1144 gfc_inquire *p;
5e805e44 1145 tree tmp, var;
6f0f0b2e 1146 unsigned int mask = 0, mask2 = 0;
6de9cd9a 1147
5e805e44 1148 gfc_start_block (&block);
6de9cd9a
DN
1149 gfc_init_block (&post_block);
1150
5e805e44
JJ
1151 var = gfc_create_var (st_parameter[IOPARM_ptype_inquire].type,
1152 "inquire_parm");
1153
1154 set_error_locus (&block, var, &code->loc);
6de9cd9a
DN
1155 p = code->ext.inquire;
1156
7aba8abe 1157 if (p->iomsg)
5e805e44
JJ
1158 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1159 p->iomsg);
7aba8abe 1160
6de9cd9a 1161 if (p->iostat)
5e805e44
JJ
1162 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1163 p->iostat);
6de9cd9a 1164
f96d606f
JD
1165 if (p->err)
1166 mask |= IOPARM_common_err;
1167
1168 /* Sanity check. */
1169 if (p->unit && p->file)
1170 gfc_error ("INQUIRE statement at %L cannot contain both FILE and UNIT specifiers", &code->loc);
1171
1172 if (p->file)
1173 mask |= set_string (&block, &post_block, var, IOPARM_inquire_file,
1174 p->file);
1175
6de9cd9a 1176 if (p->exist)
c16dd6a8
JD
1177 {
1178 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
1179 p->exist);
1180
1181 if (p->unit && !p->iostat)
1182 {
1183 p->iostat = create_dummy_iostat ();
1184 mask |= set_parameter_ref (&block, &post_block, var,
1185 IOPARM_common_iostat, p->iostat);
1186 }
1187 }
6de9cd9a
DN
1188
1189 if (p->opened)
5e805e44
JJ
1190 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_opened,
1191 p->opened);
6de9cd9a
DN
1192
1193 if (p->number)
5e805e44
JJ
1194 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_number,
1195 p->number);
6de9cd9a
DN
1196
1197 if (p->named)
5e805e44
JJ
1198 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_named,
1199 p->named);
6de9cd9a
DN
1200
1201 if (p->name)
5e805e44
JJ
1202 mask |= set_string (&block, &post_block, var, IOPARM_inquire_name,
1203 p->name);
6de9cd9a
DN
1204
1205 if (p->access)
5e805e44
JJ
1206 mask |= set_string (&block, &post_block, var, IOPARM_inquire_access,
1207 p->access);
6de9cd9a
DN
1208
1209 if (p->sequential)
5e805e44
JJ
1210 mask |= set_string (&block, &post_block, var, IOPARM_inquire_sequential,
1211 p->sequential);
6de9cd9a
DN
1212
1213 if (p->direct)
5e805e44
JJ
1214 mask |= set_string (&block, &post_block, var, IOPARM_inquire_direct,
1215 p->direct);
6de9cd9a
DN
1216
1217 if (p->form)
5e805e44
JJ
1218 mask |= set_string (&block, &post_block, var, IOPARM_inquire_form,
1219 p->form);
6de9cd9a
DN
1220
1221 if (p->formatted)
5e805e44
JJ
1222 mask |= set_string (&block, &post_block, var, IOPARM_inquire_formatted,
1223 p->formatted);
6de9cd9a
DN
1224
1225 if (p->unformatted)
5e805e44
JJ
1226 mask |= set_string (&block, &post_block, var, IOPARM_inquire_unformatted,
1227 p->unformatted);
6de9cd9a
DN
1228
1229 if (p->recl)
5e805e44
JJ
1230 mask |= set_parameter_ref (&block, &post_block, var,
1231 IOPARM_inquire_recl_out, p->recl);
6de9cd9a
DN
1232
1233 if (p->nextrec)
5e805e44
JJ
1234 mask |= set_parameter_ref (&block, &post_block, var,
1235 IOPARM_inquire_nextrec, p->nextrec);
6de9cd9a
DN
1236
1237 if (p->blank)
5e805e44
JJ
1238 mask |= set_string (&block, &post_block, var, IOPARM_inquire_blank,
1239 p->blank);
6de9cd9a 1240
d06b3496
JD
1241 if (p->delim)
1242 mask |= set_string (&block, &post_block, var, IOPARM_inquire_delim,
1243 p->delim);
1244
6de9cd9a 1245 if (p->position)
5e805e44
JJ
1246 mask |= set_string (&block, &post_block, var, IOPARM_inquire_position,
1247 p->position);
6de9cd9a
DN
1248
1249 if (p->action)
5e805e44
JJ
1250 mask |= set_string (&block, &post_block, var, IOPARM_inquire_action,
1251 p->action);
6de9cd9a
DN
1252
1253 if (p->read)
5e805e44
JJ
1254 mask |= set_string (&block, &post_block, var, IOPARM_inquire_read,
1255 p->read);
6de9cd9a
DN
1256
1257 if (p->write)
5e805e44
JJ
1258 mask |= set_string (&block, &post_block, var, IOPARM_inquire_write,
1259 p->write);
6de9cd9a
DN
1260
1261 if (p->readwrite)
5e805e44
JJ
1262 mask |= set_string (&block, &post_block, var, IOPARM_inquire_readwrite,
1263 p->readwrite);
6de9cd9a 1264
dae24534 1265 if (p->pad)
5e805e44
JJ
1266 mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
1267 p->pad);
d06b3496 1268
181c9f4a
TK
1269 if (p->convert)
1270 mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
1271 p->convert);
1272
014ec6ee
JD
1273 if (p->strm_pos)
1274 mask |= set_parameter_ref (&block, &post_block, var,
1275 IOPARM_inquire_strm_pos_out, p->strm_pos);
1276
6f0f0b2e
JD
1277 /* The second series of flags. */
1278 if (p->asynchronous)
1279 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_asynchronous,
1280 p->asynchronous);
1281
1282 if (p->decimal)
1283 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_decimal,
1284 p->decimal);
1285
1286 if (p->encoding)
1287 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_encoding,
1288 p->encoding);
1289
1290 if (p->round)
1291 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_round,
1292 p->round);
1293
1294 if (p->sign)
1295 mask2 |= set_string (&block, &post_block, var, IOPARM_inquire_sign,
1296 p->sign);
1297
1298 if (p->pending)
1299 mask2 |= set_parameter_ref (&block, &post_block, var,
1300 IOPARM_inquire_pending, p->pending);
1301
1302 if (p->size)
1303 mask2 |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_size,
1304 p->size);
1305
1306 if (p->id)
d06b3496
JD
1307 mask2 |= set_parameter_ref (&block, &post_block,var, IOPARM_inquire_id,
1308 p->id);
6f0f0b2e 1309
6f0f0b2e 1310 if (mask2)
e1456843 1311 mask |= set_parameter_const (&block, var, IOPARM_inquire_flags2, mask2);
6f0f0b2e 1312
5e805e44 1313 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1314
f96d606f
JD
1315 if (p->unit)
1316 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1317 else
1318 set_parameter_const (&block, var, IOPARM_common_unit, 0);
1319
628c189e 1320 tmp = gfc_build_addr_expr (NULL_TREE, var);
5039610b 1321 tmp = build_call_expr (iocall[IOCALL_INQUIRE], 1, tmp);
6de9cd9a
DN
1322 gfc_add_expr_to_block (&block, tmp);
1323
1324 gfc_add_block_to_block (&block, &post_block);
1325
5e805e44 1326 io_result (&block, var, p->err, NULL, NULL);
6de9cd9a
DN
1327
1328 return gfc_finish_block (&block);
1329}
1330
6f0f0b2e
JD
1331
1332tree
1333gfc_trans_wait (gfc_code * code)
1334{
1335 stmtblock_t block, post_block;
1336 gfc_wait *p;
1337 tree tmp, var;
1338 unsigned int mask = 0;
1339
1340 gfc_start_block (&block);
1341 gfc_init_block (&post_block);
1342
1343 var = gfc_create_var (st_parameter[IOPARM_ptype_wait].type,
1344 "wait_parm");
1345
1346 set_error_locus (&block, var, &code->loc);
1347 p = code->ext.wait;
1348
1349 /* Set parameters here. */
1350 if (p->iomsg)
1351 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1352 p->iomsg);
1353
1354 if (p->iostat)
1355 mask |= set_parameter_ref (&block, &post_block, var, IOPARM_common_iostat,
1356 p->iostat);
1357
1358 if (p->err)
1359 mask |= IOPARM_common_err;
1360
1361 if (p->id)
1362 mask |= set_parameter_value (&block, var, IOPARM_wait_id, p->id);
1363
1364 set_parameter_const (&block, var, IOPARM_common_flags, mask);
1365
1366 if (p->unit)
1367 set_parameter_value (&block, var, IOPARM_common_unit, p->unit);
1368
628c189e 1369 tmp = gfc_build_addr_expr (NULL_TREE, var);
6f0f0b2e
JD
1370 tmp = build_call_expr (iocall[IOCALL_WAIT], 1, tmp);
1371 gfc_add_expr_to_block (&block, tmp);
1372
1373 gfc_add_block_to_block (&block, &post_block);
1374
1375 io_result (&block, var, p->err, NULL, NULL);
1376
1377 return gfc_finish_block (&block);
1378
1379}
1380
6de9cd9a 1381static gfc_expr *
cb9e4f55 1382gfc_new_nml_name_expr (const char * name)
6de9cd9a
DN
1383{
1384 gfc_expr * nml_name;
29dc5138 1385
6de9cd9a
DN
1386 nml_name = gfc_get_expr();
1387 nml_name->ref = NULL;
1388 nml_name->expr_type = EXPR_CONSTANT;
9d64df18 1389 nml_name->ts.kind = gfc_default_character_kind;
6de9cd9a
DN
1390 nml_name->ts.type = BT_CHARACTER;
1391 nml_name->value.character.length = strlen(name);
00660189 1392 nml_name->value.character.string = gfc_char_to_widechar (name);
6de9cd9a
DN
1393
1394 return nml_name;
1395}
1396
29dc5138 1397/* nml_full_name builds up the fully qualified name of a
66e4ab31 1398 derived type component. */
29dc5138
PT
1399
1400static char*
1401nml_full_name (const char* var_name, const char* cmp_name)
6de9cd9a 1402{
29dc5138
PT
1403 int full_name_length;
1404 char * full_name;
1405
1406 full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
1407 full_name = (char*)gfc_getmem (full_name_length + 1);
1408 strcpy (full_name, var_name);
1409 full_name = strcat (full_name, "%");
1410 full_name = strcat (full_name, cmp_name);
1411 return full_name;
6de9cd9a
DN
1412}
1413
29dc5138
PT
1414/* nml_get_addr_expr builds an address expression from the
1415 gfc_symbol or gfc_component backend_decl's. An offset is
1416 provided so that the address of an element of an array of
1417 derived types is returned. This is used in the runtime to
66e4ab31 1418 determine that span of the derived type. */
29dc5138
PT
1419
1420static tree
1421nml_get_addr_expr (gfc_symbol * sym, gfc_component * c,
1422 tree base_addr)
1423{
1424 tree decl = NULL_TREE;
1425 tree tmp;
1426 tree itmp;
1427 int array_flagged;
1428 int dummy_arg_flagged;
1429
1430 if (sym)
1431 {
1432 sym->attr.referenced = 1;
1433 decl = gfc_get_symbol_decl (sym);
847b053d
PT
1434
1435 /* If this is the enclosing function declaration, use
1436 the fake result instead. */
1437 if (decl == current_function_decl)
1438 decl = gfc_get_fake_result_decl (sym, 0);
1439 else if (decl == DECL_CONTEXT (current_function_decl))
1440 decl = gfc_get_fake_result_decl (sym, 1);
29dc5138
PT
1441 }
1442 else
1443 decl = c->backend_decl;
1444
1445 gcc_assert (decl && ((TREE_CODE (decl) == FIELD_DECL
1446 || TREE_CODE (decl) == VAR_DECL
1447 || TREE_CODE (decl) == PARM_DECL)
1448 || TREE_CODE (decl) == COMPONENT_REF));
1449
1450 tmp = decl;
1451
1452 /* Build indirect reference, if dummy argument. */
1453
1454 dummy_arg_flagged = POINTER_TYPE_P (TREE_TYPE(tmp));
1455
38611275 1456 itmp = (dummy_arg_flagged) ? build_fold_indirect_ref (tmp) : tmp;
29dc5138
PT
1457
1458 /* If an array, set flag and use indirect ref. if built. */
1459
1460 array_flagged = (TREE_CODE (TREE_TYPE (itmp)) == ARRAY_TYPE
1461 && !TYPE_STRING_FLAG (TREE_TYPE (itmp)));
1462
1463 if (array_flagged)
1464 tmp = itmp;
1465
1466 /* Treat the component of a derived type, using base_addr for
1467 the derived type. */
1468
1469 if (TREE_CODE (decl) == FIELD_DECL)
44855d8c
TS
1470 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
1471 base_addr, tmp, NULL_TREE);
29dc5138
PT
1472
1473 /* If we have a derived type component, a reference to the first
1474 element of the array is built. This is done so that base_addr,
1475 used in the build of the component reference, always points to
1476 a RECORD_TYPE. */
1477
1478 if (array_flagged)
1d6b7f39 1479 tmp = gfc_build_array_ref (tmp, gfc_index_zero_node, NULL);
29dc5138
PT
1480
1481 /* Now build the address expression. */
1482
628c189e 1483 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
29dc5138
PT
1484
1485 /* If scalar dummy, resolve indirect reference now. */
1486
1487 if (dummy_arg_flagged && !array_flagged)
38611275 1488 tmp = build_fold_indirect_ref (tmp);
29dc5138
PT
1489
1490 gcc_assert (tmp && POINTER_TYPE_P (TREE_TYPE (tmp)));
1491
1492 return tmp;
1493}
3bc268e6 1494
29dc5138 1495/* For an object VAR_NAME whose base address is BASE_ADDR, generate a
5e805e44
JJ
1496 call to iocall[IOCALL_SET_NML_VAL]. For derived type variable, recursively
1497 generate calls to iocall[IOCALL_SET_NML_VAL] for each component. */
3bc268e6 1498
29dc5138 1499#define IARG(i) build_int_cst (gfc_array_index_type, i)
3bc268e6
VL
1500
1501static void
29dc5138
PT
1502transfer_namelist_element (stmtblock_t * block, const char * var_name,
1503 gfc_symbol * sym, gfc_component * c,
1504 tree base_addr)
3bc268e6 1505{
29dc5138
PT
1506 gfc_typespec * ts = NULL;
1507 gfc_array_spec * as = NULL;
1508 tree addr_expr = NULL;
1509 tree dt = NULL;
1510 tree string;
1511 tree tmp;
29dc5138 1512 tree dtype;
5e805e44 1513 tree dt_parm_addr;
29dc5138
PT
1514 int n_dim;
1515 int itype;
1516 int rank = 0;
3bc268e6 1517
29dc5138 1518 gcc_assert (sym || c);
3bc268e6 1519
29dc5138
PT
1520 /* Build the namelist object name. */
1521
1522 string = gfc_build_cstring_const (var_name);
1523 string = gfc_build_addr_expr (pchar_type_node, string);
1524
1525 /* Build ts, as and data address using symbol or component. */
1526
1527 ts = (sym) ? &sym->ts : &c->ts;
1528 as = (sym) ? sym->as : c->as;
1529
1530 addr_expr = nml_get_addr_expr (sym, c, base_addr);
1531
1532 if (as)
1533 rank = as->rank;
1534
1535 if (rank)
3bc268e6 1536 {
29dc5138
PT
1537 dt = TREE_TYPE ((sym) ? sym->backend_decl : c->backend_decl);
1538 dtype = gfc_get_dtype (dt);
3bc268e6 1539 }
29dc5138
PT
1540 else
1541 {
1542 itype = GFC_DTYPE_UNKNOWN;
3bc268e6 1543
29dc5138 1544 switch (ts->type)
3bc268e6 1545
29dc5138
PT
1546 {
1547 case BT_INTEGER:
1548 itype = GFC_DTYPE_INTEGER;
1549 break;
1550 case BT_LOGICAL:
1551 itype = GFC_DTYPE_LOGICAL;
1552 break;
1553 case BT_REAL:
1554 itype = GFC_DTYPE_REAL;
1555 break;
1556 case BT_COMPLEX:
1557 itype = GFC_DTYPE_COMPLEX;
1558 break;
1559 case BT_DERIVED:
1560 itype = GFC_DTYPE_DERIVED;
1561 break;
1562 case BT_CHARACTER:
1563 itype = GFC_DTYPE_CHARACTER;
1564 break;
1565 default:
1566 gcc_unreachable ();
1567 }
1568
1569 dtype = IARG (itype << GFC_DTYPE_TYPE_SHIFT);
3bc268e6
VL
1570 }
1571
29dc5138
PT
1572 /* Build up the arguments for the transfer call.
1573 The call for the scalar part transfers:
1574 (address, name, type, kind or string_length, dtype) */
1575
628c189e 1576 dt_parm_addr = gfc_build_addr_expr (NULL_TREE, dt_parm);
29dc5138
PT
1577
1578 if (ts->type == BT_CHARACTER)
5039610b 1579 tmp = ts->cl->backend_decl;
29dc5138 1580 else
5039610b
SL
1581 tmp = build_int_cst (gfc_charlen_type_node, 0);
1582 tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL], 6,
1583 dt_parm_addr, addr_expr, string,
1584 IARG (ts->kind), tmp, dtype);
3bc268e6 1585 gfc_add_expr_to_block (block, tmp);
29dc5138
PT
1586
1587 /* If the object is an array, transfer rank times:
1588 (null pointer, name, stride, lbound, ubound) */
1589
1590 for ( n_dim = 0 ; n_dim < rank ; n_dim++ )
1591 {
5039610b
SL
1592 tmp = build_call_expr (iocall[IOCALL_SET_NML_VAL_DIM], 5,
1593 dt_parm_addr,
1594 IARG (n_dim),
1595 GFC_TYPE_ARRAY_STRIDE (dt, n_dim),
1596 GFC_TYPE_ARRAY_LBOUND (dt, n_dim),
1597 GFC_TYPE_ARRAY_UBOUND (dt, n_dim));
29dc5138
PT
1598 gfc_add_expr_to_block (block, tmp);
1599 }
1600
1601 if (ts->type == BT_DERIVED)
1602 {
1603 gfc_component *cmp;
1604
1605 /* Provide the RECORD_TYPE to build component references. */
1606
38611275 1607 tree expr = build_fold_indirect_ref (addr_expr);
29dc5138
PT
1608
1609 for (cmp = ts->derived->components; cmp; cmp = cmp->next)
1610 {
1611 char *full_name = nml_full_name (var_name, cmp->name);
1612 transfer_namelist_element (block,
1613 full_name,
1614 NULL, cmp, expr);
1615 gfc_free (full_name);
1616 }
1617 }
3bc268e6 1618}
6de9cd9a 1619
29dc5138 1620#undef IARG
29dc5138 1621
6de9cd9a
DN
1622/* Create a data transfer statement. Not all of the fields are valid
1623 for both reading and writing, but improper use has been filtered
1624 out by now. */
1625
1626static tree
5e805e44 1627build_dt (tree function, gfc_code * code)
6de9cd9a 1628{
d4feb3d3 1629 stmtblock_t block, post_block, post_end_block, post_iu_block;
6de9cd9a 1630 gfc_dt *dt;
5e805e44 1631 tree tmp, var;
29dc5138 1632 gfc_expr *nmlname;
3bc268e6 1633 gfc_namelist *nml;
5e1bdeb7 1634 unsigned int mask = 0;
6de9cd9a 1635
5e805e44 1636 gfc_start_block (&block);
6de9cd9a 1637 gfc_init_block (&post_block);
5e805e44 1638 gfc_init_block (&post_end_block);
d4feb3d3 1639 gfc_init_block (&post_iu_block);
5e805e44
JJ
1640
1641 var = gfc_create_var (st_parameter[IOPARM_ptype_dt].type, "dt_parm");
1642
1643 set_error_locus (&block, var, &code->loc);
6de9cd9a 1644
5e805e44
JJ
1645 if (last_dt == IOLENGTH)
1646 {
1647 gfc_inquire *inq;
1648
1649 inq = code->ext.inquire;
6de9cd9a 1650
5e805e44
JJ
1651 /* First check that preconditions are met. */
1652 gcc_assert (inq != NULL);
1653 gcc_assert (inq->iolength != NULL);
1654
1655 /* Connect to the iolength variable. */
1656 mask |= set_parameter_ref (&block, &post_end_block, var,
1657 IOPARM_dt_iolength, inq->iolength);
1658 dt = NULL;
1659 }
1660 else
1661 {
1662 dt = code->ext.dt;
1663 gcc_assert (dt != NULL);
1664 }
8750f9cd 1665
5e805e44 1666 if (dt && dt->io_unit)
6de9cd9a
DN
1667 {
1668 if (dt->io_unit->ts.type == BT_CHARACTER)
1669 {
d4feb3d3
PT
1670 mask |= set_internal_unit (&block, &post_iu_block,
1671 var, dt->io_unit);
5e805e44 1672 set_parameter_const (&block, var, IOPARM_common_unit, 0);
6de9cd9a 1673 }
6de9cd9a 1674 }
5e805e44
JJ
1675 else
1676 set_parameter_const (&block, var, IOPARM_common_unit, 0);
6de9cd9a 1677
5e805e44
JJ
1678 if (dt)
1679 {
f96d606f
JD
1680 if (dt->iomsg)
1681 mask |= set_string (&block, &post_block, var, IOPARM_common_iomsg,
1682 dt->iomsg);
1683
1684 if (dt->iostat)
1685 mask |= set_parameter_ref (&block, &post_end_block, var,
1686 IOPARM_common_iostat, dt->iostat);
1687
1688 if (dt->err)
1689 mask |= IOPARM_common_err;
1690
1691 if (dt->eor)
1692 mask |= IOPARM_common_eor;
1693
1694 if (dt->end)
1695 mask |= IOPARM_common_end;
1696
6f0f0b2e
JD
1697 if (dt->id)
1698 mask |= set_parameter_ref (&block, &post_end_block, var,
1699 IOPARM_dt_id, dt->id);
1700
1701 if (dt->pos)
1702 mask |= set_parameter_value (&block, var, IOPARM_dt_pos, dt->pos);
1703
1704 if (dt->asynchronous)
1705 mask |= set_string (&block, &post_block, var, IOPARM_dt_asynchronous,
1706 dt->asynchronous);
1707
1708 if (dt->blank)
1709 mask |= set_string (&block, &post_block, var, IOPARM_dt_blank,
1710 dt->blank);
1711
1712 if (dt->decimal)
1713 mask |= set_string (&block, &post_block, var, IOPARM_dt_decimal,
1714 dt->decimal);
1715
1716 if (dt->delim)
1717 mask |= set_string (&block, &post_block, var, IOPARM_dt_delim,
1718 dt->delim);
1719
1720 if (dt->pad)
1721 mask |= set_string (&block, &post_block, var, IOPARM_dt_pad,
1722 dt->pad);
1723
1724 if (dt->round)
1725 mask |= set_string (&block, &post_block, var, IOPARM_dt_round,
1726 dt->round);
1727
1728 if (dt->sign)
1729 mask |= set_string (&block, &post_block, var, IOPARM_dt_sign,
1730 dt->sign);
1731
5e805e44
JJ
1732 if (dt->rec)
1733 mask |= set_parameter_value (&block, var, IOPARM_dt_rec, dt->rec);
6de9cd9a 1734
5e805e44
JJ
1735 if (dt->advance)
1736 mask |= set_string (&block, &post_block, var, IOPARM_dt_advance,
1737 dt->advance);
6de9cd9a 1738
5e805e44 1739 if (dt->format_expr)
9341698a 1740 mask |= set_string (&block, &post_end_block, var, IOPARM_dt_format,
5e805e44 1741 dt->format_expr);
6de9cd9a 1742
5e805e44
JJ
1743 if (dt->format_label)
1744 {
1745 if (dt->format_label == &format_asterisk)
1746 mask |= IOPARM_dt_list_format;
1747 else
1748 mask |= set_string (&block, &post_block, var, IOPARM_dt_format,
1749 dt->format_label->format);
1750 }
6de9cd9a 1751
5e805e44
JJ
1752 if (dt->size)
1753 mask |= set_parameter_ref (&block, &post_end_block, var,
1754 IOPARM_dt_size, dt->size);
6de9cd9a 1755
5e805e44
JJ
1756 if (dt->namelist)
1757 {
1758 if (dt->format_expr || dt->format_label)
1759 gfc_internal_error ("build_dt: format with namelist");
1760
1761 nmlname = gfc_new_nml_name_expr (dt->namelist->name);
29dc5138 1762
5e805e44
JJ
1763 mask |= set_string (&block, &post_block, var, IOPARM_dt_namelist_name,
1764 nmlname);
29dc5138 1765
5e805e44
JJ
1766 if (last_dt == READ)
1767 mask |= IOPARM_dt_namelist_read_mode;
29dc5138 1768
5e805e44 1769 set_parameter_const (&block, var, IOPARM_common_flags, mask);
29dc5138 1770
5e805e44
JJ
1771 dt_parm = var;
1772
1773 for (nml = dt->namelist->namelist; nml; nml = nml->next)
1774 transfer_namelist_element (&block, nml->sym->name, nml->sym,
1775 NULL, NULL);
1776 }
1777 else
1778 set_parameter_const (&block, var, IOPARM_common_flags, mask);
f96d606f
JD
1779
1780 if (dt->io_unit && dt->io_unit->ts.type == BT_INTEGER)
1781 set_parameter_value (&block, var, IOPARM_common_unit, dt->io_unit);
6de9cd9a 1782 }
5e805e44
JJ
1783 else
1784 set_parameter_const (&block, var, IOPARM_common_flags, mask);
6de9cd9a 1785
628c189e 1786 tmp = gfc_build_addr_expr (NULL_TREE, var);
5039610b 1787 tmp = build_call_expr (function, 1, tmp);
6de9cd9a
DN
1788 gfc_add_expr_to_block (&block, tmp);
1789
1790 gfc_add_block_to_block (&block, &post_block);
1791
5e805e44
JJ
1792 dt_parm = var;
1793 dt_post_end_block = &post_end_block;
1794
1795 gfc_add_expr_to_block (&block, gfc_trans_code (code->block->next));
1796
d4feb3d3
PT
1797 gfc_add_block_to_block (&block, &post_iu_block);
1798
5e805e44
JJ
1799 dt_parm = NULL;
1800 dt_post_end_block = NULL;
1801
6de9cd9a
DN
1802 return gfc_finish_block (&block);
1803}
1804
1805
8750f9cd
JB
1806/* Translate the IOLENGTH form of an INQUIRE statement. We treat
1807 this as a third sort of data transfer statement, except that
e7dc5b4f 1808 lengths are summed instead of actually transferring any data. */
8750f9cd
JB
1809
1810tree
1811gfc_trans_iolength (gfc_code * code)
1812{
8750f9cd 1813 last_dt = IOLENGTH;
5e805e44 1814 return build_dt (iocall[IOCALL_IOLENGTH], code);
8750f9cd
JB
1815}
1816
1817
6de9cd9a
DN
1818/* Translate a READ statement. */
1819
1820tree
1821gfc_trans_read (gfc_code * code)
1822{
6de9cd9a 1823 last_dt = READ;
5e805e44 1824 return build_dt (iocall[IOCALL_READ], code);
6de9cd9a
DN
1825}
1826
1827
1828/* Translate a WRITE statement */
1829
1830tree
1831gfc_trans_write (gfc_code * code)
1832{
6de9cd9a 1833 last_dt = WRITE;
5e805e44 1834 return build_dt (iocall[IOCALL_WRITE], code);
6de9cd9a
DN
1835}
1836
1837
1838/* Finish a data transfer statement. */
1839
1840tree
1841gfc_trans_dt_end (gfc_code * code)
1842{
1843 tree function, tmp;
1844 stmtblock_t block;
1845
1846 gfc_init_block (&block);
1847
8750f9cd
JB
1848 switch (last_dt)
1849 {
1850 case READ:
5e805e44 1851 function = iocall[IOCALL_READ_DONE];
8750f9cd
JB
1852 break;
1853
1854 case WRITE:
5e805e44 1855 function = iocall[IOCALL_WRITE_DONE];
8750f9cd
JB
1856 break;
1857
1858 case IOLENGTH:
5e805e44 1859 function = iocall[IOCALL_IOLENGTH_DONE];
8750f9cd
JB
1860 break;
1861
1862 default:
6e45f57b 1863 gcc_unreachable ();
8750f9cd 1864 }
6de9cd9a 1865
628c189e 1866 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
5039610b 1867 tmp = build_call_expr (function, 1, tmp);
6de9cd9a 1868 gfc_add_expr_to_block (&block, tmp);
5e805e44
JJ
1869 gfc_add_block_to_block (&block, dt_post_end_block);
1870 gfc_init_block (dt_post_end_block);
6de9cd9a 1871
8750f9cd
JB
1872 if (last_dt != IOLENGTH)
1873 {
6e45f57b 1874 gcc_assert (code->ext.dt != NULL);
5e805e44 1875 io_result (&block, dt_parm, code->ext.dt->err,
8750f9cd
JB
1876 code->ext.dt->end, code->ext.dt->eor);
1877 }
6de9cd9a
DN
1878
1879 return gfc_finish_block (&block);
1880}
1881
d2ccf6aa 1882static void
aa5e22f0 1883transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code);
d2ccf6aa
VL
1884
1885/* Given an array field in a derived type variable, generate the code
1886 for the loop that iterates over array elements, and the code that
1887 accesses those array elements. Use transfer_expr to generate code
1888 for transferring that element. Because elements may also be
1889 derived types, transfer_expr and transfer_array_component are mutually
1890 recursive. */
1891
1892static tree
bdfd2ff0 1893transfer_array_component (tree expr, gfc_component * cm, locus * where)
d2ccf6aa
VL
1894{
1895 tree tmp;
1896 stmtblock_t body;
1897 stmtblock_t block;
1898 gfc_loopinfo loop;
1899 int n;
1900 gfc_ss *ss;
1901 gfc_se se;
1902
1903 gfc_start_block (&block);
1904 gfc_init_se (&se, NULL);
1905
1906 /* Create and initialize Scalarization Status. Unlike in
1907 gfc_trans_transfer, we can't simply use gfc_walk_expr to take
1908 care of this task, because we don't have a gfc_expr at hand.
1909 Build one manually, as in gfc_trans_subarray_assign. */
1910
1911 ss = gfc_get_ss ();
1912 ss->type = GFC_SS_COMPONENT;
1913 ss->expr = NULL;
1914 ss->shape = gfc_get_shape (cm->as->rank);
1915 ss->next = gfc_ss_terminator;
1916 ss->data.info.dimen = cm->as->rank;
1917 ss->data.info.descriptor = expr;
1918 ss->data.info.data = gfc_conv_array_data (expr);
1919 ss->data.info.offset = gfc_conv_array_offset (expr);
1920 for (n = 0; n < cm->as->rank; n++)
1921 {
1922 ss->data.info.dim[n] = n;
1923 ss->data.info.start[n] = gfc_conv_array_lbound (expr, n);
1924 ss->data.info.stride[n] = gfc_index_one_node;
1925
1926 mpz_init (ss->shape[n]);
1927 mpz_sub (ss->shape[n], cm->as->upper[n]->value.integer,
1928 cm->as->lower[n]->value.integer);
1929 mpz_add_ui (ss->shape[n], ss->shape[n], 1);
1930 }
1931
f7b529fa 1932 /* Once we got ss, we use scalarizer to create the loop. */
d2ccf6aa
VL
1933
1934 gfc_init_loopinfo (&loop);
1935 gfc_add_ss_to_loop (&loop, ss);
1936 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1937 gfc_conv_loop_setup (&loop, where);
d2ccf6aa
VL
1938 gfc_mark_ss_chain_used (ss, 1);
1939 gfc_start_scalarized_body (&loop, &body);
1940
1941 gfc_copy_loopinfo_to_se (&se, &loop);
1942 se.ss = ss;
1943
1944 /* gfc_conv_tmp_array_ref assumes that se.expr contains the array. */
1945 se.expr = expr;
1946 gfc_conv_tmp_array_ref (&se);
1947
1948 /* Now se.expr contains an element of the array. Take the address and pass
1949 it to the IO routines. */
628c189e 1950 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
aa5e22f0 1951 transfer_expr (&se, &cm->ts, tmp, NULL);
d2ccf6aa
VL
1952
1953 /* We are done now with the loop body. Wrap up the scalarizer and
f7b529fa 1954 return. */
d2ccf6aa
VL
1955
1956 gfc_add_block_to_block (&body, &se.pre);
1957 gfc_add_block_to_block (&body, &se.post);
1958
1959 gfc_trans_scalarizing_loops (&loop, &body);
1960
1961 gfc_add_block_to_block (&block, &loop.pre);
1962 gfc_add_block_to_block (&block, &loop.post);
1963
d2ccf6aa
VL
1964 for (n = 0; n < cm->as->rank; n++)
1965 mpz_clear (ss->shape[n]);
1966 gfc_free (ss->shape);
1967
96654664
PB
1968 gfc_cleanup_loop (&loop);
1969
d2ccf6aa
VL
1970 return gfc_finish_block (&block);
1971}
6de9cd9a
DN
1972
1973/* Generate the call for a scalar transfer node. */
1974
1975static void
aa5e22f0 1976transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
6de9cd9a 1977{
8a221914 1978 tree tmp, function, arg2, arg3, field, expr;
6de9cd9a
DN
1979 gfc_component *c;
1980 int kind;
1981
a8b3b0b6
CR
1982 /* It is possible to get a C_NULL_PTR or C_NULL_FUNPTR expression here if
1983 the user says something like: print *, 'c_null_ptr: ', c_null_ptr
1984 We need to translate the expression to a constant if it's either
aa5e22f0
CR
1985 C_NULL_PTR or C_NULL_FUNPTR. We could also get a user variable of
1986 type C_PTR or C_FUNPTR, in which case the ts->type may no longer be
1987 BT_DERIVED (could have been changed by gfc_conv_expr). */
1988 if ((ts->type == BT_DERIVED && ts->is_iso_c == 1 && ts->derived != NULL)
1989 || (ts->derived != NULL && ts->derived->ts.is_iso_c == 1))
a8b3b0b6 1990 {
aa5e22f0
CR
1991 /* C_PTR and C_FUNPTR have private components which means they can not
1992 be printed. However, if -std=gnu and not -pedantic, allow
1993 the component to be printed to help debugging. */
1994 if (gfc_notification_std (GFC_STD_GNU) != SILENT)
1995 {
1996 gfc_error_now ("Derived type '%s' at %L has PRIVATE components",
1997 ts->derived->name, code != NULL ? &(code->loc) :
1998 &gfc_current_locus);
1999 return;
2000 }
2001
a8b3b0b6
CR
2002 ts->type = ts->derived->ts.type;
2003 ts->kind = ts->derived->ts.kind;
2004 ts->f90_type = ts->derived->ts.f90_type;
2005 }
2006
6de9cd9a
DN
2007 kind = ts->kind;
2008 function = NULL;
2009 arg2 = NULL;
8a221914 2010 arg3 = NULL;
6de9cd9a
DN
2011
2012 switch (ts->type)
2013 {
2014 case BT_INTEGER:
7d60be94 2015 arg2 = build_int_cst (NULL_TREE, kind);
5e805e44 2016 function = iocall[IOCALL_X_INTEGER];
6de9cd9a
DN
2017 break;
2018
2019 case BT_REAL:
7d60be94 2020 arg2 = build_int_cst (NULL_TREE, kind);
5e805e44 2021 function = iocall[IOCALL_X_REAL];
6de9cd9a
DN
2022 break;
2023
2024 case BT_COMPLEX:
7d60be94 2025 arg2 = build_int_cst (NULL_TREE, kind);
5e805e44 2026 function = iocall[IOCALL_X_COMPLEX];
6de9cd9a
DN
2027 break;
2028
2029 case BT_LOGICAL:
7d60be94 2030 arg2 = build_int_cst (NULL_TREE, kind);
5e805e44 2031 function = iocall[IOCALL_X_LOGICAL];
6de9cd9a
DN
2032 break;
2033
2034 case BT_CHARACTER:
8a221914
JD
2035 if (kind == 4)
2036 {
2037 if (se->string_length)
2038 arg2 = se->string_length;
2039 else
2040 {
2041 tmp = build_fold_indirect_ref (addr_expr);
2042 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2043 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2044 arg2 = fold_convert (gfc_charlen_type_node, arg2);
2045 }
2046 arg3 = build_int_cst (NULL_TREE, kind);
2047 function = iocall[IOCALL_X_CHARACTER_WIDE];
628c189e 2048 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
8a221914
JD
2049 tmp = build_call_expr (function, 4, tmp, addr_expr, arg2, arg3);
2050 gfc_add_expr_to_block (&se->pre, tmp);
2051 gfc_add_block_to_block (&se->pre, &se->post);
2052 return;
2053 }
2054 /* Fall through. */
7b95e2a8 2055 case BT_HOLLERITH:
d2ccf6aa
VL
2056 if (se->string_length)
2057 arg2 = se->string_length;
2058 else
2059 {
38611275 2060 tmp = build_fold_indirect_ref (addr_expr);
d2ccf6aa
VL
2061 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
2062 arg2 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tmp)));
2063 }
5e805e44 2064 function = iocall[IOCALL_X_CHARACTER];
6de9cd9a
DN
2065 break;
2066
2067 case BT_DERIVED:
d2ccf6aa 2068 /* Recurse into the elements of the derived type. */
6de9cd9a 2069 expr = gfc_evaluate_now (addr_expr, &se->pre);
38611275 2070 expr = build_fold_indirect_ref (expr);
6de9cd9a
DN
2071
2072 for (c = ts->derived->components; c; c = c->next)
2073 {
2074 field = c->backend_decl;
6e45f57b 2075 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6de9cd9a 2076
44855d8c
TS
2077 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
2078 expr, field, NULL_TREE);
6de9cd9a 2079
d4b7d0f0 2080 if (c->attr.dimension)
d2ccf6aa 2081 {
bdfd2ff0 2082 tmp = transfer_array_component (tmp, c, & code->loc);
d2ccf6aa
VL
2083 gfc_add_expr_to_block (&se->pre, tmp);
2084 }
2085 else
2086 {
d4b7d0f0 2087 if (!c->attr.pointer)
628c189e 2088 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
aa5e22f0 2089 transfer_expr (se, &c->ts, tmp, code);
d2ccf6aa 2090 }
6de9cd9a
DN
2091 }
2092 return;
2093
2094 default:
2095 internal_error ("Bad IO basetype (%d)", ts->type);
2096 }
2097
628c189e 2098 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
5039610b 2099 tmp = build_call_expr (function, 3, tmp, addr_expr, arg2);
6de9cd9a
DN
2100 gfc_add_expr_to_block (&se->pre, tmp);
2101 gfc_add_block_to_block (&se->pre, &se->post);
8750f9cd 2102
6de9cd9a
DN
2103}
2104
2105
18623fae
JB
2106/* Generate a call to pass an array descriptor to the IO library. The
2107 array should be of one of the intrinsic types. */
2108
2109static void
2110transfer_array_desc (gfc_se * se, gfc_typespec * ts, tree addr_expr)
2111{
5039610b 2112 tree tmp, charlen_arg, kind_arg;
18623fae
JB
2113
2114 if (ts->type == BT_CHARACTER)
2115 charlen_arg = se->string_length;
2116 else
7fb41a42 2117 charlen_arg = build_int_cst (NULL_TREE, 0);
18623fae 2118
e5ef4b3b
JB
2119 kind_arg = build_int_cst (NULL_TREE, ts->kind);
2120
628c189e 2121 tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
5039610b
SL
2122 tmp = build_call_expr (iocall[IOCALL_X_ARRAY], 4,
2123 tmp, addr_expr, kind_arg, charlen_arg);
18623fae
JB
2124 gfc_add_expr_to_block (&se->pre, tmp);
2125 gfc_add_block_to_block (&se->pre, &se->post);
2126}
2127
2128
6de9cd9a
DN
2129/* gfc_trans_transfer()-- Translate a TRANSFER code node */
2130
2131tree
2132gfc_trans_transfer (gfc_code * code)
2133{
2134 stmtblock_t block, body;
2135 gfc_loopinfo loop;
2136 gfc_expr *expr;
99c7ab42 2137 gfc_ref *ref;
6de9cd9a
DN
2138 gfc_ss *ss;
2139 gfc_se se;
2140 tree tmp;
c63173dd 2141 int n;
6de9cd9a
DN
2142
2143 gfc_start_block (&block);
18623fae 2144 gfc_init_block (&body);
6de9cd9a 2145
a513927a 2146 expr = code->expr1;
6de9cd9a
DN
2147 ss = gfc_walk_expr (expr);
2148
99c7ab42 2149 ref = NULL;
6de9cd9a
DN
2150 gfc_init_se (&se, NULL);
2151
2152 if (ss == gfc_ss_terminator)
18623fae 2153 {
815d8045 2154 /* Transfer a scalar value. */
18623fae 2155 gfc_conv_expr_reference (&se, expr);
aa5e22f0 2156 transfer_expr (&se, &expr->ts, se.expr, code);
18623fae 2157 }
815d8045 2158 else
6de9cd9a 2159 {
99c7ab42
PT
2160 /* Transfer an array. If it is an array of an intrinsic
2161 type, pass the descriptor to the library. Otherwise
2162 scalarize the transfer. */
2163 if (expr->ref)
2164 {
2165 for (ref = expr->ref; ref && ref->type != REF_ARRAY;
2166 ref = ref->next);
2167 gcc_assert (ref->type == REF_ARRAY);
2168 }
2169
1d6b7f39
PT
2170 if (expr->ts.type != BT_DERIVED
2171 && ref && ref->next == NULL
2172 && !is_subref_array (expr))
815d8045 2173 {
c63173dd
PT
2174 bool seen_vector = false;
2175
2176 if (ref && ref->u.ar.type == AR_SECTION)
2177 {
2178 for (n = 0; n < ref->u.ar.dimen; n++)
2179 if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR)
2180 seen_vector = true;
2181 }
2182
2183 if (seen_vector && last_dt == READ)
2184 {
2185 /* Create a temp, read to that and copy it back. */
2186 gfc_conv_subref_array_arg (&se, expr, 0, INTENT_OUT);
2187 tmp = se.expr;
2188 }
2189 else
2190 {
2191 /* Get the descriptor. */
2192 gfc_conv_expr_descriptor (&se, expr, ss);
628c189e 2193 tmp = gfc_build_addr_expr (NULL_TREE, se.expr);
c63173dd
PT
2194 }
2195
99c7ab42
PT
2196 transfer_array_desc (&se, &expr->ts, tmp);
2197 goto finish_block_label;
815d8045
JB
2198 }
2199
6de9cd9a
DN
2200 /* Initialize the scalarizer. */
2201 gfc_init_loopinfo (&loop);
2202 gfc_add_ss_to_loop (&loop, ss);
2203
2204 /* Initialize the loop. */
2205 gfc_conv_ss_startstride (&loop);
a513927a 2206 gfc_conv_loop_setup (&loop, &code->expr1->where);
6de9cd9a
DN
2207
2208 /* The main loop body. */
2209 gfc_mark_ss_chain_used (ss, 1);
2210 gfc_start_scalarized_body (&loop, &body);
2211
2212 gfc_copy_loopinfo_to_se (&se, &loop);
2213 se.ss = ss;
6de9cd9a 2214
18623fae 2215 gfc_conv_expr_reference (&se, expr);
aa5e22f0 2216 transfer_expr (&se, &expr->ts, se.expr, code);
18623fae 2217 }
815d8045
JB
2218
2219 finish_block_label:
6de9cd9a
DN
2220
2221 gfc_add_block_to_block (&body, &se.pre);
2222 gfc_add_block_to_block (&body, &se.post);
2223
2224 if (se.ss == NULL)
2225 tmp = gfc_finish_block (&body);
2226 else
2227 {
6e45f57b 2228 gcc_assert (se.ss == gfc_ss_terminator);
6de9cd9a
DN
2229 gfc_trans_scalarizing_loops (&loop, &body);
2230
2231 gfc_add_block_to_block (&loop.pre, &loop.post);
2232 tmp = gfc_finish_block (&loop.pre);
2233 gfc_cleanup_loop (&loop);
2234 }
2235
2236 gfc_add_expr_to_block (&block, tmp);
2237
d2ccf6aa 2238 return gfc_finish_block (&block);
6de9cd9a
DN
2239}
2240
2241#include "gt-fortran-trans-io.h"